Commit f3d8287f authored by argon.sun's avatar argon.sun

recon

parent bcfd1afc
......@@ -8,44 +8,129 @@ int DuelClient::responseI;
unsigned char DuelClient::responseB[64];
bool DuelClient::is_responseB;
unsigned char DuelClient::response_len;
event_base* DuelClient::client_base = 0;
bufferevent* DuelClient::client_bev = 0;
char DuelClient::duel_client_read[0x2000];
char DuelClient::duel_client_write[0x2000];
bool DuelClient::is_host = false;
bool DuelClient::StartClient(unsigned int ip, unsigned short port) {
if(connect_state)
return false;
event_base* evbase;
bufferevent* bev;
sockaddr_in sin;
evbase = event_base_new();
client_base = event_base_new();
if(!client_base)
return false;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl(ip);
sin.sin_port = htons(port);
bev = bufferevent_socket_new(evbase, -1, BEV_OPT_CLOSE_ON_FREE);
bufferevent_setcb(bev, ClientRead, NULL, ClientEvent, NULL);
if (bufferevent_socket_connect(bev, (sockaddr*)&sin, sizeof(sin)) < 0) {
bufferevent_free(bev);
client_bev = bufferevent_socket_new(client_base, -1, BEV_OPT_CLOSE_ON_FREE);
bufferevent_setcb(client_bev, ClientRead, NULL, ClientEvent, NULL);
if (bufferevent_socket_connect(client_bev, (sockaddr*)&sin, sizeof(sin)) < 0) {
bufferevent_free(client_bev);
return false;
}
connect_state = 1;
Thread::NewThread(ClientThread, evbase);
Thread::NewThread(ClientThread, 0);
return true;
}
void DuelClient::StopClient() {
if(connect_state != 2)
return;
irr::SEvent sevt;
sevt.EventType = irr::EET_USER_EVENT;
sevt.UserEvent.UserData1 = UEVENT_EXIT;
sevt.UserEvent.UserData2 = 1;
mainGame->device->postEventFromUser(sevt);
event_base_loopexit(client_base, NULL);
}
void DuelClient::ClientRead(bufferevent* bev, void* ctx) {
evbuffer* input = bufferevent_get_input(bev);
size_t len = evbuffer_get_length(input);
unsigned short packet_len = 0;
while(true) {
if(len < 2)
return;
evbuffer_copyout(input, &packet_len, 2);
if(len < packet_len + 2)
return;
evbuffer_remove(input, duel_client_read, packet_len + 2);
if(packet_len)
HandleSTOCPacket(&duel_client_read[2], packet_len);
len -= packet_len + 2;
}
}
void DuelClient::ClientEvent(bufferevent *bev, short events, void *ptr) {
if (events & BEV_EVENT_CONNECTED) {
mainGame->HideElement(mainGame->wCreateHost);
mainGame->WaitFrameSignal(10);
CTOS_CreateGame cscg;
const wchar_t* phstr = mainGame->ebServerName->getText();
int i = 0;
while(i < 19 && phstr[i])
cscg.name[i] = phstr[i++];
cscg.name[i] = 0;
phstr = mainGame->ebServerPass->getText();
i = 0;
while(i < 19 && phstr[i])
cscg.pass[i] = phstr[i++];
cscg.pass[i] = 0;
cscg.info.rule = mainGame->cbRule->getSelected();
cscg.info.mode = mainGame->cbMatchMode->getSelected();
cscg.info.start_hand = _wtoi(mainGame->ebStartHand->getText());
cscg.info.start_lp = _wtoi(mainGame->ebStartLP->getText());
cscg.info.draw_count = _wtoi(mainGame->ebDrawCount->getText());
cscg.info.lflist = mainGame->cbLFlist->getItemData(mainGame->cbLFlist->getSelected());
cscg.info.no_check_deck = mainGame->chkNoCheckDeck->isChecked();
cscg.info.no_shuffle_deck = mainGame->chkNoShuffleDeck->isChecked();
SendPacketToServer(CTOS_CREATE_GAME, cscg);
connect_state = 2;
} else if (events & BEV_EVENT_ERROR) {
mainGame->env->addMessageBox(L"", L"无法连接到主机。");
mainGame->btnCreateHost->setEnabled(true);
mainGame->btnJoinHost->setEnabled(true);
mainGame->btnJoinCancel->setEnabled(true);
event_base_loopexit(client_base, NULL);
}
}
int DuelClient::ClientThread(void* param) {
event_base* evbase = (event_base*)param;
event_base_dispatch(evbase);
event_base_loopexit(evbase, NULL);
event_base_dispatch(client_base);
event_base_free(client_base);
bufferevent_free(client_bev);
client_base = 0;
connect_state = 0;
}
void DuelClient::HandleSTOCPacket(char* data, unsigned int len) {
char* pdata = data;
unsigned char pktType = BufferIO::ReadUInt8(pdata);
switch(pktType) {
case STOC_JOIN_GAME: {
STOC_JoinGame* pkt = (STOC_JoinGame*)pdata;
mainGame->ShowElement(mainGame->wHostSingle);
mainGame->WaitFrameSignal(10);
break;
}
case STOC_JOIN_FAIL: {
STOC_JoinFail* pkt = (STOC_JoinFail*)pdata;
if(pkt->reason == 0)
mainGame->env->addMessageBox(L"", L"无法加入主机。");
else if(pkt->reason == 1)
mainGame->env->addMessageBox(L"", L"密码错误。");
else if(pkt->reason == 2)
mainGame->env->addMessageBox(L"", L"主机拒绝了连接。");
mainGame->btnCreateHost->setEnabled(true);
mainGame->btnJoinHost->setEnabled(true);
mainGame->btnJoinCancel->setEnabled(true);
break;
}
case STOC_HS_PLAYER_ENTER:
break;
case STOC_HS_PLAYER_CHANGE:
break;
case STOC_HS_WATCH_CHANGE:
break;
}
}
void DuelClient::SetResponseI(int respI) {
responseI = respI;
......
......@@ -20,14 +20,35 @@ private:
static unsigned char responseB[64];
static bool is_responseB;
static unsigned char response_len;
static event_base* client_base;
static bufferevent* client_bev;
static char duel_client_read[0x2000];
static char duel_client_write[0x2000];
static bool is_host;
public:
static bool StartClient(unsigned int ip, unsigned short port);
static void StopClient();
static void ClientRead(bufferevent* bev, void* ctx);
static void ClientEvent(bufferevent *bev, short events, void *ptr);
static int ClientThread(void* param);
static void HandleSTOCPacket(char* data, unsigned int len);
static void SetResponseI(int respI);
static void SetResponseB(unsigned char* respB, unsigned char len);
template<typename ST>
static void SendPacketToServer(unsigned char proto, ST& st) {
char* p = duel_client_write;
BufferIO::WriteInt16(p, 1 + sizeof(ST));
BufferIO::WriteInt8(p, proto);
memcpy(p, &st, sizeof(ST));
evbuffer_add(bufferevent_get_output(client_bev), duel_client_write, sizeof(ST) + 3);
}
static void SendBufferToServer(unsigned char proto, void* buffer, size_t len) {
char* p = duel_client_write;
BufferIO::WriteInt16(p, 1 + len);
BufferIO::WriteInt8(p, proto);
memcpy(p, buffer, len);
evbuffer_add(bufferevent_get_output(client_bev), duel_client_write, len + 3);
}
};
}
......
......@@ -100,7 +100,7 @@ bool Game::Initialize() {
env->addStaticText(dataManager.GetSysString(1226), rect<s32>(20, 60, 220, 80), false, false, wCreateHost);
cbLFlist = env->addComboBox(rect<s32>(140, 55, 300, 80), wCreateHost);
for(int i = 0; i < deckManager._lfList.size(); ++i)
cbLFlist->addItem(deckManager._lfList[i].listName);
cbLFlist->addItem(deckManager._lfList[i].listName, deckManager._lfList[i].hash);
env->addStaticText(dataManager.GetSysString(1227), rect<s32>(20, 90, 220, 110), false, false, wCreateHost);
cbMatchMode = env->addComboBox(rect<s32>(140, 85, 300, 110), wCreateHost);
cbMatchMode->addItem(dataManager.GetSysString(1244));
......
#include "config.h"
#include "menu_handler.h"
#include "netserver.h"
#include "duelclient.h"
#include "game.h"
namespace ygo {
......@@ -21,6 +23,9 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) {
break;
}
case BUTTON_JOIN_HOST: {
mainGame->btnCreateHost->setEnabled(false);
mainGame->btnJoinHost->setEnabled(false);
mainGame->btnJoinCancel->setEnabled(false);
break;
}
case BUTTON_JOIN_CANCEL: {
......@@ -28,11 +33,20 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) {
break;
}
case BUTTON_CREATE_HOST: {
mainGame->btnHostConfirm->setEnabled(true);
mainGame->btnHostCancel->setEnabled(true);
mainGame->HideElement(mainGame->wLanWindow, false, mainGame->wCreateHost);
break;
}
case BUTTON_HOST_CONFIRM: {
mainGame->HideElement(mainGame->wCreateHost, false, mainGame->wHostSingle);
if(NetServer::StartServer(mainGame->gameConf.serverport))
break;
if(!DuelClient::StartClient(0x7f000001, mainGame->gameConf.serverport)) {
NetServer::StopServer();
break;
}
mainGame->btnHostConfirm->setEnabled(false);
mainGame->btnHostCancel->setEnabled(false);
break;
}
case BUTTON_HOST_CANCEL: {
......
......@@ -44,7 +44,8 @@ void NetServer::ServerAccept(evconnlistener* listener, evutil_socket_t fd, socka
bufferevent* bev = bufferevent_socket_new(net_evbase, fd, BEV_OPT_CLOSE_ON_FREE);
DuelPlayer dp;
dp.name[0] = 0;
dp.output = bufferevent_get_output(bev);
dp.type = 0xff;
dp.bev = bev;
users[bev] = dp;
bufferevent_setcb(bev, ServerEchoRead, NULL, ServerEchoEvent, NULL);
bufferevent_enable(bev, EV_READ | EV_WRITE);
......@@ -77,9 +78,18 @@ void NetServer::ServerEchoEvent(bufferevent* bev, short events, void* ctx) {
int NetServer::ServerThread(void* param) {
event_base_dispatch(net_evbase);
event_base_free(net_evbase);
for(auto bit = users.begin(); bit != users.end(); ++bit)
bufferevent_free(bit->first);
net_evbase = 0;
return 0;
}
void NetServer::DisconnectPlayer(DuelPlayer* dp) {
auto bit = users.find(dp->bev);
if(bit != users.end()) {
users.erase(bit);
bufferevent_free(dp->bev);
}
}
void NetServer::HandleCTOSPacket(DuelPlayer* dp, char* data, unsigned int len) {
char* pdata = data;
unsigned char pktType = BufferIO::ReadUInt8(pdata);
......@@ -106,12 +116,30 @@ void NetServer::HandleCTOSPacket(DuelPlayer* dp, char* data, unsigned int len) {
duel_mode = new MatchDuel;
}
duel_mode->host_info = pkt->info;
for(int i = 0; i < 20; ++i) {
duel_mode->name[i] = pkt->name[i];
duel_mode->pass[i] = pkt->pass[i];
}
}
case CTOS_JOIN_GAME: {
if(dp->game)
return;
if(!duel_mode)
return;
if(pktType != CTOS_CREATE_GAME) {
if((dp->game && dp->type != 0xff) || !duel_mode) {
STOC_JoinFail scjf;
scjf.reason = 0;
SendPacketToPlayer(dp, STOC_JOIN_FAIL, scjf);
break;
}
CTOS_JoinGame* pkt = (CTOS_JoinGame*)pdata;
wchar_t jpass[20];
for(int i = 0; i < 20; ++i) jpass[i] = pkt->pass[i];
jpass[20] = 0;
if(wcscmp(jpass, duel_mode->pass)) {
STOC_JoinFail scjf;
scjf.reason = 1;
SendPacketToPlayer(dp, STOC_JOIN_FAIL, scjf);
break;
}
}
dp->game = duel_mode;
if(!duel_mode->players[0] && !duel_mode->players[1] && duel_mode->observers.size() == 0)
duel_mode->host_player = dp;
......@@ -141,14 +169,14 @@ void NetServer::HandleCTOSPacket(DuelPlayer* dp, char* data, unsigned int len) {
duel_mode->observers.insert(dp);
dp->type = NETPLAYER_TYPE_OBSERVER;
scjg.type |= NETPLAYER_TYPE_OBSERVER;
STOC_HS_ReadyChange scrc;
scrc.ready = duel_mode->observers.size();
STOC_HS_WatchChange scwc;
scwc.watch_count = duel_mode->observers.size();
if(duel_mode->players[0])
NetServer::SendPacketToPlayer(duel_mode->players[0], STOC_HS_READY_CHANGE, scrc);
NetServer::SendPacketToPlayer(duel_mode->players[0], STOC_HS_WATCH_CHANGE, scwc);
if(duel_mode->players[1])
NetServer::SendPacketToPlayer(duel_mode->players[1], STOC_HS_READY_CHANGE, scrc);
NetServer::SendPacketToPlayer(duel_mode->players[1], STOC_HS_WATCH_CHANGE, scwc);
for(auto pit = duel_mode->observers.begin(); pit != duel_mode->observers.end(); ++pit)
NetServer::SendPacketToPlayer(*pit, STOC_HS_READY_CHANGE, scrc);
NetServer::SendPacketToPlayer(*pit, STOC_HS_WATCH_CHANGE, scwc);
}
NetServer::SendPacketToPlayer(dp, STOC_JOIN_GAME, scjg);
if(duel_mode->players[0]) {
......@@ -174,9 +202,9 @@ void NetServer::HandleCTOSPacket(DuelPlayer* dp, char* data, unsigned int len) {
}
}
if(duel_mode->observers.size()) {
STOC_HS_ReadyChange scrc;
scrc.ready = duel_mode->observers.size();
NetServer::SendPacketToPlayer(dp, STOC_HS_READY_CHANGE, scrc);
STOC_HS_WatchChange scwc;
scwc.watch_count = duel_mode->observers.size();
NetServer::SendPacketToPlayer(dp, STOC_HS_WATCH_CHANGE, scwc);
}
break;
}
......
......@@ -23,14 +23,12 @@ struct DuelPlayer {
DuelMode* game;
unsigned char type;
unsigned char state;
unsigned int uid;
evbuffer* output;
bufferevent* bev;
DuelPlayer() {
uid = 0;
game = 0;
type = 0;
state = 0;
output = 0;
bev = 0;
}
};
......@@ -56,6 +54,8 @@ public:
DuelPlayer* host_player;
HostInfo host_info;
unsigned long pduel;
wchar_t name[20];
wchar_t pass[20];
};
class NetServer {
......@@ -75,6 +75,7 @@ public:
static void ServerEchoRead(bufferevent* bev, void* ctx);
static void ServerEchoEvent(bufferevent* bev, short events, void* ctx);
static int ServerThread(void* param);
static void DisconnectPlayer(DuelPlayer* dp);
static void HandleCTOSPacket(DuelPlayer* dp, char* data, unsigned int len);
template<typename ST>
static void SendPacketToPlayer(DuelPlayer* dp, unsigned char proto, ST& st) {
......@@ -83,7 +84,7 @@ public:
BufferIO::WriteInt8(p, proto);
memcpy(p, &st, sizeof(ST));
last_sent = sizeof(ST) + 3;
evbuffer_add(dp->output, net_server_write, last_sent);
evbuffer_add(bufferevent_get_output(dp->bev), net_server_write, last_sent);
}
static void SendBufferToPlayer(DuelPlayer* dp, unsigned char proto, void* buffer, size_t len) {
char* p = net_server_write;
......@@ -91,10 +92,10 @@ public:
BufferIO::WriteInt8(p, proto);
memcpy(p, buffer, len);
last_sent = len + 3;
evbuffer_add(dp->output, net_server_write, last_sent);
evbuffer_add(bufferevent_get_output(dp->bev), net_server_write, last_sent);
}
static void ReSendToPlayer(DuelPlayer* dp) {
evbuffer_add(dp->output, net_server_write, last_sent);
evbuffer_add(bufferevent_get_output(dp->bev), net_server_write, last_sent);
}
};
......
......@@ -8,7 +8,6 @@
namespace ygo {
struct HostInfo {
unsigned short name[20];
unsigned char rule;
unsigned char mode;
unsigned int lflist;
......@@ -40,11 +39,13 @@ struct CTOS_PlayerInfo {
};
struct CTOS_CreateGame {
HostInfo info;
unsigned short name[20];
unsigned short pass[20];
};
struct CTOS_JoinGame {
unsigned int gameid;
unsigned short pass[20];
};
struct STOC_CreateGame {
unsigned int gameid;
};
......@@ -54,15 +55,18 @@ struct STOC_JoinGame {
};
struct STOC_ExitGame {
};
struct STOC_JoinFail {
//0 - common error
//1 - password incorrect
//2 - host denied
unsigned int reason;
};
struct STOC_HS_PlayerEnter {
unsigned short name[20];
};
struct STOC_HS_PlayerChange {
unsigned char status;
};
struct STOC_HS_ReadyChange {
unsigned char ready;
};
struct STOC_HS_WatchChange {
unsigned short watch_count;
};
......@@ -90,10 +94,10 @@ extern const unsigned short PROTO_VERSION;
#define STOC_CREATE_GAME 0x11
#define STOC_JOIN_GAME 0x12
#define STOC_EXIT_GAME 0x13
#define STOC_JOIN_FAIL 0x14
#define STOC_HS_PLAYER_ENTER 0x20
#define STOC_HS_PLAYER_CHANGE 0x21
#define STOC_HS_READY_CHANGE 0x22
#define STOC_HS_WATCH_CHANGE 0x23
#define STOC_HS_WATCH_CHANGE 0x22
#define PLAYERCHANGE_READY 0x1
#define PLAYERCHANGE_NOTREADY 0x2
......
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