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__ */
21 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
23 ACE_ALLOC_HOOK_DEFINE(ACE_SOCK_SEQPACK_Connector
)
26 ACE_SOCK_SEQPACK_Connector::dump (void) const
28 #if defined (ACE_HAS_DUMP)
29 ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::dump");
30 #endif /* ACE_HAS_DUMP */
34 ACE_SOCK_SEQPACK_Connector::shared_open (ACE_SOCK_SEQPACK_Association
&new_association
,
39 ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::shared_open");
43 // Only open a new socket if we don't already have a valid handle.
44 if (new_association
.get_handle () == ACE_INVALID_HANDLE
&&
45 #if defined (ACE_HAS_LKSCTP)
46 new_association
.open (SOCK_STREAM
,
48 new_association
.open (SOCK_SEQPACKET
,
49 #endif /* ACE_HAS_LKSCTP */
59 ACE_SOCK_SEQPACK_Connector::shared_open (ACE_SOCK_SEQPACK_Association
&new_association
,
62 ACE_Protocol_Info
*protocolinfo
,
67 ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::shared_open");
69 // Only open a new socket if we don't already have a valid handle.
70 if (new_association
.get_handle () == ACE_INVALID_HANDLE
&&
71 #if defined (ACE_HAS_LKSCTP)
72 new_association
.open (SOCK_STREAM
,
74 new_association
.open (SOCK_SEQPACKET
,
75 #endif /* ACE_HAS_LKSCTP */
88 ACE_SOCK_SEQPACK_Connector::shared_connect_start (ACE_SOCK_SEQPACK_Association
&new_association
,
89 const ACE_Time_Value
*timeout
,
90 const ACE_Addr
&local_sap
)
92 ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::shared_connect_start");
94 if (local_sap
!= ACE_Addr::sap_any
)
96 sockaddr
*laddr
= reinterpret_cast<sockaddr
*> (local_sap
.get_addr ());
97 int size
= local_sap
.get_size ();
99 if (ACE_OS::bind (new_association
.get_handle (),
103 // Save/restore errno.
104 ACE_Errno_Guard
error (errno
);
105 new_association
.close ();
110 // Enable non-blocking, if required.
112 && new_association
.enable (ACE_NONBLOCK
) == -1)
118 // Multihomed version of same
120 ACE_SOCK_SEQPACK_Connector::shared_connect_start (ACE_SOCK_SEQPACK_Association
&new_association
,
121 const ACE_Time_Value
*timeout
,
122 const ACE_Multihomed_INET_Addr
&local_sap
)
124 ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::shared_connect_start");
126 if (local_sap
.ACE_Addr::operator!= (ACE_Addr::sap_any
))
128 // The total number of addresses is the number of secondary
129 // addresses plus one.
130 size_t num_addresses
= local_sap
.get_num_secondary_addresses() + 1;
132 // Create an array of sockaddr_in to hold the underlying
133 // representations of the primary and secondary
135 sockaddr_in
* local_inet_addrs
= 0;
136 #if defined(ACE_HAS_ALLOC_HOOKS)
137 ACE_ALLOCATOR_NORETURN (local_inet_addrs
, static_cast<sockaddr_in
*>(ACE_Allocator::instance()->malloc(sizeof(sockaddr_in
) * (num_addresses
))));
139 ACE_NEW_NORETURN (local_inet_addrs
, sockaddr_in
[num_addresses
]);
141 if (!local_inet_addrs
)
144 // Populate the array by invoking the get_addresses method on
145 // the Multihomed_INET_Addr
146 local_sap
.get_addresses(local_inet_addrs
, num_addresses
);
148 #if defined (ACE_HAS_LKSCTP)
149 sockaddr_in
*local_sockaddr
= 0;
151 int sn
= sizeof(sockaddr
);
153 // bind to the primary addr first
154 if (ACE_OS::bind(new_association
.get_handle (),
155 reinterpret_cast<sockaddr
*> (&(local_inet_addrs
[0])),
158 ACE_Errno_Guard
error (errno
);
159 new_association
.close ();
163 // do we need to bind multiple addrs
164 if (num_addresses
> 1)
166 // allocate enough memory to hold the number of secondary addrs
167 ACE_NEW_NORETURN(local_sockaddr
,
168 sockaddr_in
[num_addresses
- 1]);
170 // get sockaddr_in for the local handle
171 if (ACE_OS::getsockname(new_association
.get_handle (),
172 reinterpret_cast<sockaddr
*> (&portst
),
175 ACE_Errno_Guard
error (errno
);
176 new_association
.close ();
180 // set the local port # assigned by the os to every secondary addr
181 for (size_t i
= 1; i
< num_addresses
; i
++)
183 local_inet_addrs
[i
].sin_port
= portst
.sin_port
;
186 // copy all of the secondary addrs into a sockaddr structure
187 for (size_t i
= 0; i
< num_addresses
- 1; i
++)
189 ACE_OS::memcpy(&(local_sockaddr
[i
]),
190 &(local_inet_addrs
[i
+ 1]),
191 sizeof(sockaddr_in
));
195 if (sctp_bindx(new_association
.get_handle(),
196 reinterpret_cast<sockaddr
*> (local_sockaddr
),
198 SCTP_BINDX_ADD_ADDR
))
200 ACE_Errno_Guard
error (errno
);
201 new_association
.close ();
205 delete [] local_sockaddr
;
210 size_t name_len
= (sizeof (sockaddr_in
)) * num_addresses
;
211 if (ACE_OS::bind (new_association
.get_handle (),
212 reinterpret_cast<sockaddr
*> (local_inet_addrs
),
213 static_cast<int> (name_len
)) == -1)
215 // Save/restore errno.
216 ACE_Errno_Guard
error (errno
);
217 new_association
.close ();
220 #endif /* ACE_HAS_LKSCTP */
222 #if defined (ACE_HAS_ALLOC_HOOKS)
223 ACE_Allocator::instance()->free(local_inet_addrs
);
225 delete [] local_inet_addrs
;
226 #endif /* ACE_HAS_ALLOC_HOOKS */
229 // Enable non-blocking, if required.
231 && new_association
.enable (ACE_NONBLOCK
) == -1)
238 ACE_SOCK_SEQPACK_Connector::shared_connect_finish (ACE_SOCK_SEQPACK_Association
&new_association
,
239 const ACE_Time_Value
*timeout
,
242 ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::shared_connect_finish");
243 // Save/restore errno.
244 ACE_Errno_Guard
error (errno
);
246 if (result
== -1 && timeout
!= 0)
248 // Check whether the connection is in progress.
249 if (error
== EINPROGRESS
|| error
== EWOULDBLOCK
)
251 // This expression checks if we were polling.
252 if (*timeout
== ACE_Time_Value::zero
)
254 // Wait synchronously using timeout.
255 else if (this->complete (new_association
,
264 // EISCONN is treated specially since this routine may be used to
265 // check if we are already connected.
266 if (result
!= -1 || error
== EISCONN
)
267 // Start out with non-blocking disabled on the <new_association>.
268 new_association
.disable (ACE_NONBLOCK
);
269 else if (!(error
== EWOULDBLOCK
|| error
== ETIMEDOUT
))
270 new_association
.close ();
275 // Actively connect and produce a new ACE_SOCK_SEQPACK_Association if things go well...
279 ACE_SOCK_SEQPACK_Connector::connect (ACE_SOCK_SEQPACK_Association
&new_association
,
280 const ACE_Addr
&remote_sap
,
281 const ACE_Time_Value
*timeout
,
282 const ACE_Addr
&local_sap
,
288 ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::connect");
290 if (this->shared_open (new_association
,
291 remote_sap
.get_type (),
295 else if (this->shared_connect_start (new_association
,
300 int result
= ACE_OS::connect (new_association
.get_handle (),
301 reinterpret_cast<sockaddr
*> (remote_sap
.get_addr ()),
302 remote_sap
.get_size ());
304 return this->shared_connect_finish (new_association
,
309 // Multihomed version of same
311 ACE_SOCK_SEQPACK_Connector::connect (ACE_SOCK_SEQPACK_Association
&new_association
,
312 const ACE_Addr
&remote_sap
,
313 const ACE_Time_Value
*timeout
,
314 const ACE_Multihomed_INET_Addr
&local_sap
,
320 ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::connect");
322 if (this->shared_open (new_association
,
323 remote_sap
.get_type (),
327 else if (this->shared_connect_start (new_association
,
332 int result
= ACE_OS::connect (new_association
.get_handle (),
333 reinterpret_cast<sockaddr
*> (remote_sap
.get_addr ()),
334 remote_sap
.get_size ());
336 return this->shared_connect_finish (new_association
,
341 // Try to complete a non-blocking connection.
344 ACE_SOCK_SEQPACK_Connector::complete (ACE_SOCK_SEQPACK_Association
&new_association
,
345 ACE_Addr
*remote_sap
,
346 const ACE_Time_Value
*tv
)
348 ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::complete");
349 ACE_HANDLE h
= ACE::handle_timed_complete (new_association
.get_handle (),
351 // We failed to get connected.
352 if (h
== ACE_INVALID_HANDLE
)
354 #if defined (ACE_WIN32)
355 // Win32 has a timing problem - if you check to see if the
356 // connection has completed too fast, it will fail - so wait
357 // <ACE_NON_BLOCKING_BUG_DELAY> microseconds to let it catch up
358 // then retry to see if it's a real failure.
359 ACE_Time_Value
time (0, ACE_NON_BLOCKING_BUG_DELAY
);
360 ACE_OS::sleep (time
);
361 h
= ACE::handle_timed_complete (new_association
.get_handle (),
363 if (h
== ACE_INVALID_HANDLE
)
365 #endif /* ACE_WIN32 */
366 // Save/restore errno.
367 ACE_Errno_Guard
error (errno
);
368 new_association
.close ();
370 #if defined (ACE_WIN32)
372 #endif /* ACE_WIN32 */
377 int len
= remote_sap
->get_size ();
378 sockaddr
*addr
= reinterpret_cast<sockaddr
*> (remote_sap
->get_addr ());
379 if (ACE_OS::getpeername (h
,
383 // Save/restore errno.
384 ACE_Errno_Guard
error (errno
);
385 new_association
.close ();
390 // Start out with non-blocking disabled on the <new_association>.
391 new_association
.disable (ACE_NONBLOCK
);
395 ACE_SOCK_SEQPACK_Connector::ACE_SOCK_SEQPACK_Connector (ACE_SOCK_SEQPACK_Association
&new_association
,
396 const ACE_Addr
&remote_sap
,
397 const ACE_Time_Value
*timeout
,
398 const ACE_Addr
&local_sap
,
404 ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::ACE_SOCK_SEQPACK_Connector");
406 if (this->connect (new_association
,
415 && !(errno
== EWOULDBLOCK
|| errno
== ETIME
|| errno
== ETIMEDOUT
))
416 ACELIB_ERROR ((LM_ERROR
,
418 ACE_TEXT ("ACE_SOCK_SEQPACK_Connector::ACE_SOCK_SEQPACK_Connector")));
421 // Multihomed version of same
422 ACE_SOCK_SEQPACK_Connector::ACE_SOCK_SEQPACK_Connector (ACE_SOCK_SEQPACK_Association
&new_association
,
423 const ACE_Addr
&remote_sap
,
424 const ACE_Time_Value
*timeout
,
425 const ACE_Multihomed_INET_Addr
&local_sap
,
431 ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::ACE_SOCK_SEQPACK_Connector");
433 if (this->connect (new_association
,
442 && !(errno
== EWOULDBLOCK
|| errno
== ETIME
|| errno
== ETIMEDOUT
))
443 ACELIB_ERROR ((LM_ERROR
,
445 ACE_TEXT ("ACE_SOCK_SEQPACK_Connector::ACE_SOCK_SEQPACK_Connector")));
448 ACE_END_VERSIONED_NAMESPACE_DECL