Files
2026-08-11 08:21:50 +08:00

87 lines
3.2 KiB
C++

#ifndef NETSERVER_H
#define NETSERVER_H
#include "config.h"
#include "network.h"
namespace ygo {
class NetServer {
private:
static unsigned char net_server_write[SIZE_NETWORK_BUFFER];
static size_t last_sent;
static bufferevent* disconnecting_bev;
static int WriteBufferEvent(bufferevent* bufev, const void* data, size_t size);
static bool CanWriteToPlayer(DuelPlayer* dp) {
return dp && dp->bev && dp->bev != disconnecting_bev;
}
public:
static bool StartServer(unsigned short port, unsigned int ip = 0, unsigned short* out_actual_port = nullptr, bool enable_broadcast = true);
static bool StartBroadcast();
static void StopServer();
static void StopBroadcast();
static void StopListen();
static void StartDuelTimer();
static void StopDuelTimer();
static void BroadcastEvent(EventSocket fd, short events, void* arg);
static void ServerAccept(evconnlistener* listener, EventSocket fd, sockaddr* address, int socklen, void* ctx);
static void ServerAcceptError(evconnlistener *listener, void* ctx);
static void ServerEchoRead(bufferevent* bev, void* ctx);
static void ServerEchoEvent(bufferevent* bev, short events, void* ctx);
static void ServerThread();
static void DisconnectPlayer(DuelPlayer* dp);
static void HandleCTOSPacket(DuelPlayer* dp, unsigned char* data, size_t len);
static size_t CreateChatPacket(unsigned char* src, int src_size, unsigned char* dst, uint16_t dst_player_type);
static inline bool ShouldHideFacedownCode(uint8_t position) {
return (position & POS_FACEDOWN) != 0 && (position & POS_REVEAL) == 0;
}
// TODO: remove this function in the next protocol version, let the client handle the POS_REVEAL flag instead.
static inline uint8_t StripRevealFlag(unsigned char* qbuf, size_t offset) {
uint32_t info = 0;
std::memcpy(&info, qbuf + offset, sizeof info);
info &= ~(static_cast<uint32_t>(POS_REVEAL) << 24);
std::memcpy(qbuf + offset, &info, sizeof info);
return static_cast<uint8_t>(info >> 24);
}
static void SendPacketToPlayer(DuelPlayer* dp, unsigned char proto) {
auto p = net_server_write;
BufferIO::Write<uint16_t>(p, 1);
BufferIO::Write<uint8_t>(p, proto);
last_sent = 3;
if (CanWriteToPlayer(dp))
WriteBufferEvent(dp->bev, net_server_write, 3);
}
template<typename ST>
static void SendPacketToPlayer(DuelPlayer* dp, unsigned char proto, const ST& st) {
auto p = net_server_write;
static_assert(sizeof(ST) <= MAX_DATA_SIZE, "Packet size is too large.");
BufferIO::Write<uint16_t>(p, (uint16_t)(1 + sizeof(ST)));
BufferIO::Write<uint8_t>(p, proto);
std::memcpy(p, &st, sizeof(ST));
last_sent = sizeof(ST) + 3;
if (CanWriteToPlayer(dp))
WriteBufferEvent(dp->bev, net_server_write, sizeof(ST) + 3);
}
static void SendBufferToPlayer(DuelPlayer* dp, unsigned char proto, void* buffer, size_t len) {
auto p = net_server_write;
if (len > MAX_DATA_SIZE)
len = MAX_DATA_SIZE;
BufferIO::Write<uint16_t>(p, (uint16_t)(1 + len));
BufferIO::Write<uint8_t>(p, proto);
std::memcpy(p, buffer, len);
last_sent = len + 3;
if (CanWriteToPlayer(dp))
WriteBufferEvent(dp->bev, net_server_write, len + 3);
}
static void ReSendToPlayer(DuelPlayer* dp) {
if (CanWriteToPlayer(dp))
WriteBufferEvent(dp->bev, net_server_write, last_sent);
}
};
}
#endif //NETSERVER_H