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); } }
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(); } }
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; } }