Initial handshake and network game start. Works with multiple clients. Not yet stable, because it is not thread-safe. GUI callbacks not complete yet (server dialog not updated).
This commit is contained in:
+2
-1
@@ -145,9 +145,10 @@ SOURCES += src/game.cpp \
|
|||||||
src/net/common/serverexception.cpp \
|
src/net/common/serverexception.cpp \
|
||||||
src/net/common/serverrecvthread.cpp \
|
src/net/common/serverrecvthread.cpp \
|
||||||
src/net/common/serverrecvstate.cpp \
|
src/net/common/serverrecvstate.cpp \
|
||||||
|
src/net/common/servercallback.cpp \
|
||||||
|
src/net/common/sessiondata.cpp \
|
||||||
src/net/common/socket_helper_cmn.cpp \
|
src/net/common/socket_helper_cmn.cpp \
|
||||||
src/net/common/clientexception.cpp \
|
src/net/common/clientexception.cpp \
|
||||||
src/net/common/netcallback.cpp \
|
|
||||||
src/net/common/netcontext.cpp \
|
src/net/common/netcontext.cpp \
|
||||||
src/net/common/netexception.cpp \
|
src/net/common/netexception.cpp \
|
||||||
src/net/common/receiverhelper.cpp \
|
src/net/common/receiverhelper.cpp \
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#define GUIINTERFACE_H
|
#define GUIINTERFACE_H
|
||||||
|
|
||||||
#include <net/clientcallback.h>
|
#include <net/clientcallback.h>
|
||||||
|
#include <net/servercallback.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class Game;
|
class Game;
|
||||||
@@ -28,7 +29,7 @@ class Session;
|
|||||||
class HandInterface;
|
class HandInterface;
|
||||||
|
|
||||||
|
|
||||||
class GuiInterface : public ClientCallback {
|
class GuiInterface : public ClientCallback, public ServerCallback {
|
||||||
public:
|
public:
|
||||||
virtual ~GuiInterface();
|
virtual ~GuiInterface();
|
||||||
|
|
||||||
|
|||||||
@@ -44,9 +44,9 @@ void connectToServerDialogImpl::refresh(int actionID) {
|
|||||||
default: { label_actionMessage->setText("Please wait..."); }
|
default: { label_actionMessage->setText("Please wait..."); }
|
||||||
}
|
}
|
||||||
|
|
||||||
progressBar->setValue(actionID*(100/MSG_SOCK_LAST));
|
progressBar->setValue(actionID*(100/MSG_SOCK_LIMIT_CONNECT));
|
||||||
|
|
||||||
if (actionID == MSG_SOCK_LAST)
|
if (actionID == MSG_SOCK_LIMIT_CONNECT)
|
||||||
QTimer::singleShot(1000, this, SLOT(accept()));
|
QTimer::singleShot(1000, this, SLOT(accept()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -88,5 +88,10 @@ void GuiWrapper::meInAction() const { myW->meInAction(); }
|
|||||||
void GuiWrapper::logPlayerActionMsg(string playerName, int action, int setValue) { myLog->logPlayerActionMsg(playerName, action, setValue); }
|
void GuiWrapper::logPlayerActionMsg(string playerName, int action, int setValue) { myLog->logPlayerActionMsg(playerName, action, setValue); }
|
||||||
void GuiWrapper::logNewGameHandMsg(int gameID, int handID) { myLog->logNewGameHandMsg(gameID, handID); }
|
void GuiWrapper::logNewGameHandMsg(int gameID, int handID) { myLog->logNewGameHandMsg(gameID, handID); }
|
||||||
|
|
||||||
void GuiWrapper::SignalNetSuccess(int actionID) { myW->SignalNetSuccess(actionID); }
|
void GuiWrapper::SignalNetClientConnect(int actionID) { myW->SignalNetClientConnect(actionID); }
|
||||||
void GuiWrapper::SignalNetError(int errorID, int osErrorID) { myW->SignalNetError(errorID, osErrorID); }
|
void GuiWrapper::SignalNetClientGameInfo(int actionID) { myW->SignalNetClientGameInfo(actionID); }
|
||||||
|
void GuiWrapper::SignalNetClientError(int errorID, int osErrorID) { myW->SignalNetClientError(errorID, osErrorID); }
|
||||||
|
|
||||||
|
void GuiWrapper::SignalNetServerSuccess(int actionID) { }
|
||||||
|
void GuiWrapper::SignalNetServerError(int errorID, int osErrorID) { }
|
||||||
|
|
||||||
|
|||||||
@@ -88,8 +88,12 @@ public:
|
|||||||
void logPlayerActionMsg(std::string playerName, int action, int setValue) ;
|
void logPlayerActionMsg(std::string playerName, int action, int setValue) ;
|
||||||
void logNewGameHandMsg(int gameID, int handID) ;
|
void logNewGameHandMsg(int gameID, int handID) ;
|
||||||
|
|
||||||
void SignalNetSuccess(int actionID);
|
void SignalNetClientConnect(int actionID);
|
||||||
void SignalNetError(int errorID, int osErrorID);
|
void SignalNetClientGameInfo(int actionID);
|
||||||
|
void SignalNetClientError(int errorID, int osErrorID);
|
||||||
|
|
||||||
|
void SignalNetServerSuccess(int actionID);
|
||||||
|
void SignalNetServerError(int errorID, int osErrorID);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
#include "connecttoserverdialogimpl.h"
|
#include "connecttoserverdialogimpl.h"
|
||||||
#include "createnetworkgamedialogimpl.h"
|
#include "createnetworkgamedialogimpl.h"
|
||||||
#include "startnetworkgamedialogimpl.h"
|
#include "startnetworkgamedialogimpl.h"
|
||||||
|
#include "waitforservertostartgamedialogimpl.h"
|
||||||
|
|
||||||
#include "startsplash.h"
|
#include "startsplash.h"
|
||||||
#include "mycardspixmaplabel.h"
|
#include "mycardspixmaplabel.h"
|
||||||
@@ -427,6 +427,7 @@ mainWindowImpl::mainWindowImpl(QMainWindow *parent)
|
|||||||
myConnectToServerDialog = new connectToServerDialogImpl(this);
|
myConnectToServerDialog = new connectToServerDialogImpl(this);
|
||||||
myStartNetworkGameDialog = new startNetworkGameDialogImpl(this);
|
myStartNetworkGameDialog = new startNetworkGameDialogImpl(this);
|
||||||
myCreateNetworkGameDialog = new createNetworkGameDialogImpl(this);
|
myCreateNetworkGameDialog = new createNetworkGameDialogImpl(this);
|
||||||
|
myWaitingForServerGameDialog = new waitForServerToStartGameDialogImpl(this);
|
||||||
|
|
||||||
//Connects
|
//Connects
|
||||||
connect(dealFlopCards0Timer, SIGNAL(timeout()), this, SLOT( dealFlopCards1() ));
|
connect(dealFlopCards0Timer, SIGNAL(timeout()), this, SLOT( dealFlopCards1() ));
|
||||||
@@ -481,8 +482,10 @@ mainWindowImpl::mainWindowImpl(QMainWindow *parent)
|
|||||||
connect ( pushButton_break, SIGNAL( clicked()), this, SLOT ( breakButtonClicked() ) ); // auch wieder starten!!!!
|
connect ( pushButton_break, SIGNAL( clicked()), this, SLOT ( breakButtonClicked() ) ); // auch wieder starten!!!!
|
||||||
|
|
||||||
//Nachrichten Thread-Save
|
//Nachrichten Thread-Save
|
||||||
connect(this, SIGNAL(SignalNetSuccess(int)), myConnectToServerDialog, SLOT(refresh(int)));
|
connect(this, SIGNAL(SignalNetClientConnect(int)), myConnectToServerDialog, SLOT(refresh(int)));
|
||||||
connect(this, SIGNAL(SignalNetError(int, int)), myConnectToServerDialog, SLOT(error(int, int)));
|
connect(this, SIGNAL(SignalNetClientGameInfo(int)), myWaitingForServerGameDialog, SLOT(refresh(int)));
|
||||||
|
// TODO Fix, errors MUST be global, not within one dialog.
|
||||||
|
connect(this, SIGNAL(SignalNetClientError(int, int)), myConnectToServerDialog, SLOT(error(int, int)));
|
||||||
|
|
||||||
// textBrowser_Log->append(QString::number(this->pos().x(),10)+" "+QString::number(this->pos().y(),10));
|
// textBrowser_Log->append(QString::number(this->pos().x(),10)+" "+QString::number(this->pos().y(),10));
|
||||||
// textBrowser_Log->append(QString::number(this->x(),10)+" "+QString::number(this->y(),10));
|
// textBrowser_Log->append(QString::number(this->x(),10)+" "+QString::number(this->y(),10));
|
||||||
@@ -586,29 +589,18 @@ void mainWindowImpl::callAboutPokerthDialog() {
|
|||||||
|
|
||||||
void mainWindowImpl::callCreateNetworkGameDialog() {
|
void mainWindowImpl::callCreateNetworkGameDialog() {
|
||||||
|
|
||||||
myCreateNetworkGameDialog->showDialog();
|
myCreateNetworkGameDialog->exec();
|
||||||
//
|
//
|
||||||
if (myCreateNetworkGameDialog->result() == QDialog::Accepted ) {
|
if (myCreateNetworkGameDialog->result() == QDialog::Accepted ) {
|
||||||
|
|
||||||
mySession->terminateNetworkServer();
|
mySession->terminateNetworkServer();
|
||||||
mySession->startNetworkServer();
|
mySession->startNetworkServer();
|
||||||
//
|
|
||||||
// mySession->terminateNetworkClient();
|
myStartNetworkGameDialog->exec();
|
||||||
//
|
|
||||||
// // Maybe use QUrl::toPunycode.
|
if (myStartNetworkGameDialog->result() == QDialog::Accepted ) {
|
||||||
// mySession->startNetworkClient(
|
mySession->initiateNetworkServerGame();
|
||||||
// myJoinNetworkGameDialog->lineEdit_ipAddress->text().toUtf8().constData(),
|
}
|
||||||
// myJoinNetworkGameDialog->spinBox_port->value(),
|
|
||||||
// myJoinNetworkGameDialog->checkBox_ipv6->isChecked(),
|
|
||||||
// myJoinNetworkGameDialog->lineEdit_password->text().toUtf8().constData());
|
|
||||||
//
|
|
||||||
// //Dialog mit Statusbalken
|
|
||||||
// myConnectToServerDialog->exec();
|
|
||||||
//
|
|
||||||
// if (myConnectToServerDialog->result() == QDialog::Rejected ) {
|
|
||||||
// mySession->terminateNetworkClient();
|
|
||||||
// actionJoin_network_Game->trigger(); // re-trigger
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -635,6 +627,9 @@ void mainWindowImpl::callJoinNetworkGameDialog() {
|
|||||||
mySession->terminateNetworkClient();
|
mySession->terminateNetworkClient();
|
||||||
actionJoin_network_Game->trigger(); // re-trigger
|
actionJoin_network_Game->trigger(); // re-trigger
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
myWaitingForServerGameDialog->exec();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ class joinNetworkGameDialogImpl;
|
|||||||
class connectToServerDialogImpl;
|
class connectToServerDialogImpl;
|
||||||
class createNetworkGameDialogImpl;
|
class createNetworkGameDialogImpl;
|
||||||
class startNetworkGameDialogImpl;
|
class startNetworkGameDialogImpl;
|
||||||
|
class waitForServerToStartGameDialogImpl;
|
||||||
|
|
||||||
class QColor;
|
class QColor;
|
||||||
|
|
||||||
@@ -88,8 +89,9 @@ public:
|
|||||||
void setSpeeds();
|
void setSpeeds();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void SignalNetSuccess(int actionID);
|
void SignalNetClientConnect(int actionID);
|
||||||
void SignalNetError(int errorID, int osErrorID);
|
void SignalNetClientGameInfo(int actionID);
|
||||||
|
void SignalNetClientError(int errorID, int osErrorID);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
@@ -258,6 +260,7 @@ private:
|
|||||||
connectToServerDialogImpl *myConnectToServerDialog;
|
connectToServerDialogImpl *myConnectToServerDialog;
|
||||||
startNetworkGameDialogImpl *myStartNetworkGameDialog;
|
startNetworkGameDialogImpl *myStartNetworkGameDialog;
|
||||||
createNetworkGameDialogImpl *myCreateNetworkGameDialog;
|
createNetworkGameDialogImpl *myCreateNetworkGameDialog;
|
||||||
|
waitForServerToStartGameDialogImpl *myWaitingForServerGameDialog;
|
||||||
|
|
||||||
int maxQuantityPlayers;
|
int maxQuantityPlayers;
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,10 @@ waitForServerToStartGameDialogImpl::waitForServerToStartGameDialogImpl(QWidget *
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void waitForServerToStartGameDialogImpl::refresh(int actionID) {
|
||||||
|
QTimer::singleShot(1000, this, SLOT(accept()));
|
||||||
|
}
|
||||||
|
|
||||||
void waitForServerToStartGameDialogImpl::cancel() {
|
void waitForServerToStartGameDialogImpl::cancel() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ public:
|
|||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
|
void refresh(int actionID);
|
||||||
void cancel();
|
void cancel();
|
||||||
void keyPressEvent ( QKeyEvent * event );
|
void keyPressEvent ( QKeyEvent * event );
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -21,12 +21,14 @@
|
|||||||
#ifndef _CLIENTCALLBACK_H_
|
#ifndef _CLIENTCALLBACK_H_
|
||||||
#define _CLIENTCALLBACK_H_
|
#define _CLIENTCALLBACK_H_
|
||||||
|
|
||||||
#include <net/netcallback.h>
|
class ClientCallback
|
||||||
|
|
||||||
class ClientCallback : public NetCallback
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~ClientCallback();
|
virtual ~ClientCallback();
|
||||||
|
|
||||||
|
virtual void SignalNetClientConnect(int actionID) = 0;
|
||||||
|
virtual void SignalNetClientGameInfo(int actionID) = 0;
|
||||||
|
virtual void SignalNetClientError(int errorID, int osErrorID) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+19
-1
@@ -164,7 +164,7 @@ public:
|
|||||||
|
|
||||||
virtual ~ClientStateWaitSession();
|
virtual ~ClientStateWaitSession();
|
||||||
|
|
||||||
// sleep.
|
// select on socket.
|
||||||
virtual int Process(ClientThread &client);
|
virtual int Process(ClientThread &client);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -173,6 +173,24 @@ protected:
|
|||||||
ClientStateWaitSession();
|
ClientStateWaitSession();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// State: Wait for start of the game or start info.
|
||||||
|
class ClientStateWaitGame : public ClientState
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Access the state singleton.
|
||||||
|
static ClientStateWaitGame &Instance();
|
||||||
|
|
||||||
|
virtual ~ClientStateWaitGame();
|
||||||
|
|
||||||
|
// select on socket.
|
||||||
|
virtual int Process(ClientThread &client);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// Protected constructor - this is a singleton.
|
||||||
|
ClientStateWaitGame();
|
||||||
|
};
|
||||||
|
|
||||||
// State: Final (TODO).
|
// State: Final (TODO).
|
||||||
class ClientStateFinal : public ClientState
|
class ClientStateFinal : public ClientState
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -24,10 +24,10 @@
|
|||||||
#include <core/thread.h>
|
#include <core/thread.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <net/clientcallback.h>
|
||||||
|
|
||||||
class ClientContext;
|
class ClientContext;
|
||||||
class ClientState;
|
class ClientState;
|
||||||
class ClientCallback;
|
|
||||||
class SenderThread;
|
class SenderThread;
|
||||||
class ReceiverHelper;
|
class ReceiverHelper;
|
||||||
class ClientSenderCallback;
|
class ClientSenderCallback;
|
||||||
@@ -77,6 +77,7 @@ friend class ClientStateStartConnect;
|
|||||||
friend class ClientStateConnecting;
|
friend class ClientStateConnecting;
|
||||||
friend class ClientStateStartSession;
|
friend class ClientStateStartSession;
|
||||||
friend class ClientStateWaitSession;
|
friend class ClientStateWaitSession;
|
||||||
|
friend class ClientStateWaitGame;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -321,7 +321,7 @@ ClientStateStartSession::~ClientStateStartSession()
|
|||||||
int
|
int
|
||||||
ClientStateStartSession::Process(ClientThread &client)
|
ClientStateStartSession::Process(ClientThread &client)
|
||||||
{
|
{
|
||||||
boost::shared_ptr<NetPacket> packet(new TestNetPacket(10));
|
boost::shared_ptr<NetPacket> packet(new NetPacketInit(10));
|
||||||
client.GetSender().Send(packet, client.GetContext().GetSocket());
|
client.GetSender().Send(packet, client.GetContext().GetSocket());
|
||||||
|
|
||||||
client.SetState(ClientStateWaitSession::Instance());
|
client.SetState(ClientStateWaitSession::Instance());
|
||||||
@@ -356,15 +356,54 @@ ClientStateWaitSession::Process(ClientThread &client)
|
|||||||
|
|
||||||
boost::shared_ptr<NetPacket> tmpPacket = client.GetReceiver().Recv(context.GetSocket());
|
boost::shared_ptr<NetPacket> tmpPacket = client.GetReceiver().Recv(context.GetSocket());
|
||||||
|
|
||||||
if (tmpPacket.get())
|
if (tmpPacket.get() && tmpPacket->ToNetPacketInitAck())
|
||||||
{
|
{
|
||||||
client.SetState(ClientStateFinal::Instance());
|
client.SetState(ClientStateWaitGame::Instance());
|
||||||
retVal = MSG_SOCK_SESSION_DONE;
|
retVal = MSG_SOCK_SESSION_DONE;
|
||||||
}
|
}
|
||||||
else
|
else // TODO: handle error packet
|
||||||
|
{
|
||||||
|
retVal = MSG_SOCK_INTERNAL_PENDING;
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
ClientStateWaitGame &
|
||||||
|
ClientStateWaitGame::Instance()
|
||||||
|
{
|
||||||
|
static ClientStateWaitGame state;
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientStateWaitGame::ClientStateWaitGame()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientStateWaitGame::~ClientStateWaitGame()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ClientStateWaitGame::Process(ClientThread &client)
|
||||||
|
{
|
||||||
|
int retVal;
|
||||||
|
ClientContext &context = client.GetContext();
|
||||||
|
|
||||||
|
// delegate to receiver helper class
|
||||||
|
|
||||||
|
boost::shared_ptr<NetPacket> tmpPacket = client.GetReceiver().Recv(context.GetSocket());
|
||||||
|
|
||||||
|
if (tmpPacket.get() && tmpPacket->ToNetPacketGameStart())
|
||||||
|
{
|
||||||
|
client.SetState(ClientStateFinal::Instance());
|
||||||
|
retVal = MSG_SOCK_GAME_START;
|
||||||
|
}
|
||||||
|
else // TODO: handle error packet
|
||||||
{
|
{
|
||||||
retVal = MSG_SOCK_INTERNAL_PENDING;
|
retVal = MSG_SOCK_INTERNAL_PENDING;
|
||||||
Thread::Msleep(CLIENT_WAIT_TIMEOUT_MSEC);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return retVal;
|
return retVal;
|
||||||
|
|||||||
@@ -22,7 +22,6 @@
|
|||||||
#include <net/clientcontext.h>
|
#include <net/clientcontext.h>
|
||||||
#include <net/senderthread.h>
|
#include <net/senderthread.h>
|
||||||
#include <net/receiverhelper.h>
|
#include <net/receiverhelper.h>
|
||||||
#include <net/clientcallback.h>
|
|
||||||
#include <net/clientexception.h>
|
#include <net/clientexception.h>
|
||||||
#include <net/socket_msg.h>
|
#include <net/socket_msg.h>
|
||||||
|
|
||||||
@@ -43,7 +42,7 @@ public:
|
|||||||
// For now, we ignore the socket.
|
// For now, we ignore the socket.
|
||||||
// Just signal the error.
|
// Just signal the error.
|
||||||
// We assume that the client thread will be terminated.
|
// We assume that the client thread will be terminated.
|
||||||
m_client.GetCallback().SignalNetError(errorID, osErrorID);
|
m_client.GetCallback().SignalNetClientError(errorID, osErrorID);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -97,11 +96,16 @@ ClientThread::Main()
|
|||||||
{
|
{
|
||||||
int msg = GetState().Process(*this);
|
int msg = GetState().Process(*this);
|
||||||
if (msg != MSG_SOCK_INTERNAL_PENDING)
|
if (msg != MSG_SOCK_INTERNAL_PENDING)
|
||||||
GetCallback().SignalNetSuccess(msg);
|
{
|
||||||
|
if (msg <= MSG_SOCK_LIMIT_CONNECT)
|
||||||
|
GetCallback().SignalNetClientConnect(msg);
|
||||||
|
else
|
||||||
|
GetCallback().SignalNetClientGameInfo(msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (const NetException &e)
|
} catch (const NetException &e)
|
||||||
{
|
{
|
||||||
GetCallback().SignalNetError(e.GetErrorId(), e.GetOsErrorCode());
|
GetCallback().SignalNetClientError(e.GetErrorId(), e.GetOsErrorCode());
|
||||||
}
|
}
|
||||||
GetSender().SignalTermination();
|
GetSender().SignalTermination();
|
||||||
GetSender().Join(SENDER_THREAD_TERMINATE_TIMEOUT);
|
GetSender().Join(SENDER_THREAD_TERMINATE_TIMEOUT);
|
||||||
|
|||||||
@@ -22,7 +22,6 @@
|
|||||||
ConnectData::ConnectData()
|
ConnectData::ConnectData()
|
||||||
: m_sockfd(INVALID_SOCKET)
|
: m_sockfd(INVALID_SOCKET)
|
||||||
{
|
{
|
||||||
bzero(&m_sockaddr, sizeof(m_sockaddr));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ConnectData::~ConnectData()
|
ConnectData::~ConnectData()
|
||||||
@@ -31,3 +30,11 @@ ConnectData::~ConnectData()
|
|||||||
CLOSESOCKET(m_sockfd);
|
CLOSESOCKET(m_sockfd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SOCKET
|
||||||
|
ConnectData::ReleaseSocket()
|
||||||
|
{
|
||||||
|
SOCKET tmpSock = m_sockfd;
|
||||||
|
m_sockfd = INVALID_SOCKET;
|
||||||
|
return tmpSock;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
+147
-15
@@ -25,35 +25,61 @@ NetPacket::~NetPacket()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
const NetPacketInit *
|
||||||
|
NetPacket::ToNetPacketInit() const
|
||||||
TestNetPacket::TestNetPacket()
|
|
||||||
{
|
{
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
TestNetPacket::TestNetPacket(u_int32_t value)
|
const NetPacketInitAck *
|
||||||
|
NetPacket::ToNetPacketInitAck() const
|
||||||
{
|
{
|
||||||
m_data.head.type = htons(NET_TYPE_TEST);
|
return NULL;
|
||||||
m_data.head.length = htons(sizeof(m_data));
|
}
|
||||||
|
|
||||||
|
const NetPacketGameStart *
|
||||||
|
NetPacket::ToNetPacketGameStart() const
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
NetPacketInit::NetPacketInit()
|
||||||
|
{
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
NetPacketInit::NetPacketInit(u_int32_t value)
|
||||||
|
{
|
||||||
|
Init();
|
||||||
m_data.test = htonl(value);
|
m_data.test = htonl(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestNetPacket::~TestNetPacket()
|
NetPacketInit::~NetPacketInit()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
NetPacketHeader *
|
|
||||||
TestNetPacket::GetData()
|
|
||||||
{
|
|
||||||
return (NetPacketHeader *)&m_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
TestNetPacket::SetData(const NetPacketHeader *p)
|
NetPacketInit::Init()
|
||||||
|
{
|
||||||
|
m_data.head.type = htons(NET_TYPE_INIT);
|
||||||
|
m_data.head.length = htons(sizeof(m_data));
|
||||||
|
m_data.test = htonl(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const NetPacketHeader *
|
||||||
|
NetPacketInit::GetData() const
|
||||||
|
{
|
||||||
|
return (const NetPacketHeader *)&m_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetPacketInit::SetData(const NetPacketHeader *p)
|
||||||
{
|
{
|
||||||
u_int16_t tmpLen = ntohs(p->length);
|
u_int16_t tmpLen = ntohs(p->length);
|
||||||
if (tmpLen != sizeof(m_data)
|
if (tmpLen != sizeof(m_data)
|
||||||
|| ntohs(p->type) != NET_TYPE_TEST)
|
|| ntohs(p->type) != NET_TYPE_INIT)
|
||||||
{
|
{
|
||||||
throw NetException(ERR_SOCK_INTERNAL, 0);
|
throw NetException(ERR_SOCK_INTERNAL, 0);
|
||||||
}
|
}
|
||||||
@@ -61,3 +87,109 @@ TestNetPacket::SetData(const NetPacketHeader *p)
|
|||||||
memcpy(&m_data, p, tmpLen);
|
memcpy(&m_data, p, tmpLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const NetPacketInit *
|
||||||
|
NetPacketInit::ToNetPacketInit() const
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
NetPacketInitAck::NetPacketInitAck()
|
||||||
|
{
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
NetPacketInitAck::NetPacketInitAck(u_int32_t value)
|
||||||
|
{
|
||||||
|
Init();
|
||||||
|
m_data.test = htonl(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
NetPacketInitAck::~NetPacketInitAck()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetPacketInitAck::Init()
|
||||||
|
{
|
||||||
|
m_data.head.type = htons(NET_TYPE_INIT_ACK);
|
||||||
|
m_data.head.length = htons(sizeof(m_data));
|
||||||
|
m_data.test = htonl(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const NetPacketHeader *
|
||||||
|
NetPacketInitAck::GetData() const
|
||||||
|
{
|
||||||
|
return (const NetPacketHeader *)&m_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetPacketInitAck::SetData(const NetPacketHeader *p)
|
||||||
|
{
|
||||||
|
u_int16_t tmpLen = ntohs(p->length);
|
||||||
|
if (tmpLen != sizeof(m_data)
|
||||||
|
|| ntohs(p->type) != NET_TYPE_INIT_ACK)
|
||||||
|
{
|
||||||
|
throw NetException(ERR_SOCK_INTERNAL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&m_data, p, tmpLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
const NetPacketInitAck *
|
||||||
|
NetPacketInitAck::ToNetPacketInitAck() const
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
NetPacketGameStart::NetPacketGameStart()
|
||||||
|
{
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
NetPacketGameStart::NetPacketGameStart(u_int32_t value)
|
||||||
|
{
|
||||||
|
Init();
|
||||||
|
m_data.test = htonl(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
NetPacketGameStart::~NetPacketGameStart()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetPacketGameStart::Init()
|
||||||
|
{
|
||||||
|
m_data.head.type = htons(NET_TYPE_GAME_START);
|
||||||
|
m_data.head.length = htons(sizeof(m_data));
|
||||||
|
m_data.test = htonl(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const NetPacketHeader *
|
||||||
|
NetPacketGameStart::GetData() const
|
||||||
|
{
|
||||||
|
return (NetPacketHeader *)&m_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetPacketGameStart::SetData(const NetPacketHeader *p)
|
||||||
|
{
|
||||||
|
u_int16_t tmpLen = ntohs(p->length);
|
||||||
|
if (tmpLen != sizeof(m_data)
|
||||||
|
|| ntohs(p->type) != NET_TYPE_GAME_START)
|
||||||
|
{
|
||||||
|
throw NetException(ERR_SOCK_INTERNAL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&m_data, p, tmpLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
const NetPacketGameStart *
|
||||||
|
NetPacketGameStart::ToNetPacketGameStart() const
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,6 @@
|
|||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
#define RECV_TIMEOUT_MSEC 50
|
|
||||||
|
|
||||||
ReceiverHelper::ReceiverHelper()
|
ReceiverHelper::ReceiverHelper()
|
||||||
: m_socket(INVALID_SOCKET), m_tmpInBufSize(0)
|
: m_socket(INVALID_SOCKET), m_tmpInBufSize(0)
|
||||||
@@ -124,19 +123,26 @@ ReceiverHelper::InternalCreateNetPacket(const NetPacketHeader *p)
|
|||||||
{
|
{
|
||||||
boost::shared_ptr<NetPacket> tmpPacket;
|
boost::shared_ptr<NetPacket> tmpPacket;
|
||||||
|
|
||||||
switch(ntohs(p->type))
|
|
||||||
{
|
|
||||||
case NET_TYPE_TEST:
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
tmpPacket = boost::shared_ptr<NetPacket>(new TestNetPacket);
|
switch(ntohs(p->type))
|
||||||
|
{
|
||||||
|
case NET_TYPE_INIT:
|
||||||
|
tmpPacket = boost::shared_ptr<NetPacket>(new NetPacketInit);
|
||||||
|
break;
|
||||||
|
case NET_TYPE_INIT_ACK:
|
||||||
|
tmpPacket = boost::shared_ptr<NetPacket>(new NetPacketInitAck);
|
||||||
|
break;
|
||||||
|
case NET_TYPE_GAME_START:
|
||||||
|
tmpPacket = boost::shared_ptr<NetPacket>(new NetPacketGameStart);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (tmpPacket.get())
|
||||||
tmpPacket->SetData(p);
|
tmpPacket->SetData(p);
|
||||||
} catch (const NetException &)
|
} catch (const NetException &)
|
||||||
{
|
{
|
||||||
tmpPacket.reset();
|
tmpPacket.reset();
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
return tmpPacket;
|
return tmpPacket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,10 +17,10 @@
|
|||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#include <net/netcallback.h>
|
#include <net/servercallback.h>
|
||||||
|
|
||||||
|
|
||||||
NetCallback::~NetCallback()
|
ServerCallback::~ServerCallback()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -19,6 +19,9 @@
|
|||||||
|
|
||||||
#include <net/serverrecvstate.h>
|
#include <net/serverrecvstate.h>
|
||||||
#include <net/serverrecvthread.h>
|
#include <net/serverrecvthread.h>
|
||||||
|
#include <net/receiverhelper.h>
|
||||||
|
#include <net/senderthread.h>
|
||||||
|
#include <net/netpacket.h>
|
||||||
#include <net/socket_msg.h>
|
#include <net/socket_msg.h>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@@ -48,14 +51,78 @@ ServerRecvStateInit::~ServerRecvStateInit()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ServerRecvStateInit::HandleNewConnection(ServerRecvThread &server, boost::shared_ptr<ConnectData> data)
|
ServerRecvStateInit::HandleNewConnection(ServerRecvThread &server, boost::shared_ptr<ConnectData> connData)
|
||||||
{
|
{
|
||||||
|
boost::shared_ptr<SessionData> sessionData(new SessionData);
|
||||||
|
server.AddSession(connData, sessionData);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ServerRecvStateInit::Process(ServerRecvThread &server)
|
ServerRecvStateInit::Process(ServerRecvThread &server)
|
||||||
{
|
{
|
||||||
Thread::Msleep(SERVER_WAIT_TIMEOUT_MSEC);
|
SOCKET recvSock = server.Select();
|
||||||
|
|
||||||
|
if (recvSock != INVALID_SOCKET)
|
||||||
|
{
|
||||||
|
boost::shared_ptr<NetPacket> packet = server.GetReceiver().Recv(recvSock);
|
||||||
|
boost::shared_ptr<SessionData> session = server.GetSession(recvSock);
|
||||||
|
|
||||||
|
// Ignore if no session / no packet.
|
||||||
|
if (packet.get() && session.get())
|
||||||
|
{
|
||||||
|
if (session->GetState() == SessionData::Init)
|
||||||
|
{
|
||||||
|
// Only accept init packets.
|
||||||
|
if (packet->ToNetPacketInit())
|
||||||
|
{
|
||||||
|
boost::shared_ptr<NetPacket> answer(new NetPacketInitAck);
|
||||||
|
server.GetSender().Send(answer, recvSock);
|
||||||
|
session->SetState(SessionData::Established);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO send error message, invalid packet
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO send error message, invalid state
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return MSG_SOCK_INIT_DONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
ServerRecvStateStartGame &
|
||||||
|
ServerRecvStateStartGame::Instance()
|
||||||
|
{
|
||||||
|
static ServerRecvStateStartGame state;
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerRecvStateStartGame::ServerRecvStateStartGame()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerRecvStateStartGame::~ServerRecvStateStartGame()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ServerRecvStateStartGame::HandleNewConnection(ServerRecvThread &server, boost::shared_ptr<ConnectData> connData)
|
||||||
|
{
|
||||||
|
// TODO: send error msg
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ServerRecvStateStartGame::Process(ServerRecvThread &server)
|
||||||
|
{
|
||||||
|
boost::shared_ptr<NetPacket> answer(new NetPacketGameStart);
|
||||||
|
|
||||||
|
server.SendToAllClients(answer);
|
||||||
|
|
||||||
return MSG_SOCK_INIT_DONE;
|
return MSG_SOCK_INIT_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,28 @@ ServerRecvThread::~ServerRecvThread()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ServerRecvThread::StartGame()
|
||||||
|
{
|
||||||
|
// TODO: not thread safe. use flag or something.
|
||||||
|
SetState(SERVER_START_GAME_STATE::Instance());
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ServerRecvThread::SendToAllClients(boost::shared_ptr<NetPacket> packet)
|
||||||
|
{
|
||||||
|
// TODO: possible race condition if used in multithreading
|
||||||
|
SocketSessionMap::iterator i = m_sessions.begin();
|
||||||
|
SocketSessionMap::iterator end = m_sessions.end();
|
||||||
|
|
||||||
|
while (i != end)
|
||||||
|
{
|
||||||
|
// TODO: desparately need clone here, this is very dangerous.
|
||||||
|
GetSender().Send(packet, i->first);
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ServerRecvThread::AddConnection(boost::shared_ptr<ConnectData> data)
|
ServerRecvThread::AddConnection(boost::shared_ptr<ConnectData> data)
|
||||||
{
|
{
|
||||||
@@ -91,6 +113,67 @@ ServerRecvThread::Main()
|
|||||||
}
|
}
|
||||||
GetSender().SignalTermination();
|
GetSender().SignalTermination();
|
||||||
GetSender().Join(SENDER_THREAD_TERMINATE_TIMEOUT);
|
GetSender().Join(SENDER_THREAD_TERMINATE_TIMEOUT);
|
||||||
|
|
||||||
|
// TODO: clear connection queue
|
||||||
|
}
|
||||||
|
|
||||||
|
SOCKET
|
||||||
|
ServerRecvThread::Select()
|
||||||
|
{
|
||||||
|
SOCKET retSock = INVALID_SOCKET;
|
||||||
|
|
||||||
|
if (m_sessions.empty())
|
||||||
|
{
|
||||||
|
Msleep(RECV_TIMEOUT_MSEC); // just sleep if there is no session
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// wait for data
|
||||||
|
SOCKET maxSock = 0;
|
||||||
|
fd_set rdset;
|
||||||
|
FD_ZERO(&rdset);
|
||||||
|
|
||||||
|
{
|
||||||
|
SocketSessionMap::iterator i = m_sessions.begin();
|
||||||
|
SocketSessionMap::iterator end = m_sessions.end();
|
||||||
|
|
||||||
|
while (i != end)
|
||||||
|
{
|
||||||
|
SOCKET tmpSock = i->first;
|
||||||
|
FD_SET(tmpSock, &rdset);
|
||||||
|
if (tmpSock > maxSock)
|
||||||
|
maxSock = tmpSock;
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct timeval timeout;
|
||||||
|
timeout.tv_sec = 0;
|
||||||
|
timeout.tv_usec = RECV_TIMEOUT_MSEC * 1000;
|
||||||
|
int selectResult = select(maxSock + 1, &rdset, NULL, NULL, &timeout);
|
||||||
|
if (!IS_VALID_SELECT(selectResult))
|
||||||
|
{
|
||||||
|
throw ServerException(ERR_SOCK_SELECT_FAILED, SOCKET_ERRNO());
|
||||||
|
}
|
||||||
|
if (selectResult > 0) // one (or more) of the sockets is readable
|
||||||
|
{
|
||||||
|
// Check which socket is readable, return the first.
|
||||||
|
SocketSessionMap::iterator i = m_sessions.begin();
|
||||||
|
SocketSessionMap::iterator end = m_sessions.end();
|
||||||
|
|
||||||
|
while (i != end)
|
||||||
|
{
|
||||||
|
SOCKET tmpSock = i->first;
|
||||||
|
if (FD_ISSET(tmpSock, &rdset))
|
||||||
|
{
|
||||||
|
retSock = tmpSock;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return retSock;
|
||||||
}
|
}
|
||||||
|
|
||||||
ServerRecvState &
|
ServerRecvState &
|
||||||
@@ -106,6 +189,33 @@ ServerRecvThread::SetState(ServerRecvState &newState)
|
|||||||
m_curState = &newState;
|
m_curState = &newState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boost::shared_ptr<SessionData>
|
||||||
|
ServerRecvThread::GetSession(SOCKET sock)
|
||||||
|
{
|
||||||
|
boost::shared_ptr<SessionData> tmpSession;
|
||||||
|
|
||||||
|
SocketSessionMap::iterator pos = m_sessions.find(sock);
|
||||||
|
if (pos != m_sessions.end())
|
||||||
|
{
|
||||||
|
tmpSession = pos->second;
|
||||||
|
}
|
||||||
|
return tmpSession;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ServerRecvThread::AddSession(boost::shared_ptr<ConnectData> connData, boost::shared_ptr<SessionData> sessionData)
|
||||||
|
{
|
||||||
|
SocketSessionMap::iterator pos = m_sessions.lower_bound(connData->GetSocket());
|
||||||
|
|
||||||
|
// If pos points to a pair whose key is equivalent to the socket, this handle
|
||||||
|
// already exists within the list.
|
||||||
|
if (pos != m_sessions.end() && connData->GetSocket() == pos->first)
|
||||||
|
{
|
||||||
|
throw ServerException(ERR_SOCK_CONN_EXISTS, 0);
|
||||||
|
}
|
||||||
|
m_sessions.insert(pos, SocketSessionMap::value_type(connData->ReleaseSocket(), sessionData));
|
||||||
|
}
|
||||||
|
|
||||||
SenderThread &
|
SenderThread &
|
||||||
ServerRecvThread::GetSender()
|
ServerRecvThread::GetSender()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -29,7 +29,8 @@
|
|||||||
#define NET_SERVER_LISTEN_BACKLOG 5
|
#define NET_SERVER_LISTEN_BACKLOG 5
|
||||||
|
|
||||||
|
|
||||||
ServerThread::ServerThread()
|
ServerThread::ServerThread(ServerCallback &cb)
|
||||||
|
: m_callback(cb)
|
||||||
{
|
{
|
||||||
m_context.reset(new ServerContext);
|
m_context.reset(new ServerContext);
|
||||||
}
|
}
|
||||||
@@ -51,6 +52,22 @@ ServerThread::Init(unsigned serverPort, bool ipv6, const std::string &pwd)
|
|||||||
context.SetPassword(pwd);
|
context.SetPassword(pwd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ServerThread::StartGame()
|
||||||
|
{
|
||||||
|
if (!IsRunning())
|
||||||
|
return; // TODO: throw exception
|
||||||
|
|
||||||
|
// TODO: possible race condition
|
||||||
|
GetRecvThread().StartGame();
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerCallback &
|
||||||
|
ServerThread::GetCallback()
|
||||||
|
{
|
||||||
|
return m_callback;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ServerThread::Main()
|
ServerThread::Main()
|
||||||
{
|
{
|
||||||
@@ -65,9 +82,9 @@ ServerThread::Main()
|
|||||||
// The main server thread is simple. It only accepts connections.
|
// The main server thread is simple. It only accepts connections.
|
||||||
AcceptLoop();
|
AcceptLoop();
|
||||||
}
|
}
|
||||||
} catch (const NetException &)
|
} catch (const NetException &e)
|
||||||
{
|
{
|
||||||
// TODO: callback.
|
GetCallback().SignalNetServerError(e.GetErrorId(), e.GetOsErrorCode());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,8 +158,7 @@ ServerThread::AcceptLoop()
|
|||||||
if (selectResult > 0) // accept is possible
|
if (selectResult > 0) // accept is possible
|
||||||
{
|
{
|
||||||
boost::shared_ptr<ConnectData> tmpData(new ConnectData);
|
boost::shared_ptr<ConnectData> tmpData(new ConnectData);
|
||||||
socklen_t addrSize = sizeof(*tmpData->GetSockaddr());
|
tmpData->SetSocket(accept(context.GetSocket(), NULL, NULL));
|
||||||
tmpData->SetSocket(accept(context.GetSocket(), (struct sockaddr *)tmpData->GetSockaddr(), &addrSize));
|
|
||||||
|
|
||||||
if (!IS_VALID_SOCKET(tmpData->GetSocket()))
|
if (!IS_VALID_SOCKET(tmpData->GetSocket()))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2007 by Lothar May *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include <net/sessiondata.h>
|
||||||
|
|
||||||
|
SessionData::SessionData()
|
||||||
|
: m_id(SESSION_ID_INIT), m_state(SessionData::Init)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SessionData::~SessionData()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
@@ -33,14 +33,11 @@ public:
|
|||||||
{return m_sockfd;}
|
{return m_sockfd;}
|
||||||
void SetSocket(SOCKET sockfd)
|
void SetSocket(SOCKET sockfd)
|
||||||
{m_sockfd = sockfd;}
|
{m_sockfd = sockfd;}
|
||||||
const sockaddr_storage *GetSockaddr() const
|
|
||||||
{return &m_sockaddr;}
|
SOCKET ReleaseSocket();
|
||||||
sockaddr_storage *GetSockaddr()
|
|
||||||
{return &m_sockaddr;}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SOCKET m_sockfd;
|
SOCKET m_sockfd;
|
||||||
sockaddr_storage m_sockaddr;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+73
-9
@@ -26,7 +26,9 @@
|
|||||||
|
|
||||||
#define MAX_PACKET_SIZE 256
|
#define MAX_PACKET_SIZE 256
|
||||||
|
|
||||||
#define NET_TYPE_TEST 0
|
#define NET_TYPE_INIT 0
|
||||||
|
#define NET_TYPE_INIT_ACK 1
|
||||||
|
#define NET_TYPE_GAME_START 2
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma pack(push, 2)
|
#pragma pack(push, 2)
|
||||||
@@ -40,7 +42,19 @@ struct NetPacketHeader
|
|||||||
u_int16_t length;
|
u_int16_t length;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NetPacketInit
|
struct NetPacketInitData
|
||||||
|
{
|
||||||
|
NetPacketHeader head;
|
||||||
|
u_int32_t test;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct NetPacketInitAckData
|
||||||
|
{
|
||||||
|
NetPacketHeader head;
|
||||||
|
u_int32_t test;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct NetPacketGameStartData
|
||||||
{
|
{
|
||||||
NetPacketHeader head;
|
NetPacketHeader head;
|
||||||
u_int32_t test;
|
u_int32_t test;
|
||||||
@@ -52,6 +66,9 @@ struct NetPacketInit
|
|||||||
#pragma align 0
|
#pragma align 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
class NetPacketInit;
|
||||||
|
class NetPacketInitAck;
|
||||||
|
class NetPacketGameStart;
|
||||||
|
|
||||||
class NetPacket
|
class NetPacket
|
||||||
{
|
{
|
||||||
@@ -59,21 +76,68 @@ public:
|
|||||||
virtual ~NetPacket();
|
virtual ~NetPacket();
|
||||||
|
|
||||||
virtual void SetData(const NetPacketHeader *p) = 0;
|
virtual void SetData(const NetPacketHeader *p) = 0;
|
||||||
virtual NetPacketHeader *GetData() = 0;
|
virtual const NetPacketHeader *GetData() const = 0;
|
||||||
|
|
||||||
|
virtual const NetPacketInit *ToNetPacketInit() const;
|
||||||
|
virtual const NetPacketInitAck *ToNetPacketInitAck() const;
|
||||||
|
virtual const NetPacketGameStart *ToNetPacketGameStart() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TestNetPacket : public NetPacket
|
class NetPacketInit : public NetPacket
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TestNetPacket();
|
NetPacketInit();
|
||||||
TestNetPacket(u_int32_t value);
|
NetPacketInit(u_int32_t value);
|
||||||
virtual ~TestNetPacket();
|
virtual ~NetPacketInit();
|
||||||
|
|
||||||
virtual NetPacketHeader *GetData();
|
virtual const NetPacketHeader *GetData() const;
|
||||||
virtual void SetData(const NetPacketHeader *p);
|
virtual void SetData(const NetPacketHeader *p);
|
||||||
|
|
||||||
|
virtual const NetPacketInit *ToNetPacketInit() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
NetPacketInit m_data;
|
void Init();
|
||||||
|
|
||||||
|
private:
|
||||||
|
NetPacketInitData m_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
class NetPacketInitAck : public NetPacket
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NetPacketInitAck();
|
||||||
|
NetPacketInitAck(u_int32_t value);
|
||||||
|
virtual ~NetPacketInitAck();
|
||||||
|
|
||||||
|
virtual const NetPacketHeader *GetData() const;
|
||||||
|
virtual void SetData(const NetPacketHeader *p);
|
||||||
|
|
||||||
|
virtual const NetPacketInitAck *ToNetPacketInitAck() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void Init();
|
||||||
|
|
||||||
|
private:
|
||||||
|
NetPacketInitAckData m_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
class NetPacketGameStart : public NetPacket
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NetPacketGameStart();
|
||||||
|
NetPacketGameStart(u_int32_t value);
|
||||||
|
virtual ~NetPacketGameStart();
|
||||||
|
|
||||||
|
virtual const NetPacketHeader *GetData() const;
|
||||||
|
virtual void SetData(const NetPacketHeader *p);
|
||||||
|
|
||||||
|
virtual const NetPacketGameStart *ToNetPacketGameStart() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void Init();
|
||||||
|
|
||||||
|
private:
|
||||||
|
NetPacketGameStartData m_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
|
|
||||||
// MUST be larger than MAX_PACKET_SIZE
|
// MUST be larger than MAX_PACKET_SIZE
|
||||||
#define RECV_BUF_SIZE 10 * MAX_PACKET_SIZE
|
#define RECV_BUF_SIZE 10 * MAX_PACKET_SIZE
|
||||||
|
#define RECV_TIMEOUT_MSEC 50
|
||||||
|
|
||||||
|
|
||||||
class ReceiverHelper
|
class ReceiverHelper
|
||||||
|
|||||||
@@ -16,18 +16,18 @@
|
|||||||
* Free Software Foundation, Inc., *
|
* Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
/* Generic callback interface for network system. */
|
/* Callback interface for network server gui. */
|
||||||
|
|
||||||
#ifndef _NETCALLBACK_H_
|
#ifndef _SERVERCALLBACK_H_
|
||||||
#define _NETCALLBACK_H_
|
#define _SERVERCALLBACK_H_
|
||||||
|
|
||||||
class NetCallback
|
class ServerCallback
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~NetCallback();
|
virtual ~ServerCallback();
|
||||||
|
|
||||||
virtual void SignalNetSuccess(int actionID) = 0;
|
virtual void SignalNetServerSuccess(int actionID) = 0;
|
||||||
virtual void SignalNetError(int errorID, int osErrorID) = 0;
|
virtual void SignalNetServerError(int errorID, int osErrorID) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -25,6 +25,7 @@
|
|||||||
#include <net/connectdata.h>
|
#include <net/connectdata.h>
|
||||||
|
|
||||||
#define SERVER_INITIAL_STATE ServerRecvStateInit
|
#define SERVER_INITIAL_STATE ServerRecvStateInit
|
||||||
|
#define SERVER_START_GAME_STATE ServerRecvStateStartGame
|
||||||
|
|
||||||
class ServerRecvThread;
|
class ServerRecvThread;
|
||||||
class ServerCallback;
|
class ServerCallback;
|
||||||
@@ -35,7 +36,7 @@ public:
|
|||||||
virtual ~ServerRecvState();
|
virtual ~ServerRecvState();
|
||||||
|
|
||||||
// Handling of a new TCP connection.
|
// Handling of a new TCP connection.
|
||||||
virtual void HandleNewConnection(ServerRecvThread &server, boost::shared_ptr<ConnectData> data) = 0;
|
virtual void HandleNewConnection(ServerRecvThread &server, boost::shared_ptr<ConnectData> connData) = 0;
|
||||||
|
|
||||||
// Main processing function of the current state.
|
// Main processing function of the current state.
|
||||||
virtual int Process(ServerRecvThread &server) = 0;
|
virtual int Process(ServerRecvThread &server) = 0;
|
||||||
@@ -62,4 +63,25 @@ protected:
|
|||||||
ServerRecvStateInit();
|
ServerRecvStateInit();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// State: Start server game.
|
||||||
|
class ServerRecvStateStartGame : public ServerRecvState
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Access the state singleton.
|
||||||
|
static ServerRecvStateStartGame &Instance();
|
||||||
|
|
||||||
|
virtual ~ServerRecvStateStartGame();
|
||||||
|
|
||||||
|
//
|
||||||
|
virtual void HandleNewConnection(ServerRecvThread &server, boost::shared_ptr<ConnectData> data);
|
||||||
|
|
||||||
|
//
|
||||||
|
virtual int Process(ServerRecvThread &server);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// Protected constructor - this is a singleton.
|
||||||
|
ServerRecvStateStartGame();
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -23,14 +23,17 @@
|
|||||||
|
|
||||||
#include <core/thread.h>
|
#include <core/thread.h>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
#include <map>
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
#include <net/connectdata.h>
|
#include <net/connectdata.h>
|
||||||
|
#include <net/sessiondata.h>
|
||||||
|
|
||||||
class ServerRecvState;
|
class ServerRecvState;
|
||||||
class SenderThread;
|
class SenderThread;
|
||||||
class ReceiverHelper;
|
class ReceiverHelper;
|
||||||
class ServerSenderCallback;
|
class ServerSenderCallback;
|
||||||
|
class NetPacket;
|
||||||
|
|
||||||
class ServerRecvThread : public Thread
|
class ServerRecvThread : public Thread
|
||||||
{
|
{
|
||||||
@@ -38,18 +41,24 @@ public:
|
|||||||
ServerRecvThread();
|
ServerRecvThread();
|
||||||
virtual ~ServerRecvThread();
|
virtual ~ServerRecvThread();
|
||||||
|
|
||||||
|
void StartGame();
|
||||||
|
void SendToAllClients(boost::shared_ptr<NetPacket> packet);
|
||||||
void AddConnection(boost::shared_ptr<ConnectData> data);
|
void AddConnection(boost::shared_ptr<ConnectData> data);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
typedef std::map<SOCKET, boost::shared_ptr<SessionData> > SocketSessionMap;
|
||||||
|
|
||||||
// Main function of the thread.
|
// Main function of the thread.
|
||||||
virtual void Main();
|
virtual void Main();
|
||||||
|
|
||||||
|
SOCKET Select();
|
||||||
|
|
||||||
ServerRecvState &GetState();
|
ServerRecvState &GetState();
|
||||||
void SetState(ServerRecvState &newState);
|
void SetState(ServerRecvState &newState);
|
||||||
|
|
||||||
//const ServerRecvContext &GetContext() const;
|
boost::shared_ptr<SessionData> GetSession(SOCKET sock);
|
||||||
//ServerRecvContext &GetContext();
|
void AddSession(boost::shared_ptr<ConnectData> connData, boost::shared_ptr<SessionData> sessionData);
|
||||||
|
|
||||||
SenderThread &GetSender();
|
SenderThread &GetSender();
|
||||||
ReceiverHelper &GetReceiver();
|
ReceiverHelper &GetReceiver();
|
||||||
@@ -57,16 +66,19 @@ protected:
|
|||||||
ServerSenderCallback &GetSenderCallback();
|
ServerSenderCallback &GetSenderCallback();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//std::auto_ptr<ServerRecvContext> m_context;
|
|
||||||
|
|
||||||
std::deque<boost::shared_ptr<ConnectData> > m_connectQueue;
|
std::deque<boost::shared_ptr<ConnectData> > m_connectQueue;
|
||||||
mutable boost::mutex m_connectQueueMutex;
|
mutable boost::mutex m_connectQueueMutex;
|
||||||
ServerRecvState *m_curState;
|
ServerRecvState *m_curState;
|
||||||
|
|
||||||
|
SocketSessionMap m_sessions;
|
||||||
|
|
||||||
std::auto_ptr<ReceiverHelper> m_receiver;
|
std::auto_ptr<ReceiverHelper> m_receiver;
|
||||||
std::auto_ptr<SenderThread> m_sender;
|
std::auto_ptr<SenderThread> m_sender;
|
||||||
|
|
||||||
std::auto_ptr<ServerSenderCallback> m_senderCallback;
|
std::auto_ptr<ServerSenderCallback> m_senderCallback;
|
||||||
|
|
||||||
|
friend class ServerRecvStateInit;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include <core/thread.h>
|
#include <core/thread.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <net/servercallback.h>
|
||||||
|
|
||||||
class ServerContext;
|
class ServerContext;
|
||||||
class ServerRecvThread;
|
class ServerRecvThread;
|
||||||
@@ -33,11 +34,14 @@ class SenderThread;
|
|||||||
class ServerThread : public Thread
|
class ServerThread : public Thread
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ServerThread(/*ServerCallback &gui*/);
|
ServerThread(ServerCallback &gui);
|
||||||
virtual ~ServerThread();
|
virtual ~ServerThread();
|
||||||
|
|
||||||
// Set the parameters.
|
// Set the parameters.
|
||||||
void Init(unsigned serverPort, bool ipv6, const std::string &pwd);
|
void Init(unsigned serverPort, bool ipv6, const std::string &pwd);
|
||||||
|
void StartGame();
|
||||||
|
|
||||||
|
ServerCallback &GetCallback();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
@@ -55,6 +59,8 @@ protected:
|
|||||||
private:
|
private:
|
||||||
std::auto_ptr<ServerContext> m_context;
|
std::auto_ptr<ServerContext> m_context;
|
||||||
std::auto_ptr<ServerRecvThread> m_recvThread;
|
std::auto_ptr<ServerRecvThread> m_recvThread;
|
||||||
|
|
||||||
|
ServerCallback &m_callback;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2007 by Lothar May *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
/* Session data (a session is a valid client connection). */
|
||||||
|
|
||||||
|
#ifndef _SESSIONDATA_H_
|
||||||
|
#define _SESSIONDATA_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#define SESSION_ID_INIT 0
|
||||||
|
|
||||||
|
class SessionData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum State { Init, Established };
|
||||||
|
|
||||||
|
SessionData();
|
||||||
|
~SessionData();
|
||||||
|
|
||||||
|
unsigned GetId() const
|
||||||
|
{return m_id;}
|
||||||
|
void SetId(unsigned id)
|
||||||
|
{m_id = id;}
|
||||||
|
State GetState() const
|
||||||
|
{return m_state;}
|
||||||
|
void SetState(State state)
|
||||||
|
{m_state = state;}
|
||||||
|
|
||||||
|
const std::string &GetClientAddr() const
|
||||||
|
{return m_clientAddr;}
|
||||||
|
void SetClientAddr(const std::string &addr)
|
||||||
|
{m_clientAddr = addr;}
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned m_id;
|
||||||
|
State m_state;
|
||||||
|
std::string m_clientAddr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -35,16 +35,22 @@
|
|||||||
#define ERR_SOCK_RECV_FAILED 13
|
#define ERR_SOCK_RECV_FAILED 13
|
||||||
#define ERR_SOCK_SEND_FAILED 14
|
#define ERR_SOCK_SEND_FAILED 14
|
||||||
#define ERR_SOCK_CONN_RESET 15
|
#define ERR_SOCK_CONN_RESET 15
|
||||||
|
#define ERR_SOCK_CONN_EXISTS 16
|
||||||
|
|
||||||
// This is an internal message which is not reported.
|
// This is an internal message which is not reported.
|
||||||
#define MSG_SOCK_INTERNAL_PENDING 0
|
#define MSG_SOCK_INTERNAL_PENDING 0
|
||||||
|
|
||||||
// The following messages are reported.
|
// The following messages are connect messages.
|
||||||
#define MSG_SOCK_INIT_DONE 1
|
#define MSG_SOCK_INIT_DONE 1
|
||||||
#define MSG_SOCK_RESOLVE_DONE 2
|
#define MSG_SOCK_RESOLVE_DONE 2
|
||||||
#define MSG_SOCK_CONNECT_DONE 3
|
#define MSG_SOCK_CONNECT_DONE 3
|
||||||
#define MSG_SOCK_SESSION_DONE 4
|
#define MSG_SOCK_SESSION_DONE 4
|
||||||
|
|
||||||
|
#define MSG_SOCK_LIMIT_CONNECT MSG_SOCK_SESSION_DONE
|
||||||
|
|
||||||
|
// The following messages are game messages.
|
||||||
|
#define MSG_SOCK_GAME_START 5
|
||||||
|
|
||||||
#define MSG_SOCK_LAST MSG_SOCK_SESSION_DONE
|
#define MSG_SOCK_LAST MSG_SOCK_SESSION_DONE
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+9
-2
@@ -85,14 +85,21 @@ void Session::startNetworkServer()
|
|||||||
{
|
{
|
||||||
if (myNetServer)
|
if (myNetServer)
|
||||||
return; // TODO: throw exception
|
return; // TODO: throw exception
|
||||||
myNetServer = new ServerThread();
|
myNetServer = new ServerThread(*myGui);
|
||||||
myNetServer->Init(
|
myNetServer->Init(
|
||||||
myConfig->readConfigInt("ServerPort"),
|
myConfig->readConfigInt("ServerPort"),
|
||||||
myConfig->readConfigInt("ServerUseIpv6") == 1,
|
myConfig->readConfigInt("ServerUseIpv6") == 1,
|
||||||
"");
|
""); // TODO: use pwd
|
||||||
myNetServer->Run();
|
myNetServer->Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Session::initiateNetworkServerGame()
|
||||||
|
{
|
||||||
|
if (!myNetServer)
|
||||||
|
return; // TODO: throw exception
|
||||||
|
myNetServer->StartGame();
|
||||||
|
}
|
||||||
|
|
||||||
void Session::terminateNetworkServer()
|
void Session::terminateNetworkServer()
|
||||||
{
|
{
|
||||||
if (!myNetServer)
|
if (!myNetServer)
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ public:
|
|||||||
void terminateNetworkClient();
|
void terminateNetworkClient();
|
||||||
|
|
||||||
void startNetworkServer();
|
void startNetworkServer();
|
||||||
|
void initiateNetworkServerGame();
|
||||||
void terminateNetworkServer();
|
void terminateNetworkServer();
|
||||||
|
|
||||||
void setActualGameID(const int& theValue) { actualGameID = theValue; }
|
void setActualGameID(const int& theValue) { actualGameID = theValue; }
|
||||||
|
|||||||
Reference in New Issue
Block a user