#include <Connector.h>
Inheritance diagram for ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >:
Public Member Functions | |
Connector () | |
Constructor. Do-nothing. | |
virtual | ~Connector () |
Destructor. Do-nothing. | |
virtual int | open (const TimeVal &tv_=TimeVal(5.0), ConnectMode mode_=sync, Reactor *r_=(Reactor *) NULL) |
Configure Connector. | |
virtual int | close (void) |
Do-nothing close. | |
virtual int | connect (SERVICE_HANDLER *sh_, Address &addr_, int protocol_=AF_INET) |
Define strategy for establishing connection. | |
virtual int | handle_write (int fd) |
Handle connection completion. | |
virtual int | handle_timeout (TimerId tid) |
Handler connection timeout. | |
Protected Types | |
enum | ProgressState { idle, waiting, conned, failed } |
state. More... | |
Protected Member Functions | |
virtual SERVICE_HANDLER * | makeServiceHandler (SERVICE_HANDLER *sh_) |
Defines creation strategy for ServiceHandler. | |
virtual int | connectServiceHandler (Address &addr, int protocol) |
Default strategy is to make synchronous connection with no timeouts. | |
virtual int | activateServiceHandler () |
Activate handler by calling its open() method. | |
Protected Attributes | |
TimeVal | m_timeout |
Timeout. | |
TimerId | m_tid |
Timer id. | |
Reactor * | m_reactor |
Reference to Reactor (for async). | |
ProgressState | m_state |
Connection progress state. | |
int | m_flags |
Socket options. | |
SERVICE_HANDLER * | m_sh |
Reference to ServiceHandler. | |
int | m_fd |
Socket file descriptor. | |
ConnectMode | m_mode |
Mode (sync/async). | |
Private Member Functions | |
void | doAsync (void) |
Setup for asynchronous mode completion. | |
int | doSync (void) |
Synchronous mode completion. |
This template class implements the generic strategy for actively
initializing communication services.
SERVICE_HANDLER is the type of service. It shall be a type derived from ServiceHandler interface class.
PEER_CONNECTOR is the type of concrete Socket class - particular transport mechanism used by the Connector to actively establish the connection. It should be derived from Socket interface class.
Definition at line 57 of file Connector.h.
|
state. Connection state.
Definition at line 125 of file Connector.h.
|
|
Constructor. Do-nothing.
Definition at line 199 of file Connector.h. References ASSA::EventHandler::set_id(), ASSA::SOCKTRACE, and trace_with_mask. 00200 : m_tid (0), m_reactor (0), m_state (idle), 00201 m_flags (0), m_sh ((SERVICE_HANDLER*)NULL), m_fd (-1), m_mode (sync) 00202 { 00203 trace_with_mask("Connector::Connector",SOCKTRACE); 00204 set_id ("Connector"); 00205 }
|
|
Destructor. Do-nothing.
Definition at line 209 of file Connector.h. References ASSA::SOCKTRACE, and trace_with_mask. 00210 { 00211 trace_with_mask("Connector::~Connector",SOCKTRACE); 00212 // If I created SERVICE_HANDLER, should I delete it too? 00213 }
|
|
Activate handler by calling its open() method.
Definition at line 319 of file Connector.h. References ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::m_sh, ASSA::SOCKTRACE, and trace_with_mask. Referenced by ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::handle_write(). 00320 { 00321 trace_with_mask("Connector::activateServiceHandler",SOCKTRACE); 00322 00323 return m_sh->open (); 00324 }
|
|
Do-nothing close. Derive classes can change this strategy by overloading this method.
Definition at line 231 of file Connector.h. References ASSA::SOCKTRACE, and trace_with_mask. 00232 { 00233 trace_with_mask("Connector::close",SOCKTRACE); 00234 return 0; 00235 }
|
|
Define strategy for establishing connection. Default is to connect synchronously to the remote peer. In sync mode connection either will be established or failed when returned from Connector::connect() call. In async mode, call to Connector::connect() returns immediately reporting only immediate error. Later on connection is completed asynchronously. Default timeout on connection waiting is 10 seconds. Timeout can be configured by passing TimeVal parameter to the Connector::open() member function. If connetion failed, caller should definitely close PEER_CONNECTOR communication point.
Definition at line 239 of file Connector.h. References ASSA::Address::bad(), EL, ASSA::ERROR, ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::m_sh, ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::makeServiceHandler(), ASSA::SOCKTRACE, and trace_with_mask. 00240 { 00241 /* 00242 * We restore socket to its original mode only on 00243 * successful connection. If error occured, client would have 00244 * to close socket anyway. 00245 * 00246 * NOTE: If sh_==0, then result is dangling pointer 00247 * new_sh produced ! Destructor should determine whether 00248 * SERVICE_HANDLER has been created dynamically and if so, delete 00249 * it. 00250 */ 00251 trace_with_mask("Connector::connect",SOCKTRACE); 00252 errno = 0; 00253 00254 m_sh = makeServiceHandler (sh_); 00255 PEER_CONNECTOR& s = *m_sh; 00256 00257 if (addr_.bad ()) { 00258 errno = EFAULT; // Bad address 00259 EL((ERROR,"Bad address (errno %d)\n", errno)); 00260 return -1; 00261 } 00262 00263 if (connectServiceHandler (addr_, protocol_family_) == -1) { 00264 00265 if (errno == EINPROGRESS) { 00266 00267 if (async == m_mode) { 00268 doAsync (); 00269 return 0; 00270 } 00271 return doSync (); 00272 } 00273 return -1; 00274 } 00275 /* Switch to blocking mode */ 00276 fcntl (s.getHandler (), F_SETFL, m_flags); 00277 00278 return activateServiceHandler (); 00279 }
|
|
Default strategy is to make synchronous connection with no timeouts. Derived class can change this strategy by overloading this method.
Definition at line 297 of file Connector.h. References EL, ASSA::ERROR, ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::m_sh, ASSA::SOCKTRACE, and trace_with_mask. 00298 { 00299 trace_with_mask("Connector::connectServiceHandler",SOCKTRACE); 00300 00301 PEER_CONNECTOR& s = *m_sh; 00302 00303 if ( !s.open (protocol_family_) ) { 00304 EL((ERROR,"Socket::open (protocol=%d) failed\n", 00305 protocol_family_)); 00306 return -1; 00307 } 00308 // Switch to non-blocking mode 00309 00310 m_fd = s.getHandler (); 00311 m_flags = fcntl (m_fd, F_GETFL, 0); 00312 fcntl (m_fd, F_SETFL, m_flags | O_NONBLOCK); 00313 00314 return s.connect (addr_) ? 0 : -1; 00315 }
|
|
|
|
Handler connection timeout.
Reimplemented from ASSA::EventHandler. Definition at line 465 of file Connector.h. References ASSA::async, ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::failed, ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::m_mode, ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::m_reactor, ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::m_state, ASSA::Reactor::removeHandler(), ASSA::SOCKTRACE, trace_with_mask, and ASSA::WRITE_EVENT. 00466 { 00467 trace_with_mask("Connector::handle_timeout",SOCKTRACE); 00468 00469 m_state = failed; 00470 errno = ETIMEDOUT; // Connection timed out 00471 00472 if (async == m_mode) { 00473 m_reactor->removeHandler (this, WRITE_EVENT); 00474 } 00475 return -1; // Remove Timer Handler 00476 }
|
|
Handle connection completion. Always remove IO handler first. Reimplemented from ASSA::EventHandler. Definition at line 373 of file Connector.h. References ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::activateServiceHandler(), ASSA::async, ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::conned, DL, EL, ASSA::ERROR, ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::failed, ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::m_fd, ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::m_mode, ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::m_reactor, ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::m_sh, ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::m_state, ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::m_tid, ASSA::Reactor::removeHandler(), ASSA::Reactor::removeTimerHandler(), ASSA::SOCKTRACE, trace_with_mask, and ASSA::WRITE_EVENT. 00374 { 00375 trace_with_mask("Connector::handle_write",SOCKTRACE); 00376 00377 /* Precondition 00378 */ 00379 if (fd_ != m_fd) { 00380 return -1; 00381 } 00382 00383 /* This method serves both sync and async modes - thus the 00384 * differences. For async we remove Timer here. sync runs 00385 * its own private Reactor and handler termination is 00386 * handled in doSync(). 00387 */ 00388 00389 if (async == m_mode) { // Complete SH activation 00390 m_reactor->removeTimerHandler (m_tid); 00391 m_tid = 0; 00392 } 00393 00394 /* 00395 * Although SUN and Linux man pages on connect(3) claims that 00396 * "upon asynchronous establishement of connection, select(3) 00397 * will indicate that the file descriptor for the socket is ready 00398 * for writing", as discussed in W.S.Stevens "UNIX network 00399 * programming", Vol I, 2nd edition, BSD-derived systems also 00400 * mark file descriptor both readable and writable when the 00401 * connection establishment encouters an error. 00402 * 00403 * Therefore we need an extra step to find out what really happened. 00404 * One way to do so is to look at socket pending errors... 00405 */ 00406 00407 int error; 00408 int ret; 00409 error = ret = errno = 0; 00410 socklen_t n = sizeof (error); 00411 00414 m_reactor->removeHandler (this, WRITE_EVENT); 00415 00416 #ifdef __CYGWIN32__ 00417 ret = getsockopt (m_fd, SOL_SOCKET, SO_ERROR, (void*)&error, (int*)&n); 00418 #else 00419 ret = getsockopt (m_fd, SOL_SOCKET, SO_ERROR, (void*)&error, &n); 00420 #endif 00421 00422 if (ret == 0) { 00423 if (error == 0) { 00424 if (activateServiceHandler () == 0) { 00425 DL((SOCKTRACE,"Nonblocking connect() completed\n")); 00426 m_state = conned; 00427 } 00428 else { 00429 DL((SOCKTRACE,"Nonblocking connect() failed\n")); 00430 m_state = failed; 00431 } 00432 return (0); // return value doesn't really matter 00433 } 00434 /* Socket pending error - propagate it via errno. */ 00435 EL((ERROR,"Socket pending error: %d\n",error)); 00436 errno = error; 00437 } 00438 else { 00439 /* Solaris pending error. */ 00440 EL((ERROR,"getsockopt(3) = %d\n", ret)); 00441 EL((ERROR,"Solaris pending error!\n")); 00442 } 00443 m_state = failed; 00444 00445 EL((ERROR,"Nonblocking connect (2) failed\n")); 00446 00447 if (errno == ECONNREFUSED) { 00448 EL((ERROR,"Try to compare port " 00449 "numbers on client and service hosts.\n")); 00450 } 00451 /* This is the only way to tell SH that we failed to connect. 00452 */ 00453 if (async == m_mode) { 00454 m_sh->close (); 00455 } 00456 00457 /* Don't alter fd mask - SERVICE_HANDLER::open() could have changed 00458 * it already for application processing needs. 00459 */ 00460 return 0; 00461 }
|
|
Defines creation strategy for ServiceHandler. Default is to dynamically allocate new SERVICE_HANDLER, if one is not given as an argument.
Definition at line 283 of file Connector.h. References ASSA::SOCKTRACE, and trace_with_mask. Referenced by ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::connect(). 00284 { 00285 trace_with_mask("Connector::makeServiceHandler",SOCKTRACE); 00286 00287 SERVICE_HANDLER* new_sh = sh_; 00288 00289 if (sh_ == 0) { 00290 new_sh = new SERVICE_HANDLER; 00291 } 00292 return new_sh; 00293 }
|
|
Configure Connector. Timeout will be used to timeout connection operation. If mode_ is async, then Reactor r_ ought to be specified for handling asynchronous event processing. Derive classes can change this strategy by overloading this method.
Definition at line 217 of file Connector.h. References ASSA::async, ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::m_mode, ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::m_reactor, ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::m_timeout, ASSA::SOCKTRACE, and trace_with_mask. 00218 { 00219 trace_with_mask("Connector::open", SOCKTRACE); 00220 00221 m_timeout = tv_; 00222 if (async == mode_ && (Reactor*) NULL == r_) 00223 return -1; 00224 m_mode = mode_; 00225 m_reactor = r_; 00226 return 0; 00227 }
|
|
Socket file descriptor.
Definition at line 173 of file Connector.h. Referenced by ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::doAsync(), ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::doSync(), and ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::handle_write(). |
|
Socket options.
Definition at line 167 of file Connector.h. Referenced by ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::doSync(). |
|
Mode (sync/async).
Definition at line 176 of file Connector.h. Referenced by ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::handle_timeout(), ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::handle_write(), and ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::open(). |
|
Reference to Reactor (for async).
Definition at line 161 of file Connector.h. Referenced by ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::doAsync(), ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::doSync(), ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::handle_timeout(), ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::handle_write(), and ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::open(). |
|
|
Connection progress state.
Definition at line 164 of file Connector.h. Referenced by ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::doAsync(), ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::doSync(), ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::handle_timeout(), and ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::handle_write(). |
|
Timer id.
Definition at line 158 of file Connector.h. Referenced by ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::doAsync(), and ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::handle_write(). |
|
Timeout.
Definition at line 155 of file Connector.h. Referenced by ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::doAsync(), ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::doSync(), and ASSA::Connector< SERVICE_HANDLER, PEER_CONNECTOR >::open(). |