private async Task ClientDisconnected_Internal(WsConnectedClient player) { lock (clients) { clients.Remove(player); } if (ClientDisconnected != null) { await ClientDisconnected.Invoke(player); } }
private async Task Send(WsConnectedClient ConnectedClient, ArraySegment <byte> data) { try { await ConnectedClient.workSocket.SendAsync(data, SocketFlags.None); } catch (Exception e) { Logger.Debug(e.ToString()); await ClientDisconnected_Internal(ConnectedClient); } }
private async Task Send(WsConnectedClient ConnectedClient, string json) { try { await ConnectedClient.workSocket.SendAsync(GetFrameFromString(json), SocketFlags.None); } catch (Exception e) { Logger.Debug(e.ToString()); await ClientDisconnected_Internal(ConnectedClient); } }
public async Task Start() { IPAddress ipv4Address = IPAddress.Any; IPAddress ipv6Address = IPAddress.IPv6Any; IPEndPoint localIPV4EndPoint = new IPEndPoint(ipv4Address, port); IPEndPoint localIPV6EndPoint = new IPEndPoint(ipv6Address, port); ipv4Server = new Socket(ipv4Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp); ipv6Server = new Socket(ipv6Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp); ipv4Server.Bind(localIPV4EndPoint); ipv6Server.Bind(localIPV6EndPoint); ipv4Server.Listen(100); ipv6Server.Listen(100); Func <Socket, Task> processClient = async(clientSocket) => { var ConnectedClient = new WsConnectedClient { workSocket = clientSocket, id = Guid.NewGuid() }; byte[] buffer = new byte[1024]; string headerResponse = string.Empty; if ((ipv4Server != null && ipv4Server.IsBound) || (ipv6Server != null && ipv6Server.IsBound)) { var i = ConnectedClient.workSocket.Receive(buffer); headerResponse = (Encoding.UTF8.GetString(buffer)).Substring(0, i); } if (clientSocket != null) { /* Handshaking and managing ClientSocket */ if (headerResponse != "") { var key = headerResponse.Replace("ey:", "`") .Split('`')[1] .Replace("\r", "").Split('\n')[0] .Trim(); byte[] ComputeHash(string str) { return(sha1.ComputeHash(Encoding.ASCII.GetBytes(str))); } string AcceptKey(ref string key) { string longKey = key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; byte[] hashBytes = ComputeHash(longKey); return(Convert.ToBase64String(hashBytes)); } var acceptKey = AcceptKey(ref key); var newLine = "\r\n"; var response = "HTTP/1.1 101 Switching Protocols" + newLine + "Upgrade: websocket" + newLine + "Connection: Upgrade" + newLine + "Sec-WebSocket-Accept: " + acceptKey + newLine + newLine; clientSocket.Send(Encoding.UTF8.GetBytes(response)); } } lock (clients) { clients.Add(ConnectedClient); } if (ClientConnected != null) { await ClientConnected.Invoke(ConnectedClient); } ReceiveLoop(ConnectedClient); }; Func <Task> ipv4Accept = async() => { while (Enabled) { // Start an asynchronous socket to listen for connections. Logger.Debug($"Waiting for an IPV4 connection on {ipv4Address}:{port} ..."); var clientSocket = await ipv4Server.AcceptAsync(); Logger.Debug($"Accepted connection on {ipv4Address}:{port} ..."); await processClient(clientSocket); } }; Func <Task> ipv6Accept = async() => { while (Enabled) { // Start an asynchronous socket to listen for connections. Logger.Debug($"Waiting for an IPV6 connection on {ipv6Address}:{port} ..."); var clientSocket = await ipv6Server.AcceptAsync(); Logger.Debug($"Accpeted connection on {ipv6Address}:{port} ..."); await processClient(clientSocket); } }; await ipv4Accept(); //Task.Run(ipv4Accept); //ipv6Accept(); }
private async void ReceiveLoop(WsConnectedClient player) { try { // Begin receiving the data from the remote device. while (player?.workSocket?.Connected ?? false) { var bytesRead = await player.workSocket.ReceiveAsync(player.buffer, SocketFlags.None); if (bytesRead > 0) { var currentBytes = new byte[bytesRead]; Buffer.BlockCopy(player.buffer.ToArray(), 0, currentBytes, 0, bytesRead); Packet readPacket = null; bool fin = (currentBytes[0] & 0b10000000) != 0, mask = (currentBytes[1] & 0b10000000) != 0; int opcode = currentBytes[0] & 0b00001111, msglen = currentBytes[1] - 128, offset = 2; if (opcode == 0x8) { await Send(player, GetFrameFromString("", EOpcodeType.ClosedConnection)); throw new Exception("Stream ended"); } if (msglen == 126) { msglen = BitConverter.ToUInt16(new byte[] { currentBytes[3], currentBytes[2] }, 0); offset = 4; } if (msglen == 0) { Logger.Debug("msglen == 0"); } else if (mask) { byte[] decoded = new byte[msglen]; byte[] masks = new byte[4] { currentBytes[offset], currentBytes[offset + 1], currentBytes[offset + 2], currentBytes[offset + 3] }; offset += 4; for (int i = 0; i < msglen; ++i) { decoded[i] = (byte)(currentBytes[offset + i] ^ masks[i % 4]); } player.accumulatedBytes.AddRange(decoded); var accumulatedBytes = player.accumulatedBytes.ToArray(); if (accumulatedBytes.Length == msglen) { string text = Encoding.UTF8.GetString(decoded); Logger.Warning(text); try { readPacket = Packet.FromJSON(text); PacketReceived?.Invoke(player, readPacket); } catch (Exception e) { Logger.Error(e.Message); Logger.Error(e.StackTrace); } player.accumulatedBytes.Clear(); accumulatedBytes = player.accumulatedBytes.ToArray(); } } } else if (bytesRead == 0) { await Send(player, GetFrameFromString("", EOpcodeType.ClosedConnection)); throw new Exception("Stream ended"); } } } catch (ObjectDisposedException) { await ClientDisconnected_Internal(player); } catch (Exception e) { Logger.Debug(e.ToString()); await ClientDisconnected_Internal(player); } }