-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpacket_handler.cpp
More file actions
119 lines (88 loc) · 4.13 KB
/
Copy pathpacket_handler.cpp
File metadata and controls
119 lines (88 loc) · 4.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
//
// Created by Micael Cossa on 26/07/2025.
//
#include <map>
#include <memory>
#include <utility>
#include <chrono>
#include "packet_handler.h"
#include "../minecraft_internal.h"
#include "packets/HandshakePacket.h"
#include "packets/PingPongPacket.h"
#include "packets/UndefinedPacket.h"
#include "packets/ServerQueryPacket.h"
#include "packets/LoginStartPacket.h"
#include "packets/EncryptionPacket.h"
#include "server_utils.h"
namespace {
thread_local std::array<std::unique_ptr<Packet>, 256> packetFactory = {};
constexpr auto handshake_index = std::to_underlying(ConnectionState::HANDSHAKING);
constexpr auto status_index = std::to_underlying(ConnectionState::STATUS);
constexpr auto login_index = std::to_underlying(ConnectionState::LOGIN);
constexpr auto play_index = std::to_underlying(ConnectionState::PLAY);
constexpr auto disconnect_index = std::to_underlying(ConnectionState::DISCONNECT);
}
void setupPacketFactory() {
for (auto& packet : packetFactory) {
packet = std::make_unique<UndefinedPacket>();
}
packetFactory[std::to_underlying(ConnectionState::HANDSHAKING) + 0] = std::make_unique<HandshakePacket>();
packetFactory[std::to_underlying(ConnectionState::STATUS) + 0] = std::make_unique<ServerQueryPacket>();
packetFactory[std::to_underlying(ConnectionState::STATUS) + 1] = std::make_unique<PingPongPacket>();
packetFactory[std::to_underlying(ConnectionState::LOGIN) + 0] = std::make_unique<LoginStartPacket>();
packetFactory[std::to_underlying(ConnectionState::LOGIN) + 1] = std::make_unique<EncryptionPacket>();
}
bool isPacketIdInBounds(int playerState, int packetid) {
switch (playerState) {
case handshake_index:
return packetid >= handshake_index && packetid < status_index;
case status_index:
return packetid >= status_index && packetid < login_index;
case login_index:
return packetid >= login_index && packetid < play_index;
case play_index:
return packetid >= play_index && packetid < disconnect_index;
default:
return false; // not unreachable, (logically it is)
}
}
//RECEIVE_DATA_EVENT_HANDLER method from NetworkManager
void invokePacket(ReadPacketBuffer* packetBuffer, PLAYER_CONNECTION_CONTEXT* connectionContext) {
int packetId = packetBuffer->readVarInt();
if(packetId >= packetFactory.size() || packetId < 0 ) {
printInfo("invalid Packet id: ", packetId);
return;
}
int stateNum = std::to_underlying(connectionContext->connectionInfo.connectionState);
// Checking if the player is invoking a packet within the bounds of its connection state
// Example: A player pinging the server should not sending a EncryptionPacket.
if(!isPacketIdInBounds(stateNum, packetId))
return;
packetFactory[stateNum + packetId]->handlePacket(packetBuffer, connectionContext);
packetFactory[stateNum + packetId]->clear();
}
/**
* Packet format
* - length (id + data)
* - id
* - data
* @param packet
* @param connectionContext
*/
void sendPacket(Packet* packet, PLAYER_CONNECTION_CONTEXT* connectionContext) {
PLAYER_CONNECTION_CONTEXT* sendcontext = getNetworkManager().acquireContext();
if (!sendcontext) {
printInfo("Failed to acquire context for sending");
return;
}
// copy the socket, state, status
sendcontext->copy(connectionContext);
WritePacketBuffer packetBuffer = WritePacketBuffer(sendcontext->buffer.buf, sendcontext->buffer.len);
packet->writeToBuffer(&packetBuffer);
packetBuffer.writeVarIntAtTheFront((int)packetBuffer.getSize());
// dummy byte, for some reason minecraft drops one byte (which would completely mess up the way it was read) despite WSASend confirming the correct amount of bytes sent
// The fact that I am writing this, despite knowing this project wont be shared, it would give insights to the levels of frustrations.
// But if you are not the future me and is someone who just happened to come across this file, this single line of code contains days of agony
packetBuffer.writeByte(0);
getNetworkManager().sendDataToConnection(sendcontext);
}