private async Task ClientDisconnected_Internal(ConnectedUser player) { lock (clients) { clients.Remove(player); } if (ClientDisconnected != null) { await ClientDisconnected.Invoke(player); } }
private async Task Send(ConnectedUser ConnectedClient, ArraySegment <byte> data) { try { await ConnectedClient.socket.SendAsync(data, SocketFlags.None); } catch (Exception e) { Logger.Debug(e.ToString()); await ClientDisconnected_Internal(ConnectedClient); } }
public async Task Send(ConnectedUser ConnectedClient, Packet packet) { try { var bytes = GetFrameFromPacket(packet); await ConnectedClient.networkStream.WriteAsync(bytes.Array, 0, bytes.Count); } catch (Exception e) { Logger.Debug(e.ToString()); await ClientDisconnected_Internal(ConnectedClient); } }
public async Task Start() { var ipv4Address = IPAddress.Any; var localIPV4EndPoint = new IPEndPoint(ipv4Address, port); ipv4Server = new Socket(ipv4Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp); ipv4Server.Bind(localIPV4EndPoint); ipv4Server.Listen(100); 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} ..."); var connectedUser = new ConnectedUser { socket = clientSocket, networkStream = new NetworkStream(clientSocket, ownsSocket: true), id = Guid.NewGuid() }; byte[] buffer = new byte[1024]; string headerResponse = string.Empty; if (ipv4Server != null && ipv4Server.IsBound) { try { var i = connectedUser.networkStream.Read(buffer, 0, 1024); headerResponse = (Encoding.UTF8.GetString(buffer)).Substring(0, i); } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine(e.StackTrace); } } 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 refKey) { string longKey = refKey + "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(connectedUser); } if (ClientConnected != null) { await ClientConnected.Invoke(connectedUser); } ReceiveLoop(connectedUser); } }
private async void ReceiveLoop(ConnectedUser player) { try { // Begin receiving the data from the remote device. while (player?.socket?.Connected ?? false) { var bytesRead = await player.networkStream.ReadAsync(player.buffer, 0, ConnectedUser.BufferSize); 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, GetFrameFromPacket(null, 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) { try { readPacket = decoded.ProtoDeserialize <Packet>(); 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, GetFrameFromPacket(null, EOpcodeType.ClosedConnection)); throw new Exception("Stream ended"); } } } catch (ObjectDisposedException) { await ClientDisconnected_Internal(player); } catch (Exception e) { Logger.Debug(e.ToString()); await ClientDisconnected_Internal(player); } }
private async Task WsServer_PacketReceived(ConnectedUser user, Packet packet) { if (packet.packetCase == Packet.packetOneofCase.Connect) { var response = new Packet() { ConnectResponse = new ConnectResponse() { Self = new User() { Id = Guid.NewGuid().ToString(), Name = "Moon" }, Response = new Response() { Message = "Successfully connected to Rain server", Type = Response.ResponseType.Success }, State = State } }; await Send(user, response); } else if (packet.packetCase == Packet.packetOneofCase.Command) { UnityMainThreadDispatcher.Instance().Enqueue(() => { var command = packet.Command; switch (command.commandCase) { case Command.commandOneofCase.do_action_command: { DoAction(command.do_action_command.Action); break; } } }); } else if (packet.packetCase == Packet.packetOneofCase.Event) { var @event = packet.Event; switch (@event.eventCase) { case Event.eventOneofCase.player_added_event: await AddPlayer(@event.player_added_event.Player); break; case Event.eventOneofCase.player_updated_event: await UpdatePlayer(@event.player_updated_event.Player); break; case Event.eventOneofCase.player_left_event: await RemovePlayer(@event.player_left_event.Player); break; case Event.eventOneofCase.toggle_updated_event: await UpdateToggle(@event.toggle_updated_event.Toggle); break; } } }