private async Task ConnectAsyncCore(Uri uri, CancellationToken cancellationToken)
{
HttpWebResponse response = null;
CancellationTokenRegistration connectCancellation = new CancellationTokenRegistration();
// Any errors from here on out are fatal and this instance will be disposed.
try
{
HttpWebRequest request = CreateAndConfigureRequest(uri);
if (Logging.On)
{
Logging.Associate(Logging.WebSockets, this, request);
}
connectCancellation = cancellationToken.Register(AbortRequest, request, false);
response = await request.GetResponseAsync().SuppressContextFlow() as HttpWebResponse;
Contract.Assert(response != null, "Not an HttpWebResponse");
if (Logging.On)
{
Logging.Associate(Logging.WebSockets, this, response);
}
string subprotocol = ValidateResponse(request, response);
innerWebSocket = WebSocket.CreateClientWebSocket(response.GetResponseStream(), subprotocol,
options.ReceiveBufferSize, options.SendBufferSize, options.KeepAliveInterval, false,
options.GetOrCreateBuffer());
if (Logging.On)
{
Logging.Associate(Logging.WebSockets, this, innerWebSocket);
}
// Change internal state to 'connected' to enable the other methods
if (Interlocked.CompareExchange(ref state, connected, connecting) != connecting)
{
// Aborted/Disposed during connect.
throw new ObjectDisposedException(GetType().FullName);
}
}
catch (WebException ex)
{
ConnectExceptionCleanup(response);
WebSocketException wex = new WebSocketException(SR.GetString(SR.net_webstatus_ConnectFailure), ex);
if (Logging.On)
{
Logging.Exception(Logging.WebSockets, this, "ConnectAsync", wex);
}
throw wex;
}
catch (Exception ex)
{
ConnectExceptionCleanup(response);
if (Logging.On)
{
Logging.Exception(Logging.WebSockets, this, "ConnectAsync", ex);
}
throw;
}
finally
{
// We successfully connected (or failed trying), disengage from this token.
// Otherwise any timeout/cancellation would apply to the full session.
// In the failure case we need to release the reference to HWR.
connectCancellation.Dispose();
}
}