Changes to attempt to silence bcc64x
[ACE_TAO.git] / ACE / ace / SOCK_SEQPACK_Connector.cpp
blobe2522863ed21deefcb66dac1703f50ecb7927612
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)
23 void
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 */
31 int
32 ACE_SOCK_SEQPACK_Connector::shared_open (ACE_SOCK_SEQPACK_Association &new_association,
33 int protocol_family,
34 int protocol,
35 int reuse_addr)
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,
44 #else
45 new_association.open (SOCK_SEQPACKET,
46 #endif /* ACE_HAS_LKSCTP */
47 protocol_family,
48 protocol,
49 reuse_addr) == -1)
50 return -1;
51 else
52 return 0;
55 int
56 ACE_SOCK_SEQPACK_Connector::shared_open (ACE_SOCK_SEQPACK_Association &new_association,
57 int protocol_family,
58 int protocol,
59 ACE_Protocol_Info *protocolinfo,
60 ACE_SOCK_GROUP g,
61 u_long flags,
62 int reuse_addr)
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,
70 #else
71 new_association.open (SOCK_SEQPACKET,
72 #endif /* ACE_HAS_LKSCTP */
73 protocol_family,
74 protocol,
75 protocolinfo,
77 flags,
78 reuse_addr) == -1)
79 return -1;
80 else
81 return 0;
84 int
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 (),
97 laddr,
98 size) == -1)
100 // Save/restore errno.
101 ACE_Errno_Guard error (errno);
102 new_association.close ();
103 return -1;
107 // Enable non-blocking, if required.
108 if (timeout != 0
109 && new_association.enable (ACE_NONBLOCK) == -1)
110 return -1;
111 else
112 return 0;
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
131 // addresses.
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))));
135 #else
136 ACE_NEW_NORETURN (local_inet_addrs, sockaddr_in[num_addresses]);
137 #endif
138 if (!local_inet_addrs)
139 return -1;
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;
147 sockaddr_in portst;
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])),
153 sizeof(sockaddr)))
155 ACE_Errno_Guard error (errno);
156 new_association.close ();
157 return -1;
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),
170 &sn))
172 ACE_Errno_Guard error (errno);
173 new_association.close ();
174 return -1;
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));
191 // bind other ifaces
192 if (sctp_bindx(new_association.get_handle(),
193 reinterpret_cast<sockaddr *> (local_sockaddr),
194 num_addresses - 1,
195 SCTP_BINDX_ADD_ADDR))
197 ACE_Errno_Guard error (errno);
198 new_association.close ();
199 return -1;
202 delete [] local_sockaddr;
204 #else
206 // Call bind
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 ();
215 return -1;
217 #endif /* ACE_HAS_LKSCTP */
219 #if defined (ACE_HAS_ALLOC_HOOKS)
220 ACE_Allocator::instance()->free(local_inet_addrs);
221 #else
222 delete [] local_inet_addrs;
223 #endif /* ACE_HAS_ALLOC_HOOKS */
226 // Enable non-blocking, if required.
227 if (timeout != 0
228 && new_association.enable (ACE_NONBLOCK) == -1)
229 return -1;
230 else
231 return 0;
235 ACE_SOCK_SEQPACK_Connector::shared_connect_finish (ACE_SOCK_SEQPACK_Association &new_association,
236 const ACE_Time_Value *timeout,
237 int result)
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)
250 error = EWOULDBLOCK;
251 // Wait synchronously using timeout.
252 else if (this->complete (new_association,
254 timeout) == -1)
255 error = errno;
256 else
257 return 0;
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 ();
269 return result;
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,
280 int reuse_addr,
281 int /* flags */,
282 int /* perms */,
283 int protocol)
285 ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::connect");
287 if (this->shared_open (new_association,
288 remote_sap.get_type (),
289 protocol,
290 reuse_addr) == -1)
291 return -1;
292 else if (this->shared_connect_start (new_association,
293 timeout,
294 local_sap) == -1)
295 return -1;
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,
302 timeout,
303 result);
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,
312 int reuse_addr,
313 int /* flags */,
314 int /* perms */,
315 int protocol)
317 ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::connect");
319 if (this->shared_open (new_association,
320 remote_sap.get_type (),
321 protocol,
322 reuse_addr) == -1)
323 return -1;
324 else if (this->shared_connect_start (new_association,
325 timeout,
326 local_sap) == -1)
327 return -1;
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,
334 timeout,
335 result);
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 (),
347 tv);
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 (),
359 tv);
360 if (h == ACE_INVALID_HANDLE)
362 #endif /* ACE_WIN32 */
363 // Save/restore errno.
364 ACE_Errno_Guard error (errno);
365 new_association.close ();
366 return -1;
367 #if defined (ACE_WIN32)
369 #endif /* ACE_WIN32 */
372 if (remote_sap != 0)
374 int len = remote_sap->get_size ();
375 sockaddr *addr = reinterpret_cast<sockaddr *> (remote_sap->get_addr ());
376 if (ACE_OS::getpeername (h,
377 addr,
378 &len) == -1)
380 // Save/restore errno.
381 ACE_Errno_Guard error (errno);
382 new_association.close ();
383 return -1;
387 // Start out with non-blocking disabled on the <new_association>.
388 new_association.disable (ACE_NONBLOCK);
389 return 0;
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,
396 int reuse_addr,
397 int flags,
398 int perms,
399 int protocol)
401 ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::ACE_SOCK_SEQPACK_Connector");
403 if (this->connect (new_association,
404 remote_sap,
405 timeout,
406 local_sap,
407 reuse_addr,
408 flags,
409 perms,
410 protocol) == -1
411 && timeout != 0
412 && !(errno == EWOULDBLOCK || errno == ETIME || errno == ETIMEDOUT))
413 ACELIB_ERROR ((LM_ERROR,
414 ACE_TEXT ("%p\n"),
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,
423 int reuse_addr,
424 int flags,
425 int perms,
426 int protocol)
428 ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::ACE_SOCK_SEQPACK_Connector");
430 if (this->connect (new_association,
431 remote_sap,
432 timeout,
433 local_sap,
434 reuse_addr,
435 flags,
436 perms,
437 protocol) == -1
438 && timeout != 0
439 && !(errno == EWOULDBLOCK || errno == ETIME || errno == ETIMEDOUT))
440 ACELIB_ERROR ((LM_ERROR,
441 ACE_TEXT ("%p\n"),
442 ACE_TEXT ("ACE_SOCK_SEQPACK_Connector::ACE_SOCK_SEQPACK_Connector")));
445 ACE_END_VERSIONED_NAMESPACE_DECL