internal async Task <WebSocketStream> AcceptAsync() { // Performance: Address Resolution (ARP) work-around: When we receive the control message from a TCP connection which hasn't had any // outbound traffic for 2 minutes the ARP cache no longer has the MAC address required to ACK the control message. If we also begin // connecting a new socket at exactly the same time there's a known race condition (insert link here) where ARP can only resolve one // address at a time, which causes the loser of the race to have to retry after 3000ms. To avoid the 3000ms delay we just pause for // a few ms here instead. await Task.Delay(TimeSpan.FromMilliseconds(2)).ConfigureAwait(false); var clientWebSocket = this.CreateWebSocket(); // If we are accepting a sub-protocol handle that here var subProtocol = this.Response.Headers[HybridConnectionConstants.Headers.SecWebSocketProtocol]; if (!string.IsNullOrEmpty(subProtocol)) { clientWebSocket.Options.AddSubProtocol(subProtocol); } using (var cancelSource = new CancellationTokenSource(AcceptTimeout)) { await clientWebSocket.ConnectAsync(this.wssRendezvousAddress, cancelSource.Token).ConfigureAwait(false); } var webSocketStream = new WebSocketStream(clientWebSocket, this.TrackingContext); return(webSocketStream); }
public async Task AcceptConnectionAsync() { try { // Performance: Address Resolution (ARP) work-around: When we receive the control message from a TCP connection which hasn't had any // outbound traffic for 2 minutes the ARP cache no longer has the MAC address required to ACK the control message. If we also begin // connecting a new socket at exactly the same time there's a known race condition (insert link here) where ARP can only resolve one // address at a time, which causes the loser of the race to have to retry after 3000ms. To avoid the 3000ms delay we just pause for // a few ms here instead. await Task.Delay(TimeSpan.FromMilliseconds(2)).ConfigureAwait(false); var timeoutHelper = new TimeoutHelper(AcceptTimeout); var clientWebSocket = new ClientWebSocket45(); clientWebSocket.Options.SetBuffer(this.bufferSize, this.bufferSize); clientWebSocket.Options.Host = this.Address.Host; clientWebSocket.Options.Proxy = this.listener.Proxy; clientWebSocket.Options.KeepAliveInterval = HybridConnectionConstants.KeepAliveInterval; using (var cancelSource = new CancellationTokenSource(timeoutHelper.RemainingTime())) { await clientWebSocket.ConnectAsync(this.rendezvousAddress, cancelSource.Token).ConfigureAwait(false); } var webSocketStream = new WebSocketStream(clientWebSocket, this.TrackingContext); this.AcceptSucceeded(webSocketStream); } catch (Exception exception) { if (Fx.IsFatal(exception)) { throw; } this.AcceptFailed(exception); } }