TrinityCore
PacketLog.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "PacketLog.h"
19#include "Config.h"
20#include "GameTime.h"
21#include "IpAddress.h"
22#include "Realm.h"
23#include "Timer.h"
24#include "World.h"
25#include "WorldPacket.h"
26
27#pragma pack(push, 1)
28
29// Packet logging structures in PKT 3.1 format
31{
32 char Signature[3];
36 char Locale[4];
41};
42
44{
45 // used to uniquely identify a connection
47 {
50 };
51
59};
60
61#pragma pack(pop)
62
63PacketLog::PacketLog() : _file(nullptr)
64{
65 std::call_once(_initializeFlag, &PacketLog::Initialize, this);
66}
67
69{
70 if (_file)
71 fclose(_file);
72
73 _file = nullptr;
74}
75
77{
78 static PacketLog instance;
79 return &instance;
80}
81
83{
84 std::string logsDir = sConfigMgr->GetStringDefault("LogsDir", "");
85
86 if (!logsDir.empty())
87 if ((logsDir.at(logsDir.length() - 1) != '/') && (logsDir.at(logsDir.length() - 1) != '\\'))
88 logsDir.push_back('/');
89
90 std::string logname = sConfigMgr->GetStringDefault("PacketLogFile", "");
91 if (!logname.empty())
92 {
93 _file = fopen((logsDir + logname).c_str(), "wb");
94
95 if (CanLogPacket())
96 {
97 LogHeader header;
98 header.Signature[0] = 'P'; header.Signature[1] = 'K'; header.Signature[2] = 'T';
99 header.FormatVersion = 0x0301;
100 header.SnifferId = 'T';
101 header.Build = realm.Build;
102 header.Locale[0] = 'e'; header.Locale[1] = 'n'; header.Locale[2] = 'U'; header.Locale[3] = 'S';
103 std::memset(header.SessionKey, 0, sizeof(header.SessionKey));
105 header.SniffStartTicks = getMSTime();
106 header.OptionalDataSize = 0;
107
108 fwrite(&header, sizeof(header), 1, _file);
109 }
110 }
111}
112
113void PacketLog::LogPacket(WorldPacket const& packet, Direction direction, boost::asio::ip::address const& addr, uint16 port, ConnectionType connectionType)
114{
115 std::lock_guard<std::mutex> lock(_logPacketLock);
116
117 PacketHeader header;
118 header.Direction = direction == CLIENT_TO_SERVER ? 0x47534d43 : 0x47534d53;
119 header.ConnectionId = connectionType;
120 header.ArrivalTicks = getMSTime();
121
122 header.OptionalDataSize = sizeof(header.OptionalData);
123 memset(header.OptionalData.SocketIPBytes, 0, sizeof(header.OptionalData.SocketIPBytes));
124 if (addr.is_v4())
125 {
126 auto bytes = addr.to_v4().to_bytes();
127 memcpy(header.OptionalData.SocketIPBytes, bytes.data(), bytes.size());
128 }
129 else if (addr.is_v6())
130 {
131 auto bytes = addr.to_v6().to_bytes();
132 memcpy(header.OptionalData.SocketIPBytes, bytes.data(), bytes.size());
133 }
134
135 header.OptionalData.SocketPort = port;
136 std::size_t size = packet.size();
137 if (direction == CLIENT_TO_SERVER)
138 size -= 2;
139
140 header.Length = size + sizeof(header.Opcode);
141 header.Opcode = packet.GetOpcode();
142
143 fwrite(&header, sizeof(header), 1, _file);
144 if (size)
145 {
146 uint8 const* data = packet.contents();
147 if (direction == CLIENT_TO_SERVER)
148 data += 2;
149 fwrite(data, 1, size, _file);
150 }
151
152 fflush(_file);
153}
std::array< uint8, SESSION_KEY_LENGTH > SessionKey
Definition: AuthDefines.h:25
#define sConfigMgr
Definition: Config.h:61
uint8_t uint8
Definition: Define.h:144
uint16_t uint16
Definition: Define.h:143
uint32_t uint32
Definition: Define.h:142
Direction
Definition: PacketLog.h:25
@ CLIENT_TO_SERVER
Definition: PacketLog.h:26
std::pair< uint32, ObjectGuid > Signature
Definition: PetitionMgr.h:50
uint32 getMSTime()
Definition: Timer.h:33
size_t size() const
Definition: ByteBuffer.h:536
uint8 * contents()
Definition: ByteBuffer.h:522
FILE * _file
Definition: PacketLog.h:60
bool CanLogPacket() const
Definition: PacketLog.h:56
static PacketLog * instance()
Definition: PacketLog.cpp:76
std::once_flag _initializeFlag
Definition: PacketLog.h:50
void LogPacket(WorldPacket const &packet, Direction direction, boost::asio::ip::address const &addr, uint16 port, ConnectionType connectionType)
Definition: PacketLog.cpp:113
void Initialize()
Definition: PacketLog.cpp:82
std::mutex _logPacketLock
Definition: PacketLog.h:49
uint32 GetOpcode() const
Definition: WorldPacket.h:84
ConnectionType
Definition: Opcodes.h:29
Realm realm
Definition: World.cpp:3966
time_t GetGameTime()
Definition: GameTime.cpp:44
constexpr std::size_t size()
Definition: UpdateField.h:796
uint32 SniffStartTicks
Definition: PacketLog.cpp:39
char Signature[3]
Definition: PacketLog.cpp:32
uint32 OptionalDataSize
Definition: PacketLog.cpp:40
uint32 SniffStartUnixtime
Definition: PacketLog.cpp:38
uint8 SnifferId
Definition: PacketLog.cpp:34
uint32 Build
Definition: PacketLog.cpp:35
uint16 FormatVersion
Definition: PacketLog.cpp:33
char Locale[4]
Definition: PacketLog.cpp:36
uint8 SessionKey[40]
Definition: PacketLog.cpp:37
uint32 Direction
Definition: PacketLog.cpp:52
uint32 OptionalDataSize
Definition: PacketLog.cpp:55
uint32 Opcode
Definition: PacketLog.cpp:58
uint32 ArrivalTicks
Definition: PacketLog.cpp:54
OptionalData OptionalData
Definition: PacketLog.cpp:57
uint32 Length
Definition: PacketLog.cpp:56
uint32 ConnectionId
Definition: PacketLog.cpp:53
uint32 Build
Definition: Realm.h:83