private static async void OnWebsocketEvent(object sender, WebSocketEventArg args) { if (args.data != null && args.isText) { string received = Encoding.UTF8.GetString(args.data); await _WebsocketServer.SendTextMessageAsync("Client: " + args.clientId + " on url: " + args.clientBaseUrl + ", says: " + received); } else { if (args.isOpen) { Console.WriteLine("Client: " + args.clientId + " connected!"); await _WebsocketServer.SendTextMessageAsync("Client: " + args.clientId + " on url: " + args.clientBaseUrl + ", says: " + "joined!"); } } if (args.isClosed) { if (args.data != null) { string received = Encoding.UTF8.GetString(args.data); Console.WriteLine("Client: " + args.clientId + " disconnected with message:"); Console.WriteLine(received); } else { string received = Encoding.UTF8.GetString(args.data); Console.WriteLine("Client: " + args.clientId + " disconnected."); } } }
/// <summary> /// WebSocket Server event handler, fires the event. /// </summary> /// <param name="arg">Arguments containing event arguments.</param> public void OnWebsocketEvent(object sender, WebSocketEventArg arg) { if (arg.isClosed) { WebSocketClientInfo key = null; bool found = false; foreach (var connection in _ListWithConnections) { if (connection.Key.clientId == arg.clientId) { key = connection.Key; found = true; break; } } if (found) { _ListWithConnections.Remove(key); } } WebsocketEvent?.Invoke(this, arg); }
/// <summary> /// Starts a connection given the settings set by caller. /// </summary> /// <param name="client">TcpClient socket handler.</param> /// <param name="stream">NetworkStream stream handler.</param> /// <param name="clientId">Id of client.</param> /// <param name="baseUrl">URL path used by client.</param> public async void StartConnection(TcpClient client, string clientId, string baseUrl) { WebSocketClientInfo info = new WebSocketClientInfo() { client = client, clientId = clientId, clientBaseUrl = baseUrl }; WebSocketServer newServer = new WebSocketServer(info, _BufferSize); newServer.WebSocketServerEvent += OnWebsocketEvent; _ListWithConnections.Add(info, newServer); try { await newServer.StartServerAsync(); } catch (Exception) { WebSocketEventArg args = new WebSocketEventArg() { clientId = clientId, clientBaseUrl = baseUrl, errorMessage = "Client disconnected forcefully", isClosed = true }; OnWebsocketEvent(this, args); } }
private async void OnWebSocketServerEvent(object sender, WebSocketEventArg args) { DebugHandler.TraceMessage("OnWebSocketServerEvent Called", DebugSource.TASK, DebugType.ENTRY_EXIT); try { if (args.isOpen) { if (!ClientIds.Contains(args.clientId)) { DebugHandler.TraceMessage("Client with id " + args.clientId + " from " + args.clientBaseUrl + " connected!", DebugSource.TASK, DebugType.INFO); ClientIds.Add(args.clientId); await SendMessage(new JsonWelcome() { local = LittleWeebSettings.Local }.ToJson()); } } if (args.isClosed) { if (ClientIds.Contains(args.clientId)) { DebugHandler.TraceMessage("Client with id " + args.clientId + " from " + args.clientBaseUrl + " disconnected!", DebugSource.TASK, DebugType.INFO); ClientIds.Remove(args.clientId); } } if (args.data != null && args.isText) { string received = Encoding.ASCII.GetString(args.data); DebugHandler.TraceMessage(received, DebugSource.TASK, DebugType.INFO); OnWebSocketEvent?.Invoke(this, new WebSocketEventArgs() { Message = received }); await SendMessage(new JsonReceivedResponse() { received = received }.ToJson()); } if (args.isPing) { DebugHandler.TraceMessage("IsPing: " + args.isPing.ToString(), DebugSource.TASK, DebugType.INFO); await Server.SendPongMessageAsync(); } if (args.isPong) { DebugHandler.TraceMessage("IsPong: " + args.isPing.ToString(), DebugSource.TASK, DebugType.INFO); await Server.SendPingMessageAsync(); } } catch (Exception e) { DebugHandler.TraceMessage(e.ToString(), DebugSource.TASK, DebugType.WARNING); } }
/// <summary> /// Starts the WebSocket server / connection with the client synchronous. /// </summary> /// <returns></returns> public void StartServer() { NetworkStream stream = _ClientInfo.client.GetStream(); byte[] buffer = new byte[_BufferSize]; List <byte> data = new List <byte>(); bool continuationFrame = false; WebSocketEventArg messageArg = new WebSocketEventArg(); bool isConnected = false; while (_ClientInfo.client.Connected && stream.CanRead) { messageArg = new WebSocketEventArg() { clientBaseUrl = _ClientInfo.clientBaseUrl, clientId = _ClientInfo.clientId }; if (!isConnected) { Thread.Sleep(500); messageArg.clientId = _ClientInfo.clientId; messageArg.isOpen = true; isConnected = true; WebSocketServerEvent?.Invoke(this, messageArg); } int bytesRead = stream.Read(buffer, 0, buffer.Length); stream.Flush(); int opCode = buffer[0] & 0x0F; bool finalMessage = ((buffer[0] & 0x80) == 0x80); bool maskKey = ((buffer[1] & 0x80) == 0x80); UInt64 payloadLength = 0; int initialPayloadLength = buffer[1] & 0x7F; switch (opCode) { case 0x00: continuationFrame = true; break; case 0x01: continuationFrame = false; messageArg.isText = true; break; case 0x02: continuationFrame = false; messageArg.isBinary = true; break; case 0x08: continuationFrame = false; messageArg.isClosed = true; break; case 0x09: continuationFrame = false; messageArg.isPing = true; break; case 0x0A: continuationFrame = false; messageArg.isPong = true; break; default: stream.Close(); _ClientInfo.client.Close(); break; } byte[] payloadLengthBytes; byte[] maskKeyBytes = new byte[4]; switch (initialPayloadLength) { case 126: payloadLengthBytes = new byte[2]; Array.Copy(buffer, 2, payloadLengthBytes, 0, payloadLengthBytes.Length); payloadLength = BitConverter.ToUInt16(payloadLengthBytes.Reverse <byte>().ToArray(), 0); messageArg.messageLength = payloadLength; if (maskKey) { Array.Copy(buffer, 4, maskKeyBytes, 0, maskKeyBytes.Length); byte[] tempData = new byte[payloadLength]; Array.Copy(buffer, 8, tempData, 0, tempData.Length); for (int i = 0; i < tempData.Length; i++) { tempData[i] = (byte)(maskKeyBytes[i % 4] ^ tempData[i]); } data.AddRange(tempData); } else { byte[] tempData = new byte[payloadLength]; Array.Copy(buffer, 4, tempData, 0, tempData.Length); data.AddRange(tempData); } break; case 127: payloadLengthBytes = new byte[8]; Array.Copy(buffer, 2, payloadLengthBytes, 0, payloadLengthBytes.Length); payloadLength = BitConverter.ToUInt64(payloadLengthBytes.Reverse <byte>().ToArray(), 0); messageArg.messageLength = payloadLength; if (maskKey) { Array.Copy(buffer, 10, maskKeyBytes, 0, maskKeyBytes.Length); byte[] tempData = new byte[payloadLength]; Array.Copy(buffer, 14, tempData, 0, tempData.Length); for (int i = 0; i < tempData.Length; i++) { tempData[i] = (byte)(maskKeyBytes[i % 4] ^ tempData[i]); } data.AddRange(tempData); } else { byte[] tempData = new byte[payloadLength]; Array.Copy(buffer, 10, tempData, 0, tempData.Length); data.AddRange(tempData); } break; default: payloadLength = (uint)initialPayloadLength; messageArg.messageLength = payloadLength; if (maskKey) { Array.Copy(buffer, 2, maskKeyBytes, 0, maskKeyBytes.Length); byte[] tempData = new byte[payloadLength]; Array.Copy(buffer, 6, tempData, 0, tempData.Length); for (int i = 0; i < tempData.Length; i++) { tempData[i] = (byte)(maskKeyBytes[i % 4] ^ tempData[i]); } data.AddRange(tempData); } else { byte[] tempData = new byte[(bytesRead - 2)]; Array.Copy(buffer, 2, tempData, 0, tempData.Length); data.AddRange(tempData); } break; } if (!continuationFrame && finalMessage) { messageArg.data = data.ToArray(); WebSocketServerEvent?.Invoke(this, messageArg); data.Clear(); } } messageArg.isOpen = false; WebSocketServerEvent?.Invoke(this, messageArg); }