Beispiel #1
0
        public virtual bool Read(IReadMessage msg, bool discardData = false)
        {
            if (!CanReceive)
            {
                throw new Exception("Called Read on a VoipQueue not set up for receiving");
            }

            UInt16 incLatestBufferID = msg.ReadUInt16();

            if ((firstRead || NetIdUtils.IdMoreRecent(incLatestBufferID, LatestBufferID)) && !discardData)
            {
                ForceLocal = msg.ReadBoolean(); msg.ReadPadBits();

                firstRead = false;
                for (int i = 0; i < BUFFER_COUNT; i++)
                {
                    bufferLengths[i] = msg.ReadByte();
                    buffers[i]       = msg.ReadBytes(bufferLengths[i]);
                }
                newestBufferInd = BUFFER_COUNT - 1;
                LatestBufferID  = incLatestBufferID;
                LastReadTime    = DateTime.Now;
                return(true);
            }
            else
            {
                msg.ReadBoolean(); msg.ReadPadBits();
                for (int i = 0; i < BUFFER_COUNT; i++)
                {
                    byte len = msg.ReadByte();
                    msg.BitPosition += len * 8;
                }
                return(false);
            }
        }
Beispiel #2
0
            public void ReadBytes(IReadMessage inc, int bytesToRead)
            {
                if (Received + bytesToRead > FileSize)
                {
                    //strip out excess bytes
                    bytesToRead -= Received + bytesToRead - FileSize;
                }

                byte[] all = inc.ReadBytes(bytesToRead);
                Received += all.Length;
                WriteStream.Write(all, 0, all.Length);

                int   passed = Environment.TickCount - TimeStarted;
                float psec   = passed / 1000.0f;

                if (GameSettings.VerboseLogging)
                {
                    DebugConsole.Log("Received " + all.Length + " bytes of the file " + FileName + " (" + Received + "/" + FileSize + " received)");
                }

                BytesPerSecond = Received / psec;

                Status = Received >= FileSize ? FileTransferStatus.Finished : FileTransferStatus.Receiving;
            }
        private void ReadConnectionInitializationStep(PendingClient pendingClient, IReadMessage inc)
        {
            if (netServer == null)
            {
                return;
            }

            pendingClient.TimeOut = NetworkConnection.TimeoutThreshold;

            ConnectionInitialization initializationStep = (ConnectionInitialization)inc.ReadByte();

            //DebugConsole.NewMessage(initializationStep+" "+pendingClient.InitializationStep);

            if (pendingClient.InitializationStep != initializationStep)
            {
                return;
            }

            pendingClient.UpdateTime = Timing.TotalTime + Timing.Step;

            switch (initializationStep)
            {
            case ConnectionInitialization.SteamTicketAndVersion:
                string name         = Client.SanitizeName(inc.ReadString());
                UInt64 steamId      = inc.ReadUInt64();
                UInt16 ticketLength = inc.ReadUInt16();
                inc.BitPosition += ticketLength * 8;     //skip ticket, owner handles steam authentication

                if (!Client.IsValidName(name, serverSettings))
                {
                    RemovePendingClient(pendingClient, DisconnectReason.InvalidName, "The name \"" + name + "\" is invalid");
                    return;
                }

                string version             = inc.ReadString();
                bool   isCompatibleVersion = NetworkMember.IsCompatible(version, GameMain.Version.ToString()) ?? false;
                if (!isCompatibleVersion)
                {
                    RemovePendingClient(pendingClient, DisconnectReason.InvalidVersion,
                                        $"DisconnectMessage.InvalidVersion~[version]={GameMain.Version.ToString()}~[clientversion]={version}");

                    GameServer.Log(name + " (" + pendingClient.SteamID.ToString() + ") couldn't join the server (incompatible game version)", ServerLog.MessageType.Error);
                    DebugConsole.NewMessage(name + " (" + pendingClient.SteamID.ToString() + ") couldn't join the server (incompatible game version)", Microsoft.Xna.Framework.Color.Red);
                    return;
                }

                int contentPackageCount = (int)inc.ReadVariableUInt32();
                List <ClientContentPackage> clientContentPackages = new List <ClientContentPackage>();
                for (int i = 0; i < contentPackageCount; i++)
                {
                    string packageName = inc.ReadString();
                    string packageHash = inc.ReadString();
                    clientContentPackages.Add(new ClientContentPackage(packageName, packageHash));
                }

                //check if the client is missing any of our packages
                List <ContentPackage> missingPackages = new List <ContentPackage>();
                foreach (ContentPackage serverContentPackage in GameMain.SelectedPackages)
                {
                    if (!serverContentPackage.HasMultiplayerIncompatibleContent)
                    {
                        continue;
                    }
                    bool packageFound = clientContentPackages.Any(cp => cp.Name == serverContentPackage.Name && cp.Hash == serverContentPackage.MD5hash.Hash);
                    if (!packageFound)
                    {
                        missingPackages.Add(serverContentPackage);
                    }
                }

                //check if the client is using packages we don't have
                List <ClientContentPackage> redundantPackages = new List <ClientContentPackage>();
                foreach (ClientContentPackage clientContentPackage in clientContentPackages)
                {
                    bool packageFound = GameMain.SelectedPackages.Any(cp => cp.Name == clientContentPackage.Name && cp.MD5hash.Hash == clientContentPackage.Hash);
                    if (!packageFound)
                    {
                        redundantPackages.Add(clientContentPackage);
                    }
                }

                if (missingPackages.Count == 1)
                {
                    RemovePendingClient(pendingClient, DisconnectReason.MissingContentPackage,
                                        $"DisconnectMessage.MissingContentPackage~[missingcontentpackage]={GetPackageStr(missingPackages[0])}");
                    GameServer.Log(name + " (" + pendingClient.SteamID + ") couldn't join the server (missing content package " + GetPackageStr(missingPackages[0]) + ")", ServerLog.MessageType.Error);
                    return;
                }
                else if (missingPackages.Count > 1)
                {
                    List <string> packageStrs = new List <string>();
                    missingPackages.ForEach(cp => packageStrs.Add(GetPackageStr(cp)));
                    RemovePendingClient(pendingClient, DisconnectReason.MissingContentPackage,
                                        $"DisconnectMessage.MissingContentPackages~[missingcontentpackages]={string.Join(", ", packageStrs)}");
                    GameServer.Log(name + " (" + pendingClient.SteamID + ") couldn't join the server (missing content packages " + string.Join(", ", packageStrs) + ")", ServerLog.MessageType.Error);
                    return;
                }
                if (redundantPackages.Count == 1)
                {
                    RemovePendingClient(pendingClient, DisconnectReason.IncompatibleContentPackage,
                                        $"DisconnectMessage.IncompatibleContentPackage~[incompatiblecontentpackage]={GetPackageStr(redundantPackages[0])}");
                    GameServer.Log(name + " (" + pendingClient.SteamID + ") couldn't join the server (using an incompatible content package " + GetPackageStr(redundantPackages[0]) + ")", ServerLog.MessageType.Error);
                    return;
                }
                if (redundantPackages.Count > 1)
                {
                    List <string> packageStrs = new List <string>();
                    redundantPackages.ForEach(cp => packageStrs.Add(GetPackageStr(cp)));
                    RemovePendingClient(pendingClient, DisconnectReason.IncompatibleContentPackage,
                                        $"DisconnectMessage.IncompatibleContentPackages~[incompatiblecontentpackages]={string.Join(", ", packageStrs)}");
                    GameServer.Log(name + " (" + pendingClient.SteamID + ") couldn't join the server (using incompatible content packages " + string.Join(", ", packageStrs) + ")", ServerLog.MessageType.Error);
                    return;
                }

                if (!pendingClient.AuthSessionStarted)
                {
                    pendingClient.InitializationStep = serverSettings.HasPassword ? ConnectionInitialization.Password: ConnectionInitialization.Success;

                    pendingClient.Name = name;
                    pendingClient.AuthSessionStarted = true;
                }
                break;

            case ConnectionInitialization.Password:
                int    pwLength    = inc.ReadByte();
                byte[] incPassword = inc.ReadBytes(pwLength);
                if (pendingClient.PasswordSalt == null)
                {
                    DebugConsole.ThrowError("Received password message from client without salt");
                    return;
                }
                if (serverSettings.IsPasswordCorrect(incPassword, pendingClient.PasswordSalt.Value))
                {
                    pendingClient.InitializationStep = ConnectionInitialization.Success;
                }
                else
                {
                    pendingClient.Retries++;

                    if (pendingClient.Retries >= 3)
                    {
                        string banMsg = "Failed to enter correct password too many times";
                        serverSettings.BanList.BanPlayer(pendingClient.Name, pendingClient.SteamID, banMsg, null);

                        RemovePendingClient(pendingClient, DisconnectReason.Banned, banMsg);
                        return;
                    }
                }
                pendingClient.UpdateTime = Timing.TotalTime;
                break;
            }
        }
        /// <summary>
        /// Read the events from the message, ignoring ones we've already received
        /// </summary>
        public void Read(IReadMessage msg, Client sender = null)
        {
            UInt16 firstEventID = msg.ReadUInt16();
            int    eventCount   = msg.ReadByte();

            for (int i = 0; i < eventCount; i++)
            {
                UInt16 thisEventID = (UInt16)(firstEventID + (UInt16)i);
                UInt16 entityID    = msg.ReadUInt16();

                if (entityID == Entity.NullEntityID)
                {
                    msg.ReadPadBits();
                    if (thisEventID == (UInt16)(sender.LastSentEntityEventID + 1))
                    {
                        sender.LastSentEntityEventID++;
                    }
                    continue;
                }

                int msgLength = (int)msg.ReadVariableUInt32();

                IClientSerializable entity = Entity.FindEntityByID(entityID) as IClientSerializable;

                //skip the event if we've already received it
                if (thisEventID != (UInt16)(sender.LastSentEntityEventID + 1))
                {
                    if (GameSettings.VerboseLogging)
                    {
                        DebugConsole.NewMessage("Received msg " + thisEventID + ", expecting " + sender.LastSentEntityEventID, Color.Red);
                    }
                    msg.BitPosition += msgLength * 8;
                }
                else if (entity == null)
                {
                    //entity not found -> consider the even read and skip over it
                    //(can happen, for example, when a client uses a medical item repeatedly
                    //and creates an event for it before receiving the event about it being removed)
                    if (GameSettings.VerboseLogging)
                    {
                        DebugConsole.NewMessage(
                            "Received msg " + thisEventID + ", entity " + entityID + " not found",
                            Microsoft.Xna.Framework.Color.Orange);
                    }
                    sender.LastSentEntityEventID++;
                    msg.BitPosition += msgLength * 8;
                }
                else
                {
                    if (GameSettings.VerboseLogging)
                    {
                        DebugConsole.NewMessage("Received msg " + thisEventID, Microsoft.Xna.Framework.Color.Green);
                    }

                    UInt16 characterStateID = msg.ReadUInt16();

                    ReadWriteMessage buffer = new ReadWriteMessage();
                    byte[]           temp   = msg.ReadBytes(msgLength - 2);
                    buffer.Write(temp, 0, msgLength - 2);
                    buffer.BitPosition = 0;
                    BufferEvent(new BufferedEvent(sender, sender.Character, characterStateID, entity, buffer));

                    sender.LastSentEntityEventID++;
                }
                msg.ReadPadBits();
            }
        }
