/// <summary> /// Handles the those commands send by the client through a TCP socket. /// </summary> protected void HandleCommandsThreadMethod() { Message messageToProcess = null; ManagedMessage managedMessageReference = null; if (!this.ableToRun) { KSPMGlobals.Globals.Log.WriteTo(Error.ErrorType.ServerUnableToRun.ToString()); } try { KSPMGlobals.Globals.Log.WriteTo("-Starting to handle commands[ " + this.alive + " ]"); while (this.alive) { this.commandsQueue.DequeueCommandMessage(out messageToProcess); if (messageToProcess != null) { managedMessageReference = (ManagedMessage)messageToProcess; switch (messageToProcess.Command) { case Message.CommandType.Chat: this.clientsHandler.TCPBroadcastTo(this.chatManager.GetChatGroupById(ChatMessage.InflateTargetGroupId(messageToProcess.bodyMessage)).MembersAsList, messageToProcess); /* * if (ChatMessage.InflateChatMessage(messageToProcess.bodyMessage, out chatMessage) == Error.ErrorType.Ok) * { * //KSPMGlobals.Globals.Log.WriteTo(string.Format("[{0}][{1}_{2}]-Says:{3}", managedMessageReference.OwnerNetworkEntity.Id, chatMessage.Time.ToShortTimeString(), chatMessage.sendersUsername, chatMessage.Body)); * this.clientsHandler.TCPBroadcastTo(this.chatManager.AttachMessage(chatMessage).MembersAsList, messageToProcess); * } */ break; case Message.CommandType.KeepAlive: KSPMGlobals.Globals.Log.WriteTo("KeepAlive command: " + messageToProcess.Command.ToString()); break; case Message.CommandType.Unknown: default: KSPMGlobals.Globals.Log.WriteTo("Unknown command: " + messageToProcess.Command.ToString()); break; } ///Releasing and recycling the message. this.incomingMessagesPool.Recycle(messageToProcess); } else { ///Yielding the process. Thread.Sleep(0); } } } catch (ThreadAbortException) { this.alive = false; } }
/// <summary> /// Handles the TCP socket and the main Queue of messages, uses the a TCP socket to send messages. /// </summary> protected void HandleOutgoingPriorityMessagesThreadMethod() { Message outgoingMessage = null; ManagedMessage managedReference = null; if (!this.ableToRun) { KSPMGlobals.Globals.Log.WriteTo(Error.ErrorType.ServerUnableToRun.ToString()); } try { KSPMGlobals.Globals.Log.WriteTo("-Starting to handle outgoing messages[ " + this.alive + " ]"); while (this.alive) { this.priorityOutgoingMessagesQueue.DequeueCommandMessage(out outgoingMessage); if (outgoingMessage != null) { //KSPMGlobals.Globals.Log.WriteTo(string.Format("[{0}]===Error==={1}.", outgoingMessage.bodyMessage[ 4 ], outgoingMessage.Command)); managedReference = (ManagedMessage)outgoingMessage; try { ///Checking if the NetworkEntity is still running. if (managedReference.OwnerNetworkEntity.IsAlive()) { KSPMGlobals.Globals.Log.WriteTo(outgoingMessage.Command.ToString()); managedReference.OwnerNetworkEntity.ownerNetworkCollection.socketReference.BeginSend(outgoingMessage.bodyMessage, 0, (int)outgoingMessage.MessageBytesSize, SocketFlags.None, new AsyncCallback(this.AsyncSenderCallback), managedReference.OwnerNetworkEntity); } } catch (System.Exception ex) { KSPMGlobals.Globals.Log.WriteTo(string.Format("[{0}][\"{1}-{2}\"] Something went wrong with the remote client, performing a removing process on it.", managedReference.OwnerNetworkEntity.Id, "HandleOutgoingPriorityMessages", ex.Message)); this.DisconnectClient(managedReference.OwnerNetworkEntity); } ///Releasing the processed command. outgoingMessage.Release(); outgoingMessage = null; } Thread.Sleep(1); } } catch (ThreadAbortException) { this.alive = false; } }
/// <summary> /// Handles the commands passed by the UI or the console if is it one implemented. /// </summary> protected void HandleLocalCommandsThreadMethod() { Message messageToProcess = null; Message responseMessage = null; ManagedMessage managedMessageReference = null; ServerSideClient newClientAttempt = null; ServerSideClient serverSideClientReference = null; GameUser referredUser = null; if (!this.ableToRun) { KSPMGlobals.Globals.Log.WriteTo(Error.ErrorType.ServerUnableToRun.ToString()); } try { KSPMGlobals.Globals.Log.WriteTo("-Starting to handle local commands[ " + this.alive + " ]"); while (this.alive) { this.localCommandsQueue.DequeueCommandMessage(out messageToProcess); if (messageToProcess != null) { //KSPMGlobals.Globals.Log.WriteTo(messageToProcess.Command.ToString()); managedMessageReference = (ManagedMessage)messageToProcess; switch (messageToProcess.Command) { case Message.CommandType.NewClient: if (this.clientsHandler.ConnectedClients < this.lowLevelOperationSettings.maxConnectedClients) { if (this.defaultUserManagementSystem.Query(managedMessageReference.OwnerNetworkEntity)) { if (ServerSideClient.CreateFromNetworkEntity(managedMessageReference.OwnerNetworkEntity, out newClientAttempt) == Error.ErrorType.Ok) { newClientAttempt.RegisterUserConnectedEvent(this.UserConnected); if (newClientAttempt.StartClient()) { this.clientsHandler.AddNewClient(newClientAttempt); } } } } else { //Creates the reject message and set the callback to the RejectMessageToClient. Performed in that way because it is needed to send the reject message before to proceed to disconnect the client. Message.ServerFullMessage(managedMessageReference.OwnerNetworkEntity, out responseMessage); PacketHandler.EncodeRawPacket(ref responseMessage.bodyMessage); ((ManagedMessage)responseMessage).OwnerNetworkEntity.SetMessageSentCallback(this.RejectMessageToClient); this.priorityOutgoingMessagesQueue.EnqueueCommandMessage(ref responseMessage); } break; case Message.CommandType.StopServer: this.ShutdownServer(); break; case Message.CommandType.Authentication: User.InflateUserFromBytes(messageToProcess.bodyMessage, ((BufferedMessage)messageToProcess).StartsAt, messageToProcess.MessageBytesSize, out referredUser); serverSideClientReference = (ServerSideClient)managedMessageReference.OwnerNetworkEntity; serverSideClientReference.gameUser = referredUser; if (this.usersAccountManager.Query(managedMessageReference.OwnerNetworkEntity)) { /* * Message.AuthenticationSuccessMessage(messageOwner, out responseMessage); * this.outgoingMessagesQueue.EnqueueCommandMessage(ref responseMessage); */ serverSideClientReference.RemoveAwaitingState(ServerSideClient.ClientStatus.Authenticated); } else { ///Need to improve this code for a only one if. ///And to check if is it needed to send a disconnect message before release the socket. if ((serverSideClientReference.gameUser.AuthencticationAttempts++) < this.lowLevelOperationSettings.maxAuthenticationAttempts) { ///There is still a chance to authenticate again. Message.AuthenticationFailMessage(managedMessageReference.OwnerNetworkEntity, out responseMessage); PacketHandler.EncodeRawPacket(ref responseMessage.bodyMessage); } else { ///There is no chance to try it again. ((ManagedMessage)responseMessage).OwnerNetworkEntity.SetMessageSentCallback(this.RejectMessageToClient); } this.priorityOutgoingMessagesQueue.EnqueueCommandMessage(ref responseMessage); } break; case Message.CommandType.Disconnect: ///Disconnects either a NetworkEntity or a ServerSideClient. this.DisconnectClient(managedMessageReference.OwnerNetworkEntity); break; case Message.CommandType.Unknown: default: KSPMGlobals.Globals.Log.WriteTo("Unknown command: " + messageToProcess.Command.ToString()); break; } ///Recyles and releases the message. this.priorityMessagesPool.Recycle(messageToProcess); } Thread.Sleep(1); } } catch (ThreadAbortException) { this.alive = false; } }
/// <summary> /// Handles the TCP socket and the main Queue of messages, uses the a TCP socket to send messages. /// </summary> protected void HandleOutgoingMessagesThreadMethod() { Message outgoingMessage = null; ManagedMessage managedReference = null; BroadcastMessage broadcastReference = null; SocketAsyncEventArgs sendingData = null; int entityCounter = 0; int blockSize; if (!this.ableToRun) { KSPMGlobals.Globals.Log.WriteTo(Error.ErrorType.ServerUnableToRun.ToString()); } try { KSPMGlobals.Globals.Log.WriteTo("-Starting to handle outgoing messages[ " + this.alive + " ]"); while (this.alive) { #if PROFILING this.profilerOutgoingMessages.Set(); #endif this.outgoingMessagesQueue.DequeueCommandMessage(out outgoingMessage); if (outgoingMessage != null) { //KSPMGlobals.Globals.Log.WriteTo(string.Format("[{0}]===Error==={1}.", outgoingMessage.bodyMessage[ 4 ], outgoingMessage.Command)); try { ///If it is broadcaste message a different sending procces is performed. if (outgoingMessage.IsBroadcast) { broadcastReference = (BroadcastMessage)outgoingMessage; for (entityCounter = 0; entityCounter < broadcastReference.Targets.Length; entityCounter++) { if (broadcastReference.Targets[entityCounter] != null && broadcastReference.Targets[entityCounter].IsAlive()) { blockSize = System.BitConverter.ToInt32(outgoingMessage.bodyMessage, 4); if (blockSize == outgoingMessage.MessageBytesSize) { sendingData = ((ServerSideClient)broadcastReference.Targets[entityCounter]).TCPOutSocketAsyncEventArgsPool.NextSlot; sendingData.AcceptSocket = broadcastReference.Targets[entityCounter].ownerNetworkCollection.socketReference; sendingData.UserToken = broadcastReference.Targets[entityCounter]; sendingData.SetBuffer(outgoingMessage.bodyMessage, 0, (int)outgoingMessage.MessageBytesSize); if (!broadcastReference.Targets[entityCounter].ownerNetworkCollection.socketReference.SendAsync(sendingData)) { this.OnSendingOutgoingDataComplete(this, sendingData); } } else { KSPMGlobals.Globals.Log.WriteTo("PACKET CRC ERROR, Avoiding it."); } } } } else { managedReference = (ManagedMessage)outgoingMessage; blockSize = System.BitConverter.ToInt32(outgoingMessage.bodyMessage, 4); if (blockSize == outgoingMessage.MessageBytesSize) { ///Checking if the NetworkEntity is still running and it has not been released. if (managedReference.OwnerNetworkEntity != null && managedReference.OwnerNetworkEntity.IsAlive()) { sendingData = ((ServerSideClient)managedReference.OwnerNetworkEntity).TCPOutSocketAsyncEventArgsPool.NextSlot; sendingData.AcceptSocket = managedReference.OwnerNetworkEntity.ownerNetworkCollection.socketReference; sendingData.UserToken = managedReference.OwnerNetworkEntity; sendingData.SetBuffer(outgoingMessage.bodyMessage, 0, (int)outgoingMessage.MessageBytesSize); if (!managedReference.OwnerNetworkEntity.ownerNetworkCollection.socketReference.SendAsync(sendingData)) { this.OnSendingOutgoingDataComplete(this, sendingData); } } } else { KSPMGlobals.Globals.Log.WriteTo("PACKET CRC ERROR, Avoiding it."); } } } catch (System.Exception ex) { KSPMGlobals.Globals.Log.WriteTo(string.Format("[{0}][\"{1}-{2}\"] Something went wrong with the remote client, performing a removing process on it.", (outgoingMessage.IsBroadcast ? ((BroadcastMessage)outgoingMessage).Targets[entityCounter].Id : ((ManagedMessage)outgoingMessage).OwnerNetworkEntity.Id), "HandleOutgoingMessages", ex.Message)); this.DisconnectClient((outgoingMessage.IsBroadcast ? ((BroadcastMessage)outgoingMessage).Targets[entityCounter] : ((ManagedMessage)outgoingMessage).OwnerNetworkEntity)); } finally { ///Cleaning up. outgoingMessage.Release(); outgoingMessage = null; } } else { ///Yielding the process. Thread.Sleep(0); } #if PROFILING this.profilerOutgoingMessages.Mark(); #endif } } catch (ThreadAbortException) { this.alive = false; } }
/// <summary> /// Creates a GeneralChat message, it means a chat to be broadcasted to every member on the group. /// </summary> /// <param name="sender">Network entity who is sending the message.</param> /// <param name="targetGroup">ChatGroup to whom is sent the message.</param> /// <param name="bodyMessage">String containing the message.</param> /// <param name="targetMessage">Out reference to the message to be sent.</param> /// <returns></returns> public static Error.ErrorType CreateChatMessage(NetworkEntity sender, ChatGroup targetGroup, string bodyMessage, out Message targetMessage) { int bytesToSend = Message.HeaderOfMessageCommand.Length; byte[] rawBuffer = new byte[Server.ServerSettings.ServerBufferSize]; GameClient senderClient; short shortBuffer; targetMessage = null; byte[] messageHeaderContent = null; byte[] bytesBuffer = null; if (sender == null) { return(Error.ErrorType.InvalidNetworkEntity); } if (targetGroup == null) { return(Error.ErrorType.ChatInvalidGroup); } senderClient = (GameClient)sender; ///Writing header System.Buffer.BlockCopy(Message.HeaderOfMessageCommand, 0, rawBuffer, 0, Message.HeaderOfMessageCommand.Length); bytesToSend += 4; ///Writing the command. rawBuffer[bytesToSend] = (byte)Message.CommandType.Chat; bytesToSend += 1; ///Writing the hash's length shortBuffer = (short)senderClient.ClientOwner.Hash.Length; bytesBuffer = null; bytesBuffer = System.BitConverter.GetBytes(shortBuffer); System.Buffer.BlockCopy(bytesBuffer, 0, rawBuffer, bytesToSend, bytesBuffer.Length); bytesToSend += bytesBuffer.Length; ///Writing the user's hash code. System.Buffer.BlockCopy(senderClient.ClientOwner.Hash, 0, rawBuffer, bytesToSend, shortBuffer); bytesToSend += shortBuffer; ///Writing the user name length bytesToSend + 2 to make room to the name's length. KSPMGlobals.Globals.StringEncoder.GetBytes(((GameClient)sender).ClientOwner.Username, out bytesBuffer); shortBuffer = (short)bytesBuffer.Length; System.Buffer.BlockCopy(bytesBuffer, 0, rawBuffer, bytesToSend + 2, bytesBuffer.Length); bytesBuffer = System.BitConverter.GetBytes(shortBuffer); System.Buffer.BlockCopy(bytesBuffer, 0, rawBuffer, bytesToSend, bytesBuffer.Length); bytesToSend += bytesBuffer.Length + shortBuffer; ///Writing the groupId. bytesBuffer = System.BitConverter.GetBytes(targetGroup.Id); System.Buffer.BlockCopy(bytesBuffer, 0, rawBuffer, bytesToSend, bytesBuffer.Length); bytesToSend += bytesBuffer.Length; ///Writing the body message. KSPMGlobals.Globals.StringEncoder.GetBytes(bodyMessage, out bytesBuffer); shortBuffer = (short)bytesBuffer.Length; ///bytesToSend + 2 because we have to left room for the size of the messagebody. System.Buffer.BlockCopy(bytesBuffer, 0, rawBuffer, bytesToSend + 2, shortBuffer); ///Writing the body message's size bytesBuffer = System.BitConverter.GetBytes(shortBuffer); System.Buffer.BlockCopy(bytesBuffer, 0, rawBuffer, bytesToSend, bytesBuffer.Length); bytesToSend += shortBuffer + bytesBuffer.Length; ///Writing the EndOfMessage command. System.Buffer.BlockCopy(Message.EndOfMessageCommand, 0, rawBuffer, bytesToSend, Message.EndOfMessageCommand.Length); bytesToSend += Message.EndOfMessageCommand.Length; //Writing the message length. messageHeaderContent = System.BitConverter.GetBytes(bytesToSend); System.Buffer.BlockCopy(messageHeaderContent, 0, rawBuffer, Message.HeaderOfMessageCommand.Length, messageHeaderContent.Length); targetMessage = new ManagedMessage((Message.CommandType)rawBuffer[Message.HeaderOfMessageCommand.Length + 4], sender); targetMessage.SetBodyMessage(rawBuffer, (uint)bytesToSend); return(Error.ErrorType.Ok); }