public void State(String socketId, WebSocketState state, String description) { if (IsEnabled()) { State(socketId, state.ToString(), description ?? String.Empty); } }
internal static string CheckIfAvailable( WebSocketState state, bool connecting = false, bool open = true, bool closing = false, bool closed = false) { return((!connecting && state == WebSocketState.Connecting) || (!open && state == WebSocketState.Open) || (!closing && state == WebSocketState.Closing) || (!closed && state == WebSocketState.Closed) ? "This operation isn't available in: " + state.ToString().ToLower() : null); }
protected override void AbortInternal() { WebSocketState webSocketState = this.webSocket.State; if (!this.socketAborted && webSocketState != WebSocketState.Aborted) { Events.TransportAborted(this.correlationId); this.socketAborted = true; this.webSocket.Abort(); this.webSocket.Dispose(); } else { Events.TransportAlreadyClosedOrAborted(this.correlationId, webSocketState.ToString()); } }
private async void ClientHandler_ClientStateChanged(object sender, WebSocketState e) { DialogService.Toast("Client State Changed" + e.ToString()); if (e == WebSocketState.Open) { await Task.Delay(2000); var res = await SendMessage(new ChatObject(MessageType.Subscribe) { Message = AppService.Token, SenderName = AppService.CurrentUser }); Debug.WriteLine(res); } }
protected override bool CloseInternal() { WebSocketState webSocketState = this.webSocket.State; if (webSocketState != WebSocketState.Closed && webSocketState != WebSocketState.Aborted) { Events.TransportClosed(this.correlationId); this.CloseInternalAsync(TimeSpan.FromSeconds(30)).ContinueWith( t => { Events.CloseException(this.correlationId, t.Exception); }, TaskContinuationOptions.OnlyOnFaulted); } else { Events.TransportAlreadyClosedOrAborted(this.correlationId, webSocketState.ToString()); } return(true); }
/// <summary> /// Sends binary <paramref name="data" /> using the WebSocket connection. /// </summary> /// <param name="data">An array of <see cref="byte" /> that represents the binary data to send.</param> /// <param name="opcode">The opcode.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns> /// A task that represents the asynchronous of send /// binary data using websocket. /// </returns> public async Task SendAsync(byte[] data, Opcode opcode, CancellationToken cancellationToken = default) { if (_readyState != WebSocketState.Open) { throw new WebSocketException(CloseStatusCode.Normal, $"This operation isn\'t available in: {_readyState.ToString()}"); } using (var stream = new WebSocketStream(data, opcode, Compression)) { foreach (var frame in stream.GetFrames()) { await Send(frame).ConfigureAwait(false); } } }
override public string ToString() { return(Connection.Id + ": " + WebSocketState.ToString()); }
private static string CheckIfAvailable(WebSocketState state, bool connecting, bool open, bool closing, bool closed) { return (!connecting && state == WebSocketState.Connecting) || (!open && state == WebSocketState.Open) || (!closing && state == WebSocketState.Closing) || (!closed && state == WebSocketState.Closed) ? "This operation isn't available in: " + state.ToString().ToLower() : null; }
// This task will run until the socket closes or is canceled, then it exits. private async Task Send(CancellationToken token) { bool exit = false; while (!exit) { switch (_webSocket.State) { case WebSocketState.CloseSent: // Probably not allowed to send again after sending Close once. case WebSocketState.Closed: case WebSocketState.Aborted: case WebSocketState.None: exit = true; break; case WebSocketState.CloseReceived: try { await _webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "", token).ConfigureAwait(false); } catch (OperationCanceledException) // not an error, flow control { exit = true; } catch (WebSocketException wse) { exit = true; _lastError = $"{_displayId} Send: [{_webSocket.State.ToString()}] {wse.Message}"; _logger?.Invoke(_lastError, 1); } break; case WebSocketState.Connecting: case WebSocketState.Open: { Tuple <string, byte[], long> msgBytes; //------------------- // Wait until the semaphore says we should wake up. If it's set, we just run right through. try { // Wait forever for a new message to be added or for the Recv task to tell us to give up due to websocket closure or abort await _releaseSendThread.WaitAsync(token).ConfigureAwait(false); } catch (OperationCanceledException) // not an error, flow control { exit = true; } //------------------- // If there's anything to send, send it. if (_outgoing.TryDequeue(out msgBytes)) // keep sending until we run dry, then block { long deltaTicks = (DateTime.UtcNow.Ticks - msgBytes.Item3); _stats_msgQueuedTime += deltaTicks; // this is the total time this message was queued _logger?.Invoke($"{_displayId} msg queue time: {TimeSpan.FromTicks(deltaTicks).TotalSeconds}", 2); try { if (msgBytes.Item2 == null) // is text message { byte[] rawMsgBytes = System.Text.Encoding.UTF8.GetBytes(msgBytes.Item1); await _webSocket.SendAsync(new ArraySegment <byte>(rawMsgBytes), WebSocketMessageType.Text, true, token).ConfigureAwait(false); // keep stats _stats_sentMsgs++; _stats_sentBytes += rawMsgBytes.Length; } else { if (msgBytes.Item2.Equals(sCloseOutputAsync)) // we want to close { await _webSocket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "", token).ConfigureAwait(false); } else { await _webSocket.SendAsync(new ArraySegment <byte>(msgBytes.Item2), WebSocketMessageType.Binary, true, token).ConfigureAwait(false); // keep stats _stats_sentMsgs++; _stats_sentBytes += msgBytes.Item2.Length; } } } catch (OperationCanceledException) // not an error, flow control { exit = true; } catch (WebSocketException wse) { exit = true; _lastError = $"{_displayId} Send: [{_webSocket.State.ToString()}] {wse.Message}"; _logger?.Invoke(_lastError, 1); } } break; } } } //------------------- try { // Give the connection 5 seconds to close gracefully, then kill it with the token if (await Task.WhenAny(_recvTask, Task.Delay(2000, _cancellationTokenSource.Token)) == _recvTask) { // This waits a second on the off-chance Send exits due to an exception of some sort and Recv keeps running. await _recvTask; // make sure recv is exited before we do the disconnect callback. } else { _cancellationTokenSource.Cancel(); } } catch (Exception e) { _logger?.Invoke($"Exception shutting down Send thread. {e.Message}", 0); } finally // must make sure we call _onDisconnectCallback, otherwise it's an infinite loop waiting for send threads to tear down { _logger?.Invoke("enter the finally", 0); WebSocketState finalState = _webSocket != null ? _webSocket.State : WebSocketState.None; // Let the program know this socket is dead -- note this is on the Send thread, NOT main thread!!! _onDisconnectCallback(this); double totalSeconds = Math.Max(0.1, TimeSpan.FromTicks(DateTime.UtcNow.Ticks - _connectedAtTicks).TotalSeconds); _logger?.Invoke($"{_displayId} ({finalState.ToString()}) SendExit Recv: {_stats_recvMsgs}/{Utilities.BytesToHumanReadable(_stats_recvBytes)}/{Utilities.BytesToHumanReadable((long)(_stats_recvBytes / totalSeconds))}/s Send: {_stats_sentMsgs}/{Utilities.BytesToHumanReadable(_stats_sentBytes)}/{Utilities.BytesToHumanReadable((long)(_stats_sentBytes / totalSeconds))}/s TotalMsgQTime: {TimeSpan.FromTicks(_stats_msgQueuedTime).TotalSeconds}", 0); } }