Started to implement server state engine.

This commit is contained in:
lotodore
2007-03-13 23:27:17 +00:00
parent 6f33202406
commit ca354dce7f
33 changed files with 1130 additions and 193 deletions
-3
View File
@@ -27,9 +27,6 @@ class ClientCallback : public NetCallback
{
public:
virtual ~ClientCallback();
virtual void SignalNetSuccess(int actionID) = 0;
virtual void SignalNetError(int errorID, int osErrorID) = 0;
};
#endif
+71
View File
@@ -0,0 +1,71 @@
/***************************************************************************
* 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. *
***************************************************************************/
/* Context of network client. */
#ifndef _CLIENTCONTEXT_H_
#define _CLIENTCONTEXT_H_
#include <net/netcontext.h>
class ClientContext : public NetContext
{
public:
ClientContext();
virtual ~ClientContext();
virtual SOCKET GetSocket() const;
virtual u_int32_t GetId() const;
void SetSocket(SOCKET sockfd);
int GetAddrFamily() const
{return m_addrFamily;}
void SetAddrFamily(int addrFamily)
{m_addrFamily = addrFamily;}
const std::string &GetServerAddr() const
{return m_serverAddr;}
void SetServerAddr(const std::string &serverAddr)
{m_serverAddr = serverAddr;}
unsigned GetServerPort() const
{return m_serverPort;}
void SetServerPort(unsigned serverPort)
{m_serverPort = serverPort;}
const std::string &GetPassword() const
{return m_password;}
void SetPassword(const std::string &password)
{m_password = password;}
const sockaddr_storage *GetClientSockaddr() const
{return &m_clientSockaddr;}
sockaddr_storage *GetClientSockaddr()
{return &m_clientSockaddr;}
int GetClientSockaddrSize() const
{return m_addrFamily == AF_INET6 ? sizeof(sockaddr_in6) : sizeof(sockaddr_in);}
private:
SOCKET m_sockfd;
int m_addrFamily;
std::string m_serverAddr;
unsigned m_serverPort;
std::string m_password;
sockaddr_storage m_clientSockaddr;
};
#endif
+10 -4
View File
@@ -25,11 +25,12 @@
#include <string>
#include <memory>
class ClientData;
class ClientContext;
class ClientState;
class ClientCallback;
class SenderThread;
class ReceiverHelper;
class ClientSenderCallback;
class ClientThread : public Thread
{
@@ -42,13 +43,15 @@ public:
// (i.e. after starting the thread).
void Init(const std::string &serverAddress, unsigned serverPort, bool ipv6, const std::string &pwd);
ClientCallback &GetCallback();
protected:
// Main function of the thread.
virtual void Main();
const ClientData &GetData() const;
ClientData &GetData();
const ClientContext &GetContext() const;
ClientContext &GetContext();
ClientState &GetState();
void SetState(ClientState &newState);
@@ -56,9 +59,12 @@ protected:
SenderThread &GetSender();
ReceiverHelper &GetReceiver();
ClientSenderCallback &GetSenderCallback();
private:
std::auto_ptr<ClientData> m_data;
std::auto_ptr<ClientContext> m_context;
std::auto_ptr<ClientSenderCallback> m_senderCallback;
ClientState *m_curState;
ClientCallback &m_callback;
std::auto_ptr<SenderThread> m_sender;
+52
View File
@@ -0,0 +1,52 @@
/***************************************************************************
* 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/clientcontext.h>
ClientContext::ClientContext()
: m_sockfd(INVALID_SOCKET), m_addrFamily(AF_INET), m_serverPort(0)
{
bzero(&m_clientSockaddr, sizeof(m_clientSockaddr));
}
ClientContext::~ClientContext()
{
if (m_sockfd != INVALID_SOCKET)
CLOSESOCKET(m_sockfd);
}
SOCKET
ClientContext::GetSocket() const
{
return m_sockfd;
}
u_int32_t
ClientContext::GetId() const
{
// Id is unused for clients.
return 0;
}
void
ClientContext::SetSocket(SOCKET sockfd)
{
m_sockfd = sockfd;
}
+27 -33
View File
@@ -19,7 +19,7 @@
#include <net/clientstate.h>
#include <net/clientthread.h>
#include <net/clientdata.h>
#include <net/clientcontext.h>
#include <net/senderthread.h>
#include <net/receiverhelper.h>
#include <net/netpacket.h>
@@ -28,11 +28,9 @@
#include <net/socket_helper.h>
#include <net/socket_msg.h>
#include <stdexcept>
using namespace std;
#define CLIENT_WAIT_TIMEOUT_MSEC 100
#define CLIENT_WAIT_TIMEOUT_MSEC 50
ClientState::~ClientState()
@@ -59,20 +57,20 @@ ClientStateInit::~ClientStateInit()
int
ClientStateInit::Process(ClientThread &client)
{
ClientData &data = client.GetData();
ClientContext &context = client.GetContext();
if (data.serverAddr.empty())
if (context.GetServerAddr().empty())
throw ClientException(ERR_SOCK_SERVERADDR_NOT_SET, 0);
// if (data.serverPort < 1024)
// if (context.GetServerPort() < 1024)
// throw ClientException(ERR_SOCK_INVALID_PORT, 0);
data.sockfd = socket(data.addrFamily, SOCK_STREAM, 0);
if (!IS_VALID_SOCKET(data.sockfd))
context.SetSocket(socket(context.GetAddrFamily(), SOCK_STREAM, 0));
if (!IS_VALID_SOCKET(context.GetSocket()))
throw ClientException(ERR_SOCK_CREATION_FAILED, SOCKET_ERRNO());
unsigned long mode = 1;
if (IOCTLSOCKET(data.sockfd, FIONBIO, &mode) == SOCKET_ERROR)
if (IOCTLSOCKET(context.GetSocket(), FIONBIO, &mode) == SOCKET_ERROR)
throw ClientException(ERR_SOCK_CREATION_FAILED, SOCKET_ERRNO());
client.SetState(ClientStateStartResolve::Instance());
@@ -102,19 +100,19 @@ ClientStateStartResolve::Process(ClientThread &client)
{
int retVal;
ClientData &data = client.GetData();
ClientContext &context = client.GetContext();
data.clientAddr.ss_family = data.addrFamily;
context.GetClientSockaddr()->ss_family = context.GetAddrFamily();
// Treat the server address as numbers first.
if (socket_string_to_addr(
data.serverAddr.c_str(),
data.addrFamily,
(struct sockaddr *)&data.clientAddr,
data.GetServerAddrSize()))
context.GetServerAddr().c_str(),
context.GetAddrFamily(),
(struct sockaddr *)context.GetClientSockaddr(),
context.GetClientSockaddrSize()))
{
// Success - but we still need to set the port.
if (!socket_set_port(data.serverPort, data.addrFamily, (struct sockaddr *)&data.clientAddr, data.GetServerAddrSize()))
if (!socket_set_port(context.GetServerPort(), context.GetAddrFamily(), (struct sockaddr *)context.GetClientSockaddr(), context.GetClientSockaddrSize()))
throw ClientException(ERR_SOCK_SET_PORT_FAILED, 0);
// No need to resolve - start connecting.
@@ -126,7 +124,7 @@ ClientStateStartResolve::Process(ClientThread &client)
// Start name resolution in a separate thread, since it is blocking
// for up to about 30 seconds.
std::auto_ptr<ResolverThread> resolver(new ResolverThread);
resolver->Init(data);
resolver->Init(context);
resolver->Run();
ClientStateResolving::Instance().SetResolver(resolver.release());
@@ -175,8 +173,8 @@ ClientStateResolving::Process(ClientThread &client)
if (m_resolver->Join(CLIENT_WAIT_TIMEOUT_MSEC))
{
ClientData &data = client.GetData();
bool success = m_resolver->GetResult(data);
ClientContext &context = client.GetContext();
bool success = m_resolver->GetResult(context);
Cleanup(); // Not required, but better keep things clean.
if (!success)
@@ -226,9 +224,9 @@ int
ClientStateStartConnect::Process(ClientThread &client)
{
int retVal;
ClientData &data = client.GetData();
ClientContext &context = client.GetContext();
int connectResult = connect(data.sockfd, (struct sockaddr *)&data.clientAddr, data.GetServerAddrSize());
int connectResult = connect(context.GetSocket(), (struct sockaddr *)context.GetClientSockaddr(), context.GetClientSockaddrSize());
if (IS_VALID_CONNECT(connectResult))
{
@@ -271,24 +269,24 @@ int
ClientStateConnecting::Process(ClientThread &client)
{
int retVal;
ClientData &data = client.GetData();
ClientContext &context = client.GetContext();
fd_set writeSet;
struct timeval timeout;
FD_ZERO(&writeSet);
FD_SET(data.sockfd, &writeSet);
FD_SET(context.GetSocket(), &writeSet);
timeout.tv_sec = 0;
timeout.tv_usec = CLIENT_WAIT_TIMEOUT_MSEC * 1000;
int selectResult = select(data.sockfd + 1, NULL, &writeSet, NULL, &timeout);
int selectResult = select(context.GetSocket() + 1, NULL, &writeSet, NULL, &timeout);
if (selectResult > 0) // success
{
// Check whether the connect call succeeded.
int connectResult = 0;
socklen_t tmpSize = sizeof(connectResult);
getsockopt(data.sockfd, SOL_SOCKET, SO_ERROR, (char *)&connectResult, &tmpSize);
getsockopt(context.GetSocket(), SOL_SOCKET, SO_ERROR, (char *)&connectResult, &tmpSize);
if (connectResult != 0)
throw ClientException(ERR_SOCK_CONNECT_FAILED, connectResult);
client.SetState(ClientStateStartSession::Instance());
@@ -323,12 +321,8 @@ ClientStateStartSession::~ClientStateStartSession()
int
ClientStateStartSession::Process(ClientThread &client)
{
client.GetReceiver().Init(client.GetData().sockfd);
client.GetSender().Init(client.GetData().sockfd);
client.GetSender().Run();
boost::shared_ptr<NetPacket> packet(new TestNetPacket(10));
client.GetSender().Send(packet);
client.GetSender().Send(packet, client.GetContext().GetSocket());
client.SetState(ClientStateWaitSession::Instance());
@@ -356,11 +350,11 @@ int
ClientStateWaitSession::Process(ClientThread &client)
{
int retVal;
ClientData &data = client.GetData();
ClientContext &context = client.GetContext();
// delegate to receiver helper class
boost::shared_ptr<NetPacket> tmpPacket = client.GetReceiver().Recv();
boost::shared_ptr<NetPacket> tmpPacket = client.GetReceiver().Recv(context.GetSocket());
if (tmpPacket.get())
{
+58 -21
View File
@@ -19,7 +19,7 @@
#include <net/clientthread.h>
#include <net/clientstate.h>
#include <net/clientdata.h>
#include <net/clientcontext.h>
#include <net/senderthread.h>
#include <net/receiverhelper.h>
#include <net/clientcallback.h>
@@ -32,10 +32,30 @@
using namespace std;
class ClientSenderCallback : public SenderCallback
{
public:
ClientSenderCallback(ClientThread &client) : m_client(client) {}
virtual ~ClientSenderCallback() {}
virtual void SignalNetError(SOCKET sock, int errorID, int osErrorID)
{
// For now, we ignore the socket.
// Just signal the error.
// We assume that the client thread will be terminated.
m_client.GetCallback().SignalNetError(errorID, osErrorID);
}
private:
ClientThread &m_client;
};
ClientThread::ClientThread(ClientCallback &cb)
: m_curState(NULL), m_callback(cb)
{
m_data.reset(new ClientData);
m_context.reset(new ClientContext);
m_senderCallback.reset(new ClientSenderCallback(*this));
}
ClientThread::~ClientThread()
@@ -48,47 +68,57 @@ ClientThread::Init(const string &serverAddress, unsigned serverPort, bool ipv6,
if (IsRunning())
return; // TODO: throw exception
ClientData &data = GetData();
ClientContext &context = GetContext();
data.addrFamily = ipv6 ? AF_INET6 : AF_INET;
data.serverAddr = serverAddress;
data.serverPort = serverPort;
data.password = pwd;
context.SetAddrFamily(ipv6 ? AF_INET6 : AF_INET);
context.SetServerAddr(serverAddress);
context.SetServerPort(serverPort);
context.SetPassword(pwd);
}
ClientCallback &
ClientThread::GetCallback()
{
return m_callback;
}
void
ClientThread::Main()
{
m_sender.reset(new SenderThread(m_callback));
m_receiver.reset(new ReceiverHelper);
SetState(CLIENT_INITIAL_STATE::Instance());
try {
m_sender.reset(new SenderThread(GetSenderCallback()));
m_receiver.reset(new ReceiverHelper);
GetSender().Run();
try
{
while (!ShouldTerminate())
{
int msg = GetState().Process(*this);
if (msg != MSG_SOCK_INTERNAL_PENDING)
m_callback.SignalNetSuccess(msg);
GetCallback().SignalNetSuccess(msg);
}
} catch (const NetException &e)
{
m_callback.SignalNetError(e.GetErrorId(), e.GetOsErrorCode());
GetCallback().SignalNetError(e.GetErrorId(), e.GetOsErrorCode());
}
GetSender().SignalTermination();
GetSender().Join(100);
GetSender().Join(SENDER_THREAD_TERMINATE_TIMEOUT);
}
const ClientData &
ClientThread::GetData() const
const ClientContext &
ClientThread::GetContext() const
{
assert(m_data.get());
return *m_data;
assert(m_context.get());
return *m_context;
}
ClientData &
ClientThread::GetData()
ClientContext &
ClientThread::GetContext()
{
assert(m_data.get());
return *m_data;
assert(m_context.get());
return *m_context;
}
ClientState &
@@ -118,3 +148,10 @@ ClientThread::GetReceiver()
return *m_receiver;
}
ClientSenderCallback &
ClientThread::GetSenderCallback()
{
assert(m_senderCallback.get());
return *m_senderCallback;
}
@@ -17,17 +17,17 @@
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <net/clientdata.h>
#include <net/connectdata.h>
ClientData::ClientData()
: sockfd(INVALID_SOCKET), addrFamily(AF_INET), serverPort(0)
ConnectData::ConnectData()
: m_sockfd(INVALID_SOCKET)
{
bzero(&clientAddr, sizeof(clientAddr));
bzero(&m_sockaddr, sizeof(m_sockaddr));
}
ClientData::~ClientData()
ConnectData::~ConnectData()
{
if (sockfd != INVALID_SOCKET)
CLOSESOCKET(sockfd);
if (m_sockfd != INVALID_SOCKET)
CLOSESOCKET(m_sockfd);
}
+25
View File
@@ -0,0 +1,25 @@
/***************************************************************************
* 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/netcontext.h>
NetContext::~NetContext()
{
}
+4 -4
View File
@@ -45,7 +45,7 @@ ReceiverHelper::Init(SOCKET socket)
}
boost::shared_ptr<NetPacket>
ReceiverHelper::Recv()
ReceiverHelper::Recv(SOCKET sock)
{
boost::shared_ptr<NetPacket> tmpPacket(InternalGetPacket());
@@ -59,18 +59,18 @@ ReceiverHelper::Recv()
struct timeval timeout;
FD_ZERO(&readSet);
FD_SET(m_socket, &readSet);
FD_SET(sock, &readSet);
timeout.tv_sec = 0;
timeout.tv_usec = RECV_TIMEOUT_MSEC * 1000;
int selectResult = select(m_socket + 1, &readSet, NULL, NULL, &timeout);
int selectResult = select(sock + 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);
int bytesRecvd = recv(sock, m_tmpInBuf + m_tmpInBufSize, bufSize, 0);
if (!IS_VALID_RECV(bytesRecvd))
{
+22 -22
View File
@@ -18,7 +18,7 @@
***************************************************************************/
#include <net/resolverthread.h>
#include <net/clientdata.h>
#include <net/clientcontext.h>
#include <net/clientexception.h>
#include <sstream>
@@ -30,7 +30,7 @@ using namespace std;
ResolverThread::ResolverThread()
: m_retVal(false)
{
m_data.reset(new ClientData);
m_context.reset(new ClientContext);
}
ResolverThread::~ResolverThread()
@@ -38,24 +38,24 @@ ResolverThread::~ResolverThread()
}
void
ResolverThread::Init(const ClientData &data)
ResolverThread::Init(const ClientContext &context)
{
if (IsRunning())
return; // TODO: throw exception
m_data->addrFamily = data.addrFamily;
m_data->serverAddr = data.serverAddr;
m_data->serverPort = data.serverPort;
GetContext().SetAddrFamily(context.GetAddrFamily());
GetContext().SetServerAddr(context.GetServerAddr());
GetContext().SetServerPort(context.GetServerPort());
}
bool
ResolverThread::GetResult(ClientData &data)
ResolverThread::GetResult(ClientContext &context) const
{
if (IsRunning())
return false; // TODO: throw exception
if (m_retVal)
memcpy(&data.clientAddr, &GetData().clientAddr, GetData().GetServerAddrSize());
memcpy(context.GetClientSockaddr(), GetContext().GetClientSockaddr(), GetContext().GetClientSockaddrSize());
return m_retVal;
}
@@ -63,34 +63,34 @@ ResolverThread::GetResult(ClientData &data)
void
ResolverThread::Main()
{
const ClientData &data = GetData();
const ClientContext &context = GetContext();
// Convert the port to a string.
ostringstream tmpStr;
tmpStr << data.serverPort;
tmpStr << context.GetServerPort();
// Start the name resolution.
m_retVal = socket_resolve(
data.serverAddr.c_str(),
context.GetServerAddr().c_str(),
tmpStr.str().c_str(),
data.addrFamily,
context.GetAddrFamily(),
SOCK_STREAM,
0,
(struct sockaddr *)&data.clientAddr,
data.GetServerAddrSize());
(struct sockaddr *)context.GetClientSockaddr(),
context.GetClientSockaddrSize());
}
const ClientData &
ResolverThread::GetData() const
const ClientContext &
ResolverThread::GetContext() const
{
assert(m_data.get());
return *m_data;
assert(m_context.get());
return *m_context;
}
ClientData &
ResolverThread::GetData()
ClientContext &
ResolverThread::GetContext()
{
assert(m_data.get());
return *m_data;
assert(m_context.get());
return *m_context;
}
+26
View File
@@ -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 <net/sendercallback.h>
SenderCallback::~SenderCallback()
{
}
+23 -25
View File
@@ -18,7 +18,7 @@
***************************************************************************/
#include <net/senderthread.h>
#include <net/netcallback.h>
#include <net/sendercallback.h>
#include <net/socket_msg.h>
#include <cstring>
@@ -26,8 +26,8 @@ using namespace std;
#define SEND_TIMEOUT_MSEC 50
SenderThread::SenderThread(NetCallback &cb)
: m_tmpOutBufSize(0), m_callback(cb)
SenderThread::SenderThread(SenderCallback &cb)
: m_curSocket(INVALID_SOCKET), m_tmpOutBufSize(0), m_callback(cb)
{
}
@@ -36,19 +36,13 @@ SenderThread::~SenderThread()
}
void
SenderThread::Init(SOCKET socket)
SenderThread::Send(boost::shared_ptr<NetPacket> packet, SOCKET sock)
{
if (!IS_VALID_SOCKET(socket) || IsRunning())
return; // TODO: throw exception
m_socket = socket;
}
void
SenderThread::Send(boost::shared_ptr<NetPacket> packet)
{
boost::mutex::scoped_lock lock(m_outBufMutex);
m_outBuf.push_back(packet);
if (packet.get() && IS_VALID_SOCKET(sock))
{
boost::mutex::scoped_lock lock(m_outBufMutex);
m_outBuf.push_back(std::make_pair(packet, sock));
}
}
void
@@ -61,22 +55,26 @@ SenderThread::Main()
// For reasons of simplicity, only one packet is sent at a time.
if (!m_tmpOutBufSize)
{
boost::shared_ptr<NetPacket> tmpPacket;
SendData tmpData;
{
boost::mutex::scoped_lock lock(m_outBufMutex);
if (!m_outBuf.empty())
{
tmpPacket = m_outBuf.front();
tmpData = m_outBuf.front();
m_outBuf.pop_front();
}
}
if (tmpPacket.get())
if (tmpData.first.get())
{
u_int16_t tmpLen = ntohs(tmpPacket->GetData()->length);
if (IS_VALID_SOCKET(tmpData.second))
m_curSocket = tmpData.second;
u_int16_t tmpLen = ntohs(tmpData.first->GetData()->length);
if (tmpLen <= MAX_PACKET_SIZE)
{
m_tmpOutBufSize = tmpLen;
memcpy(m_tmpOutBuf, tmpPacket->GetData(), m_tmpOutBufSize);
memcpy(m_tmpOutBuf, tmpData.first->GetData(), m_tmpOutBufSize);
}
}
}
@@ -86,25 +84,25 @@ SenderThread::Main()
struct timeval timeout;
FD_ZERO(&writeSet);
FD_SET(m_socket, &writeSet);
FD_SET(m_curSocket, &writeSet);
timeout.tv_sec = 0;
timeout.tv_usec = SEND_TIMEOUT_MSEC * 1000;
int selectResult = select(m_socket + 1, NULL, &writeSet, NULL, &timeout);
int selectResult = select(m_curSocket + 1, NULL, &writeSet, NULL, &timeout);
if (!IS_VALID_SELECT(selectResult))
{
m_callback.SignalNetError(ERR_SOCK_SELECT_FAILED, SOCKET_ERRNO());
m_callback.SignalNetError(m_curSocket, ERR_SOCK_SELECT_FAILED, SOCKET_ERRNO());
// Assume that this is a fatal error, terminate thread.
return;
}
if (selectResult > 0) // send is possible
{
// send next chunk of data
int bytesSent = send(m_socket, m_tmpOutBuf, m_tmpOutBufSize, 0);
int bytesSent = send(m_curSocket, m_tmpOutBuf, m_tmpOutBufSize, 0);
if (!IS_VALID_SEND(bytesSent))
{
m_callback.SignalNetError(ERR_SOCK_SEND_FAILED, SOCKET_ERRNO());
m_callback.SignalNetError(m_curSocket, ERR_SOCK_SEND_FAILED, SOCKET_ERRNO());
// Assume that this is a fatal error, terminate thread.
return;
}
+52
View File
@@ -0,0 +1,52 @@
/***************************************************************************
* 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/servercontext.h>
ServerContext::ServerContext()
: m_sockfd(INVALID_SOCKET), m_addrFamily(AF_INET), m_serverPort(0)
{
bzero(&m_serverSockaddr, sizeof(m_serverSockaddr));
}
ServerContext::~ServerContext()
{
if (m_sockfd != INVALID_SOCKET)
CLOSESOCKET(m_sockfd);
}
SOCKET
ServerContext::GetSocket() const
{
return m_sockfd;
}
u_int32_t
ServerContext::GetId() const
{
// Id is unused for main server thread.
return 0;
}
void
ServerContext::SetSocket(SOCKET sockfd)
{
m_sockfd = sockfd;
}
+26
View File
@@ -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 <net/serverexception.h>
ServerException::~ServerException()
{
}
+63
View File
@@ -0,0 +1,63 @@
/***************************************************************************
* 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/serverrecvstate.h>
#include <net/serverrecvthread.h>
#include <net/socket_msg.h>
using namespace std;
#define SERVER_WAIT_TIMEOUT_MSEC 50
ServerRecvState::~ServerRecvState()
{
}
//-----------------------------------------------------------------------------
ServerRecvStateInit &
ServerRecvStateInit::Instance()
{
static ServerRecvStateInit state;
return state;
}
ServerRecvStateInit::ServerRecvStateInit()
{
}
ServerRecvStateInit::~ServerRecvStateInit()
{
}
void
ServerRecvStateInit::HandleNewConnection(ServerRecvThread &server, boost::shared_ptr<ConnectData> data)
{
}
int
ServerRecvStateInit::Process(ServerRecvThread &server)
{
Thread::Msleep(SERVER_WAIT_TIMEOUT_MSEC);
return MSG_SOCK_INIT_DONE;
}
//-----------------------------------------------------------------------------
+129
View File
@@ -0,0 +1,129 @@
/***************************************************************************
* 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/serverrecvthread.h>
#include <net/serverexception.h>
#include <net/serverrecvstate.h>
#include <net/senderthread.h>
#include <net/sendercallback.h>
#include <net/receiverhelper.h>
#include <net/socket_msg.h>
class ServerSenderCallback : public SenderCallback
{
public:
ServerSenderCallback(ServerRecvThread &server) : m_server(server) {}
virtual ~ServerSenderCallback() {}
virtual void SignalNetError(SOCKET sock, int errorID, int osErrorID)
{
// TODO
}
private:
ServerRecvThread &m_server;
};
ServerRecvThread::ServerRecvThread()
{
m_senderCallback.reset(new ServerSenderCallback(*this));
}
ServerRecvThread::~ServerRecvThread()
{
}
void
ServerRecvThread::AddConnection(boost::shared_ptr<ConnectData> data)
{
boost::mutex::scoped_lock lock(m_connectQueueMutex);
m_connectQueue.push_back(data);
}
void
ServerRecvThread::Main()
{
SetState(SERVER_INITIAL_STATE::Instance());
m_sender.reset(new SenderThread(GetSenderCallback()));
m_receiver.reset(new ReceiverHelper);
GetSender().Run();
try
{
while (!ShouldTerminate())
{
{
boost::shared_ptr<ConnectData> tmpData;
{
boost::mutex::scoped_lock lock(m_connectQueueMutex);
if (!m_connectQueue.empty())
{
tmpData = m_connectQueue.front();
m_connectQueue.pop_front();
}
}
if (tmpData.get())
GetState().HandleNewConnection(*this, tmpData);
}
GetState().Process(*this);
}
} catch (const NetException &)
{
// TODO
}
GetSender().SignalTermination();
GetSender().Join(SENDER_THREAD_TERMINATE_TIMEOUT);
}
ServerRecvState &
ServerRecvThread::GetState()
{
assert(m_curState);
return *m_curState;
}
void
ServerRecvThread::SetState(ServerRecvState &newState)
{
m_curState = &newState;
}
SenderThread &
ServerRecvThread::GetSender()
{
assert(m_sender.get());
return *m_sender;
}
ReceiverHelper &
ServerRecvThread::GetReceiver()
{
assert(m_receiver.get());
return *m_receiver;
}
ServerSenderCallback &
ServerRecvThread::GetSenderCallback()
{
assert(m_senderCallback.get());
return *m_senderCallback;
}
+131 -28
View File
@@ -18,11 +18,20 @@
***************************************************************************/
#include <net/serverthread.h>
#include <net/servercontext.h>
#include <net/connectdata.h>
#include <net/serverrecvthread.h>
#include <net/socket_helper.h>
#include <net/serverexception.h>
#include <net/socket_msg.h>
#define ACCEPT_TIMEOUT_MSEC 50
#define NET_SERVER_LISTEN_BACKLOG 5
ServerThread::ServerThread()
{
m_context.reset(new ServerContext);
}
ServerThread::~ServerThread()
@@ -30,44 +39,138 @@ ServerThread::~ServerThread()
}
void
ServerThread::Init()
ServerThread::Init(unsigned serverPort, bool ipv6, const std::string &pwd)
{
if (IsRunning())
return; // TODO: throw exception
ServerContext &context = GetContext();
context.SetAddrFamily(ipv6 ? AF_INET6 : AF_INET);
context.SetServerPort(serverPort);
context.SetPassword(pwd);
}
void
ServerThread::Main()
{
while (!ShouldTerminate())
m_recvThread.reset(new ServerRecvThread);
try
{
// Simple hacked server for testing.
SOCKET sockfd;
char buf[1024];
struct sockaddr_storage servaddr, clientaddr;
int sockaddr_size = sizeof(struct sockaddr_in);
int addrFamily = AF_INET;
socklen_t addrSize;
Listen();
GetRecvThread().Run();
sockfd = socket(addrFamily, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.ss_family = addrFamily;
socket_string_to_addr("0.0.0.0", addrFamily, (struct sockaddr *)&servaddr, sockaddr_size);
socket_set_port(7234, addrFamily, (struct sockaddr *)&servaddr, sockaddr_size);
bind(sockfd, (const struct sockaddr *)&servaddr, sockaddr_size);
listen(sockfd, 1);
bzero(&clientaddr, sizeof(clientaddr));
addrSize = sockaddr_size;
SOCKET conn = accept(sockfd, (struct sockaddr *)&clientaddr, &addrSize);
CLOSESOCKET(sockfd);
int ret = recv(conn, buf, sizeof(buf), 0);
send(conn, buf, ret, 0);
CLOSESOCKET(conn);
while (!ShouldTerminate())
{
// The main server thread is simple. It only accepts connections.
AcceptLoop();
}
} catch (const NetException &)
{
// TODO: callback.
}
}
void
ServerThread::Listen()
{
ServerContext &context = GetContext();
// if (context.GetServerPort() < 1024)
// throw ServerException(ERR_SOCK_INVALID_PORT, 0);
context.SetSocket(socket(context.GetAddrFamily(), SOCK_STREAM, 0));
if (!IS_VALID_SOCKET(context.GetSocket()))
throw ServerException(ERR_SOCK_CREATION_FAILED, SOCKET_ERRNO());
unsigned long mode = 1;
if (IOCTLSOCKET(context.GetSocket(), FIONBIO, &mode) == SOCKET_ERROR)
throw ServerException(ERR_SOCK_CREATION_FAILED, SOCKET_ERRNO());
context.GetServerSockaddr()->ss_family = context.GetAddrFamily();
if (!socket_string_to_addr(
"0.0.0.0",
context.GetAddrFamily(),
(struct sockaddr *)context.GetServerSockaddr(),
context.GetServerSockaddrSize()))
{
throw ServerException(ERR_SOCK_SET_ADDR_FAILED, 0);
}
if (!socket_set_port(
context.GetServerPort(),
context.GetAddrFamily(),
(struct sockaddr *)context.GetServerSockaddr(),
context.GetServerSockaddrSize()))
{
throw ServerException(ERR_SOCK_SET_PORT_FAILED, 0);
}
if (!IS_VALID_BIND(bind(
context.GetSocket(),
(const struct sockaddr *)context.GetServerSockaddr(),
context.GetServerSockaddrSize())))
{
throw ServerException(ERR_SOCK_BIND_FAILED, SOCKET_ERRNO());
}
if (!IS_VALID_LISTEN(listen(context.GetSocket(), NET_SERVER_LISTEN_BACKLOG)))
{
throw ServerException(ERR_SOCK_LISTEN_FAILED, SOCKET_ERRNO());
}
}
void
ServerThread::AcceptLoop()
{
ServerContext &context = GetContext();
fd_set readSet;
struct timeval timeout;
FD_ZERO(&readSet);
FD_SET(context.GetSocket(), &readSet);
timeout.tv_sec = 0;
timeout.tv_usec = ACCEPT_TIMEOUT_MSEC * 1000;
int selectResult = select(context.GetSocket() + 1, &readSet, NULL, NULL, &timeout);
if (!IS_VALID_SELECT(selectResult))
{
throw ServerException(ERR_SOCK_SELECT_FAILED, SOCKET_ERRNO());
}
if (selectResult > 0) // accept is possible
{
boost::shared_ptr<ConnectData> tmpData(new ConnectData);
socklen_t addrSize = sizeof(*tmpData->GetSockaddr());
tmpData->SetSocket(accept(context.GetSocket(), (struct sockaddr *)tmpData->GetSockaddr(), &addrSize));
if (!IS_VALID_SOCKET(tmpData->GetSocket()))
{
throw ServerException(ERR_SOCK_ACCEPT_FAILED, SOCKET_ERRNO());
}
GetRecvThread().AddConnection(tmpData);
}
}
const ServerContext &
ServerThread::GetContext() const
{
assert(m_context.get());
return *m_context;
}
ServerContext &
ServerThread::GetContext()
{
assert(m_context.get());
return *m_context;
}
ServerRecvThread &
ServerThread::GetRecvThread()
{
assert(m_recvThread.get());
return *m_recvThread;
}
+46
View File
@@ -0,0 +1,46 @@
/***************************************************************************
* 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. *
***************************************************************************/
/* Connection data. */
#ifndef _CONNECTDATA_H_
#define _CONNECTDATA_H_
#include <net/socket_helper.h>
class ConnectData
{
public:
ConnectData();
~ConnectData();
SOCKET GetSocket() const
{return m_sockfd;}
void SetSocket(SOCKET sockfd)
{m_sockfd = sockfd;}
const sockaddr_storage *GetSockaddr() const
{return &m_sockaddr;}
sockaddr_storage *GetSockaddr()
{return &m_sockaddr;}
private:
SOCKET m_sockfd;
sockaddr_storage m_sockaddr;
};
#endif
+8 -17
View File
@@ -16,31 +16,22 @@
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
/* State of network client. */
/* Network context data. */
#ifndef _CLIENTDATA_H_
#define _CLIENTDATA_H_
#ifndef _NETCONTEXT_H_
#define _NETCONTEXT_H_
#include <string>
#include <net/socket_helper.h>
#include <string>
class ClientData
class NetContext
{
public:
ClientData();
~ClientData();
int GetServerAddrSize() const
{
return addrFamily == AF_INET6 ? sizeof(sockaddr_in6) : sizeof(sockaddr_in);
}
virtual ~NetContext();
SOCKET sockfd;
int addrFamily;
std::string serverAddr;
unsigned serverPort;
std::string password;
sockaddr_storage clientAddr;
virtual SOCKET GetSocket() const = 0;
virtual u_int32_t GetId() const = 0;
};
#endif
+2 -1
View File
@@ -30,6 +30,7 @@
// MUST be larger than MAX_PACKET_SIZE
#define RECV_BUF_SIZE 10 * MAX_PACKET_SIZE
class ReceiverHelper
{
public:
@@ -39,7 +40,7 @@ public:
// Set the socket from which to receive data.
void Init(SOCKET socket);
boost::shared_ptr<NetPacket> Recv();
boost::shared_ptr<NetPacket> Recv(SOCKET sock);
protected:
boost::shared_ptr<NetPacket> InternalGetPacket();
+6 -6
View File
@@ -25,7 +25,7 @@
#include <string>
#include <memory>
class ClientData;
class ClientContext;
class ResolverThread : public Thread
{
@@ -36,24 +36,24 @@ public:
// Set the parameters. Does not do any error checking.
// To prevent access faults if this thread cannot be
// terminated, the data is not modified.
void Init(const ClientData &data);
void Init(const ClientContext &context);
// Retrieve the result of the name resolution.
// ONLY CALL THIS FUNCTION AFTER THE THREAD TERMINATED.
// You have been warned...
bool GetResult(ClientData &data);
bool GetResult(ClientContext &context) const;
protected:
// Main function of the thread.
virtual void Main();
const ClientData &GetData() const;
ClientData &GetData();
const ClientContext &GetContext() const;
ClientContext &GetContext();
private:
std::auto_ptr<ClientData> m_data;
std::auto_ptr<ClientContext> m_context;
bool m_retVal;
};
+34
View File
@@ -0,0 +1,34 @@
/***************************************************************************
* 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. *
***************************************************************************/
/* Callback interface for the sender thread. */
#ifndef _SENDERCALLBACK_H_
#define _SENDERCALLBACK_H_
#include <net/socket_helper.h>
class SenderCallback
{
public:
virtual ~SenderCallback();
virtual void SignalNetError(SOCKET sock, int errorID, int osErrorID) = 0;
};
#endif
+8 -9
View File
@@ -24,22 +24,20 @@
#include <core/thread.h>
#include <net/socket_helper.h>
#include <net/netpacket.h>
#include <net/sendercallback.h>
#include <deque>
#include <boost/shared_ptr.hpp>
class NetCallback;
#define SENDER_THREAD_TERMINATE_TIMEOUT 100
class SenderThread : public Thread
{
public:
SenderThread(NetCallback &cb);
SenderThread(SenderCallback &cb);
virtual ~SenderThread();
// Set the socket used to send data.
void Init(SOCKET socket);
void Send(boost::shared_ptr<NetPacket> packet);
void Send(boost::shared_ptr<NetPacket> packet, SOCKET sock);
protected:
@@ -48,15 +46,16 @@ protected:
private:
SOCKET m_socket;
SOCKET m_curSocket;
std::deque<boost::shared_ptr<NetPacket> > m_outBuf;
typedef std::pair<boost::shared_ptr<NetPacket>, SOCKET> SendData;
std::deque<SendData> m_outBuf;
mutable boost::mutex m_outBufMutex;
char m_tmpOutBuf[MAX_PACKET_SIZE];
unsigned m_tmpOutBufSize;
NetCallback &m_callback;
SenderCallback &m_callback;
};
#endif
+66
View File
@@ -0,0 +1,66 @@
/***************************************************************************
* 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. *
***************************************************************************/
/* Context of network server. */
#ifndef _SERVERCONTEXT_H_
#define _SERVERCONTEXT_H_
#include <net/netcontext.h>
class ServerContext : public NetContext
{
public:
ServerContext();
virtual ~ServerContext();
virtual SOCKET GetSocket() const;
virtual u_int32_t GetId() const;
void SetSocket(SOCKET sockfd);
int GetAddrFamily() const
{return m_addrFamily;}
void SetAddrFamily(int addrFamily)
{m_addrFamily = addrFamily;}
unsigned GetServerPort() const
{return m_serverPort;}
void SetServerPort(unsigned serverPort)
{m_serverPort = serverPort;}
const std::string &GetPassword() const
{return m_password;}
void SetPassword(const std::string &password)
{m_password = password;}
const sockaddr_storage *GetServerSockaddr() const
{return &m_serverSockaddr;}
sockaddr_storage *GetServerSockaddr()
{return &m_serverSockaddr;}
int GetServerSockaddrSize() const
{return m_addrFamily == AF_INET6 ? sizeof(sockaddr_in6) : sizeof(sockaddr_in);}
private:
SOCKET m_sockfd;
int m_addrFamily;
unsigned m_serverPort;
std::string m_password;
sockaddr_storage m_serverSockaddr;
};
#endif
+36
View File
@@ -0,0 +1,36 @@
/***************************************************************************
* 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 server errors. */
#ifndef _SERVEREXCEPTION_H_
#define _SERVEREXCEPTION_H_
#include <net/netexception.h>
class ServerException : public NetException
{
public:
ServerException(int errorId, int osErrorCode)
: NetException(errorId, osErrorCode) {}
virtual ~ServerException();
};
#endif
+65
View File
@@ -0,0 +1,65 @@
/***************************************************************************
* 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. *
***************************************************************************/
/* State of network server. */
#ifndef _SERVERRECVSTATE_H_
#define _SERVERRECVSTATE_H_
#include <boost/shared_ptr.hpp>
#include <net/connectdata.h>
#define SERVER_INITIAL_STATE ServerRecvStateInit
class ServerRecvThread;
class ServerCallback;
class ServerRecvState
{
public:
virtual ~ServerRecvState();
// Handling of a new TCP connection.
virtual void HandleNewConnection(ServerRecvThread &server, boost::shared_ptr<ConnectData> data) = 0;
// Main processing function of the current state.
virtual int Process(ServerRecvThread &server) = 0;
};
// State: Initialization.
class ServerRecvStateInit : public ServerRecvState
{
public:
// Access the state singleton.
static ServerRecvStateInit &Instance();
virtual ~ServerRecvStateInit();
//
virtual void HandleNewConnection(ServerRecvThread &server, boost::shared_ptr<ConnectData> data);
//
virtual int Process(ServerRecvThread &server);
protected:
// Protected constructor - this is a singleton.
ServerRecvStateInit();
};
#endif
+72
View File
@@ -0,0 +1,72 @@
/***************************************************************************
* 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 server receive thread. */
#ifndef _SERVERRECVTHREAD_H_
#define _SERVERRECVTHREAD_H_
#include <core/thread.h>
#include <deque>
#include <boost/shared_ptr.hpp>
#include <net/connectdata.h>
class ServerRecvState;
class SenderThread;
class ReceiverHelper;
class ServerSenderCallback;
class ServerRecvThread : public Thread
{
public:
ServerRecvThread();
virtual ~ServerRecvThread();
void AddConnection(boost::shared_ptr<ConnectData> data);
protected:
// Main function of the thread.
virtual void Main();
ServerRecvState &GetState();
void SetState(ServerRecvState &newState);
//const ServerRecvContext &GetContext() const;
//ServerRecvContext &GetContext();
SenderThread &GetSender();
ReceiverHelper &GetReceiver();
ServerSenderCallback &GetSenderCallback();
private:
//std::auto_ptr<ServerRecvContext> m_context;
std::deque<boost::shared_ptr<ConnectData> > m_connectQueue;
mutable boost::mutex m_connectQueueMutex;
ServerRecvState *m_curState;
std::auto_ptr<ReceiverHelper> m_receiver;
std::auto_ptr<SenderThread> m_sender;
std::auto_ptr<ServerSenderCallback> m_senderCallback;
};
#endif
+16 -3
View File
@@ -25,6 +25,10 @@
#include <string>
#include <memory>
class ServerContext;
class ServerRecvThread;
class ServerSenderCallback;
class SenderThread;
class ServerThread : public Thread
{
@@ -32,16 +36,25 @@ public:
ServerThread(/*ServerCallback &gui*/);
virtual ~ServerThread();
// Set the parameters. TODO
void Init();
// Set the parameters.
void Init(unsigned serverPort, bool ipv6, const std::string &pwd);
protected:
// Main function of the thread.
virtual void Main();
private:
void Listen();
void AcceptLoop();
const ServerContext &GetContext() const;
ServerContext &GetContext();
ServerRecvThread &GetRecvThread();
private:
std::auto_ptr<ServerContext> m_context;
std::auto_ptr<ServerRecvThread> m_recvThread;
};
#endif
+1
View File
@@ -51,6 +51,7 @@ typedef unsigned char u_char;
#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_LISTEN(_l) ((_l) != SOCKET_ERROR)
#define IS_VALID_RECV(_r) ((_r) != SOCKET_ERROR)
#define IS_VALID_SEND(_s) ((_s) != SOCKET_ERROR)
#define IS_VALID_SELECT(_s) ((_s) != SOCKET_ERROR)
+11 -7
View File
@@ -24,13 +24,17 @@
#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
#define ERR_SOCK_SET_ADDR_FAILED 5
#define ERR_SOCK_SET_PORT_FAILED 6
#define ERR_SOCK_RESOLVE_FAILED 7
#define ERR_SOCK_BIND_FAILED 8
#define ERR_SOCK_LISTEN_FAILED 9
#define ERR_SOCK_ACCEPT_FAILED 10
#define ERR_SOCK_CONNECT_FAILED 11
#define ERR_SOCK_SELECT_FAILED 12
#define ERR_SOCK_RECV_FAILED 13
#define ERR_SOCK_SEND_FAILED 14
#define ERR_SOCK_CONN_RESET 15
// This is an internal message which is not reported.
#define MSG_SOCK_INTERNAL_PENDING 0