diff --git a/pokerth.pro b/pokerth.pro index 4860ce94..2a23f56d 100755 --- a/pokerth.pro +++ b/pokerth.pro @@ -148,6 +148,10 @@ SOURCES += src/game.cpp \ src/net/common/senderthread.cpp \ src/net/common/serverthread.cpp \ src/net/common/socket_helper_cmn.cpp \ + src/net/common/clientexception.cpp \ + src/net/common/netcallback.cpp \ + src/net/common/netexception.cpp \ + src/net/common/receiverhelper.cpp \ src/gui/qt/aboutpokerth/aboutpokerthimpl.cpp \ src/gui/qt/connecttoserverdialog/connecttoserverdialogimpl.cpp \ src/gui/qt/createnetworkgamedialog/createnetworkgamedialogimpl.cpp \ diff --git a/src/gui/qt/connecttoserverdialog/connecttoserverdialogimpl.cpp b/src/gui/qt/connecttoserverdialog/connecttoserverdialogimpl.cpp index b920dd6b..908dc8a8 100644 --- a/src/gui/qt/connecttoserverdialog/connecttoserverdialogimpl.cpp +++ b/src/gui/qt/connecttoserverdialog/connecttoserverdialogimpl.cpp @@ -94,10 +94,15 @@ void connectToServerDialogImpl::error(int errorID, int osErrorID) { tr("Internal network error: \"recv\" failed."), QMessageBox::Close); } break; + case ERR_SOCK_SEND_FAILED: { QMessageBox::warning(this, tr("Network Error"), tr("Internal network error: \"send\" failed."), QMessageBox::Close); } - case ERR_SOCK_SEND_FAILED: + break; + case ERR_SOCK_CONN_RESET: + { QMessageBox::warning(this, tr("Network Error"), + tr("Connection was closed by server."), + QMessageBox::Close); } break; default: { QMessageBox::warning(this, tr("Network Error"), tr("DEFAULT ERROR"), diff --git a/src/gui/qt/guiwrapper.cpp b/src/gui/qt/guiwrapper.cpp index 3e11aa3d..0928a895 100644 --- a/src/gui/qt/guiwrapper.cpp +++ b/src/gui/qt/guiwrapper.cpp @@ -88,5 +88,5 @@ void GuiWrapper::meInAction() const { myW->meInAction(); } 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::SignalNetClientSuccess(int actionID) { myW->SignalNetClientSuccess(actionID); } -void GuiWrapper::SignalNetClientError(int errorID, int osErrorID) { myW->SignalNetClientError(errorID, osErrorID); } +void GuiWrapper::SignalNetSuccess(int actionID) { myW->SignalNetSuccess(actionID); } +void GuiWrapper::SignalNetError(int errorID, int osErrorID) { myW->SignalNetError(errorID, osErrorID); } diff --git a/src/gui/qt/guiwrapper.h b/src/gui/qt/guiwrapper.h index 2a5c31cf..434097c8 100644 --- a/src/gui/qt/guiwrapper.h +++ b/src/gui/qt/guiwrapper.h @@ -88,8 +88,8 @@ public: void logPlayerActionMsg(std::string playerName, int action, int setValue) ; void logNewGameHandMsg(int gameID, int handID) ; - void SignalNetClientSuccess(int actionID); - void SignalNetClientError(int errorID, int osErrorID); + void SignalNetSuccess(int actionID); + void SignalNetError(int errorID, int osErrorID); private: diff --git a/src/gui/qt/mainwindow/mainwindowimpl.cpp b/src/gui/qt/mainwindow/mainwindowimpl.cpp index 5589ccf4..ca9e734b 100755 --- a/src/gui/qt/mainwindow/mainwindowimpl.cpp +++ b/src/gui/qt/mainwindow/mainwindowimpl.cpp @@ -480,8 +480,8 @@ mainWindowImpl::mainWindowImpl(QMainWindow *parent) connect ( pushButton_break, SIGNAL( clicked()), this, SLOT ( breakButtonClicked() ) ); // auch wieder starten!!!! //Nachrichten Thread-Save - connect(this, SIGNAL(SignalNetClientSuccess(int)), myConnectToServerDialog, SLOT(refresh(int))); - connect(this, SIGNAL(SignalNetClientError(int, int)), myConnectToServerDialog, SLOT(error(int, int))); + connect(this, SIGNAL(SignalNetSuccess(int)), myConnectToServerDialog, SLOT(refresh(int))); + connect(this, SIGNAL(SignalNetError(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->x(),10)+" "+QString::number(this->y(),10)); diff --git a/src/gui/qt/mainwindow/mainwindowimpl.h b/src/gui/qt/mainwindow/mainwindowimpl.h index b43a7e65..f003b182 100755 --- a/src/gui/qt/mainwindow/mainwindowimpl.h +++ b/src/gui/qt/mainwindow/mainwindowimpl.h @@ -88,8 +88,8 @@ public: void setSpeeds(); signals: - void SignalNetClientSuccess(int actionID); - void SignalNetClientError(int errorID, int osErrorID); + void SignalNetSuccess(int actionID); + void SignalNetError(int errorID, int osErrorID); public slots: diff --git a/src/net/clientcallback.h b/src/net/clientcallback.h index 769ab6b6..47699484 100644 --- a/src/net/clientcallback.h +++ b/src/net/clientcallback.h @@ -21,13 +21,15 @@ #ifndef _CLIENTCALLBACK_H_ #define _CLIENTCALLBACK_H_ -class ClientCallback +#include + +class ClientCallback : public NetCallback { public: virtual ~ClientCallback(); - virtual void SignalNetClientSuccess(int actionID) = 0; - virtual void SignalNetClientError(int errorID, int osErrorID) = 0; + virtual void SignalNetSuccess(int actionID) = 0; + virtual void SignalNetError(int errorID, int osErrorID) = 0; }; #endif diff --git a/src/net/clientexception.h b/src/net/clientexception.h index de1c45bc..29bcdeaa 100644 --- a/src/net/clientexception.h +++ b/src/net/clientexception.h @@ -21,20 +21,16 @@ #ifndef _CLIENTEXCEPTION_H_ #define _CLIENTEXCEPTION_H_ +#include -class ClientException +class ClientException : public NetException { public: ClientException(int errorId, int osErrorCode) - : m_errorId(errorId), m_osErrorCode(osErrorCode) {} + : NetException(errorId, osErrorCode) {} - int GetErrorId() const {return m_errorId;} - int GetOsErrorCode() const {return m_osErrorCode;} - -private: - int m_errorId; - int m_osErrorCode; + virtual ~ClientException(); }; #endif diff --git a/src/net/clientthread.h b/src/net/clientthread.h index 7080ef7d..7b75a574 100644 --- a/src/net/clientthread.h +++ b/src/net/clientthread.h @@ -29,6 +29,7 @@ class ClientData; class ClientState; class ClientCallback; class SenderThread; +class ReceiverHelper; class ClientThread : public Thread { @@ -53,6 +54,7 @@ protected: void SetState(ClientState &newState); SenderThread &GetSender(); + ReceiverHelper &GetReceiver(); private: @@ -60,6 +62,7 @@ private: ClientState *m_curState; ClientCallback &m_callback; std::auto_ptr m_sender; + std::auto_ptr m_receiver; friend class ClientStateInit; friend class ClientStateStartResolve; diff --git a/src/net/common/clientexception.cpp b/src/net/common/clientexception.cpp new file mode 100644 index 00000000..48293d0e --- /dev/null +++ b/src/net/common/clientexception.cpp @@ -0,0 +1,26 @@ +/*************************************************************************** + * 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 + + +ClientException::~ClientException() +{ +} + diff --git a/src/net/common/clientstate.cpp b/src/net/common/clientstate.cpp index 828556c9..92709435 100644 --- a/src/net/common/clientstate.cpp +++ b/src/net/common/clientstate.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -322,6 +323,7 @@ ClientStateStartSession::~ClientStateStartSession() int ClientStateStartSession::Process(ClientThread &client) { + client.GetReceiver().Init(client.GetData().sockfd); client.GetSender().Init(client.GetData().sockfd); client.GetSender().Run(); @@ -356,29 +358,20 @@ ClientStateWaitSession::Process(ClientThread &client) int retVal; ClientData &data = client.GetData(); - // TODO: use receiver thread. - fd_set readSet; - struct timeval timeout; + // delegate to receiver helper class - FD_ZERO(&readSet); - FD_SET(data.sockfd, &readSet); + boost::shared_ptr tmpPacket = client.GetReceiver().Recv(); - timeout.tv_sec = 0; - timeout.tv_usec = CLIENT_WAIT_TIMEOUT_MSEC * 1000; - int selectResult = select(data.sockfd + 1, &readSet, NULL, NULL, &timeout); - if (selectResult > 0) // recv is possible + if (tmpPacket.get()) { - char buf[128]; - if (recv(data.sockfd, buf, sizeof(buf), 0) > 0) - { - client.SetState(ClientStateFinal::Instance()); - retVal = MSG_SOCK_SESSION_DONE; - } - else - throw ClientException(ERR_SOCK_RECV_FAILED, 0); + client.SetState(ClientStateFinal::Instance()); + retVal = MSG_SOCK_SESSION_DONE; } else + { retVal = MSG_SOCK_INTERNAL_PENDING; + Thread::Msleep(CLIENT_WAIT_TIMEOUT_MSEC); + } return retVal; } diff --git a/src/net/common/clientthread.cpp b/src/net/common/clientthread.cpp index 6c3adc4f..bf38c513 100644 --- a/src/net/common/clientthread.cpp +++ b/src/net/common/clientthread.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -58,18 +59,19 @@ ClientThread::Init(const string &serverAddress, unsigned serverPort, bool ipv6, void ClientThread::Main() { - m_sender.reset(new SenderThread); + m_sender.reset(new SenderThread(m_callback)); + m_receiver.reset(new ReceiverHelper); SetState(CLIENT_INITIAL_STATE::Instance()); try { while (!ShouldTerminate()) { int msg = GetState().Process(*this); if (msg != MSG_SOCK_INTERNAL_PENDING) - m_callback.SignalNetClientSuccess(msg); + m_callback.SignalNetSuccess(msg); } - } catch (const ClientException &e) + } catch (const NetException &e) { - m_callback.SignalNetClientError(e.GetErrorId(), e.GetOsErrorCode()); + m_callback.SignalNetError(e.GetErrorId(), e.GetOsErrorCode()); } GetSender().SignalTermination(); GetSender().Join(100); @@ -109,3 +111,10 @@ ClientThread::GetSender() return *m_sender; } +ReceiverHelper & +ClientThread::GetReceiver() +{ + assert(m_receiver.get()); + return *m_receiver; +} + diff --git a/src/net/common/netcallback.cpp b/src/net/common/netcallback.cpp new file mode 100644 index 00000000..b18b9198 --- /dev/null +++ b/src/net/common/netcallback.cpp @@ -0,0 +1,26 @@ +/*************************************************************************** + * 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 + + +NetCallback::~NetCallback() +{ +} + diff --git a/src/net/common/netexception.cpp b/src/net/common/netexception.cpp new file mode 100644 index 00000000..f5d93b3f --- /dev/null +++ b/src/net/common/netexception.cpp @@ -0,0 +1,26 @@ +/*************************************************************************** + * 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 + + +NetException::~NetException() +{ +} + diff --git a/src/net/common/netpacket.cpp b/src/net/common/netpacket.cpp index a6767f48..807d7097 100644 --- a/src/net/common/netpacket.cpp +++ b/src/net/common/netpacket.cpp @@ -18,6 +18,8 @@ ***************************************************************************/ #include +#include +#include NetPacket::~NetPacket() { @@ -25,11 +27,15 @@ NetPacket::~NetPacket() //----------------------------------------------------------------------------- +TestNetPacket::TestNetPacket() +{ +} + TestNetPacket::TestNetPacket(u_int32_t value) { - m_data.head.type = 0; - m_data.head.length = sizeof(m_data); - m_data.test = value; + m_data.head.type = htons(NET_TYPE_TEST); + m_data.head.length = htons(sizeof(m_data)); + m_data.test = htonl(value); } TestNetPacket::~TestNetPacket() @@ -42,3 +48,16 @@ TestNetPacket::GetData() return (NetPacketHeader *)&m_data; } +void +TestNetPacket::SetData(const NetPacketHeader *p) +{ + u_int16_t tmpLen = ntohs(p->length); + if (tmpLen != sizeof(m_data) + || ntohs(p->type) != NET_TYPE_TEST) + { + throw NetException(ERR_SOCK_INTERNAL, 0); + } + + memcpy(&m_data, p, tmpLen); +} + diff --git a/src/net/common/receiverhelper.cpp b/src/net/common/receiverhelper.cpp new file mode 100644 index 00000000..7f929574 --- /dev/null +++ b/src/net/common/receiverhelper.cpp @@ -0,0 +1,142 @@ +/*************************************************************************** + * 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 +#include +#include +#include + +using namespace std; + +#define RECV_TIMEOUT_MSEC 50 + +ReceiverHelper::ReceiverHelper() +: m_socket(INVALID_SOCKET), m_tmpInBufSize(0) +{ +} + +ReceiverHelper::~ReceiverHelper() +{ +} + +void +ReceiverHelper::Init(SOCKET socket) +{ + if (!IS_VALID_SOCKET(socket)) + return; // TODO: throw exception + + m_socket = socket; +} + +boost::shared_ptr +ReceiverHelper::Recv() +{ + boost::shared_ptr tmpPacket(InternalGetPacket()); + + if (!tmpPacket.get()) + { + unsigned bufSize = RECV_BUF_SIZE - m_tmpInBufSize; + + if (bufSize) // check if there is room in the input buffer + { + fd_set readSet; + struct timeval timeout; + + FD_ZERO(&readSet); + FD_SET(m_socket, &readSet); + + timeout.tv_sec = 0; + timeout.tv_usec = RECV_TIMEOUT_MSEC * 1000; + int selectResult = select(m_socket + 1, &readSet, NULL, NULL, &timeout); + if (!IS_VALID_SELECT(selectResult)) + { + throw NetException(ERR_SOCK_SELECT_FAILED, SOCKET_ERRNO()); + } + if (selectResult > 0) // recv is possible + { + int bytesRecvd = recv(m_socket, m_tmpInBuf + m_tmpInBufSize, bufSize, 0); + + if (!IS_VALID_RECV(bytesRecvd)) + { + throw NetException(ERR_SOCK_RECV_FAILED, SOCKET_ERRNO()); + } + else if (bytesRecvd == 0) + { + throw NetException(ERR_SOCK_CONN_RESET, 0); + } + else + { + m_tmpInBufSize += bytesRecvd; + tmpPacket = InternalGetPacket(); + } + } + } + } + return tmpPacket; +} + +boost::shared_ptr +ReceiverHelper::InternalGetPacket() +{ + boost::shared_ptr tmpPacket; + + // This is necessary, because we use TCP. + // Packets may be received in multiple chunks or + // several packets may be received at once. + if (m_tmpInBufSize >= sizeof(NetPacketHeader)) + { + NetPacketHeader *tmpHeader = (NetPacketHeader *)m_tmpInBuf; + u_int16_t tmpLen = ntohs(tmpHeader->length); + + if (tmpLen < sizeof(NetPacketHeader) + || tmpLen > MAX_PACKET_SIZE) + { + // Invalid packet - reset input buffer. + m_tmpInBufSize = 0; + } + else if (m_tmpInBufSize >= tmpLen) + { + tmpPacket = InternalCreateNetPacket(tmpHeader); + m_tmpInBufSize -= tmpLen; + } + } + return tmpPacket; +} + +boost::shared_ptr +ReceiverHelper::InternalCreateNetPacket(const NetPacketHeader *p) +{ + boost::shared_ptr tmpPacket; + + switch(ntohs(p->type)) + { + case NET_TYPE_TEST: + try + { + tmpPacket = boost::shared_ptr(new TestNetPacket); + tmpPacket->SetData(p); + } catch (const NetException &) + { + tmpPacket.reset(); + } + break; + } + return tmpPacket; +} + diff --git a/src/net/common/senderthread.cpp b/src/net/common/senderthread.cpp index 5d70c16a..b3689c33 100644 --- a/src/net/common/senderthread.cpp +++ b/src/net/common/senderthread.cpp @@ -18,11 +18,16 @@ ***************************************************************************/ #include -#include +#include +#include +#include + +using namespace std; #define SEND_TIMEOUT_MSEC 50 -SenderThread::SenderThread() +SenderThread::SenderThread(NetCallback &cb) +: m_tmpOutBufSize(0), m_callback(cb) { } @@ -49,19 +54,33 @@ SenderThread::Send(boost::shared_ptr packet) void SenderThread::Main() { - boost::shared_ptr tmpPacket; while (!ShouldTerminate()) { - if (!tmpPacket.get()) + // Send remaining bytes of output buffer OR + // copy ONE packet to output buffer. + // For reasons of simplicity, only one packet is sent at a time. + if (!m_tmpOutBufSize) { - boost::mutex::scoped_lock lock(m_outBufMutex); - if (!m_outBuf.empty()) + boost::shared_ptr tmpPacket; { - tmpPacket = m_outBuf.front(); - m_outBuf.pop_front(); + boost::mutex::scoped_lock lock(m_outBufMutex); + if (!m_outBuf.empty()) + { + tmpPacket = m_outBuf.front(); + m_outBuf.pop_front(); + } + } + if (tmpPacket.get()) + { + u_int16_t tmpLen = ntohs(tmpPacket->GetData()->length); + if (tmpLen <= MAX_PACKET_SIZE) + { + m_tmpOutBufSize = tmpLen; + memcpy(m_tmpOutBuf, tmpPacket->GetData(), m_tmpOutBufSize); + } } } - if (tmpPacket.get()) + if (m_tmpOutBufSize) { fd_set writeSet; struct timeval timeout; @@ -72,10 +91,32 @@ SenderThread::Main() timeout.tv_sec = 0; timeout.tv_usec = SEND_TIMEOUT_MSEC * 1000; int selectResult = select(m_socket + 1, NULL, &writeSet, NULL, &timeout); + if (!IS_VALID_SELECT(selectResult)) + { + m_callback.SignalNetError(ERR_SOCK_SELECT_FAILED, SOCKET_ERRNO()); + // Assume that this is a fatal error, terminate thread. + return; + } if (selectResult > 0) // send is possible { - send(m_socket, (const char *)tmpPacket->GetData(), tmpPacket->GetData()->length, 0); - tmpPacket.reset(); + // send next chunk of data + int bytesSent = send(m_socket, m_tmpOutBuf, m_tmpOutBufSize, 0); + + if (!IS_VALID_SEND(bytesSent)) + { + m_callback.SignalNetError(ERR_SOCK_SEND_FAILED, SOCKET_ERRNO()); + // Assume that this is a fatal error, terminate thread. + return; + } + else if ((unsigned)bytesSent < m_tmpOutBufSize) + { + m_tmpOutBufSize = m_tmpOutBufSize - (unsigned)bytesSent; + memmove(m_tmpOutBuf, m_tmpOutBuf + bytesSent, m_tmpOutBufSize); + } + else + { + m_tmpOutBufSize = 0; + } } } else diff --git a/src/net/netcallback.h b/src/net/netcallback.h new file mode 100644 index 00000000..588e10fa --- /dev/null +++ b/src/net/netcallback.h @@ -0,0 +1,33 @@ +/*************************************************************************** + * 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. * + ***************************************************************************/ +/* Generic callback interface for network system. */ + +#ifndef _NETCALLBACK_H_ +#define _NETCALLBACK_H_ + +class NetCallback +{ +public: + virtual ~NetCallback(); + + virtual void SignalNetSuccess(int actionID) = 0; + virtual void SignalNetError(int errorID, int osErrorID) = 0; +}; + +#endif diff --git a/src/net/netexception.h b/src/net/netexception.h new file mode 100644 index 00000000..fd69b1c0 --- /dev/null +++ b/src/net/netexception.h @@ -0,0 +1,41 @@ +/*************************************************************************** + * 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. * + ***************************************************************************/ +/* Exception class for network errors. */ + +#ifndef _NETEXCEPTION_H_ +#define _NETEXCEPTION_H_ + + +class NetException +{ +public: + + NetException(int errorId, int osErrorCode) + : m_errorId(errorId), m_osErrorCode(osErrorCode) {} + virtual ~NetException(); + + int GetErrorId() const {return m_errorId;} + int GetOsErrorCode() const {return m_osErrorCode;} + +private: + int m_errorId; + int m_osErrorCode; +}; + +#endif diff --git a/src/net/netpacket.h b/src/net/netpacket.h index 8ec75f88..98c702f2 100644 --- a/src/net/netpacket.h +++ b/src/net/netpacket.h @@ -24,6 +24,10 @@ #include #include +#define MAX_PACKET_SIZE 256 + +#define NET_TYPE_TEST 0 + #ifdef _MSC_VER #pragma pack(push, 2) #else @@ -54,16 +58,19 @@ class NetPacket public: virtual ~NetPacket(); + virtual void SetData(const NetPacketHeader *p) = 0; virtual NetPacketHeader *GetData() = 0; }; class TestNetPacket : public NetPacket { public: + TestNetPacket(); TestNetPacket(u_int32_t value); virtual ~TestNetPacket(); virtual NetPacketHeader *GetData(); + virtual void SetData(const NetPacketHeader *p); protected: NetPacketInit m_data; diff --git a/src/net/receiverhelper.h b/src/net/receiverhelper.h new file mode 100644 index 00000000..4b51f95c --- /dev/null +++ b/src/net/receiverhelper.h @@ -0,0 +1,57 @@ +/*************************************************************************** + * 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. * + ***************************************************************************/ +/* Network receiver helper class. NOTE: By design, this is not a thread. */ + +#ifndef _RECEIVERHELPER_H_ +#define _RECEIVERHELPER_H_ + +#include +#include + +#include +#include + +// MUST be larger than MAX_PACKET_SIZE +#define RECV_BUF_SIZE 10 * MAX_PACKET_SIZE + +class ReceiverHelper +{ +public: + ReceiverHelper(); + virtual ~ReceiverHelper(); + + // Set the socket from which to receive data. + void Init(SOCKET socket); + + boost::shared_ptr Recv(); + +protected: + boost::shared_ptr InternalGetPacket(); + boost::shared_ptr InternalCreateNetPacket(const NetPacketHeader *p); + +private: + + SOCKET m_socket; + + char m_tmpInBuf[RECV_BUF_SIZE]; + unsigned m_tmpInBufSize; +}; + +#endif + diff --git a/src/net/senderthread.h b/src/net/senderthread.h index 01e4e0b8..e2d2f6b6 100644 --- a/src/net/senderthread.h +++ b/src/net/senderthread.h @@ -23,21 +23,20 @@ #include #include +#include #include #include -class ClientData; -class NetPacket; +class NetCallback; class SenderThread : public Thread { public: - SenderThread(); + SenderThread(NetCallback &cb); virtual ~SenderThread(); - // Set the socket from which to receive data. - // TODO: Add error callback. + // Set the socket used to send data. void Init(SOCKET socket); void Send(boost::shared_ptr packet); @@ -53,6 +52,11 @@ private: std::deque > m_outBuf; mutable boost::mutex m_outBufMutex; + + char m_tmpOutBuf[MAX_PACKET_SIZE]; + unsigned m_tmpOutBufSize; + + NetCallback &m_callback; }; #endif diff --git a/src/net/socket_helper.h b/src/net/socket_helper.h index a8d85d8c..3a1b3e2f 100644 --- a/src/net/socket_helper.h +++ b/src/net/socket_helper.h @@ -45,13 +45,15 @@ typedef unsigned char u_char; #define SOCKET_ERRNO() errno #define IOCTLSOCKET ioctl #define SOCKET_ERR_WOULDBLOCK EINPROGRESS + #endif #define IS_VALID_SOCKET(_s) ((_s) != INVALID_SOCKET) #define IS_VALID_CONNECT(_c) ((_c) == 0) +#define IS_VALID_BIND(_b) ((_b) != SOCKET_ERROR) #define IS_VALID_RECV(_r) ((_r) != SOCKET_ERROR) #define IS_VALID_SEND(_s) ((_s) != SOCKET_ERROR) -#define IS_VALID_BIND(_b) ((_b) != SOCKET_ERROR) +#define IS_VALID_SELECT(_s) ((_s) != SOCKET_ERROR) // All char *s are assumed to be UTF-8. diff --git a/src/net/socket_msg.h b/src/net/socket_msg.h index c10fe189..68bf65b4 100644 --- a/src/net/socket_msg.h +++ b/src/net/socket_msg.h @@ -20,15 +20,17 @@ #ifndef _SOCKET_MSG_H_ #define _SOCKET_MSG_H_ -#define ERR_SOCK_SERVERADDR_NOT_SET 1 -#define ERR_SOCK_INVALID_PORT 2 -#define ERR_SOCK_CREATION_FAILED 3 -#define ERR_SOCK_SET_PORT_FAILED 4 -#define ERR_SOCK_RESOLVE_FAILED 5 -#define ERR_SOCK_CONNECT_FAILED 6 -#define ERR_SOCK_SELECT_FAILED 7 -#define ERR_SOCK_RECV_FAILED 8 -#define ERR_SOCK_SEND_FAILED 9 +#define ERR_SOCK_INTERNAL 1 +#define ERR_SOCK_SERVERADDR_NOT_SET 2 +#define ERR_SOCK_INVALID_PORT 3 +#define ERR_SOCK_CREATION_FAILED 4 +#define ERR_SOCK_SET_PORT_FAILED 5 +#define ERR_SOCK_RESOLVE_FAILED 6 +#define ERR_SOCK_CONNECT_FAILED 7 +#define ERR_SOCK_SELECT_FAILED 8 +#define ERR_SOCK_RECV_FAILED 9 +#define ERR_SOCK_SEND_FAILED 10 +#define ERR_SOCK_CONN_RESET 11 // This is an internal message which is not reported. #define MSG_SOCK_INTERNAL_PENDING 0