public override void Dispatch(IPacketWrapper wrapper) { if (wrapper.Packet.Origin == PacketOrigin.Client && wrapper.Packet.Type == PacketType.Response) { FrostbitePacket requestPacket = this.PacketQueue.GetRequestPacket(wrapper) as FrostbitePacket; // If the request packet is valid and has at least one word. if (requestPacket != null && requestPacket.Packet.Words.Count >= 1) { // If the sent command was successful if (wrapper.Packet.Words.Count >= 1 && String.CompareOrdinal(wrapper.Packet.Words[0], FrostbitePacket.StringResponseOkay) == 0) { this.Dispatch(new PacketDispatch() { Name = requestPacket.Packet.Words[0], Origin = requestPacket.Packet.Origin }, requestPacket, wrapper); } else { // The command sent failed for some reason. this.Dispatch(new PacketDispatch() { Name = wrapper.Packet.Words[0], Origin = wrapper.Packet.Origin }, requestPacket, wrapper); } } } else if (wrapper.Packet.Words.Count >= 1 && wrapper.Packet.Origin == PacketOrigin.Server && wrapper.Packet.Type == PacketType.Request) { this.Dispatch(new PacketDispatch() { Name = wrapper.Packet.Words[0], Origin = wrapper.Packet.Origin }, wrapper, null); } }
public override IPacket Send(IPacketWrapper wrapper) { IPacket sent = null; if (wrapper.Packet.RequestId == null) { wrapper.Packet.RequestId = this.AcquireSequenceNumber; } // QueueUnqueuePacket if (wrapper.Packet.Origin == PacketOrigin.Server && wrapper.Packet.Type == PacketType.Response) { // I don't think this will ever be encountered since OnPacketReceived calls the base.Send. sent = base.Send(wrapper); } else { // Null return because we're not popping a packet, just checking to see if this one needs to be queued. IPacketWrapper poppedWrapper = null; if ((poppedWrapper = this.PacketQueue.PacketSend(wrapper)) != null) { sent = base.Send(poppedWrapper); } // Shutdown if we're just waiting for a response to an old packet. if (this.PacketQueue.RestartConnectionOnQueueFailure() == true) { this.Shutdown(new Exception("Failed to hear response to packet within two minutes, forced shutdown.")); } } return sent; }
protected override void OnPacketReceived(IPacketWrapper wrapper) { base.OnPacketReceived(wrapper); // Respond with "OK" to all server events. if (wrapper.Packet.Origin == PacketOrigin.Server && wrapper.Packet.Type == PacketType.Request) { base.Send(new FrostbitePacket() { Packet = { Origin = PacketOrigin.Server, Type = PacketType.Response, RequestId = wrapper.Packet.RequestId, Words = new List<String>() { FrostbitePacket.StringResponseOkay } } }); } // Pop the next packet if a packet is waiting to be sent. IPacketWrapper poppedWrapper = null; if ((poppedWrapper = this.PacketQueue.PacketReceived(wrapper)) != null) { this.Send(poppedWrapper); } // Shutdown if we're just waiting for a response to an old packet. if (this.PacketQueue.RestartConnectionOnQueueFailure() == true) { this.Shutdown(new Exception("Failed to hear response to packet within two minutes, forced shutdown.")); } }
/// <summary> /// Serializes a packet into an array of bytes to send to the server. /// </summary> /// <param name="wrapper">The packe to serialize</param> /// <returns>An array of bytes to send to the server.</returns> public byte[] Serialize(IPacketWrapper wrapper) { FrostbitePacket frostbiteWrapper = wrapper as FrostbitePacket; byte[] serialized = null; if (frostbiteWrapper != null) { // Construct the header uint32 UInt32 header = frostbiteWrapper.Packet.RequestId != null ? (UInt32)frostbiteWrapper.Packet.RequestId & 0x3fffffff : 0x3fffffff; if (frostbiteWrapper.Packet.Origin == PacketOrigin.Server) { header |= 0x80000000; } if (frostbiteWrapper.Packet.Type == PacketType.Response) { header |= 0x40000000; } // Construct the remaining packet headers UInt32 packetSize = this.PacketHeaderSize; UInt32 wordCount = Convert.ToUInt32(frostbiteWrapper.Packet.Words.Count); // Encode each word (WordLength, Word Bytes, Null Byte) byte[] encodedWords = new byte[] { }; foreach (string word in frostbiteWrapper.Packet.Words) { string convertedWord = word; // Truncate words over 64 kbs (though the string is Unicode it gets converted below so this does make sense) if (convertedWord.Length > UInt16.MaxValue - 1) { convertedWord = convertedWord.Substring(0, UInt16.MaxValue - 1); } byte[] appendEncodedWords = new byte[encodedWords.Length + convertedWord.Length + 5]; encodedWords.CopyTo(appendEncodedWords, 0); BitConverter.GetBytes(convertedWord.Length).CopyTo(appendEncodedWords, encodedWords.Length); Encoding.GetEncoding(1252).GetBytes(convertedWord + Convert.ToChar(0x00)).CopyTo(appendEncodedWords, encodedWords.Length + 4); encodedWords = appendEncodedWords; } // Get the full size of the packet. packetSize += Convert.ToUInt32(encodedWords.Length); // Now compile the whole packet. serialized = new byte[packetSize]; BitConverter.GetBytes(header).CopyTo(serialized, 0); BitConverter.GetBytes(packetSize).CopyTo(serialized, 4); BitConverter.GetBytes(wordCount).CopyTo(serialized, 8); encodedWords.CopyTo(serialized, this.PacketHeaderSize); wrapper.Packet.Data = serialized; wrapper.Packet.Text = String.Join(" ", wrapper.Packet.Words); wrapper.Packet.DebugText = String.Join(" ", wrapper.Packet.Words.Select((word, index) => String.Format("[{0}-{1}]", index, word))); } return serialized; }
public override void Dispatch(IPacketWrapper wrapper) { base.Dispatch(wrapper); this.Dispatch(new PacketDispatch() { Name = wrapper.Packet.Words[0], Origin = wrapper.Packet.Origin }, wrapper, wrapper); }
public void ServerOnLevelLoadedDispatchHandler(IPacketWrapper request, IPacketWrapper response) { if (request.Packet.Words.Count >= 5) { int currentRound = 0, totalRounds = 0; if (int.TryParse(request.Packet.Words[3], out currentRound) == true && int.TryParse(request.Packet.Words[4], out totalRounds) == true) { this.UpdateSettingsMap(request.Packet.Words[1], request.Packet.Words[2]); this.UpdateSettingsRound(currentRound, totalRounds); } } }
/// <summary> /// Fetches the packet that initiated the request. /// </summary> /// <param name="recievedWrapper">The response packet</param> /// <returns>The request packet</returns> public IPacketWrapper GetRequestPacket(IPacketWrapper recievedWrapper) { IPacketWrapper requestPacket = null; if (recievedWrapper.Packet.RequestId != null && this.OutgoingPackets.ContainsKey(recievedWrapper.Packet.RequestId) == true) { requestPacket = this.OutgoingPackets[recievedWrapper.Packet.RequestId]; } return requestPacket; }
/// <summary> /// Dequeues the current packet. If a packet is returned then it should be sent /// </summary> /// <param name="wrapper"></param> /// <returns></returns> public IPacketWrapper PacketReceived(IPacketWrapper wrapper) { IPacketWrapper poppedWrapper = null; // Pop the next packet if a packet is waiting to be sent. if (wrapper != null && wrapper.Packet.RequestId != null) { if (this.OutgoingPackets.ContainsKey(wrapper.Packet.RequestId) == true) { IPacketWrapper ignored = null; this.OutgoingPackets.TryRemove(wrapper.Packet.RequestId, out ignored); } } if (this.QueuedPackets.Count > 0) { this.QueuedPackets.TryDequeue(out poppedWrapper); } return poppedWrapper; }
public override IPacket Send(IPacketWrapper wrapper) { IPacket sent = null; if (wrapper != null) { if (this.BeforePacketSend(wrapper) == false && this.Client != null) { byte[] bytePacket = this.PacketSerializer.Serialize(wrapper); if (bytePacket != null && bytePacket.Length > 0) { this.Client.BeginSend(bytePacket, bytePacket.Length, this.RemoteEndPoint, this.SendAsynchronousCallback, wrapper); sent = wrapper.Packet; } } } return sent; }
public byte[] Serialize(IPacketWrapper wrapper) { MockPacket mockPacket = wrapper as MockPacket; byte[] serialized = null; if (mockPacket != null) { if (mockPacket.Packet.RequestId == null) mockPacket.Packet.RequestId = 111; serialized = new byte[this.PacketHeaderSize + mockPacket.Text.Length]; BitConverter.GetBytes((int)mockPacket.Packet.Origin).CopyTo(serialized, 0); BitConverter.GetBytes((int)mockPacket.Packet.Type).CopyTo(serialized, 4); BitConverter.GetBytes(mockPacket.Packet.RequestId.Value).CopyTo(serialized, 8); BitConverter.GetBytes(mockPacket.Text.Length).CopyTo(serialized, 12); Encoding.ASCII.GetBytes(mockPacket.Text).CopyTo(serialized, this.PacketHeaderSize); mockPacket.Packet.DebugText = String.Format("{0} {1} {2} {3}", mockPacket.Packet.Origin, mockPacket.Packet.Type, mockPacket.Packet.RequestId, mockPacket.Packet.Text); } return serialized; }
public void PunkBusterOnMessageDispatchHandler(IPacketWrapper request, IPacketWrapper response) { if (request.Packet.Words.Count >= 1) { IPunkBuster pbObject = PunkBusterSerializer.Deserialize(request.Packet.Words[1]); if (pbObject is PunkBusterPlayer) { PunkBusterPlayer player = pbObject as PunkBusterPlayer; PlayerModel statePlayer = this.State.Players.Select(p => p.Value).FirstOrDefault(p => p.Name == player.Name); if (statePlayer != null) { statePlayer.SlotId = player.SlotId; statePlayer.Ip = player.Ip; Location location = FrostbiteGame.Geolocation.Locate(statePlayer.Ip); if (location != null) { statePlayer.Location = location; } } } else if (pbObject is PunkBusterBeginPlayerList) { } else if (pbObject is PunkBusterEndPlayerList) { this.OnProtocolEvent(ProtocolEventType.ProtocolPlayerlistUpdated, new ProtocolStateDifference()); } } }
public override void AdminListPlayersResponseDispatchHandler(IPacketWrapper request, IPacketWrapper response) { List<PlayerModel> players = SecondFrostbitePlayerList.Parse(response.Packet.Words.GetRange(1, response.Packet.Words.Count - 1)); this.AdminListPlayersFinalize(players); }
public override void PlayerOnAuthenticatedDispatchHandler(IPacketWrapper request, IPacketWrapper response) { // Ignored. }
public override void MapListListDispatchHandler(IPacketWrapper request, IPacketWrapper response) { if (request.Packet.Words.Count >= 1) { ConcurrentDictionary<String, MapModel> modified = new ConcurrentDictionary<String, MapModel>(); List<MapModel> maps = SecondFrostbiteMapList.Parse(response.Packet.Words.GetRange(1, response.Packet.Words.Count - 1)); foreach (MapModel map in maps) { var closureMap = map; MapModel mapInfo = this.State.MapPool.Values.FirstOrDefault(m => String.Compare(m.Name, closureMap.Name, StringComparison.OrdinalIgnoreCase) == 0 && String.Compare(m.GameMode.Name, closureMap.GameMode.Name, StringComparison.OrdinalIgnoreCase) == 0); if (mapInfo != null) { closureMap.FriendlyName = mapInfo.FriendlyName; closureMap.GameMode = mapInfo.GameMode; } modified.AddOrUpdate(String.Format("{0}/{1}", closureMap.GameMode.Name, closureMap.Name), id => closureMap, (id, model) => closureMap); } IProtocolStateDifference difference = new ProtocolStateDifference() { Override = true, Modified = { Maps = modified } }; this.ApplyProtocolStateDifference(difference); this.OnProtocolEvent( ProtocolEventType.ProtocolMaplistUpdated, difference ); } }
public override void PlayerOnJoinDispatchHandler(IPacketWrapper request, IPacketWrapper response) { if (request.Packet.Words.Count >= 2) { PlayerModel player = new PlayerModel() { Name = request.Packet.Words[1], Uid = request.Packet.Words[2] }; IProtocolStateDifference difference = new ProtocolStateDifference() { Modified = { Players = new ConcurrentDictionary<String, PlayerModel>(new Dictionary<String, PlayerModel>() { { player.Uid, player } }) } }; this.ApplyProtocolStateDifference(difference); this.OnProtocolEvent( ProtocolEventType.ProtocolPlayerJoin, difference, new ProtocolEventData() { Players = new List<PlayerModel>() { player } } ); } }
public virtual void Dispatch(IPacketWrapper packet) { }
public IPacket Send(IPacketWrapper packet) { return null; }
protected void client_PacketReceived(IClient sender, IPacketWrapper packet) { // Bubble the packet for processing. this.OnPacketReceived(sender, packet as MockPacket); }
/// <summary> /// Sends a packet to the server, provided a client exists and the connection is open and ready or logged in. /// This allows for the login command to be sent to a ready connection, otherwise no login packets could be sent. /// </summary> /// <param name="wrapper"></param> public virtual IPacket Send(IPacketWrapper wrapper) { IPacket sent = null; if (wrapper != null) { if (this.Client != null && (this.Client.ConnectionState == ConnectionState.ConnectionReady || this.Client.ConnectionState == ConnectionState.ConnectionLoggedIn)) { sent = this.Client.Send(wrapper); } } return sent; }
public void ServerOnLoadingLevelDispatchHandler(IPacketWrapper request, IPacketWrapper response) { if (request.Packet.Words.Count >= 4) { int currentRound = 0, totalRounds = 0; if (int.TryParse(request.Packet.Words[2], out currentRound) == true && int.TryParse(request.Packet.Words[3], out totalRounds) == true) { this.State.Settings.Current.RoundIndex = currentRound; this.State.Settings.Maximum.RoundIndex = totalRounds; // Maps are the same, only a round change if (String.Compare(this.State.Settings.Current.MapNameText, request.Packet.Words[1], StringComparison.OrdinalIgnoreCase) == 0) { IProtocolStateDifference difference = new ProtocolStateDifference() { Modified = { Settings = this.State.Settings } }; this.ApplyProtocolStateDifference(difference); this.OnProtocolEvent( ProtocolEventType.ProtocolRoundChanged, difference ); } else { MapModel selectedMap = this.State.MapPool.Select(m => m.Value).FirstOrDefault(x => String.Compare(x.Name, request.Packet.Words[1], StringComparison.OrdinalIgnoreCase) == 0); if (selectedMap != null) { this.State.Settings.Current.GameModeNameText = selectedMap.GameMode.Name; this.State.Settings.Current.FriendlyGameModeNameText = selectedMap.GameMode.FriendlyName; this.State.Settings.Current.FriendlyMapNameText = selectedMap.FriendlyName; } this.State.Settings.Current.MapNameText = request.Packet.Words[1]; IProtocolStateDifference difference = new ProtocolStateDifference() { Modified = { Settings = this.State.Settings } }; this.ApplyProtocolStateDifference(difference); this.OnProtocolEvent( ProtocolEventType.ProtocolMapChanged, difference ); } } } }
public IPacket Send(IPacketWrapper wrapper) { return null; }
public IPacket Send(IPacketWrapper packet) { return this.SandboxedProtocol != null ? this.SandboxedProtocol.Send(packet) : null; }
public byte[] Serialize(IPacketWrapper wrapper) { CommandServerPacket commandServerWrapper = wrapper as CommandServerPacket; byte[] serialized = null; if (commandServerWrapper != null) { byte[] content = this.SerializeContent(commandServerWrapper); byte[] header = this.SerializeHeader(commandServerWrapper, content); serialized = new byte[header.Length + content.Length]; Array.Copy(header, serialized, header.Length); Array.Copy(content, 0, serialized, header.Length, content.Length); } return serialized; }
public IPacket Send(IPacketWrapper packet) { return this.OnSendHandler != null ? this.OnSendHandler(packet) : null; }
/// <summary> /// Handles the player.onKill event sent from the server. /// This method holds for Battlefield 3/4, but may need an override in bfbc2. /// </summary> public override void PlayerOnKillDispatchHandler(IPacketWrapper request, IPacketWrapper response) { if (request.Packet.Words.Count >= 5) { bool headshot = false; if (bool.TryParse(request.Packet.Words[4], out headshot) == true) { ItemModel item = this.State.Items.Select(i => i.Value).FirstOrDefault(i => i.Name == Regex.Replace(request.Packet.Words[3], @"[^\w\/_-]+", "")) ?? new ItemModel() { Name = request.Packet.Words[3] }; var killer = this.State.Players.Select(p => p.Value).FirstOrDefault(p => p.Name == request.Packet.Words[1]); var victim = this.State.Players.Select(p => p.Value).FirstOrDefault(p => p.Name == request.Packet.Words[2]); if (killer != null && victim != null) { // Assign the item to the player, overwriting everything else attached to this killer. killer.Inventory.Now.Items.Clear(); killer.Inventory.Now.Items.Add(item); victim.Deaths++; // If this wasn't an inside job. if (killer.Uid != victim.Uid) { killer.Kills++; } var difference = new ProtocolStateDifference() { Modified = { Players = new ConcurrentDictionary<String, PlayerModel>() } }; difference.Modified.Players.AddOrUpdate(killer.Uid, id => killer, (id, model) => killer); difference.Modified.Players.AddOrUpdate(victim.Uid, id => victim, (id, model) => victim); this.ApplyProtocolStateDifference(difference); // We've updated the state, now fetch the players from the state with all of the statistics information attached. PlayerModel stateKiller = null; PlayerModel stateVictim = null; this.State.Players.TryGetValue(killer.Uid, out stateKiller); this.State.Players.TryGetValue(victim.Uid, out stateVictim); this.OnProtocolEvent( ProtocolEventType.ProtocolPlayerKill, difference, new ProtocolEventData() { Kills = new List<KillModel>() { new KillModel() { Scope = { Players = new List<PlayerModel>() { stateVictim }, Items = new List<ItemModel>() { item }, HumanHitLocations = new List<HumanHitLocation>() { headshot == true ? FrostbiteGame.Headshot : FrostbiteGame.Bodyshot } }, Now = { Players = new List<PlayerModel>() { stateKiller } } } } } ); } } } }
public virtual void PlayerOnKillDispatchHandler(IPacketWrapper request, IPacketWrapper response) { if (request.Packet.Words.Count >= 11) { bool headshot = false; if (bool.TryParse(request.Packet.Words[4], out headshot) == true) { var killer = this.State.Players.Select(p => p.Value).FirstOrDefault(p => p.Name == request.Packet.Words[1]); var victim = this.State.Players.Select(p => p.Value).FirstOrDefault(p => p.Name == request.Packet.Words[2]); IProtocolStateDifference difference = new ProtocolStateDifference() { Modified = { Players = new ConcurrentDictionary<String, PlayerModel>(new Dictionary<String, PlayerModel>() { { killer != null ? killer.Uid : "", killer }, { victim != null ? victim.Uid : "", victim } }) } }; this.ApplyProtocolStateDifference(difference); this.OnProtocolEvent( ProtocolEventType.ProtocolPlayerKill, difference, new ProtocolEventData() { Kills = new List<KillModel>() { new KillModel() { Scope = { Players = new List<PlayerModel>() { victim }, Items = new List<ItemModel>() { new ItemModel() { Name = request.Packet.Words[3] } }, Points = new List<Point3DModel>() { new Point3DModel(request.Packet.Words[8], request.Packet.Words[10], request.Packet.Words[9]) }, HumanHitLocations = new List<HumanHitLocation>() { headshot == true ? FrostbiteGame.Headshot : FrostbiteGame.Bodyshot } }, Now = { Players = new List<PlayerModel>() { killer }, Points = new List<Point3DModel>() { new Point3DModel(request.Packet.Words[5], request.Packet.Words[7], request.Packet.Words[6]) } } } } } ); } } }
/// <summary> /// Called when dispatching, but no method matches the exact identifier used. /// </summary> /// <param name="identifier"></param> /// <param name="request"></param> /// <param name="response"></param> public virtual void MissingDispatch(IPacketDispatch identifier, IPacketWrapper request, IPacketWrapper response) { if (this.MissingDispatchHandler != null) { this.MissingDispatchHandler(identifier, request, response); } }
public override void BanListListDispatchHandler(IPacketWrapper request, IPacketWrapper response) { if (request.Packet.Words.Count >= 1) { int startOffset = 0; if (request.Packet.Words.Count >= 2) { if (int.TryParse(request.Packet.Words[1], out startOffset) == false) { startOffset = 0; } } // We've just started requesting the banlist, clear it. if (startOffset == 0) { this.State.Bans.Clear(); } List<BanModel> banList = SecondFrostbiteBanList.Parse(response.Packet.Words.GetRange(1, response.Packet.Words.Count - 1)); if (banList.Count > 0) { foreach (BanModel ban in banList) { if (ban.Scope.Times.Count > 0 && ban.Scope.Players.Count > 0) { var closureBan = ban; var key = String.Format("{0}/{1}", ban.Scope.Times.First().Context, ban.Scope.Players.First().Uid ?? ban.Scope.Players.First().Name ?? ban.Scope.Players.First().Ip); this.State.Bans.AddOrUpdate(key, id => closureBan, (id, model) => closureBan); } } this.Send(this.CreatePacket("banList.list {0}", startOffset + 100)); } else { IProtocolStateDifference difference = new ProtocolStateDifference() { Override = true, Modified = { Bans = this.State.Bans } }; this.ApplyProtocolStateDifference(difference); // We have recieved the whole banlist in 100 ban increments.. throw event. this.OnProtocolEvent( ProtocolEventType.ProtocolBanlistUpdated, difference ); } } }
/// <summary> /// Dispatches a recieved packet. Each game implementation needs to supply its own dispatch /// method as the protocol may be very different and have additional requirements beyond a /// simple text match. /// </summary> /// <param name="identifer"></param> /// <param name="request"></param> /// <param name="response"></param> public virtual void Dispatch(IPacketDispatch identifer, IPacketWrapper request, IPacketWrapper response) { var dispatchMethods = this.Handlers.Where(dispatcher => dispatcher.Key.Name == identifer.Name) .Where(dispatcher => dispatcher.Key.Origin == PacketOrigin.None || dispatcher.Key.Origin == identifer.Origin) .Select(dispatcher => dispatcher.Value) .ToList(); if (dispatchMethods.Any()) { foreach (Action<IPacketWrapper, IPacketWrapper> handler in dispatchMethods) { handler(request, response); } } else { this.MissingDispatch(identifer, request, response); } }
/// <summary> /// TODO: Move the PlayerJoin event to the onAuthenticated? /// </summary> /// <param name="request"></param> /// <param name="response"></param> public virtual void PlayerOnJoinDispatchHandler(IPacketWrapper request, IPacketWrapper response) { if (request.Packet.Words.Count >= 2) { // todo this is blanked out to follow a "no unique id, no existence" type of policy instead of juggling different states of players // todo I need to look into older frostbite games to see if this will present a problem. /* PlayerModel player = new PlayerModel() { Name = request.Packet.Words[1] }; if (this.State.Players.Find(x => x.Name == player.Name) == null) { this.State.Players.Add(player); } */ } }