in Source/WebSocket/WinRT/winrt_websocket.cpp [176:308]
HRESULT WebsocketConnectDoWork(
_Inout_ XAsyncBlock* asyncBlock,
_In_opt_ void* executionRoutineContext
)
try
{
HCWebsocketHandle websocket = static_cast<HCWebsocketHandle>(executionRoutineContext);
HC_TRACE_INFORMATION(WEBSOCKET, "Websocket [ID %llu]: Connect executing", TO_ULL(websocket->id));
std::shared_ptr<winrt_websocket_impl> websocketTask = std::dynamic_pointer_cast<winrt_websocket_impl>(websocket->impl);
try
{
websocketTask->m_connectClosing = false;
websocketTask->m_messageWebSocket = ref new MessageWebSocket();
uint32_t numHeaders = 0;
HCWebSocketGetNumHeaders(websocket, &numHeaders);
http_internal_string protocolHeader("Sec-WebSocket-Protocol");
for (uint32_t i = 0; i < numHeaders; i++)
{
const char* headerName;
const char* headerValue;
HCWebSocketGetHeaderAtIndex(websocket, i, &headerName, &headerValue);
// The MessageWebSocket API throws a COMException if you try to set the
// 'Sec-WebSocket-Protocol' header here. It requires you to go through their API instead.
if (headerName != nullptr && headerValue != nullptr && !str_icmp(headerName, protocolHeader.c_str()))
{
http_internal_wstring wHeaderName = utf16_from_utf8(headerName);
http_internal_wstring wHeaderValue = utf16_from_utf8(headerValue);
websocketTask->m_messageWebSocket->SetRequestHeader(
Platform::StringReference(wHeaderName.c_str()),
Platform::StringReference(wHeaderValue.c_str()));
HC_TRACE_INFORMATION(WEBSOCKET, "Websocket [ID %llu]: Header %d [%s: %s]", TO_ULL(websocket->id), i, headerName, headerValue);
}
}
auto protocols = parse_subprotocols(websocket->SubProtocol());
for (const auto& value : protocols)
{
websocketTask->m_messageWebSocket->Control->SupportedProtocols->Append(Platform::StringReference(value.c_str()));
HC_TRACE_INFORMATION(WEBSOCKET, "Websocket [ID %llu]: Protocol [%S]", TO_ULL(websocket->id), value.c_str());
}
websocketTask->m_context = ref new ReceiveContext();
websocketTask->m_context->m_websocket = websocket;
http_internal_wstring aUrl = utf16_from_utf8(websocket->Uri());
const auto cxUri = ref new Windows::Foundation::Uri(Platform::StringReference(aUrl.c_str()));
websocketTask->m_messageWebSocket->MessageReceived += ref new TypedEventHandler<MessageWebSocket^, MessageWebSocketMessageReceivedEventArgs^>(websocketTask->m_context, &ReceiveContext::OnReceive);
websocketTask->m_messageWebSocket->Closed += ref new TypedEventHandler<IWebSocket^, WebSocketClosedEventArgs^>(websocketTask->m_context, &ReceiveContext::OnClosed);
HC_TRACE_INFORMATION(WEBSOCKET, "Websocket [ID %llu]: connecting to %s", TO_ULL(websocket->id), websocket->Uri().c_str());
websocketTask->m_connectAsyncOp = websocketTask->m_messageWebSocket->ConnectAsync(cxUri);
websocketTask->m_connectAsyncOp->Completed = ref new AsyncActionCompletedHandler(
[websocket, websocketTask, asyncBlock](
Windows::Foundation::IAsyncAction^ asyncOp,
Windows::Foundation::AsyncStatus status)
{
UNREFERENCED_PARAMETER(status);
try
{
websocketTask->m_messageDataWriter = ref new DataWriter(websocketTask->m_messageWebSocket->OutputStream);
if (status == Windows::Foundation::AsyncStatus::Error)
{
websocketTask->m_connectAsyncOpResult = E_FAIL;
}
else
{
websocketTask->m_connectAsyncOpResult = S_OK;
}
}
catch (Platform::Exception^ e)
{
websocketTask->m_connectAsyncOpResult = e->HResult;
}
catch (...)
{
websocketTask->m_connectAsyncOpResult = E_FAIL;
}
if (FAILED(websocketTask->m_connectAsyncOpResult))
{
HC_TRACE_ERROR(WEBSOCKET, "Websocket [ID %llu]: connect failed 0x%0.8x", TO_ULL(websocket->id), websocketTask->m_connectAsyncOpResult);
try
{
// Cleaning up the websocket state
websocketTask->m_connectClosing = true;
if (websocketTask->m_messageWebSocket != nullptr)
{
websocketTask->m_messageWebSocket->Close(static_cast<unsigned short>(HCWebSocketCloseStatus::Normal), "");
websocketTask->m_messageWebSocket = nullptr;
}
}
catch (...)
{
}
}
else
{
HC_TRACE_INFORMATION(WEBSOCKET, "Websocket [ID %llu] connect complete", TO_ULL(websocket->id));
}
XAsyncComplete(asyncBlock, S_OK, sizeof(WebSocketCompletionResult));
});
}
catch (Platform::Exception^ e)
{
try
{
// Cleaning up the websocket state
websocketTask->m_connectClosing = true;
if (websocketTask->m_messageWebSocket != nullptr)
{
websocketTask->m_messageWebSocket->Close(static_cast<unsigned short>(HCWebSocketCloseStatus::Normal), "");
websocketTask->m_messageWebSocket = nullptr;
}
}
catch (...)
{
}
HC_TRACE_ERROR(WEBSOCKET, "Websocket [ID %llu]: ConnectAsync failed = 0x%0.8x", TO_ULL(websocketTask->m_websocketHandle->id), e->HResult);
return e->HResult;
}
return E_PENDING;
}