#pragma once #include "..\Minecraft.World\PacketListener.h" #include #include #include #include class MinecraftServer; class Socket; class LoginPacket; class Connection; class Random; class AuthResponsePacket; using namespace std; class PendingConnection : public PacketListener { private: static const int FAKE_LAG = 0; static const int MAX_TICKS_BEFORE_LOGIN = 20 * 30; // public static Logger logger = Logger.getLogger("Minecraft"); static Random *random; public: Connection *connection; public: bool done; private: MinecraftServer *server; int _tick; wstring name; shared_ptr acceptedLogin; wstring loginKey; // Auth handshake state enum eAuthState { eAuth_None, eAuth_WaitingResponse, eAuth_Verifying, eAuth_WaitingAck, eAuth_Done }; eAuthState m_authState = eAuth_None; std::string m_serverId; // random hex challenge std::string m_authUsername; // username from auth response std::string m_authUuid; // uuid from auth response (dashed) std::string m_authScheme; // "mojang" or "offline" // Thread-safe verification result (heap-allocated so detached thread cannot UAF) struct AuthVerifyResult { std::atomic ready{false}; std::atomic cancelled{false}; std::mutex mutex; // protects fields below bool success = false; std::string username; std::string uuid; // undashed from HasJoined std::string skinUrl; // Mojang skin texture URL std::vector skinData; // downloaded skin PNG bytes std::string errorDetail; // diagnostic info on failure }; std::shared_ptr m_authVerifyResult; // Skin data received from Mojang after auth verification std::string m_authSkinUrl; // texture key for this player's skin std::vector m_authSkinData; // raw PNG bytes public: PendingConnection(MinecraftServer *server, Socket *socket, const wstring& id); ~PendingConnection(); void tick(); void disconnect(DisconnectPacket::eDisconnectReason reason); virtual void handlePreLogin(shared_ptr packet); virtual void handleLogin(shared_ptr packet); virtual void handleAcceptedLogin(shared_ptr packet); virtual void handleAuthResponse(shared_ptr packet); virtual void onDisconnect(DisconnectPacket::eDisconnectReason reason, void *reasonObjects); virtual void handleGetInfo(shared_ptr packet); virtual void handleKeepAlive(shared_ptr packet); virtual void onUnhandledPacket(shared_ptr packet); void send(shared_ptr packet); wstring getName(); virtual bool isServerPacketListener(); virtual bool isDisconnected(); private: void sendPreLoginResponse(); };