示例#1
0
        /// <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);
            }
        }
示例#2
0
        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);
        }
示例#3
0
        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;
            }
        }
示例#4
0
        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;
            }
        }