public override void Update(float deltaTime) { if (!started) { return; } if (OnOwnerDetermined != null && OwnerConnection != null) { OnOwnerDetermined?.Invoke(OwnerConnection); OnOwnerDetermined = null; } //backwards for loop so we can remove elements while iterating for (int i = connectedClients.Count - 1; i >= 0; i--) { SteamP2PConnection conn = connectedClients[i] as SteamP2PConnection; conn.Decay(deltaTime); if (conn.Timeout < 0.0) { Disconnect(conn, "Timed out"); } } try { while (ChildServerRelay.Read(out byte[] incBuf)) { IReadMessage inc = new ReadOnlyMessage(incBuf, false, 0, incBuf.Length, OwnerConnection); HandleDataMessage(inc); } } catch (Exception e) { string errorMsg = "Server failed to read an incoming message. {" + e + "}\n" + e.StackTrace; GameAnalyticsManager.AddErrorEventOnce("SteamP2PServerPeer.Update:ClientReadException" + e.TargetSite.ToString(), GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg); #if DEBUG DebugConsole.ThrowError(errorMsg); #else if (GameSettings.VerboseLogging) { DebugConsole.ThrowError(errorMsg); } #endif } for (int i = 0; i < pendingClients.Count; i++) { PendingClient pendingClient = pendingClients[i]; UpdatePendingClient(pendingClient); if (i >= pendingClients.Count || pendingClients[i] != pendingClient) { i--; } } }
public override void Start(object endPoint, int ownerKey) { contentPackageOrderReceived = false; steamAuthTicket = SteamManager.GetAuthSessionTicket(); //TODO: wait for GetAuthSessionTicketResponse_t if (steamAuthTicket == null) { throw new Exception("GetAuthSessionTicket returned null"); } if (!(endPoint is UInt64 steamIdEndpoint)) { throw new InvalidCastException("endPoint is not UInt64"); } hostSteamId = steamIdEndpoint; Steamworks.SteamNetworking.ResetActions(); Steamworks.SteamNetworking.OnP2PSessionRequest = OnIncomingConnection; Steamworks.SteamNetworking.OnP2PConnectionFailed = OnConnectionFailed; Steamworks.SteamNetworking.AllowP2PPacketRelay(true); ServerConnection = new SteamP2PConnection("Server", hostSteamId); ServerConnection.SetOwnerSteamIDIfUnknown(hostSteamId); incomingInitializationMessages = new List <IReadMessage>(); incomingDataMessages = new List <IReadMessage>(); IWriteMessage outMsg = new WriteOnlyMessage(); outMsg.Write((byte)DeliveryMethod.Reliable); outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep); outMsg.Write((byte)ConnectionInitialization.ConnectionStarted); Steamworks.SteamNetworking.SendP2PPacket(hostSteamId, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Reliable); sentBytes += outMsg.LengthBytes; initializationStep = ConnectionInitialization.SteamTicketAndVersion; timeout = NetworkConnection.TimeoutThreshold; heartbeatTimer = 1.0; connectionStatusTimer = 0.0; isActive = true; }
public override void Start(object endPoint, int ownerKey) { steamAuthTicket = SteamManager.GetAuthSessionTicket(); //TODO: wait for GetAuthSessionTicketResponse_t if (steamAuthTicket == null) { throw new Exception("GetAuthSessionTicket returned null"); } if (!(endPoint is UInt64 steamIdEndpoint)) { throw new InvalidCastException("endPoint is not UInt64"); } hostSteamId = steamIdEndpoint; Steam.SteamManager.Instance.Networking.OnIncomingConnection = OnIncomingConnection; Steam.SteamManager.Instance.Networking.OnP2PData = OnP2PData; Steam.SteamManager.Instance.Networking.SetListenChannel(0, true); ServerConnection = new SteamP2PConnection("Server", hostSteamId); incomingInitializationMessages = new List <IReadMessage>(); incomingDataMessages = new List <IReadMessage>(); IWriteMessage outMsg = new WriteOnlyMessage(); outMsg.Write((byte)DeliveryMethod.Reliable); outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep); outMsg.Write((byte)ConnectionInitialization.ConnectionStarted); SteamManager.Instance.Networking.SendP2PPacket(hostSteamId, outMsg.Buffer, outMsg.LengthBytes, Facepunch.Steamworks.Networking.SendType.Reliable); initializationStep = ConnectionInitialization.SteamTicketAndVersion; timeout = NetworkConnection.TimeoutThreshold; heartbeatTimer = 1.0; isActive = true; }
private void UpdatePendingClient(PendingClient pendingClient) { if (netServer == null) { return; } if (serverSettings.BanList.IsBanned(pendingClient.SteamID)) { RemovePendingClient(pendingClient, DisconnectReason.Banned, "Initialization interrupted by ban"); return; } //DebugConsole.NewMessage("pending client status: " + pendingClient.InitializationStep); if (connectedClients.Count >= serverSettings.MaxPlayers - 1) { RemovePendingClient(pendingClient, DisconnectReason.ServerFull, ""); } if (pendingClient.InitializationStep == ConnectionInitialization.Success) { SteamP2PConnection newConnection = new SteamP2PConnection(pendingClient.Name, pendingClient.SteamID) { Status = NetworkConnectionStatus.Connected }; connectedClients.Add(newConnection); pendingClients.Remove(pendingClient); OnInitializationComplete?.Invoke(newConnection); } pendingClient.TimeOut -= Timing.Step; if (pendingClient.TimeOut < 0.0) { RemovePendingClient(pendingClient, DisconnectReason.Unknown, Lidgren.Network.NetConnection.NoResponseMessage); } if (Timing.TotalTime < pendingClient.UpdateTime) { return; } pendingClient.UpdateTime = Timing.TotalTime + 1.0; NetOutgoingMessage outMsg = netServer.CreateMessage(); outMsg.Write(pendingClient.SteamID); outMsg.Write((byte)(PacketHeader.IsConnectionInitializationStep | PacketHeader.IsServerMessage)); outMsg.Write((byte)pendingClient.InitializationStep); switch (pendingClient.InitializationStep) { case ConnectionInitialization.Password: outMsg.Write(pendingClient.PasswordSalt == null); outMsg.WritePadBits(); if (pendingClient.PasswordSalt == null) { pendingClient.PasswordSalt = CryptoRandom.Instance.Next(); outMsg.Write(pendingClient.PasswordSalt.Value); } else { outMsg.Write(pendingClient.Retries); } break; } if (netConnection != null) { NetSendResult result = netServer.SendMessage(outMsg, netConnection, NetDeliveryMethod.ReliableUnordered); if (result != NetSendResult.Sent && result != NetSendResult.Queued) { DebugConsole.NewMessage("Failed to send initialization step " + pendingClient.InitializationStep.ToString() + " to pending client: " + result.ToString(), Microsoft.Xna.Framework.Color.Yellow); } } }
private void HandleDataMessage(NetIncomingMessage inc) { if (netServer == null) { return; } if (inc.SenderConnection != netConnection) { return; } UInt64 senderSteamId = inc.ReadUInt64(); byte incByte = inc.ReadByte(); bool isCompressed = (incByte & (byte)PacketHeader.IsCompressed) != 0; bool isConnectionInitializationStep = (incByte & (byte)PacketHeader.IsConnectionInitializationStep) != 0; bool isDisconnectMessage = (incByte & (byte)PacketHeader.IsDisconnectMessage) != 0; bool isServerMessage = (incByte & (byte)PacketHeader.IsServerMessage) != 0; bool isHeartbeatMessage = (incByte & (byte)PacketHeader.IsHeartbeatMessage) != 0; if (isServerMessage) { DebugConsole.ThrowError("Got server message from" + senderSteamId.ToString()); return; } if (senderSteamId != OwnerSteamID) //sender is remote, handle disconnects and heartbeats { PendingClient pendingClient = pendingClients.Find(c => c.SteamID == senderSteamId); SteamP2PConnection connectedClient = connectedClients.Find(c => c.SteamID == senderSteamId); pendingClient?.Heartbeat(); connectedClient?.Heartbeat(); if (serverSettings.BanList.IsBanned(senderSteamId)) { if (pendingClient != null) { RemovePendingClient(pendingClient, DisconnectReason.Banned, "Banned"); } else if (connectedClient != null) { Disconnect(connectedClient, DisconnectReason.Banned.ToString() + "/ Banned"); } return; } else if (isDisconnectMessage) { if (pendingClient != null) { string disconnectMsg = $"ServerMessage.HasDisconnected~[client]={pendingClient.Name}"; RemovePendingClient(pendingClient, DisconnectReason.Unknown, disconnectMsg); } else if (connectedClient != null) { string disconnectMsg = $"ServerMessage.HasDisconnected~[client]={connectedClient.Name}"; Disconnect(connectedClient, disconnectMsg, false); } return; } else if (isHeartbeatMessage) { //message exists solely as a heartbeat, ignore its contents return; } else if (isConnectionInitializationStep) { if (pendingClient != null) { ReadConnectionInitializationStep(pendingClient, new ReadOnlyMessage(inc.Data, false, inc.PositionInBytes, inc.LengthBytes - inc.PositionInBytes, null)); } else { ConnectionInitialization initializationStep = (ConnectionInitialization)inc.ReadByte(); if (initializationStep == ConnectionInitialization.ConnectionStarted) { pendingClients.Add(new PendingClient(senderSteamId)); } } } else if (connectedClient != null) { UInt16 length = inc.ReadUInt16(); IReadMessage msg = new ReadOnlyMessage(inc.Data, isCompressed, inc.PositionInBytes, length, connectedClient); OnMessageReceived?.Invoke(connectedClient, msg); } } else //sender is owner { if (OwnerConnection != null) { (OwnerConnection as SteamP2PConnection).Heartbeat(); } if (isDisconnectMessage) { DebugConsole.ThrowError("Received disconnect message from owner"); return; } if (isServerMessage) { DebugConsole.ThrowError("Received server message from owner"); return; } if (isConnectionInitializationStep) { if (OwnerConnection == null) { string ownerName = inc.ReadString(); OwnerConnection = new SteamP2PConnection(ownerName, OwnerSteamID) { Status = NetworkConnectionStatus.Connected }; OnInitializationComplete?.Invoke(OwnerConnection); } return; } if (isHeartbeatMessage) { return; } else { UInt16 length = inc.ReadUInt16(); IReadMessage msg = new ReadOnlyMessage(inc.Data, isCompressed, inc.PositionInBytes, length, OwnerConnection); OnMessageReceived?.Invoke(OwnerConnection, msg); } } }
private void UpdatePendingClient(PendingClient pendingClient) { if (!started) { return; } if (serverSettings.BanList.IsBanned(pendingClient.SteamID, out string banReason)) { RemovePendingClient(pendingClient, DisconnectReason.Banned, banReason); return; } //DebugConsole.NewMessage("pending client status: " + pendingClient.InitializationStep); if (connectedClients.Count >= serverSettings.MaxPlayers - 1) { RemovePendingClient(pendingClient, DisconnectReason.ServerFull, ""); } if (pendingClient.InitializationStep == ConnectionInitialization.Success) { SteamP2PConnection newConnection = new SteamP2PConnection(pendingClient.Name, pendingClient.SteamID) { Status = NetworkConnectionStatus.Connected }; connectedClients.Add(newConnection); pendingClients.Remove(pendingClient); OnInitializationComplete?.Invoke(newConnection); } pendingClient.TimeOut -= Timing.Step; if (pendingClient.TimeOut < 0.0) { RemovePendingClient(pendingClient, DisconnectReason.Unknown, Lidgren.Network.NetConnection.NoResponseMessage); } if (Timing.TotalTime < pendingClient.UpdateTime) { return; } pendingClient.UpdateTime = Timing.TotalTime + 1.0; IWriteMessage outMsg = new WriteOnlyMessage(); outMsg.Write(pendingClient.SteamID); outMsg.Write((byte)DeliveryMethod.Reliable); outMsg.Write((byte)(PacketHeader.IsConnectionInitializationStep | PacketHeader.IsServerMessage)); outMsg.Write((byte)pendingClient.InitializationStep); switch (pendingClient.InitializationStep) { case ConnectionInitialization.ContentPackageOrder: var mpContentPackages = GameMain.SelectedPackages.Where(cp => cp.HasMultiplayerIncompatibleContent).ToList(); outMsg.WriteVariableUInt32((UInt32)mpContentPackages.Count); for (int i = 0; i < mpContentPackages.Count; i++) { outMsg.Write(mpContentPackages[i].MD5hash.Hash); } break; case ConnectionInitialization.Password: outMsg.Write(pendingClient.PasswordSalt == null); outMsg.WritePadBits(); if (pendingClient.PasswordSalt == null) { pendingClient.PasswordSalt = Lidgren.Network.CryptoRandom.Instance.Next(); outMsg.Write(pendingClient.PasswordSalt.Value); } else { outMsg.Write(pendingClient.Retries); } break; } byte[] msgToSend = (byte[])outMsg.Buffer.Clone(); Array.Resize(ref msgToSend, outMsg.LengthBytes); ChildServerRelay.Write(msgToSend); }