public async Task CloseAsync( string message, SocketCloseStatus closeStatus, CancellationToken cancellationToken) { try { WebSocket?webSocket = _webSocket; if (_disposed || Closed || webSocket is null) { return; } await webSocket.CloseOutputAsync( MapCloseStatus(closeStatus), message, cancellationToken); Dispose(); } catch { // we do not throw here ... } }
internal static ServerEventsStatus CalculateServerEventsStatus(bool enabled, WebSocket?socket) { if (!enabled) { return(ServerEventsStatus.Disabled); } return(socket == null ? ServerEventsStatus.Connecting : ServerEventsStatus.Enabled); }
public Task ConnectAsync(Uri uri, CancellationToken cancellationToken, ClientWebSocketOptions options) { cancellationToken.ThrowIfCancellationRequested(); var ws = new BrowserWebSocket(); WebSocket = ws; return(ws.ConnectAsync(uri, options.RequestedSubProtocols, cancellationToken)); }
/// <summary> /// Attaches an WebSocket instance to the payment processing delegate event /// </summary> /// <param name="webSocket">the WebSocket instance to attach to</param> public void ListeningPaymentProcessing(WebSocket webSocket) { _webSocket = webSocket; if (_paymentProcessing.HasPaymentProcessingEventMethod) { return; } _logger.LogInformation("Assigned to payment websocket event"); _paymentProcessing.PaymentProcessingEvent += PaymentProcessingOnPaymentProcessingEvent; }
public async Task <TaskCompletionSource <bool> > GetSocketCompletion(WebSocket socket) { await DiscardSocket(); _serverEventsSocket = socket; _completion = new TaskCompletionSource <bool>(); await FlushIfPending(); return(_completion); }
private async Task DiscardSocket() { if (_serverEventsSocket != null) { _completion?.SetResult(true); await PostEventHandler.CloseSocket(_serverEventsSocket); _serverEventsSocket = null; } }
protected virtual void Dispose(bool disposing) { if (disposing) { if (WebSocket != null) { WebSocket.Dispose(); WebSocket = null; } } }
protected virtual void Dispose(bool disposing) { if (!_disposed) { if (disposing) { Subscriptions.Dispose(); _webSocket?.Dispose(); _webSocket = null; } _disposed = true; } }
public async Task ReceiveAsync( PipeWriter writer, CancellationToken cancellationToken) { WebSocket?webSocket = _webSocket; if (_disposed || webSocket == null) { return; } try { WebSocketReceiveResult?socketResult = null; do { Memory <byte> memory = writer.GetMemory(_maxMessageSize); bool success = MemoryMarshal.TryGetArray(memory, out ArraySegment <byte> buffer); if (success) { try { socketResult = await webSocket.ReceiveAsync(buffer, cancellationToken); if (socketResult.Count == 0) { break; } writer.Advance(socketResult.Count); } catch { break; } FlushResult result = await writer.FlushAsync(cancellationToken); if (result.IsCompleted) { break; } } } while (socketResult == null || !socketResult.EndOfMessage); } catch (ObjectDisposedException) { // we will just stop receiving } }
private void CloseConnectionIfItsNotNull() { if (_socketConnection != null) { _logger.LogDebug("Closing existing connection"); using (_socketConnection) { _socketConnection.MessageReceived -= SocketConnectionOnMessageReceived; _socketConnection.Closed -= SocketConnectionOnClosed; _socketConnection.Error -= SocketConnectionOnError; _welcomeReceived.Reset(); _socketConnection.Close(); _socketConnection = null; } } }
public Task SendAsync( byte[] message, CancellationToken cancellationToken) { WebSocket?webSocket = _webSocket; if (_disposed || webSocket == null) { return(Task.CompletedTask); } return(webSocket.SendAsync( new ArraySegment <byte>(message), WebSocketMessageType.Text, true, cancellationToken)); }
protected override async Task InternalConnectAsync(CancellationToken token) { int roomId = _Options.RoomId; DanmakuServerInfo server = await _CredentialProvider.GetDanmakuServerInfoAsync(token); ClientWebSocket client = new ClientWebSocket(); client.Options.KeepAliveInterval = Timeout.InfiniteTimeSpan; token.Register(client.Dispose); DanmakuServerHostInfo serverHost = server.Hosts[(int)(Stopwatch.GetTimestamp() % server.Hosts.Length)]; await client.ConnectAsync(new Uri($"wss://{serverHost.Host}:{serverHost.WssPort}/sub"), token); await SendJoinRoomAsync(client, roomId, 0, server.Token, token); _Client = client; }
public async Task ReadWebSocket(WebSocket socket) { if (WebSocket != null) { try { Task ignored = WebSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None); } catch (Exception) { } } WebSocket = socket; const int maxMessageSize = 1024; byte[] receiveBuffer = new byte[maxMessageSize]; while (!closed) { try { WebSocketReceiveResult receiveResult = await socket.ReceiveAsync(new ArraySegment <byte>(receiveBuffer), CancellationToken.None); if (receiveResult.MessageType == WebSocketMessageType.Close) { await Close(); return; } if (receiveResult.Count == 2 && receiveBuffer[0] == (byte)'O' && receiveBuffer[1] == (byte)'K') { eventAcked = true; } lastActivity = Timestamp.Now; } catch (Exception) { try { Task ignored = socket.CloseAsync(WebSocketCloseStatus.ProtocolError, string.Empty, CancellationToken.None); } catch (Exception) { } if (socket == WebSocket) { WebSocket = null; } return; } } }
public async Task ConnectAsync(Uri uri, CancellationToken cancellationToken, ClientWebSocketOptions options) { try { cancellationToken.ThrowIfCancellationRequested(); // avoid allocating a WebSocket object if cancellation was requested before connect CancellationTokenSource?linkedCancellation; CancellationTokenSource externalAndAbortCancellation; if (cancellationToken.CanBeCanceled) // avoid allocating linked source if external token is not cancelable { linkedCancellation = externalAndAbortCancellation = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, _abortSource.Token); } else { linkedCancellation = null; externalAndAbortCancellation = _abortSource; } using (linkedCancellation) { WebSocket = new BrowserWebSocket(); await((BrowserWebSocket)WebSocket).ConnectAsyncJavaScript(uri, externalAndAbortCancellation.Token, options.RequestedSubProtocols).ConfigureAwait(continueOnCapturedContext: true); externalAndAbortCancellation.Token.ThrowIfCancellationRequested(); } } catch (Exception exc) { if (_state < WebSocketState.Closed) { _state = WebSocketState.Closed; } Abort(); switch (exc) { case WebSocketException: case OperationCanceledException _ when cancellationToken.IsCancellationRequested: throw; default: throw new WebSocketException(SR.net_webstatus_ConnectFailure, exc); } } }
public async Task ReceiveAsync( PipeWriter writer, CancellationToken cancellationToken) { WebSocket?webSocket = _webSocket; if (_disposed || webSocket == null) { return; } try { ValueWebSocketReceiveResult socketResult; do { if (webSocket.State != WebSocketState.Open) { break; } Memory <byte> memory = writer.GetMemory(_maxMessageSize); socketResult = await webSocket.ReceiveAsync(memory, cancellationToken); if (socketResult.Count == 0) { break; } writer.Advance(socketResult.Count); FlushResult result = await writer.FlushAsync(cancellationToken); if (result.IsCompleted) { break; } } while (!socketResult.EndOfMessage); } catch { // swallow exception, there's nothing we can reasonably do } }
public bool Connect() { CloseConnectionIfItsNotNull(); _socketConnection = new WebSocket($"wss://{Environments.Values[_bitmexEnvironment]}/realtime") { EnableAutoSendPing = true, AutoSendPingInterval = 2 }; BitmexWelcomeMessage welcomeData = null; EventHandler <MessageReceivedEventArgs> welcomeMessageReceived = (sender, e) => { _logger.LogDebug($"Welcome Data Received {e.Message}"); welcomeData = BitmexJsonSerializer.Deserialize <BitmexWelcomeMessage>(e.Message); _welcomeReceived.Set(); }; _socketConnection.MessageReceived += welcomeMessageReceived; _socketConnection.Open(); var waitResult = _welcomeReceived.WaitOne(SocketMessageResponseTimeout); _socketConnection.MessageReceived -= welcomeMessageReceived; if (waitResult && (welcomeData?.Limit?.Remaining ?? 0) == 0) { _logger.LogError("Bitmex connection limit reached"); throw new BitmexWebSocketLimitReachedException(); } if (!waitResult) { _logger.LogError("Open connection timeout. Welcome message is not received"); return(false); } if (IsAlive) { _logger.LogInformation("Bitmex web socket connection opened"); _socketConnection.MessageReceived += SocketConnectionOnMessageReceived; _socketConnection.Closed += SocketConnectionOnClosed; _socketConnection.Error += SocketConnectionOnError; } return(IsAlive); }
internal async Task Close() { if (closed) { return; } closed = true; if (WebSocket != null) { var socket = WebSocket; WebSocket = null; try { await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, "", CancellationToken.None); } catch (Exception) { } } if (currentView != null) { try { await currentView.OnDeactivate(); } catch (Exception) { } currentView = null; } foreach (ViewBase view in views.Values) { try { await view.OnDestroy(); } catch (Exception) { } } await connection.Close(); }
public async Task <bool> TryOpenAsync() { if (_disposed) { throw new ObjectDisposedException(nameof(WebSocketConnection)); } _webSocket = await WebSockets.AcceptWebSocketAsync(_protocol); if (_webSocket.SubProtocol is not null && WebSockets.WebSocketRequestedProtocols.Contains(_webSocket.SubProtocol)) { return(true); } await _webSocket.CloseOutputAsync( WebSocketCloseStatus.ProtocolError, "Expected graphql-ws protocol.", CancellationToken.None); _webSocket.Dispose(); _webSocket = null; return(false); }
public async Task ConnectAsync(Uri uri, CancellationToken cancellationToken, ClientWebSocketOptions options) { HttpResponseMessage?response = null; SocketsHttpHandler? handler = null; bool disposeHandler = true; try { var request = new HttpRequestMessage(HttpMethod.Get, uri); if (options._requestHeaders?.Count > 0) // use field to avoid lazily initializing the collection { foreach (string key in options.RequestHeaders) { request.Headers.TryAddWithoutValidation(key, options.RequestHeaders[key]); } } // Create the security key and expected response, then build all of the request headers KeyValuePair <string, string> secKeyAndSecWebSocketAccept = CreateSecKeyAndSecWebSocketAccept(); AddWebSocketHeaders(request, secKeyAndSecWebSocketAccept.Key, options); // Create the handler for this request and populate it with all of the options. // Try to use a shared handler rather than creating a new one just for this request, if // the options are compatible. if (options.Credentials == null && !options.UseDefaultCredentials && options.Proxy == null && options.Cookies == null && options.RemoteCertificateValidationCallback == null && options._clientCertificates?.Count == 0) { disposeHandler = false; handler = s_defaultHandler; if (handler == null) { handler = new SocketsHttpHandler() { PooledConnectionLifetime = TimeSpan.Zero, UseProxy = false, UseCookies = false, }; if (Interlocked.CompareExchange(ref s_defaultHandler, handler, null) != null) { handler.Dispose(); handler = s_defaultHandler; } } } else { handler = new SocketsHttpHandler(); handler.PooledConnectionLifetime = TimeSpan.Zero; handler.CookieContainer = options.Cookies; handler.UseCookies = options.Cookies != null; handler.SslOptions.RemoteCertificateValidationCallback = options.RemoteCertificateValidationCallback; if (options.UseDefaultCredentials) { handler.Credentials = CredentialCache.DefaultCredentials; } else { handler.Credentials = options.Credentials; } if (options.Proxy == null) { handler.UseProxy = false; } else if (options.Proxy != DefaultWebProxy.Instance) { handler.Proxy = options.Proxy; } if (options._clientCertificates?.Count > 0) // use field to avoid lazily initializing the collection { Debug.Assert(handler.SslOptions.ClientCertificates == null); handler.SslOptions.ClientCertificates = new X509Certificate2Collection(); handler.SslOptions.ClientCertificates.AddRange(options.ClientCertificates); } } // Issue the request. The response must be status code 101. CancellationTokenSource?linkedCancellation; CancellationTokenSource externalAndAbortCancellation; if (cancellationToken.CanBeCanceled) // avoid allocating linked source if external token is not cancelable { linkedCancellation = externalAndAbortCancellation = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, _abortSource.Token); } else { linkedCancellation = null; externalAndAbortCancellation = _abortSource; } using (linkedCancellation) { response = await new HttpMessageInvoker(handler).SendAsync(request, externalAndAbortCancellation.Token).ConfigureAwait(false); externalAndAbortCancellation.Token.ThrowIfCancellationRequested(); // poll in case sends/receives in request/response didn't observe cancellation } if (response.StatusCode != HttpStatusCode.SwitchingProtocols) { throw new WebSocketException(WebSocketError.NotAWebSocket, SR.Format(SR.net_WebSockets_Connect101Expected, (int)response.StatusCode)); } // The Connection, Upgrade, and SecWebSocketAccept headers are required and with specific values. ValidateHeader(response.Headers, HttpKnownHeaderNames.Connection, "Upgrade"); ValidateHeader(response.Headers, HttpKnownHeaderNames.Upgrade, "websocket"); ValidateHeader(response.Headers, HttpKnownHeaderNames.SecWebSocketAccept, secKeyAndSecWebSocketAccept.Value); // The SecWebSocketProtocol header is optional. We should only get it with a non-empty value if we requested subprotocols, // and then it must only be one of the ones we requested. If we got a subprotocol other than one we requested (or if we // already got one in a previous header), fail. Otherwise, track which one we got. string?subprotocol = null; if (response.Headers.TryGetValues(HttpKnownHeaderNames.SecWebSocketProtocol, out IEnumerable <string>?subprotocolEnumerableValues)) { Debug.Assert(subprotocolEnumerableValues is string[]); string[] subprotocolArray = (string[])subprotocolEnumerableValues; if (subprotocolArray.Length > 0 && !string.IsNullOrEmpty(subprotocolArray[0])) { subprotocol = options.RequestedSubProtocols.Find(requested => string.Equals(requested, subprotocolArray[0], StringComparison.OrdinalIgnoreCase)); if (subprotocol == null) { throw new WebSocketException( WebSocketError.UnsupportedProtocol, SR.Format(SR.net_WebSockets_AcceptUnsupportedProtocol, string.Join(", ", options.RequestedSubProtocols), string.Join(", ", subprotocolArray))); } } } if (response.Content is null) { throw new WebSocketException(WebSocketError.ConnectionClosedPrematurely); } // Get the response stream and wrap it in a web socket. Stream connectedStream = response.Content.ReadAsStream(); Debug.Assert(connectedStream.CanWrite); Debug.Assert(connectedStream.CanRead); WebSocket = WebSocket.CreateFromStream( connectedStream, isServer: false, subprotocol, options.KeepAliveInterval); } catch (Exception exc) { if (_state < WebSocketState.Closed) { _state = WebSocketState.Closed; } Abort(); response?.Dispose(); if (exc is WebSocketException || (exc is OperationCanceledException && cancellationToken.IsCancellationRequested)) { throw; } throw new WebSocketException(WebSocketError.Faulted, SR.net_webstatus_ConnectFailure, exc); } finally { // Disposing the handler will not affect any active stream wrapped in the WebSocket. if (disposeHandler) { handler?.Dispose(); } } }
public StandardWebSocket(WebSocket webSocket, HttpContext context) { this.Context = context; this.WebSocket = webSocket ?? throw new ArgumentNullException(nameof(webSocket)); }
public override async Task KeepConnectionOpen(CancellationToken cancellationToken) { if (_websocket != null) { throw new Exception("WebSocket has already been accepted"); } try { _websocket = await _httpContext.WebSockets.AcceptWebSocketAsync(); var buffer = ArrayPool <byte> .Shared.Rent(4096); while (!cancellationToken.IsCancellationRequested && _websocket.State is WebSocketState.Connecting or WebSocketState.Open) { WebSocketReceiveResult message; try { message = await _websocket.ReceiveAsync(new ArraySegment <byte>(buffer), cancellationToken); } catch (OperationCanceledException) { break; } catch (WebSocketException) { break; } catch (IOException) { break; } if (message.MessageType == WebSocketMessageType.Close) { break; } if (message.EndOfMessage && message.MessageType == WebSocketMessageType.Text) { try { var parsed = JsonSerializer.Deserialize <Message>(buffer); if (parsed != null) { OnMessageReceived(parsed); } } catch (JsonException) { } } } } catch (Exception) { } finally { OnDisconnected(); } }
public WebSocketAdapter(ClientWebSocket?client = null, WebSocket?server = null) { Assert.True(client is null ^ server is null); _client = client; _server = server; }