#pragma once #ifdef __linux__ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../../Minecraft.Client/Common/Network/NetworkPlayerInterface.h" typedef int SOCKET; #define INVALID_SOCKET (-1) #define SOCKET_ERROR (-1) inline int closesocket(SOCKET s) { return close(s); } #define WIN64_NET_DEFAULT_PORT 25565 #define WIN64_NET_RECV_BUFFER_SIZE 131072 #define WIN64_NET_MAX_PACKET_SIZE (3 * 1024 * 1024) #define WIN64_LAN_DISCOVERY_PORT 25566 #define WIN64_LAN_BROADCAST_MAGIC 0x4D434C4E #define WIN64_LAN_BROADCAST_PLAYERS 8 #define WIN64_NET_IO_THREADS 2 #define WIN64_NET_EPOLL_MAX_EVENTS 64 #define WIN64_NET_SEND_BUFFER_SIZE 262144 class Socket; #pragma pack(push, 1) struct Win64LANBroadcast { DWORD magic; uint16_t netVersion; uint16_t gamePort; uint16_t hostName[32]; uint8_t playerCount; uint8_t maxPlayers; DWORD gameHostSettings; DWORD texturePackParentId; uint8_t subTexturePackId; uint8_t isJoinable; uint8_t isDedicatedServer; char playerNames[WIN64_LAN_BROADCAST_PLAYERS][32]; // XUSER_NAME_SIZE }; #pragma pack(pop) struct Win64LANSession { char hostIP[64]; int hostPort; wchar_t hostName[32]; unsigned short netVersion; unsigned char playerCount; unsigned char maxPlayers; unsigned int gameHostSettings; unsigned int texturePackParentId; unsigned char subTexturePackId; bool isJoinable; bool isDedicatedServer; DWORD lastSeenTick; char playerNames[WIN64_LAN_BROADCAST_PLAYERS][32]; }; struct Win64RemoteConnection { SOCKET tcpSocket; uint8_t smallId; volatile bool active; pthread_mutex_t sendLock; uint8_t *recvBuffer; int recvBufferUsed; int recvBufferSize; int currentPacketSize; bool readingHeader; uint8_t *sendBuffer; int sendBufferUsed; int sendBufferSize; pthread_mutex_t sendBufLock; }; class WinsockNetLayer { public: static bool Initialize(); static void Shutdown(); static bool HostGame(int port); static bool JoinGame(const char *ip, int port); enum JoinResult { JOIN_IN_PROGRESS, JOIN_SUCCESS, JOIN_FAILED }; static bool BeginJoinGame(const char *ip, int port); static JoinResult PollJoinResult(); static void CancelJoinGame(); static bool SendToSmallId(uint8_t targetSmallId, const void *data, int dataSize); static bool SendOnSocket(SOCKET sock, const void *data, int dataSize); static bool IsHosting() { return s_isHost; } static bool IsConnected() { return s_connected; } static bool IsActive() { return s_active; } static uint8_t GetLocalSmallId() { return s_localSmallId; } static uint8_t GetHostSmallId() { return s_hostSmallId; } static SOCKET GetSocketForSmallId(uint8_t smallId); static std::string GetIPForSmallId(uint8_t smallId); static void HandleDataReceived(uint8_t fromSmallId, uint8_t toSmallId, unsigned char *data, unsigned int dataSize); static void FlushPendingData(); static bool PopDisconnectedSmallId(uint8_t *outSmallId); static void PushFreeSmallId(uint8_t smallId); static void CloseConnectionBySmallId(uint8_t smallId); static bool PopPendingJoinSmallId(uint8_t *outSmallId); static bool IsSmallIdConnected(uint8_t smallId); static bool StartAdvertising(int gamePort, const wchar_t *hostName, unsigned int gameSettings, unsigned int texPackId, unsigned char subTexId, unsigned short netVer); static void StopAdvertising(); static void UpdateAdvertisePlayerCount(uint8_t count); static void UpdateAdvertiseJoinable(bool joinable); static void UpdateAdvertisePlayerNames(uint8_t count, const char playerNames[][32]); static void UpdateAdvertiseGameHostSettings(unsigned int settings); static bool StartDiscovery(); static void StopDiscovery(); static std::vector GetDiscoveredSessions(); static int GetHostPort() { return s_hostGamePort; } static void FlushSendBuffers(); private: static size_t GetConnectionSlotCount(); static void* AcceptThreadProc(void* param); static void* EpollThreadProc(void* param); static void* ClientRecvThreadProc(void* param); static void* AdvertiseThreadProc(void* param); static void* DiscoveryThreadProc(void* param); static void* AsyncJoinThreadProc(void* param); static bool ProcessRecvData(Win64RemoteConnection &conn); static void MarkConnectionDisconnected(uint8_t smallId); static SOCKET s_listenSocket; static SOCKET s_hostConnectionSocket; static pthread_t s_acceptThread; static bool s_acceptThreadActive; static pthread_t s_clientRecvThread; static bool s_clientRecvThreadActive; static int s_epollFd; static pthread_t s_epollThreads[WIN64_NET_IO_THREADS]; static bool s_epollThreadsActive; static bool s_isHost; static bool s_connected; static bool s_active; static bool s_initialized; static uint8_t s_localSmallId; static uint8_t s_hostSmallId; static std::atomic s_nextSmallId; static pthread_mutex_t s_sendLock; static pthread_mutex_t s_connectionsLock; static std::vector s_connections; static SOCKET s_advertiseSock; static pthread_t s_advertiseThread; static bool s_advertiseThreadActive; static volatile bool s_advertising; static Win64LANBroadcast s_advertiseData; static pthread_mutex_t s_advertiseLock; static int s_hostGamePort; static SOCKET s_discoverySock; static SOCKET s_discoveryLegacySock; static pthread_t s_discoveryThread; static bool s_discoveryThreadActive; static volatile bool s_discovering; static pthread_mutex_t s_discoveryLock; static std::vector s_discoveredSessions; static pthread_mutex_t s_disconnectLock; static std::vector s_disconnectedSmallIds; static pthread_mutex_t s_pendingJoinLock; static std::vector s_pendingJoinSmallIds; static pthread_mutex_t s_freeSmallIdLock; static std::vector s_freeSmallIds; static pthread_mutex_t s_earlyDataLock; static std::vector > s_earlyDataBuffers; static pthread_t s_asyncJoinThread; static bool s_asyncJoinThreadActive; static volatile JoinResult s_asyncJoinResult; static volatile bool s_asyncJoinActive; static char s_asyncJoinIP[256]; static int s_asyncJoinPort; }; extern bool g_Win64MultiplayerHost; extern bool g_Win64MultiplayerJoin; extern int g_Win64MultiplayerPort; extern char g_Win64MultiplayerIP[256]; #endif // __linux__