Changes to attempt to silence bcc64x
[ACE_TAO.git] / ACE / ace / Asynch_Acceptor.cpp
blobeff953ef89abe3ad9dbf6160acf91423db809d83
1 /* -*- C++ -*- */
2 #ifndef ACE_ASYNCH_ACCEPTOR_C
3 #define ACE_ASYNCH_ACCEPTOR_C
5 #include "ace/Asynch_Acceptor.h"
7 #if !defined (ACE_LACKS_PRAGMA_ONCE)
8 # pragma once
9 #endif /* ACE_LACKS_PRAGMA_ONCE */
11 #if defined (ACE_HAS_WIN32_OVERLAPPED_IO) || defined (ACE_HAS_AIO_CALLS)
12 // This only works on platforms that support async i/o.
14 #include "ace/OS_Errno.h"
15 #include "ace/OS_Memory.h"
16 #include "ace/OS_NS_sys_socket.h"
17 #include "ace/Log_Category.h"
18 #include "ace/Message_Block.h"
19 #include "ace/INET_Addr.h"
20 #include "ace/SOCK_Stream.h"
21 #include "ace/Sock_Connect.h"
23 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
25 template <class HANDLER>
26 ACE_Asynch_Acceptor<HANDLER>::ACE_Asynch_Acceptor ()
27 : addr_family_ (0),
28 listen_handle_ (ACE_INVALID_HANDLE),
29 pass_addresses_ (false),
30 validate_new_connection_ (false),
31 reissue_accept_ (1),
32 bytes_to_read_ (0)
36 template <class HANDLER>
37 ACE_Asynch_Acceptor<HANDLER>::~ACE_Asynch_Acceptor ()
39 // Close down the listen socket
40 if (this->listen_handle_ != ACE_INVALID_HANDLE)
42 ACE_OS::closesocket (this->listen_handle_);
43 this->listen_handle_ = ACE_INVALID_HANDLE;
47 template <class HANDLER> int
48 ACE_Asynch_Acceptor<HANDLER>::open (const ACE_INET_Addr &address,
49 size_t bytes_to_read,
50 bool pass_addresses,
51 int backlog,
52 int reuse_addr,
53 ACE_Proactor *proactor,
54 bool validate_new_connection,
55 int reissue_accept,
56 int number_of_initial_accepts)
58 ACE_TRACE ("ACE_Asynch_Acceptor<>::open");
60 this->proactor (proactor);
61 this->pass_addresses_ = pass_addresses;
62 this->bytes_to_read_ = bytes_to_read;
63 this->validate_new_connection_ = validate_new_connection;
64 this->reissue_accept_ = reissue_accept;
65 this->addr_family_ = address.get_type ();
67 // Create the listener socket
68 this->listen_handle_ = ACE_OS::socket (address.get_type (), SOCK_STREAM, 0);
69 if (this->listen_handle_ == ACE_INVALID_HANDLE)
70 ACELIB_ERROR_RETURN ((LM_ERROR,
71 ACE_TEXT ("%p\n"),
72 ACE_TEXT ("ACE_OS::socket")),
73 -1);
74 // Initialize the ACE_Asynch_Accept
75 if (this->asynch_accept_.open (*this,
76 this->listen_handle_,
78 this->proactor ()) == -1)
80 ACE_Errno_Guard g (errno);
81 ACELIB_ERROR ((LM_ERROR,
82 ACE_TEXT ("%p\n"),
83 ACE_TEXT ("ACE_Asynch_Accept::open")));
84 ACE_OS::closesocket (this->listen_handle_);
85 this->listen_handle_ = ACE_INVALID_HANDLE;
86 return -1;
89 if (reuse_addr)
91 // Reuse the address
92 int one = 1;
93 if (ACE_OS::setsockopt (this->listen_handle_,
94 SOL_SOCKET,
95 SO_REUSEADDR,
96 (const char*) &one,
97 sizeof one) == -1)
99 ACE_Errno_Guard g (errno);
100 ACELIB_ERROR ((LM_ERROR,
101 ACE_TEXT ("%p\n"),
102 ACE_TEXT ("ACE_OS::setsockopt")));
103 ACE_OS::closesocket (this->listen_handle_);
104 this->listen_handle_ = ACE_INVALID_HANDLE;
105 return -1;
109 // If port is not specified, bind to any port.
110 static ACE_INET_Addr sa (ACE_sap_any_cast (const ACE_INET_Addr &));
112 if (address == sa &&
113 ACE::bind_port (this->listen_handle_,
114 INADDR_ANY,
115 address.get_type()) == -1)
117 ACE_Errno_Guard g (errno);
118 ACELIB_ERROR ((LM_ERROR,
119 ACE_TEXT ("%p\n"),
120 ACE_TEXT ("ACE::bind_port")));
121 ACE_OS::closesocket (this->listen_handle_);
122 this->listen_handle_ = ACE_INVALID_HANDLE;
123 return -1;
126 // Bind to the specified port.
127 if (ACE_OS::bind (this->listen_handle_,
128 reinterpret_cast<sockaddr *> (address.get_addr ()),
129 address.get_size ()) == -1)
131 ACE_Errno_Guard g (errno);
132 ACELIB_ERROR ((LM_ERROR,
133 ACE_TEXT ("%p\n"),
134 ACE_TEXT ("ACE_OS::bind")));
135 ACE_OS::closesocket (this->listen_handle_);
136 this->listen_handle_ = ACE_INVALID_HANDLE;
137 return -1;
140 // Start listening.
141 if (ACE_OS::listen (this->listen_handle_, backlog) == -1)
143 ACE_Errno_Guard g (errno);
144 ACELIB_ERROR ((LM_ERROR,
145 ACE_TEXT ("%p\n"),
146 ACE_TEXT ("ACE_OS::listen")));
147 ACE_OS::closesocket (this->listen_handle_);
148 this->listen_handle_ = ACE_INVALID_HANDLE;
149 return -1;
152 // For the number of <intial_accepts>.
153 if (number_of_initial_accepts == -1)
154 number_of_initial_accepts = backlog;
156 for (int i = 0; i < number_of_initial_accepts; i++)
158 // Initiate accepts.
159 if (this->accept (bytes_to_read) == -1)
161 ACE_Errno_Guard g (errno);
162 ACELIB_ERROR ((LM_ERROR,
163 ACE_TEXT ("%p\n"),
164 ACE_TEXT ("ACE_Asynch_Acceptor::accept")));
165 ACE_OS::closesocket (this->listen_handle_);
166 this->listen_handle_ = ACE_INVALID_HANDLE;
167 return -1;
171 return 0;
174 template <class HANDLER> int
175 ACE_Asynch_Acceptor<HANDLER>::set_handle (ACE_HANDLE listen_handle)
177 ACE_TRACE ("ACE_Asynch_Acceptor<>::set_handle");
179 // Take ownership of the <listen_handle>
180 this->listen_handle_ = listen_handle;
182 // Reinitialize the ACE_Asynch_Accept
183 if (this->asynch_accept_.open (*this,
184 this->listen_handle_,
186 this->proactor ()) == -1)
187 ACELIB_ERROR_RETURN ((LM_ERROR,
188 ACE_TEXT ("%p\n"),
189 ACE_TEXT ("ACE_Asynch_Accept::open")),
190 -1);
191 return 0;
194 template <class HANDLER> ACE_HANDLE
195 ACE_Asynch_Acceptor<HANDLER>::get_handle () const
197 return this->listen_handle_;
200 template <class HANDLER> int
201 ACE_Asynch_Acceptor<HANDLER>::accept (size_t bytes_to_read, const void *act)
203 ACE_TRACE ("ACE_Asynch_Acceptor<>::accept");
205 ACE_Message_Block *message_block = 0;
206 // The space_needed calculation is drive by needs of Windows. POSIX doesn't
207 // need to extra 16 bytes, but it doesn't hurt.
208 size_t space_needed = sizeof (sockaddr_in) + 16;
209 #if defined (ACE_HAS_IPV6)
210 if (PF_INET6 == this->addr_family_)
211 space_needed = sizeof (sockaddr_in6) + 16;
212 #endif /* ACE_HAS_IPV6 */
213 space_needed = (2 * space_needed) + bytes_to_read;
215 // Create a new message block big enough for the addresses and data
216 ACE_NEW_RETURN (message_block,
217 ACE_Message_Block (space_needed),
218 -1);
220 // Initiate asynchronous accepts
221 if (this->asynch_accept_.accept (*message_block,
222 bytes_to_read,
223 ACE_INVALID_HANDLE,
224 act,
226 ACE_SIGRTMIN,
227 this->addr_family_) == -1)
229 // Cleanup on error
230 message_block->release ();
231 return -1;
233 return 0;
236 template <class HANDLER> void
237 ACE_Asynch_Acceptor<HANDLER>::handle_accept (const ACE_Asynch_Accept::Result &result)
239 ACE_TRACE ("ACE_Asynch_Acceptor<>::handle_accept");
241 // Variable for error tracking
242 bool error = false;
244 // If the asynchronous accept fails.
245 if (!result.success () || result.accept_handle () == ACE_INVALID_HANDLE)
247 error = true;
250 #if defined (ACE_WIN32)
251 // In order to use accept handle with other Window Sockets 1.1
252 // functions, we call the setsockopt function with the
253 // SO_UPDATE_ACCEPT_CONTEXT option. This option initializes the
254 // socket so that other Windows Sockets routines to access the
255 // socket correctly.
256 if (!error &&
257 ACE_OS::setsockopt (result.accept_handle (),
258 SOL_SOCKET,
259 SO_UPDATE_ACCEPT_CONTEXT,
260 (char *) &this->listen_handle_,
261 sizeof (this->listen_handle_)) == -1)
263 error = true;
265 #endif /* ACE_WIN32 */
267 // Parse address.
268 ACE_INET_Addr local_address;
269 ACE_INET_Addr remote_address;
270 if (!error &&
271 (this->validate_new_connection_ || this->pass_addresses_))
272 // Parse the addresses.
273 this->parse_address (result,
274 remote_address,
275 local_address);
277 // Validate remote address
278 if (!error &&
279 this->validate_new_connection_ &&
280 (this->validate_connection (result, remote_address, local_address) == -1))
282 error = true;
285 HANDLER *new_handler = 0;
286 if (!error)
288 // The Template method
289 new_handler = this->make_handler ();
290 if (new_handler == 0)
292 error = true;
296 // If no errors
297 if (!error)
299 // Update the Proactor unless make_handler() or constructed handler
300 // set up its own.
301 if (new_handler->proactor () == 0)
302 new_handler->proactor (this->proactor ());
304 // Pass the addresses
305 if (this->pass_addresses_)
306 new_handler->addresses (remote_address,
307 local_address);
309 // Pass the ACT
310 if (result.act () != 0)
311 new_handler->act (result.act ());
313 // Set up the handler's new handle value
314 new_handler->handle (result.accept_handle ());
316 // Initiate the handler
317 new_handler->open (result.accept_handle (),
318 result.message_block ());
321 // On failure, no choice but to close the socket
322 if (error &&
323 result.accept_handle() != ACE_INVALID_HANDLE )
324 ACE_OS::closesocket (result.accept_handle ());
326 // Delete the dynamically allocated message_block
327 result.message_block ().release ();
329 // Start off another asynchronous accept to keep the backlog going,
330 // unless we closed the listen socket already (from the destructor),
331 // or this callback is the result of a canceled/aborted accept.
332 if (this->should_reissue_accept () &&
333 this->listen_handle_ != ACE_INVALID_HANDLE
334 #if defined (ACE_WIN32)
335 && result.error () != ERROR_OPERATION_ABORTED
336 #else
337 && result.error () != ECANCELED
338 #endif
340 this->accept (this->bytes_to_read_, result.act ());
343 template <class HANDLER> int
344 ACE_Asynch_Acceptor<HANDLER>::validate_connection
345 (const ACE_Asynch_Accept::Result& /* result */,
346 const ACE_INET_Addr& /* remote */,
347 const ACE_INET_Addr& /* local */)
349 // Default implementation always validates the remote address.
350 return 0;
353 template <class HANDLER> int
354 ACE_Asynch_Acceptor<HANDLER>::cancel ()
356 ACE_TRACE ("ACE_Asynch_Acceptor<>::cancel");
358 // All I/O operations that are canceled will complete with the error
359 // ERROR_OPERATION_ABORTED. All completion notifications for the I/O
360 // operations will occur normally.
361 #if defined (ACE_HAS_WIN32_OVERLAPPED_IO)
362 return (int) ::CancelIo (this->listen_handle_);
363 #else
364 // Supported now
365 return this->asynch_accept_.cancel();
366 #endif /* defined (ACE_HAS_WIN32_OVERLAPPED_IO) */
369 template <class HANDLER> void
370 ACE_Asynch_Acceptor<HANDLER>::parse_address (const
371 ACE_Asynch_Accept::Result &result,
372 ACE_INET_Addr &remote_address,
373 ACE_INET_Addr &local_address)
375 ACE_TRACE ("ACE_Asynch_Acceptor<>::parse_address");
377 #if defined (ACE_HAS_AIO_CALLS)
379 // Use an ACE_SOCK to get the addresses - it knows how to deal with
380 // ACE_INET_Addr objects and get IPv4/v6 addresses.
381 ACE_SOCK_Stream str (result.accept_handle ());
382 str.get_local_addr (local_address);
383 str.get_remote_addr (remote_address);
385 #elif defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
387 ACE_Message_Block &message_block = result.message_block ();
389 sockaddr *local_addr = 0;
390 sockaddr *remote_addr = 0;
391 int local_size = 0;
392 int remote_size = 0;
393 // This matches setup in accept().
394 size_t addr_size = sizeof (sockaddr_in) + 16;
395 #if defined (ACE_HAS_IPV6)
396 if (this->addr_family_ == PF_INET6)
397 addr_size = sizeof (sockaddr_in6) + 16;
398 #endif /* ACE_HAS_IPV6 */
400 ::GetAcceptExSockaddrs (message_block.rd_ptr (),
401 static_cast<DWORD> (this->bytes_to_read_),
402 static_cast<DWORD> (addr_size),
403 static_cast<DWORD> (addr_size),
404 &local_addr,
405 &local_size,
406 &remote_addr,
407 &remote_size);
409 local_address.set (reinterpret_cast<sockaddr_in *> (local_addr),
410 local_size);
411 remote_address.set (reinterpret_cast<sockaddr_in *> (remote_addr),
412 remote_size);
413 #else
414 // just in case
415 errno = ENOTSUP;
416 #endif /* defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) */
417 return;
420 template <class HANDLER> ACE_HANDLE
421 ACE_Asynch_Acceptor<HANDLER>::handle () const
423 return this->listen_handle_;
426 template <class HANDLER> void
427 ACE_Asynch_Acceptor<HANDLER>::handle (ACE_HANDLE h)
429 ACE_Handler::handle (h);
432 template <class HANDLER> ACE_Asynch_Accept &
433 ACE_Asynch_Acceptor<HANDLER>::asynch_accept ()
435 return this->asynch_accept_;
438 template <class HANDLER> HANDLER *
439 ACE_Asynch_Acceptor<HANDLER>::make_handler ()
441 // Default behavior
442 HANDLER *handler = 0;
443 ACE_NEW_RETURN (handler,
444 HANDLER,
446 return handler;
449 template <class HANDLER> bool
450 ACE_Asynch_Acceptor<HANDLER>::pass_addresses () const
452 return this->pass_addresses_;
455 template <class HANDLER> void
456 ACE_Asynch_Acceptor<HANDLER>::pass_addresses (bool new_value)
458 this->pass_addresses_ = new_value;
461 template <class HANDLER> bool
462 ACE_Asynch_Acceptor<HANDLER>::validate_new_connection () const
464 return this->validate_new_connection_;
467 template <class HANDLER> void
468 ACE_Asynch_Acceptor<HANDLER>::validate_new_connection (bool new_value)
470 this->validate_new_connection_ = new_value;
473 template <class HANDLER> int
474 ACE_Asynch_Acceptor<HANDLER>::reissue_accept () const
476 return this->reissue_accept_;
479 template <class HANDLER> void
480 ACE_Asynch_Acceptor<HANDLER>::reissue_accept (int new_value)
482 this->reissue_accept_ = new_value;
485 template <class HANDLER> size_t
486 ACE_Asynch_Acceptor<HANDLER>::bytes_to_read () const
488 return this->bytes_to_read_;
491 template <class HANDLER> void
492 ACE_Asynch_Acceptor<HANDLER>::bytes_to_read (size_t new_value)
494 this->bytes_to_read_ = new_value;
497 template <class HANDLER> int
498 ACE_Asynch_Acceptor<HANDLER>::should_reissue_accept ()
500 return this->reissue_accept_;
503 ACE_END_VERSIONED_NAMESPACE_DECL
505 #endif /* ACE_WIN32 || ACE_HAS_AIO_CALLS */
506 #endif /* ACE_ASYNCH_ACCEPTOR_C */