Beispiel #5
0
        protected void ReadConnectionInitializationStep(PendingClient pendingClient, IReadMessage inc)
        {
            pendingClient.TimeOut = NetworkConnection.TimeoutThreshold;

            ConnectionInitialization initializationStep = (ConnectionInitialization)inc.ReadByte();

            if (pendingClient.InitializationStep != initializationStep)
            {
                return;
            }

            pendingClient.UpdateTime = Timing.TotalTime + Timing.Step;

            switch (initializationStep)
            {
            case ConnectionInitialization.SteamTicketAndVersion:
                string name         = Client.SanitizeName(inc.ReadString());
                int    ownerKey     = inc.ReadInt32();
                UInt64 steamId      = inc.ReadUInt64();
                UInt16 ticketLength = inc.ReadUInt16();
                byte[] ticketBytes  = inc.ReadBytes(ticketLength);

                if (!Client.IsValidName(name, serverSettings))
                {
                    RemovePendingClient(pendingClient, DisconnectReason.InvalidName, "");
                    return;
                }

                string version             = inc.ReadString();
                bool   isCompatibleVersion = NetworkMember.IsCompatible(version, GameMain.Version.ToString()) ?? false;
                if (!isCompatibleVersion)
                {
                    RemovePendingClient(pendingClient, DisconnectReason.InvalidVersion,
                                        $"DisconnectMessage.InvalidVersion~[version]={GameMain.Version}~[clientversion]={version}");

                    GameServer.Log(name + " (" + pendingClient.SteamID.ToString() + ") couldn't join the server (incompatible game version)", ServerLog.MessageType.Error);
                    DebugConsole.NewMessage(name + " (" + pendingClient.SteamID.ToString() + ") couldn't join the server (incompatible game version)", Microsoft.Xna.Framework.Color.Red);
                    return;
                }

                string language = inc.ReadString();
                pendingClient.Connection.Language = language;

                Client nameTaken = GameMain.Server.ConnectedClients.Find(c => Homoglyphs.Compare(c.Name.ToLower(), name.ToLower()));
                if (nameTaken != null)
                {
                    RemovePendingClient(pendingClient, DisconnectReason.NameTaken, "");
                    GameServer.Log(name + " (" + pendingClient.SteamID.ToString() + ") couldn't join the server (name too similar to the name of the client \"" + nameTaken.Name + "\").", ServerLog.MessageType.Error);
                    return;
                }

                if (!pendingClient.AuthSessionStarted)
                {
                    ProcessAuthTicket(name, ownerKey, steamId, pendingClient, ticketBytes);
                }
                break;

            case ConnectionInitialization.Password:
                int    pwLength    = inc.ReadByte();
                byte[] incPassword = inc.ReadBytes(pwLength);
                if (pendingClient.PasswordSalt == null)
                {
                    DebugConsole.ThrowError("Received password message from client without salt");
                    return;
                }
                if (serverSettings.IsPasswordCorrect(incPassword, pendingClient.PasswordSalt.Value))
                {
                    pendingClient.InitializationStep = ConnectionInitialization.ContentPackageOrder;
                }
                else
                {
                    pendingClient.Retries++;
                    if (serverSettings.BanAfterWrongPassword && pendingClient.Retries > serverSettings.MaxPasswordRetriesBeforeBan)
                    {
                        string banMsg = "Failed to enter correct password too many times";
                        BanPendingClient(pendingClient, banMsg, null);

                        RemovePendingClient(pendingClient, DisconnectReason.Banned, banMsg);
                        return;
                    }
                }
                pendingClient.UpdateTime = Timing.TotalTime;
                break;

            case ConnectionInitialization.ContentPackageOrder:
                pendingClient.InitializationStep = ConnectionInitialization.Success;
                pendingClient.UpdateTime         = Timing.TotalTime;
                break;
            }
        }