1 #include "ace/SOCK_SEQPACK_Connector.h"
3 #include "ace/INET_Addr.h"
4 #include "ace/Log_Category.h"
5 #include "ace/Time_Value.h"
6 #include "ace/OS_Memory.h"
7 #include "ace/OS_NS_string.h"
8 #include "ace/OS_NS_sys_socket.h"
9 #include "ace/os_include/os_fcntl.h"
11 #if defined (ACE_WIN32)
12 #include "ace/OS_NS_unistd.h"
13 #endif /* ACE_WIN32 */
15 #if !defined (__ACE_INLINE__)
16 #include "ace/SOCK_SEQPACK_Connector.inl"
17 #endif /* __ACE_INLINE__ */
19 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
21 ACE_ALLOC_HOOK_DEFINE(ACE_SOCK_SEQPACK_Connector
)
24 ACE_SOCK_SEQPACK_Connector::dump () const
26 #if defined (ACE_HAS_DUMP)
27 ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::dump");
28 #endif /* ACE_HAS_DUMP */
32 ACE_SOCK_SEQPACK_Connector::shared_open (ACE_SOCK_SEQPACK_Association
&new_association
,
37 ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::shared_open");
40 // Only open a new socket if we don't already have a valid handle.
41 if (new_association
.get_handle () == ACE_INVALID_HANDLE
&&
42 #if defined (ACE_HAS_LKSCTP)
43 new_association
.open (SOCK_STREAM
,
45 new_association
.open (SOCK_SEQPACKET
,
46 #endif /* ACE_HAS_LKSCTP */
56 ACE_SOCK_SEQPACK_Connector::shared_open (ACE_SOCK_SEQPACK_Association
&new_association
,
59 ACE_Protocol_Info
*protocolinfo
,
64 ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::shared_open");
66 // Only open a new socket if we don't already have a valid handle.
67 if (new_association
.get_handle () == ACE_INVALID_HANDLE
&&
68 #if defined (ACE_HAS_LKSCTP)
69 new_association
.open (SOCK_STREAM
,
71 new_association
.open (SOCK_SEQPACKET
,
72 #endif /* ACE_HAS_LKSCTP */
85 ACE_SOCK_SEQPACK_Connector::shared_connect_start (ACE_SOCK_SEQPACK_Association
&new_association
,
86 const ACE_Time_Value
*timeout
,
87 const ACE_Addr
&local_sap
)
89 ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::shared_connect_start");
91 if (local_sap
!= ACE_Addr::sap_any
)
93 sockaddr
*laddr
= reinterpret_cast<sockaddr
*> (local_sap
.get_addr ());
94 int size
= local_sap
.get_size ();
96 if (ACE_OS::bind (new_association
.get_handle (),
100 // Save/restore errno.
101 ACE_Errno_Guard
error (errno
);
102 new_association
.close ();
107 // Enable non-blocking, if required.
109 && new_association
.enable (ACE_NONBLOCK
) == -1)
115 // Multihomed version of same
117 ACE_SOCK_SEQPACK_Connector::shared_connect_start (ACE_SOCK_SEQPACK_Association
&new_association
,
118 const ACE_Time_Value
*timeout
,
119 const ACE_Multihomed_INET_Addr
&local_sap
)
121 ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::shared_connect_start");
123 if (local_sap
.ACE_Addr::operator!= (ACE_Addr::sap_any
))
125 // The total number of addresses is the number of secondary
126 // addresses plus one.
127 size_t num_addresses
= local_sap
.get_num_secondary_addresses() + 1;
129 // Create an array of sockaddr_in to hold the underlying
130 // representations of the primary and secondary
132 sockaddr_in
* local_inet_addrs
= 0;
133 #if defined(ACE_HAS_ALLOC_HOOKS)
134 ACE_ALLOCATOR_NORETURN (local_inet_addrs
, static_cast<sockaddr_in
*>(ACE_Allocator::instance()->malloc(sizeof(sockaddr_in
) * (num_addresses
))));
136 ACE_NEW_NORETURN (local_inet_addrs
, sockaddr_in
[num_addresses
]);
138 if (!local_inet_addrs
)
141 // Populate the array by invoking the get_addresses method on
142 // the Multihomed_INET_Addr
143 local_sap
.get_addresses(local_inet_addrs
, num_addresses
);
145 #if defined (ACE_HAS_LKSCTP)
146 sockaddr_in
*local_sockaddr
= 0;
148 int sn
= sizeof(sockaddr
);
150 // bind to the primary addr first
151 if (ACE_OS::bind(new_association
.get_handle (),
152 reinterpret_cast<sockaddr
*> (&(local_inet_addrs
[0])),
155 ACE_Errno_Guard
error (errno
);
156 new_association
.close ();
160 // do we need to bind multiple addrs
161 if (num_addresses
> 1)
163 // allocate enough memory to hold the number of secondary addrs
164 ACE_NEW_NORETURN(local_sockaddr
,
165 sockaddr_in
[num_addresses
- 1]);
167 // get sockaddr_in for the local handle
168 if (ACE_OS::getsockname(new_association
.get_handle (),
169 reinterpret_cast<sockaddr
*> (&portst
),
172 ACE_Errno_Guard
error (errno
);
173 new_association
.close ();
177 // set the local port # assigned by the os to every secondary addr
178 for (size_t i
= 1; i
< num_addresses
; i
++)
180 local_inet_addrs
[i
].sin_port
= portst
.sin_port
;
183 // copy all of the secondary addrs into a sockaddr structure
184 for (size_t i
= 0; i
< num_addresses
- 1; i
++)
186 ACE_OS::memcpy(&(local_sockaddr
[i
]),
187 &(local_inet_addrs
[i
+ 1]),
188 sizeof(sockaddr_in
));
192 if (sctp_bindx(new_association
.get_handle(),
193 reinterpret_cast<sockaddr
*> (local_sockaddr
),
195 SCTP_BINDX_ADD_ADDR
))
197 ACE_Errno_Guard
error (errno
);
198 new_association
.close ();
202 delete [] local_sockaddr
;
207 size_t name_len
= (sizeof (sockaddr_in
)) * num_addresses
;
208 if (ACE_OS::bind (new_association
.get_handle (),
209 reinterpret_cast<sockaddr
*> (local_inet_addrs
),
210 static_cast<int> (name_len
)) == -1)
212 // Save/restore errno.
213 ACE_Errno_Guard
error (errno
);
214 new_association
.close ();
217 #endif /* ACE_HAS_LKSCTP */
219 #if defined (ACE_HAS_ALLOC_HOOKS)
220 ACE_Allocator::instance()->free(local_inet_addrs
);
222 delete [] local_inet_addrs
;
223 #endif /* ACE_HAS_ALLOC_HOOKS */
226 // Enable non-blocking, if required.
228 && new_association
.enable (ACE_NONBLOCK
) == -1)
235 ACE_SOCK_SEQPACK_Connector::shared_connect_finish (ACE_SOCK_SEQPACK_Association
&new_association
,
236 const ACE_Time_Value
*timeout
,
239 ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::shared_connect_finish");
240 // Save/restore errno.
241 ACE_Errno_Guard
error (errno
);
243 if (result
== -1 && timeout
!= 0)
245 // Check whether the connection is in progress.
246 if (error
== EINPROGRESS
|| error
== EWOULDBLOCK
)
248 // This expression checks if we were polling.
249 if (*timeout
== ACE_Time_Value::zero
)
251 // Wait synchronously using timeout.
252 else if (this->complete (new_association
,
261 // EISCONN is treated specially since this routine may be used to
262 // check if we are already connected.
263 if (result
!= -1 || error
== EISCONN
)
264 // Start out with non-blocking disabled on the <new_association>.
265 new_association
.disable (ACE_NONBLOCK
);
266 else if (!(error
== EWOULDBLOCK
|| error
== ETIMEDOUT
))
267 new_association
.close ();
272 // Actively connect and produce a new ACE_SOCK_SEQPACK_Association if things go well...
276 ACE_SOCK_SEQPACK_Connector::connect (ACE_SOCK_SEQPACK_Association
&new_association
,
277 const ACE_Addr
&remote_sap
,
278 const ACE_Time_Value
*timeout
,
279 const ACE_Addr
&local_sap
,
285 ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::connect");
287 if (this->shared_open (new_association
,
288 remote_sap
.get_type (),
292 else if (this->shared_connect_start (new_association
,
297 int result
= ACE_OS::connect (new_association
.get_handle (),
298 reinterpret_cast<sockaddr
*> (remote_sap
.get_addr ()),
299 remote_sap
.get_size ());
301 return this->shared_connect_finish (new_association
,
306 // Multihomed version of same
308 ACE_SOCK_SEQPACK_Connector::connect (ACE_SOCK_SEQPACK_Association
&new_association
,
309 const ACE_Addr
&remote_sap
,
310 const ACE_Time_Value
*timeout
,
311 const ACE_Multihomed_INET_Addr
&local_sap
,
317 ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::connect");
319 if (this->shared_open (new_association
,
320 remote_sap
.get_type (),
324 else if (this->shared_connect_start (new_association
,
329 int result
= ACE_OS::connect (new_association
.get_handle (),
330 reinterpret_cast<sockaddr
*> (remote_sap
.get_addr ()),
331 remote_sap
.get_size ());
333 return this->shared_connect_finish (new_association
,
338 // Try to complete a non-blocking connection.
341 ACE_SOCK_SEQPACK_Connector::complete (ACE_SOCK_SEQPACK_Association
&new_association
,
342 ACE_Addr
*remote_sap
,
343 const ACE_Time_Value
*tv
)
345 ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::complete");
346 ACE_HANDLE h
= ACE::handle_timed_complete (new_association
.get_handle (),
348 // We failed to get connected.
349 if (h
== ACE_INVALID_HANDLE
)
351 #if defined (ACE_WIN32)
352 // Win32 has a timing problem - if you check to see if the
353 // connection has completed too fast, it will fail - so wait
354 // <ACE_NON_BLOCKING_BUG_DELAY> microseconds to let it catch up
355 // then retry to see if it's a real failure.
356 ACE_Time_Value
time (0, ACE_NON_BLOCKING_BUG_DELAY
);
357 ACE_OS::sleep (time
);
358 h
= ACE::handle_timed_complete (new_association
.get_handle (),
360 if (h
== ACE_INVALID_HANDLE
)
362 #endif /* ACE_WIN32 */
363 // Save/restore errno.
364 ACE_Errno_Guard
error (errno
);
365 new_association
.close ();
367 #if defined (ACE_WIN32)
369 #endif /* ACE_WIN32 */
374 int len
= remote_sap
->get_size ();
375 sockaddr
*addr
= reinterpret_cast<sockaddr
*> (remote_sap
->get_addr ());
376 if (ACE_OS::getpeername (h
,
380 // Save/restore errno.
381 ACE_Errno_Guard
error (errno
);
382 new_association
.close ();
387 // Start out with non-blocking disabled on the <new_association>.
388 new_association
.disable (ACE_NONBLOCK
);
392 ACE_SOCK_SEQPACK_Connector::ACE_SOCK_SEQPACK_Connector (ACE_SOCK_SEQPACK_Association
&new_association
,
393 const ACE_Addr
&remote_sap
,
394 const ACE_Time_Value
*timeout
,
395 const ACE_Addr
&local_sap
,
401 ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::ACE_SOCK_SEQPACK_Connector");
403 if (this->connect (new_association
,
412 && !(errno
== EWOULDBLOCK
|| errno
== ETIME
|| errno
== ETIMEDOUT
))
413 ACELIB_ERROR ((LM_ERROR
,
415 ACE_TEXT ("ACE_SOCK_SEQPACK_Connector::ACE_SOCK_SEQPACK_Connector")));
418 // Multihomed version of same
419 ACE_SOCK_SEQPACK_Connector::ACE_SOCK_SEQPACK_Connector (ACE_SOCK_SEQPACK_Association
&new_association
,
420 const ACE_Addr
&remote_sap
,
421 const ACE_Time_Value
*timeout
,
422 const ACE_Multihomed_INET_Addr
&local_sap
,
428 ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::ACE_SOCK_SEQPACK_Connector");
430 if (this->connect (new_association
,
439 && !(errno
== EWOULDBLOCK
|| errno
== ETIME
|| errno
== ETIMEDOUT
))
440 ACELIB_ERROR ((LM_ERROR
,
442 ACE_TEXT ("ACE_SOCK_SEQPACK_Connector::ACE_SOCK_SEQPACK_Connector")));
445 ACE_END_VERSIONED_NAMESPACE_DECL