/// <summary> /// Handles received message /// </summary> /// <param name="client">Client this message was received from</param> /// <param name="line">Network message</param> public void ReceiveMessage(ClientConnection client, string line) { Logger.Log("Received [" + client.Name + "]: " + Network.RawMsgDecode(line), "Server"); string[] lineParts = line.Split(new char[] { Network.MSG_SEPARATOR }, StringSplitOptions.RemoveEmptyEntries); int i = 1; switch (Network.GetMessageType(lineParts)) { case MessageType.Message: SendToAll(Network.MakeServerMessage(MessageType.Message, client, lineParts[1])); Network.AddMessage("[S] Message: " + client.Name + ": " + lineParts[1]); break; case MessageType.Ping: client.SetPing(); break; case MessageType.NickChange: string newNick = lineParts[i++]; bool success = true; lock (ClientConnections) { foreach (var item in ClientConnections) if (item.Name == newNick) { success = false; break; } } if (!success) { client.StartSend(Network.MakeServerMessage(MessageType.Failed, MessageType.NickChange, "Selected nickname already taken.")); break; } SendToAll(Network.MakeServerMessage(MessageType.NickChange, client.Name, newNick)); client.Name = newNick; break; case MessageType.UserList: string userListMsg; lock (ClientConnections) { userListMsg = Network.MakeServerMessage(MessageType.UserList, ClientConnections); } SendToAll(userListMsg); break; case MessageType.INVALID: case MessageType.Hello: Logger.MessageBox("Unexpected message type", "Networking"); break; default: Debug.Assert(clientMessages != null); lock (clientMessages) { clientMessages.Enqueue(lineParts); } break; } }
/// <summary> /// Stats the tcplistener and accepts new connections /// </summary> public async void Start() { Logger.Log("Starting listener at " + IPAddress.Loopback + ":" + Network.PORT, "Server side"); Network.AddMessage("Server started"); listener = new TcpListener(IPAddress.Any, Network.PORT); CurrentGameState = GameState.Lobby; try { listener.Start(); Accepting = true; PingThread(); while (!Stopping) { var client = await listener.AcceptTcpClientAsync(); if (client == null) break; if (Stopping) break; var connection = new ClientConnection("newUser" + nextUserId++, client, ReceiveMessage, CloseClient); connection.StartSend(Network.MakeServerMessage(MessageType.Hello, connection)); connection.StartSend(Network.MakeServerMessage(MessageType.SettingsUpdate, MapWidth, MapHeight, UnitCap)); Logger.Log("Client connected " + connection.Name, "Server"); if (!Accepting) { connection.Close("Server is not accepting any new connections right now"); continue; } string userListMsg; lock (ClientConnections) { ClientConnections.Add(connection); userListMsg = Network.MakeServerMessage(MessageType.UserList, ClientConnections); } SendToAll(userListMsg); } } #region exception handling catch (InvalidOperationException ex) { Logger.Log("InvalidOperationException: " + ex.Message, "Server side"); } catch (SocketException ex) { Logger.Log("SocketException: " + ex.Message, "Server side"); } #endregion Accepting = false; Logger.Log("Server no longer listening", "Server side"); Network.AddMessage("Server stopped"); }
/// <summary> /// Closes the client connection /// </summary> /// <param name="client">Client to disconnect</param> /// <param name="reason">Reason of disconnecting</param> public void CloseClient(ClientConnection client, string reason) { lock (ClientConnections) { if (!ClientConnections.Contains(client)) return; ClientConnections.Remove(client); } Logger.Log("Closing client " + client.Name + ", Reason: " + reason, "Server"); client.Close(reason); if (CurrentGameState == GameState.Started && client.IngamePlayerId.HasValue) { if (Game.Players == null) return; Player player = Game.Players.FirstOrDefault(p => p.Id == client.IngamePlayerId); player.ApplyState(Player.PlayerState.Defeated); } }