static void AcceptClients(object arg) { LogEntry($"Accepting clients..."); while (true) { if (clients.Count < MAX_CONNECTED_CLIENTS) { var socket = server.Accept(); Client client = new Client(new Protocol(new UTF8Encoding(), 5000, socket)); LogEntry($"{client.IPAddress} connected"); lock (clients) { clients.Add(client); } new TaskFactory().StartNew(() => { while (true) { if (client.Protocol.Socket.Connected) { if (!client.IsHeard) { client.IsHeard = true; new TaskFactory().StartNew(() => { Message message = Receive(client); client.IsHeard = false; new TaskFactory().StartNew(() => { if (message is Request) { HandleClientRequest(client, (Request)message); } else if (message is Response) { client.LatestResponse = (Response)message; } }); }); } } else { clients.Remove(client); LogEntry($"{client.IPAddress} disconnected"); break; } } }); } } }
static void HandleClientRequest(Client client, Request request) { switch (request.Status) { case RequestStatus.SEND_CHAT_MESSAGE: SendChatMessage(client, request); break; case RequestStatus.MOVE: MovePlayer(client, request); break; case RequestStatus.LOGIN: Login(client, request); break; } }
static void SendChatMessage(Client client, Request request) { if (request.Status == RequestStatus.SEND_CHAT_MESSAGE && request.DataType == DataType.JSON && client.IsLoggedIn) { Respond(client, new Response(ResponseStatus.OK)); Request req = new Request(RequestStatus.SEND_CHAT_MESSAGE, DataType.JSON, request.Data); foreach (Client c in clients.Where(c => c.IsLoggedIn && c != client)) { Request(c, req); } } else { Respond(client, new Response(ResponseStatus.BAD_REQUEST)); } }
static void Respond(Client client, Response response) { client.Protocol.Send(response); LogEntry($"[{serverEndPoint} --> {client.IPAddress}] {client.Protocol.GetMessage(response)}"); }
static Response Request(Client client, Request request) { lock (requestLocker) { LogEntry($"[{serverEndPoint} --> {client.IPAddress}] {client.Protocol.GetMessage(request)}"); client.LatestResponse = null; client.Protocol.Send(request); while (client.LatestResponse == null) { } Response response = client.LatestResponse; return response; } }
static Message Receive(Client client, int msgSizeOverride = 0) { if (msgSizeOverride == 0) { msgSizeOverride = client.Protocol.MsgSize; } Message message = client.Protocol.Receive(); LogEntry($"[{serverEndPoint} <-- {client.IPAddress}] {client.Protocol.GetMessage(message)}"); return message; }
static void MovePlayer(Client client, Request request) { if (request.Status != RequestStatus.MOVE || !gameStarted || request.DataType != DataType.JSON) { Respond(client, new Response(ResponseStatus.BAD_REQUEST)); } else { if (client.IsLoggedIn) { var direction = JsonConvert.DeserializeObject<Direction>(request.Data); Respond(client, new Response(ResponseStatus.OK)); map.MovePlayer(direction, client.Player); } else { Respond(client, new Response(ResponseStatus.UNAUTHORIZED)); } } }
static void Login(Client client, Request request) { lock (client) { if (request.Status != RequestStatus.LOGIN) { Respond(client, new Response(ResponseStatus.BAD_REQUEST)); } else if (client.IsLoggedIn) { Respond(client, new Response(ResponseStatus.BAD_REQUEST, DataType.TEXT, "You are already logged in.")); } else if (clients.Count(c => c.IsLoggedIn) >= MAX_LOGGED_IN_CLIENTS) { Respond(client, new Response(ResponseStatus.LIMIT_REACHED, DataType.TEXT, $"Only {MAX_LOGGED_IN_CLIENTS} users can be logged in at a time.")); } else { string message = request.Data; string username = message.Split(' ')[0]; Account account = db.Account.SingleOrDefault(u => u.Username == username); if (account == null) { Respond(client, new Response(ResponseStatus.NOT_FOUND, DataType.TEXT, "This user does not exist.")); } else if (clients.Any(c => c.IsLoggedIn && c.Account == account)) { Respond(client, new Response(ResponseStatus.UNAUTHORIZED, DataType.TEXT, "This user is already logged in.")); } else { string password = message.Split(' ')[1]; if (password != account.Password) { Respond(client, new Response(ResponseStatus.UNAUTHORIZED, DataType.TEXT, "Incorrect password.")); } else { client.Account = account; Respond(client, new Response(ResponseStatus.OK)); } } } } }