[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. |