Correct feature names
[ACE_TAO.git] / ACE / ace / SOCK_SEQPACK_Connector.cpp
blob92787f9a5e3fc83c5f86dcb7580af4640033d73c
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)
25 void
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 */
33 int
34 ACE_SOCK_SEQPACK_Connector::shared_open (ACE_SOCK_SEQPACK_Association &new_association,
35 int protocol_family,
36 int protocol,
37 int reuse_addr)
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,
47 #else
48 new_association.open (SOCK_SEQPACKET,
49 #endif /* ACE_HAS_LKSCTP */
50 protocol_family,
51 protocol,
52 reuse_addr) == -1)
53 return -1;
54 else
55 return 0;
58 int
59 ACE_SOCK_SEQPACK_Connector::shared_open (ACE_SOCK_SEQPACK_Association &new_association,
60 int protocol_family,
61 int protocol,
62 ACE_Protocol_Info *protocolinfo,
63 ACE_SOCK_GROUP g,
64 u_long flags,
65 int reuse_addr)
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,
73 #else
74 new_association.open (SOCK_SEQPACKET,
75 #endif /* ACE_HAS_LKSCTP */
76 protocol_family,
77 protocol,
78 protocolinfo,
80 flags,
81 reuse_addr) == -1)
82 return -1;
83 else
84 return 0;
87 int
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 (),
100 laddr,
101 size) == -1)
103 // Save/restore errno.
104 ACE_Errno_Guard error (errno);
105 new_association.close ();
106 return -1;
110 // Enable non-blocking, if required.
111 if (timeout != 0
112 && new_association.enable (ACE_NONBLOCK) == -1)
113 return -1;
114 else
115 return 0;
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
134 // addresses.
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))));
138 #else
139 ACE_NEW_NORETURN (local_inet_addrs, sockaddr_in[num_addresses]);
140 #endif
141 if (!local_inet_addrs)
142 return -1;
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;
150 sockaddr_in portst;
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])),
156 sizeof(sockaddr)))
158 ACE_Errno_Guard error (errno);
159 new_association.close ();
160 return -1;
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),
173 &sn))
175 ACE_Errno_Guard error (errno);
176 new_association.close ();
177 return -1;
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));
194 // bind other ifaces
195 if (sctp_bindx(new_association.get_handle(),
196 reinterpret_cast<sockaddr *> (local_sockaddr),
197 num_addresses - 1,
198 SCTP_BINDX_ADD_ADDR))
200 ACE_Errno_Guard error (errno);
201 new_association.close ();
202 return -1;
205 delete [] local_sockaddr;
207 #else
209 // Call bind
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 ();
218 return -1;
220 #endif /* ACE_HAS_LKSCTP */
222 #if defined (ACE_HAS_ALLOC_HOOKS)
223 ACE_Allocator::instance()->free(local_inet_addrs);
224 #else
225 delete [] local_inet_addrs;
226 #endif /* ACE_HAS_ALLOC_HOOKS */
229 // Enable non-blocking, if required.
230 if (timeout != 0
231 && new_association.enable (ACE_NONBLOCK) == -1)
232 return -1;
233 else
234 return 0;
238 ACE_SOCK_SEQPACK_Connector::shared_connect_finish (ACE_SOCK_SEQPACK_Association &new_association,
239 const ACE_Time_Value *timeout,
240 int result)
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)
253 error = EWOULDBLOCK;
254 // Wait synchronously using timeout.
255 else if (this->complete (new_association,
257 timeout) == -1)
258 error = errno;
259 else
260 return 0;
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 ();
272 return result;
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,
283 int reuse_addr,
284 int /* flags */,
285 int /* perms */,
286 int protocol)
288 ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::connect");
290 if (this->shared_open (new_association,
291 remote_sap.get_type (),
292 protocol,
293 reuse_addr) == -1)
294 return -1;
295 else if (this->shared_connect_start (new_association,
296 timeout,
297 local_sap) == -1)
298 return -1;
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,
305 timeout,
306 result);
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,
315 int reuse_addr,
316 int /* flags */,
317 int /* perms */,
318 int protocol)
320 ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::connect");
322 if (this->shared_open (new_association,
323 remote_sap.get_type (),
324 protocol,
325 reuse_addr) == -1)
326 return -1;
327 else if (this->shared_connect_start (new_association,
328 timeout,
329 local_sap) == -1)
330 return -1;
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,
337 timeout,
338 result);
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 (),
350 tv);
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 (),
362 tv);
363 if (h == ACE_INVALID_HANDLE)
365 #endif /* ACE_WIN32 */
366 // Save/restore errno.
367 ACE_Errno_Guard error (errno);
368 new_association.close ();
369 return -1;
370 #if defined (ACE_WIN32)
372 #endif /* ACE_WIN32 */
375 if (remote_sap != 0)
377 int len = remote_sap->get_size ();
378 sockaddr *addr = reinterpret_cast<sockaddr *> (remote_sap->get_addr ());
379 if (ACE_OS::getpeername (h,
380 addr,
381 &len) == -1)
383 // Save/restore errno.
384 ACE_Errno_Guard error (errno);
385 new_association.close ();
386 return -1;
390 // Start out with non-blocking disabled on the <new_association>.
391 new_association.disable (ACE_NONBLOCK);
392 return 0;
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,
399 int reuse_addr,
400 int flags,
401 int perms,
402 int protocol)
404 ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::ACE_SOCK_SEQPACK_Connector");
406 if (this->connect (new_association,
407 remote_sap,
408 timeout,
409 local_sap,
410 reuse_addr,
411 flags,
412 perms,
413 protocol) == -1
414 && timeout != 0
415 && !(errno == EWOULDBLOCK || errno == ETIME || errno == ETIMEDOUT))
416 ACELIB_ERROR ((LM_ERROR,
417 ACE_TEXT ("%p\n"),
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,
426 int reuse_addr,
427 int flags,
428 int perms,
429 int protocol)
431 ACE_TRACE ("ACE_SOCK_SEQPACK_Connector::ACE_SOCK_SEQPACK_Connector");
433 if (this->connect (new_association,
434 remote_sap,
435 timeout,
436 local_sap,
437 reuse_addr,
438 flags,
439 perms,
440 protocol) == -1
441 && timeout != 0
442 && !(errno == EWOULDBLOCK || errno == ETIME || errno == ETIMEDOUT))
443 ACELIB_ERROR ((LM_ERROR,
444 ACE_TEXT ("%p\n"),
445 ACE_TEXT ("ACE_SOCK_SEQPACK_Connector::ACE_SOCK_SEQPACK_Connector")));
448 ACE_END_VERSIONED_NAMESPACE_DECL