public void SendGear(uint connectionToSend, NetworkingSockets server) { byte[] sendData = new byte[gearStream.Count + 6]; if (sendData.Length > Library.maxMessageSize) { ushort totalMessages = (ushort)Math.Ceiling((double)sendData.Length / Library.maxMessageSize); byte[] textureDataArray = gearStream.ToArray(); for (ushort currentMessage = 0; currentMessage < totalMessages; currentMessage++) { int startIndex = currentMessage == 0 ? 0 : currentMessage * (Library.maxMessageSize - 6); byte[] messagePart = new byte[Math.Min(Library.maxMessageSize, textureDataArray.Length - (Library.maxMessageSize - 6) * currentMessage + 6)]; messagePart[0] = (byte)OpCode.Texture; Array.Copy(BitConverter.GetBytes(currentMessage), 0, messagePart, 1, 2); Array.Copy(BitConverter.GetBytes(totalMessages - 1), 0, messagePart, 3, 2); Array.Copy(textureDataArray, startIndex, messagePart, 5, messagePart.Length - 6); messagePart[messagePart.Length - 1] = playerID; server.SendMessageToConnection(connectionToSend, messagePart, SendFlags.Reliable); } } else { sendData[0] = (byte)OpCode.Texture; Array.Copy(BitConverter.GetBytes((ushort)0), 0, sendData, 1, 2); Array.Copy(BitConverter.GetBytes((ushort)0), 0, sendData, 3, 2); Array.Copy(gearStream.ToArray(), 0, sendData, 5, gearStream.Count); sendData[sendData.Length - 1] = playerID; server.SendMessageToConnection(connectionToSend, sendData, SendFlags.Reliable); } }
public void Send(Byte[] data, SendFlags flags, OnSent onSent) { if (connected) { client.SendMessageToConnection(connection, data, flags); onSent?.Invoke(); } }
public void StatusCallbackFunction(ref StatusInfo info, IntPtr context) { switch (info.connectionInfo.state) { case ConnectionState.None: break; case ConnectionState.Connecting: { if (info.connectionInfo.listenSocket != listenSocket) { mainServer.StatusCallbackFunction(ref info, context); break; } //Console.WriteLine("connecting on file server"); if (mainServer.bannedIPs.Contains(info.connectionInfo.address.GetIP())) { //Console.WriteLine("Ban player attempted to connect to the server, IP: {0}", info.connectionInfo.address.GetIP()); server.CloseConnection(info.connection); } else { server.AcceptConnection(info.connection); server.SetConnectionPollGroup(pollGroup, info.connection); } } break; case ConnectionState.Connected: { if (info.connectionInfo.listenSocket != listenSocket) { mainServer.StatusCallbackFunction(ref info, context); break; } if (mainServer.motdBytes != null) { server.SendMessageToConnection(info.connection, mainServer.motdBytes); } //Console.WriteLine("connected on file server"); } break; case ConnectionState.ClosedByPeer: case ConnectionState.ProblemDetectedLocally: mainServer.RemovePlayer(info.connection); break; } }
private static void RemovePlayer(uint connection, int ID = -1, bool kicked = false) { server.CloseConnection(connection); Player removedPlayer = null; if (ID == -1) { foreach (Player player in players) { if (player != null && player.connection == connection) { removedPlayer = player; break; } } } else { removedPlayer = players[ID]; } if (removedPlayer != null) { if (!kicked) { Console.WriteLine("Client disconnected - ID: " + removedPlayer.playerID); } foreach (Player player in players) { if (player != null && player != removedPlayer) { server.SendMessageToConnection(player.connection, new byte[] { (byte)OpCode.Disconnect, removedPlayer.playerID }, SendFlags.Reliable | SendFlags.NoNagle); } } players[removedPlayer.playerID] = null; } }
public void Update() { FrameWatch.Restart(); recentTimeSinceStartup = Time.realtimeSinceStartup; if (networkMessageQueue != null) { GC.KeepAlive(networkMessageQueue); GC.KeepAlive(CompressedSounds); GC.KeepAlive(DecompressedSounds); GC.KeepAlive(CompressedAnimations); GC.KeepAlive(DecompressedAnimations); } if (GameStateMachine.Instance.CurrentState.GetType().Equals(typeof(PauseState))) { if (GameStateMachine.Instance.CurrentState.CanDoTransitionTo(typeof(ChallengeSelectionState))) { Type[] allowedTransitions = null; Type objectDropperState = AccessTools.TypeByName("ObjectDropperState"); if (MultiplayerUtils.serverMapDictionary.Count == 0) { allowedTransitions = objectDropperState == null ? new Type[4] : new Type[5]; allowedTransitions[3] = typeof(LevelSelectionState); } else { allowedTransitions = objectDropperState == null ? new Type[3] : new Type[4]; } allowedTransitions[0] = typeof(PlayState); allowedTransitions[1] = typeof(ReplayMenuState); allowedTransitions[2] = typeof(SettingsState); if (objectDropperState != null) allowedTransitions[allowedTransitions.Length - 1] = objectDropperState; Traverse.Create(GameStateMachine.Instance.CurrentState).Field("availableTransitions").SetValue( allowedTransitions ); } } if (initiatingServerConnection) { ConnectionCallback(); this.StartCoroutine(this.playerController.EncodeTextures()); initiatingServerConnection = false; } else if (initiatingFileServerConnection) { this.debugWriter.WriteLine("connected on file server"); byte[] connectMessage = new byte[5]; connectMessage[0] = (byte)OpCode.Connect; Array.Copy(BitConverter.GetBytes(serverConnectionNumber), 0, connectMessage, 1, 4); fileClient.SendMessageToConnection(fileConnection, connectMessage, SendFlags.Reliable | SendFlags.NoNagle); isFileConnected = true; initiatingFileServerConnection = false; } if (closedByPeer) { //Client disconnected from server this.debugWriter.WriteLine("Disconnected from server"); Main.utilityMenu.SendImportantChat("<b><color=\"red\">You have been disconnected from the server</color></b>", 7500); DisconnectFromServer(); } if (problemDetectedLocally) { //Client unable to connect this.debugWriter.WriteLine("Unable to connect to server"); Main.utilityMenu.SendImportantChat("<b><color=\"red\">You could not connect to the server</color></b>", 7500); DisconnectFromServer(); } if (client == null) return; if (usernameMessage != null) { SendBytes(OpCode.Settings, usernameMessage, true, true); usernameMessage = null; } if (GameStateMachine.Instance.CurrentState.GetType() != typeof(ReplayState)) { if (replayStarted) { foreach (MultiplayerRemotePlayerController controller in remoteControllers) { if (controller.playerID == 255) { controller.skater.SetActive(false); controller.board.SetActive(false); } controller.EndReplay(); foreach (ReplayAudioEventPlayer replayAudioPlayer in controller.replayController.AudioEventPlayers) { if (replayAudioPlayer != null) { Traverse.Create(replayAudioPlayer).Method("UnloadEvents").GetValue(); } } } } replayStarted = false; } else { if (!replayStarted) { replayStarted = true; foreach (MultiplayerRemotePlayerController controller in remoteControllers) { if (controller.playerID == 255) { controller.skater.SetActive(true); controller.board.SetActive(true); } controller.PrepareReplay(); } } } recentTimeSinceStartup = Time.realtimeSinceStartup; StateManagementTime = FrameWatch.Elapsed.TotalMilliseconds; if (sendingUpdates) { this.playerController.SendTextures(); timeSinceLastUpdate += Time.unscaledDeltaTime; if (timeSinceLastUpdate > 1f / (float)tickRate) { SendUpdate(); timeSinceLastUpdate = 0.0f; } } recentTimeSinceStartup = Time.realtimeSinceStartup; // Calculate network statistics every 10 seconds if (Time.time - statisticsResetTime > 10f && pingTimes.Count > 0 && sentAlive10Seconds > 0) { float totalPing = 0; foreach (float ping in pingTimes) { totalPing += ping; } int realPing = (int)(totalPing / pingTimes.Count * 1000f); float lossPercent = Mathf.Max(((1f - ((float)receivedAlive10Seconds / (float)sentAlive10Seconds)) * 100f), 0); string netstats = $"Ping: {realPing}ms Packet Loss: {lossPercent.ToString("N2")}%"; this.debugWriter.WriteLine(netstats); statisticsResetTime = Time.time; sentAlive10Seconds = 0; receivedAlive10Seconds = 0; pingTimes.Clear(); } NetworkDiagnosticTime = FrameWatch.Elapsed.TotalMilliseconds - StateManagementTime; ProcessMessageQueue(); MessageQueueTime = FrameWatch.Elapsed.TotalMilliseconds - NetworkDiagnosticTime; ProcessSoundAnimationQueue(); double SoundAnimationTime = FrameWatch.Elapsed.TotalMilliseconds - MessageQueueTime; recentTimeSinceStartup = Time.realtimeSinceStartup; // Lerp frames using frame buffer List<MultiplayerRemotePlayerController> controllerToRemove = new List<MultiplayerRemotePlayerController>(); foreach (MultiplayerRemotePlayerController controller in this.remoteControllers) { if (controller != null) { controller.ApplyTextures(); if (replayStarted && GameManagement.GameStateMachine.Instance.CurrentState.GetType() == typeof(GameManagement.ReplayState)) { controller.replayController.TimeScale = ReplayEditorController.Instance.playbackController.TimeScale; controller.replayController.SetPlaybackTime(ReplayEditorController.Instance.playbackController.CurrentTime); if (controller.playerID == 255 && ((controller.replayController.ClipFrames.Last().time < ReplayEditorController.Instance.playbackController.CurrentTime && controller.skater.activeSelf) || (controller.replayController.ClipFrames.Count == 0 && controller.skater.activeSelf))) { controller.skater.SetActive(false); controller.board.SetActive(false); } else if (controller.playerID == 255 && controller.replayController.ClipFrames.Count > 0 && controller.replayController.ClipFrames.Last().time > ReplayEditorController.Instance.playbackController.CurrentTime && !controller.skater.activeSelf) { controller.skater.SetActive(true); controller.board.SetActive(true); } } if (controller.playerID == 255 && (ReplayRecorder.Instance.RecordedFrames.Count < 1 || controller.replayAnimationFrames.LastOrDefault(obj => obj.realFrameTime != -1f) == null || (controller.replayAnimationFrames.Last(obj => obj.realFrameTime != -1f).realFrameTime < ReplayRecorder.Instance.RecordedFrames.First().time))) { controllerToRemove.Add(controller); } // TODO: Perform calculations on seperate thread and then apply transformations on main thread if (controller.playerID != 255) controller.StartFrameLerp(); } recentTimeSinceStartup = Time.realtimeSinceStartup; } foreach (MultiplayerRemotePlayerController player in controllerToRemove) RemovePlayer(player); foreach (MultiplayerRemotePlayerController controller in this.remoteControllers) { if (controller.playerID != 255) controller.EndLerpFrame(); } SoundAndAnimationTime = FrameWatch.Elapsed.TotalMilliseconds - MessageQueueTime; //private double StateManagementTime = 0; //private double NetworkDiagnosticTime = 0; //private double MessageQueueTime = 0; //private double SoundAndAnimationTime = 0; FrameWatch.Stop(); previousQueueTimes.Add(MessageQueueTime); double averageTime = 0; if(previousQueueTimes.Count > 100) { previousQueueTimes.RemoveAt(previousQueueTimes.Count - 1); foreach(double t in previousQueueTimes) { averageTime += t; } averageTime /= previousQueueTimes.Count; if(MessageQueueTime > averageTime * 1.5) { this.debugWriter.WriteLine($"Frame Time Multiplayer: {FrameWatch.Elapsed.TotalMilliseconds} - Sound and Animation Queue Processing {SoundAndAnimationTime}, State management {StateManagementTime}, Network Diagnostics {NetworkDiagnosticTime}, Message Queue Processing {MessageQueueTime}, Sound and Animations {SoundAndAnimationTime}, Messages Processed {messagesProcessed}"); foreach(Tuple<double, OpCode> item in proccessedMessages) { this.debugWriter.WriteLine($"Opcode {item.Item2} took {item.Item1}ms"); } } } recentTimeSinceStartup = Time.realtimeSinceStartup; }
public static void ServerLoop() { Library.Initialize(); server = new NetworkingSockets(); Address address = new Address(); NetworkingUtils utils = new NetworkingUtils(); utils.SetDebugCallback(DebugType.Important, (type, message) => { Console.WriteLine("Valve Debug - Type: {0}, Message: {1}", type, message); }); unsafe { int sendRateMin = 5 * 1024 * 1024; int sendRateMax = MAX_UPLOAD; int sendBufferSize = MAX_BUFFER; utils.SetConfigurationValue(ConfigurationValue.SendRateMin, ConfigurationScope.Global, IntPtr.Zero, ConfigurationDataType.Int32, new IntPtr(&sendRateMin)); utils.SetConfigurationValue(ConfigurationValue.SendRateMax, ConfigurationScope.Global, IntPtr.Zero, ConfigurationDataType.Int32, new IntPtr(&sendRateMax)); utils.SetConfigurationValue(ConfigurationValue.SendBufferSize, ConfigurationScope.Global, IntPtr.Zero, ConfigurationDataType.Int32, new IntPtr(&sendBufferSize)); } address.SetAddress("::0", port); uint listenSocket = server.CreateListenSocket(ref address); uint pollGroup = server.CreatePollGroup(); Console.WriteLine($"Server {SERVER_NAME} started Listening on port {port} for maximum of {MAX_PLAYERS} players\nEnforcing maps is {ENFORCE_MAPS}"); StartAnnouncing(); StatusCallback status = (ref StatusInfo info, IntPtr context) => { switch (info.connectionInfo.state) { case ConnectionState.None: break; case ConnectionState.Connecting: server.AcceptConnection(info.connection); server.SetConnectionPollGroup(pollGroup, info.connection); break; case ConnectionState.Connected: Console.WriteLine("Client connected - IP: " + info.connectionInfo.address.GetIP()); bool openSlot = false; for (byte i = 0; i < MAX_PLAYERS; i++) { if (players[i] == null) { players[i] = new Player(i, info.connection, info.connectionInfo.address); byte[] versionNumber = ASCIIEncoding.ASCII.GetBytes(VERSION_NUMBER); byte[] versionMessage = new byte[versionNumber.Length + 1]; versionMessage[0] = (byte)OpCode.VersionNumber; Array.Copy(versionNumber, 0, versionMessage, 1, versionNumber.Length); server.SendMessageToConnection(players[i].connection, versionMessage, SendFlags.Reliable | SendFlags.NoNagle); if (ENFORCE_MAPS) { server.SendMessageToConnection(players[i].connection, mapListBytes, SendFlags.Reliable); server.SendMessageToConnection(players[i].connection, GetCurrentMapHashMessage(), SendFlags.Reliable); } foreach (Player player in players) { if (player != null && player != players[i]) { server.SendMessageToConnection(players[i].connection, new byte[] { (byte)OpCode.Connect, player.playerID }, SendFlags.Reliable); server.SendMessageToConnection(player.connection, new byte[] { (byte)OpCode.Connect, i }, SendFlags.Reliable); if (player.usernameMessage != null) { server.SendMessageToConnection(players[i].connection, player.usernameMessage, SendFlags.Reliable); } if (player.allGearUploaded) { foreach (KeyValuePair <string, byte[]> value in player.gear) { server.SendMessageToConnection(players[i].connection, value.Value, SendFlags.Reliable); } } } } server.FlushMessagesOnConnection(players[i].connection); openSlot = true; break; } } if (!openSlot) { server.CloseConnection(info.connection); } break; case ConnectionState.ClosedByPeer: RemovePlayer(info.connection); break; } }; #if VALVESOCKETS_SPAN MessageCallback messageCallback = (in NetworkingMessage netMessage) => { byte[] messageData = new byte[netMessage.length]; netMessage.CopyTo(messageData); Player sendingPlayer = null; foreach (Player player in players) { if (player != null && player.connection == netMessage.connection) { sendingPlayer = player; break; } } if (sendingPlayer != null) { ProcessMessage(messageData, sendingPlayer.playerID, server); } }; #else const int maxMessages = 256; NetworkingMessage[] netMessages = new NetworkingMessage[maxMessages]; #endif while (RUNNING) { server.DispatchCallback(status); #if VALVESOCKETS_SPAN server.ReceiveMessagesOnPollGroup(pollGroup, messageCallback, 256); #else int netMessagesCount = server.ReceiveMessagesOnConnection(listenSocket, netMessages, maxMessages); if (netMessagesCount > 0) { for (int i = 0; i < netMessagesCount; i++) { ref NetworkingMessage netMessage = ref netMessages[i]; byte[] messageData = new byte[netMessage.length]; netMessage.CopyTo(messageData); Player sendingPlayer = null; foreach (Player player in players) { if (player != null && player.connection == netMessage.connection) { sendingPlayer = player; break; } } //Console.WriteLine("Recieved packet from connection {0}, sending player null: {1}", netMessage.connection, sendingPlayer == null); if (sendingPlayer != null) { ProcessMessage(messageData, sendingPlayer.playerID, server); } netMessage.Destroy(); } } #endif mapVotes.Clear(); total_players = 0; foreach (Player player in players) { if (player != null) { total_players++; if (player.timeoutWatch.ElapsedMilliseconds > 15000) { Console.WriteLine($"{player.playerID} has been timed out for not responding for 15 seconds"); RemovePlayer(player.connection, player.playerID, true); } if (!mapVotes.ContainsKey(player.currentVote)) { mapVotes.Add(player.currentVote, 1); } else { mapVotes[player.currentVote]++; } } } // Handle map voting and map enforcement if (ENFORCE_MAPS) { if (total_players == 0) { currentMapHash = "1"; } bool startNewTimer = false; if (mapVotes.ContainsKey("current")) { if (mapVotes["current"] < (int)Math.Ceiling((float)total_players / 2)) { if (!mapVoteTimer.IsRunning) { startNewTimer = true; } } } else if (!mapVoteTimer.IsRunning && total_players > 0) { startNewTimer = true; } if (startNewTimer) { mapVoteTimer.Restart(); byte[] mapVoteMsg = new byte[] { (byte)OpCode.MapVote, 0, 0 }; foreach (Player player in players) { if (player != null) { server.SendMessageToConnection(player.connection, mapVoteMsg, SendFlags.Reliable); } } } if (mapVoteTimer.IsRunning && mapVoteTimer.ElapsedMilliseconds > 30000 && total_players > 0) { mapVoteTimer.Stop(); Tuple <string, int> mostVoted = null; foreach (var item in mapVotes) { if (!item.Key.Equals("current")) { if (mostVoted == null || mostVoted.Item2 < item.Value) { mostVoted = Tuple.Create <string, int>(item.Key, item.Value); } } } currentMapHash = mostVoted.Item1; byte[] newMapMessage = GetCurrentMapHashMessage(); foreach (Player player in players) { if (player != null) { server.SendMessageToConnection(player.connection, newMapMessage, SendFlags.Reliable); player.currentVote = "current"; } } } else if (total_players == 0) { mapVoteTimer.Stop(); } } }
private static void ProcessMessage(byte[] buffer, byte fromID, NetworkingSockets server) { if (!Enum.IsDefined(typeof(OpCode), (OpCode)buffer[0]) || players[fromID] == null) { return; } players[fromID].timeoutWatch.Restart(); switch ((OpCode)buffer[0]) { case OpCode.Settings: Thread usernameThread = new Thread(new ParameterizedThreadStart(Server.HandleUsername)); usernameThread.IsBackground = true; usernameThread.Start(Tuple.Create(buffer, fromID)); break; case OpCode.Texture: { Console.WriteLine("Received Texture from " + fromID); Player player = players[fromID]; if (player != null && player.playerID == fromID) { player.AddGear(buffer); if (player.allGearUploaded) { foreach (Player player2 in players) { if (player2 != null && player2.playerID != fromID) { foreach (KeyValuePair <string, byte[]> value in player.gear) { server.SendMessageToConnection(player2.connection, value.Value, SendFlags.Reliable); } server.FlushMessagesOnConnection(player2.connection); } } } } } break; case OpCode.Animation: if (players[fromID] != null) { bool reliable = buffer[buffer.Length - 1] == (byte)1 ? true : false; buffer[buffer.Length - 1] = fromID; foreach (Player player in players) { if (player != null && player.playerID != fromID) { ConnectionStatus status = new ConnectionStatus(); if (server.GetQuickConnectionStatus(player.connection, ref status)) { int bytesPending = status.pendingReliable + status.sentUnackedReliable; if (reliable && bytesPending >= MAX_BYTES_PENDING) { Console.WriteLine($"Sending animation unreliably to ({player.playerID}) because pending bytes is higher than max"); reliable = false; } } server.SendMessageToConnection(player.connection, buffer, reliable ? SendFlags.Reliable | SendFlags.NoNagle : SendFlags.Unreliable | SendFlags.NoNagle); } } } break; case OpCode.Chat: string contents = ASCIIEncoding.ASCII.GetString(buffer, 1, buffer.Length - 1); Console.WriteLine("Chat Message from {0} saying: {1}", fromID, contents); byte[] sendBuffer = new byte[buffer.Length + 1]; Array.Copy(buffer, 0, sendBuffer, 0, buffer.Length); sendBuffer[buffer.Length] = fromID; foreach (Player player in players) { if (player != null) { server.SendMessageToConnection(player.connection, sendBuffer, SendFlags.Reliable); } } break; case OpCode.MapVote: if (ENFORCE_MAPS) { string vote = ASCIIEncoding.ASCII.GetString(buffer, 1, buffer.Length - 1); if (mapList.ContainsKey(vote) || vote.ToLower().Equals("current")) { vote = mapList.ContainsKey(vote) && mapList[vote].Equals(currentMapHash) ? "current" : vote; players[fromID].currentVote = vote; Console.WriteLine("{0} voted for the map {1}", fromID, mapList.ContainsKey(vote) ? mapList[vote] : vote); } } break; case OpCode.StillAlive: if (players[fromID] != null) { server.SendMessageToConnection(players[fromID].connection, buffer, SendFlags.Unreliable | SendFlags.NoNagle); } break; } }
public void SendTo(UInt32 connectionID, byte[] data, SendFlags flags) { server.SendMessageToConnection(connectionID, data, flags); }
void Test() { byte[] data = new byte[64]; client.SendMessageToConnection(connection, data); }
public void ServerLoop() { Library.Initialize(); server = new NetworkingSockets(); Address address = new Address(); //Console.WriteLine($"Gameplay port: {Server.port}, File Server Port: {(ushort)(Server.port + 1)}"); address.SetAddress("::0", (ushort)(Server.port + 1)); listenSocket = server.CreateListenSocket(ref address); pollGroup = server.CreatePollGroup(); NetworkingUtils utils = new NetworkingUtils(); unsafe { int sendRateMin = 512000; int sendRateMax = Server.FILE_MAX_UPLOAD; utils.SetConfigurationValue(ConfigurationValue.SendRateMin, ConfigurationScope.ListenSocket, new IntPtr(listenSocket), ConfigurationDataType.Int32, new IntPtr(&sendRateMin)); utils.SetConfigurationValue(ConfigurationValue.SendRateMax, ConfigurationScope.ListenSocket, new IntPtr(listenSocket), ConfigurationDataType.Int32, new IntPtr(&sendRateMax)); } StatusCallback status = StatusCallbackFunction; MessageCallback messageCallback = (in NetworkingMessage netMessage) => { byte[] message = new byte[netMessage.length]; netMessage.CopyTo(message); if ((OpCode)message[0] == OpCode.Connect) { uint originalConnection = BitConverter.ToUInt32(message, 1); Player newPlayer = null; foreach (Player player in mainServer.players) { if (player != null && player.connection == originalConnection) { player.fileConnection = netMessage.connection; newPlayer = player; break; } } if (newPlayer == null) { //Console.WriteLine("Connection on file server doesn't exist on gameplay server"); server.CloseConnection(netMessage.connection); } else { foreach (Player player in mainServer.players) { if (player != null && player.playerID != newPlayer.playerID && player.completedGearStream) { player.SendGear(newPlayer.fileConnection, server); } } foreach (Plugin plugin in mainServer.loadedPlugins) { if (plugin.hash != "" && plugin.dependencyFile != "") { byte[] hashBytes = ASCIIEncoding.ASCII.GetBytes(plugin.hash); byte[] hashMessage = new byte[hashBytes.Length + 2]; hashMessage[0] = (byte)OpCode.PluginHash; hashMessage[1] = plugin.pluginID; Array.Copy(hashBytes, 0, hashMessage, 2, hashBytes.Length); server.SendMessageToConnection(newPlayer.fileConnection, hashMessage, SendFlags.Reliable); } } } } else if ((OpCode)message[0] == OpCode.StillAlive) { server.SendMessageToConnection(netMessage.connection, message, SendFlags.Unreliable | SendFlags.NoNagle); } else { foreach (Player player in mainServer.players) { if (player != null && player.fileConnection == netMessage.connection) { mainServer.ProcessMessage(message, player.playerID, mainServer.server); } } } }; Stopwatch fileServerLoopTime = new Stopwatch(); while (mainServer.RUNNING) { fileServerLoopTime.Restart(); server.DispatchCallback(status); server.ReceiveMessagesOnPollGroup(pollGroup, messageCallback, 256); SpinWait.SpinUntil(() => fileServerLoopTime.Elapsed.TotalMilliseconds >= 1, 1); } }
public void ServerLoop() { Library.Initialize(); server = new NetworkingSockets(); Address address = new Address(); //Console.WriteLine($"Gameplay port: {Server.port}, File Server Port: {(ushort)(Server.port + 1)}"); address.SetAddress("::0", (ushort)(Server.port + 1)); listenSocket = server.CreateListenSocket(ref address); pollGroup = server.CreatePollGroup(); NetworkingUtils utils = new NetworkingUtils(); unsafe { int sendRateMin = 512000; int sendRateMax = Server.FILE_MAX_UPLOAD; utils.SetConfigurationValue(ConfigurationValue.SendRateMin, ConfigurationScope.ListenSocket, new IntPtr(listenSocket), ConfigurationDataType.Int32, new IntPtr(&sendRateMin)); utils.SetConfigurationValue(ConfigurationValue.SendRateMax, ConfigurationScope.ListenSocket, new IntPtr(listenSocket), ConfigurationDataType.Int32, new IntPtr(&sendRateMax)); } StatusCallback status = StatusCallbackFunction; MessageCallback messageCallback = (in NetworkingMessage netMessage) => { byte[] message = new byte[netMessage.length]; netMessage.CopyTo(message); if ((OpCode)message[0] == OpCode.Connect) { uint originalConnection = BitConverter.ToUInt32(message, 1); Player newPlayer = null; foreach (Player player in mainServer.players) { if (player != null && player.connection == originalConnection) { player.fileConnection = netMessage.connection; newPlayer = player; break; } } if (newPlayer == null) { //Console.WriteLine("Connection on file server doesn't exist on gameplay server"); server.CloseConnection(netMessage.connection); } else { foreach (Player player in mainServer.players) { if (player != null && player.playerID != newPlayer.playerID && player.completedGearStream) { player.SendGear(newPlayer.fileConnection, server); } } } } else if ((OpCode)message[0] == OpCode.StillAlive) { server.SendMessageToConnection(netMessage.connection, message, SendFlags.Unreliable | SendFlags.NoNagle); } else { foreach (Player player in mainServer.players) { if (player != null && player.fileConnection == netMessage.connection) { mainServer.ProcessMessage(message, player.playerID, mainServer.server); } } } }; while (mainServer.RUNNING) { server.DispatchCallback(status); server.ReceiveMessagesOnPollGroup(pollGroup, messageCallback, 256); } }
public void StatusCallbackFunction(ref StatusInfo info, IntPtr context) { switch (info.connectionInfo.state) { case ConnectionState.None: break; case ConnectionState.Connecting: { if (info.connectionInfo.listenSocket != listenSocket) { mainServer.StatusCallbackFunction(ref info, context); break; } //Console.WriteLine("connecting on file server"); if (mainServer.bannedIPs.Contains(info.connectionInfo.address.GetIP())) { //Console.WriteLine("Ban player attempted to connect to the server, IP: {0}", info.connectionInfo.address.GetIP()); server.CloseConnection(info.connection); } else { server.AcceptConnection(info.connection); server.SetConnectionPollGroup(pollGroup, info.connection); } } break; case ConnectionState.Connected: { if (info.connectionInfo.listenSocket != listenSocket) { mainServer.StatusCallbackFunction(ref info, context); break; } if (mainServer.motdBytes != null) { server.SendMessageToConnection(info.connection, mainServer.motdBytes); } foreach (Player player in mainServer.players) { foreach (Plugin plugin in mainServer.loadedPlugins) { if (plugin.hash != "") { byte[] hashBytes = ASCIIEncoding.ASCII.GetBytes(plugin.hash); byte[] hashMessage = new byte[hashBytes.Length + 2]; hashMessage[0] = (byte)OpCode.PluginHash; hashMessage[1] = plugin.pluginID; Array.Copy(hashBytes, 0, hashMessage, 2, hashBytes.Length); server.SendMessageToConnection(player.connection, hashMessage, SendFlags.Reliable); } } } //Console.WriteLine("connected on file server"); } break; case ConnectionState.ClosedByPeer: case ConnectionState.ProblemDetectedLocally: mainServer.RemovePlayer(info.connection); break; } }