Commit e726ae9b authored by fallenstardust's avatar fallenstardust

update network server

parent f55445bd
......@@ -29,7 +29,7 @@ public:
}
// return: string length
template<typename T1, typename T2>
inline static int CopyWStr(T1* src, T2* pstr, int bufsize) {
inline static int CopyWStr(const T1* src, T2* pstr, int bufsize) {
int l = 0;
while(src[l] && l < bufsize - 1) {
pstr[l] = (T2)src[l];
......@@ -39,7 +39,7 @@ public:
return l;
}
template<typename T1, typename T2>
inline static int CopyWStrRef(T1* src, T2*& pstr, int bufsize) {
inline static int CopyWStrRef(const T1* src, T2*& pstr, int bufsize) {
int l = 0;
while(src[l] && l < bufsize - 1) {
pstr[l] = (T2)src[l];
......
......@@ -36,7 +36,7 @@ void DeckManager::LoadLFListSingle(const char* path) {
int count = -1;
if (sscanf(linebuf, "%d %d", &code, &count) != 2)
continue;
if (code <= 0 || code > 99999999)
if (code <= 0 || code > 0xfffffff)
continue;
if (count < 0 || count > 2)
continue;
......@@ -88,11 +88,11 @@ int DeckManager::CheckDeck(Deck& deck, int lfhash, int rule) {
if(!list)
return 0;
int dc = 0;
if(deck.main.size() < 40 || deck.main.size() > 60)
if(deck.main.size() < DECK_MIN_SIZE || deck.main.size() > DECK_MAX_SIZE)
return (DECKERROR_MAINCOUNT << 28) + deck.main.size();
if(deck.extra.size() > 15)
if(deck.extra.size() > EXTRA_MAX_SIZE)
return (DECKERROR_EXTRACOUNT << 28) + deck.extra.size();
if(deck.side.size() > 15)
if(deck.side.size() > SIDE_MAX_SIZE)
return (DECKERROR_SIDECOUNT << 28) + deck.side.size();
const int rule_map[6] = { AVAIL_OCG, AVAIL_TCG, AVAIL_SC, AVAIL_CUSTOM, AVAIL_OCGTCG, 0 };
int avail = rule_map[rule];
......@@ -160,10 +160,10 @@ int DeckManager::LoadDeck(Deck& deck, int* dbuf, int mainc, int sidec, bool is_p
continue;
}
else if(cd.type & (TYPE_FUSION | TYPE_SYNCHRO | TYPE_XYZ | TYPE_LINK)) {
if(deck.extra.size() >= 15)
if(deck.extra.size() >= EXTRA_MAX_SIZE)
continue;
deck.extra.push_back(dataManager.GetCodePointer(code));
} else if(deck.main.size() < 60) {
} else if(deck.main.size() < DECK_MAX_SIZE) {
deck.main.push_back(dataManager.GetCodePointer(code));
}
}
......
......@@ -8,6 +8,10 @@
#include <sstream>
namespace ygo {
constexpr int DECK_MAX_SIZE = 60;
constexpr int DECK_MIN_SIZE = 40;
constexpr int EXTRA_MAX_SIZE = 15;
constexpr int SIDE_MAX_SIZE = 15;
struct LFList {
unsigned int hash{};
......
......@@ -22,6 +22,7 @@ bool DuelClient::is_host = false;
event_base* DuelClient::client_base = 0;
bufferevent* DuelClient::client_bev = 0;
unsigned char DuelClient::duel_client_read[SIZE_NETWORK_BUFFER];
int DuelClient::read_len = 0;
unsigned char DuelClient::duel_client_write[SIZE_NETWORK_BUFFER];
bool DuelClient::is_closing = false;
bool DuelClient::is_swapping = false;
......@@ -100,17 +101,23 @@ void DuelClient::StopClient(bool is_exiting) {
}
void DuelClient::ClientRead(bufferevent* bev, void* ctx) {
evbuffer* input = bufferevent_get_input(bev);
size_t len = evbuffer_get_length(input);
int len = evbuffer_get_length(input);
unsigned short packet_len = 0;
while(true) {
if(len < 2)
return;
evbuffer_copyout(input, &packet_len, 2);
if(len < (size_t)packet_len + 2)
if (packet_len + 2 > SIZE_NETWORK_BUFFER) {
ClientEvent(bev, BEV_EVENT_ERROR, 0);
return;
evbuffer_remove(input, duel_client_read, packet_len + 2);
if(packet_len)
HandleSTOCPacketLan(&duel_client_read[2], packet_len);
}
if(len < packet_len + 2)
return;
if (packet_len < 1)
return;
read_len = evbuffer_remove(input, duel_client_read, packet_len + 2);
if (read_len >= 3)
HandleSTOCPacketLan(&duel_client_read[2], read_len - 2);
len -= packet_len + 2;
}
}
......@@ -237,16 +244,22 @@ int DuelClient::ClientThread() {
connect_state = 0;
return 0;
}
void DuelClient::HandleSTOCPacketLan(unsigned char* data, unsigned int len) {
void DuelClient::HandleSTOCPacketLan(unsigned char* data, int len) {
unsigned char* pdata = data;
unsigned char pktType = BufferIO::ReadUInt8(pdata);
switch(pktType) {
case STOC_GAME_MSG: {
if (len < 1 + (int)sizeof(unsigned char))
return;
ClientAnalyze(pdata, len - 1);
break;
}
case STOC_ERROR_MSG: {
STOC_ErrorMsg* pkt = (STOC_ErrorMsg*)pdata;
if (len < 1 + (int)sizeof(STOC_ErrorMsg))
return;
STOC_ErrorMsg packet;
std::memcpy(&packet, pdata, sizeof packet);
const auto* pkt = &packet;
switch(pkt->msg) {
case ERRMSG_JOINERROR: {
mainGame->btnCreateHost->setEnabled(true);
......@@ -362,7 +375,11 @@ void DuelClient::HandleSTOCPacketLan(unsigned char* data, unsigned int len) {
break;
}
case STOC_HAND_RESULT: {
STOC_HandResult* pkt = (STOC_HandResult*)pdata;
if (len < 1 + (int)sizeof(STOC_HandResult))
return;
STOC_HandResult packet;
std::memcpy(&packet, pdata, sizeof packet);
const auto* pkt = &packet;
mainGame->stHintMsg->setVisible(false);
mainGame->showcardcode = (pkt->res1 - 1) + ((pkt->res2 - 1) << 16);
mainGame->showcarddif = 50;
......@@ -419,6 +436,8 @@ void DuelClient::HandleSTOCPacketLan(unsigned char* data, unsigned int len) {
break;
}
case STOC_DECK_COUNT: {
if (len < 1 + (int)sizeof(int16_t) * 6)
return;
mainGame->gMutex.lock();
int deckc = BufferIO::ReadInt16(pdata);
int extrac = BufferIO::ReadInt16(pdata);
......@@ -432,7 +451,11 @@ void DuelClient::HandleSTOCPacketLan(unsigned char* data, unsigned int len) {
break;
}
case STOC_JOIN_GAME: {
STOC_JoinGame* pkt = (STOC_JoinGame*)pdata;
if (len < 1 + (int)sizeof(STOC_JoinGame))
return;
STOC_JoinGame packet;
std::memcpy(&packet, pdata, sizeof packet);
const auto* pkt = &packet;
std::wstring str;
wchar_t msgbuf[256];
myswprintf(msgbuf, L"%ls%ls\n", dataManager.GetSysString(1226), deckManager.GetLFListName(pkt->info.lflist));
......@@ -524,7 +547,11 @@ void DuelClient::HandleSTOCPacketLan(unsigned char* data, unsigned int len) {
break;
}
case STOC_TYPE_CHANGE: {
STOC_TypeChange* pkt = (STOC_TypeChange*)pdata;
if (len < 1 + (int)sizeof(STOC_TypeChange))
return;
STOC_TypeChange packet;
std::memcpy(&packet, pdata, sizeof packet);
const auto* pkt = &packet;
if(!mainGame->dInfo.isTag) {
selftype = pkt->type & 0xf;
is_host = ((pkt->type >> 4) & 0xf) != 0;
......@@ -714,6 +741,8 @@ void DuelClient::HandleSTOCPacketLan(unsigned char* data, unsigned int len) {
break;
}
case STOC_REPLAY: {
if (len < 1 + (int)sizeof(ReplayHeader))
return;
mainGame->gMutex.lock();
mainGame->wPhase->setVisible(false);
if(mainGame->dInfo.player_type < 7)
......@@ -721,7 +750,7 @@ void DuelClient::HandleSTOCPacketLan(unsigned char* data, unsigned int len) {
mainGame->CloseGameButtons();
auto prep = pdata;
Replay new_replay;
memcpy(&new_replay.pheader, prep, sizeof(ReplayHeader));
std::memcpy(&new_replay.pheader, prep, sizeof(new_replay.pheader));
time_t starttime;
if (new_replay.pheader.flag & REPLAY_UNIFORM)
starttime = new_replay.pheader.start_time;
......@@ -750,7 +779,7 @@ void DuelClient::HandleSTOCPacketLan(unsigned char* data, unsigned int len) {
}
if(mainGame->actionParam || !is_host) {
prep += sizeof(ReplayHeader);
memcpy(new_replay.comp_data, prep, len - sizeof(ReplayHeader) - 1);
std::memcpy(new_replay.comp_data, prep, len - sizeof(ReplayHeader) - 1);
new_replay.comp_size = len - sizeof(ReplayHeader) - 1;
if(mainGame->actionParam)
new_replay.SaveReplay(mainGame->ebRSName->getText());
......@@ -760,7 +789,11 @@ void DuelClient::HandleSTOCPacketLan(unsigned char* data, unsigned int len) {
break;
}
case STOC_TIME_LIMIT: {
STOC_TimeLimit* pkt = (STOC_TimeLimit*)pdata;
if (len < 1 + (int)sizeof(STOC_TimeLimit))
return;
STOC_TimeLimit packet;
std::memcpy(&packet, pdata, sizeof packet);
const auto* pkt = &packet;
int lplayer = mainGame->LocalPlayer(pkt->player);
if(lplayer == 0)
DuelClient::SendPacketToServer(CTOS_TIME_CONFIRM);
......@@ -770,8 +803,16 @@ void DuelClient::HandleSTOCPacketLan(unsigned char* data, unsigned int len) {
break;
}
case STOC_CHAT: {
STOC_Chat* pkt = (STOC_Chat*)pdata;
int player = pkt->player;
const int chat_msg_size = len - 1 - sizeof(uint16_t);
if (!check_msg_size(chat_msg_size))
return;
uint16_t chat_player_type = buffer_read<uint16_t>(pdata);
uint16_t chat_msg[LEN_CHAT_MSG];
buffer_read_block(pdata, chat_msg, chat_msg_size);
const int chat_msg_len = chat_msg_size / sizeof(uint16_t);
if (chat_msg[chat_msg_len - 1] != 0)
return;
int player = chat_player_type;
auto play_sound = false;
if(player < 4) {
if(mainGame->chkIgnore1->isChecked())
......@@ -791,16 +832,21 @@ void DuelClient::HandleSTOCPacketLan(unsigned char* data, unsigned int len) {
player = 10;
}
}
wchar_t msg[256];
BufferIO::CopyWStr(pkt->msg, msg, 256);
// UTF-16 to wchar_t
wchar_t msg[LEN_CHAT_MSG];
BufferIO::CopyWStr(chat_msg, msg, LEN_CHAT_MSG);
mainGame->gMutex.lock();
mainGame->AddChatMsg(msg, player, play_sound);
mainGame->gMutex.unlock();
break;
}
case STOC_HS_PLAYER_ENTER: {
if (len < 1 + STOC_HS_PlayerEnter_size)
return;
mainGame->soundManager->PlaySoundEffect(SoundManager::SFX::PLAYER_ENTER);
STOC_HS_PlayerEnter* pkt = (STOC_HS_PlayerEnter*)pdata;
STOC_HS_PlayerEnter packet;
std::memcpy(&packet, pdata, STOC_HS_PlayerEnter_size);
const auto* pkt = &packet;
if(pkt->pos > 3)
break;
wchar_t name[20];
......@@ -831,7 +877,11 @@ void DuelClient::HandleSTOCPacketLan(unsigned char* data, unsigned int len) {
break;
}
case STOC_HS_PLAYER_CHANGE: {
STOC_HS_PlayerChange* pkt = (STOC_HS_PlayerChange*)pdata;
if (len < 1 + (int)sizeof(STOC_HS_PlayerChange))
return;
STOC_HS_PlayerChange packet;
std::memcpy(&packet, pdata, sizeof packet);
const auto* pkt = &packet;
unsigned char pos = (pkt->status >> 4) & 0xf;
unsigned char state = pkt->status & 0xf;
if(pos > 3)
......@@ -839,7 +889,7 @@ void DuelClient::HandleSTOCPacketLan(unsigned char* data, unsigned int len) {
mainGame->gMutex.lock();
if(state < 8) {
mainGame->soundManager->PlaySoundEffect(SoundManager::SFX::PLAYER_ENTER);
wchar_t* prename = (wchar_t*)mainGame->stHostPrepDuelist[pos]->getToolTipText().c_str();
const wchar_t* prename = mainGame->stHostPrepDuelist[pos]->getToolTipText().c_str();
if(mainGame->gameConf.hide_player_name)
mainGame->stHostPrepDuelist[state]->setText(L"[********]");
else
......@@ -895,7 +945,11 @@ void DuelClient::HandleSTOCPacketLan(unsigned char* data, unsigned int len) {
break;
}
case STOC_HS_WATCH_CHANGE: {
STOC_HS_WatchChange* pkt = (STOC_HS_WatchChange*)pdata;
if (len < 1 + (int)sizeof(STOC_HS_WatchChange))
return;
STOC_HS_WatchChange packet;
std::memcpy(&packet, pdata, sizeof packet);
const auto* pkt = &packet;
watching = pkt->watch_count;
wchar_t watchbuf[32];
myswprintf(watchbuf, L"%ls%d", dataManager.GetSysString(1253), watching);
......@@ -908,6 +962,7 @@ void DuelClient::HandleSTOCPacketLan(unsigned char* data, unsigned int len) {
if(!mainGame->dField.tag_surrender)
mainGame->dField.tag_teammate_surrender = true;
mainGame->btnLeaveGame->setText(dataManager.GetSysString(1355));
break;
}
}
}
......@@ -917,7 +972,7 @@ int DuelClient::ClientAnalyze(unsigned char* msg, unsigned int len) {
wchar_t textBuffer[256];
mainGame->dInfo.curMsg = BufferIO::ReadUInt8(pbuf);
if(mainGame->dInfo.curMsg != MSG_RETRY) {
memcpy(last_successful_msg, msg, len);
std::memcpy(last_successful_msg, msg, len);
last_successful_msg_length = len;
}
mainGame->dField.HideMenu();
......@@ -3014,7 +3069,7 @@ int DuelClient::ClientAnalyze(unsigned char* msg, unsigned int len) {
int ct = BufferIO::ReadUInt8(pbuf);
if(mainGame->dInfo.isReplay && mainGame->dInfo.isReplaySkiping)
return true;
if(mainGame->dField.chains.size() > 1 || mainGame->dField.chains.size() == 1 && mainGame->dField.chains[0].need_distinguish || mainGame->gameConf.draw_single_chain) {
if(mainGame->dField.chains.size() > 1 || mainGame->gameConf.draw_single_chain) {
if (mainGame->dField.last_chain)
mainGame->WaitFrameSignal(11);
for(int i = 0; i < 5; ++i) {
......@@ -4055,13 +4110,13 @@ void DuelClient::SwapField() {
is_swapping = true;
}
void DuelClient::SetResponseI(int respI) {
*((int*)response_buf) = respI;
std::memcpy(response_buf, &respI, sizeof respI);
response_len = 4;
}
void DuelClient::SetResponseB(void* respB, unsigned int len) {
if (len > SIZE_RETURN_VALUE)
len = SIZE_RETURN_VALUE;
memcpy(response_buf, respB, len);
std::memcpy(response_buf, respB, len);
response_len = len;
}
void DuelClient::SendResponse() {
......@@ -4184,7 +4239,9 @@ void DuelClient::BroadcastReply(evutil_socket_t fd, short events, void * arg) {
socklen_t sz = sizeof(sockaddr_in);
char buf[256];
/*int ret = */recvfrom(fd, buf, 256, 0, (sockaddr*)&bc_addr, &sz);
HostPacket* pHP = (HostPacket*)buf;
HostPacket packet;
std::memcpy(&packet, buf, sizeof packet);
HostPacket* pHP = &packet;
if(is_closing || pHP->identifier != NETWORK_SERVER_ID)
return;
if(pHP->version != PRO_VERSION)
......
......@@ -27,6 +27,7 @@ private:
static event_base* client_base;
static bufferevent* client_bev;
static unsigned char duel_client_read[SIZE_NETWORK_BUFFER];
static int read_len;
static unsigned char duel_client_write[SIZE_NETWORK_BUFFER];
static bool is_closing;
static bool is_swapping;
......@@ -45,7 +46,7 @@ public:
static void ClientRead(bufferevent* bev, void* ctx);
static void ClientEvent(bufferevent *bev, short events, void *ctx);
static int ClientThread();
static void HandleSTOCPacketLan(unsigned char* data, unsigned int len);
static void HandleSTOCPacketLan(unsigned char* data, int len);
static int ClientAnalyze(unsigned char* msg, unsigned int len);
static void SwapField();
static void SetResponseI(int respI);
......@@ -62,10 +63,10 @@ public:
auto p = duel_client_write;
int blen = sizeof(ST);
if (blen > MAX_DATA_SIZE)
blen = MAX_DATA_SIZE;
return;
BufferIO::WriteInt16(p, (short)(1 + blen));
BufferIO::WriteInt8(p, proto);
memcpy(p, &st, blen);
std::memcpy(p, &st, blen);
bufferevent_write(client_bev, duel_client_write, blen + 3);
}
static void SendBufferToServer(unsigned char proto, void* buffer, size_t len) {
......@@ -77,7 +78,7 @@ public:
blen = MAX_DATA_SIZE;
BufferIO::WriteInt16(p, (short)(1 + blen));
BufferIO::WriteInt8(p, proto);
memcpy(p, buffer, blen);
std::memcpy(p, buffer, blen);
bufferevent_write(client_bev, duel_client_write, blen + 3);
}
......
......@@ -21,7 +21,7 @@
#include <COGLESDriver.h>
#endif
const unsigned short PRO_VERSION = 0x1360;
const unsigned short PRO_VERSION = 0x1361;
namespace ygo {
......
......@@ -10,6 +10,7 @@ event* NetServer::broadcast_ev = 0;
evconnlistener* NetServer::listener = 0;
DuelMode* NetServer::duel_mode = 0;
unsigned char NetServer::net_server_read[SIZE_NETWORK_BUFFER];
int NetServer::read_len = 0;
unsigned char NetServer::net_server_write[SIZE_NETWORK_BUFFER];
unsigned short NetServer::last_sent = 0;
......@@ -84,7 +85,9 @@ void NetServer::BroadcastEvent(evutil_socket_t fd, short events, void* arg) {
int ret = recvfrom(fd, buf, 256, 0, (sockaddr*)&bc_addr, &sz);
if(ret == -1)
return;
HostRequest* pHR = (HostRequest*)buf;
HostRequest packet;
std::memcpy(&packet, buf, sizeof packet);
const HostRequest* pHR = &packet;
if(pHR->identifier == NETWORK_CLIENT_ID) {
SOCKADDR_IN sockTo;
sockTo.sin_addr.s_addr = bc_addr.sin_addr.s_addr;
......@@ -112,19 +115,30 @@ void NetServer::ServerAccept(evconnlistener* listener, evutil_socket_t fd, socka
void NetServer::ServerAcceptError(evconnlistener* listener, void* ctx) {
event_base_loopexit(net_evbase, 0);
}
/*
* packet_len: 2 bytes
* proto: 1 byte
* [data]: (packet_len - 1) bytes
*/
void NetServer::ServerEchoRead(bufferevent *bev, void *ctx) {
evbuffer* input = bufferevent_get_input(bev);
size_t len = evbuffer_get_length(input);
int len = evbuffer_get_length(input);
unsigned short packet_len = 0;
while(true) {
if(len < 2)
return;
evbuffer_copyout(input, &packet_len, 2);
if(len < (size_t)packet_len + 2)
if (packet_len + 2 > SIZE_NETWORK_BUFFER) {
ServerEchoEvent(bev, BEV_EVENT_ERROR, 0);
return;
evbuffer_remove(input, net_server_read, packet_len + 2);
if(packet_len)
HandleCTOSPacket(&users[bev], &net_server_read[2], packet_len);
}
if (len < packet_len + 2)
return;
if (packet_len < 1)
return;
read_len = evbuffer_remove(input, net_server_read, packet_len + 2);
if (read_len >= 3)
HandleCTOSPacket(&users[bev], &net_server_read[2], read_len - 2);
len -= packet_len + 2;
}
}
......@@ -134,7 +148,8 @@ void NetServer::ServerEchoEvent(bufferevent* bev, short events, void* ctx) {
DuelMode* dm = dp->game;
if(dm)
dm->LeaveGame(dp);
else DisconnectPlayer(dp);
else
DisconnectPlayer(dp);
}
}
int NetServer::ServerThread() {
......@@ -171,7 +186,7 @@ void NetServer::DisconnectPlayer(DuelPlayer* dp) {
users.erase(bit);
}
}
void NetServer::HandleCTOSPacket(DuelPlayer* dp, unsigned char* data, unsigned int len) {
void NetServer::HandleCTOSPacket(DuelPlayer* dp, unsigned char* data, int len) {
auto pdata = data;
unsigned char pktType = BufferIO::ReadUInt8(pdata);
if((pktType != CTOS_SURRENDER) && (pktType != CTOS_CHAT) && (dp->state == 0xff || (dp->state && dp->state != pktType)))
......@@ -180,6 +195,8 @@ void NetServer::HandleCTOSPacket(DuelPlayer* dp, unsigned char* data, unsigned i
case CTOS_RESPONSE: {
if(!dp->game || !duel_mode->pduel)
return;
if (len < 1 + (int)sizeof(unsigned char))
return;
duel_mode->GetResponse(dp, pdata, len - 1);
break;
}
......@@ -192,38 +209,58 @@ void NetServer::HandleCTOSPacket(DuelPlayer* dp, unsigned char* data, unsigned i
case CTOS_CHAT: {
if(!dp->game)
return;
if (len < 1 + (int)sizeof(unsigned char))
return;
duel_mode->Chat(dp, pdata, len - 1);
break;
}
case CTOS_UPDATE_DECK: {
if(!dp->game)
return;
if (len < 1 + (int)sizeof(unsigned char))
return;
duel_mode->UpdateDeck(dp, pdata, len - 1);
break;
}
case CTOS_HAND_RESULT: {
if(!dp->game)
return;
CTOS_HandResult* pkt = (CTOS_HandResult*)pdata;
if (len < 1 + (int)sizeof(CTOS_HandResult))
return;
CTOS_HandResult packet;
std::memcpy(&packet, pdata, sizeof packet);
const auto* pkt = &packet;
dp->game->HandResult(dp, pkt->res);
break;
}
case CTOS_TP_RESULT: {
if(!dp->game)
return;
CTOS_TPResult* pkt = (CTOS_TPResult*)pdata;
if (len < 1 + (int)sizeof(CTOS_TPResult))
return;
CTOS_TPResult packet;
std::memcpy(&packet, pdata, sizeof packet);
const auto* pkt = &packet;
dp->game->TPResult(dp, pkt->res);
break;
}
case CTOS_PLAYER_INFO: {
CTOS_PlayerInfo* pkt = (CTOS_PlayerInfo*)pdata;
if (len < 1 + (int)sizeof(CTOS_PlayerInfo))
return;
CTOS_PlayerInfo packet;
std::memcpy(&packet, pdata, sizeof packet);
const auto* pkt = &packet;
BufferIO::CopyWStr(pkt->name, dp->name, 20);
break;
}
case CTOS_CREATE_GAME: {
if(dp->game || duel_mode)
return;
CTOS_CreateGame* pkt = (CTOS_CreateGame*)pdata;
if (len < 1 + (int)sizeof(CTOS_CreateGame))
return;
CTOS_CreateGame packet;
std::memcpy(&packet, pdata, sizeof packet);
auto pkt = &packet;
if(pkt->info.mode == MODE_SINGLE) {
duel_mode = new SingleDuel(false);
duel_mode->etimer = event_new(net_evbase, 0, EV_TIMEOUT | EV_PERSIST, SingleDuel::SingleTimer, duel_mode);
......@@ -261,56 +298,76 @@ void NetServer::HandleCTOSPacket(DuelPlayer* dp, unsigned char* data, unsigned i
break;
}
case CTOS_JOIN_GAME: {
if(!duel_mode)
break;
if (!duel_mode)
return;
if (len < 1 + (int)sizeof(CTOS_JoinGame))
return;
duel_mode->JoinGame(dp, pdata, false);
break;
}
case CTOS_LEAVE_GAME: {
if(!duel_mode)
break;
if (!duel_mode)
return;
duel_mode->LeaveGame(dp);
break;
}
case CTOS_SURRENDER: {
if(!duel_mode)
break;
if (!duel_mode)
return;
duel_mode->Surrender(dp);
break;
}
case CTOS_HS_TODUELIST: {
if(!duel_mode || duel_mode->pduel)
break;
if (!duel_mode || duel_mode->pduel)
return;
duel_mode->ToDuelist(dp);
break;
}
case CTOS_HS_TOOBSERVER: {
if(!duel_mode || duel_mode->pduel)
break;
if (!duel_mode || duel_mode->pduel)
return;
duel_mode->ToObserver(dp);
break;
}
case CTOS_HS_READY:
case CTOS_HS_NOTREADY: {
if(!duel_mode || duel_mode->pduel)
break;
if (!duel_mode || duel_mode->pduel)
return;
duel_mode->PlayerReady(dp, (CTOS_HS_NOTREADY - pktType) != 0);
break;
}
case CTOS_HS_KICK: {
if(!duel_mode || duel_mode->pduel)
break;
CTOS_Kick* pkt = (CTOS_Kick*)pdata;
if (!duel_mode || duel_mode->pduel)
return;
if (len < 1 + (int)sizeof(CTOS_Kick))
return;
CTOS_Kick packet;
std::memcpy(&packet, pdata, sizeof packet);
const auto* pkt = &packet;
duel_mode->PlayerKick(dp, pkt->pos);
break;
}
case CTOS_HS_START: {
if(!duel_mode || duel_mode->pduel)
break;
if (!duel_mode || duel_mode->pduel)
return;
duel_mode->StartDuel(dp);
break;
}
}
}
size_t NetServer::CreateChatPacket(unsigned char* src, int src_size, unsigned char* dst, uint16_t dst_player_type) {
if (!check_msg_size(src_size))
return 0;
uint16_t src_msg[LEN_CHAT_MSG];
std::memcpy(src_msg, src, src_size);
const int src_len = src_size / sizeof(uint16_t);
if (src_msg[src_len - 1] != 0)
return 0;
// STOC_Chat packet
auto pdst = dst;
buffer_write<uint16_t>(pdst, dst_player_type);
buffer_write_block(pdst, src_msg, src_size);
return sizeof(dst_player_type) + src_size;
}
}
......@@ -19,6 +19,7 @@ private:
static evconnlistener* listener;
static DuelMode* duel_mode;
static unsigned char net_server_read[SIZE_NETWORK_BUFFER];
static int read_len;
static unsigned char net_server_write[SIZE_NETWORK_BUFFER];
static unsigned short last_sent;
......@@ -35,7 +36,8 @@ public:
static void ServerEchoEvent(bufferevent* bev, short events, void* ctx);
static int ServerThread();
static void DisconnectPlayer(DuelPlayer* dp);
static void HandleCTOSPacket(DuelPlayer* dp, unsigned char* data, unsigned int len);
static void HandleCTOSPacket(DuelPlayer* dp, unsigned char* data, int len);
static size_t CreateChatPacket(unsigned char* src, int src_size, unsigned char* dst, uint16_t dst_player_type);
static void SendPacketToPlayer(DuelPlayer* dp, unsigned char proto) {
auto p = net_server_write;
BufferIO::WriteInt16(p, 1);
......@@ -50,10 +52,10 @@ public:
auto p = net_server_write;
int blen = sizeof(ST);
if (blen > MAX_DATA_SIZE)
blen = MAX_DATA_SIZE;
return;
BufferIO::WriteInt16(p, (short)(1 + blen));
BufferIO::WriteInt8(p, proto);
memcpy(p, &st, blen);
std::memcpy(p, &st, blen);
last_sent = blen + 3;
if (dp)
bufferevent_write(dp->bev, net_server_write, blen + 3);
......@@ -67,7 +69,7 @@ public:
blen = MAX_DATA_SIZE;
BufferIO::WriteInt16(p, (short)(1 + blen));
BufferIO::WriteInt8(p, proto);
memcpy(p, buffer, blen);
std::memcpy(p, buffer, blen);
last_sent = blen + 3;
if (dp)
bufferevent_write(dp->bev, net_server_write, blen + 3);
......
......@@ -8,95 +8,176 @@
#include <event2/bufferevent.h>
#include <event2/buffer.h>
#include <event2/thread.h>
#include <type_traits>
#define check_trivially_copyable(T) static_assert(std::is_trivially_copyable<T>::value == true && std::is_standard_layout<T>::value == true, "not trivially copyable")
namespace ygo {
constexpr int SIZE_NETWORK_BUFFER = 0x2000;
constexpr int MAX_DATA_SIZE = SIZE_NETWORK_BUFFER - 3;
constexpr int MAINC_MAX = 250; // the limit of card_state
constexpr int SIDEC_MAX = MAINC_MAX;
struct HostInfo {
unsigned int lflist{ 0 };
unsigned char rule{ 0 };
unsigned char mode{ 0 };
unsigned char duel_rule{ 0 };
bool no_check_deck{ false };
bool no_shuffle_deck{ false };
unsigned int start_lp{ 0 };
unsigned char start_hand{ 0 };
unsigned char draw_count{ 0 };
unsigned short time_limit{ 0 };
uint32_t lflist{};
unsigned char rule{};
unsigned char mode{};
unsigned char duel_rule{};
unsigned char no_check_deck{};
unsigned char no_shuffle_deck{};
// byte padding[3]
uint32_t start_lp{};
unsigned char start_hand{};
unsigned char draw_count{};
uint16_t time_limit{};
};
check_trivially_copyable(HostInfo);
static_assert(sizeof(HostInfo) == 20, "size mismatch: HostInfo");
struct HostPacket {
unsigned short identifier;
unsigned short version;
unsigned short port;
unsigned int ipaddr;
unsigned short name[20];
uint16_t identifier;
uint16_t version;
uint16_t port;
// byte padding[2]
uint32_t ipaddr;
uint16_t name[20];
HostInfo host;
};
check_trivially_copyable(HostPacket);
static_assert(sizeof(HostPacket) == 72, "size mismatch: HostPacket");
struct HostRequest {
unsigned short identifier;
uint16_t identifier;
};
check_trivially_copyable(HostRequest);
static_assert(sizeof(HostRequest) == 2, "size mismatch: HostRequest");
struct CTOS_HandResult {
unsigned char res;
};
check_trivially_copyable(CTOS_HandResult);
static_assert(sizeof(CTOS_HandResult) == 1, "size mismatch: CTOS_HandResult");
struct CTOS_TPResult {
unsigned char res;
};
check_trivially_copyable(CTOS_TPResult);
static_assert(sizeof(CTOS_TPResult) == 1, "size mismatch: CTOS_TPResult");
struct CTOS_PlayerInfo {
unsigned short name[20];
uint16_t name[20];
};
check_trivially_copyable(CTOS_PlayerInfo);
static_assert(sizeof(CTOS_PlayerInfo) == 40, "size mismatch: CTOS_PlayerInfo");
struct CTOS_CreateGame {
HostInfo info;
unsigned short name[20];
unsigned short pass[20];
uint16_t name[20];
uint16_t pass[20];
};
check_trivially_copyable(CTOS_CreateGame);
static_assert(sizeof(CTOS_CreateGame) == 100, "size mismatch: CTOS_CreateGame");
struct CTOS_JoinGame {
unsigned short version;
unsigned int gameid;
unsigned short pass[20];
uint16_t version;
// byte padding[2]
uint32_t gameid;
uint16_t pass[20];
};
check_trivially_copyable(CTOS_JoinGame);
static_assert(sizeof(CTOS_JoinGame) == 48, "size mismatch: CTOS_JoinGame");
struct CTOS_Kick {
unsigned char pos;
};
check_trivially_copyable(CTOS_Kick);
static_assert(sizeof(CTOS_Kick) == 1, "size mismatch: CTOS_Kick");
// STOC
struct STOC_ErrorMsg {
unsigned char msg;
unsigned int code;
// byte padding[3]
uint32_t code;
};
check_trivially_copyable(STOC_ErrorMsg);
static_assert(sizeof(STOC_ErrorMsg) == 8, "size mismatch: STOC_ErrorMsg");
struct STOC_HandResult {
unsigned char res1;
unsigned char res2;
};
check_trivially_copyable(STOC_HandResult);
static_assert(sizeof(STOC_HandResult) == 2, "size mismatch: STOC_HandResult");
// reserved for STOC_CREATE_GAME
struct STOC_CreateGame {
unsigned int gameid;
uint32_t gameid;
};
check_trivially_copyable(STOC_CreateGame);
static_assert(sizeof(STOC_CreateGame) == 4, "size mismatch: STOC_CreateGame");
struct STOC_JoinGame {
HostInfo info;
};
check_trivially_copyable(STOC_JoinGame);
static_assert(sizeof(STOC_JoinGame) == 20, "size mismatch: STOC_JoinGame");
struct STOC_TypeChange {
unsigned char type;
};
check_trivially_copyable(STOC_TypeChange);
static_assert(sizeof(STOC_TypeChange) == 1, "size mismatch: STOC_TypeChange");
// reserved for STOC_LEAVE_GAME
struct STOC_ExitGame {
unsigned char pos;
};
check_trivially_copyable(STOC_ExitGame);
static_assert(sizeof(STOC_ExitGame) == 1, "size mismatch: STOC_ExitGame");
struct STOC_TimeLimit {
unsigned char player;
unsigned short left_time;
};
struct STOC_Chat {
unsigned short player;
unsigned short msg[256];
// byte padding[1]
uint16_t left_time;
};
check_trivially_copyable(STOC_TimeLimit);
static_assert(sizeof(STOC_TimeLimit) == 4, "size mismatch: STOC_TimeLimit");
/*
* STOC_Chat
* uint16_t player_type;
* uint16_t msg[256]; (UTF-16 string)
*/
constexpr int LEN_CHAT_PLAYER = 1;
constexpr int LEN_CHAT_MSG = 256;
constexpr int SIZE_STOC_CHAT = (LEN_CHAT_PLAYER + LEN_CHAT_MSG) * sizeof(uint16_t);
struct STOC_HS_PlayerEnter {
unsigned short name[20];
uint16_t name[20];
unsigned char pos;
// byte padding[1]
};
check_trivially_copyable(STOC_HS_PlayerEnter);
//static_assert(sizeof(STOC_HS_PlayerEnter) == 42, "size mismatch: STOC_HS_PlayerEnter");
constexpr int STOC_HS_PlayerEnter_size = 41; //workwround
struct STOC_HS_PlayerChange {
//pos<<4 | state
unsigned char status;
};
check_trivially_copyable(STOC_HS_PlayerChange);
static_assert(sizeof(STOC_HS_PlayerChange) == 1, "size mismatch: STOC_HS_PlayerChange");
struct STOC_HS_WatchChange {
unsigned short watch_count;
uint16_t watch_count;
};
check_trivially_copyable(STOC_HS_WatchChange);
static_assert(sizeof(STOC_HS_WatchChange) == 2, "size mismatch: STOC_HS_WatchChange");
class DuelMode;
......@@ -108,18 +189,34 @@ struct DuelPlayer {
bufferevent* bev{ 0 };
};
inline bool check_msg_size(int size) {
// empty string is not allowed
if (size < 2* sizeof(uint16_t))
return false;
if (size > LEN_CHAT_MSG * sizeof(uint16_t))
return false;
if (size % sizeof(uint16_t) != 0)
return false;
return true;
}
inline unsigned int GetPosition(unsigned char* qbuf, int offset) {
unsigned int info = 0;
std::memcpy(&info, qbuf + offset, sizeof info);
return info >> 24;
}
class DuelMode {
public:
DuelMode(): host_player(nullptr), pduel(0), duel_stage(0) {}
virtual ~DuelMode() {}
virtual void Chat(DuelPlayer* dp, void* pdata, int len) {}
virtual void JoinGame(DuelPlayer* dp, void* pdata, bool is_creater) {}
virtual void Chat(DuelPlayer* dp, unsigned char* pdata, int len) {}
virtual void JoinGame(DuelPlayer* dp, unsigned char* pdata, bool is_creater) {}
virtual void LeaveGame(DuelPlayer* dp) {}
virtual void ToDuelist(DuelPlayer* dp) {}
virtual void ToObserver(DuelPlayer* dp) {}
virtual void PlayerReady(DuelPlayer* dp, bool is_ready) {}
virtual void PlayerKick(DuelPlayer* dp, unsigned char pos) {}
virtual void UpdateDeck(DuelPlayer* dp, void* pdata, unsigned int len) {}
virtual void UpdateDeck(DuelPlayer* dp, unsigned char* pdata, int len) {}
virtual void StartDuel(DuelPlayer* dp) {}
virtual void HandResult(DuelPlayer* dp, unsigned char res) {}
virtual void TPResult(DuelPlayer* dp, unsigned char tp) {}
......@@ -128,18 +225,18 @@ public:
return 0;
}
virtual void Surrender(DuelPlayer* dp) {}
virtual void GetResponse(DuelPlayer* dp, void* pdata, unsigned int len) {}
virtual void GetResponse(DuelPlayer* dp, unsigned char* pdata, unsigned int len) {}
virtual void TimeConfirm(DuelPlayer* dp) {}
virtual void EndDuel() {};
virtual void EndDuel() {}
public:
event* etimer;
DuelPlayer* host_player;
event* etimer { nullptr };
DuelPlayer* host_player{ nullptr };
HostInfo host_info;
int duel_stage;
intptr_t pduel;
wchar_t name[20];
wchar_t pass[20];
int duel_stage{};
intptr_t pduel{};
wchar_t name[20]{};
wchar_t pass[20]{};
};
}
......@@ -155,46 +252,48 @@ public:
#define NETPLAYER_TYPE_PLAYER6 5
#define NETPLAYER_TYPE_OBSERVER 7
#define CTOS_RESPONSE 0x1
#define CTOS_UPDATE_DECK 0x2
#define CTOS_HAND_RESULT 0x3
#define CTOS_TP_RESULT 0x4
#define CTOS_PLAYER_INFO 0x10
#define CTOS_CREATE_GAME 0x11
#define CTOS_JOIN_GAME 0x12
#define CTOS_LEAVE_GAME 0x13
#define CTOS_SURRENDER 0x14
#define CTOS_TIME_CONFIRM 0x15
#define CTOS_CHAT 0x16
#define CTOS_HS_TODUELIST 0x20
#define CTOS_HS_TOOBSERVER 0x21
#define CTOS_HS_READY 0x22
#define CTOS_HS_NOTREADY 0x23
#define CTOS_HS_KICK 0x24
#define CTOS_HS_START 0x25
#define STOC_GAME_MSG 0x1
#define STOC_ERROR_MSG 0x2
#define STOC_SELECT_HAND 0x3
#define STOC_SELECT_TP 0x4
#define STOC_HAND_RESULT 0x5
#define STOC_TP_RESULT 0x6
#define STOC_CHANGE_SIDE 0x7
#define STOC_WAITING_SIDE 0x8
#define STOC_DECK_COUNT 0x9
#define STOC_CREATE_GAME 0x11
#define STOC_JOIN_GAME 0x12
#define STOC_TYPE_CHANGE 0x13
#define STOC_LEAVE_GAME 0x14
#define STOC_DUEL_START 0x15
#define STOC_DUEL_END 0x16
#define STOC_REPLAY 0x17
#define STOC_TIME_LIMIT 0x18
#define STOC_CHAT 0x19
#define STOC_HS_PLAYER_ENTER 0x20
#define STOC_HS_PLAYER_CHANGE 0x21
#define STOC_HS_WATCH_CHANGE 0x22
#define STOC_TEAMMATE_SURRENDER 0x23
#define CTOS_RESPONSE 0x1 // byte array
#define CTOS_UPDATE_DECK 0x2 // int32_t array
#define CTOS_HAND_RESULT 0x3 // CTOS_HandResult
#define CTOS_TP_RESULT 0x4 // CTOS_TPResult
#define CTOS_PLAYER_INFO 0x10 // CTOS_PlayerInfo
#define CTOS_CREATE_GAME 0x11 // CTOS_CreateGame
#define CTOS_JOIN_GAME 0x12 // CTOS_JoinGame
#define CTOS_LEAVE_GAME 0x13 // no data
#define CTOS_SURRENDER 0x14 // no data
#define CTOS_TIME_CONFIRM 0x15 // no data
#define CTOS_CHAT 0x16 // uint16_t array
#define CTOS_HS_TODUELIST 0x20 // no data
#define CTOS_HS_TOOBSERVER 0x21 // no data
#define CTOS_HS_READY 0x22 // no data
#define CTOS_HS_NOTREADY 0x23 // no data
#define CTOS_HS_KICK 0x24 // CTOS_Kick
#define CTOS_HS_START 0x25 // no data
#define CTOS_REQUEST_FIELD 0x30
#define STOC_GAME_MSG 0x1 // byte array
#define STOC_ERROR_MSG 0x2 // STOC_ErrorMsg
#define STOC_SELECT_HAND 0x3 // no data
#define STOC_SELECT_TP 0x4 // no data
#define STOC_HAND_RESULT 0x5 // STOC_HandResult
#define STOC_TP_RESULT 0x6 // reserved
#define STOC_CHANGE_SIDE 0x7 // no data
#define STOC_WAITING_SIDE 0x8 // no data
#define STOC_DECK_COUNT 0x9 // int16_t[6]
#define STOC_CREATE_GAME 0x11 // reserved
#define STOC_JOIN_GAME 0x12 // STOC_JoinGame
#define STOC_TYPE_CHANGE 0x13 // STOC_TypeChange
#define STOC_LEAVE_GAME 0x14 // reserved
#define STOC_DUEL_START 0x15 // no data
#define STOC_DUEL_END 0x16 // no data
#define STOC_REPLAY 0x17 // ReplayHeader + byte array
#define STOC_TIME_LIMIT 0x18 // STOC_TimeLimit
#define STOC_CHAT 0x19 // uint16_t + uint16_t array
#define STOC_HS_PLAYER_ENTER 0x20 // STOC_HS_PlayerEnter
#define STOC_HS_PLAYER_CHANGE 0x21 // STOC_HS_PlayerChange
#define STOC_HS_WATCH_CHANGE 0x22 // STOC_HS_WatchChange
#define STOC_TEAMMATE_SURRENDER 0x23 // no data
#define STOC_FIELD_FINISH 0x30
#define PLAYERCHANGE_OBSERVE 0x8
#define PLAYERCHANGE_READY 0x9
......
......@@ -940,7 +940,7 @@ uint32 ReplayMode::MessageHandler(intptr_t fduel, uint32 type) {
if(!enable_log)
return 0;
char msgbuf[1024];
get_log_message(fduel, (byte*)msgbuf);
get_log_message(fduel, msgbuf);
mainGame->AddDebugMsg(msgbuf);
return 0;
}
......
......@@ -12,17 +12,17 @@ SingleDuel::SingleDuel(bool is_match) {
}
SingleDuel::~SingleDuel() {
}
void SingleDuel::Chat(DuelPlayer* dp, void* pdata, int len) {
STOC_Chat scc;
scc.player = dp->type;
unsigned short* msg = (unsigned short*)pdata;
int msglen = BufferIO::CopyWStr(msg, scc.msg, 256);
NetServer::SendBufferToPlayer(players[0], STOC_CHAT, &scc, 4 + msglen * 2);
void SingleDuel::Chat(DuelPlayer* dp, unsigned char* pdata, int len) {
unsigned char scc[SIZE_STOC_CHAT];
const auto scc_size = NetServer::CreateChatPacket(pdata, len, scc, dp->type);
if (!scc_size)
return;
NetServer::SendBufferToPlayer(players[0], STOC_CHAT, scc, scc_size);
NetServer::ReSendToPlayer(players[1]);
for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::ReSendToPlayer(*pit);
}
void SingleDuel::JoinGame(DuelPlayer* dp, void* pdata, bool is_creater) {
void SingleDuel::JoinGame(DuelPlayer* dp, unsigned char* pdata, bool is_creater) {
if(!is_creater) {
if(dp->game && dp->type != 0xff) {
STOC_ErrorMsg scem;
......@@ -32,7 +32,9 @@ void SingleDuel::JoinGame(DuelPlayer* dp, void* pdata, bool is_creater) {
NetServer::DisconnectPlayer(dp);
return;
}
CTOS_JoinGame* pkt = (CTOS_JoinGame*)pdata;
CTOS_JoinGame packet;
std::memcpy(&packet, pdata, sizeof packet);
const auto* pkt = &packet;
if(pkt->version != PRO_VERSION) {
STOC_ErrorMsg scem;
scem.msg = ERRMSG_VERERROR;
......@@ -272,25 +274,35 @@ void SingleDuel::PlayerKick(DuelPlayer* dp, unsigned char pos) {
return;
LeaveGame(players[pos]);
}
void SingleDuel::UpdateDeck(DuelPlayer* dp, void* pdata, unsigned int len) {
void SingleDuel::UpdateDeck(DuelPlayer* dp, unsigned char* pdata, int len) {
if(dp->type > 1 || ready[dp->type])
return;
unsigned char* deckbuf = (unsigned char*)pdata;
if (len < 8)
return;
bool valid = true;
auto deckbuf = pdata;
int mainc = BufferIO::ReadInt32(deckbuf);
int sidec = BufferIO::ReadInt32(deckbuf);
// verify data
const unsigned int possibleMaxLength = (len - 8) / 4;
if((unsigned)mainc > possibleMaxLength || (unsigned)sidec > possibleMaxLength || (unsigned)mainc + (unsigned)sidec > possibleMaxLength) {
const int deck_size = len - 2 * sizeof(int32_t);
if (mainc < 0 || mainc > MAINC_MAX)
valid = false;
else if (sidec < 0 || sidec > SIDEC_MAX)
valid = false;
else if (deck_size != (mainc + sidec) * (int)sizeof(int32_t))
valid = false;
if (!valid) {
STOC_ErrorMsg scem;
scem.msg = ERRMSG_DECKERROR;
scem.code = 0;
NetServer::SendPacketToPlayer(dp, STOC_ERROR_MSG, scem);
return;
}
int deck_list[SIZE_NETWORK_BUFFER / sizeof(int32_t)];
std::memcpy(deck_list, deckbuf, deck_size);
if(duel_count == 0) {
deck_error[dp->type] = deckManager.LoadDeck(pdeck[dp->type], (int*)deckbuf, mainc, sidec);
deck_error[dp->type] = deckManager.LoadDeck(pdeck[dp->type], deck_list, mainc, sidec);
} else {
if(deckManager.LoadSide(pdeck[dp->type], (int*)deckbuf, mainc, sidec)) {
if(deckManager.LoadSide(pdeck[dp->type], deck_list, mainc, sidec)) {
ready[dp->type] = true;
NetServer::SendPacketToPlayer(dp, STOC_DUEL_START);
if(ready[0] && ready[1]) {
......@@ -330,9 +342,9 @@ void SingleDuel::StartDuel(DuelPlayer* dp) {
BufferIO::WriteInt16(pbuf, (short)pdeck[1].side.size());
NetServer::SendBufferToPlayer(players[0], STOC_DECK_COUNT, deckbuff, 12);
char tempbuff[6];
memcpy(tempbuff, deckbuff, 6);
memcpy(deckbuff, deckbuff + 6, 6);
memcpy(deckbuff + 6, tempbuff, 6);
std::memcpy(tempbuff, deckbuff, 6);
std::memcpy(deckbuff, deckbuff + 6, 6);
std::memcpy(deckbuff + 6, tempbuff, 6);
NetServer::SendBufferToPlayer(players[1], STOC_DECK_COUNT, deckbuff, 12);
NetServer::SendPacketToPlayer(players[0], STOC_SELECT_HAND);
NetServer::ReSendToPlayer(players[1]);
......@@ -1404,11 +1416,11 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
}
return 0;
}
void SingleDuel::GetResponse(DuelPlayer* dp, void* pdata, unsigned int len) {
void SingleDuel::GetResponse(DuelPlayer* dp, unsigned char* pdata, unsigned int len) {
byte resb[SIZE_RETURN_VALUE];
if (len > SIZE_RETURN_VALUE)
len = SIZE_RETURN_VALUE;
memcpy(resb, pdata, len);
std::memcpy(resb, pdata, len);
last_replay.WriteInt8(len);
last_replay.WriteData(resb, len);
set_responseb(pduel, resb);
......@@ -1426,9 +1438,9 @@ void SingleDuel::EndDuel() {
return;
last_replay.EndRecord();
char replaybuf[0x2000], *pbuf = replaybuf;
memcpy(pbuf, &last_replay.pheader, sizeof(ReplayHeader));
std::memcpy(pbuf, &last_replay.pheader, sizeof(ReplayHeader));
pbuf += sizeof(ReplayHeader);
memcpy(pbuf, last_replay.comp_data, last_replay.comp_size);
std::memcpy(pbuf, last_replay.comp_data, last_replay.comp_size);
NetServer::SendBufferToPlayer(players[0], STOC_REPLAY, replaybuf, sizeof(ReplayHeader) + last_replay.comp_size);
NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
......@@ -1468,10 +1480,6 @@ inline int SingleDuel::WriteUpdateData(int& player, int location, int& flag, uns
int len = query_field_card(pduel, player, location, flag, qbuf, use_cache);
return len;
}
inline unsigned int GetPosition(unsigned char*& qbuf, int offset) {
unsigned int info = *(unsigned int*)(qbuf + offset);
return info >> 24;
}
void SingleDuel::RefreshMzone(int player, int flag, int use_cache) {
std::vector<unsigned char> query_buffer;
query_buffer.resize(SIZE_QUERY_BUFFER);
......@@ -1579,7 +1587,7 @@ uint32 SingleDuel::MessageHandler(intptr_t fduel, uint32 type) {
if(!enable_log)
return 0;
char msgbuf[1024];
get_log_message(fduel, (byte*)msgbuf);
get_log_message(fduel, msgbuf);
mainGame->AddDebugMsg(msgbuf);
return 0;
}
......
......@@ -11,21 +11,21 @@ class SingleDuel: public DuelMode {
public:
SingleDuel(bool is_match);
virtual ~SingleDuel();
virtual void Chat(DuelPlayer* dp, void* pdata, int len);
virtual void JoinGame(DuelPlayer* dp, void* pdata, bool is_creater);
virtual void Chat(DuelPlayer* dp, unsigned char* pdata, int len);
virtual void JoinGame(DuelPlayer* dp, unsigned char* pdata, bool is_creater);
virtual void LeaveGame(DuelPlayer* dp);
virtual void ToDuelist(DuelPlayer* dp);
virtual void ToObserver(DuelPlayer* dp);
virtual void PlayerReady(DuelPlayer* dp, bool ready);
virtual void PlayerKick(DuelPlayer* dp, unsigned char pos);
virtual void UpdateDeck(DuelPlayer* dp, void* pdata, unsigned int len);
virtual void UpdateDeck(DuelPlayer* dp, unsigned char* pdata, int len);
virtual void StartDuel(DuelPlayer* dp);
virtual void HandResult(DuelPlayer* dp, unsigned char res);
virtual void TPResult(DuelPlayer* dp, unsigned char tp);
virtual void Process();
virtual void Surrender(DuelPlayer* dp);
virtual int Analyze(unsigned char* msgbuffer, unsigned int len);
virtual void GetResponse(DuelPlayer* dp, void* pdata, unsigned int len);
virtual void GetResponse(DuelPlayer* dp, unsigned char* pdata, unsigned int len);
virtual void TimeConfirm(DuelPlayer* dp);
virtual void EndDuel();
......
......@@ -741,7 +741,7 @@ bool SingleMode::SinglePlayAnalyze(unsigned char* msg, unsigned int len) {
int len = BufferIO::ReadInt16(pbuf);
auto begin = pbuf;
pbuf += len + 1;
memcpy(namebuf, begin, len + 1);
std::memcpy(namebuf, begin, len + 1);
BufferIO::DecodeUTF8(namebuf, wname);
BufferIO::CopyWStr(wname, mainGame->dInfo.clientname, 20);
break;
......@@ -752,7 +752,7 @@ bool SingleMode::SinglePlayAnalyze(unsigned char* msg, unsigned int len) {
int len = BufferIO::ReadInt16(pbuf);
auto begin = pbuf;
pbuf += len + 1;
memcpy(msgbuf, begin, len + 1);
std::memcpy(msgbuf, begin, len + 1);
BufferIO::DecodeUTF8(msgbuf, msg);
mainGame->gMutex.lock();
mainGame->SetStaticText(mainGame->stMessage, 370 * mainGame->xScale, mainGame->guiFont, msg);
......@@ -826,7 +826,7 @@ uint32 SingleMode::MessageHandler(intptr_t fduel, uint32 type) {
if(!enable_log)
return 0;
char msgbuf[1024];
get_log_message(fduel, (byte*)msgbuf);
get_log_message(fduel, msgbuf);
mainGame->AddDebugMsg(msgbuf);
return 0;
}
......
......@@ -16,17 +16,17 @@ TagDuel::TagDuel() {
}
TagDuel::~TagDuel() {
}
void TagDuel::Chat(DuelPlayer* dp, void* pdata, int len) {
STOC_Chat scc;
scc.player = dp->type;
unsigned short* msg = (unsigned short*)pdata;
int msglen = BufferIO::CopyWStr(msg, scc.msg, 256);
void TagDuel::Chat(DuelPlayer* dp, unsigned char* pdata, int len) {
unsigned char scc[SIZE_STOC_CHAT];
const auto scc_size = NetServer::CreateChatPacket(pdata, len, scc, dp->type);
if (!scc_size)
return;
for(int i = 0; i < 4; ++i)
NetServer::SendBufferToPlayer(players[i], STOC_CHAT, &scc, 4 + msglen * 2);
NetServer::SendBufferToPlayer(players[i], STOC_CHAT, scc, scc_size);
for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::ReSendToPlayer(*pit);
}
void TagDuel::JoinGame(DuelPlayer* dp, void* pdata, bool is_creater) {
void TagDuel::JoinGame(DuelPlayer* dp, unsigned char* pdata, bool is_creater) {
if(!is_creater) {
if(dp->game && dp->type != 0xff) {
STOC_ErrorMsg scem;
......@@ -36,7 +36,9 @@ void TagDuel::JoinGame(DuelPlayer* dp, void* pdata, bool is_creater) {
NetServer::DisconnectPlayer(dp);
return;
}
CTOS_JoinGame* pkt = (CTOS_JoinGame*)pdata;
CTOS_JoinGame packet;
std::memcpy(&packet, pdata, sizeof packet);
const auto* pkt = &packet;
if(pkt->version != PRO_VERSION) {
STOC_ErrorMsg scem;
scem.msg = ERRMSG_VERERROR;
......@@ -255,22 +257,32 @@ void TagDuel::PlayerKick(DuelPlayer* dp, unsigned char pos) {
return;
LeaveGame(players[pos]);
}
void TagDuel::UpdateDeck(DuelPlayer* dp, void* pdata, unsigned int len) {
void TagDuel::UpdateDeck(DuelPlayer* dp, unsigned char* pdata, int len) {
if(dp->type > 3 || ready[dp->type])
return;
unsigned char* deckbuf = (unsigned char*)pdata;
if (len < 8)
return;
bool valid = true;
auto deckbuf = pdata;
int mainc = BufferIO::ReadInt32(deckbuf);
int sidec = BufferIO::ReadInt32(deckbuf);
// verify data
const unsigned int possibleMaxLength = (len - 8) / 4;
if((unsigned)mainc > possibleMaxLength || (unsigned)sidec > possibleMaxLength || (unsigned)mainc + (unsigned)sidec > possibleMaxLength) {
const int deck_size = len - 2 * sizeof(int32_t);
if (mainc < 0 || mainc > MAINC_MAX)
valid = false;
else if (sidec < 0 || sidec > SIDEC_MAX)
valid = false;
else if (deck_size != (mainc + sidec) * (int)sizeof(int32_t))
valid = false;
if (!valid) {
STOC_ErrorMsg scem;
scem.msg = ERRMSG_DECKERROR;
scem.code = 0;
NetServer::SendPacketToPlayer(dp, STOC_ERROR_MSG, scem);
return;
}
deck_error[dp->type] = deckManager.LoadDeck(pdeck[dp->type], (int*)deckbuf, mainc, sidec);
int deck_list[SIZE_NETWORK_BUFFER / sizeof(int32_t)];
std::memcpy(deck_list, deckbuf, deck_size);
deck_error[dp->type] = deckManager.LoadDeck(pdeck[dp->type], deck_list, mainc, sidec);
}
void TagDuel::StartDuel(DuelPlayer* dp) {
if(dp != host_player)
......@@ -296,9 +308,9 @@ void TagDuel::StartDuel(DuelPlayer* dp) {
NetServer::SendBufferToPlayer(players[0], STOC_DECK_COUNT, deckbuff, 12);
NetServer::ReSendToPlayer(players[1]);
char tempbuff[6];
memcpy(tempbuff, deckbuff, 6);
memcpy(deckbuff, deckbuff + 6, 6);
memcpy(deckbuff + 6, tempbuff, 6);
std::memcpy(tempbuff, deckbuff, 6);
std::memcpy(deckbuff, deckbuff + 6, 6);
std::memcpy(deckbuff + 6, tempbuff, 6);
NetServer::SendBufferToPlayer(players[2], STOC_DECK_COUNT, deckbuff, 12);
NetServer::ReSendToPlayer(players[3]);
NetServer::SendPacketToPlayer(players[0], STOC_SELECT_HAND);
......@@ -1519,11 +1531,11 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
}
return 0;
}
void TagDuel::GetResponse(DuelPlayer* dp, void* pdata, unsigned int len) {
void TagDuel::GetResponse(DuelPlayer* dp, unsigned char* pdata, unsigned int len) {
byte resb[SIZE_RETURN_VALUE];
if (len > SIZE_RETURN_VALUE)
len = SIZE_RETURN_VALUE;
memcpy(resb, pdata, len);
std::memcpy(resb, pdata, len);
last_replay.WriteInt8(len);
last_replay.WriteData(resb, len);
set_responseb(pduel, resb);
......@@ -1542,9 +1554,9 @@ void TagDuel::EndDuel() {
return;
last_replay.EndRecord();
char replaybuf[0x2000], *pbuf = replaybuf;
memcpy(pbuf, &last_replay.pheader, sizeof(ReplayHeader));
std::memcpy(pbuf, &last_replay.pheader, sizeof(ReplayHeader));
pbuf += sizeof(ReplayHeader);
memcpy(pbuf, last_replay.comp_data, last_replay.comp_size);
std::memcpy(pbuf, last_replay.comp_data, last_replay.comp_size);
NetServer::SendBufferToPlayer(players[0], STOC_REPLAY, replaybuf, sizeof(ReplayHeader) + last_replay.comp_size);
NetServer::ReSendToPlayer(players[1]);
NetServer::ReSendToPlayer(players[2]);
......@@ -1590,10 +1602,6 @@ inline int TagDuel::WriteUpdateData(int& player, int location, int& flag, unsign
int len = query_field_card(pduel, player, location, flag, qbuf, use_cache);
return len;
}
inline unsigned int GetPosition(unsigned char*& qbuf, int offset) {
unsigned int info = *(unsigned int*)(qbuf + offset);
return info >> 24;
}
void TagDuel::RefreshMzone(int player, int flag, int use_cache) {
std::vector<unsigned char> query_buffer;
query_buffer.resize(SIZE_QUERY_BUFFER);
......@@ -1726,7 +1734,7 @@ uint32 TagDuel::MessageHandler(intptr_t fduel, uint32 type) {
if(!enable_log)
return 0;
char msgbuf[1024];
get_log_message(fduel, (byte*)msgbuf);
get_log_message(fduel, msgbuf);
mainGame->AddDebugMsg(msgbuf);
return 0;
}
......
......@@ -11,21 +11,21 @@ class TagDuel: public DuelMode {
public:
TagDuel();
virtual ~TagDuel();
virtual void Chat(DuelPlayer* dp, void* pdata, int len);
virtual void JoinGame(DuelPlayer* dp, void* pdata, bool is_creater);
virtual void Chat(DuelPlayer* dp, unsigned char* pdata, int len);
virtual void JoinGame(DuelPlayer* dp, unsigned char* pdata, bool is_creater);
virtual void LeaveGame(DuelPlayer* dp);
virtual void ToDuelist(DuelPlayer* dp);
virtual void ToObserver(DuelPlayer* dp);
virtual void PlayerReady(DuelPlayer* dp, bool ready);
virtual void PlayerKick(DuelPlayer* dp, unsigned char pos);
virtual void UpdateDeck(DuelPlayer* dp, void* pdata, unsigned int len);
virtual void UpdateDeck(DuelPlayer* dp, unsigned char* pdata, int len);
virtual void StartDuel(DuelPlayer* dp);
virtual void HandResult(DuelPlayer* dp, unsigned char res);
virtual void TPResult(DuelPlayer* dp, unsigned char tp);
virtual void Process();
virtual void Surrender(DuelPlayer* dp);
virtual int Analyze(unsigned char* msgbuffer, unsigned int len);
virtual void GetResponse(DuelPlayer* dp, void* pdata, unsigned int len);
virtual void GetResponse(DuelPlayer* dp, unsigned char* pdata, unsigned int len);
virtual void TimeConfirm(DuelPlayer* dp);
virtual void EndDuel();
......
......@@ -29,7 +29,7 @@ public:
}
// return: string length
template<typename T1, typename T2>
inline static int CopyWStr(T1* src, T2* pstr, int bufsize) {
inline static int CopyWStr(const T1* src, T2* pstr, int bufsize) {
int l = 0;
while(src[l] && l < bufsize - 1) {
pstr[l] = (T2)src[l];
......@@ -39,7 +39,7 @@ public:
return l;
}
template<typename T1, typename T2>
inline static int CopyWStrRef(T1* src, T2*& pstr, int bufsize) {
inline static int CopyWStrRef(const T1* src, T2*& pstr, int bufsize) {
int l = 0;
while(src[l] && l < bufsize - 1) {
pstr[l] = (T2)src[l];
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment