1 #include "ace/TLI_Connector.h"
5 #if defined (ACE_HAS_TLI)
7 #if !defined (__ACE_INLINE__)
8 #include "ace/TLI_Connector.inl"
9 #endif /* __ACE_INLINE__ */
11 #include "ace/Handle_Set.h"
13 #include "ace/OS_NS_string.h"
14 #include "ace/Time_Value.h"
16 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
18 ACE_ALLOC_HOOK_DEFINE(ACE_TLI_Connector
)
21 ACE_TLI_Connector::dump (void) const
23 #if defined (ACE_HAS_DUMP)
24 ACE_TRACE ("ACE_TLI_Connector::dump");
25 #endif /* ACE_HAS_DUMP */
28 ACE_TLI_Connector::ACE_TLI_Connector (void)
30 ACE_TRACE ("ACE_TLI_Connector::ACE_TLI_Connector");
33 // Connect the <new_stream> to the <remote_sap>, waiting up to
34 // <timeout> amount of time if necessary. It's amazing how
35 // complicated this is to do in TLI...
38 ACE_TLI_Connector::connect (ACE_TLI_Stream
&new_stream
,
39 const ACE_Addr
&remote_sap
,
40 ACE_Time_Value
*timeout
,
41 const ACE_Addr
&local_sap
,
51 ACE_TRACE ("ACE_TLI_Connector::connect");
54 // Only open a new endpoint if we don't already have a valid handle.
56 if (new_stream
.get_handle () == ACE_INVALID_HANDLE
57 && new_stream
.open (device
, flags
, info
) == ACE_INVALID_HANDLE
)
60 if (local_sap
!= ACE_Addr::sap_any
)
62 // Bind the local endpoint to a specific addr.
64 struct t_bind
*localaddr
;
66 localaddr
= (struct t_bind
*)
67 ACE_OS::t_alloc (new_stream
.get_handle (), T_BIND
, T_ADDR
);
74 #if !defined (ACE_HAS_FORE_ATM_XTI)
75 // Reusing the address causes problems with FORE's API. The
76 // issue may be that t_optmgmt isn't fully supported by
77 // FORE. t_errno is TBADOPT after the t_optmgmt call so
78 // maybe options are configured differently for XTI than for
79 // TLI (at least for FORE's implementation - XTI is supposed
80 // to be a superset of TLI).
82 && new_stream
.set_option (SOL_SOCKET
,
88 #endif /* ACE_HAS_FORE_ATM_XTI */
90 void *addr_buf
= local_sap
.get_addr ();
91 localaddr
->addr
.len
= local_sap
.get_size ();
92 ACE_OS::memcpy(localaddr
->addr
.buf
,
96 if (ACE_OS::t_bind (new_stream
.get_handle (),
101 ACE_OS::t_free ((char *) localaddr
,
112 // Let TLI select the local endpoint addr.
113 else if (ACE_OS::t_bind (new_stream
.get_handle (), 0, 0) == -1)
116 struct t_call
*callptr
= 0;
118 callptr
= (struct t_call
*)
119 ACE_OS::t_alloc (new_stream
.get_handle (), T_CALL
, T_ADDR
);
127 void *addr_buf
= remote_sap
.get_addr ();
128 callptr
->addr
.len
= remote_sap
.get_size ();
129 ACE_OS::memcpy (callptr
->addr
.buf
,
132 //callptr->addr.buf = (char *) remote_sap.get_addr ();
135 ACE_OS::memcpy ((void *) &callptr
->udata
, (void *) udata
, sizeof *udata
);
137 ACE_OS::memcpy ((void *) &callptr
->opt
, (void *) opt
, sizeof *opt
);
139 // Connect to remote endpoint.
140 #if defined (ACE_HAS_FORE_ATM_XTI)
141 // FORE's XTI/ATM driver has problems with ioctl/fcntl calls so (at least
142 // for now) always have blocking calls.
144 #endif /* ACE_HAS_FORE_ATM_XTI */
146 if (timeout
!= 0) // Enable non-blocking, if required.
148 if (new_stream
.enable (ACE_NONBLOCK
) == -1)
151 // Do a non-blocking connect.
152 if (ACE_OS::t_connect (new_stream
.get_handle (), callptr
, 0) == -1)
156 // Check to see if we simply haven't connected yet on a
157 // non-blocking handle or whether there's really an error.
158 if (t_errno
== TNODATA
)
160 if (*timeout
== ACE_Time_Value::zero
)
163 result
= this->complete (new_stream
, 0, timeout
);
165 else if (t_errno
== TLOOK
&& new_stream
.look () == T_DISCONNECT
)
166 new_stream
.rcvdis ();
169 // Do a blocking connect to the server.
170 else if (ACE_OS::t_connect (new_stream
.get_handle (), callptr
, 0) == -1)
175 new_stream
.set_rwflag (rwf
);
176 #if defined (I_PUSH) && !defined (ACE_HAS_FORE_ATM_XTI)
177 if (new_stream
.get_rwflag ())
178 result
= ACE_OS::ioctl (new_stream
.get_handle (),
180 const_cast<char *> ("tirdwr"));
183 else if (!(errno
== EWOULDBLOCK
|| errno
== ETIME
))
185 // If things have gone wrong, close down and return an error.
187 new_stream
.set_handle (ACE_INVALID_HANDLE
);
190 if (ACE_OS::t_free ((char *) callptr
, T_CALL
) == -1)
195 // Try to complete a non-blocking connection.
198 ACE_TLI_Connector::complete (ACE_TLI_Stream
&new_stream
,
199 ACE_Addr
*remote_sap
,
202 ACE_TRACE ("ACE_TLI_Connector::complete");
203 #if defined (ACE_WIN32)
204 if (WaitForSingleObject (new_stream
.get_handle(), tv
->msec()) == WAIT_OBJECT_0
)
206 if (ACE_OS::t_look (new_stream
.get_handle()) == T_CONNECT
)
207 return t_rcvconnect (new_stream
.get_handle(), 0);
214 ACE_HANDLE h
= ACE::handle_timed_complete (new_stream
.get_handle (),
217 if (h
== ACE_INVALID_HANDLE
)
222 else // We've successfully connected!
226 #if defined (ACE_HAS_XTI) || defined (ACE_HAS_SVR4_TLI)
229 name
.maxlen
= remote_sap
->get_size ();
230 name
.buf
= (char *) remote_sap
->get_addr ();
232 if (ACE_OS::t_getname (new_stream
.get_handle (),
237 #endif /* ACE_HAS_XTI || ACE_HAS_SVR4_TLI */
244 // Start out with non-blocking disabled on the <new_stream>.
245 new_stream
.disable (ACE_NONBLOCK
);
249 #endif /* ACE_WIN32 */
252 ACE_END_VERSIONED_NAMESPACE_DECL
254 #endif /* ACE_HAS_TLI */