1 #include "ace/SOCK_Connector.h"
2 #include "ace/INET_Addr.h"
3 #include "ace/Log_Category.h"
4 #include "ace/OS_NS_unistd.h"
5 #include "ace/OS_NS_sys_socket.h"
6 #include "ace/os_include/os_fcntl.h"
7 #if defined (ACE_HAS_ALLOC_HOOKS)
8 # include "ace/Malloc_Base.h"
9 #endif /* ACE_HAS_ALLOC_HOOKS */
11 #include "ace/OS_QoS.h"
13 #if !defined (__ACE_INLINE__)
14 #include "ace/SOCK_Connector.inl"
15 #endif /* __ACE_INLINE__ */
17 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
19 ACE_ALLOC_HOOK_DEFINE(ACE_SOCK_Connector
)
22 ACE_SOCK_Connector::dump () const
24 #if defined (ACE_HAS_DUMP)
25 ACE_TRACE ("ACE_SOCK_Connector::dump");
26 #endif /* ACE_HAS_DUMP */
30 ACE_SOCK_Connector::shared_open (ACE_SOCK_Stream
&new_stream
,
35 ACE_TRACE ("ACE_SOCK_Connector::shared_open");
37 // Only open a new socket if we don't already have a valid handle.
38 if (new_stream
.get_handle () == ACE_INVALID_HANDLE
39 && new_stream
.open (SOCK_STREAM
,
49 ACE_SOCK_Connector::shared_open (ACE_SOCK_Stream
&new_stream
,
52 ACE_Protocol_Info
*protocolinfo
,
57 ACE_TRACE ("ACE_SOCK_Connector::shared_open");
59 // Only open a new socket if we don't already have a valid handle.
60 if (new_stream
.get_handle () == ACE_INVALID_HANDLE
61 && new_stream
.open (SOCK_STREAM
,
74 ACE_SOCK_Connector::shared_connect_start (ACE_SOCK_Stream
&new_stream
,
75 const ACE_Time_Value
*timeout
,
76 const ACE_Addr
&local_sap
)
78 ACE_TRACE ("ACE_SOCK_Connector::shared_connect_start");
80 if (local_sap
!= ACE_Addr::sap_any
)
82 sockaddr
*laddr
= reinterpret_cast<sockaddr
*> (local_sap
.get_addr ());
83 int const size
= local_sap
.get_size ();
85 if (ACE_OS::bind (new_stream
.get_handle (), laddr
, size
) == -1)
87 // Save/restore errno.
88 ACE_Errno_Guard
error (errno
);
94 // Enable non-blocking, if required.
95 if (timeout
!= 0 && new_stream
.enable (ACE_NONBLOCK
) == -1)
102 ACE_SOCK_Connector::shared_connect_finish (ACE_SOCK_Stream
&new_stream
,
103 const ACE_Time_Value
*timeout
,
106 ACE_TRACE ("ACE_SOCK_Connector::shared_connect_finish");
107 // Save/restore errno.
108 ACE_Errno_Guard
error (errno
);
110 if (result
== -1 && timeout
!= 0)
112 // Check whether the connection is in progress.
113 if (error
== EINPROGRESS
|| error
== EWOULDBLOCK
)
115 // This expression checks if we were polling.
116 if (*timeout
== ACE_Time_Value::zero
)
118 #if defined(ACE_WIN32)
119 // In order to detect when the socket that has been
120 // bound to is in TIME_WAIT we need to do the connect
121 // (which will always return EWOULDBLOCK) and then do an
122 // ACE::handle_timed_complete() (with timeout==0,
123 // i.e. poll). This will do a select() on the handle
124 // which will immediately return with the handle in an
125 // error state. The error code is then retrieved with
126 // getsockopt(). Good sockets however will return from
127 // the select() with ETIME - in this case return
128 // EWOULDBLOCK so the wait strategy can complete the
130 if(ACE::handle_timed_complete (new_stream
.get_handle (),
131 timeout
) == ACE_INVALID_HANDLE
)
133 int const tmp
= errno
;
143 #else /* ACE_WIN32 */
145 #endif /* ACE_WIN32 */
147 // Wait synchronously using timeout.
148 else if (this->complete (new_stream
, 0, timeout
) == -1)
155 // EISCONN is treated specially since this routine may be used to
156 // check if we are already connected.
157 if (result
!= -1 || error
== EISCONN
)
159 // Start out with non-blocking disabled on the new_stream.
160 result
= new_stream
.disable (ACE_NONBLOCK
);
166 else if (!(error
== EWOULDBLOCK
|| error
== ETIMEDOUT
))
174 // Actively connect and produce a new ACE_SOCK_Stream if things go well...
176 ACE_SOCK_Connector::connect (ACE_SOCK_Stream
&new_stream
,
177 const ACE_Addr
&remote_sap
,
178 const ACE_Time_Value
*timeout
,
179 const ACE_Addr
&local_sap
,
185 ACE_TRACE ("ACE_SOCK_Connector::connect");
187 if (this->shared_open (new_stream
,
188 remote_sap
.get_type (),
192 else if (this->shared_connect_start (new_stream
,
197 #if defined(ACE_WIN32) && defined(ACE_HAS_IPV6)
198 // On windows, the IPv4-mapped IPv6 address format can only be used on a dual-stack socket.
199 const ACE_INET_Addr
& remote_address
= static_cast<const ACE_INET_Addr
&>(remote_sap
);
200 if (remote_address
.is_ipv4_mapped_ipv6()) {
202 ACE_OS::setsockopt(new_stream
.get_handle(),
210 int result
= ACE_OS::connect (new_stream
.get_handle (),
211 reinterpret_cast<sockaddr
*> (remote_sap
.get_addr ()),
212 remote_sap
.get_size ());
214 return this->shared_connect_finish (new_stream
, timeout
, result
);
218 ACE_SOCK_Connector::connect (ACE_SOCK_Stream
&new_stream
,
219 const ACE_Addr
&remote_sap
,
220 ACE_QoS_Params qos_params
,
221 const ACE_Time_Value
*timeout
,
222 const ACE_Addr
&local_sap
,
223 ACE_Protocol_Info
* protocolinfo
,
229 ACE_TRACE ("ACE_SOCK_Connector::connect");
231 if (this->shared_open (new_stream
,
232 remote_sap
.get_type (),
239 else if (this->shared_connect_start (new_stream
,
244 #if defined(ACE_WIN32) && defined(ACE_HAS_IPV6)
245 // On windows, the IPv4-mapped IPv6 address format can only be used on a dual-stack socket.
246 const ACE_INET_Addr
& remote_address
= static_cast<const ACE_INET_Addr
&>(remote_sap
);
247 if (remote_address
.is_ipv4_mapped_ipv6()) {
249 ACE_OS::setsockopt(new_stream
.get_handle(),
257 int result
= ACE_OS::connect (new_stream
.get_handle (),
258 reinterpret_cast<sockaddr
*> (remote_sap
.get_addr ()),
259 remote_sap
.get_size (),
262 return this->shared_connect_finish (new_stream
, timeout
, result
);
265 // Try to complete a non-blocking connection.
267 ACE_SOCK_Connector::complete (ACE_SOCK_Stream
&new_stream
,
268 ACE_Addr
*remote_sap
,
269 const ACE_Time_Value
*tv
)
271 ACE_TRACE ("ACE_SOCK_Connector::complete");
272 ACE_HANDLE h
= ACE::handle_timed_complete (new_stream
.get_handle (), tv
);
273 // We failed to get connected.
274 if (h
== ACE_INVALID_HANDLE
)
276 #if defined (ACE_NON_BLOCKING_BUG_DELAY) && ACE_NON_BLOCKING_BUG_DELAY > 0
277 // Win32 has a timing problem - if you check to see if the
278 // connection has completed too fast, it will fail - so wait
279 // <ACE_NON_BLOCKING_BUG_DELAY> microseconds to let it catch up
280 // then retry to see if it's a real failure.
281 ACE_Time_Value
time (0, ACE_NON_BLOCKING_BUG_DELAY
);
282 ACE_OS::sleep (time
);
283 h
= ACE::handle_timed_complete (new_stream
.get_handle (), tv
);
284 if (h
== ACE_INVALID_HANDLE
)
286 #endif /* ACE_NON_BLOCKING_BUG_DELAY */
287 // Save/restore errno.
288 ACE_Errno_Guard
error (errno
);
291 #if defined (ACE_NON_BLOCKING_BUG_DELAY) && ACE_NON_BLOCKING_BUG_DELAY > 0
293 #endif /* ACE_NON_BLOCKING_BUG_DELAY */
298 int len
= remote_sap
->get_size ();
299 sockaddr
*addr
= reinterpret_cast<sockaddr
*> (remote_sap
->get_addr ());
300 if (ACE_OS::getpeername (h
,
304 // Save/restore errno.
305 ACE_Errno_Guard
error (errno
);
311 // Start out with non-blocking disabled on the <new_stream>.
312 new_stream
.disable (ACE_NONBLOCK
);
316 ACE_SOCK_Connector::ACE_SOCK_Connector (ACE_SOCK_Stream
&new_stream
,
317 const ACE_Addr
&remote_sap
,
318 const ACE_Time_Value
*timeout
,
319 const ACE_Addr
&local_sap
,
325 ACE_TRACE ("ACE_SOCK_Connector::ACE_SOCK_Connector");
327 if (this->connect (new_stream
,
336 && !(errno
== EWOULDBLOCK
|| errno
== ETIME
|| errno
== ETIMEDOUT
))
337 ACELIB_ERROR ((LM_ERROR
,
339 ACE_TEXT ("ACE_SOCK_Connector::ACE_SOCK_Connector")));
342 ACE_SOCK_Connector::ACE_SOCK_Connector (ACE_SOCK_Stream
&new_stream
,
343 const ACE_Addr
&remote_sap
,
344 ACE_QoS_Params qos_params
,
345 const ACE_Time_Value
*timeout
,
346 const ACE_Addr
&local_sap
,
347 ACE_Protocol_Info
*protocolinfo
,
353 ACE_TRACE ("ACE_SOCK_Connector::ACE_SOCK_Connector");
355 if (this->connect (new_stream
,
366 && !(errno
== EWOULDBLOCK
|| errno
== ETIME
|| errno
== ETIMEDOUT
))
367 ACELIB_ERROR ((LM_ERROR
,
369 ACE_TEXT ("ACE_SOCK_Connector::ACE_SOCK_Connector")));
372 ACE_END_VERSIONED_NAMESPACE_DECL