private void SendMessageHeaderDirect(TcpClient client, KLFCommon.ServerMessageID id, int msgLength) { client.GetStream().Write(KLFCommon.IntToBytes((int)id), 0, 4); client.GetStream().Write(KLFCommon.IntToBytes(msgLength), 0, 4); DebugConsoleWriteLine("Sending message: " + id.ToString()); }
public void HandleMessage(int clientIndex, KLFCommon.ClientMessageID id, byte[] data) { if (!ValidClient(clientIndex)) return; DebugConsoleWriteLine("Message id: " + id.ToString() + " data: " + (data != null ? data.Length.ToString() : "0")); UnicodeEncoding encoder = new UnicodeEncoding(); switch (id) { case KLFCommon.ClientMessageID.Handshake: if (data != null) { StringBuilder sb = new StringBuilder(); //Read username Int32 usernameLength = KLFCommon.BytesToInt(data, 0); String username = encoder.GetString(data, 4, usernameLength); int offset = 4 + usernameLength; String version = encoder.GetString(data, offset, data.Length - offset); String usernameLower = username.ToLower(); bool accepted = true; //Ensure no other players have the same username for (int i = 0; i < Clients.Length; i++) { if (i != clientIndex && ClientIsReady(i) && Clients[i].Username.ToLower() == usernameLower) { //Disconnect the player DisconnectClient(clientIndex, "Your username is already in use."); StampedConsoleWriteLine("Rejected client due to duplicate username: "******"There is currently 1 other user on this server: "); for (int i = 0; i < Clients.Length; i++) { if (i != clientIndex && ClientIsReady(i)) { sb.Append(Clients[i].Username); break; } } } else { sb.Append("There are currently "); sb.Append(NumClients - 1); sb.Append(" other users on this server."); if (NumClients > 1) sb.Append(" Enter /list to see them."); } Clients[clientIndex].Username = username; Clients[clientIndex].ReceivedHandshake = true; SendServerMessage(clientIndex, sb.ToString()); SendServerSettings(clientIndex); StampedConsoleWriteLine(username + " ("+GetClientIP(clientIndex).ToString()+") has joined the server using client version " + version); if (!Clients[clientIndex].MessagesThrottled) {//Build join message sb.Clear(); sb.Append("User "); sb.Append(username); sb.Append(" has joined the server."); //Send the join message to all other Clients SendServerMessageToAll(sb.ToString(), clientIndex); } MessageFloodIncrement(clientIndex); } break; case KLFCommon.ClientMessageID.PrimaryPluginUpdate: case KLFCommon.ClientMessageID.SecondaryPluginUpdate: if (data != null && ClientIsReady(clientIndex)) { #if SEND_UPDATES_TO_SENDER SendPluginUpdateToAll(data, id == KLFCommon.ClientMessageID.SecondaryPluginUpdate); #else SendPluginUpdateToAll(data, id == KLFCommon.ClientMessageID.SecondaryPluginUpdate, clientIndex); #endif } break; case KLFCommon.ClientMessageID.TextMessage: if (data != null && ClientIsReady(clientIndex)) HandleClientTextMessage(clientIndex, encoder.GetString(data, 0, data.Length)); break; case KLFCommon.ClientMessageID.ScreenWatchPlayer: if(!ClientIsReady(clientIndex) || data == null || data.Length < 9) break; bool sendScreenshot = data[0] != 0; int watchIndex = KLFCommon.BytesToInt(data, 1); int currentIndex = KLFCommon.BytesToInt(data, 5); String watchName = encoder.GetString(data, 9, data.Length - 9); bool watchNameChanged = false; lock (Clients[clientIndex].WatchPlayerNameLock) { if(watchName != Clients[clientIndex].WatchPlayerName || watchIndex != Clients[clientIndex].WatchPlayerIndex) {//Set the watch player name Clients[clientIndex].WatchPlayerIndex = watchIndex; Clients[clientIndex].WatchPlayerName = watchName; watchNameChanged = true; } } if (sendScreenshot && watchNameChanged && watchName.Length > 0) {//Try to find the player the client is watching and send that player's current screenshot int watchedIndex = GetClientIndexByName(watchName); if (ClientIsReady(watchedIndex)) { Screenshot screenshot = null; lock (Clients[watchedIndex].ScreenshotLock) { screenshot = Clients[watchedIndex].GetScreenshot(watchIndex); if (screenshot == null && watchIndex == -1) screenshot = Clients[watchedIndex].LastScreenshot; } if(screenshot != null && screenshot.Index != currentIndex) SendScreenshot(clientIndex, screenshot); } } break; case KLFCommon.ClientMessageID.ScreenshotShare: if (data != null && data.Length <= Configuration.ScreenshotSettings.MaxNumBytes && ClientIsReady(clientIndex)) { if (!Clients[clientIndex].ScreenshotsThrottled) { StringBuilder sb = new StringBuilder(); Screenshot screenshot = new Screenshot(); screenshot.SetFromByteArray(data); //Set the screenshot for the player lock (Clients[clientIndex].ScreenshotLock) { Clients[clientIndex].PushScreenshot(screenshot); } sb.Append(Clients[clientIndex].Username); sb.Append(" has shared a screenshot."); SendTextMessageToAll(sb.ToString()); StampedConsoleWriteLine(sb.ToString()); //Send the screenshot to every client watching the player SendScreenshotToWatchers(clientIndex, screenshot); if (Configuration.SaveScreenshots) saveScreenshot(screenshot, Clients[clientIndex].Username); } bool throttled = Clients[clientIndex].ScreenshotsThrottled; Clients[clientIndex].ScreenshotFloodIncrement(); if (!throttled && Clients[clientIndex].ScreenshotsThrottled) { long throttleSeconds = Configuration.ScreenshotFloodThrottleTime / 1000; SendServerMessage(clientIndex, "You have been restricted from sharing screenshots for " + throttleSeconds + " seconds."); StampedConsoleWriteLine(Clients[clientIndex].Username + " has been restricted from sharing screenshots for " + throttleSeconds + " seconds."); } else if (Clients[clientIndex].CurrentThrottle.MessageFloodCounter == Configuration.ScreenshotFloodLimit - 1) SendServerMessage(clientIndex, "Warning: You are sharing too many screenshots."); } break; case KLFCommon.ClientMessageID.ConnectionEnd: String message = String.Empty; if (data != null) message = encoder.GetString(data, 0, data.Length); //Decode the message DisconnectClient(clientIndex, message); //Disconnect the client break; case KLFCommon.ClientMessageID.ShareCraftFile: if(ClientIsReady(clientIndex) && data != null && data.Length > 5 && (data.Length - 5) <= KLFCommon.MaxCraftFileBytes) { if (Clients[clientIndex].MessagesThrottled) { MessageFloodIncrement(clientIndex); break; } MessageFloodIncrement(clientIndex); //Read craft name length byte craftType = data[0]; int craftNameLength = KLFCommon.BytesToInt(data, 1); if (craftNameLength < data.Length - 5) { //Read craft name String craftName = encoder.GetString(data, 5, craftNameLength); //Read craft bytes byte[] craftBytes = new byte[data.Length - craftNameLength - 5]; Array.Copy(data, 5 + craftNameLength, craftBytes, 0, craftBytes.Length); lock (Clients[clientIndex].SharedCraftLock) { Clients[clientIndex].SharedCraftName = craftName; Clients[clientIndex].SharedCraftFile = craftBytes; Clients[clientIndex].SharedCraftType = craftType; } //Send a message to players informing them that a craft has been shared StringBuilder sb = new StringBuilder(); sb.Append(Clients[clientIndex].Username); sb.Append(" shared "); sb.Append(craftName); switch (craftType) { case KLFCommon.CraftTypeVab: sb.Append(" (VAB)"); break; case KLFCommon.CraftTypeSph: sb.Append(" (SPH)"); break; } StampedConsoleWriteLine(sb.ToString()); sb.Append(" . Enter " + KLFCommon.GetCraftCommand); sb.Append(Clients[clientIndex].Username); sb.Append(" to get it."); SendTextMessageToAll(sb.ToString()); } } break; case KLFCommon.ClientMessageID.ActivityUpdateInFlight: Clients[clientIndex].UpdateActivity(ServerClient.Activity.InFlight); break; case KLFCommon.ClientMessageID.ActivityUpdateInGame: Clients[clientIndex].UpdateActivity(ServerClient.Activity.InGame); break; case KLFCommon.ClientMessageID.Ping: Clients[clientIndex].QueueOutgoingMessage(KLFCommon.ServerMessageID.PingReply, null); break; } DebugConsoleWriteLine("Handled message"); }
public void handleMessage(int client_index, KLFCommon.ClientMessageID id, byte[] data) { if (!clientIsValid(client_index)) return; debugConsoleWriteLine("Message id: " + id.ToString() + " data: " + (data != null ? data.Length.ToString() : "0")); UnicodeEncoding encoder = new UnicodeEncoding(); switch (id) { case KLFCommon.ClientMessageID.HANDSHAKE: if (data != null) { StringBuilder sb = new StringBuilder(); //Read username Int32 username_length = KLFCommon.intFromBytes(data, 0); String username = encoder.GetString(data, 4, username_length); int offset = 4 + username_length; String version = encoder.GetString(data, offset, data.Length - offset); String username_lower = username.ToLower(); bool accepted = true; //Ensure no other players have the same username for (int i = 0; i < clients.Length; i++) { if (i != client_index && clientIsReady(i) && clients[i].username.ToLower() == username_lower) { //Disconnect the player disconnectClient(client_index, "Your username is already in use."); stampedConsoleWriteLine("Rejected client due to duplicate username: "******"Your Client is Outdated Please Update"); stampedConsoleWriteLine("Rejected client due to wrong version : " + version + " New "+ KLFCommon.PROGRAM_VERSION); accepted = false; break; } if (!accepted) break; //Send the active user count to the client if (numClients == 2) { //Get the username of the other user on the server sb.Append("There is currently 1 other user on this server: "); for (int i = 0; i < clients.Length; i++) { if (i != client_index && clientIsReady(i)) { sb.Append(clients[i].username); break; } } } else { sb.Append("There are currently "); sb.Append(numClients - 1); sb.Append(" other users on this server."); if (numClients > 1) { sb.Append(" Enter !list to see them."); } } clients[client_index].username = username; clients[client_index].receivedHandshake = true; sendServerMessage(client_index, sb.ToString()); sendServerSettings(client_index); stampedConsoleWriteLine(username + " ("+getClientIP(client_index).ToString()+") has joined the server using client version " + version); if (!clients[client_index].messagesThrottled) { //Build join message sb.Clear(); sb.Append("User "); sb.Append(username); sb.Append(" has joined the server."); //Send the join message to all other clients sendServerMessageToAll(sb.ToString(), client_index); } messageFloodIncrement(client_index); } break; case KLFCommon.ClientMessageID.PRIMARY_PLUGIN_UPDATE: case KLFCommon.ClientMessageID.SECONDARY_PLUGIN_UPDATE: if (data != null && clientIsReady(client_index)) { #if SEND_UPDATES_TO_SENDER sendPluginUpdateToAll(data, id == KLFCommon.ClientMessageID.SECONDARY_PLUGIN_UPDATE); #else sendPluginUpdateToAll(data, id == KLFCommon.ClientMessageID.SECONDARY_PLUGIN_UPDATE, client_index); #endif } break; case KLFCommon.ClientMessageID.TEXT_MESSAGE: if (data != null && clientIsReady(client_index)) handleClientTextMessage(client_index, encoder.GetString(data, 0, data.Length)); break; case KLFCommon.ClientMessageID.SCREEN_WATCH_PLAYER: if (!clientIsReady(client_index) || data == null || data.Length < 9) break; bool send_screenshot = data[0] != 0; int watch_index = KLFCommon.intFromBytes(data, 1); int current_index = KLFCommon.intFromBytes(data, 5); String watch_name = encoder.GetString(data, 9, data.Length - 9); bool watch_name_changed = false; lock (clients[client_index].watchPlayerNameLock) { if (watch_name != clients[client_index].watchPlayerName || watch_index != clients[client_index].watchPlayerIndex) { //Set the watch player name clients[client_index].watchPlayerIndex = watch_index; clients[client_index].watchPlayerName = watch_name; watch_name_changed = true; } } if (send_screenshot && watch_name_changed && watch_name.Length > 0) { //Try to find the player the client is watching and send that player's current screenshot int watched_index = getClientIndexByName(watch_name); if (clientIsReady(watched_index)) { Screenshot screenshot = null; lock (clients[watched_index].screenshotLock) { screenshot = clients[watched_index].getScreenshot(watch_index); if (screenshot == null && watch_index == -1) screenshot = clients[watched_index].lastScreenshot; } if (screenshot != null && screenshot.index != current_index) { sendScreenshot(client_index, screenshot); } } } break; case KLFCommon.ClientMessageID.SCREENSHOT_SHARE: if (data != null && data.Length <= settings.screenshotSettings.maxNumBytes && clientIsReady(client_index)) { if (!clients[client_index].screenshotsThrottled) { StringBuilder sb = new StringBuilder(); Screenshot screenshot = new Screenshot(); screenshot.setFromByteArray(data); //Set the screenshot for the player lock (clients[client_index].screenshotLock) { clients[client_index].pushScreenshot(screenshot); } sb.Append(clients[client_index].username); sb.Append(" has shared a screenshot."); sendTextMessageToAll(sb.ToString()); stampedConsoleWriteLine(sb.ToString()); //Send the screenshot to every client watching the player sendScreenshotToWatchers(client_index, screenshot); if (settings.saveScreenshots) saveScreenshot(screenshot, clients[client_index].username); SHARED_SCREEN_SHOTS += 1; } bool was_throttled = clients[client_index].screenshotsThrottled; clients[client_index].screenshotFloodIncrement(); if (!was_throttled && clients[client_index].screenshotsThrottled) { long throttle_secs = settings.screenshotFloodThrottleTime / 1000; sendServerMessage(client_index, "You have been restricted from sharing screenshots for " + throttle_secs + " seconds."); stampedConsoleWriteLine(clients[client_index].username + " has been restricted from sharing screenshots for " + throttle_secs + " seconds."); } else if (clients[client_index].throttleState.messageFloodCounter == settings.screenshotFloodLimit - 1) sendServerMessage(client_index, "Warning: You are sharing too many screenshots."); } break; case KLFCommon.ClientMessageID.CONNECTION_END: String message = String.Empty; if (data != null) message = encoder.GetString(data, 0, data.Length); //Decode the message disconnectClient(client_index, message); //Disconnect the client break; case KLFCommon.ClientMessageID.SHARE_CRAFT_FILE: if (clientIsReady(client_index) && data != null && data.Length > 5 && (data.Length - 5) <= KLFCommon.MAX_CRAFT_FILE_BYTES) { if (clients[client_index].messagesThrottled) { messageFloodIncrement(client_index); break; } messageFloodIncrement(client_index); //Read craft name length byte craft_type = data[0]; int craft_name_length = KLFCommon.intFromBytes(data, 1); if (craft_name_length < data.Length - 5) { //Read craft name String craft_name = encoder.GetString(data, 5, craft_name_length); //Read craft bytes byte[] craft_bytes = new byte[data.Length - craft_name_length - 5]; Array.Copy(data, 5 + craft_name_length, craft_bytes, 0, craft_bytes.Length); lock (clients[client_index].sharedCraftLock) { clients[client_index].sharedCraftName = craft_name; clients[client_index].sharedCraftFile = craft_bytes; clients[client_index].sharedCraftType = craft_type; } //Send a message to players informing them that a craft has been shared StringBuilder sb = new StringBuilder(); sb.Append(clients[client_index].username); sb.Append(" shared "); sb.Append(craft_name); switch (craft_type) { case KLFCommon.CRAFT_TYPE_VAB: sb.Append(" (VAB)"); break; case KLFCommon.CRAFT_TYPE_SPH: sb.Append(" (SPH)"); break; } stampedConsoleWriteLine(sb.ToString()); sb.Append(" . Enter !getcraft "); sb.Append(clients[client_index].username); sb.Append(" to get it."); sendTextMessageToAll(sb.ToString()); } } break; case KLFCommon.ClientMessageID.ACTIVITY_UPDATE_IN_FLIGHT: clients[client_index].updateActivityLevel(ServerClient.ActivityLevel.IN_FLIGHT); break; case KLFCommon.ClientMessageID.ACTIVITY_UPDATE_IN_GAME: clients[client_index].updateActivityLevel(ServerClient.ActivityLevel.IN_GAME); break; case KLFCommon.ClientMessageID.PING: clients[client_index].queueOutgoingMessage(KLFCommon.ServerMessageID.PING_REPLY, null); break; } debugConsoleWriteLine("Handled message"); }