libassa 3.5.0
|
00001 // -*- c++ -*- 00002 //------------------------------------------------------------------------ 00003 // Acceptor.h 00004 //------------------------------------------------------------------------ 00005 // Copyright (C) 1999 Vladislav Grinchenko 00006 // 00007 // This library is free software; you can redistribute it and/or 00008 // modify it under the terms of the GNU Library General Public 00009 // License as published by the Free Software Foundation; either 00010 // version 2 of the License, or (at your option) any later version. 00011 //------------------------------------------------------------------------ 00012 #ifndef ACCEPTOR_H 00013 #define ACCEPTOR_H 00014 00015 #include "assa/Logger.h" 00016 #include "assa/EventHandler.h" 00017 #include "assa/Address.h" 00018 #include "assa/Reactor.h" 00019 #include "assa/ServiceHandler.h" 00020 00040 namespace ASSA { 00041 00042 template<class SERVICE_HANDLER, class PEER_ACCEPTOR> 00043 class Acceptor : public virtual EventHandler 00044 { 00045 public: 00049 Acceptor (Reactor* r_); 00050 00054 virtual ~Acceptor (); 00055 00063 virtual int open (const Address& local_addr_); 00064 00068 virtual int close (void); 00069 00079 int handle_read (int fd); 00080 00091 virtual int handle_close (int fd); 00092 00093 protected: 00098 virtual SERVICE_HANDLER* makeServiceHandler (PEER_ACCEPTOR* sock_); 00099 00108 virtual int acceptServiceHandler (PEER_ACCEPTOR*& new_socket_); 00109 00118 virtual int activateServiceHandler (PEER_ACCEPTOR* new_socket_); 00119 00120 protected: 00123 PEER_ACCEPTOR m_listenSocket; 00124 00125 private: 00126 00129 Reactor* m_reactor; 00130 }; 00131 00132 // Convenience definitions 00133 00134 #define SH SERVICE_HANDLER 00135 #define PA PEER_ACCEPTOR 00136 00137 //------------------------------------------------------------------------------ 00138 // Template member functions definitions 00139 //------------------------------------------------------------------------------ 00140 00141 template<class SH, class PA> 00142 inline 00143 Acceptor<SH, PA>:: 00144 Acceptor (Reactor* r_) 00145 : m_reactor (r_) 00146 { 00147 trace("Acceptor::Acceptor"); 00148 } 00149 00150 template<class SH, class PA> 00151 inline 00152 Acceptor<SH, PA>:: 00153 ~Acceptor () 00154 { 00155 trace("Acceptor::~Acceptor"); 00156 } 00157 00158 template<class SH, class PA> 00159 inline int 00160 Acceptor<SH, PA>:: 00161 close (void) 00162 { 00163 trace("Acceptor::close"); 00164 m_listenSocket.close (); 00165 return 0; 00166 } 00167 00168 template<class SH, class PA> 00169 inline int 00170 Acceptor<SH, PA>:: 00171 handle_close (int /* fd */) 00172 { 00173 trace("Acceptor::handle_close"); 00174 00175 // Reactor::get_instance ()->removeHandler (this->id()); 00176 00177 // NOT IMPLEMENTED: This spot requires validation 00178 // whether Acceptor is created on the heap or in 00179 // automatic memory. 00180 DL ((REACT,"Deleted acceptor \"%s\"\n", get_id ().c_str ())); 00181 delete this; 00182 return -1; 00183 } 00184 00185 template<class SH, class PA> 00186 inline SERVICE_HANDLER* 00187 Acceptor<SH, PA>:: 00188 makeServiceHandler (PEER_ACCEPTOR* sock_) 00189 { 00190 trace("Acceptor<>::makeServiceHandler"); 00191 00192 return new SERVICE_HANDLER (sock_); 00193 } 00194 00195 template<class SH, class PA> 00196 inline int 00197 Acceptor<SH, PA>:: 00198 acceptServiceHandler (PEER_ACCEPTOR*& new_socket_) 00199 { 00200 trace("Acceptor::acceptServiceHandler"); 00201 00202 new_socket_ = m_listenSocket.accept (); 00203 return new_socket_ ? 0 : -1; 00204 } 00205 00206 template<class SH, class PA> int 00207 Acceptor<SH, PA>:: 00208 activateServiceHandler (PA* new_socket_) 00209 { 00210 trace("Acceptor::activateServiceHandler"); 00211 00212 if (!new_socket_) { 00213 return -1; 00214 } 00215 SH* sh = makeServiceHandler (new_socket_); 00216 if (sh->open () < 0) { 00217 sh->close (); 00218 } 00219 return 0; 00220 } 00221 00222 template<class SH, class PA> int 00223 Acceptor<SH, PA>:: 00224 open (const Address& local_addr_) 00225 { 00226 trace("Acceptor::open"); 00227 00228 if ( !m_listenSocket.open (local_addr_.getAddress ()->sa_family) ) { 00229 return -1; 00230 } 00231 00232 if ( !m_listenSocket.bind (local_addr_) ) { 00233 return -1; 00234 } 00235 00236 m_reactor->registerIOHandler ( 00237 this, m_listenSocket.getHandler (), READ_EVENT); 00238 00239 DL((TRACE,"Opened acceptor for fd=%d\n", 00240 m_listenSocket.getHandler ())); 00241 00242 return 0; 00243 } 00244 00245 //------------------------------------------------------------------------------ 00246 // Accept all connections waiting in listen queue at once. This avoids going 00247 // through Reactor's event loop for each new connection. 00248 //------------------------------------------------------------------------------ 00249 00250 template <class SH, class PA> int 00251 Acceptor<SH, PA>:: 00252 handle_read (int fd_) 00253 { 00254 trace("Acceptor<>::handle_read"); 00255 00256 FdSet mask; 00257 timeval poll = {0, 0}; 00258 PA* new_socket = 0; 00259 00260 int fd = m_listenSocket.getHandler (); 00261 00262 if (fd != fd_) { 00263 return -1; 00264 } 00265 00266 do { 00267 if ( acceptServiceHandler (new_socket) == -1 ) { 00268 return -1; 00269 } 00270 if ( !activateServiceHandler (new_socket) == -1 ) { 00271 return -1; 00272 } 00273 mask.reset (); 00274 mask.setFd (fd); 00275 } 00276 while ((::select (fd+1, &mask, NULL, NULL, &poll) == 1)); 00277 00278 return 0; 00279 } 00280 00281 } // end namespace ASSA 00282 00283 #endif /* ACCEPTOR_H */