/// <summary> /// Write the events to the outgoing message. The recipient parameter is only needed for ServerEntityEventManager /// </summary> protected void Write(IWriteMessage msg, List <NetEntityEvent> eventsToSync, out List <NetEntityEvent> sentEvents, Client recipient = null) { //write into a temporary buffer so we can write the number of events before the actual data IWriteMessage tempBuffer = new WriteOnlyMessage(); sentEvents = new List <NetEntityEvent>(); int eventCount = 0; foreach (NetEntityEvent e in eventsToSync) { //write into a temporary buffer so we can write the length before the actual data IWriteMessage tempEventBuffer = new WriteOnlyMessage(); try { WriteEvent(tempEventBuffer, e, recipient); } catch (Exception exception) { DebugConsole.ThrowError("Failed to write an event for the entity \"" + e.Entity + "\"", exception); GameAnalyticsManager.AddErrorEventOnce("NetEntityEventManager.Write:WriteFailed" + e.Entity.ToString(), GameAnalyticsSDK.Net.EGAErrorSeverity.Error, "Failed to write an event for the entity \"" + e.Entity + "\"\n" + exception.StackTrace.CleanupStackTrace()); //write an empty event to avoid messing up IDs //(otherwise the clients might read the next event in the message and think its ID //is consecutive to the previous one, even though we skipped over this broken event) tempBuffer.Write(Entity.NullEntityID); tempBuffer.WritePadBits(); eventCount++; continue; } if (eventCount > 0 && msg.LengthBytes + tempBuffer.LengthBytes + tempEventBuffer.LengthBytes > MaxEventBufferLength) { //no more room in this packet break; } tempBuffer.Write(e.EntityID); tempBuffer.WriteVariableUInt32((uint)tempEventBuffer.LengthBytes); tempBuffer.Write(tempEventBuffer.Buffer, 0, tempEventBuffer.LengthBytes); tempBuffer.WritePadBits(); sentEvents.Add(e); eventCount++; } if (eventCount > 0) { msg.Write(eventsToSync[0].ID); msg.Write((byte)eventCount); msg.Write(tempBuffer.Buffer, 0, tempBuffer.LengthBytes); } }
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); }
private void ReadConnectionInitializationStep(IReadMessage inc) { if (!isActive) { return; } ConnectionInitialization step = (ConnectionInitialization)inc.ReadByte(); IWriteMessage outMsg; //DebugConsole.NewMessage(step + " " + initializationStep); switch (step) { case ConnectionInitialization.SteamTicketAndVersion: if (initializationStep != ConnectionInitialization.SteamTicketAndVersion) { return; } outMsg = new WriteOnlyMessage(); outMsg.Write((byte)DeliveryMethod.Reliable); outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep); outMsg.Write((byte)ConnectionInitialization.SteamTicketAndVersion); outMsg.Write(Name); outMsg.Write(SteamManager.GetSteamID()); outMsg.Write((UInt16)steamAuthTicket.Data.Length); outMsg.Write(steamAuthTicket.Data, 0, steamAuthTicket.Data.Length); outMsg.Write(GameMain.Version.ToString()); IEnumerable <ContentPackage> mpContentPackages = GameMain.SelectedPackages.Where(cp => cp.HasMultiplayerIncompatibleContent); outMsg.WriteVariableUInt32((UInt32)mpContentPackages.Count()); foreach (ContentPackage contentPackage in mpContentPackages) { outMsg.Write(contentPackage.Name); outMsg.Write(contentPackage.MD5hash.Hash); } heartbeatTimer = 5.0; Steamworks.SteamNetworking.SendP2PPacket(hostSteamId, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Reliable); sentBytes += outMsg.LengthBytes; break; case ConnectionInitialization.ContentPackageOrder: if (initializationStep == ConnectionInitialization.SteamTicketAndVersion || initializationStep == ConnectionInitialization.Password) { initializationStep = ConnectionInitialization.ContentPackageOrder; } if (initializationStep != ConnectionInitialization.ContentPackageOrder) { return; } outMsg = new WriteOnlyMessage(); outMsg.Write((byte)DeliveryMethod.Reliable); outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep); outMsg.Write((byte)ConnectionInitialization.ContentPackageOrder); UInt32 cpCount = inc.ReadVariableUInt32(); List <ContentPackage> serverContentPackages = new List <ContentPackage>(); for (int i = 0; i < cpCount; i++) { string hash = inc.ReadString(); serverContentPackages.Add(GameMain.Config.SelectedContentPackages.Find(cp => cp.MD5hash.Hash == hash)); } if (!contentPackageOrderReceived) { GameMain.Config.ReorderSelectedContentPackages(cp => serverContentPackages.Contains(cp) ? serverContentPackages.IndexOf(cp) : serverContentPackages.Count + GameMain.Config.SelectedContentPackages.IndexOf(cp)); contentPackageOrderReceived = true; } Steamworks.SteamNetworking.SendP2PPacket(hostSteamId, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Reliable); sentBytes += outMsg.LengthBytes; break; case ConnectionInitialization.Password: if (initializationStep == ConnectionInitialization.SteamTicketAndVersion) { initializationStep = ConnectionInitialization.Password; } if (initializationStep != ConnectionInitialization.Password) { return; } bool incomingSalt = inc.ReadBoolean(); inc.ReadPadBits(); int retries = 0; if (incomingSalt) { passwordSalt = inc.ReadInt32(); } else { retries = inc.ReadInt32(); } OnRequestPassword?.Invoke(passwordSalt, retries); break; } }
protected void UpdatePendingClient(PendingClient pendingClient) { if (IsPendingClientBanned(pendingClient, out string banReason)) { RemovePendingClient(pendingClient, DisconnectReason.Banned, banReason); return; } if (connectedClients.Count >= serverSettings.MaxPlayers - 1) { RemovePendingClient(pendingClient, DisconnectReason.ServerFull, ""); } if (pendingClient.InitializationStep == ConnectionInitialization.Success) { NetworkConnection newConnection = pendingClient.Connection; connectedClients.Add(newConnection); pendingClients.Remove(pendingClient); CheckOwnership(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((byte)(PacketHeader.IsConnectionInitializationStep | PacketHeader.IsServerMessage)); outMsg.Write((byte)pendingClient.InitializationStep); switch (pendingClient.InitializationStep) { case ConnectionInitialization.ContentPackageOrder: outMsg.Write(GameMain.Server.ServerName); var mpContentPackages = GameMain.Config.AllEnabledPackages.Where(cp => cp.HasMultiplayerIncompatibleContent).ToList(); outMsg.WriteVariableUInt32((UInt32)mpContentPackages.Count); for (int i = 0; i < mpContentPackages.Count; i++) { outMsg.Write(mpContentPackages[i].Name); outMsg.Write(mpContentPackages[i].MD5hash.Hash); outMsg.Write(mpContentPackages[i].SteamWorkshopId); } 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; } SendMsgInternal(pendingClient.Connection, DeliveryMethod.Reliable, outMsg); }
private void ReadConnectionInitializationStep(IReadMessage inc) { if (!isActive) { return; } ConnectionInitialization step = (ConnectionInitialization)inc.ReadByte(); //DebugConsole.NewMessage(step + " " + initializationStep); switch (step) { case ConnectionInitialization.SteamTicketAndVersion: if (initializationStep != ConnectionInitialization.SteamTicketAndVersion) { return; } IWriteMessage outMsg = new WriteOnlyMessage(); outMsg.Write((byte)DeliveryMethod.Reliable); outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep); outMsg.Write((byte)ConnectionInitialization.SteamTicketAndVersion); outMsg.Write(Name); outMsg.Write(SteamManager.GetSteamID()); outMsg.Write((UInt16)steamAuthTicket.Data.Length); outMsg.Write(steamAuthTicket.Data, 0, steamAuthTicket.Data.Length); outMsg.Write(GameMain.Version.ToString()); IEnumerable <ContentPackage> mpContentPackages = GameMain.SelectedPackages.Where(cp => cp.HasMultiplayerIncompatibleContent); outMsg.WriteVariableUInt32((UInt32)mpContentPackages.Count()); foreach (ContentPackage contentPackage in mpContentPackages) { outMsg.Write(contentPackage.Name); outMsg.Write(contentPackage.MD5hash.Hash); } heartbeatTimer = 5.0; SteamManager.Instance.Networking.SendP2PPacket(hostSteamId, outMsg.Buffer, outMsg.LengthBytes, Facepunch.Steamworks.Networking.SendType.Reliable); break; case ConnectionInitialization.Password: if (initializationStep == ConnectionInitialization.SteamTicketAndVersion) { initializationStep = ConnectionInitialization.Password; } if (initializationStep != ConnectionInitialization.Password) { return; } bool incomingSalt = inc.ReadBoolean(); inc.ReadPadBits(); int retries = 0; if (incomingSalt) { passwordSalt = inc.ReadInt32(); } else { retries = inc.ReadInt32(); } OnRequestPassword?.Invoke(passwordSalt, retries); break; } }