/// <summary> /// Static loop method for receiving Steam P2P packets and enqueuing them in the receive queue /// </summary> public static async Task ReceiveLoop(MirrorpunchCommon a) { if (!a.Active) { return; // Don't bother with receive loop if inactive } bool warned = false; DateTime timeWarned = DateTime.Now; try { while (a.Active) { for (int i = 0; i < (int)P2PChannel.NUM_CHANNELS; i++) { if (!a.GetNextPacket(out P2Packet? packet, (P2PChannel)i)) { continue; } if (packet == null) { continue; } int packetLen = packet.Value.Data.Length; if (packetLen >= MP_PACKET_MAX) { Output.LogWarning($"{a.Name}: Received a packet that is too large ({packetLen})"); continue; } a.EnqueuePacket((P2Packet)packet); } if (!warned && a.ReceiveQueue.Length > MP_QUEUE_SIZE_WARNING) { Output.LogWarning($"{a.Name}: ReceiveQueue is backing up ({a.ReceiveQueue.Length} packets queued)"); timeWarned = DateTime.Now; } if (warned) { TimeSpan timeSinceWarning = DateTime.Now - timeWarned; if (timeSinceWarning.TotalSeconds > MP_QUEUE_WARNING_TIMEOUT) { warned = false; } } await Task.Delay(TimeSpan.FromMilliseconds(TickRate)); } // Return if behavior is no longer active return; } catch (Exception e) { Output.LogError($"{a.Name}: Exception raised in ReceiveLoop ({e.Message})"); return; // Return on any exception } }
/// <summary> /// Static method to process any messages in the receive queue /// </summary> public static bool ProcessMessages(MirrorpunchCommon a) { if (!a.Active) { return(false); // Don't process messages if inactive } if (!a.ReceiveQueue.HasNodes) { return(true); // Only return false if something goes wrong } DateTime timer = DateTime.Now; try { // Want to avoid a potential infinite loop, so only looping through a known number of nodes for (int i = 0; i < a.ReceiveQueue.Length; i++) { P2Packet?packet = a.ReceiveQueue.Dequeue(); if (packet == null) { continue; } SteamId senderId = packet.Value.SteamId; if (packet.Value.Data == null || packet.Value.Data.Length == 0) { continue; } if (!a.IsKnown(senderId)) { byte byteType = packet.Value.Data[0]; if (byteType < 0 || byteType >= (byte)PacketType.NUM_TYPES) { throw new Exception("Packet with invalid PacketType received from unexpected SteamId; check sending code?"); } PacketType packetType = (PacketType)byteType; switch (packetType) { case PacketType.CONNECT: Output.Log($"Connection requested by {senderId}"); a.OnSessionRequest(senderId); break; case PacketType.CONNECTION_ACCEPTED: Output.Log($"Connection accepted by {senderId}"); break; default: throw new Exception($"Unexpected packet type received from {senderId} [{byteType}]"); } // Packet from unknown sender handled without exception, continue continue; } // Received a packet from a known sender, handle received data byte[] data = packet.Value.Data; a.OnReceivedData(senderId, data); } TimeSpan checkTimer = DateTime.Now - timer; if (checkTimer.TotalMilliseconds >= MP_PROCESS_WARNING) { Output.LogWarning($"{a.Name}: ProcessMessages took longer than expected ({checkTimer.TotalMilliseconds} ms)"); } // We made it here without an exception, report success return(true); } catch (Exception e) { Output.LogError($"{a.Name}: Exception in ProcessMessages ({e.Message})"); return(false); } }
/// <summary> /// Initialize common values /// </summary> private void InitCommon() { SteamNetworking.AllowP2PPacketRelay(_allowRelay); MirrorpunchCommon.SetTickRate(_tickRate); }