/// <summary> /// Writes a GameClock object to the database /// </summary> /// <returns>bool indicating success</returns> /// <param name="gameID">Game (bucket) to write to</param> /// <param name="gc">GameClock to write</param> public static bool DatabaseWrite_Clock(string gameID, GameClock gc) { var rClock = new RiakObject(gameID, "gameClock", gc); var putClockResult = Globals_Server.rClient.Put(rClock); if (!putClockResult.IsSuccess) { Globals_Server.logError("Write failed: GameClock to bucket " + rClock.Bucket + ": " + putClockResult.ErrorMessage); } return(putClockResult.IsSuccess); }
public static bool DatabaseWrite_Client(string gameID, Client client) { Client_Serialized clientSer = new Client_Serialized(client); var rString = new RiakObject(gameID, client.username, clientSer); var putStringResult = Globals_Server.rClient.Put(rString); if (!putStringResult.IsSuccess) { Globals_Server.logError("Write failed: String variable " + clientSer.user + " to bucket " + rString.Bucket); } return(putStringResult.IsSuccess); }
/// <summary> /// Writes a key list (List object) to the database /// </summary> /// <returns>bool indicating success</returns> /// <param name="gameID">Game (bucket) to write to</param> /// <par am name="k">key of key list</param> /// <param name="kl">key list to write</param> public static bool DatabaseWrite_KeyList <T>(string gameID, string k, List <T> kl) { Console.WriteLine("Writing key list " + k + " to bucket " + gameID); RiakObject rList = new RiakObject(gameID, k); var putListResult = Globals_Server.rClient.Put(rList); if (!putListResult.IsSuccess) { Globals_Server.logError("Write failed: Key list " + rList.Key + " to bucket " + rList.Bucket); } return(putListResult.IsSuccess); }
/// <summary> /// Writes a string variable to the database /// </summary> /// <returns>bool indicating success</returns> /// <param name="gameID">Game (bucket) to write to</param> /// <param name="key">Database key to use</param> /// <param name="pcID">string to write</param> public static bool DatabaseWrite_String(string gameID, string key, string pcID) { pcID = "\"" + pcID + "\""; var rString = new RiakObject(gameID, key, pcID); var putStringResult = Globals_Server.rClient.Put(rString); if (!putStringResult.IsSuccess) { Globals_Server.logError("Write failed: String variable " + key + " to bucket " + rString.Bucket); } return(putStringResult.IsSuccess); }
/// <summary> /// Writes a Province or Province_Serialised object to the database /// </summary> /// <returns>bool indicating success</returns> /// <param name="gameID">Game (bucket) to write to</param> /// <param name="p">Province to write</param> /// <param name="ps">Province_Serialised to write</param> public static bool DatabaseWrite_Province(string gameID, Province p = null, Province_Serialised ps = null) { if (p != null) { // convert Province into Province_Serialised ps = DatabaseWrite.Province_serialise(p); } var rProv = new RiakObject(gameID, ps.id, ps); var putProvResult = Globals_Server.rClient.Put(rProv); if (!putProvResult.IsSuccess) { Globals_Server.logError("Write failed: Province " + rProv.Key + " to bucket " + rProv.Bucket); } return(putProvResult.IsSuccess); }
/// <summary> /// Writes a Kingdom or Kingdom_Serialised object to the database /// </summary> /// <returns>bool indicating success</returns> /// <param name="gameID">Game (bucket) to write to</param> /// <param name="k">Kingdom to write</param> /// <param name="ks">Kingdom_Serialised to write</param> public static bool DatabaseWrite_Kingdom(string gameID, Kingdom k = null, Kingdom_Serialised ks = null) { if (k != null) { // convert Kingdom into Kingdom_Serialised ks = DatabaseWrite.Kingdom_serialise(k); } var rKing = new RiakObject(gameID, ks.id, ks); var putKingResult = Globals_Server.rClient.Put(rKing); if (!putKingResult.IsSuccess) { Globals_Server.logError("Write failed: Kingdom " + rKing.Key + " to bucket " + rKing.Bucket); } return(putKingResult.IsSuccess); }
/// <summary> /// Writes a Position or Position_Serialised object to the database /// </summary> /// <returns>bool indicating success</returns> /// <param name="gameID">Game (bucket) to write to</param> /// <param name="p">Position to write</param> /// <param name="ps">Position_Serialised to write</param> public static bool DatabaseWrite_Position(string gameID, Position p = null, Position_Serialised ps = null) { if (p != null) { // convert Position into Position_Serialised ps = DatabaseWrite.Position_serialise(p); } var rPos = new RiakObject(gameID, ps.id.ToString(), ps); var putPosResult = Globals_Server.rClient.Put(rPos); if (!putPosResult.IsSuccess) { Globals_Server.logError("Write failed: Position " + rPos.Key + " to bucket " + rPos.Bucket); } return(putPosResult.IsSuccess); }
/// <summary> /// Writes a HexMapGraph edges collection to the database /// </summary> /// <returns>bool indicating success</returns> /// <param name="gameID">Game (bucket) to write to</param> /// <param name="map">HexMapGraph containing edges collection to write</param> /// <param name="edges">Edges collection to write</param> public static bool DatabaseWrite_MapEdges(string gameID, HexMapGraph map = null, List <TaggedEdge <string, string> > edges = null) { if (map != null) { // convert Language into Language_Serialised edges = DatabaseWrite.EdgeCollection_serialise(map.myMap.Edges.ToList()); } var rMapE = new RiakObject(gameID, "mapEdges", edges); var putMapResultE = Globals_Server.rClient.Put(rMapE); if (!putMapResultE.IsSuccess) { Globals_Server.logError("Write failed: Map edges collection " + rMapE.Key + " to bucket " + rMapE.Bucket); } return(putMapResultE.IsSuccess); }
/// <summary> /// Writes a Fief or Fief_Serialised object to the database /// </summary> /// <returns>bool indicating success</returns> /// <param name="gameID">Game (bucket) to write to</param> /// <param name="f">Fief to write</param> /// <param name="fs">Fief_Serialised to write</param> public static bool DatabaseWrite_Fief(string gameID, Fief f = null, Fief_Serialised fs = null) { if (f != null) { // convert Fief to Fief_Serialised fs = DatabaseWrite.Fief_serialise(f); } var rFief = new RiakObject(gameID, fs.id, fs); var putFiefResult = Globals_Server.rClient.Put(rFief); if (!putFiefResult.IsSuccess) { Globals_Server.logError("Write failed: Fief " + rFief.Key + " to bucket " + rFief.Bucket); } return(putFiefResult.IsSuccess); }
//public static void SendViaProto(global::ProtoMessage.ProtoMessage m, NetConnection conn, bool isPCL, NetEncryption alg = null) //{ // Contract.Requires(m != null && conn != null); // NetOutgoingMessage msg = server.CreateMessage(); // MemoryStream ms = new MemoryStream(); // Serializer.SerializeWithLengthPrefix<global::ProtoMessage.ProtoMessage>(ms, m, PrefixStyle.Fixed32); // msg.Write(ms.GetBuffer()); // if (alg != null) // { // msg.Encrypt(alg); // } // server.SendMessage(msg, conn, NetDeliveryMethod.ReliableOrdered); // server.FlushSendQueue(); //} /// <summary> /// Read a message, get the relevant reply and send to client /// </summary> /// <param name="m">Deserialised message from client</param> /// <param name="connection">Client's connecton</param> public void ProcessMessage(ProtoMessage m, NetConnection connection) { Contract.Requires(connection != null && m != null); Client client; clientConnections.TryGetValue(connection, out client); if (client == null) { NetOutgoingMessage errorMessage = server.CreateMessage("There was a problem with the connection. Please try re-connecting"); server.SendMessage(errorMessage, connection, NetDeliveryMethod.ReliableOrdered); string log = "Connection from peer " + connection.Peer.UniqueIdentifier + " not found in client connections. Timestamp: " + DateTime.Now.ToString(DateTimeFormatInfo.CurrentInfo); Globals_Server.logError(log); return; } var pc = client.myPlayerCharacter; if (pc == null || !pc.isAlive) { NetOutgoingMessage msg = server.CreateMessage("You have no valid PlayerCharacter!"); server.SendMessage(msg, connection, NetDeliveryMethod.ReliableOrdered); server.FlushSendQueue(); } else { Globals_Server.logEvent("From: " + clientConnections[connection].username + ": request = " + m.ActionType.ToString()); ProtoMessage reply = Game.ActionController(m, client); // Set action type to ensure client knows which action invoked response if (reply == null) { ProtoMessage invalid = new ProtoMessage(DisplayMessages.ErrorGenericMessageInvalid); invalid.ActionType = Actions.Update; reply = invalid; } else { reply.ActionType = m.ActionType; } SendViaProto(reply, connection, client.alg); } }
/// <summary> /// Writes a PlayerCharacter or PlayerCharacter_Serialised object to the database /// </summary> /// <returns>bool indicating success</returns> /// <param name="gameID">Game (bucket) to write to</param> /// <param name="pc">PlayerCharacter to write</param> /// <param name="pcs">PlayerCharacter_Serialised to write</param> public static bool DatabaseWrite_PC(string gameID, PlayerCharacter pc = null, PlayerCharacter_Serialised pcs = null) { if (pc != null) { // convert PlayerCharacter into PlayerCharacter_Serialised pcs = DatabaseWrite.PC_serialise(pc); } // write PlayerCharacter_Serialised to database var rPC = new RiakObject(gameID, pcs.charID, pcs); var putPCresult = Globals_Server.rClient.Put(rPC); if (!putPCresult.IsSuccess) { Globals_Server.logError("Write failed: PC " + rPC.Key + " to bucket " + rPC.Bucket); } return(putPCresult.IsSuccess); }
/// <summary> /// Writes a NonPlayerCharacter or NonPlayerCharacter_Serialised object to the database /// </summary> /// <returns>bool indicating success</returns> /// <param name="gameID">Game (bucket) to write to</param> /// <param name="npc">NonPlayerCharacter to write</param> /// <param name="npcs">NonPlayerCharacter_Serialised to write</param> public static bool DatabaseWrite_NPC(string gameID, NonPlayerCharacter npc = null, NonPlayerCharacter_Serialised npcs = null) { if (npc != null) { // convert NonPlayerCharacter into NonPlayerCharacter_Serialised npcs = DatabaseWrite.NPC_serialise(npc); } // write NonPlayerCharacter_Serialised to database var rNPC = new RiakObject(gameID, npcs.charID, npcs); var putNPCresult = Globals_Server.rClient.Put(rNPC); if (!putNPCresult.IsSuccess) { Globals_Server.logError("Write failed: NPC " + rNPC.Key + " to bucket " + rNPC.Bucket); } return(putNPCresult.IsSuccess); }
/// <summary> /// Writes a Language or Language_Serialised object to the database /// </summary> /// <returns>bool indicating success</returns> /// <param name="gameID">Game (bucket) to write to</param> /// <param name="l">Language to write</param> /// <param name="ls">Language_Serialised to write</param> public static bool DatabaseWrite_Language(string gameID, Language l = null, Language_Serialised ls = null) { if (l != null) { // convert Language into Language_Serialised ls = DatabaseWrite.Language_serialise(l); } // write Language_Serialised to database var rLanguage = new RiakObject(gameID, ls.id, ls); var putLanguageResult = Globals_Server.rClient.Put(rLanguage); if (!putLanguageResult.IsSuccess) { Globals_Server.logError("Write failed: Language " + rLanguage.Key + " to bucket " + rLanguage.Bucket); } return(putLanguageResult.IsSuccess); }
/// <summary> /// Respond to ransom demands /// </summary> /// <param name="paid">Whether or not ransom is to be paid</param> /// <returns>Bool indicating success</returns> public bool RansomResponse(bool paid, out ProtoMessage error) { error = null; // Check if type is ransom if (this.type.Equals("ransom")) { // Check if already replied if (replied) { // Already replied error = new ProtoMessage(); error.ResponseType = DisplayMessages.RansomRepliedAlready; return(false); } Character captive = null; PlayerCharacter captor; PlayerCharacter captiveHeadOfHousehold; // Confirm captive is still alive and being held foreach (string persona in personae) { string[] split = persona.Split(new char[] { '|' }); if (split[1].Equals("Captive")) { captive = Globals_Game.getCharFromID(split[0]); } } if (captive == null) { // Captive does not exist- error error = new ProtoMessage(); error.ResponseType = DisplayMessages.ErrorGenericCharacterUnidentified; Globals_Server.logError("Captive unidentified in JEntry: " + this.jEntryID); return(false); } else if (!captive.isAlive) { // Captive is dead error = new ProtoMessage(); error.ResponseType = DisplayMessages.RansomCaptiveDead; return(false); } captor = Globals_Game.getCharFromID(captive.captorID) as PlayerCharacter; if (captor == null) { // Captive does not have a captor error = new ProtoMessage(); error.ResponseType = DisplayMessages.NotCaptive; return(false); } captiveHeadOfHousehold = captive.GetPlayerCharacter(); if (captiveHeadOfHousehold == null) { // Captive is not an employee, family member or player character Globals_Server.logError("Captive has no PlayerCharacter: " + captive.charID); error = new ProtoMessage(); error.ResponseType = DisplayMessages.ErrorGenericCharacterUnidentified; return(false); } if (paid) { // Get ransom amount uint ransom = 0; if (!UInt32.TryParse(entryDetails.MessageFields[1], out ransom)) { // Error parsing to int Globals_Server.logError("Could not parse ransom to uint in JEntry: " + jEntryID); error = new ProtoMessage(); error.ResponseType = DisplayMessages.ErrorGenericMessageInvalid; return(false); } else { // Check captive's head of household has the funds to release if (captiveHeadOfHousehold.GetHomeFief().GetAvailableTreasury(false) >= ransom) { if (!captiveHeadOfHousehold.GetHomeFief().TreasuryTransfer(captor.GetHomeFief(), (Int32)ransom, out error)) { return(false); } else { // Release captive captor.ReleaseCaptive(captive); replied = true; Globals_Game.UpdatePlayer(captor.playerID, DisplayMessages.RansomPaid, new string[] { captive.firstName + " " + captive.familyName }); return(true); } } else { // Insufficient funds error = new ProtoMessage(); error.ResponseType = DisplayMessages.ErrorGenericInsufficientFunds; return(false); } } } // If not paying ransom, inform captor else { // Create journal entry and update captor string[] newPersonae = new string[] { captive.charID + "|Captive", captor.charID + "|Captor", captiveHeadOfHousehold.charID + "|HeadOfCaptiveFamily" }; ProtoMessage deniedMessage = new ProtoMessage(); deniedMessage.ResponseType = DisplayMessages.RansonDenied; deniedMessage.MessageFields = new string[] { captive.firstName + " " + captive.familyName, captor.firstName + " " + captor.familyName, captiveHeadOfHousehold.firstName + " " + captiveHeadOfHousehold.familyName }; Globals_Game.UpdatePlayer(captor.playerID, deniedMessage); JournalEntry ransomDenied = new JournalEntry(Globals_Game.GetNextJournalEntryID(), Globals_Game.clock.currentYear, Globals_Game.clock.currentSeason, newPersonae, "ransomDenied", deniedMessage); Globals_Game.AddPastEvent(ransomDenied); replied = true; return(true); } } else { // Not a ransom error = new ProtoMessage(); error.ResponseType = DisplayMessages.EntryNotRansom; return(false); } }
public void read() { while (client.Status == NetPeerStatus.Running && !ctSource.Token.IsCancellationRequested) { WaitHandle.WaitAny(new WaitHandle[] { client.MessageReceivedEvent, ctSource.Token.WaitHandle }); NetIncomingMessage im; while ((im = client.ReadMessage()) != null && !ctSource.IsCancellationRequested) { switch (im.MessageType) { case NetIncomingMessageType.DebugMessage: case NetIncomingMessageType.ErrorMessage: case NetIncomingMessageType.WarningMessage: case NetIncomingMessageType.VerboseDebugMessage: case NetIncomingMessageType.Data: try { if (alg != null) { im.Decrypt(alg); } MemoryStream ms = new MemoryStream(im.Data); ProtoMessage m = null; try { m = Serializer.DeserializeWithLengthPrefix <ProtoMessage>(ms, PrefixStyle.Fixed32); } catch (Exception e) { // Attempt to read string and add to message queue string s = im.ReadString(); if (!string.IsNullOrWhiteSpace(s)) { Console.WriteLine("CLIENT: Got message: " + s); tClient.stringMessageQueue.Enqueue(s); } } if (m != null) { Console.WriteLine("CLIENT: Got ProtoMessage with ActionType: " + m.ActionType + " and response type: " + m.ResponseType); if (m.ResponseType == DisplayMessages.LogInSuccess) { loggedIn = true; tClient.protobufMessageQueue.Enqueue(m); } else { if (m.ActionType == Actions.Update) { // Don't do anything at the moment for updates } else { tClient.protobufMessageQueue.Enqueue(m); if (m.ActionType == Actions.LogIn && m.ResponseType == DisplayMessages.None) { byte[] key = null; if (ValidateCertificateAndCreateKey(m as ProtoLogIn, out key)) { ComputeAndSendHashAndKey(m as ProtoLogIn, key); } } else { // Attempt to read string and add to message queue string s = im.ReadString(); if (!string.IsNullOrWhiteSpace(s)) { tClient.stringMessageQueue.Enqueue(s); } } } } } } catch (Exception e) { Globals_Server.logError("Error in reading data: " + e.GetType() + " :" + e.Message + "; Stack Trace: " + e.StackTrace); } break; case NetIncomingMessageType.StatusChanged: NetConnectionStatus status = (NetConnectionStatus)im.ReadByte(); Console.WriteLine("CLIENT: Status changed to " + status.ToString()); //MemoryStream ms2 = new MemoryStream(im.SenderConnection.RemoteHailMessage.Data); if (status == NetConnectionStatus.Connected) { if (im.SenderConnection.RemoteHailMessage != null) { try { MemoryStream ms2 = new MemoryStream(im.SenderConnection.RemoteHailMessage.Data); ProtoMessage m = Serializer.DeserializeWithLengthPrefix <ProtoMessage>(ms2, PrefixStyle.Fixed32); if (m != null) { tClient.protobufMessageQueue.Enqueue(m); if (m.ActionType == Actions.LogIn && m.ResponseType == DisplayMessages.None) { byte[] key = null; if (ValidateCertificateAndCreateKey(m as ProtoLogIn, out key)) { if (autoLogIn) { ComputeAndSendHashAndKey(m as ProtoLogIn, key); } } else { Console.WriteLine("Certificate validation failed: Server may be untrusted"); client.Disconnect("Invalid Certificate"); } } } } catch (Exception e) { } } break; } else if (status == NetConnectionStatus.Disconnected) { string reason = im.ReadString(); if (!string.IsNullOrEmpty(reason)) { tClient.stringMessageQueue.Enqueue(reason); } } if (im.SenderConnection.RemoteHailMessage != null && (NetConnectionStatus)im.ReadByte() == NetConnectionStatus.Connected) { } break; case NetIncomingMessageType.ConnectionLatencyUpdated: break; default: break; } client.Recycle(im); } } #if DEBUG Globals_Server.logEvent("Client listening thread ends"); #endif }
public void Listen() { while (server.Status == NetPeerStatus.Running && !ctSource.Token.IsCancellationRequested) { NetIncomingMessage im; WaitHandle.WaitAny(new WaitHandle[] { server.MessageReceivedEvent, ctSource.Token.WaitHandle }); while ((im = server.ReadMessage()) != null && !ctSource.Token.IsCancellationRequested) { if (im.SenderConnection != null) { Globals_Server.logEvent("Recieved: " + im.MessageType.ToString() + " | " + im.SenderConnection.RemoteEndPoint.ToString()); } else { Globals_Server.logEvent("Recieved: " + im.MessageType.ToString() + " | NULL"); } switch (im.MessageType) { case NetIncomingMessageType.DebugMessage: case NetIncomingMessageType.ErrorMessage: case NetIncomingMessageType.WarningMessage: Globals_Server.logError("Recieved warning message: " + im.ReadString()); break; case NetIncomingMessageType.VerboseDebugMessage: case NetIncomingMessageType.Data: { #if DEBUG //Console.WriteLine("SERVER: recieved data message"); #endif if (!clientConnections.ContainsKey(im.SenderConnection)) { //error im.SenderConnection.Disconnect("Not recognised"); return; } Client c = clientConnections[im.SenderConnection]; if (c.alg != null) { im.Decrypt(c.alg); } ProtoMessage m = null; using (MemoryStream ms = new MemoryStream(im.Data)) { try { m = Serializer.DeserializeWithLengthPrefix <ProtoMessage>(ms, PrefixStyle.Fixed32); } catch (Exception e) { NetOutgoingMessage errorMessage = server.CreateMessage( "Failed to deserialise message. The message may be incorrect, or the decryption may have failed."); if (c.alg != null) { errorMessage.Encrypt(c.alg); } server.SendMessage(errorMessage, im.SenderConnection, NetDeliveryMethod.ReliableOrdered); Globals_Server.logError("Failed to deserialize message for client: " + c.username); } } if (m == null) { string error = "Recieved null message from " + im.SenderEndPoint.ToString(); if (clientConnections.ContainsKey(im.SenderConnection)) { error += ", recognised client " + clientConnections[im.SenderConnection]; } else { error += ", unrecognised client (possible ping)"; } error += ". Data: " + im.ReadString(); Globals_Server.logError(error); break; } if (m.ActionType == Actions.LogIn) { ProtoLogIn login = m as ProtoLogIn; if (login == null) { im.SenderConnection.Disconnect("Received blank login message."); return; } lock (ServerLock) { if (LogInManager.VerifyUser(c.username, login.userSalt)) { if (LogInManager.ProcessLogIn(login, c)) { string log = c.username + " logs in from " + im.SenderEndPoint.ToString(); Globals_Server.logEvent(log); } } else { ProtoMessage reply = new ProtoMessage { ActionType = Actions.LogIn, ResponseType = DisplayMessages.LogInFail }; Server.SendViaProto(reply, c.conn, c.alg); //reply = new ProtoMessage { // ActionType = Actions.Update, // ResponseType = DisplayMessages.Error //}; //Server.SendViaProto(reply, c.conn, c.alg); im.SenderConnection.Disconnect("Authentication Fail"); Globals_Server.logEvent("Wrong Password, disconnecting user."); } } } // temp for testing, should validate connection first else if (clientConnections.ContainsKey(im.SenderConnection)) { if (Globals_Game.IsObserver(c)) { ProcessMessage(m, im.SenderConnection); ProtoClient clientDetails = new ProtoClient(c); clientDetails.ActionType = Actions.Update; clientDetails.ResponseType = DisplayMessages.Success; SendViaProto(clientDetails, im.SenderConnection, c.alg); } else { im.SenderConnection.Disconnect("Not logged in- Disconnecting"); } } } break; case NetIncomingMessageType.StatusChanged: byte stat = im.ReadByte(); NetConnectionStatus status = NetConnectionStatus.None; if (Enum.IsDefined(typeof(NetConnectionStatus), Convert.ToInt32(stat))) { status = (NetConnectionStatus)stat; } else { Globals_Server.logError("Failure to parse byte " + stat + " to NetConnectionStatus for endpoint " + im.ReadIPEndPoint()); } Globals_Server.logEvent("\tStatus is now: " + status); if (status == NetConnectionStatus.Disconnected) { string reason = im.ReadString(); if (reason == null) { reason = "Unknown"; } Globals_Server.logEvent(im.SenderConnection.RemoteEndPoint.ToString() + " has disconnected. Reason: " + reason); if (clientConnections.ContainsKey(im.SenderConnection)) { Disconnect(im.SenderConnection); } } break; case NetIncomingMessageType.ConnectionApproval: { string senderID = im.ReadString(); string text = im.ReadString(); Client client; Globals_Server.Clients.TryGetValue(senderID, out client); if (client != null) { ProtoLogIn logIn; //ProtoMessage logIn; if (!LogInManager.AcceptConnection(client, text, out logIn)) { im.SenderConnection.Deny("User not recognised."); } else { ProtoMessage temp = logIn; NetOutgoingMessage msg = server.CreateMessage(); MemoryStream ms = new MemoryStream(); // Include X509 certificate as bytes for client to validate //Serializer.SerializeWithLengthPrefix<ProtoLogIn>(ms, logIn, PrefixStyle.Fixed32); Serializer.SerializeWithLengthPrefix <ProtoMessage>(ms, temp, PrefixStyle.Fixed32); msg.Write(ms.GetBuffer()); clientConnections.Add(im.SenderConnection, client); client.conn = im.SenderConnection; im.SenderConnection.Approve(msg); //server.FlushSendQueue(); Globals_Server.logEvent("Accepted connection from " + client.username + " | " + senderID + " | " + text); } } else { im.SenderConnection.Deny("Username unrecognised."); } server.FlushSendQueue(); } break; case NetIncomingMessageType.ConnectionLatencyUpdated: Globals_Server.logEvent("LATENCY: Still getting these."); break; default: Globals_Server.logError("Received unrecognised incoming message type: " + im.MessageType); break; } server.Recycle(im); } } Globals_Server.logEvent("Server listening thread exits."); }