TLI_Connector.cpp

Go to the documentation of this file.
00001 // TLI_Connector.cpp,v 4.28 2005/10/28 16:14:56 ossama Exp
00002 
00003 #include "ace/TLI_Connector.h"
00004 
00005 ACE_RCSID(ace, TLI_Connector, "TLI_Connector.cpp,v 4.28 2005/10/28 16:14:56 ossama Exp")
00006 
00007 #if defined (ACE_HAS_TLI)
00008 
00009 #if !defined (__ACE_INLINE__)
00010 #include "ace/TLI_Connector.inl"
00011 #endif /* __ACE_INLINE__ */
00012 
00013 #include "ace/Handle_Set.h"
00014 #include "ace/ACE.h"
00015 #include "ace/OS_NS_string.h"
00016 #include "ace/Time_Value.h"
00017 
00018 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00019 
00020 ACE_ALLOC_HOOK_DEFINE(ACE_TLI_Connector)
00021 
00022 void
00023 ACE_TLI_Connector::dump (void) const
00024 {
00025 #if defined (ACE_HAS_DUMP)
00026   ACE_TRACE ("ACE_TLI_Connector::dump");
00027 #endif /* ACE_HAS_DUMP */
00028 }
00029 
00030 ACE_TLI_Connector::ACE_TLI_Connector (void)
00031 {
00032   ACE_TRACE ("ACE_TLI_Connector::ACE_TLI_Connector");
00033 }
00034 
00035 // Connect the <new_stream> to the <remote_sap>, waiting up to
00036 // <timeout> amount of time if necessary.  It's amazing how
00037 // complicated this is to do in TLI...
00038 
00039 int
00040 ACE_TLI_Connector::connect (ACE_TLI_Stream &new_stream,
00041                             const ACE_Addr &remote_sap,
00042                             ACE_Time_Value *timeout,
00043                             const ACE_Addr &local_sap,
00044                             int reuse_addr,
00045                             int flags,
00046                             int /* perms */,
00047                             const char device[],
00048                             struct t_info *info,
00049                             int rwf,
00050                             struct netbuf *udata,
00051                             struct netbuf *opt)
00052 {
00053   ACE_TRACE ("ACE_TLI_Connector::connect");
00054   int result = 0;
00055 
00056   // Only open a new endpoint if we don't already have a valid handle.
00057 
00058   if (new_stream.get_handle () == ACE_INVALID_HANDLE
00059       && new_stream.open (device, flags, info) == ACE_INVALID_HANDLE)
00060     return -1;
00061 
00062   if (local_sap != ACE_Addr::sap_any)
00063     {
00064       // Bind the local endpoint to a specific addr.
00065 
00066       struct t_bind *localaddr;
00067 
00068       localaddr = (struct t_bind *)
00069         ACE_OS::t_alloc (new_stream.get_handle (), T_BIND, T_ADDR);
00070 
00071       if (localaddr == 0)
00072         result = -1;
00073       else
00074         {
00075           int one = 1;
00076 #if !defined (ACE_HAS_FORE_ATM_XTI)
00077           // Reusing the address causes problems with FORE's API. The
00078           // issue may be that t_optmgmt isn't fully supported by
00079           // FORE. t_errno is TBADOPT after the t_optmgmt call so
00080           // maybe options are configured differently for XTI than for
00081           // TLI (at least for FORE's implementation - XTI is supposed
00082           // to be a superset of TLI).
00083           if (reuse_addr
00084               && new_stream.set_option (SOL_SOCKET,
00085                                         SO_REUSEADDR,
00086                                         &one,
00087                                         sizeof one) == -1)
00088             result = -1;
00089           else
00090 #endif /* ACE_HAS_FORE_ATM_XTI */
00091             {
00092               void *addr_buf = local_sap.get_addr ();
00093               localaddr->addr.len = local_sap.get_size ();
00094               ACE_OS::memcpy(localaddr->addr.buf,
00095                              addr_buf,
00096                              localaddr->addr.len);
00097 
00098               if (ACE_OS::t_bind (new_stream.get_handle (),
00099                                   localaddr,
00100                                   localaddr) == -1)
00101                 result = -1;
00102 
00103               ACE_OS::t_free ((char *) localaddr,
00104                               T_BIND);
00105             }
00106         }
00107 
00108       if (result == -1)
00109         {
00110           new_stream.close ();
00111           return -1;
00112         }
00113     }
00114   // Let TLI select the local endpoint addr.
00115   else if (ACE_OS::t_bind (new_stream.get_handle (), 0, 0) == -1)
00116     return -1;
00117 
00118   struct t_call *callptr = 0;
00119 
00120   callptr = (struct t_call *)
00121     ACE_OS::t_alloc (new_stream.get_handle (), T_CALL, T_ADDR);
00122 
00123   if (callptr == 0)
00124     {
00125       new_stream.close ();
00126       return -1;
00127     }
00128 
00129   void *addr_buf = remote_sap.get_addr ();
00130   callptr->addr.len = remote_sap.get_size ();
00131   ACE_OS::memcpy (callptr->addr.buf,
00132                   addr_buf,
00133                   callptr->addr.len);
00134   //callptr->addr.buf = (char *) remote_sap.get_addr ();
00135 
00136   if (udata != 0)
00137     ACE_OS::memcpy ((void *) &callptr->udata, (void *) udata, sizeof *udata);
00138   if (opt != 0)
00139     ACE_OS::memcpy ((void *) &callptr->opt, (void *) opt, sizeof *opt);
00140 
00141   // Connect to remote endpoint.
00142 #if defined (ACE_HAS_FORE_ATM_XTI)
00143   // FORE's XTI/ATM driver has problems with ioctl/fcntl calls so (at least
00144   // for now) always have blocking calls.
00145   timeout = 0;
00146 #endif /* ACE_HAS_FORE_ATM_XTI */
00147 
00148   if (timeout != 0)   // Enable non-blocking, if required.
00149     {
00150       if (new_stream.enable (ACE_NONBLOCK) == -1)
00151         result = -1;
00152 
00153       // Do a non-blocking connect.
00154       if (ACE_OS::t_connect (new_stream.get_handle (), callptr, 0) == -1)
00155         {
00156           result = -1;
00157 
00158           // Check to see if we simply haven't connected yet on a
00159           // non-blocking handle or whether there's really an error.
00160           if (t_errno == TNODATA)
00161             {
00162               if (timeout->sec () == 0 && timeout->usec () == 0)
00163                 errno = EWOULDBLOCK;
00164               else
00165                 result = this->complete (new_stream, 0, timeout);
00166             }
00167           else if (t_errno == TLOOK && new_stream.look () == T_DISCONNECT)
00168             new_stream.rcvdis ();
00169         }
00170     }
00171   // Do a blocking connect to the server.
00172   else if (ACE_OS::t_connect (new_stream.get_handle (), callptr, 0) == -1)
00173     result = -1;
00174 
00175   if (result != -1)
00176     {
00177       new_stream.set_rwflag (rwf);
00178 #if defined (I_PUSH) && !defined (ACE_HAS_FORE_ATM_XTI)
00179       if (new_stream.get_rwflag ())
00180         result = ACE_OS::ioctl (new_stream.get_handle (),
00181                                 I_PUSH,
00182                                 const_cast<char *> ("tirdwr"));
00183 #endif /* I_PUSH */
00184     }
00185   else if (!(errno == EWOULDBLOCK || errno == ETIME))
00186     {
00187       // If things have gone wrong, close down and return an error.
00188       new_stream.close ();
00189       new_stream.set_handle (ACE_INVALID_HANDLE);
00190     }
00191 
00192   if (ACE_OS::t_free ((char *) callptr, T_CALL) == -1)
00193     return -1;
00194   return result;
00195 }
00196 
00197 // Try to complete a non-blocking connection.
00198 
00199 int
00200 ACE_TLI_Connector::complete (ACE_TLI_Stream &new_stream,
00201                              ACE_Addr *remote_sap,
00202                              ACE_Time_Value *tv)
00203 {
00204   ACE_TRACE ("ACE_TLI_Connector::complete");
00205 #if defined (ACE_WIN32)
00206    if (WaitForSingleObject (new_stream.get_handle(), tv->msec()) == WAIT_OBJECT_0)
00207     {
00208       if (ACE_OS::t_look (new_stream.get_handle()) == T_CONNECT)
00209         return t_rcvconnect (new_stream.get_handle(), 0);
00210       else
00211         return -1;
00212     }
00213   else
00214     return -1;
00215 #else
00216   ACE_HANDLE h = ACE::handle_timed_complete (new_stream.get_handle (),
00217                                              tv,
00218                                              1);
00219   if (h == ACE_INVALID_HANDLE)
00220     {
00221       new_stream.close ();
00222       return -1;
00223     }
00224   else    // We've successfully connected!
00225     {
00226       if (remote_sap != 0)
00227         {
00228 #if defined (ACE_HAS_XTI) || defined (ACE_HAS_SVR4_TLI)
00229           struct netbuf name;
00230 
00231           name.maxlen = remote_sap->get_size ();
00232           name.buf    = (char *) remote_sap->get_addr ();
00233 
00234           if (ACE_OS::t_getname (new_stream.get_handle (),
00235                                  &name,
00236                                  REMOTENAME) == -1)
00237 #else /* SunOS4 */
00238           if (0)
00239 #endif /* ACE_HAS_XTI || ACE_HAS_SVR4_TLI */
00240             {
00241               new_stream.close ();
00242               return -1;
00243             }
00244         }
00245 
00246       // Start out with non-blocking disabled on the <new_stream>.
00247       new_stream.disable (ACE_NONBLOCK);
00248 
00249       return 0;
00250     }
00251 #endif /* ACE_WIN32 */
00252 }
00253 
00254 ACE_END_VERSIONED_NAMESPACE_DECL
00255 
00256 #endif /* ACE_HAS_TLI */

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