public static void Write(byte[] data, ClientOpcodes opcode, IPAddress address, uint port, ConnectionType connectionType) { if (!CanLog()) { return; } lock (syncObj) { using (var writer = new BinaryWriter(File.Open(FullPath, FileMode.Append), Encoding.ASCII)) { writer.Write("CMSG".ToCharArray()); writer.Write((uint)connectionType); writer.Write(Time.GetMSTime()); writer.Write(20); byte[] SocketIPBytes = new byte[16]; if (address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) { Buffer.BlockCopy(address.GetAddressBytes(), 0, SocketIPBytes, 0, 4); } else { Buffer.BlockCopy(address.GetAddressBytes(), 0, SocketIPBytes, 0, 16); } writer.Write(data.Length + 4); writer.Write(SocketIPBytes); writer.Write(port); writer.Write((uint)opcode); writer.Write(data); } } }
public static PacketHandler GetHandler(ClientOpcodes opcode) { return(_clientPacketTable.LookupByKey(opcode)); }
public WorldPacketHandlerAttribute(ClientOpcodes opcode) { Opcode = opcode; Status = SessionStatus.Loggedin; Processing = PacketProcessing.ThreadUnsafe; }
public static bool ContainsHandler(ClientOpcodes opcode) { return(_clientPacketTable.ContainsKey(opcode)); }
bool ProcessPacket(WorldPacket packet) { ClientOpcodes opcode = (ClientOpcodes)packet.GetOpcode(); PacketLog.Write(packet.GetData(), opcode, GetRemoteIpAddress(), GetRemotePort(), _connectType); try { switch (opcode) { case ClientOpcodes.Ping: Ping ping = new Ping(packet); ping.Read(); return(HandlePing(ping)); case ClientOpcodes.AuthSession: if (_worldSession != null) { Log.outError(LogFilter.Network, "WorldSocket.ProcessPacket: received duplicate CMSG_AUTH_SESSION from {0}", _worldSession.GetPlayerInfo()); return(false); } AuthSession authSession = new AuthSession(packet); authSession.Read(); HandleAuthSession(authSession); break; case ClientOpcodes.AuthContinuedSession: if (_worldSession != null) { Log.outError(LogFilter.Network, "WorldSocket.ProcessPacket: received duplicate CMSG_AUTH_CONTINUED_SESSION from {0}", _worldSession.GetPlayerInfo()); return(false); } AuthContinuedSession authContinuedSession = new AuthContinuedSession(packet); authContinuedSession.Read(); HandleAuthContinuedSession(authContinuedSession); break; case ClientOpcodes.LogDisconnect: break; case ClientOpcodes.EnableNagle: Log.outDebug(LogFilter.Network, "Client {0} requested enabling nagle algorithm", GetRemoteIpAddress().ToString()); SetNoDelay(false); break; case ClientOpcodes.ConnectToFailed: ConnectToFailed connectToFailed = new ConnectToFailed(packet); connectToFailed.Read(); HandleConnectToFailed(connectToFailed); break; case ClientOpcodes.EnableEncryptionAck: HandleEnableEncryptionAck(); break; default: if (_worldSession == null) { Log.outError(LogFilter.Network, "ProcessIncoming: Client not authed opcode = {0}", opcode); return(false); } if (!PacketManager.ContainsHandler(opcode)) { Log.outError(LogFilter.Network, "No defined handler for opcode {0} sent by {1}", opcode, _worldSession.GetPlayerInfo()); break; } // Our Idle timer will reset on any non PING opcodes. // Catches people idling on the login screen and any lingering ingame connections. _worldSession.ResetTimeOutTime(); _worldSession.QueuePacket(packet); break; } } catch (IOException) { Log.outError(LogFilter.Network, "WorldSocket.ProcessPacket(): client {0} sent malformed {1}", GetRemoteIpAddress().ToString(), opcode); return(false); } return(true); }
void HandleMovementOpcode(ClientOpcodes opcode, MovementInfo movementInfo) { Unit mover = GetPlayer().m_unitMovedByMe; Player plrMover = mover.ToPlayer(); if (plrMover && plrMover.IsBeingTeleported()) { return; } GetPlayer().ValidateMovementInfo(movementInfo); if (movementInfo.Guid != mover.GetGUID()) { Log.outError(LogFilter.Network, "HandleMovementOpcodes: guid error"); return; } if (!movementInfo.Pos.IsPositionValid()) { Log.outError(LogFilter.Network, "HandleMovementOpcodes: Invalid Position"); return; } // stop some emotes at player move if (plrMover && (plrMover.GetEmoteState() != 0)) { plrMover.SetEmoteState(Emote.OneshotNone); } //handle special cases if (!movementInfo.transport.guid.IsEmpty()) { // We were teleported, skip packets that were broadcast before teleport if (movementInfo.Pos.GetExactDist2d(mover) > MapConst.SizeofGrids) { return; } if (Math.Abs(movementInfo.transport.pos.GetPositionX()) > 75f || Math.Abs(movementInfo.transport.pos.GetPositionY()) > 75f || Math.Abs(movementInfo.transport.pos.GetPositionZ()) > 75f) { return; } if (!GridDefines.IsValidMapCoord(movementInfo.Pos.posX + movementInfo.transport.pos.posX, movementInfo.Pos.posY + movementInfo.transport.pos.posY, movementInfo.Pos.posZ + movementInfo.transport.pos.posZ, movementInfo.Pos.Orientation + movementInfo.transport.pos.Orientation)) { return; } if (plrMover) { if (!plrMover.GetTransport()) { Transport transport = plrMover.GetMap().GetTransport(movementInfo.transport.guid); if (transport) { transport.AddPassenger(plrMover); } } else if (plrMover.GetTransport().GetGUID() != movementInfo.transport.guid) { plrMover.GetTransport().RemovePassenger(plrMover); Transport transport = plrMover.GetMap().GetTransport(movementInfo.transport.guid); if (transport) { transport.AddPassenger(plrMover); } else { movementInfo.ResetTransport(); } } } if (!mover.GetTransport() && !mover.GetVehicle()) { GameObject go = mover.GetMap().GetGameObject(movementInfo.transport.guid); if (!go || go.GetGoType() != GameObjectTypes.Transport) { movementInfo.transport.Reset(); } } } else if (plrMover && plrMover.GetTransport()) // if we were on a transport, leave { plrMover.GetTransport().RemovePassenger(plrMover); } // fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map). if (opcode == ClientOpcodes.MoveFallLand && plrMover && !plrMover.IsInFlight()) { plrMover.HandleFall(movementInfo); } // interrupt parachutes upon falling or landing in water if (opcode == ClientOpcodes.MoveFallLand || opcode == ClientOpcodes.MoveStartSwim) { mover.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.Landing); // Parachutes } if (plrMover && movementInfo.HasMovementFlag(MovementFlag.Swimming) != plrMover.IsInWater()) { // now client not include swimming flag in case jumping under water plrMover.SetInWater(!plrMover.IsInWater() || plrMover.GetMap().IsUnderWater(plrMover.GetPhaseShift(), movementInfo.Pos.posX, movementInfo.Pos.posY, movementInfo.Pos.posZ)); } uint mstime = GameTime.GetGameTimeMS(); if (m_clientTimeDelay == 0) { m_clientTimeDelay = mstime - movementInfo.Time; } movementInfo.Time = movementInfo.Time + m_clientTimeDelay; movementInfo.Guid = mover.GetGUID(); mover.m_movementInfo = movementInfo; // Some vehicles allow the passenger to turn by himself Vehicle vehicle = mover.GetVehicle(); if (vehicle) { VehicleSeatRecord seat = vehicle.GetSeatForPassenger(mover); if (seat != null) { if (seat.HasSeatFlag(VehicleSeatFlags.AllowTurning)) { if (movementInfo.Pos.GetOrientation() != mover.GetOrientation()) { mover.SetOrientation(movementInfo.Pos.GetOrientation()); mover.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.Turning); } } } return; } mover.UpdatePosition(movementInfo.Pos); MoveUpdate moveUpdate = new MoveUpdate(); moveUpdate.Status = mover.m_movementInfo; mover.SendMessageToSet(moveUpdate, GetPlayer()); if (plrMover) // nothing is charmed, or player charmed { if (plrMover.IsSitState() && movementInfo.HasMovementFlag(MovementFlag.MaskMoving | MovementFlag.MaskTurning)) { plrMover.SetStandState(UnitStandStateType.Stand); } plrMover.UpdateFallInformationIfNeed(movementInfo, opcode); if (movementInfo.Pos.posZ < plrMover.GetMap().GetMinHeight(plrMover.GetPhaseShift(), movementInfo.Pos.GetPositionX(), movementInfo.Pos.GetPositionY())) { if (!(plrMover.GetBattleground() && plrMover.GetBattleground().HandlePlayerUnderMap(GetPlayer()))) { // NOTE: this is actually called many times while falling // even after the player has been teleported away // @todo discard movement packets after the player is rooted if (plrMover.IsAlive()) { plrMover.AddPlayerFlag(PlayerFlags.IsOutOfBounds); plrMover.EnvironmentalDamage(EnviromentalDamage.FallToVoid, (uint)GetPlayer().GetMaxHealth()); // player can be alive if GM/etc // change the death state to CORPSE to prevent the death timer from // starting in the next player update if (plrMover.IsAlive()) { plrMover.KillPlayer(); } } } } else { plrMover.RemovePlayerFlag(PlayerFlags.IsOutOfBounds); } if (opcode == ClientOpcodes.MoveJump) { plrMover.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.Jump, 605); // Mind Control plrMover.ProcSkillsAndAuras(null, ProcFlags.Jump, ProcFlags.None, ProcFlagsSpellType.MaskAll, ProcFlagsSpellPhase.None, ProcFlagsHit.None, null, null, null); } } }
void HandleForceSpeedChangeAck(MovementSpeedAck packet) { GetPlayer().ValidateMovementInfo(packet.Ack.Status); // now can skip not our packet if (GetPlayer().GetGUID() != packet.Ack.Status.Guid) { return; } /*----------------*/ // client ACK send one packet for mounted/run case and need skip all except last from its // in other cases anti-cheat check can be fail in false case UnitMoveType move_type; ClientOpcodes opcode = packet.GetOpcode(); switch (opcode) { case ClientOpcodes.MoveForceWalkSpeedChangeAck: move_type = UnitMoveType.Walk; break; case ClientOpcodes.MoveForceRunSpeedChangeAck: move_type = UnitMoveType.Run; break; case ClientOpcodes.MoveForceRunBackSpeedChangeAck: move_type = UnitMoveType.RunBack; break; case ClientOpcodes.MoveForceSwimSpeedChangeAck: move_type = UnitMoveType.Swim; break; case ClientOpcodes.MoveForceSwimBackSpeedChangeAck: move_type = UnitMoveType.SwimBack; break; case ClientOpcodes.MoveForceTurnRateChangeAck: move_type = UnitMoveType.TurnRate; break; case ClientOpcodes.MoveForceFlightSpeedChangeAck: move_type = UnitMoveType.Flight; break; case ClientOpcodes.MoveForceFlightBackSpeedChangeAck: move_type = UnitMoveType.FlightBack; break; case ClientOpcodes.MoveForcePitchRateChangeAck: move_type = UnitMoveType.PitchRate; break; default: Log.outError(LogFilter.Network, "WorldSession.HandleForceSpeedChangeAck: Unknown move type opcode: {0}", opcode); return; } // skip all forced speed changes except last and unexpected // in run/mounted case used one ACK and it must be skipped. m_forced_speed_changes[MOVE_RUN] store both. if (GetPlayer().m_forced_speed_changes[(int)move_type] > 0) { --GetPlayer().m_forced_speed_changes[(int)move_type]; if (GetPlayer().m_forced_speed_changes[(int)move_type] > 0) { return; } } if (!GetPlayer().GetTransport() && Math.Abs(GetPlayer().GetSpeed(move_type) - packet.Speed) > 0.01f) { if (GetPlayer().GetSpeed(move_type) > packet.Speed) // must be greater - just correct { Log.outError(LogFilter.Network, "{0}SpeedChange player {1} is NOT correct (must be {2} instead {3}), force set to correct value", move_type, GetPlayer().GetName(), GetPlayer().GetSpeed(move_type), packet.Speed); GetPlayer().SetSpeedRate(move_type, GetPlayer().GetSpeedRate(move_type)); } else // must be lesser - cheating { Log.outDebug(LogFilter.Server, "Player {0} from account id {1} kicked for incorrect speed (must be {2} instead {3})", GetPlayer().GetName(), GetPlayer().GetSession().GetAccountId(), GetPlayer().GetSpeed(move_type), packet.Speed); GetPlayer().GetSession().KickPlayer(); } } }
ReadDataHandlerResult ReadData() { PacketHeader header = new PacketHeader(); header.Read(_headerBuffer.GetData()); if (!_worldCrypt.Decrypt(_packetBuffer.GetData(), header.Tag)) { Log.outError(LogFilter.Network, $"WorldSocket.ReadData(): client {GetRemoteIpAddress()} failed to decrypt packet (size: {header.Size})"); return(ReadDataHandlerResult.Error); } WorldPacket packet = new WorldPacket(_packetBuffer.GetData()); _packetBuffer.Reset(); if (packet.GetOpcode() >= (int)ClientOpcodes.Max) { Log.outError(LogFilter.Network, $"WorldSocket.ReadData(): client {GetRemoteIpAddress()} sent wrong opcode (opcode: {packet.GetOpcode()})"); return(ReadDataHandlerResult.Error); } PacketLog.Write(packet.GetData(), packet.GetOpcode(), GetRemoteIpAddress(), _connectType, true); ClientOpcodes opcode = (ClientOpcodes)packet.GetOpcode(); switch (opcode) { case ClientOpcodes.Ping: Ping ping = new Ping(packet); ping.Read(); if (!HandlePing(ping)) { return(ReadDataHandlerResult.Error); } break; case ClientOpcodes.AuthSession: if (_worldSession != null) { Log.outError(LogFilter.Network, $"WorldSocket.ReadData(): received duplicate CMSG_AUTH_SESSION from {_worldSession.GetPlayerInfo()}"); return(ReadDataHandlerResult.Error); } AuthSession authSession = new AuthSession(packet); authSession.Read(); HandleAuthSession(authSession); return(ReadDataHandlerResult.WaitingForQuery); case ClientOpcodes.AuthContinuedSession: if (_worldSession != null) { Log.outError(LogFilter.Network, $"WorldSocket.ReadData(): received duplicate CMSG_AUTH_CONTINUED_SESSION from {_worldSession.GetPlayerInfo()}"); return(ReadDataHandlerResult.Error); } AuthContinuedSession authContinuedSession = new AuthContinuedSession(packet); authContinuedSession.Read(); HandleAuthContinuedSession(authContinuedSession); return(ReadDataHandlerResult.WaitingForQuery); case ClientOpcodes.KeepAlive: if (_worldSession != null) { _worldSession.ResetTimeOutTime(true); } break; case ClientOpcodes.LogDisconnect: break; case ClientOpcodes.EnableNagle: SetNoDelay(false); break; case ClientOpcodes.ConnectToFailed: ConnectToFailed connectToFailed = new ConnectToFailed(packet); connectToFailed.Read(); HandleConnectToFailed(connectToFailed); break; case ClientOpcodes.EnterEncryptedModeAck: HandleEnterEncryptedModeAck(); break; default: if (_worldSession == null) { Log.outError(LogFilter.Network, $"ProcessIncoming: Client not authed opcode = {opcode}"); return(ReadDataHandlerResult.Error); } if (!PacketManager.ContainsHandler(opcode)) { Log.outError(LogFilter.Network, $"No defined handler for opcode {opcode} sent by {_worldSession.GetPlayerInfo()}"); break; } // Our Idle timer will reset on any non PING opcodes on login screen, allowing us to catch people idling. _worldSession.ResetTimeOutTime(false); // Copy the packet to the heap before enqueuing _worldSession.QueuePacket(packet); break; } return(ReadDataHandlerResult.Ok); }