1 #include "ace/TLI_Connector.h"
3 #if defined (ACE_HAS_TLI)
5 #if !defined (__ACE_INLINE__)
6 #include "ace/TLI_Connector.inl"
7 #endif /* __ACE_INLINE__ */
9 #include "ace/Handle_Set.h"
11 #include "ace/OS_NS_string.h"
12 #include "ace/Time_Value.h"
14 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
16 ACE_ALLOC_HOOK_DEFINE(ACE_TLI_Connector
)
19 ACE_TLI_Connector::dump () const
21 #if defined (ACE_HAS_DUMP)
22 ACE_TRACE ("ACE_TLI_Connector::dump");
23 #endif /* ACE_HAS_DUMP */
26 ACE_TLI_Connector::ACE_TLI_Connector ()
28 ACE_TRACE ("ACE_TLI_Connector::ACE_TLI_Connector");
31 // Connect the <new_stream> to the <remote_sap>, waiting up to
32 // <timeout> amount of time if necessary. It's amazing how
33 // complicated this is to do in TLI...
36 ACE_TLI_Connector::connect (ACE_TLI_Stream
&new_stream
,
37 const ACE_Addr
&remote_sap
,
38 ACE_Time_Value
*timeout
,
39 const ACE_Addr
&local_sap
,
49 ACE_TRACE ("ACE_TLI_Connector::connect");
52 // Only open a new endpoint if we don't already have a valid handle.
54 if (new_stream
.get_handle () == ACE_INVALID_HANDLE
55 && new_stream
.open (device
, flags
, info
) == ACE_INVALID_HANDLE
)
58 if (local_sap
!= ACE_Addr::sap_any
)
60 // Bind the local endpoint to a specific addr.
62 struct t_bind
*localaddr
;
64 localaddr
= (struct t_bind
*)
65 ACE_OS::t_alloc (new_stream
.get_handle (), T_BIND
, T_ADDR
);
72 #if !defined (ACE_HAS_FORE_ATM_XTI)
73 // Reusing the address causes problems with FORE's API. The
74 // issue may be that t_optmgmt isn't fully supported by
75 // FORE. t_errno is TBADOPT after the t_optmgmt call so
76 // maybe options are configured differently for XTI than for
77 // TLI (at least for FORE's implementation - XTI is supposed
78 // to be a superset of TLI).
80 && new_stream
.set_option (SOL_SOCKET
,
86 #endif /* ACE_HAS_FORE_ATM_XTI */
88 void *addr_buf
= local_sap
.get_addr ();
89 localaddr
->addr
.len
= local_sap
.get_size ();
90 ACE_OS::memcpy(localaddr
->addr
.buf
,
94 if (ACE_OS::t_bind (new_stream
.get_handle (),
99 ACE_OS::t_free ((char *) localaddr
,
110 // Let TLI select the local endpoint addr.
111 else if (ACE_OS::t_bind (new_stream
.get_handle (), 0, 0) == -1)
114 struct t_call
*callptr
= 0;
116 callptr
= (struct t_call
*)
117 ACE_OS::t_alloc (new_stream
.get_handle (), T_CALL
, T_ADDR
);
125 void *addr_buf
= remote_sap
.get_addr ();
126 callptr
->addr
.len
= remote_sap
.get_size ();
127 ACE_OS::memcpy (callptr
->addr
.buf
,
130 //callptr->addr.buf = (char *) remote_sap.get_addr ();
133 ACE_OS::memcpy ((void *) &callptr
->udata
, (void *) udata
, sizeof *udata
);
135 ACE_OS::memcpy ((void *) &callptr
->opt
, (void *) opt
, sizeof *opt
);
137 // Connect to remote endpoint.
138 #if defined (ACE_HAS_FORE_ATM_XTI)
139 // FORE's XTI/ATM driver has problems with ioctl/fcntl calls so (at least
140 // for now) always have blocking calls.
142 #endif /* ACE_HAS_FORE_ATM_XTI */
144 if (timeout
!= 0) // Enable non-blocking, if required.
146 if (new_stream
.enable (ACE_NONBLOCK
) == -1)
149 // Do a non-blocking connect.
150 if (ACE_OS::t_connect (new_stream
.get_handle (), callptr
, 0) == -1)
154 // Check to see if we simply haven't connected yet on a
155 // non-blocking handle or whether there's really an error.
156 if (t_errno
== TNODATA
)
158 if (*timeout
== ACE_Time_Value::zero
)
161 result
= this->complete (new_stream
, 0, timeout
);
163 else if (t_errno
== TLOOK
&& new_stream
.look () == T_DISCONNECT
)
164 new_stream
.rcvdis ();
167 // Do a blocking connect to the server.
168 else if (ACE_OS::t_connect (new_stream
.get_handle (), callptr
, 0) == -1)
173 new_stream
.set_rwflag (rwf
);
174 #if defined (I_PUSH) && !defined (ACE_HAS_FORE_ATM_XTI)
175 if (new_stream
.get_rwflag ())
176 result
= ACE_OS::ioctl (new_stream
.get_handle (),
178 const_cast<char *> ("tirdwr"));
181 else if (!(errno
== EWOULDBLOCK
|| errno
== ETIME
))
183 // If things have gone wrong, close down and return an error.
185 new_stream
.set_handle (ACE_INVALID_HANDLE
);
188 if (ACE_OS::t_free ((char *) callptr
, T_CALL
) == -1)
193 // Try to complete a non-blocking connection.
196 ACE_TLI_Connector::complete (ACE_TLI_Stream
&new_stream
,
197 ACE_Addr
*remote_sap
,
200 ACE_TRACE ("ACE_TLI_Connector::complete");
201 #if defined (ACE_WIN32)
202 if (WaitForSingleObject (new_stream
.get_handle(), tv
->msec()) == WAIT_OBJECT_0
)
204 if (ACE_OS::t_look (new_stream
.get_handle()) == T_CONNECT
)
205 return t_rcvconnect (new_stream
.get_handle(), 0);
212 ACE_HANDLE h
= ACE::handle_timed_complete (new_stream
.get_handle (),
215 if (h
== ACE_INVALID_HANDLE
)
220 else // We've successfully connected!
224 #if defined (ACE_HAS_XTI)
227 name
.maxlen
= remote_sap
->get_size ();
228 name
.buf
= (char *) remote_sap
->get_addr ();
230 if (ACE_OS::t_getname (new_stream
.get_handle (),
233 #else /* ACE_HAS_XTI */
235 #endif /* ACE_HAS_XTI */
242 // Start out with non-blocking disabled on the <new_stream>.
243 new_stream
.disable (ACE_NONBLOCK
);
247 #endif /* ACE_WIN32 */
250 ACE_END_VERSIONED_NAMESPACE_DECL
252 #endif /* ACE_HAS_TLI */