[asycxx-devel] SF.net SVN: asycxx:[35] trunk
Status: Alpha
Brought to you by:
joe_steeve
|
From: <joe...@us...> - 2009-04-08 07:37:19
|
Revision: 35
http://asycxx.svn.sourceforge.net/asycxx/?rev=35&view=rev
Author: joe_steeve
Date: 2009-04-08 07:37:17 +0000 (Wed, 08 Apr 2009)
Log Message:
-----------
class:TCPListener now uses StreamProtocol/ProtocolFactory/Transport
From: Joe Steeve <js...@hi...>
Modified Paths:
--------------
trunk/include/asycxx/TCPListener.h
trunk/src/TCPListener.cxx
Modified: trunk/include/asycxx/TCPListener.h
===================================================================
--- trunk/include/asycxx/TCPListener.h 2009-04-08 07:36:33 UTC (rev 34)
+++ trunk/include/asycxx/TCPListener.h 2009-04-08 07:37:17 UTC (rev 35)
@@ -19,37 +19,75 @@
#include "Error.h"
#include "Listener.h"
-#include "Factory.h"
-#include "Deferred.h"
+#include "StreamProtocolFactory.h"
#include "Reactor.h"
-class TCPListener : public Listener
+namespace asycxx
{
-public:
+ class TCPListener : public Listener
+ {
+ public:
- TCPListener (Reactor *reactor, Factory *factory, unsigned short port);
- TCPListener (Reactor *reactor, Factory *factory, char *ip,
- unsigned short port);
- virtual ~TCPListener ();
+ /**
+ * \brief ctor to put TCPListener on localhost:port
+ *
+ * \param[in] reactor The reactor to hook to
+ * \param[in] factory The factory to use to produce protocols to
+ * handle new connections
+ * \param[in] port The port number to bind to
+ *
+ * \details This constructor puts the TCPListener object to listen
+ * on the 127.0.0.1:port interface.
+ */
+ TCPListener (Reactor *reactor, StreamProtocolFactory *factory,
+ unsigned short port);
- void SetupTCPNoDelay (void);
+ /**
+ * \brief ctor to put TCPListener on given ip:port
+ *
+ * \param[in] reactor The reactor to hook to
+ * \param[in] factory The factory to use to produce protocols to
+ * handle new connections
+ * \param[in] ip A string containing the IP address to bind to
+ * \param[in] port The port number to bind to
+ *
+ * \details This constructor puts the TCPListener object to listen
+ * on the given ip:port interface. This method expects a valid
+ * IPv4 ip-address in the 'ip' parameter.
+ */
+ TCPListener (Reactor *reactor, StreamProtocolFactory *factory,
+ char *ip, unsigned short port);
-protected:
- Reactor *m_Reactor;
- Factory *m_Factory;
- Deferred *m_ReactorDeferred;
+ virtual ~TCPListener () {};
- int m_Socket;
- unsigned short m_BindPort;
- in_addr m_BindIPAddr;
- char m_BindAddr_str[64];
- bool m_bSetupNoDelay;
+ /**
+ * \brief set the socket as TCP_NODELAY
+ *
+ * \details This method disables the Nagle algorithm on the
+ * connection by setting TCP_NODELAY.
+ */
+ void SetupTCPNoDelay (void) { m_bSetupNoDelay = true; }
- void Init (Reactor *reactor, Factory *factory,
- struct in_addr ip_addr, unsigned short port);
- static void handleNewConnection (void *obj);
-};
+ /* methods to be implemented for 'Selectable' */
+ virtual void Readable (void);
+
+ virtual void Writable (void) {}
+ virtual void closeReader (void) {}
+ virtual void closeWriter (void) {}
+ protected:
+ Reactor *m_Reactor;
+ StreamProtocolFactory *m_Factory;
+
+ unsigned short m_BindPort;
+ in_addr m_BindIPAddr;
+ char m_BindAddr_str[64];
+ bool m_bSetupNoDelay;
+
+ void Init (Reactor *reactor, StreamProtocolFactory *factory,
+ struct in_addr ip_addr, unsigned short port);
+ };
+}
#endif /* __HIPRO_ASYCXX__TCP_LISTENER_H__ */
/*
Modified: trunk/src/TCPListener.cxx
===================================================================
--- trunk/src/TCPListener.cxx 2009-04-08 07:36:33 UTC (rev 34)
+++ trunk/src/TCPListener.cxx 2009-04-08 07:37:17 UTC (rev 35)
@@ -27,141 +27,87 @@
#include "asycxx-common.h"
#include <asycxx/Error.h>
-#include <asycxx/Factory.h>
-#include <asycxx/Protocol.h>
+#include <asycxx/StreamProtocolFactory.h>
+#include <asycxx/StreamProtocol.h>
#include <asycxx/TCPTransport.h>
#include <asycxx/TCPListener.h>
+using namespace asycxx;
-/**
- * \brief ctor to put TCPListener on localhost:port
- *
- * \param[in] reactor The reactor to hook to
- * \param[in] factory The factory to use to produce protocols to
- * handle new connections
- * \param[in] port The port number to bind to
- *
- * \details This constructor puts the TCPListener object to listen on
- * the 127.0.0.1:port interface.
- */
-TCPListener::TCPListener (Reactor *reactor, Factory *factory,
+/* a simple constructor where we listen on loopback */
+TCPListener::TCPListener (Reactor *reactor, StreamProtocolFactory *factory,
unsigned short port)
{
struct in_addr ip_addr;
-
ip_addr.s_addr = htonl (INADDR_LOOPBACK);
+
Init (reactor, factory, ip_addr, port);
}
-/**
- * \brief ctor to put TCPListener on given ip:port
- *
- * \param[in] reactor The reactor to hook to
- * \param[in] factory The factory to use to produce protocols to
- * handle new connections
- * \param[in] ip A string containing the IP address to bind to
- * \param[in] port The port number to bind to
- *
- * \details This constructor puts the TCPListener object to listen on
- * the given ip:port interface. This method expects a valid IPv4
- * ip-address in the 'ip' parameter.
- */
-TCPListener::TCPListener (Reactor *reactor, Factory *factory,
+/* a ctor to listen on a specific interface */
+TCPListener::TCPListener (Reactor *reactor, StreamProtocolFactory *factory,
char *ip, unsigned short port)
{
int ret;
struct in_addr ip_addr;
ret = inet_aton (ip, &ip_addr);
- if (ret == 0)
- {
- THROW (RunTimeError, "'%s' is not a valid ip-address", ip);
- }
+ ASSERT ((ret != 0), "'%s' is not a valid ip-address", ip);
Init (reactor, factory, ip_addr, port);
}
-/*
- * \brief dtor
- */
-TCPListener::~TCPListener ()
-{
- if (m_Socket != -1)
- {
- close (m_Socket);
- }
-}
-
-/**
- * \brief Initialize the TCPListener
- *
- * \param[in] reactor The reactor to hook to
- * \param[in] factory The factory to use to produce protocols
- * \param[in] ip_addr A 'struct in_addr' containing the IP address to
- * listen on
- * \param[in] port The port to listen on
- *
- * \details This method is the backend method for all the
- * constructors. This creates a socket, puts it on listening mode,
- * binds it to the given interface and hooks it up to the reactor.
- */
+/* This method is the backend method for all the constructors. This
+ * creates a socket, puts it on listening mode, binds it to the given
+ * interface and hooks it up to the reactor. */
void
-TCPListener::Init (Reactor *reactor, Factory *factory,
+TCPListener::Init (Reactor *reactor, StreamProtocolFactory *factory,
struct in_addr ip_addr, unsigned short port)
{
int iret;
- ASSERT ((factory != NULL), "checking parameters");
- ASSERT ((reactor != NULL), "checking parameters");
+ ASSERT ((factory != NULL), "NULL factory :(");
+ ASSERT ((reactor != NULL), "NULL reactor :(");
m_Factory = factory;
m_Reactor = reactor;
m_bSetupNoDelay = false;
+ int sock;
sprintf (m_BindAddr_str, "%s:%d", inet_ntoa (ip_addr), port);
/* creating a socket */
- m_Socket = socket (PF_INET, SOCK_STREAM, 0);
- if (m_Socket == -1)
- {
- THROW (RunTimeError,
- "TCPListener: %s : creating socket to listen on %s",
- strerror (errno), m_BindAddr_str);
- }
+ sock = socket (PF_INET, SOCK_STREAM, 0);
+ ASSERT ((sock != -1), "TCPListener: %s : creating socket to listen on %s",
+ strerror (errno), m_BindAddr_str);
+
/* set so_reuseaddr to avoid 'address in use' */
int on = 1;
- iret = setsockopt (m_Socket, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+ iret = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
ASSERT ((iret == 0), "%s: setting SO_REUSEADDR on socket=%d",
- strerror (errno), m_Socket);
+ strerror (errno), sock);
+
/* bind the socket to an interface */
struct sockaddr_in saddr;
saddr.sin_family = AF_INET;
saddr.sin_port = htons (port);
saddr.sin_addr.s_addr = ip_addr.s_addr;
- iret = bind (m_Socket, (struct sockaddr *)&saddr, sizeof (saddr));
- if (iret == -1)
- {
- close (m_Socket);
- THROW (RunTimeError,
- "TCPListener: %s : binding socket=%u to %s",
- strerror (errno), m_Socket, m_BindAddr_str);
- }
+ iret = bind (sock, (struct sockaddr *)&saddr, sizeof (saddr));
+ ASSERT ((iret == 0), "TCPListener: %s : binding socket=%u to %s",
+ strerror (errno), sock, m_BindAddr_str);
+
/* put the socket on listen mode */
- iret = listen (m_Socket, 5);
- if (iret == -1)
- {
- close (m_Socket);
- THROW (RunTimeError,
- "TCPListener: %s : putting socket=%u to listen on %s",
- strerror (errno), m_Socket, m_BindAddr_str);
- }
+ iret = listen (sock, 5);
+ ASSERT ((iret == 0), "TCPListener: %s : putting socket=%u to listen on %s",
+ strerror (errno), sock, m_BindAddr_str);
+
/* put the socket on non-blocking mode so that we can pass it on to
the reactor */
- SetFDAsNonBlocking (m_Socket);
-
- /* register the non-blocking FD with the reactor */
- m_ReactorDeferred = m_Reactor->OnReadable (m_Socket);
- m_ReactorDeferred->OnEvent (TCPListener::handleNewConnection, (void *)this);
+ SetFDAsNonBlocking (sock);
+ Fd (sock);
+
+ /* hook ourselves to the reactor */
+ m_Reactor->addReader (this);
}
@@ -171,20 +117,16 @@
* \details
*/
void
-TCPListener::handleNewConnection (void *obj)
+TCPListener::Readable (void)
{
- ASSERT ((obj != NULL), "checking parameters");
-
int conn, ret;
struct sockaddr_in addr;
socklen_t addrlen;
- Protocol *proto;
- TCPListener *pthis = (TCPListener *) obj;
while (1)
{
addrlen = sizeof (struct sockaddr_in);
- conn = accept (pthis->m_Socket, (struct sockaddr *)&addr, &addrlen);
+ conn = accept (Fd(), (struct sockaddr *)&addr, &addrlen);
if (conn == -1)
{
if ((errno == EWOULDBLOCK) || (errno == EAGAIN))
@@ -192,59 +134,46 @@
if ((errno == EINTR) || (errno == ECONNABORTED))
{
ERR ("non-fatal: %s: accepting connections on %s",
- strerror(errno), pthis->m_BindAddr_str);
+ strerror(errno), m_BindAddr_str);
return;
}
ERR ("%s: accepting connections on %s",
- strerror(errno), pthis->m_BindAddr_str);
+ strerror(errno), m_BindAddr_str);
ERR ("**FATAL** I am silently unregistering **FATAL**");
ERR ("**FATAL** I very definitely am lost :( **FATAL**");
- pthis->m_Reactor->UnRegister (pthis->m_ReactorDeferred);
+ m_Reactor->removeReader (this);
return;
}
char client[64];
sprintf (client, "%s:%d", inet_ntoa (addr.sin_addr), addr.sin_port);
- LOG3 ("incoming connection from %s on %s", client, pthis->m_BindAddr_str);
+ LOG3 ("incoming connection from %s on %s", client, m_BindAddr_str);
/* See if we need TCP_NODELAY, and configure it */
- if (pthis->m_bSetupNoDelay == true)
+ if (m_bSetupNoDelay == true)
{
int optval = 1;
ret = setsockopt (conn, IPPROTO_TCP, TCP_NODELAY, (void *)&optval,
sizeof (optval));
- if (ret == -1)
- {
- THROW (RunTimeError,
- "setting up TCP_NODELAY on fd=%d failed with %s",
- conn, strerror (errno));
- }
+ ASSERT ((ret == 0), "setting up TCP_NODELAY on fd=%d failed with %s",
+ conn, strerror (errno));
}
/* create a transport */
TCPTransport *trans;
- trans = new TCPTransport (pthis->m_Reactor, conn);
+ trans = new TCPTransport (m_Reactor, conn);
/* create a protocol using the factory */
- proto = pthis->m_Factory->GetProtocol (trans);
- proto->BuildProtocol ();
+ StreamProtocol *proto;
+ proto = m_Factory->GetProtocol (trans);
+
+ /* attach the protocol to the transport */
+ trans->setProtocol (proto);
}
}
-/**
- * \brief set the socket as TCP_NODELAY
- *
- * \details This method disables the Nagle algorithm on the connection
- * by setting TCP_NODELAY.
- */
-void
-TCPListener::SetupTCPNoDelay (void)
-{
- m_bSetupNoDelay = true;
-}
-
/*
Local Variables:
mode: c++
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|