SOCK_SEQPACK_Connector.cpp

Go to the documentation of this file.
00001 // SOCK_SEQPACK_Connector.cpp,v 4.12 2005/10/28 16:14:55 ossama Exp
00002 
00003 #include "ace/SOCK_SEQPACK_Connector.h"
00004 
00005 #include "ace/INET_Addr.h"
00006 #include "ace/Log_Msg.h"
00007 #include "ace/Time_Value.h"
00008 #include "ace/OS_Memory.h"
00009 #include "ace/OS_NS_string.h"
00010 #include "ace/OS_NS_sys_socket.h"
00011 #include "ace/os_include/os_fcntl.h"
00012 
00013 #if defined (ACE_WIN32)
00014 #include "ace/OS_NS_unistd.h"
00015 #endif /* ACE_WIN32 */
00016 
00017 #if !defined (__ACE_INLINE__)
00018 #include "ace/SOCK_SEQPACK_Connector.inl"
00019 #endif /* __ACE_INLINE__ */
00020 
00021 ACE_RCSID(ace, SOCK_SEQPACK_Connector, "SOCK_SEQPACK_Connector.cpp,v 4.35 2002/03/08 23:18:09 spark Exp")
00022 
00023 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00024 
00025 ACE_ALLOC_HOOK_DEFINE(ACE_SOCK_SEQPACK_Connector)
00026 
00027 void
00028 ACE_SOCK_SEQPACK_Connector::dump (void) const
00029 {
00030 #if defined (ACE_HAS_DUMP)
00031   ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::dump");
00032 #endif /* ACE_HAS_DUMP */
00033 }
00034 
00035 int
00036 ACE_SOCK_SEQPACK_Connector::shared_open (ACE_SOCK_SEQPACK_Association &new_association,
00037                                  int protocol_family,
00038                                  int protocol,
00039                                  int reuse_addr)
00040 {
00041   ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::shared_open");
00042 
00043 
00044 
00045   // Only open a new socket if we don't already have a valid handle.
00046   if (new_association.get_handle () == ACE_INVALID_HANDLE &&
00047 #if defined (ACE_HAS_LKSCTP)
00048          new_association.open (SOCK_STREAM,
00049 #else
00050          new_association.open (SOCK_SEQPACKET,
00051 #endif /* ACE_HAS_LKSCTP */
00052                                protocol_family,
00053                                protocol,
00054                                reuse_addr) == -1)
00055     return -1;
00056   else
00057     return 0;
00058 }
00059 
00060 int
00061 ACE_SOCK_SEQPACK_Connector::shared_open (ACE_SOCK_SEQPACK_Association &new_association,
00062                                  int protocol_family,
00063                                  int protocol,
00064                                  ACE_Protocol_Info *protocolinfo,
00065                                  ACE_SOCK_GROUP g,
00066                                  u_long flags,
00067                                  int reuse_addr)
00068 {
00069   ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::shared_open");
00070 
00071   // Only open a new socket if we don't already have a valid handle.
00072   if (new_association.get_handle () == ACE_INVALID_HANDLE &&
00073 #if defined (ACE_HAS_LKSCTP)
00074       new_association.open (SOCK_STREAM,
00075 #else
00076       new_association.open (SOCK_SEQPACKET,
00077 #endif /* ACE_HAS_LKSCTP */
00078                                protocol_family,
00079                                protocol,
00080                                protocolinfo,
00081                                g,
00082                                flags,
00083                                reuse_addr) == -1)
00084       return -1;
00085   else
00086     return 0;
00087 }
00088 
00089 int
00090 ACE_SOCK_SEQPACK_Connector::shared_connect_start (ACE_SOCK_SEQPACK_Association &new_association,
00091                                           const ACE_Time_Value *timeout,
00092                                           const ACE_Addr &local_sap)
00093 {
00094   ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::shared_connect_start");
00095 
00096   if (local_sap != ACE_Addr::sap_any)
00097     {
00098       sockaddr *laddr = reinterpret_cast<sockaddr *> (local_sap.get_addr ());
00099       int size = local_sap.get_size ();
00100 
00101       if (ACE_OS::bind (new_association.get_handle (),
00102                         laddr,
00103                         size) == -1)
00104         {
00105           // Save/restore errno.
00106           ACE_Errno_Guard error (errno);
00107           new_association.close ();
00108           return -1;
00109         }
00110     }
00111 
00112   // Enable non-blocking, if required.
00113   if (timeout != 0
00114       && new_association.enable (ACE_NONBLOCK) == -1)
00115     return -1;
00116   else
00117     return 0;
00118 }
00119 
00120 // Multihomed version of same
00121 int
00122 ACE_SOCK_SEQPACK_Connector::shared_connect_start (ACE_SOCK_SEQPACK_Association &new_association,
00123                                           const ACE_Time_Value *timeout,
00124                                           const ACE_Multihomed_INET_Addr &local_sap)
00125 {
00126   ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::shared_connect_start");
00127 
00128   if (local_sap.ACE_Addr::operator!= (ACE_Addr::sap_any))
00129     {
00130       // The total number of addresses is the number of secondary
00131       // addresses plus one.
00132       size_t num_addresses = local_sap.get_num_secondary_addresses() + 1;
00133 
00134       // Create an array of sockaddr_in to hold the underlying
00135       // representations of the primary and secondary
00136       // addresses.
00137       sockaddr_in*  local_inet_addrs = 0;
00138       ACE_NEW_NORETURN (local_inet_addrs, sockaddr_in[num_addresses]);
00139       if (!local_inet_addrs)
00140         return -1;
00141 
00142       // Populate the array by invoking the get_addresses method on
00143       // the Multihomed_INET_Addr
00144       local_sap.get_addresses(local_inet_addrs, num_addresses);
00145 
00146 #if defined (ACE_HAS_LKSCTP)
00147       sockaddr_in *local_sockaddr = 0;
00148       sockaddr_in portst;
00149       int sn = sizeof(sockaddr);
00150 
00151       // bind to the primary addr first
00152       if (ACE_OS::bind(new_association.get_handle (),
00153                        reinterpret_cast<sockaddr *> (&(local_inet_addrs[0])),
00154                        sizeof(sockaddr)))
00155       {
00156         ACE_Errno_Guard error (errno);
00157         new_association.close ();
00158         return -1;
00159       }
00160 
00161       // do we need to bind multiple addrs
00162       if (num_addresses > 1)
00163       {
00164         // allocate enough memory to hold the number of secondary addrs
00165         ACE_NEW_NORETURN(local_sockaddr,
00166                          sockaddr_in[num_addresses - 1]);
00167 
00168         // get sockaddr_in for the local handle
00169         if (ACE_OS::getsockname(new_association.get_handle (),
00170                                 reinterpret_cast<sockaddr *> (&portst),
00171                                                      &sn))
00172         {
00173           ACE_Errno_Guard error (errno);
00174           new_association.close ();
00175           return -1;
00176         }
00177 
00178         // set the local port # assigned by the os to every secondary addr
00179         for (size_t i = 1; i < num_addresses; i++)
00180         {
00181           local_inet_addrs[i].sin_port = portst.sin_port;
00182         }
00183 
00184         // copy all of the secondary addrs into a sockaddr structure
00185         for (size_t i = 0; i < num_addresses - 1; i++)
00186         {
00187           ACE_OS::memcpy(&(local_sockaddr[i]),
00188                          &(local_inet_addrs[i + 1]),
00189                          sizeof(sockaddr_in));
00190         }
00191 
00192         // bind other ifaces
00193         if (sctp_bindx(new_association.get_handle(),
00194                        reinterpret_cast<sockaddr *> (local_sockaddr),
00195                        num_addresses - 1,
00196                        SCTP_BINDX_ADD_ADDR))
00197         {
00198           ACE_Errno_Guard error (errno);
00199           new_association.close ();
00200           return -1;
00201         }
00202 
00203         delete [] local_sockaddr;
00204       }
00205 #else
00206 
00207       // Call bind
00208       size_t name_len = (sizeof (sockaddr_in)) * num_addresses;
00209       if (ACE_OS::bind (new_association.get_handle (),
00210                         reinterpret_cast<sockaddr *> (local_inet_addrs),
00211                         static_cast<int> (name_len)) == -1)
00212         {
00213           // Save/restore errno.
00214           ACE_Errno_Guard error (errno);
00215           new_association.close ();
00216           return -1;
00217         }
00218 #endif /* ACE_HAS_LKSCTP */
00219 
00220       delete [] local_inet_addrs;
00221     }
00222 
00223   // Enable non-blocking, if required.
00224   if (timeout != 0
00225       && new_association.enable (ACE_NONBLOCK) == -1)
00226     return -1;
00227   else
00228     return 0;
00229 }
00230 
00231 int
00232 ACE_SOCK_SEQPACK_Connector::shared_connect_finish (ACE_SOCK_SEQPACK_Association &new_association,
00233                                            const ACE_Time_Value *timeout,
00234                                            int result)
00235 {
00236   ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::shared_connect_finish");
00237   // Save/restore errno.
00238   ACE_Errno_Guard error (errno);
00239 
00240   if (result == -1 && timeout != 0)
00241     {
00242       // Check whether the connection is in progress.
00243       if (error == EINPROGRESS || error == EWOULDBLOCK)
00244         {
00245           // This expression checks if we were polling.
00246           if (timeout->sec () == 0
00247               && timeout->usec () == 0)
00248             error = EWOULDBLOCK;
00249           // Wait synchronously using timeout.
00250           else if (this->complete (new_association,
00251                                    0,
00252                                    timeout) == -1)
00253             error = errno;
00254           else
00255             return 0;
00256         }
00257     }
00258 
00259   // EISCONN is treated specially since this routine may be used to
00260   // check if we are already connected.
00261   if (result != -1 || error == EISCONN)
00262     // Start out with non-blocking disabled on the <new_association>.
00263     new_association.disable (ACE_NONBLOCK);
00264   else if (!(error == EWOULDBLOCK || error == ETIMEDOUT))
00265     new_association.close ();
00266 
00267   return result;
00268 }
00269 
00270 // Actively connect and produce a new ACE_SOCK_SEQPACK_Association if things go well...
00271 
00272 
00273 int
00274 ACE_SOCK_SEQPACK_Connector::connect (ACE_SOCK_SEQPACK_Association &new_association,
00275                              const ACE_Addr &remote_sap,
00276                              const ACE_Time_Value *timeout,
00277                              const ACE_Addr &local_sap,
00278                              int reuse_addr,
00279                              int /* flags */,
00280                              int /* perms */,
00281                              int protocol)
00282 {
00283   ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::connect");
00284 
00285   if (this->shared_open (new_association,
00286                          remote_sap.get_type (),
00287                          protocol,
00288                          reuse_addr) == -1)
00289     return -1;
00290   else if (this->shared_connect_start (new_association,
00291                                        timeout,
00292                                        local_sap) == -1)
00293     return -1;
00294 
00295   int result = ACE_OS::connect (new_association.get_handle (),
00296                                 reinterpret_cast<sockaddr *> (remote_sap.get_addr ()),
00297                                 remote_sap.get_size ());
00298 
00299   return this->shared_connect_finish (new_association,
00300                                       timeout,
00301                                       result);
00302 }
00303 
00304 // Multihomed version of same
00305 int
00306 ACE_SOCK_SEQPACK_Connector::connect (ACE_SOCK_SEQPACK_Association &new_association,
00307                              const ACE_Addr &remote_sap,
00308                              const ACE_Time_Value *timeout,
00309                              const ACE_Multihomed_INET_Addr &local_sap,
00310                              int reuse_addr,
00311                              int /* flags */,
00312                              int /* perms */,
00313                              int protocol)
00314 {
00315   ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::connect");
00316 
00317   if (this->shared_open (new_association,
00318                          remote_sap.get_type (),
00319                          protocol,
00320                          reuse_addr) == -1)
00321     return -1;
00322   else if (this->shared_connect_start (new_association,
00323                                        timeout,
00324                                        local_sap) == -1)
00325     return -1;
00326 
00327   int result = ACE_OS::connect (new_association.get_handle (),
00328                                 reinterpret_cast<sockaddr *> (remote_sap.get_addr ()),
00329                                 remote_sap.get_size ());
00330 
00331   return this->shared_connect_finish (new_association,
00332                                       timeout,
00333                                       result);
00334 }
00335 
00336 // Try to complete a non-blocking connection.
00337 
00338 int
00339 ACE_SOCK_SEQPACK_Connector::complete (ACE_SOCK_SEQPACK_Association &new_association,
00340                               ACE_Addr *remote_sap,
00341                               const ACE_Time_Value *tv)
00342 {
00343   ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::complete");
00344   ACE_HANDLE h = ACE::handle_timed_complete (new_association.get_handle (),
00345                                              tv);
00346   // We failed to get connected.
00347   if (h == ACE_INVALID_HANDLE)
00348     {
00349 #if defined (ACE_WIN32)
00350       // Win32 has a timing problem - if you check to see if the
00351       // connection has completed too fast, it will fail - so wait
00352       // <ACE_NON_BLOCKING_BUG_DELAY> microseconds to let it catch up
00353       // then retry to see if it's a real failure.
00354       ACE_Time_Value time (0, ACE_NON_BLOCKING_BUG_DELAY);
00355       ACE_OS::sleep (time);
00356       h = ACE::handle_timed_complete (new_association.get_handle (),
00357                                       tv);
00358       if (h == ACE_INVALID_HANDLE)
00359         {
00360 #endif /* ACE_WIN32 */
00361       // Save/restore errno.
00362       ACE_Errno_Guard error (errno);
00363       new_association.close ();
00364       return -1;
00365 #if defined (ACE_WIN32)
00366         }
00367 #endif /* ACE_WIN32 */
00368     }
00369 
00370   if (remote_sap != 0)
00371     {
00372       int len = remote_sap->get_size ();
00373       sockaddr *addr = reinterpret_cast<sockaddr *> (remote_sap->get_addr ());
00374       if (ACE_OS::getpeername (h,
00375                                addr,
00376                                &len) == -1)
00377         {
00378           // Save/restore errno.
00379           ACE_Errno_Guard error (errno);
00380           new_association.close ();
00381           return -1;
00382         }
00383     }
00384 
00385   // Start out with non-blocking disabled on the <new_association>.
00386   new_association.disable (ACE_NONBLOCK);
00387   return 0;
00388 }
00389 
00390 ACE_SOCK_SEQPACK_Connector::ACE_SOCK_SEQPACK_Connector (ACE_SOCK_SEQPACK_Association &new_association,
00391                                         const ACE_Addr &remote_sap,
00392                                         const ACE_Time_Value *timeout,
00393                                         const ACE_Addr &local_sap,
00394                                         int reuse_addr,
00395                                         int flags,
00396                                         int perms,
00397                                         int protocol)
00398 {
00399   ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::ACE_SOCK_SEQPACK_Connector");
00400 
00401   if (this->connect (new_association,
00402                      remote_sap,
00403                      timeout,
00404                      local_sap,
00405                      reuse_addr,
00406                      flags,
00407                      perms,
00408                      protocol) == -1
00409       && timeout != 0
00410       && !(errno == EWOULDBLOCK || errno == ETIME || errno == ETIMEDOUT))
00411     ACE_ERROR ((LM_ERROR,
00412                 ACE_LIB_TEXT ("%p\n"),
00413                 ACE_LIB_TEXT ("ACE_SOCK_SEQPACK_Connector::ACE_SOCK_SEQPACK_Connector")));
00414 }
00415 
00416 // Multihomed version of same
00417 ACE_SOCK_SEQPACK_Connector::ACE_SOCK_SEQPACK_Connector (ACE_SOCK_SEQPACK_Association &new_association,
00418                                         const ACE_Addr &remote_sap,
00419                                         const ACE_Time_Value *timeout,
00420                                         const ACE_Multihomed_INET_Addr &local_sap,
00421                                         int reuse_addr,
00422                                         int flags,
00423                                         int perms,
00424                                         int protocol)
00425 {
00426   ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::ACE_SOCK_SEQPACK_Connector");
00427 
00428   if (this->connect (new_association,
00429                      remote_sap,
00430                      timeout,
00431                      local_sap,
00432                      reuse_addr,
00433                      flags,
00434                      perms,
00435                      protocol) == -1
00436       && timeout != 0
00437       && !(errno == EWOULDBLOCK || errno == ETIME || errno == ETIMEDOUT))
00438     ACE_ERROR ((LM_ERROR,
00439                 ACE_LIB_TEXT ("%p\n"),
00440                 ACE_LIB_TEXT ("ACE_SOCK_SEQPACK_Connector::ACE_SOCK_SEQPACK_Connector")));
00441 }
00442 
00443 ACE_END_VERSIONED_NAMESPACE_DECL

Generated on Thu Nov 9 09:42:04 2006 for ACE by doxygen 1.3.6