public async Task Disconnect() { if (_state == WebSocketConnectionState.Closed) { return; } if (_client == null) { return; } try { using (var cts = new CancellationTokenSource(_options.SendTimeout)) { await _client.CloseAsync(WebSocketCloseStatus.NormalClosure, "Completed", cts.Token); } _client.Dispose(); _client = null; _state = WebSocketConnectionState.Closed; } catch (Exception) { // If we fail, just ignore it } }
/// <summary> /// Close the connection. /// </summary> /// <param name="close">The close event arguments.</param> /// <param name="send">Is sending.</param> /// <param name="wait">Should wait.</param> private void Close(CloseEventArgs close, bool send, bool wait) { lock (_lockConnect) { // If already closed or closing. if (_readyState == WebSocketConnectionState.Closing || _readyState == WebSocketConnectionState.Closed) { return; } // Wait if sending. send = send && _readyState == WebSocketConnectionState.Open; wait = wait && send; // Closing. _readyState = WebSocketConnectionState.Closing; } // Close the handshake. close.WasClean = CloseHandshake( send ? Frame.CreateCloseFrame(close.PayloadData, _client).ToByteArray() : null, wait ? _waitTime : TimeSpan.Zero, _client ? (Action)ReleaseClientResources : ReleaseServerResources); // Connection state is closed. _readyState = WebSocketConnectionState.Closed; }
/// <summary> /// Check if closable. /// </summary> /// <param name="state">The web socket state.</param> /// <returns>The reason.</returns> public static string CheckIfClosable(this WebSocketConnectionState state) { return(state == WebSocketConnectionState.Closing ? "While closing the WebSocket connection." : state == WebSocketConnectionState.Closed ? "The WebSocket connection has already been closed." : null); }
private void WebSocketConnectionOnOnOpened(object sender, EventArgs e) { Logger.Debug(TAG, $"WebSocket connection opened to:{_wsUrl}"); _executor.Execute(() => { State = WebSocketConnectionState.Connected; OnConnectionOpen(); }); }
public void Dispose() { State = WebSocketConnectionState.Closed; _pinger?.Dispose(); _timerCts.Cancel(); _terminateReceiveCts.Cancel(); _inbound.Complete(); _outbound.Complete(); }
protected void ReportError(string errorMessage) { Logger.Error(TAG, errorMessage); _executor.Execute(() => { if (State == WebSocketConnectionState.Error) { return; } State = WebSocketConnectionState.Error; _events.OnWebSocketError(errorMessage); }); }
public Task <WebSocketCloseResult> ExecuteAsync(Func <WebSocketFrame, object, Task> messageHandler, object state) { if (State == WebSocketConnectionState.Closed) { throw new ObjectDisposedException(nameof(WebSocketConnection)); } if (State != WebSocketConnectionState.Created) { throw new InvalidOperationException("Connection is already running."); } State = WebSocketConnectionState.Connected; return(ReceiveLoop(messageHandler, state, _terminateReceiveCts.Token)); }
public static bool IsConnected(this WebSocketConnectionState connectionState) { try { return(connectionState.webSocket.Context.WebSocket.IsAlive); } catch (SocketException) { return(false); } catch (Exception ex) { ex.DebugLog(); return(false); } }
public static void Send(SessionState sessionState, WebSocketConnectionState connectionState, string data) { if (sessionState == null || !sessionState.driver.IsConnected()) { return; } try { lock (sessionState.driver) { connectionState.webSocket.Send(data); } } catch (Exception ex) { ex.DebugLog(); } }
private WebSocketCloseResult HandleCloseFrame(ReadableBuffer payload, WebSocketFrame frame, out ushort?actualStatusCode) { // Update state if (State == WebSocketConnectionState.CloseSent) { State = WebSocketConnectionState.Closed; } else { State = WebSocketConnectionState.CloseReceived; } // Process the close frame WebSocketCloseResult closeResult; if (!WebSocketCloseResult.TryParse(frame.Payload, out closeResult, out actualStatusCode)) { closeResult = WebSocketCloseResult.Empty; } return(closeResult); }
/// <summary> /// Sends a Close frame to the other party. This does not guarantee that the client will send a responding close frame. /// </summary> /// <remarks> /// If the other party does not respond with a close frame, the connection will remain open and the <see cref="Task{WebSocketCloseResult}"/> /// will remain active. Call the <see cref="IDisposable.Dispose"/> method on this instance to forcibly terminate the connection. /// </remarks> /// <param name="result">A <see cref="WebSocketCloseResult"/> with the payload for the close frame</param> /// <param name="cancellationToken">A <see cref="CancellationToken"/> that indicates when/if the send is cancelled.</param> /// <returns>A <see cref="Task"/> that completes when the close frame has been sent</returns> public async Task CloseAsync(WebSocketCloseResult result, CancellationToken cancellationToken) { if (State == WebSocketConnectionState.Closed) { throw new ObjectDisposedException(nameof(WebSocketConnection)); } else if (State == WebSocketConnectionState.Created) { throw new InvalidOperationException("Cannot send close frame when the connection hasn't been started"); } else if (State == WebSocketConnectionState.CloseSent) { throw new InvalidOperationException("Cannot send multiple close frames"); } var payloadSize = result.GetSize(); await SendCoreAsync( fin : true, opcode : WebSocketOpcode.Close, payloadAllocLength : payloadSize, payloadLength : payloadSize, payloadWriter : CloseResultPayloadWriter, payload : result, cancellationToken : cancellationToken); _timerCts.Cancel(); _pinger?.Dispose(); if (State == WebSocketConnectionState.CloseReceived) { State = WebSocketConnectionState.Closed; } else { State = WebSocketConnectionState.CloseSent; } }
/// <summary> /// Initialise the members. /// </summary> private void Init() { _waitTime = TimeSpan.FromSeconds(1); _readyState = WebSocketConnectionState.Open; _messageEventQueue = new Queue <MessageEventArgs>(); _receiveResult = new ReceiveResultWebContext() { ReturnComplete = true }; _lockEnqueue = ((ICollection)_messageEventQueue).SyncRoot; if (_context != null) { // Receive data in async mode. _context.Context.Context.ReceivedAsyncMode = () => AsyncModeReceiver(); } _exitReceiving = new AutoResetEvent(false); _receivePong = new AutoResetEvent(false); _recevedFrame = new AutoResetEvent(false); _frameReturnedComplete = new AutoResetEvent(false); }
public void Disconnect(bool waitForComplete) { CheckIfCalledOnValidThread(); Logger.Debug(TAG, $"Disconnect WebSocket. State: {State}"); if (State == WebSocketConnectionState.Registered) { // Send "bye" to WebSocket server. SendByeMessage(); State = WebSocketConnectionState.Connected; } if (State == WebSocketConnectionState.Connected || State == WebSocketConnectionState.Error) { if (waitForComplete) { _mre = new ManualResetEvent(false); } WebSocketConnection.Close(); State = WebSocketConnectionState.Closed; if (waitForComplete) { try { _mre.WaitOne(CloseTimeout); } catch (Exception ex) { Logger.Error(TAG, $"Wait error:{ex}"); } } } UnWireEvents(); Logger.Debug(TAG, "Disconnecting WebSocket done."); }
public async Task Connect(string remote, WebSocketConnectionOptions options = null) { if (_state != WebSocketConnectionState.Closed) { throw new Exception($"Invalid state transition {_state} -> {WebSocketConnectionState.Connecting}"); } if (options == null) { options = new WebSocketConnectionOptions(); } _state = WebSocketConnectionState.Connecting; _options = options; // fix urls with no prefix if (!remote.StartsWith("ws://")) { remote = $"ws://{remote}"; } _client = new ClientWebSocket() { Options = { KeepAliveInterval = _options.KeepAliveInterval } }; using (var cts = new CancellationTokenSource(_options.ConnectionTimeout)) { await _client.ConnectAsync(new Uri(remote), cts.Token); } _state = WebSocketConnectionState.Open; }
public static void DropConnection(this WebSocketConnectionState connectionState) { try { if (connectionState.sessionState.successfullyConnected) { try { using (var dbContext = Database.For <ThePalaceEntities>()) { var sqlParam = new SqlParameter("userID", (int)connectionState.sessionState.UserID); dbContext.Database.ExecuteSqlCommand("EXEC Users.FlushUserDetails @userID", sqlParam); } } catch (Exception ex) { ex.DebugLog(); } } try { connectionState.webSocket.Context.WebSocket.Close(); } catch (Exception ex) { ex.DebugLog(); } try { connectionState.Dispose(); } catch (Exception ex) { ex.DebugLog(); } if (connectionStates.ContainsKey(connectionState.sessionState.UserID)) { lock (connectionStates) { if (connectionStates.ContainsKey(connectionState.sessionState.UserID)) { connectionStates.Remove(connectionState.sessionState.UserID); } } } if (SessionManager.sessionStates.ContainsKey(connectionState.sessionState.UserID)) { lock (SessionManager.sessionStates) { if (SessionManager.sessionStates.ContainsKey(connectionState.sessionState.UserID)) { SessionManager.sessionStates[connectionState.sessionState.UserID].Dispose(); SessionManager.sessionStates.Remove(connectionState.sessionState.UserID); } } } if (connectionState.sessionState.successfullyConnected) { new Business.MSG_LOGOFF().SendToServer(null, new Message { sessionState = connectionState.sessionState, }); } if (SessionManager.GetRoomUserCount(connectionState.sessionState.RoomID) < 1 && ServerState.roomsCache.ContainsKey(connectionState.sessionState.RoomID)) { ServerState.roomsCache[connectionState.sessionState.RoomID].Flags &= (~(int)RoomFlags.RF_Closed); } } catch (Exception ex) { ex.DebugLog(); } }
protected override void OnOpen() { connectionState = WebAsyncSocket.Accept(this); }
public static void Receive(WebSocketConnectionState connectionState, MessageEventArgs e) { var floodControlThreadshold_InMilliseconds = ConfigManager.GetValue <int>("FloodControlThreadshold_InMilliseconds", 1000).Value; var floodControlThreadshold_RawCount = ConfigManager.GetValue <int>("FloodControlThreadshold_RawCount", 100).Value; //var floodControlThreadshold_RawSize = ConfigManager.GetValue<int>("FloodControlThreadshold_RawSize", ???).Value; var floodControlThreadshold_TimeSpan = new TimeSpan(0, 0, 0, 0, floodControlThreadshold_InMilliseconds); var sessionState = connectionState.sessionState; var handler = connectionState.webSocket; var bytesReceived = e.Data?.Length ?? 0; var data = e.Data; if (bytesReceived > 0) { connectionState.lastActivity = DateTime.UtcNow; if (!sessionState.Authorized) { #region Flood Control connectionState.floodControl[DateTime.UtcNow] = bytesReceived; //var rawSize = state.floodControl.Values.Sum(); var expired = connectionState.floodControl .Where(f => f.Key > DateTime.UtcNow.Subtract(floodControlThreadshold_TimeSpan)) .Select(f => f.Key) .ToList(); expired.ForEach(f => { connectionState.floodControl.Remove(f); }); if (connectionState.floodControl.Count > floodControlThreadshold_RawCount) { ThePalace.Core.Utility.Logger.Log(MessageTypes.Info, $"Disconnect[{sessionState.UserID}]: Flood Control", "WebAsyncSocket.Receive()"); new Business.MSG_SERVERDOWN { reason = ServerDownFlags.SD_Flood, whyMessage = "Flood Control!", }.Send(null, new Message { sessionState = sessionState, }); connectionState.DropConnection(); return; } #endregion } if (bytesReceived > 0) { try { connectionState.header = new Header(); connectionState.header.DeserializeJSON(data); } catch { } var mnemonic = Regex.Replace(connectionState.header.eventType, @"[^\w\d]+", string.Empty); var type = PluginManager.GetType($"ThePalace.Server.Plugins.Protocols.{mnemonic}"); var message = (Message)null; if (type == null) { type = Type.GetType($"ThePalace.Server.Protocols.{connectionState.header.eventType}"); } if (type == null) { new Business.MSG_SERVERDOWN { reason = ServerDownFlags.SD_CommError, whyMessage = "Communication Error!", }.Send(null, new Message { sessionState = sessionState, }); connectionState.DropConnection(); } if (type != null) { message = new Message { protocol = (IReceiveProtocol)Activator.CreateInstance(type), header = new Header(connectionState.header), sessionState = sessionState, }; } if (message != null) { try { message.protocol.DeserializeJSON(connectionState.header.message); lock (SessionManager.messages) { SessionManager.messages.Enqueue(message); ThreadController.manageMessagesQueueSignalEvent.Set(); } } catch (Exception ex) { ex.DebugLog(); } connectionState.lastPinged = null; connectionState.lastPacketReceived = DateTime.UtcNow; } } } else if (!connectionState.IsConnected()) { connectionState.DropConnection(); } }