/// <summary> /// Sends the message to the client with the connected clients /// </summary> /// <param name="clientHandler">Client handler.</param> static void RequestedEntitiesList(ClientHandler clientHandler) { List <(string, string)> entities = FetchConnectedEntities(clientHandler.Entity); ServerCommand sv_cmd_entities = new ServerCommand { Command = ServerOperations.ResponseSuccessEntities.Value, Message = Convert.ToBase64String(Encoding.Unicode.GetBytes(JsonConvert.SerializeObject(entities))) }; server.SendMessage(sv_cmd_entities, PacketType.ServerCommand, database.RetreiveEntityKey(clientHandler.Entity), clientHandler.Socket); }
/// <summary> /// Disconnects the user /// </summary> public void Disconnect() { stop = true; PacketType packetType = PacketType.ServerCommand; ServerCommand command = new ServerCommand { Command = ServerOperations.KickEntity.Value }; NetworkStream stream = Socket.GetStream(); byte[] packet = Server.BuildPacket(command, Program.database.RetreiveEntityKey(Entity), packetType); stream.Write(packet, 0, packet.Length); stream.Flush(); if (Program.enableSpy) { Program.spy.SendPacket(packet); } Socket.Close(); Socket.Dispose(); }
/// <summary> /// Handles all messages received by the client (except the first one) /// </summary> /// <param name="m">Packet without the byte length</param> /// <param name="clientHandler">Client handler.</param> static void Server_MessageReceived(byte[] m, ClientHandler clientHandler) { IPAddress ip = ((IPEndPoint)clientHandler.Socket.Client.RemoteEndPoint).Address; PacketType packetType = Server.DecodePacketType(m); Server.DeconstructPacket(m, out byte[] hmac, out ClientMessage message, out byte[] raw); if (enableDebug) { ReplaceWith(""); } ProcessDebugMessage(string.Format("Message received from {0} ({1})", message.Entity, ip)); // This step allows the verification of: // 1. if the entity is still accepted by the server // 2. if the hmac is corect Database.ValidationError validation = database.ValidateEntity(message, hmac, raw); switch (validation) { case Database.ValidationError.NoError: if (ClientOperations.RequestConnectedEntities.Value == message.Operation) { RequestedEntitiesList(clientHandler); } else if (ClientOperations.Disconnect.Value == message.Operation) { server.UserDisconnected(clientHandler.Entity); } else if (ClientOperations.RequestKeyNegotiation.Value == message.Operation) { NegotiateKey(message, clientHandler); } else { ServerCommand sv_cmd_invalid_operation = new ServerCommand { Command = ServerOperations.InvalidComand.Value }; server.SendMessage(sv_cmd_invalid_operation, PacketType.ServerCommand, database.RetreiveEntityKey(clientHandler.Entity), clientHandler.Socket); } break; case Database.ValidationError.InvalidKey: ProcessDebugMessage(string.Format("HMAC for message from {0} ({1}) failed!", message.Entity, ip)); ServerCommand sv_cmd_invalid_hmac = new ServerCommand { Command = ServerOperations.InvalidHMAC.Value, Message = string.Format("RECEIVED_HMAC={0}|COMPUTED_HMAC={1}", hmac.FromByteArrayToHex(), SHA256hmac.ComputeHMAC(raw, database.RetreiveEntityKey(clientHandler.Entity)).FromByteArrayToHex()) }; server.SendMessage(sv_cmd_invalid_hmac, PacketType.ServerCommand, DEFAULT_KEY.FromHexToByteArray(), clientHandler.Socket); break; case Database.ValidationError.NotFound: ProcessDebugMessage(string.Format("Entity {0} at {1} not found!", message.Entity, ip)); ServerCommand sv_cmd_entity_not_found = new ServerCommand { Command = ServerOperations.EntityNoLongerAvailable.Value }; server.SendMessage(sv_cmd_entity_not_found, PacketType.ServerCommand, database.RetreiveEntityKey(clientHandler.Entity), clientHandler.Socket); break; case Database.ValidationError.InvalidTime: ProcessDebugMessage("Packet time missmatch"); ServerCommand sv_cmd_ts_missmatch = new ServerCommand { Command = ServerOperations.InvalidTime.Value }; server.SendMessage(sv_cmd_ts_missmatch, PacketType.ClientMessage, database.RetreiveEntityKey(clientHandler.Entity), clientHandler.Socket); break; } if (enableDebug) { Console.WriteLine(""); Console.Write("\r" + menuManager.commandPrefix); } }
/// <summary> /// Manages the server menu /// </summary> /// <returns><c>true</c>, if the exit command was issued, <c>false</c> otherwise.</returns> bool ServerMenu() { ServerCommand command = ServerCommand.Invalid; while (command != ServerCommand.Back) { Console.Write("\r" + commandPrefix); string cmd = Console.ReadLine(); command = (ServerCommand)ToCommand(Menu.Server, cmd); switch (command) { case ServerCommand.List: Console.WriteLine(""); List <(string, string)> cmds = new List <(string, string)>(); foreach (string key in Program.server.clientHandlers.Keys) { ClientHandler handler = (ClientHandler)Program.server.clientHandlers[key]; IPAddress ip = ((IPEndPoint)handler.Socket.Client.RemoteEndPoint).Address; cmds.Add((key, ip.ToString())); } Console.WriteLine(cmds.ToStringTable( new[] { "Entity", "IP" }, a => a.Item1, a => a.Item2)); break; case ServerCommand.Back: break; case ServerCommand.Clear: Console.Clear(); break; case ServerCommand.Disconnect: MenuEventArgs listArgs = ProcessCommandArgs(Menu.Server, ServerCommand.Disconnect, cmd); string entity = (string)listArgs.Arguments.First(m => m.Key.Equals(ServerArg.Entity)).Value; Program.server.DisconnectClient(entity); ProcessLog(ProcessPrint.Info, "Entity " + entity + " was kicked", true); break; case ServerCommand.Exit: return(true); case ServerCommand.Help: HelpPrints.PrintServerHelp(); break; case ServerCommand.Invalid: ProcessLog(ProcessPrint.Error, "Invalid command", true); break; case ServerCommand.ServerInfo: ProcessLog(ProcessPrint.Info, string.Format("Server listening at {0}:{1}", Program.server.ListeningIP, Program.server.ListeningPort)); ProcessLog(ProcessPrint.Info, string.Format("There are {0} connected clients", Program.server.clientHandlers.Count)); Console.WriteLine(""); List <(string, string)> cmds1 = new List <(string, string)>(); foreach (string key in Program.server.clientHandlers.Keys) { ClientHandler handler = (ClientHandler)Program.server.clientHandlers[key]; IPAddress ip = ((IPEndPoint)handler.Socket.Client.RemoteEndPoint).Address; cmds1.Add((key, ip.ToString())); } Console.WriteLine(cmds1.ToStringTable( new[] { "Entity", "IP" }, a => a.Item1, a => a.Item2)); break; } } return(false); }