Changes to attempt to silence bcc64x
[ACE_TAO.git] / ACE / ace / WIN32_Asynch_IO.cpp
blobd445397f90e2b088a617825e96af83da68d38d15
1 #include "ace/WIN32_Asynch_IO.h"
3 #if defined (ACE_HAS_WIN32_OVERLAPPED_IO) && \
4 (defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 == 1))
6 #include "ace/WIN32_Proactor.h"
7 #include "ace/Proactor.h"
8 #include "ace/Message_Block.h"
9 #include "ace/Service_Config.h"
10 #include "ace/Flag_Manip.h"
11 #include "ace/INET_Addr.h"
12 #include "ace/Task_T.h"
13 #include "ace/OS_NS_errno.h"
14 #include "ace/OS_NS_unistd.h"
15 #include "ace/OS_NS_sys_socket.h"
17 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
19 size_t
20 ACE_WIN32_Asynch_Result::bytes_transferred () const
22 return this->bytes_transferred_;
25 const void *
26 ACE_WIN32_Asynch_Result::act () const
28 return this->act_;
31 int
32 ACE_WIN32_Asynch_Result::success () const
34 return this->success_;
37 const void *
38 ACE_WIN32_Asynch_Result::completion_key () const
40 return this->completion_key_;
43 u_long
44 ACE_WIN32_Asynch_Result::error () const
46 return this->error_;
49 ACE_HANDLE
50 ACE_WIN32_Asynch_Result::event () const
52 return this->hEvent;
55 u_long
56 ACE_WIN32_Asynch_Result::offset () const
58 return this->Offset;
61 u_long
62 ACE_WIN32_Asynch_Result::offset_high () const
64 return this->OffsetHigh;
67 int
68 ACE_WIN32_Asynch_Result::priority () const
70 ACE_NOTSUP_RETURN (0);
73 int
74 ACE_WIN32_Asynch_Result::signal_number () const
76 ACE_NOTSUP_RETURN (0);
79 int
80 ACE_WIN32_Asynch_Result::post_completion (ACE_Proactor_Impl *proactor)
82 // Get to the platform specific implementation.
83 ACE_WIN32_Proactor *win32_proactor = dynamic_cast<ACE_WIN32_Proactor *> (proactor);
85 if (win32_proactor == 0)
86 ACELIB_ERROR_RETURN ((LM_ERROR,
87 ACE_TEXT ("Dynamic cast to WIN32 Proactor failed\n")),
88 -1);
90 // Post myself.
91 return win32_proactor->post_completion (this);
94 void
95 ACE_WIN32_Asynch_Result::set_bytes_transferred (size_t nbytes)
97 this->bytes_transferred_ = nbytes;
100 void
101 ACE_WIN32_Asynch_Result::set_error (u_long errcode)
103 this->error_ = errcode;
106 ACE_WIN32_Asynch_Result::~ACE_WIN32_Asynch_Result ()
110 ACE_WIN32_Asynch_Result::ACE_WIN32_Asynch_Result
111 (const ACE_Handler::Proxy_Ptr &handler_proxy,
112 const void* act,
113 ACE_HANDLE event,
114 u_long offset,
115 u_long offset_high,
116 int priority,
117 int signal_number)
118 : ACE_Asynch_Result_Impl (),
119 OVERLAPPED (),
120 handler_proxy_ (handler_proxy),
121 act_ (act),
122 bytes_transferred_ (0),
123 success_ (0),
124 completion_key_ (0),
125 error_ (0)
127 // Set the ACE_OVERLAPPED structure
128 this->Internal = 0;
129 this->InternalHigh = 0;
130 this->Offset = offset;
131 this->OffsetHigh = offset_high;
132 this->hEvent = event;
134 ACE_UNUSED_ARG (priority);
135 ACE_UNUSED_ARG (signal_number);
139 ACE_WIN32_Asynch_Operation::open (const ACE_Handler::Proxy_Ptr &handler_proxy,
140 ACE_HANDLE handle,
141 const void *completion_key,
142 ACE_Proactor *proactor)
144 this->proactor_ = proactor;
145 this->handler_proxy_ = handler_proxy;
146 this->handle_ = handle;
148 // Grab the handle from the <handler> if <handle> is invalid
149 if (this->handle_ == ACE_INVALID_HANDLE)
151 ACE_Handler *handler = handler_proxy.get ()->handler ();
152 if (handler != 0)
153 this->handle_ = handler->handle ();
155 if (this->handle_ == ACE_INVALID_HANDLE)
156 return -1;
158 if (this->proactor_!= 0)
159 // update implementation.
160 this->win32_proactor_ =
161 dynamic_cast <ACE_WIN32_Proactor *>(this->proactor_->implementation ());
163 // Register with the <proactor>.
164 return this->win32_proactor_->register_handle (this->handle_,
165 completion_key);
169 ACE_WIN32_Asynch_Operation::cancel ()
171 #if defined (ACE_HAS_CANCEL_IO)
172 // All I/O operations that are canceled will complete with the error
173 // ERROR_OPERATION_ABORTED. All completion notifications for the I/O
174 // operations will occur normally.
176 #if (_WIN32_WINNT < 0x0600)
177 int const result = (int) ::CancelIo (this->handle_);
178 #else
179 int const result = (int) ::CancelIoEx (this->handle_, 0);
180 #endif // < _WIN32_WINNT_VISTA
181 if (result == 0)
182 // Couldn't cancel the operations.
183 return 2;
185 // result is non-zero. All the operations are cancelled then.
186 return 0;
187 #else /* !ACE_HAS_CANCEL_IO */
188 ACE_NOTSUP_RETURN (-1);
189 #endif /* ACE_HAS_CANCEL_IO */
192 ACE_Proactor *
193 ACE_WIN32_Asynch_Operation::proactor () const
195 return this->proactor_;
198 ACE_WIN32_Asynch_Operation::ACE_WIN32_Asynch_Operation (ACE_WIN32_Proactor *win32_proactor)
199 : ACE_Asynch_Operation_Impl (),
200 win32_proactor_ (win32_proactor),
201 proactor_ (0),
202 handle_ (ACE_INVALID_HANDLE)
206 ACE_WIN32_Asynch_Operation::~ACE_WIN32_Asynch_Operation ()
210 // ************************************************************
212 size_t
213 ACE_WIN32_Asynch_Read_Stream_Result::bytes_to_read () const
215 return this->bytes_to_read_;
218 ACE_Message_Block &
219 ACE_WIN32_Asynch_Read_Stream_Result::message_block () const
221 return this->message_block_;
224 ACE_HANDLE
225 ACE_WIN32_Asynch_Read_Stream_Result::handle () const
227 return this->handle_;
230 ACE_WIN32_Asynch_Read_Stream_Result::ACE_WIN32_Asynch_Read_Stream_Result (
231 const ACE_Handler::Proxy_Ptr &handler_proxy,
232 ACE_HANDLE handle,
233 ACE_Message_Block &message_block,
234 size_t bytes_to_read,
235 const void* act,
236 ACE_HANDLE event,
237 int priority,
238 int signal_number,
239 int scatter_enabled)
240 : ACE_Asynch_Result_Impl (),
241 ACE_Asynch_Read_Stream_Result_Impl (),
242 ACE_WIN32_Asynch_Result (handler_proxy,
243 act,
244 event,
247 priority,
248 signal_number),
249 bytes_to_read_ (bytes_to_read),
250 message_block_ (message_block),
251 handle_ (handle),
252 scatter_enabled_ (scatter_enabled)
256 void
257 ACE_WIN32_Asynch_Read_Stream_Result::complete (size_t bytes_transferred,
258 int success,
259 const void *completion_key,
260 u_long error)
262 // Copy the data which was returned by GetQueuedCompletionStatus
263 this->bytes_transferred_ = bytes_transferred;
264 this->success_ = success;
265 this->completion_key_ = completion_key;
266 this->error_ = error;
268 // Appropriately move the pointers in the message block.
269 if (!this->scatter_enabled ())
270 this->message_block_.wr_ptr (bytes_transferred);
271 else
273 for (ACE_Message_Block* mb = &this->message_block_;
274 (mb != 0) && (bytes_transferred > 0);
275 mb = mb->cont ())
277 size_t len_part = mb->space ();
279 if (len_part > bytes_transferred)
280 len_part = bytes_transferred;
282 mb->wr_ptr (len_part);
284 bytes_transferred -= len_part;
288 // Create the interface result class.
289 ACE_Asynch_Read_Stream::Result result (this);
291 // Call the application handler.
292 ACE_Handler *handler = this->handler_proxy_.get ()->handler ();
293 if (handler != 0)
294 handler->handle_read_stream (result);
297 ACE_WIN32_Asynch_Read_Stream_Result::~ACE_WIN32_Asynch_Read_Stream_Result ()
301 // Base class operations. These operations are here to kill dominance
302 // warnings. These methods call the base class methods.
304 size_t
305 ACE_WIN32_Asynch_Read_Stream_Result::bytes_transferred () const
307 return ACE_WIN32_Asynch_Result::bytes_transferred ();
310 const void *
311 ACE_WIN32_Asynch_Read_Stream_Result::act () const
313 return ACE_WIN32_Asynch_Result::act ();
317 ACE_WIN32_Asynch_Read_Stream_Result::success () const
319 return ACE_WIN32_Asynch_Result::success ();
322 const void *
323 ACE_WIN32_Asynch_Read_Stream_Result::completion_key () const
325 return ACE_WIN32_Asynch_Result::completion_key ();
328 u_long
329 ACE_WIN32_Asynch_Read_Stream_Result::error () const
331 return ACE_WIN32_Asynch_Result::error ();
334 ACE_HANDLE
335 ACE_WIN32_Asynch_Read_Stream_Result::event () const
337 return ACE_WIN32_Asynch_Result::event ();
340 u_long
341 ACE_WIN32_Asynch_Read_Stream_Result::offset () const
343 return ACE_WIN32_Asynch_Result::offset ();
346 u_long
347 ACE_WIN32_Asynch_Read_Stream_Result::offset_high () const
349 return ACE_WIN32_Asynch_Result::offset_high ();
353 ACE_WIN32_Asynch_Read_Stream_Result::priority () const
355 return ACE_WIN32_Asynch_Result::priority ();
359 ACE_WIN32_Asynch_Read_Stream_Result::signal_number () const
361 return ACE_WIN32_Asynch_Result::signal_number ();
365 ACE_WIN32_Asynch_Read_Stream_Result::post_completion (ACE_Proactor_Impl *proactor)
367 return ACE_WIN32_Asynch_Result::post_completion (proactor);
371 ACE_WIN32_Asynch_Read_Stream_Result::scatter_enabled () const
373 return this->scatter_enabled_;
376 ACE_WIN32_Asynch_Read_Stream::ACE_WIN32_Asynch_Read_Stream (ACE_WIN32_Proactor *win32_proactor)
377 : ACE_Asynch_Operation_Impl (),
378 ACE_Asynch_Read_Stream_Impl (),
379 ACE_WIN32_Asynch_Operation (win32_proactor)
384 ACE_WIN32_Asynch_Read_Stream::read (ACE_Message_Block &message_block,
385 size_t bytes_to_read,
386 const void *act,
387 int priority,
388 int signal_number)
390 size_t space = message_block.space ();
391 if (bytes_to_read > space)
392 bytes_to_read = space;
394 if (bytes_to_read == 0)
396 errno = ENOSPC;
397 return -1;
400 // Create the Asynch_Result.
401 ACE_WIN32_Asynch_Read_Stream_Result *result = 0;
402 ACE_NEW_RETURN (result,
403 ACE_WIN32_Asynch_Read_Stream_Result (this->handler_proxy_,
404 this->handle_,
405 message_block,
406 bytes_to_read,
407 act,
408 this->win32_proactor_->get_handle (),
409 priority,
410 signal_number),
411 -1);
413 // Shared read
414 int const return_val = this->shared_read (result);
416 // Upon errors
417 if (return_val == -1)
418 delete result;
420 return return_val;
424 ACE_WIN32_Asynch_Read_Stream::readv (ACE_Message_Block &message_block,
425 size_t bytes_to_read,
426 const void *act,
427 int priority,
428 int signal_number)
430 #if (defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0))
431 iovec iov[ACE_IOV_MAX];
432 int iovcnt = 0;
434 // We should not read more than user requested,
435 // but it is allowed to read less
437 for (const ACE_Message_Block* msg = &message_block;
438 msg != 0 && bytes_to_read > 0 && iovcnt < ACE_IOV_MAX;
439 msg = msg->cont () , ++iovcnt )
441 size_t msg_space = msg->space ();
443 // OS should correctly process zero length buffers
444 // if ( msg_space == 0 )
445 // ACELIB_ERROR_RETURN ((LM_ERROR,
446 // ACE_TEXT ("ACE_WIN32_Asynch_Read_Stream::readv:")
447 // ACE_TEXT ("No space in the message block\n")),
448 // -1);
450 if (msg_space > bytes_to_read)
451 msg_space = bytes_to_read;
452 bytes_to_read -= msg_space;
454 // Make as many iovec as needed to fit all of msg_space.
455 size_t wr_ptr_offset = 0;
457 while (msg_space > 0 && iovcnt < ACE_IOV_MAX)
459 u_long this_chunk_length;
460 if (msg_space > ULONG_MAX)
461 this_chunk_length = ULONG_MAX;
462 else
463 this_chunk_length = static_cast<u_long> (msg_space);
464 // Collect the data in the iovec.
465 iov[iovcnt].iov_base = msg->wr_ptr () + wr_ptr_offset;
466 iov[iovcnt].iov_len = this_chunk_length;
467 msg_space -= this_chunk_length;
468 wr_ptr_offset += this_chunk_length;
470 // Increment iovec counter if there's more to do.
471 if (msg_space > 0)
472 ++iovcnt;
474 if (msg_space > 0) // Ran out of iovecs before msg_space exhausted
476 errno = ERANGE;
477 return -1;
481 // Re-calculate number bytes to read
482 bytes_to_read = 0;
484 for (int i = 0; i < iovcnt ; ++i)
485 bytes_to_read += iov[i].iov_len;
487 if (bytes_to_read == 0)
488 ACELIB_ERROR_RETURN ((LM_ERROR,
489 ACE_TEXT ("ACE_WIN32_Asynch_Read_Stream::readv:")
490 ACE_TEXT ("Attempt to read 0 bytes\n")),
491 -1);
493 // Create the Asynch_Result.
494 ACE_WIN32_Asynch_Read_Stream_Result *result = 0;
495 ACE_NEW_RETURN (result,
496 ACE_WIN32_Asynch_Read_Stream_Result (this->handler_proxy_,
497 this->handle_,
498 message_block,
499 bytes_to_read,
500 act,
501 this->win32_proactor_->get_handle (),
502 priority,
503 signal_number,
504 1), // scatter read enabled
505 -1);
507 // do the scatter recv
509 result->set_error (0); // Clear error before starting IO.
511 DWORD bytes_recvd = 0;
512 u_long flags = 0;
514 int initiate_result = ::WSARecv (reinterpret_cast<SOCKET> (result->handle ()),
515 reinterpret_cast<WSABUF *> (iov),
516 iovcnt,
517 &bytes_recvd,
518 &flags,
519 result,
522 if (0 == initiate_result)
523 // Immediate success: the OVERLAPPED will still get queued.
524 return 1;
526 ACE_ASSERT (initiate_result == SOCKET_ERROR);
528 // If initiate failed, check for a bad error.
529 ACE_OS::set_errno_to_last_error ();
530 switch (errno)
532 case ERROR_IO_PENDING:
533 // The IO will complete proactively: the OVERLAPPED will still
534 // get queued.
535 initiate_result = 0;
536 break;
538 default:
539 // Something else went wrong: the OVERLAPPED will not get
540 // queued.
542 if (ACE::debug ())
544 ACELIB_DEBUG ((LM_ERROR,
545 ACE_TEXT ("%p\n"),
546 ACE_TEXT ("WSARecv")));
549 delete result;
550 initiate_result = -1;
551 break;
554 return initiate_result;
555 #else
556 ACE_UNUSED_ARG (message_block);
557 ACE_UNUSED_ARG (bytes_to_read);
558 ACE_UNUSED_ARG (act);
559 ACE_UNUSED_ARG (priority);
560 ACE_UNUSED_ARG (signal_number);
561 ACE_NOTSUP_RETURN (-1);
562 #endif /* ACE_HAS_WINSOCK2 && ACE_HAS_WINSOCK2 != 0 */
565 ACE_WIN32_Asynch_Read_Stream::~ACE_WIN32_Asynch_Read_Stream ()
570 ACE_WIN32_Asynch_Read_Stream::shared_read (ACE_WIN32_Asynch_Read_Stream_Result *result)
572 // ReadFile API limits us to DWORD range.
573 if (result->bytes_to_read () > MAXDWORD)
575 errno = ERANGE;
576 return -1;
578 DWORD bytes_to_read = static_cast<DWORD> (result->bytes_to_read ());
580 result->set_error (0); // Clear error before starting IO.
582 // Initiate the read
583 int initiate_result = ::ReadFile (result->handle (),
584 result->message_block ().wr_ptr (),
585 bytes_to_read,
587 result);
588 if (initiate_result == 1)
589 // Immediate success: the OVERLAPPED will still get queued.
590 return 0;
592 // If initiate failed, check for a bad error.
593 ACE_OS::set_errno_to_last_error ();
594 switch (errno)
596 case ERROR_IO_PENDING:
597 /* FALLTHRU */
598 case ERROR_MORE_DATA:
599 // The IO will complete proactively: the OVERLAPPED will still
600 // get queued.
601 return 0;
603 default:
604 // Something else went wrong: the OVERLAPPED will not get
605 // queued.
607 if (ACE::debug ())
609 ACELIB_DEBUG ((LM_ERROR,
610 ACE_TEXT ("%p\n"),
611 ACE_TEXT ("ReadFile")));
614 return -1;
618 // Methods belong to ACE_WIN32_Asynch_Operation base class. These
619 // methods are defined here to avoid VC++ warnings. They route the
620 // call to the ACE_WIN32_Asynch_Operation base class.
623 ACE_WIN32_Asynch_Read_Stream::open (const ACE_Handler::Proxy_Ptr &handler_proxy,
624 ACE_HANDLE handle,
625 const void *completion_key,
626 ACE_Proactor *proactor)
628 return ACE_WIN32_Asynch_Operation::open (handler_proxy,
629 handle,
630 completion_key,
631 proactor);
635 ACE_WIN32_Asynch_Read_Stream::cancel ()
637 return ACE_WIN32_Asynch_Operation::cancel ();
640 ACE_Proactor *
641 ACE_WIN32_Asynch_Read_Stream::proactor () const
643 return ACE_WIN32_Asynch_Operation::proactor ();
646 size_t
647 ACE_WIN32_Asynch_Write_Stream_Result::bytes_to_write () const
649 return this->bytes_to_write_;
652 ACE_Message_Block &
653 ACE_WIN32_Asynch_Write_Stream_Result::message_block () const
655 return this->message_block_;
658 ACE_HANDLE
659 ACE_WIN32_Asynch_Write_Stream_Result::handle () const
661 return this->handle_;
664 ACE_WIN32_Asynch_Write_Stream_Result::ACE_WIN32_Asynch_Write_Stream_Result (
665 const ACE_Handler::Proxy_Ptr &handler_proxy,
666 ACE_HANDLE handle,
667 ACE_Message_Block &message_block,
668 size_t bytes_to_write,
669 const void* act,
670 ACE_HANDLE event,
671 int priority,
672 int signal_number,
673 int gather_enabled)
674 : ACE_Asynch_Result_Impl (),
675 ACE_Asynch_Write_Stream_Result_Impl (),
676 ACE_WIN32_Asynch_Result
677 (handler_proxy, act, event, 0, 0, priority, signal_number),
678 bytes_to_write_ (bytes_to_write),
679 message_block_ (message_block),
680 handle_ (handle),
681 gather_enabled_ (gather_enabled)
685 void
686 ACE_WIN32_Asynch_Write_Stream_Result::complete (size_t bytes_transferred,
687 int success,
688 const void *completion_key,
689 u_long error)
691 // Copy the data which was returned by <GetQueuedCompletionStatus>.
692 this->bytes_transferred_ = bytes_transferred;
693 this->success_ = success;
694 this->completion_key_ = completion_key;
695 this->error_ = error;
697 // Appropriately move the pointers in the message block.
698 if (!this->gather_enabled ())
699 this->message_block_.rd_ptr (bytes_transferred);
700 else
702 for (ACE_Message_Block* mb = &this->message_block_;
703 (mb != 0) && (bytes_transferred > 0);
704 mb = mb->cont ())
706 size_t len_part = mb->length ();
708 if ( len_part > bytes_transferred)
709 len_part = bytes_transferred;
711 mb->rd_ptr (len_part);
713 bytes_transferred -= len_part;
717 // Create the interface result class.
718 ACE_Asynch_Write_Stream::Result result (this);
720 // Call the application handler.
721 ACE_Handler *handler = this->handler_proxy_.get ()->handler ();
722 if (handler != 0)
723 handler->handle_write_stream (result);
726 ACE_WIN32_Asynch_Write_Stream_Result::~ACE_WIN32_Asynch_Write_Stream_Result ()
730 // Base class operations. These operations are here to kill dominance
731 // warnings. These methods call the base class methods.
733 size_t
734 ACE_WIN32_Asynch_Write_Stream_Result::bytes_transferred () const
736 return ACE_WIN32_Asynch_Result::bytes_transferred ();
739 const void *
740 ACE_WIN32_Asynch_Write_Stream_Result::act () const
742 return ACE_WIN32_Asynch_Result::act ();
746 ACE_WIN32_Asynch_Write_Stream_Result::success () const
748 return ACE_WIN32_Asynch_Result::success ();
751 const void *
752 ACE_WIN32_Asynch_Write_Stream_Result::completion_key () const
754 return ACE_WIN32_Asynch_Result::completion_key ();
757 u_long
758 ACE_WIN32_Asynch_Write_Stream_Result::error () const
760 return ACE_WIN32_Asynch_Result::error ();
763 ACE_HANDLE
764 ACE_WIN32_Asynch_Write_Stream_Result::event () const
766 return ACE_WIN32_Asynch_Result::event ();
769 u_long
770 ACE_WIN32_Asynch_Write_Stream_Result::offset () const
772 return ACE_WIN32_Asynch_Result::offset ();
775 u_long
776 ACE_WIN32_Asynch_Write_Stream_Result::offset_high () const
778 return ACE_WIN32_Asynch_Result::offset_high ();
782 ACE_WIN32_Asynch_Write_Stream_Result::priority () const
784 return ACE_WIN32_Asynch_Result::priority ();
788 ACE_WIN32_Asynch_Write_Stream_Result::signal_number () const
790 return ACE_WIN32_Asynch_Result::signal_number ();
794 ACE_WIN32_Asynch_Write_Stream_Result::post_completion (ACE_Proactor_Impl *proactor)
796 return ACE_WIN32_Asynch_Result::post_completion (proactor);
800 ACE_WIN32_Asynch_Write_Stream_Result::gather_enabled () const
802 return this->gather_enabled_;
805 ACE_WIN32_Asynch_Write_Stream::ACE_WIN32_Asynch_Write_Stream (ACE_WIN32_Proactor *win32_proactor)
806 : ACE_Asynch_Operation_Impl (),
807 ACE_Asynch_Write_Stream_Impl (),
808 ACE_WIN32_Asynch_Operation (win32_proactor)
813 ACE_WIN32_Asynch_Write_Stream::write (ACE_Message_Block &message_block,
814 size_t bytes_to_write,
815 const void *act,
816 int priority,
817 int signal_number)
819 size_t len = message_block.length();
821 if (bytes_to_write > len)
822 bytes_to_write = len ;
824 if (bytes_to_write == 0)
825 ACELIB_ERROR_RETURN
826 ((LM_ERROR,
827 ACE_TEXT ("ACE_WIN32_Asynch_Write_Stream::write:")
828 ACE_TEXT ("Attempt to write 0 bytes\n")),
829 -1);
831 if (bytes_to_write > MAXDWORD)
833 errno = ERANGE;
834 return -1;
837 ACE_WIN32_Asynch_Write_Stream_Result *result = 0;
838 ACE_NEW_RETURN (result,
839 ACE_WIN32_Asynch_Write_Stream_Result (this->handler_proxy_,
840 this->handle_,
841 message_block,
842 bytes_to_write,
843 act,
844 this->win32_proactor_->get_handle (),
845 priority,
846 signal_number),
847 -1);
849 u_long bytes_written;
851 result->set_error (0); // Clear error before starting IO.
853 // Initiate the write; Winsock 2 is required for the higher-performing
854 // WSASend() function. For Winsock 1, fall back to the slower WriteFile().
855 int initiate_result = 0;
856 #if (defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0))
857 WSABUF iov;
858 iov.buf = result->message_block ().rd_ptr ();
859 iov.len = static_cast<DWORD> (bytes_to_write);
860 initiate_result = ::WSASend (reinterpret_cast<SOCKET> (result->handle ()),
861 &iov,
863 &bytes_written,
864 0, // flags
865 result,
867 if (initiate_result == 0)
868 #else
869 initiate_result = ::WriteFile (result->handle (),
870 result->message_block ().rd_ptr (),
871 static_cast<DWORD> (bytes_to_write),
872 &bytes_written,
873 result);
874 if (initiate_result == 1)
875 #endif /* ACE_HAS_WINSOCK2 */
877 // Immediate success: the OVERLAPPED will still get queued.
878 return 0;
881 // If initiate failed, check for a bad error.
882 ACE_OS::set_errno_to_last_error ();
883 switch (errno)
885 case ERROR_IO_PENDING:
886 // The IO will complete proactively: the OVERLAPPED will still
887 // get queued.
888 initiate_result = 0;
889 break;
891 default:
892 // Something else went wrong: the OVERLAPPED will not get
893 // queued.
895 if (ACE::debug ())
896 ACELIB_DEBUG ((LM_ERROR,
897 ACE_TEXT ("%p\n"),
898 ACE_TEXT ("Initiating write")));
899 delete result;
900 initiate_result = -1;
903 return initiate_result;
907 ACE_WIN32_Asynch_Write_Stream::writev (ACE_Message_Block &message_block,
908 size_t bytes_to_write,
909 const void *act,
910 int priority,
911 int signal_number)
913 #if (defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0))
914 iovec iov[ACE_IOV_MAX];
915 int iovcnt = 0;
917 // We should not write more than user requested,
918 // but it is allowed to write less
920 for (const ACE_Message_Block* msg = &message_block;
921 msg != 0 && bytes_to_write > 0 && iovcnt < ACE_IOV_MAX;
922 msg = msg->cont ())
924 size_t msg_len = msg->length ();
926 // Skip 0-length blocks.
927 if (msg_len == 0)
928 continue;
929 if (msg_len > bytes_to_write)
930 msg_len = bytes_to_write;
931 bytes_to_write -= msg_len;
933 // Make as many iovec as needed to fit all of msg_len.
934 size_t rd_ptr_offset = 0;
936 while (msg_len > 0 && iovcnt < ACE_IOV_MAX)
938 u_long this_chunk_length;
939 if (msg_len > ULONG_MAX)
940 this_chunk_length = ULONG_MAX;
941 else
942 this_chunk_length = static_cast<u_long> (msg_len);
943 // Collect the data in the iovec.
944 iov[iovcnt].iov_base = msg->rd_ptr () + rd_ptr_offset;
945 iov[iovcnt].iov_len = this_chunk_length;
946 msg_len -= this_chunk_length;
947 rd_ptr_offset += this_chunk_length;
949 // Increment iovec counter if there's more to do.
950 if (msg_len > 0)
951 iovcnt++;
953 if (msg_len > 0) // Ran out of iovecs before msg_space exhausted
955 errno = ERANGE;
956 return -1;
958 ++iovcnt;
961 // Re-calculate number bytes to write
962 bytes_to_write = 0;
964 for ( int i=0; i < iovcnt ; ++i )
965 bytes_to_write += iov[i].iov_len;
967 if ( bytes_to_write == 0 )
968 ACELIB_ERROR_RETURN ((LM_ERROR,
969 ACE_TEXT ("ACE_WIN32_Asynch_Write_Stream::writev:")
970 ACE_TEXT ("Attempt to write 0 bytes\n")),
971 -1);
974 ACE_WIN32_Asynch_Write_Stream_Result *result = 0;
975 ACE_NEW_RETURN (result,
976 ACE_WIN32_Asynch_Write_Stream_Result (this->handler_proxy_,
977 this->handle_,
978 message_block,
979 bytes_to_write,
980 act,
981 this->win32_proactor_->get_handle (),
982 priority,
983 signal_number,
984 1), // gather write enabled
985 -1);
987 // do the gather send
989 u_long bytes_sent = 0;
991 int initiate_result = ::WSASend (reinterpret_cast<SOCKET> (result->handle ()),
992 reinterpret_cast<WSABUF *> (iov),
993 iovcnt,
994 &bytes_sent,
995 0, // flags
996 result,
999 if (0 == initiate_result)
1000 // Immediate success: the OVERLAPPED will still get queued.
1001 return 1;
1003 ACE_ASSERT (initiate_result == SOCKET_ERROR);
1005 // If initiate failed, check for a bad error.
1006 ACE_OS::set_errno_to_last_error ();
1007 switch (errno)
1009 case ERROR_IO_PENDING:
1010 // The IO will complete proactively: the OVERLAPPED will still
1011 // get queued.
1012 initiate_result = 0;
1013 break;
1015 default:
1016 // Something else went wrong: the OVERLAPPED will not get
1017 // queued.
1019 if (ACE::debug ())
1021 ACELIB_DEBUG ((LM_ERROR,
1022 ACE_TEXT ("%p\n"),
1023 ACE_TEXT ("WSASend")));
1026 delete result;
1027 initiate_result = -1;
1028 break;
1031 return initiate_result;
1032 #else
1033 ACE_UNUSED_ARG (message_block);
1034 ACE_UNUSED_ARG (bytes_to_write);
1035 ACE_UNUSED_ARG (act);
1036 ACE_UNUSED_ARG (priority);
1037 ACE_UNUSED_ARG (signal_number);
1038 ACE_NOTSUP_RETURN (-1);
1039 #endif /* ACE_HAS_WINSOCK2 && ACE_HAS_WINSOCK2 != 0 */
1042 ACE_WIN32_Asynch_Write_Stream::~ACE_WIN32_Asynch_Write_Stream ()
1046 // Methods belong to ACE_WIN32_Asynch_Operation base class. These
1047 // methods are defined here to avoid VC++ warnings. They route the
1048 // call to the ACE_WIN32_Asynch_Operation base class.
1051 ACE_WIN32_Asynch_Write_Stream::open (const ACE_Handler::Proxy_Ptr &handler_proxy,
1052 ACE_HANDLE handle,
1053 const void *completion_key,
1054 ACE_Proactor *proactor)
1056 return ACE_WIN32_Asynch_Operation::open (handler_proxy,
1057 handle,
1058 completion_key,
1059 proactor);
1063 ACE_WIN32_Asynch_Write_Stream::cancel ()
1065 return ACE_WIN32_Asynch_Operation::cancel ();
1068 ACE_Proactor *
1069 ACE_WIN32_Asynch_Write_Stream::proactor () const
1071 return ACE_WIN32_Asynch_Operation::proactor ();
1074 ACE_WIN32_Asynch_Read_File_Result::ACE_WIN32_Asynch_Read_File_Result (
1075 const ACE_Handler::Proxy_Ptr &handler_proxy,
1076 ACE_HANDLE handle,
1077 ACE_Message_Block &message_block,
1078 size_t bytes_to_read,
1079 const void* act,
1080 u_long offset,
1081 u_long offset_high,
1082 ACE_HANDLE event,
1083 int priority,
1084 int signal_number,
1085 int scatter_enabled)
1086 : ACE_Asynch_Result_Impl (),
1087 ACE_Asynch_Read_Stream_Result_Impl (),
1088 ACE_Asynch_Read_File_Result_Impl (),
1089 ACE_WIN32_Asynch_Read_Stream_Result (handler_proxy,
1090 handle,
1091 message_block,
1092 bytes_to_read,
1093 act,
1094 event,
1095 priority,
1096 signal_number,
1097 scatter_enabled)
1099 this->Offset = offset;
1100 this->OffsetHigh = offset_high;
1103 void
1104 ACE_WIN32_Asynch_Read_File_Result::complete (size_t bytes_transferred,
1105 int success,
1106 const void *completion_key,
1107 u_long error)
1109 // Copy the data which was returned by GetQueuedCompletionStatus.
1110 this->bytes_transferred_ = bytes_transferred;
1111 this->success_ = success;
1112 this->completion_key_ = completion_key;
1113 this->error_ = error;
1115 // Appropriately move the pointers in the message block.
1116 if (!this->scatter_enabled ())
1117 this->message_block_.wr_ptr (bytes_transferred);
1118 else
1120 static const size_t page_size = ACE_OS::getpagesize();
1122 for (ACE_Message_Block* mb = &this->message_block_;
1123 (mb != 0) && (bytes_transferred > 0);
1124 mb = mb->cont ())
1126 // mb->space () is ought to be >= page_size.
1127 // this is verified in the readv method
1128 // ACE_ASSERT (mb->space () >= page_size);
1130 size_t len_part = page_size ;
1132 if ( len_part > bytes_transferred)
1133 len_part = bytes_transferred;
1135 mb->wr_ptr (len_part);
1137 bytes_transferred -= len_part;
1141 // Create the interface result class.
1142 ACE_Asynch_Read_File::Result result (this);
1144 // Call the application handler.
1145 ACE_Handler *handler = this->handler_proxy_.get ()->handler ();
1146 if (handler != 0)
1147 handler->handle_read_file (result);
1150 ACE_WIN32_Asynch_Read_File_Result::~ACE_WIN32_Asynch_Read_File_Result ()
1154 // Base class operations. These operations are here to kill dominance
1155 // warnings. These methods call the base class methods.
1157 size_t
1158 ACE_WIN32_Asynch_Read_File_Result::bytes_transferred () const
1160 return ACE_WIN32_Asynch_Result::bytes_transferred ();
1163 const void *
1164 ACE_WIN32_Asynch_Read_File_Result::act () const
1166 return ACE_WIN32_Asynch_Result::act ();
1170 ACE_WIN32_Asynch_Read_File_Result::success () const
1172 return ACE_WIN32_Asynch_Result::success ();
1175 const void *
1176 ACE_WIN32_Asynch_Read_File_Result::completion_key () const
1178 return ACE_WIN32_Asynch_Result::completion_key ();
1181 u_long
1182 ACE_WIN32_Asynch_Read_File_Result::error () const
1184 return ACE_WIN32_Asynch_Result::error ();
1187 ACE_HANDLE
1188 ACE_WIN32_Asynch_Read_File_Result::event () const
1190 return ACE_WIN32_Asynch_Result::event ();
1193 u_long
1194 ACE_WIN32_Asynch_Read_File_Result::offset () const
1196 return ACE_WIN32_Asynch_Result::offset ();
1199 u_long
1200 ACE_WIN32_Asynch_Read_File_Result::offset_high () const
1202 return ACE_WIN32_Asynch_Result::offset_high ();
1206 ACE_WIN32_Asynch_Read_File_Result::priority () const
1208 return ACE_WIN32_Asynch_Result::priority ();
1212 ACE_WIN32_Asynch_Read_File_Result::signal_number () const
1214 return ACE_WIN32_Asynch_Result::signal_number ();
1217 // The following methods belong to
1218 // ACE_WIN32_Asynch_Read_Stream_Result. They are here to avoid VC++
1219 // warnings. These methods route their call to the
1220 // ACE_WIN32_Asynch_Read_Stream_Result base class.
1222 size_t
1223 ACE_WIN32_Asynch_Read_File_Result::bytes_to_read () const
1225 return ACE_WIN32_Asynch_Read_Stream_Result::bytes_to_read ();
1228 ACE_Message_Block &
1229 ACE_WIN32_Asynch_Read_File_Result::message_block () const
1231 return ACE_WIN32_Asynch_Read_Stream_Result::message_block ();
1234 ACE_HANDLE
1235 ACE_WIN32_Asynch_Read_File_Result::handle () const
1237 return ACE_WIN32_Asynch_Read_Stream_Result::handle ();
1241 ACE_WIN32_Asynch_Read_File_Result::post_completion (ACE_Proactor_Impl *proactor)
1243 return ACE_WIN32_Asynch_Result::post_completion (proactor);
1246 // ************************************************************
1248 ACE_WIN32_Asynch_Read_File::ACE_WIN32_Asynch_Read_File (ACE_WIN32_Proactor *win32_proactor)
1249 : ACE_Asynch_Operation_Impl (),
1250 ACE_Asynch_Read_Stream_Impl (),
1251 ACE_Asynch_Read_File_Impl (),
1252 ACE_WIN32_Asynch_Read_Stream (win32_proactor)
1257 ACE_WIN32_Asynch_Read_File::read (ACE_Message_Block &message_block,
1258 size_t bytes_to_read,
1259 u_long offset,
1260 u_long offset_high,
1261 const void *act,
1262 int priority,
1263 int signal_number)
1265 size_t space = message_block.space ();
1266 if ( bytes_to_read > space )
1267 bytes_to_read = space;
1269 if ( bytes_to_read == 0 )
1270 ACELIB_ERROR_RETURN
1271 ((LM_ERROR,
1272 ACE_TEXT ("ACE_WIN32_Asynch_Read_File::read:")
1273 ACE_TEXT ("Attempt to read 0 bytes or no space in the message block\n")),
1274 -1);
1277 ACE_WIN32_Asynch_Read_File_Result *result = 0;
1278 ACE_NEW_RETURN (result,
1279 ACE_WIN32_Asynch_Read_File_Result (this->handler_proxy_,
1280 this->handle_,
1281 message_block,
1282 bytes_to_read,
1283 act,
1284 offset,
1285 offset_high,
1286 this->win32_proactor_->get_handle (),
1287 priority,
1288 signal_number),
1289 -1);
1291 // Shared read
1292 int return_val = this->shared_read (result);
1294 // Upon errors
1295 if (return_val == -1)
1296 delete result;
1298 return return_val;
1302 ACE_WIN32_Asynch_Read_File::readv (ACE_Message_Block &message_block,
1303 size_t bytes_to_read,
1304 u_long offset,
1305 u_long offset_high,
1306 const void *act,
1307 int priority,
1308 int signal_number)
1310 #if defined (ACE_HAS_WIN32_OVERLAPPED_IO)
1311 static const size_t page_size = ACE_OS::getpagesize();
1313 FILE_SEGMENT_ELEMENT buffer_pointers[ACE_IOV_MAX + 1];
1314 int buffer_pointers_count = 0;
1316 // Each buffer must be at least the size of a system memory page
1317 // and must be aligned on a system memory page size boundary
1319 // We should not read more than user requested,
1320 // but it is allowed to read less
1322 size_t total_space = 0;
1324 for (const ACE_Message_Block* msg = &message_block;
1325 msg != 0 && buffer_pointers_count < ACE_IOV_MAX && total_space < bytes_to_read;
1326 msg = msg->cont(), ++buffer_pointers_count )
1328 size_t msg_space = msg->space ();
1330 if (msg_space < page_size)
1331 ACELIB_ERROR_RETURN ((LM_ERROR,
1332 ACE_TEXT ("ACE_WIN32_Asynch_Read_File::readv:")
1333 ACE_TEXT ("Invalid message block size\n")),
1334 -1);
1336 buffer_pointers[buffer_pointers_count].Buffer = msg->wr_ptr ();
1337 total_space += page_size;
1340 // not read more than buffers space
1341 if (bytes_to_read > total_space)
1342 bytes_to_read = total_space;
1344 // ReadFileScatter API limits us to DWORD range.
1345 if (bytes_to_read > MAXDWORD)
1347 errno = ERANGE;
1348 return -1;
1350 DWORD dword_bytes_to_read = static_cast<DWORD> (bytes_to_read);
1352 // last one should be completely 0
1353 buffer_pointers[buffer_pointers_count].Buffer = 0;
1355 ACE_WIN32_Asynch_Read_File_Result *result = 0;
1356 ACE_NEW_RETURN (result,
1357 ACE_WIN32_Asynch_Read_File_Result (this->handler_proxy_,
1358 this->handle_,
1359 message_block,
1360 bytes_to_read,
1361 act,
1362 offset,
1363 offset_high,
1364 this->win32_proactor_->get_handle (),
1365 priority,
1366 signal_number,
1367 1), // scatter read enabled
1368 -1);
1370 // do the scatter read
1371 result->set_error (0); // Clear error before starting IO.
1373 int initiate_result = ::ReadFileScatter (result->handle (),
1374 buffer_pointers,
1375 dword_bytes_to_read,
1376 0, // reserved, must be NULL
1377 result);
1379 if (0 != initiate_result)
1380 // Immediate success: the OVERLAPPED will still get queued.
1381 return 1;
1383 // If initiate failed, check for a bad error.
1384 ACE_OS::set_errno_to_last_error ();
1385 switch (errno)
1387 case ERROR_IO_PENDING:
1388 // The IO will complete proactively: the OVERLAPPED will still
1389 // get queued.
1390 initiate_result = 0;
1391 break;
1393 default:
1394 // Something else went wrong: the OVERLAPPED will not get
1395 // queued.
1397 if (ACE::debug ())
1399 ACELIB_DEBUG ((LM_ERROR,
1400 ACE_TEXT ("%p\n"),
1401 ACE_TEXT ("ReadFileScatter")));
1404 delete result;
1405 initiate_result = -1;
1406 break;
1409 return initiate_result;
1410 #else
1411 ACE_NOTSUP_RETURN (-1);
1412 #endif /* ACE_WIN32_OVERLAPPED_IO */
1416 ACE_WIN32_Asynch_Read_File::~ACE_WIN32_Asynch_Read_File ()
1421 ACE_WIN32_Asynch_Read_File::read (ACE_Message_Block &message_block,
1422 size_t bytes_to_read,
1423 const void *act,
1424 int priority,
1425 int signal_number)
1427 return ACE_WIN32_Asynch_Read_Stream::read (message_block,
1428 bytes_to_read,
1429 act,
1430 priority,
1431 signal_number);
1435 ACE_WIN32_Asynch_Read_File::readv (ACE_Message_Block &message_block,
1436 size_t bytes_to_read,
1437 const void *act,
1438 int priority,
1439 int signal_number)
1441 return ACE_WIN32_Asynch_Read_Stream::readv (message_block,
1442 bytes_to_read,
1443 act,
1444 priority,
1445 signal_number);
1448 // Methods belong to ACE_WIN32_Asynch_Operation base class. These
1449 // methods are defined here to avoid VC++ warnings. They route the
1450 // call to the ACE_WIN32_Asynch_Operation base class.
1453 ACE_WIN32_Asynch_Read_File::open (const ACE_Handler::Proxy_Ptr &handler_proxy,
1454 ACE_HANDLE handle,
1455 const void *completion_key,
1456 ACE_Proactor *proactor)
1458 return ACE_WIN32_Asynch_Operation::open (handler_proxy,
1459 handle,
1460 completion_key,
1461 proactor);
1465 ACE_WIN32_Asynch_Read_File::cancel ()
1467 return ACE_WIN32_Asynch_Operation::cancel ();
1470 ACE_Proactor *
1471 ACE_WIN32_Asynch_Read_File::proactor () const
1473 return ACE_WIN32_Asynch_Operation::proactor ();
1476 ACE_WIN32_Asynch_Write_File_Result::ACE_WIN32_Asynch_Write_File_Result (
1477 const ACE_Handler::Proxy_Ptr &handler_proxy,
1478 ACE_HANDLE handle,
1479 ACE_Message_Block &message_block,
1480 size_t bytes_to_write,
1481 const void* act,
1482 u_long offset,
1483 u_long offset_high,
1484 ACE_HANDLE event,
1485 int priority,
1486 int signal_number,
1487 int gather_enabled)
1488 : ACE_Asynch_Result_Impl (),
1489 ACE_Asynch_Write_Stream_Result_Impl (),
1490 ACE_Asynch_Write_File_Result_Impl (),
1491 ACE_WIN32_Asynch_Write_Stream_Result (handler_proxy,
1492 handle,
1493 message_block,
1494 bytes_to_write,
1495 act,
1496 event,
1497 priority,
1498 signal_number,
1499 gather_enabled)
1501 this->Offset = offset;
1502 this->OffsetHigh = offset_high;
1505 void
1506 ACE_WIN32_Asynch_Write_File_Result::complete (size_t bytes_transferred,
1507 int success,
1508 const void *completion_key,
1509 u_long error)
1511 // Copy the data which was returned by GetQueuedCompletionStatus
1512 this->bytes_transferred_ = bytes_transferred;
1513 this->success_ = success;
1514 this->completion_key_ = completion_key;
1515 this->error_ = error;
1517 // Appropriately move the pointers in the message block.
1518 if (!this->gather_enabled ())
1519 this->message_block_.rd_ptr (bytes_transferred);
1520 else
1522 static const size_t page_size = ACE_OS::getpagesize();
1524 for (ACE_Message_Block* mb = &this->message_block_;
1525 (mb != 0) && (bytes_transferred > 0);
1526 mb = mb->cont ())
1528 // mb->length () is ought to be >= page_size.
1529 // this is verified in the writev method
1530 // ACE_ASSERT (mb->length () >= page_size);
1532 size_t len_part = page_size;
1534 if ( len_part > bytes_transferred)
1535 len_part = bytes_transferred;
1537 mb->rd_ptr (len_part);
1539 bytes_transferred -= len_part;
1544 // Create the interface result class.
1545 ACE_Asynch_Write_File::Result result (this);
1547 // Call the application handler.
1548 ACE_Handler *handler = this->handler_proxy_.get ()->handler ();
1549 if (handler != 0)
1550 handler->handle_write_file (result);
1553 ACE_WIN32_Asynch_Write_File_Result::~ACE_WIN32_Asynch_Write_File_Result ()
1557 // Base class operations. These operations are here to kill dominance
1558 // warnings. These methods call the base class methods.
1560 size_t
1561 ACE_WIN32_Asynch_Write_File_Result::bytes_transferred () const
1563 return ACE_WIN32_Asynch_Result::bytes_transferred ();
1566 const void *
1567 ACE_WIN32_Asynch_Write_File_Result::act () const
1569 return ACE_WIN32_Asynch_Result::act ();
1573 ACE_WIN32_Asynch_Write_File_Result::success () const
1575 return ACE_WIN32_Asynch_Result::success ();
1578 const void *
1579 ACE_WIN32_Asynch_Write_File_Result::completion_key () const
1581 return ACE_WIN32_Asynch_Result::completion_key ();
1584 u_long
1585 ACE_WIN32_Asynch_Write_File_Result::error () const
1587 return ACE_WIN32_Asynch_Result::error ();
1590 ACE_HANDLE
1591 ACE_WIN32_Asynch_Write_File_Result::event () const
1593 return ACE_WIN32_Asynch_Result::event ();
1596 u_long
1597 ACE_WIN32_Asynch_Write_File_Result::offset () const
1599 return ACE_WIN32_Asynch_Result::offset ();
1602 u_long
1603 ACE_WIN32_Asynch_Write_File_Result::offset_high () const
1605 return ACE_WIN32_Asynch_Result::offset_high ();
1609 ACE_WIN32_Asynch_Write_File_Result::priority () const
1611 return ACE_WIN32_Asynch_Result::priority ();
1615 ACE_WIN32_Asynch_Write_File_Result::signal_number () const
1617 return ACE_WIN32_Asynch_Result::signal_number ();
1620 // The following methods belong to
1621 // ACE_WIN32_Asynch_Write_Stream_Result. They are here to avoid VC++
1622 // warnings. These methods route their call to the
1623 // ACE_WIN32_Asynch_Write_Stream_Result base class.
1625 size_t
1626 ACE_WIN32_Asynch_Write_File_Result::bytes_to_write () const
1628 return ACE_WIN32_Asynch_Write_Stream_Result::bytes_to_write ();
1631 ACE_Message_Block &
1632 ACE_WIN32_Asynch_Write_File_Result::message_block () const
1634 return ACE_WIN32_Asynch_Write_Stream_Result::message_block ();
1637 ACE_HANDLE
1638 ACE_WIN32_Asynch_Write_File_Result::handle () const
1640 return ACE_WIN32_Asynch_Write_Stream_Result::handle ();
1644 ACE_WIN32_Asynch_Write_File_Result::post_completion (ACE_Proactor_Impl *proactor)
1646 return ACE_WIN32_Asynch_Result::post_completion (proactor);
1649 ACE_WIN32_Asynch_Write_File::ACE_WIN32_Asynch_Write_File (ACE_WIN32_Proactor *win32_proactor)
1650 : ACE_Asynch_Operation_Impl (),
1651 ACE_Asynch_Write_Stream_Impl (),
1652 ACE_Asynch_Write_File_Impl (),
1653 ACE_WIN32_Asynch_Write_Stream (win32_proactor)
1658 ACE_WIN32_Asynch_Write_File::write (ACE_Message_Block &message_block,
1659 size_t bytes_to_write,
1660 u_long offset,
1661 u_long offset_high,
1662 const void *act,
1663 int priority,
1664 int signal_number)
1666 size_t len = message_block.length ();
1667 if ( bytes_to_write > len )
1668 bytes_to_write = len;
1670 if ( bytes_to_write == 0 )
1671 ACELIB_ERROR_RETURN
1672 ((LM_ERROR,
1673 ACE_TEXT ("ACE_WIN32_Asynch_Write_File::write:")
1674 ACE_TEXT ("Attempt to write 0 bytes\n")),
1675 -1);
1677 if (bytes_to_write > MAXDWORD)
1679 errno = ERANGE;
1680 return -1;
1683 ACE_WIN32_Asynch_Write_File_Result *result = 0;
1684 ACE_NEW_RETURN (result,
1685 ACE_WIN32_Asynch_Write_File_Result (this->handler_proxy_,
1686 this->handle_,
1687 message_block,
1688 bytes_to_write,
1689 act,
1690 offset,
1691 offset_high,
1692 this->win32_proactor_->get_handle (),
1693 priority,
1694 signal_number),
1695 -1);
1697 u_long bytes_written;
1699 result->set_error (0); // Clear error before starting IO.
1701 // Initiate the write
1702 int initiate_result = 0;
1703 initiate_result = ::WriteFile (result->handle (),
1704 result->message_block ().rd_ptr (),
1705 static_cast<DWORD> (bytes_to_write),
1706 &bytes_written,
1707 result);
1708 if (initiate_result == 1)
1710 // Immediate success: the OVERLAPPED will still get queued.
1711 return 0;
1714 // If initiate failed, check for a bad error.
1715 ACE_OS::set_errno_to_last_error ();
1716 switch (errno)
1718 case ERROR_IO_PENDING:
1719 // The IO will complete proactively: the OVERLAPPED will still
1720 // get queued.
1721 initiate_result = 0;
1722 break;
1724 default:
1725 // Something else went wrong: the OVERLAPPED will not get
1726 // queued.
1728 if (ACE::debug ())
1729 ACELIB_DEBUG ((LM_ERROR,
1730 ACE_TEXT ("%p\n"),
1731 ACE_TEXT ("Initiating write")));
1732 delete result;
1733 initiate_result = -1;
1736 return initiate_result;
1740 ACE_WIN32_Asynch_Write_File::writev (ACE_Message_Block &message_block,
1741 size_t bytes_to_write,
1742 u_long offset,
1743 u_long offset_high,
1744 const void *act,
1745 int priority,
1746 int signal_number)
1748 #if defined (ACE_HAS_WIN32_OVERLAPPED_IO)
1749 static const size_t page_size = ACE_OS::getpagesize();
1751 FILE_SEGMENT_ELEMENT buffer_pointers[ACE_IOV_MAX + 1];
1752 int buffer_pointers_count = 0;
1754 // Each buffer must be at least the size of a system memory page
1755 // and must be aligned on a system memory page size boundary
1757 // We should not read more than user requested,
1758 // but it is allowed to read less
1760 size_t total_len = 0;
1762 for (const ACE_Message_Block* msg = &message_block;
1763 msg != 0 && buffer_pointers_count < ACE_IOV_MAX && total_len < bytes_to_write;
1764 msg = msg->cont (), ++buffer_pointers_count )
1766 size_t msg_len = msg->length ();
1768 // Don't allow writing less than page_size, unless
1769 // the size of the message block is big enough (so we don't write from
1770 // memory which does not belong to the message block), and the message
1771 // block is the last in the chain.
1772 if (msg_len < page_size &&
1773 (msg->size () - (msg->rd_ptr () - msg->base ()) < page_size || // message block too small
1774 bytes_to_write - total_len > page_size ))// NOT last chunk
1775 ACELIB_ERROR_RETURN ((LM_ERROR,
1776 ACE_TEXT ("ACE_WIN32_Asynch_Write_File::writev:")
1777 ACE_TEXT ("Invalid message block length\n")),
1778 -1);
1780 buffer_pointers[buffer_pointers_count].Buffer = msg->rd_ptr ();
1781 total_len += page_size;
1784 // not write more than we have in buffers
1785 if (bytes_to_write > total_len)
1786 bytes_to_write = total_len;
1787 // WriteFileGather API limits us to DWORD range.
1788 if (bytes_to_write > MAXDWORD)
1790 errno = ERANGE;
1791 return -1;
1793 DWORD dword_bytes_to_write = static_cast<DWORD> (bytes_to_write);
1795 // last one should be completely 0
1796 buffer_pointers[buffer_pointers_count].Buffer = 0;
1798 ACE_WIN32_Asynch_Write_File_Result *result = 0;
1799 ACE_NEW_RETURN (result,
1800 ACE_WIN32_Asynch_Write_File_Result (this->handler_proxy_,
1801 this->handle_,
1802 message_block,
1803 bytes_to_write,
1804 act,
1805 offset,
1806 offset_high,
1807 this->win32_proactor_->get_handle (),
1808 priority,
1809 signal_number,
1810 1), // gather write enabled
1811 -1);
1813 result->set_error(0);
1815 // do the gather write
1816 int initiate_result = ::WriteFileGather (result->handle (),
1817 buffer_pointers,
1818 dword_bytes_to_write,
1819 0, // reserved, must be NULL
1820 result);
1822 if (0 != initiate_result)
1823 // Immediate success: the OVERLAPPED will still get queued.
1824 return 1;
1826 // If initiate failed, check for a bad error.
1827 ACE_OS::set_errno_to_last_error ();
1828 switch (errno)
1830 case ERROR_IO_PENDING:
1831 // The IO will complete proactively: the OVERLAPPED will still
1832 // get queued.
1833 initiate_result = 0;
1834 break;
1836 default:
1837 // Something else went wrong: the OVERLAPPED will not get
1838 // queued.
1840 if (ACE::debug ())
1842 ACELIB_DEBUG ((LM_ERROR,
1843 ACE_TEXT ("%p\n"),
1844 ACE_TEXT ("WriteFileGather")));
1847 delete result;
1848 initiate_result = -1;
1849 break;
1852 return initiate_result;
1853 #else
1855 ACE_NOTSUP_RETURN (-1);
1857 #endif /* ACE_HAS_WIN32_OVERLAPPED_IO */
1861 ACE_WIN32_Asynch_Write_File::~ACE_WIN32_Asynch_Write_File ()
1866 ACE_WIN32_Asynch_Write_File::write (ACE_Message_Block &message_block,
1867 size_t bytes_to_write,
1868 const void *act,
1869 int priority,
1870 int signal_number)
1872 return this->write (message_block,
1873 bytes_to_write,
1874 0, 0,
1875 act,
1876 priority,
1877 signal_number);
1881 ACE_WIN32_Asynch_Write_File::writev (ACE_Message_Block &message_block,
1882 size_t bytes_to_write,
1883 const void *act,
1884 int priority,
1885 int signal_number)
1887 return this->writev (message_block,
1888 bytes_to_write,
1889 0, 0,
1890 act,
1891 priority,
1892 signal_number);
1895 // Methods belong to ACE_WIN32_Asynch_Operation base class. These
1896 // methods are defined here to avoid VC++ warnings. They route the
1897 // call to the ACE_WIN32_Asynch_Operation base class.
1900 ACE_WIN32_Asynch_Write_File::open (const ACE_Handler::Proxy_Ptr &handler_proxy,
1901 ACE_HANDLE handle,
1902 const void *completion_key,
1903 ACE_Proactor *proactor)
1905 return ACE_WIN32_Asynch_Operation::open (handler_proxy,
1906 handle,
1907 completion_key,
1908 proactor);
1912 ACE_WIN32_Asynch_Write_File::cancel ()
1914 return ACE_WIN32_Asynch_Operation::cancel ();
1917 ACE_Proactor *
1918 ACE_WIN32_Asynch_Write_File::proactor () const
1920 return ACE_WIN32_Asynch_Operation::proactor ();
1923 size_t
1924 ACE_WIN32_Asynch_Accept_Result::bytes_to_read () const
1926 return this->bytes_to_read_;
1929 ACE_Message_Block &
1930 ACE_WIN32_Asynch_Accept_Result::message_block () const
1932 return this->message_block_;
1935 ACE_HANDLE
1936 ACE_WIN32_Asynch_Accept_Result::listen_handle () const
1938 return this->listen_handle_;
1941 ACE_HANDLE
1942 ACE_WIN32_Asynch_Accept_Result::accept_handle () const
1944 return this->accept_handle_;
1947 ACE_WIN32_Asynch_Accept_Result::ACE_WIN32_Asynch_Accept_Result (
1948 const ACE_Handler::Proxy_Ptr &handler_proxy,
1949 ACE_HANDLE listen_handle,
1950 ACE_HANDLE accept_handle,
1951 ACE_Message_Block &message_block,
1952 size_t bytes_to_read,
1953 const void* act,
1954 ACE_HANDLE event,
1955 int priority,
1956 int signal_number)
1957 : ACE_Asynch_Result_Impl (),
1958 ACE_Asynch_Accept_Result_Impl (),
1959 ACE_WIN32_Asynch_Result (handler_proxy,
1960 act,
1961 event,
1964 priority,
1965 signal_number),
1966 bytes_to_read_ (bytes_to_read),
1967 message_block_ (message_block),
1968 listen_handle_ (listen_handle),
1969 accept_handle_ (accept_handle)
1973 void
1974 ACE_WIN32_Asynch_Accept_Result::complete (size_t bytes_transferred,
1975 int success,
1976 const void *completion_key,
1977 u_long error)
1979 // Copy the data which was returned by GetQueuedCompletionStatus
1980 this->bytes_transferred_ = bytes_transferred;
1981 this->success_ = success;
1982 this->completion_key_ = completion_key;
1983 this->error_ = error;
1985 // Appropriately move the pointers in the message block.
1986 this->message_block_.wr_ptr (bytes_transferred);
1988 if (!success && this->accept_handle_ != ACE_INVALID_HANDLE)
1990 ACE_OS::closesocket (this->accept_handle_);
1991 this->accept_handle_ = ACE_INVALID_HANDLE;
1994 // Create the interface result class.
1995 ACE_Asynch_Accept::Result result (this);
1997 // Call the application handler.
1998 ACE_Handler *handler = this->handler_proxy_.get ()->handler ();
1999 if (handler != 0)
2000 handler->handle_accept (result);
2003 ACE_WIN32_Asynch_Accept_Result::~ACE_WIN32_Asynch_Accept_Result ()
2007 // Base class operations. These operations are here to kill dominance
2008 // warnings. These methods call the base class methods.
2010 size_t
2011 ACE_WIN32_Asynch_Accept_Result::bytes_transferred () const
2013 return ACE_WIN32_Asynch_Result::bytes_transferred ();
2016 const void *
2017 ACE_WIN32_Asynch_Accept_Result::act () const
2019 return ACE_WIN32_Asynch_Result::act ();
2023 ACE_WIN32_Asynch_Accept_Result::success () const
2025 return ACE_WIN32_Asynch_Result::success ();
2028 const void *
2029 ACE_WIN32_Asynch_Accept_Result::completion_key () const
2031 return ACE_WIN32_Asynch_Result::completion_key ();
2034 u_long
2035 ACE_WIN32_Asynch_Accept_Result::error () const
2037 return ACE_WIN32_Asynch_Result::error ();
2040 ACE_HANDLE
2041 ACE_WIN32_Asynch_Accept_Result::event () const
2043 return ACE_WIN32_Asynch_Result::event ();
2046 u_long
2047 ACE_WIN32_Asynch_Accept_Result::offset () const
2049 return ACE_WIN32_Asynch_Result::offset ();
2052 u_long
2053 ACE_WIN32_Asynch_Accept_Result::offset_high () const
2055 return ACE_WIN32_Asynch_Result::offset_high ();
2059 ACE_WIN32_Asynch_Accept_Result::priority () const
2061 return ACE_WIN32_Asynch_Result::priority ();
2065 ACE_WIN32_Asynch_Accept_Result::signal_number () const
2067 return ACE_WIN32_Asynch_Result::signal_number ();
2071 ACE_WIN32_Asynch_Accept_Result::post_completion (ACE_Proactor_Impl *proactor)
2073 return ACE_WIN32_Asynch_Result::post_completion (proactor);
2076 ACE_WIN32_Asynch_Accept::ACE_WIN32_Asynch_Accept (ACE_WIN32_Proactor *win32_proactor)
2077 : ACE_Asynch_Operation_Impl (),
2078 ACE_Asynch_Accept_Impl (),
2079 ACE_WIN32_Asynch_Operation (win32_proactor)
2084 ACE_WIN32_Asynch_Accept::accept (ACE_Message_Block &message_block,
2085 size_t bytes_to_read,
2086 ACE_HANDLE accept_handle,
2087 const void *act,
2088 int priority,
2089 int signal_number,
2090 int addr_family)
2092 #if defined (ACE_HAS_WIN32_OVERLAPPED_IO) || (defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0))
2093 // Sanity check: make sure that enough space has been allocated by
2094 // the caller.
2095 size_t address_size =
2096 #if defined (ACE_HAS_IPV6)
2097 addr_family == AF_INET ? sizeof (sockaddr_in) : sizeof (sockaddr_in6);
2098 #else
2099 sizeof (sockaddr_in);
2100 #endif /* ACE_HAS_IPV6 */
2101 address_size += 16; // AcceptEx requires address size + 16 (minimum)
2102 size_t available_space = message_block.space ();
2103 size_t space_needed = bytes_to_read + 2 * address_size;
2104 if (available_space < space_needed)
2105 ACELIB_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("Buffer too small\n")), -1);
2107 // WIN Specific.
2109 // AcceptEx API limits us to DWORD range.
2110 if (bytes_to_read > MAXDWORD)
2112 errno = ERANGE;
2113 return -1;
2115 DWORD dword_bytes_to_read = static_cast<DWORD> (bytes_to_read);
2117 int close_accept_handle = 0;
2118 // If the <accept_handle> is invalid, we will create a new socket.
2119 if (accept_handle == ACE_INVALID_HANDLE)
2121 accept_handle = ACE_OS::socket (addr_family,
2122 SOCK_STREAM,
2124 if (accept_handle == ACE_INVALID_HANDLE)
2126 if (ACE::debug ())
2128 ACELIB_DEBUG ((LM_ERROR,
2129 ACE_TEXT ("%p\n"),
2130 ACE_TEXT ("ACE_OS::socket")));
2132 return -1;
2134 else
2135 // Remember to close the socket down if failures occur.
2136 close_accept_handle = 1;
2139 // Common code for both WIN and POSIX.
2140 ACE_WIN32_Asynch_Accept_Result *result = 0;
2141 ACE_NEW_RETURN (result,
2142 ACE_WIN32_Asynch_Accept_Result (this->handler_proxy_,
2143 this->handle_,
2144 accept_handle,
2145 message_block,
2146 bytes_to_read,
2147 act,
2148 this->win32_proactor_->get_handle (),
2149 priority,
2150 signal_number),
2151 -1);
2153 u_long bytes_read;
2155 // Initiate the accept.
2156 int initiate_result = ::AcceptEx ((SOCKET) result->listen_handle (),
2157 (SOCKET) result->accept_handle (),
2158 result->message_block ().wr_ptr (),
2159 dword_bytes_to_read,
2160 static_cast<DWORD> (address_size),
2161 static_cast<DWORD> (address_size),
2162 &bytes_read,
2163 result);
2164 if (initiate_result == 1)
2165 // Immediate success: the OVERLAPPED will still get queued.
2166 return 1;
2168 // If initiate failed, check for a bad error.
2169 ACE_OS::set_errno_to_last_error ();
2170 switch (errno)
2172 case ERROR_IO_PENDING:
2173 // The IO will complete proactively: the OVERLAPPED will still
2174 // get queued.
2175 return 0;
2177 default:
2178 // Something else went wrong: the OVERLAPPED will not get
2179 // queued.
2181 if (close_accept_handle == 1)
2182 // Close the newly created socket
2183 ACE_OS::closesocket (accept_handle);
2185 // Cleanup dynamically allocated Asynch_Result.
2186 delete result;
2188 if (ACE::debug ())
2190 ACELIB_DEBUG ((LM_ERROR,
2191 ACE_TEXT ("%p\n"),
2192 ACE_TEXT ("AcceptEx")));
2194 return -1;
2196 #else
2197 ACE_UNUSED_ARG (message_block);
2198 ACE_UNUSED_ARG (bytes_to_read);
2199 ACE_UNUSED_ARG (accept_handle);
2200 ACE_UNUSED_ARG (act);
2201 ACE_UNUSED_ARG (priority);
2202 ACE_UNUSED_ARG (signal_number);
2203 ACE_UNUSED_ARG (addr_family);
2204 ACE_NOTSUP_RETURN (-1);
2205 #endif /* defined (ACE_HAS_WIN32_OVERLAPPED_IO) || (defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)) */
2208 ACE_WIN32_Asynch_Accept::~ACE_WIN32_Asynch_Accept ()
2212 // Methods belong to ACE_WIN32_Asynch_Operation base class. These
2213 // methods are defined here to avoid VC++ warnings. They route the
2214 // call to the ACE_WIN32_Asynch_Operation base class.
2217 ACE_WIN32_Asynch_Accept::open (const ACE_Handler::Proxy_Ptr &handler_proxy,
2218 ACE_HANDLE handle,
2219 const void *completion_key,
2220 ACE_Proactor *proactor)
2222 return ACE_WIN32_Asynch_Operation::open (handler_proxy,
2223 handle,
2224 completion_key,
2225 proactor);
2229 ACE_WIN32_Asynch_Accept::cancel ()
2231 return ACE_WIN32_Asynch_Operation::cancel ();
2234 ACE_Proactor *
2235 ACE_WIN32_Asynch_Accept::proactor () const
2237 return ACE_WIN32_Asynch_Operation::proactor ();
2240 // *********************************************************************
2242 ACE_HANDLE
2243 ACE_WIN32_Asynch_Connect_Result::connect_handle () const
2245 return this->connect_handle_;
2248 void ACE_WIN32_Asynch_Connect_Result::connect_handle ( ACE_HANDLE handle )
2250 this->connect_handle_ = handle;
2254 ACE_WIN32_Asynch_Connect_Result::ACE_WIN32_Asynch_Connect_Result
2255 (const ACE_Handler::Proxy_Ptr &handler_proxy,
2256 ACE_HANDLE connect_handle,
2257 const void* act,
2258 ACE_HANDLE event,
2259 int priority,
2260 int signal_number)
2261 : ACE_Asynch_Result_Impl (),
2262 ACE_Asynch_Connect_Result_Impl (),
2263 ACE_WIN32_Asynch_Result
2264 (handler_proxy, act, event, 0, 0, priority, signal_number),
2265 connect_handle_ (connect_handle)
2270 void
2271 ACE_WIN32_Asynch_Connect_Result::complete (size_t bytes_transferred,
2272 int success,
2273 const void *completion_key,
2274 u_long error)
2276 // Copy the data.
2277 this->bytes_transferred_ = bytes_transferred;
2278 this->success_ = success;
2279 this->completion_key_ = completion_key;
2280 this->error_ = error;
2282 // Create the interface result class.
2283 ACE_Asynch_Connect::Result result (this);
2285 // Call the application handler.
2286 ACE_Handler *handler = this->handler_proxy_.get ()->handler ();
2287 if (handler != 0)
2288 handler->handle_connect (result);
2291 ACE_WIN32_Asynch_Connect_Result::~ACE_WIN32_Asynch_Connect_Result ()
2295 // Base class operations. These operations are here to kill dominance
2296 // warnings. These methods call the base class methods.
2298 size_t
2299 ACE_WIN32_Asynch_Connect_Result::bytes_transferred () const
2301 return ACE_WIN32_Asynch_Result::bytes_transferred ();
2304 const void *
2305 ACE_WIN32_Asynch_Connect_Result::act () const
2307 return ACE_WIN32_Asynch_Result::act ();
2311 ACE_WIN32_Asynch_Connect_Result::success () const
2313 return ACE_WIN32_Asynch_Result::success ();
2316 const void *
2317 ACE_WIN32_Asynch_Connect_Result::completion_key () const
2319 return ACE_WIN32_Asynch_Result::completion_key ();
2322 u_long
2323 ACE_WIN32_Asynch_Connect_Result::error () const
2325 return ACE_WIN32_Asynch_Result::error ();
2328 ACE_HANDLE
2329 ACE_WIN32_Asynch_Connect_Result::event () const
2331 return ACE_WIN32_Asynch_Result::event ();
2334 u_long
2335 ACE_WIN32_Asynch_Connect_Result::offset () const
2337 return ACE_WIN32_Asynch_Result::offset ();
2340 u_long
2341 ACE_WIN32_Asynch_Connect_Result::offset_high () const
2343 return ACE_WIN32_Asynch_Result::offset_high ();
2347 ACE_WIN32_Asynch_Connect_Result::priority () const
2349 return ACE_WIN32_Asynch_Result::priority ();
2353 ACE_WIN32_Asynch_Connect_Result::signal_number () const
2355 return ACE_WIN32_Asynch_Result::signal_number ();
2359 ACE_WIN32_Asynch_Connect_Result::post_completion (ACE_Proactor_Impl *proactor)
2361 return ACE_WIN32_Asynch_Result::post_completion (proactor);
2364 // *********************************************************************
2366 ACE_WIN32_Asynch_Connect::ACE_WIN32_Asynch_Connect (ACE_WIN32_Proactor * win32_proactor)
2367 : ACE_Asynch_Operation_Impl (),
2368 ACE_Asynch_Connect_Impl (),
2369 ACE_WIN32_Asynch_Operation (win32_proactor),
2370 flg_open_ (false)
2374 ACE_WIN32_Asynch_Connect::~ACE_WIN32_Asynch_Connect ()
2376 this->close ();
2377 this->reactor (0); // to avoid purge_pending_notifications
2380 ACE_Proactor *
2381 ACE_WIN32_Asynch_Connect::proactor () const
2383 return ACE_WIN32_Asynch_Operation::proactor ();
2386 ACE_HANDLE
2387 ACE_WIN32_Asynch_Connect::get_handle () const
2389 ACE_ASSERT (0);
2390 return ACE_INVALID_HANDLE;
2393 void
2394 ACE_WIN32_Asynch_Connect::set_handle (ACE_HANDLE)
2396 ACE_ASSERT (0) ;
2400 ACE_WIN32_Asynch_Connect::open (const ACE_Handler::Proxy_Ptr &handler_proxy,
2401 ACE_HANDLE,
2402 const void *completion_key,
2403 ACE_Proactor *proactor)
2405 ACE_TRACE ("ACE_WIN32_Asynch_Connect::open");
2407 // if we are already opened,
2408 // we could not create a new handler without closing the previous
2409 if (this->flg_open_)
2410 ACELIB_ERROR_RETURN ((LM_ERROR,
2411 ACE_TEXT ("%N:%l:ACE_WIN32_Asynch_Connect::open:")
2412 ACE_TEXT ("connector already open\n")),
2413 -1);
2415 //int result =
2416 ACE_WIN32_Asynch_Operation::open (handler_proxy,
2417 ACE_INVALID_HANDLE,
2418 completion_key,
2419 proactor);
2421 // Ignore result as we pass ACE_INVALID_HANDLE
2422 //if (result == -1)
2423 // return result;
2425 this->flg_open_ = true;
2427 return 0;
2431 ACE_WIN32_Asynch_Connect::connect (ACE_HANDLE connect_handle,
2432 const ACE_Addr & remote_sap,
2433 const ACE_Addr & local_sap,
2434 int reuse_addr,
2435 const void *act,
2436 int priority,
2437 int signal_number)
2439 ACE_TRACE ("ACE_WIN32_Asynch_Connect::connect");
2441 if (!this->flg_open_)
2442 ACELIB_ERROR_RETURN ((LM_ERROR,
2443 ACE_TEXT ("%N:%l:ACE_WIN32_Asynch_Connect::connect")
2444 ACE_TEXT ("connector was not opened before\n")),
2445 -1);
2447 // Common code for both WIN and WIN32.
2448 // Create future Asynch_Connect_Result
2449 ACE_WIN32_Asynch_Connect_Result *result = 0;
2450 ACE_NEW_RETURN (result,
2451 ACE_WIN32_Asynch_Connect_Result (this->handler_proxy_,
2452 connect_handle,
2453 act,
2454 this->win32_proactor_->get_handle (),
2455 priority,
2456 signal_number),
2457 -1);
2459 int rc = connect_i (result,
2460 remote_sap,
2461 local_sap,
2462 reuse_addr);
2464 // update handle
2465 connect_handle = result->connect_handle ();
2467 if (rc != 0)
2468 return post_result (result, true);
2470 // Enqueue result we will wait for completion
2472 ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1));
2474 if (this->result_map_.bind (connect_handle, result) == -1)
2476 ACELIB_ERROR ((LM_ERROR,
2477 ACE_TEXT ("ACE_WIN32_Asynch_Connect::connect: %p\n"),
2478 ACE_TEXT ("bind")));
2479 result->set_error (EFAULT);
2480 return post_result (result, true);
2484 ACE_Asynch_Pseudo_Task & task =
2485 this->win32_proactor_->get_asynch_pseudo_task ();
2487 if (-1 == task.register_io_handler (connect_handle,
2488 this,
2489 ACE_Event_Handler::CONNECT_MASK,
2490 0)) // not to suspend after register
2492 result = 0;
2494 ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1));
2495 this->result_map_.unbind (connect_handle, result);
2497 if (result != 0)
2499 result->set_error (EFAULT);
2500 this->post_result (result, true);
2504 return 0;
2507 int ACE_WIN32_Asynch_Connect::post_result (ACE_WIN32_Asynch_Connect_Result * result,
2508 bool post_enable)
2510 ACE_HANDLE handle = result->connect_handle ();
2511 if (this->flg_open_ && post_enable)
2513 // NOTE: result is invalid after post_completion(). It's either deleted
2514 // or will be shortly via the proactor dispatch, regardless of success
2515 // or fail of the call.
2516 if (this->win32_proactor_ ->post_completion (result) == 0)
2517 return 0;
2519 ACELIB_ERROR ((LM_ERROR,
2520 ACE_TEXT ("Error:(%P | %t):%p\n"),
2521 ACE_TEXT ("ACE_WIN32_Asynch_Connect::post_result: ")
2522 ACE_TEXT (" <post_completion> failed")));
2524 else
2526 // There was no call to post_completion() so manually delete result.
2527 delete result;
2530 if (handle != ACE_INVALID_HANDLE)
2531 ACE_OS::closesocket (handle);
2533 return -1;
2536 // connect_i
2537 // return code :
2538 // -1 errors before attempt to connect
2539 // 0 connect started
2540 // 1 connect finished ( may be unsuccessfully)
2543 ACE_WIN32_Asynch_Connect::connect_i (ACE_WIN32_Asynch_Connect_Result *result,
2544 const ACE_Addr & remote_sap,
2545 const ACE_Addr & local_sap,
2546 int reuse_addr)
2548 result->set_bytes_transferred (0);
2550 ACE_HANDLE handle = result->connect_handle ();
2551 if (handle == ACE_INVALID_HANDLE)
2553 int protocol_family = remote_sap.get_type ();
2554 handle = ACE_OS::socket (protocol_family,
2555 SOCK_STREAM,
2558 // save it
2559 result->connect_handle (handle);
2560 if (handle == ACE_INVALID_HANDLE)
2562 result->set_error (errno);
2563 ACELIB_ERROR_RETURN
2564 ((LM_ERROR,
2565 ACE_TEXT ("ACE_WIN32_Asynch_Connect::connect_i: %p\n"),
2566 ACE_TEXT ("socket")),
2567 -1);
2570 // Reuse the address
2571 int one = 1;
2572 if (protocol_family != PF_UNIX &&
2573 reuse_addr != 0 &&
2574 ACE_OS::setsockopt (handle,
2575 SOL_SOCKET,
2576 SO_REUSEADDR,
2577 (const char*) &one,
2578 sizeof one) == -1)
2580 result->set_error (errno);
2581 ACELIB_ERROR_RETURN
2582 ((LM_ERROR,
2583 ACE_TEXT ("ACE_WIN32_Asynch_Connect::connect_i: %p\n"),
2584 ACE_TEXT ("setsockopt")),
2585 -1);
2589 if (local_sap != ACE_Addr::sap_any)
2591 sockaddr * laddr = reinterpret_cast<sockaddr *> (local_sap.get_addr ());
2592 int size = local_sap.get_size ();
2593 if (ACE_OS::bind (handle, laddr, size) == -1)
2595 result->set_error (errno);
2596 ACELIB_ERROR_RETURN
2597 ((LM_ERROR,
2598 ACE_TEXT ("ACE_WIN32_Asynch_Connect::connect_i: %p\n"),
2599 ACE_TEXT ("bind")),
2600 -1);
2604 // set non blocking mode
2605 if (ACE::set_flags (handle, ACE_NONBLOCK) != 0)
2607 result->set_error (errno);
2608 ACELIB_ERROR_RETURN
2609 ((LM_ERROR,
2610 ACE_TEXT ("ACE_WIN32_Asynch_Connect::connect_i: %p\n"),
2611 ACE_TEXT ("set_flags")),
2612 -1);
2615 for (;;)
2617 int rc = ACE_OS::connect
2618 (handle,
2619 reinterpret_cast<sockaddr *> (remote_sap.get_addr ()),
2620 remote_sap.get_size ());
2622 if (rc < 0) // failure
2624 if (errno == EWOULDBLOCK || errno == EINPROGRESS)
2625 return 0; // connect started
2627 if (errno == EINTR)
2628 continue;
2630 result->set_error (errno);
2632 return 1 ; // connect finished
2637 // cancel_uncompleted
2638 // It performs cancellation of all pending requests
2640 // Parameter flg_notify can be
2641 // 0 - don't send notifications about canceled accepts
2642 // !0 - notify user about canceled accepts
2643 // according WIN32 standards we should receive notifications
2644 // on canceled AIO requests
2646 // Return value : number of cancelled requests
2650 ACE_WIN32_Asynch_Connect::cancel_uncompleted (bool flg_notify,
2651 ACE_Handle_Set &set)
2653 ACE_TRACE ("ACE_WIN32_Asynch_Connect::cancel_uncompleted");
2655 int retval = 0;
2657 MAP_MANAGER::ITERATOR iter (result_map_);
2658 MAP_MANAGER::ENTRY * me = 0;
2660 set.reset ();
2662 for (; iter.next (me) != 0; retval++, iter.advance ())
2664 ACE_HANDLE handle = me->ext_id_;
2665 ACE_WIN32_Asynch_Connect_Result* result = me->int_id_ ;
2667 set.set_bit (handle);
2669 result->set_bytes_transferred (0);
2670 result->set_error (ERROR_OPERATION_ABORTED);
2671 this->post_result (result, flg_notify);
2674 result_map_.unbind_all ();
2676 return retval;
2680 ACE_WIN32_Asynch_Connect::cancel ()
2682 ACE_TRACE ("ACE_WIN32_Asynch_Connect::cancel");
2684 int rc = -1 ; // ERRORS
2686 ACE_Handle_Set set;
2687 int num_cancelled = 0;
2689 ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1));
2691 num_cancelled = cancel_uncompleted (flg_open_, set);
2693 if (num_cancelled == 0)
2694 rc = 1; // AIO_ALLDONE
2695 else if (num_cancelled > 0)
2696 rc = 0; // AIO_CANCELED
2698 if (!this->flg_open_)
2699 return rc;
2701 ACE_Asynch_Pseudo_Task & task =
2702 this->win32_proactor_->get_asynch_pseudo_task ();
2704 task.remove_io_handler (set);
2705 return rc;
2709 ACE_WIN32_Asynch_Connect::close ()
2711 ACE_TRACE ("ACE_WIN32_Asynch_Connect::close");
2713 ACE_Handle_Set set;
2714 int num_cancelled = 0;
2716 ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1));
2718 num_cancelled = cancel_uncompleted (flg_open_, set);
2720 if (num_cancelled == 0 || this->flg_open_ == 0)
2722 this->flg_open_ = false;
2723 return 0;
2726 ACE_Asynch_Pseudo_Task & task =
2727 this->win32_proactor_->get_asynch_pseudo_task ();
2729 task.remove_io_handler (set);
2730 return 0;
2734 ACE_WIN32_Asynch_Connect::handle_exception (ACE_HANDLE fd)
2736 ACE_TRACE ("ACE_WIN32_Asynch_Connect::handle_exception");
2737 return handle_output (fd);
2741 ACE_WIN32_Asynch_Connect::handle_input (ACE_HANDLE fd)
2743 ACE_TRACE ("ACE_WIN32_Asynch_Connect::handle_input");
2744 return handle_output (fd);
2748 ACE_WIN32_Asynch_Connect::handle_output (ACE_HANDLE fd)
2750 ACE_TRACE ("ACE_WIN32_Asynch_Connect::handle_output");
2752 ACE_WIN32_Asynch_Connect_Result* result = 0;
2755 ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, 0));
2756 if (this->result_map_.unbind (fd, result) != 0) // not found
2757 return -1;
2760 int sockerror = 0 ;
2761 int lsockerror = sizeof sockerror;
2763 ACE_OS::getsockopt (fd,
2764 SOL_SOCKET,
2765 SO_ERROR,
2766 (char*) & sockerror,
2767 & lsockerror);
2769 // This previously just did a "return -1" and let handle_close() clean
2770 // things up. However, this entire object may be gone as a result of
2771 // the application's completion handler, so don't count on 'this' being
2772 // legitimate on return from post_result().
2773 // remove_io_handler() contains flag DONT_CALL
2774 this->win32_proactor_->get_asynch_pseudo_task().remove_io_handler (fd);
2776 result->set_bytes_transferred (0);
2777 result->set_error (sockerror);
2778 this->post_result (result, this->flg_open_);
2779 return 0;
2784 ACE_WIN32_Asynch_Connect::handle_close (ACE_HANDLE fd, ACE_Reactor_Mask)
2786 ACE_TRACE ("ACE_WIN32_Asynch_Connect::handle_close");
2788 ACE_Asynch_Pseudo_Task & task =
2789 this->win32_proactor_->get_asynch_pseudo_task ();
2790 task.remove_io_handler (fd);
2792 ACE_WIN32_Asynch_Connect_Result* result = 0;
2795 ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, 0));
2796 if (this->result_map_.unbind (fd, result) != 0) // not found
2797 return -1;
2800 result->set_bytes_transferred (0);
2801 result->set_error (ERROR_OPERATION_ABORTED);
2802 this->post_result (result, this->flg_open_);
2804 return 0;
2807 // *********************************************************************
2809 ACE_HANDLE
2810 ACE_WIN32_Asynch_Transmit_File_Result::socket () const
2812 return this->socket_;
2815 ACE_HANDLE
2816 ACE_WIN32_Asynch_Transmit_File_Result::file () const
2818 return this->file_;
2821 ACE_Asynch_Transmit_File::Header_And_Trailer *
2822 ACE_WIN32_Asynch_Transmit_File_Result::header_and_trailer () const
2824 return this->header_and_trailer_;
2827 size_t
2828 ACE_WIN32_Asynch_Transmit_File_Result::bytes_to_write () const
2830 return this->bytes_to_write_;
2833 size_t
2834 ACE_WIN32_Asynch_Transmit_File_Result::bytes_per_send () const
2836 return this->bytes_per_send_;
2839 u_long
2840 ACE_WIN32_Asynch_Transmit_File_Result::flags () const
2842 return this->flags_;
2845 ACE_WIN32_Asynch_Transmit_File_Result::ACE_WIN32_Asynch_Transmit_File_Result (
2846 const ACE_Handler::Proxy_Ptr &handler_proxy,
2847 ACE_HANDLE socket,
2848 ACE_HANDLE file,
2849 ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer,
2850 size_t bytes_to_write,
2851 u_long offset,
2852 u_long offset_high,
2853 size_t bytes_per_send,
2854 u_long flags,
2855 const void *act,
2856 ACE_HANDLE event,
2857 int priority,
2858 int signal_number)
2859 : ACE_Asynch_Result_Impl (),
2860 ACE_Asynch_Transmit_File_Result_Impl (),
2861 ACE_WIN32_Asynch_Result (handler_proxy,
2862 act,
2863 event,
2864 offset,
2865 offset_high,
2866 priority,
2867 signal_number),
2868 socket_ (socket),
2869 file_ (file),
2870 header_and_trailer_ (header_and_trailer),
2871 bytes_to_write_ (bytes_to_write),
2872 bytes_per_send_ (bytes_per_send),
2873 flags_ (flags)
2877 void
2878 ACE_WIN32_Asynch_Transmit_File_Result::complete (size_t bytes_transferred,
2879 int success,
2880 const void *completion_key,
2881 u_long error)
2883 // Copy the data which was returned by GetQueuedCompletionStatus
2884 this->bytes_transferred_ = bytes_transferred;
2885 this->success_ = success;
2886 this->completion_key_ = completion_key;
2887 this->error_ = error;
2889 // We will not do this because (a) the header and trailer blocks may
2890 // be the same message_blocks and (b) in cases of failures we have
2891 // no idea how much of what (header, data, trailer) was sent.
2893 if (this->success_ && this->header_and_trailer_ != 0)
2895 ACE_Message_Block *header = this->header_and_trailer_->header ();
2896 if (header != 0)
2897 header->rd_ptr (this->header_and_trailer_->header_bytes ());
2899 ACE_Message_Block *trailer = this->header_and_trailer_->trailer ();
2900 if (trailer != 0)
2901 trailer->rd_ptr (this->header_and_trailer_->trailer_bytes ());
2905 // Create the interface result class.
2906 ACE_Asynch_Transmit_File::Result result (this);
2908 // Call the application handler.
2909 ACE_Handler *handler = this->handler_proxy_.get ()->handler ();
2910 if (handler != 0)
2911 handler->handle_transmit_file (result);
2914 ACE_WIN32_Asynch_Transmit_File_Result::~ACE_WIN32_Asynch_Transmit_File_Result ()
2918 // Base class operations. These operations are here to kill dominance
2919 // warnings. These methods call the base class methods.
2921 size_t
2922 ACE_WIN32_Asynch_Transmit_File_Result::bytes_transferred () const
2924 return ACE_WIN32_Asynch_Result::bytes_transferred ();
2927 const void *
2928 ACE_WIN32_Asynch_Transmit_File_Result::act () const
2930 return ACE_WIN32_Asynch_Result::act ();
2934 ACE_WIN32_Asynch_Transmit_File_Result::success () const
2936 return ACE_WIN32_Asynch_Result::success ();
2939 const void *
2940 ACE_WIN32_Asynch_Transmit_File_Result::completion_key () const
2942 return ACE_WIN32_Asynch_Result::completion_key ();
2945 u_long
2946 ACE_WIN32_Asynch_Transmit_File_Result::error () const
2948 return ACE_WIN32_Asynch_Result::error ();
2951 ACE_HANDLE
2952 ACE_WIN32_Asynch_Transmit_File_Result::event () const
2954 return ACE_WIN32_Asynch_Result::event ();
2957 u_long
2958 ACE_WIN32_Asynch_Transmit_File_Result::offset () const
2960 return ACE_WIN32_Asynch_Result::offset ();
2963 u_long
2964 ACE_WIN32_Asynch_Transmit_File_Result::offset_high () const
2966 return ACE_WIN32_Asynch_Result::offset_high ();
2970 ACE_WIN32_Asynch_Transmit_File_Result::priority () const
2972 return ACE_WIN32_Asynch_Result::priority ();
2976 ACE_WIN32_Asynch_Transmit_File_Result::signal_number () const
2978 return ACE_WIN32_Asynch_Result::signal_number ();
2982 ACE_WIN32_Asynch_Transmit_File_Result::post_completion (ACE_Proactor_Impl *proactor)
2984 return ACE_WIN32_Asynch_Result::post_completion (proactor);
2987 ACE_WIN32_Asynch_Transmit_File::ACE_WIN32_Asynch_Transmit_File (ACE_WIN32_Proactor *win32_proactor)
2988 : ACE_Asynch_Operation_Impl (),
2989 ACE_Asynch_Transmit_File_Impl (),
2990 ACE_WIN32_Asynch_Operation (win32_proactor)
2995 ACE_WIN32_Asynch_Transmit_File::transmit_file (ACE_HANDLE file,
2996 ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer,
2997 size_t bytes_to_write,
2998 u_long offset,
2999 u_long offset_high,
3000 size_t bytes_per_send,
3001 u_long flags,
3002 const void *act,
3003 int priority,
3004 int signal_number)
3006 #if defined (ACE_HAS_WIN32_OVERLAPPED_IO) || (defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0))
3008 // TransmitFile API limits us to DWORD range.
3009 if (bytes_to_write > MAXDWORD || bytes_per_send > MAXDWORD)
3011 errno = ERANGE;
3012 return -1;
3014 DWORD dword_bytes_to_write = static_cast<DWORD> (bytes_to_write);
3015 DWORD dword_bytes_per_send = static_cast<DWORD> (bytes_per_send);
3017 ACE_WIN32_Asynch_Transmit_File_Result *result = 0;
3018 ACE_NEW_RETURN (result,
3019 ACE_WIN32_Asynch_Transmit_File_Result (this->handler_proxy_,
3020 this->handle_,
3021 file,
3022 header_and_trailer,
3023 bytes_to_write,
3024 offset,
3025 offset_high,
3026 bytes_per_send,
3027 flags,
3028 act,
3029 this->win32_proactor_->get_handle (),
3030 priority,
3031 signal_number),
3032 -1);
3034 ACE_LPTRANSMIT_FILE_BUFFERS transmit_buffers = 0;
3035 if (result->header_and_trailer () != 0)
3036 transmit_buffers = result->header_and_trailer ()->transmit_buffers ();
3038 // Initiate the transmit file
3039 int initiate_result = ::TransmitFile ((SOCKET) result->socket (),
3040 result->file (),
3041 dword_bytes_to_write,
3042 dword_bytes_per_send,
3043 result,
3044 transmit_buffers,
3045 result->flags ());
3046 if (initiate_result == 1)
3047 // Immediate success: the OVERLAPPED will still get queued.
3048 return 1;
3050 // If initiate failed, check for a bad error.
3051 ACE_OS::set_errno_to_last_error ();
3052 switch (errno)
3054 case ERROR_IO_PENDING:
3055 // The IO will complete proactively: the OVERLAPPED will still
3056 // get queued.
3057 return 0;
3059 default:
3060 // Something else went wrong: the OVERLAPPED will not get
3061 // queued.
3063 // Cleanup dynamically allocated Asynch_Result
3064 delete result;
3066 if (ACE::debug ())
3068 ACELIB_DEBUG ((LM_ERROR,
3069 ACE_TEXT ("%p\n"),
3070 ACE_TEXT ("TransmitFile")));
3072 return -1;
3074 #else
3075 ACE_UNUSED_ARG (file);
3076 ACE_UNUSED_ARG (header_and_trailer);
3077 ACE_UNUSED_ARG (bytes_to_write);
3078 ACE_UNUSED_ARG (offset);
3079 ACE_UNUSED_ARG (offset_high);
3080 ACE_UNUSED_ARG (bytes_per_send);
3081 ACE_UNUSED_ARG (flags);
3082 ACE_UNUSED_ARG (act);
3083 ACE_UNUSED_ARG (priority);
3084 ACE_UNUSED_ARG (signal_number);
3085 ACE_NOTSUP_RETURN (-1);
3086 #endif /* ACE_HAS_WIN32_OVERLAPPED_IO || ACE_HAS_WINSOCK2 */
3089 ACE_WIN32_Asynch_Transmit_File::~ACE_WIN32_Asynch_Transmit_File ()
3093 // Methods belong to ACE_WIN32_Asynch_Operation base class. These
3094 // methods are defined here to avoid VC++ warnings. They route the
3095 // call to the ACE_WIN32_Asynch_Operation base class.
3098 ACE_WIN32_Asynch_Transmit_File::open (const ACE_Handler::Proxy_Ptr &handler_proxy,
3099 ACE_HANDLE handle,
3100 const void *completion_key,
3101 ACE_Proactor *proactor)
3103 return ACE_WIN32_Asynch_Operation::open (handler_proxy,
3104 handle,
3105 completion_key,
3106 proactor);
3110 ACE_WIN32_Asynch_Transmit_File::cancel ()
3112 return ACE_WIN32_Asynch_Operation::cancel ();
3115 ACE_Proactor *
3116 ACE_WIN32_Asynch_Transmit_File::proactor () const
3118 return ACE_WIN32_Asynch_Operation::proactor ();
3121 size_t
3122 ACE_WIN32_Asynch_Read_Dgram_Result::bytes_to_read () const
3124 return this->bytes_to_read_;
3127 ACE_Message_Block*
3128 ACE_WIN32_Asynch_Read_Dgram_Result::message_block () const
3130 return this->message_block_;
3135 ACE_WIN32_Asynch_Read_Dgram_Result::remote_address (ACE_Addr& addr) const
3137 int retVal = -1; // failure
3139 // make sure the addresses are of the same type
3140 if (addr.get_type () == this->remote_address_->get_type ())
3141 { // copy the remote_address_ into addr
3142 addr.set_addr (this->remote_address_->get_addr (),
3143 this->remote_address_->get_size ());
3144 retVal = 0; // success
3147 return retVal;
3150 sockaddr *
3151 ACE_WIN32_Asynch_Read_Dgram_Result::saddr () const
3153 return (sockaddr *) this->remote_address_->get_addr ();
3158 ACE_WIN32_Asynch_Read_Dgram_Result::flags () const
3160 return this->flags_;
3163 ACE_HANDLE
3164 ACE_WIN32_Asynch_Read_Dgram_Result::handle () const
3166 return this->handle_;
3169 size_t
3170 ACE_WIN32_Asynch_Read_Dgram_Result::bytes_transferred () const
3172 return ACE_WIN32_Asynch_Result::bytes_transferred ();
3175 const void *
3176 ACE_WIN32_Asynch_Read_Dgram_Result::act () const
3178 return ACE_WIN32_Asynch_Result::act ();
3182 ACE_WIN32_Asynch_Read_Dgram_Result::success () const
3184 return ACE_WIN32_Asynch_Result::success ();
3187 const void *
3188 ACE_WIN32_Asynch_Read_Dgram_Result::completion_key () const
3190 return ACE_WIN32_Asynch_Result::completion_key ();
3193 u_long
3194 ACE_WIN32_Asynch_Read_Dgram_Result::error () const
3196 return ACE_WIN32_Asynch_Result::error ();
3199 ACE_HANDLE
3200 ACE_WIN32_Asynch_Read_Dgram_Result::event () const
3202 return ACE_WIN32_Asynch_Result::event ();
3205 u_long
3206 ACE_WIN32_Asynch_Read_Dgram_Result::offset () const
3208 return ACE_WIN32_Asynch_Result::offset ();
3211 u_long
3212 ACE_WIN32_Asynch_Read_Dgram_Result::offset_high () const
3214 return ACE_WIN32_Asynch_Result::offset_high ();
3218 ACE_WIN32_Asynch_Read_Dgram_Result::priority () const
3220 return ACE_WIN32_Asynch_Result::priority ();
3224 ACE_WIN32_Asynch_Read_Dgram_Result::signal_number () const
3226 return ACE_WIN32_Asynch_Result::signal_number ();
3230 ACE_WIN32_Asynch_Read_Dgram_Result::post_completion (ACE_Proactor_Impl *proactor)
3232 return ACE_WIN32_Asynch_Result::post_completion (proactor);
3235 ACE_WIN32_Asynch_Read_Dgram_Result::ACE_WIN32_Asynch_Read_Dgram_Result (
3236 const ACE_Handler::Proxy_Ptr &handler_proxy,
3237 ACE_HANDLE handle,
3238 ACE_Message_Block *message_block,
3239 size_t bytes_to_read,
3240 int flags,
3241 int protocol_family,
3242 const void* act,
3243 ACE_HANDLE event,
3244 int priority,
3245 int signal_number)
3246 : ACE_Asynch_Result_Impl (),
3247 ACE_Asynch_Read_Dgram_Result_Impl(),
3248 ACE_WIN32_Asynch_Result (handler_proxy, act, event, 0, 0, priority, signal_number),
3249 bytes_to_read_ (bytes_to_read),
3250 message_block_ (message_block),
3251 remote_address_ (0),
3252 addr_len_ (0),
3253 flags_ (flags),
3254 handle_ (handle)
3256 ACE_ASSERT (protocol_family == PF_INET); // only supporting INET addresses
3258 ACE_NEW (remote_address_, ACE_INET_Addr);
3259 addr_len_ = remote_address_->get_size ();
3261 ACE_UNUSED_ARG (protocol_family);
3264 void
3265 ACE_WIN32_Asynch_Read_Dgram_Result::complete (size_t bytes_transferred,
3266 int success,
3267 const void *completion_key,
3268 u_long error)
3270 // Copy the data which was returned by GetQueuedCompletionStatus
3271 this->bytes_transferred_ = bytes_transferred;
3272 this->success_ = success;
3273 this->completion_key_ = completion_key;
3274 this->error_ = error;
3276 // Appropriately move the pointers in the message block.
3277 for (ACE_Message_Block* mb = this->message_block_;
3278 (mb != 0) && (bytes_transferred > 0);
3279 mb = mb->cont ())
3281 size_t len_part = mb->space ();
3283 if ( len_part > bytes_transferred)
3284 len_part = bytes_transferred;
3286 mb->wr_ptr (len_part);
3288 bytes_transferred -= len_part;
3291 // Adjust the address length
3292 this->remote_address_->set_size (this->addr_len_);
3294 // Create the interface result class.
3295 ACE_Asynch_Read_Dgram::Result result (this);
3297 // Call the application handler.
3298 ACE_Handler *handler = this->handler_proxy_.get ()->handler ();
3299 if (handler != 0)
3300 handler->handle_read_dgram (result);
3303 ACE_WIN32_Asynch_Read_Dgram_Result::~ACE_WIN32_Asynch_Read_Dgram_Result ()
3305 delete this->remote_address_;
3308 //***************************************************************************
3310 ACE_WIN32_Asynch_Read_Dgram::~ACE_WIN32_Asynch_Read_Dgram ()
3314 ssize_t
3315 ACE_WIN32_Asynch_Read_Dgram::recv (ACE_Message_Block *message_block,
3316 size_t & number_of_bytes_recvd,
3317 int flags,
3318 int protocol_family,
3319 const void *act,
3320 int priority,
3321 int signal_number)
3323 number_of_bytes_recvd = 0;
3325 size_t bytes_to_read = 0;
3327 iovec iov[ACE_IOV_MAX];
3328 int iovcnt = 0;
3330 for (const ACE_Message_Block* msg = message_block;
3331 msg != 0 && iovcnt < ACE_IOV_MAX;
3332 msg = msg->cont () , ++iovcnt )
3334 size_t msg_space = msg->space ();
3336 // OS should correctly process zero length buffers
3337 // if ( msg_space == 0 )
3338 // ACELIB_ERROR_RETURN ((LM_ERROR,
3339 // ACE_TEXT ("ACE_WIN32_Asynch_Read_Dgram::recv:")
3340 // ACE_TEXT ("No space in the message block\n")),
3341 // -1);
3343 bytes_to_read += msg_space;
3345 // Make as many iovec as needed to fit all of msg_len.
3346 size_t wr_ptr_offset = 0;
3348 while (msg_space > 0 && iovcnt < ACE_IOV_MAX)
3350 u_long this_chunk_length;
3351 if (msg_space > ULONG_MAX)
3352 this_chunk_length = ULONG_MAX;
3353 else
3354 this_chunk_length = static_cast<u_long> (msg_space);
3355 // Collect the data in the iovec.
3356 iov[iovcnt].iov_base = msg->wr_ptr () + wr_ptr_offset;
3357 iov[iovcnt].iov_len = this_chunk_length;
3358 msg_space -= this_chunk_length;
3359 wr_ptr_offset += this_chunk_length;
3361 // Increment iovec counter if there's more to do.
3362 if (msg_space > 0)
3363 iovcnt++;
3365 if (msg_space > 0) // Ran out of iovecs before msg_space exhausted
3367 errno = ERANGE;
3368 return -1;
3372 if (bytes_to_read == 0)
3373 ACELIB_ERROR_RETURN ((LM_ERROR,
3374 ACE_TEXT ("ACE_WIN32_Asynch_Read_Dgram::recv:")
3375 ACE_TEXT ("Attempt to read 0 bytes\n")),
3376 -1);
3378 // Create the Asynch_Result.
3379 ACE_WIN32_Asynch_Read_Dgram_Result *result = 0;
3380 ACE_NEW_RETURN (result,
3381 ACE_WIN32_Asynch_Read_Dgram_Result (this->handler_proxy_,
3382 this->handle_,
3383 message_block,
3384 bytes_to_read,
3385 flags,
3386 protocol_family,
3387 act,
3388 this->win32_proactor_->get_handle (),
3389 priority,
3390 signal_number),
3391 -1);
3393 // do the scatter/gather recv
3394 // NOTE! The flags value is in/out to recvfrom() - it's changed AFTER
3395 // the call to WSARecvFrom returns and if it completes immediately, the
3396 // result object may already be deleted. Since the changed value is not
3397 // used, and not needed by result, pass a copy to avoid the race.
3398 ssize_t initiate_result = ACE_OS::recvfrom (result->handle (),
3399 iov,
3400 iovcnt,
3401 number_of_bytes_recvd,
3402 flags,
3403 result->saddr (),
3404 &(result->addr_len_),
3405 result,
3407 if (initiate_result == SOCKET_ERROR)
3409 // If initiate failed, check for a bad error.
3410 ACE_OS::set_errno_to_last_error ();
3411 switch (errno)
3413 case ERROR_IO_PENDING:
3414 // The IO will complete proactively: the OVERLAPPED will still
3415 // get queued.
3416 initiate_result = 0;
3417 break;
3419 default:
3420 // Something else went wrong: the OVERLAPPED will not get
3421 // queued.
3423 if (ACE::debug ())
3425 ACELIB_DEBUG ((LM_ERROR,
3426 ACE_TEXT ("%p\n"),
3427 ACE_TEXT ("WSARecvFrom")));
3430 delete result;
3431 initiate_result = -1;
3432 break;
3436 else
3438 // Immediate success: the OVERLAPPED will still get queued.
3439 // number_of_bytes_recvd contains the number of bytes recvd
3440 // addr contains the peer address
3441 // flags was updated
3443 // number_of_bytes_recvd = bytes_recvd;
3444 initiate_result = 1;
3447 return initiate_result;
3451 ACE_WIN32_Asynch_Read_Dgram::open (const ACE_Handler::Proxy_Ptr &handler_proxy,
3452 ACE_HANDLE handle,
3453 const void *completion_key,
3454 ACE_Proactor *proactor)
3456 return ACE_WIN32_Asynch_Operation::open (handler_proxy,
3457 handle,
3458 completion_key,
3459 proactor);
3463 ACE_WIN32_Asynch_Read_Dgram::cancel ()
3465 return ACE_WIN32_Asynch_Operation::cancel ();
3468 ACE_Proactor *
3469 ACE_WIN32_Asynch_Read_Dgram::proactor () const
3471 return ACE_WIN32_Asynch_Operation::proactor ();
3474 ACE_WIN32_Asynch_Read_Dgram::ACE_WIN32_Asynch_Read_Dgram (ACE_WIN32_Proactor *win32_proactor)
3475 : ACE_Asynch_Operation_Impl (),
3476 ACE_Asynch_Read_Dgram_Impl (),
3477 ACE_WIN32_Asynch_Operation (win32_proactor)
3481 //***********************************************
3483 size_t
3484 ACE_WIN32_Asynch_Write_Dgram_Result::bytes_to_write () const
3486 return this->bytes_to_write_;
3489 ACE_Message_Block*
3490 ACE_WIN32_Asynch_Write_Dgram_Result::message_block () const
3492 return this->message_block_;
3496 ACE_WIN32_Asynch_Write_Dgram_Result::flags () const
3498 return this->flags_;
3501 ACE_HANDLE
3502 ACE_WIN32_Asynch_Write_Dgram_Result::handle () const
3504 return this->handle_;
3507 size_t
3508 ACE_WIN32_Asynch_Write_Dgram_Result::bytes_transferred () const
3510 return ACE_WIN32_Asynch_Result::bytes_transferred ();
3513 const void *
3514 ACE_WIN32_Asynch_Write_Dgram_Result::act () const
3516 return ACE_WIN32_Asynch_Result::act ();
3520 ACE_WIN32_Asynch_Write_Dgram_Result::success () const
3522 return ACE_WIN32_Asynch_Result::success ();
3525 const void *
3526 ACE_WIN32_Asynch_Write_Dgram_Result::completion_key () const
3528 return ACE_WIN32_Asynch_Result::completion_key ();
3531 u_long
3532 ACE_WIN32_Asynch_Write_Dgram_Result::error () const
3534 return ACE_WIN32_Asynch_Result::error ();
3537 ACE_HANDLE
3538 ACE_WIN32_Asynch_Write_Dgram_Result::event () const
3540 return ACE_WIN32_Asynch_Result::event ();
3543 u_long
3544 ACE_WIN32_Asynch_Write_Dgram_Result::offset () const
3546 return ACE_WIN32_Asynch_Result::offset ();
3549 u_long
3550 ACE_WIN32_Asynch_Write_Dgram_Result::offset_high () const
3552 return ACE_WIN32_Asynch_Result::offset_high ();
3556 ACE_WIN32_Asynch_Write_Dgram_Result::priority () const
3558 return ACE_WIN32_Asynch_Result::priority ();
3562 ACE_WIN32_Asynch_Write_Dgram_Result::signal_number () const
3564 return ACE_WIN32_Asynch_Result::signal_number ();
3568 ACE_WIN32_Asynch_Write_Dgram_Result::post_completion (ACE_Proactor_Impl *proactor)
3570 return ACE_WIN32_Asynch_Result::post_completion (proactor);
3573 ACE_WIN32_Asynch_Write_Dgram_Result::ACE_WIN32_Asynch_Write_Dgram_Result (
3574 const ACE_Handler::Proxy_Ptr &handler_proxy,
3575 ACE_HANDLE handle,
3576 ACE_Message_Block *message_block,
3577 size_t bytes_to_write,
3578 int flags,
3579 const void* act,
3580 ACE_HANDLE event,
3581 int priority,
3582 int signal_number)
3583 : ACE_Asynch_Result_Impl (),
3584 ACE_Asynch_Write_Dgram_Result_Impl(),
3585 ACE_WIN32_Asynch_Result (handler_proxy,
3586 act,
3587 event,
3590 priority,
3591 signal_number),
3592 bytes_to_write_ (bytes_to_write),
3593 message_block_ (message_block),
3594 flags_ (flags),
3595 handle_ (handle)
3599 void
3600 ACE_WIN32_Asynch_Write_Dgram_Result::complete (size_t bytes_transferred,
3601 int success,
3602 const void *completion_key,
3603 u_long error)
3605 // Copy the data which was returned by GetQueuedCompletionStatus
3606 this->bytes_transferred_ = bytes_transferred;
3607 this->success_ = success;
3608 this->completion_key_ = completion_key;
3609 this->error_ = error;
3611 // Appropriately move the pointers in the message block.
3612 for (ACE_Message_Block* mb = this->message_block_;
3613 (mb != 0) && (bytes_transferred > 0);
3614 mb = mb->cont ())
3616 size_t len_part = mb->length ();
3618 if ( len_part > bytes_transferred)
3619 len_part = bytes_transferred;
3621 mb->rd_ptr (len_part);
3623 bytes_transferred -= len_part;
3626 // Create the interface result class.
3627 ACE_Asynch_Write_Dgram::Result result (this);
3629 // Call the application handler.
3630 ACE_Handler *handler = this->handler_proxy_.get ()->handler ();
3631 if (handler != 0)
3632 handler->handle_write_dgram (result);
3635 ACE_WIN32_Asynch_Write_Dgram_Result::~ACE_WIN32_Asynch_Write_Dgram_Result ()
3640 //***********************************************
3642 ACE_WIN32_Asynch_Write_Dgram::~ACE_WIN32_Asynch_Write_Dgram ()
3646 ssize_t
3647 ACE_WIN32_Asynch_Write_Dgram::send (ACE_Message_Block *message_block,
3648 size_t &number_of_bytes_sent,
3649 int flags,
3650 const ACE_Addr &addr,
3651 const void *act,
3652 int priority,
3653 int signal_number)
3655 number_of_bytes_sent = 0;
3657 size_t bytes_to_write = 0;
3659 iovec iov[ACE_IOV_MAX];
3660 int iovcnt = 0;
3662 for (const ACE_Message_Block* msg = message_block;
3663 msg != 0 && iovcnt < ACE_IOV_MAX;
3664 msg = msg->cont () , ++iovcnt )
3666 size_t msg_len = msg->length ();
3668 bytes_to_write += msg_len;
3670 // Make as many iovec as needed to fit all of msg_len.
3671 size_t rd_ptr_offset = 0;
3675 //if (msg_len >= 0 && iovcnt < ACE_IOV_MAX)
3676 // msg_len >= 0 is always true since msg_len is unsigned
3677 if (iovcnt < ACE_IOV_MAX)
3679 u_long this_chunk_length;
3680 if (msg_len > ULONG_MAX)
3681 this_chunk_length = ULONG_MAX;
3682 else
3683 this_chunk_length = static_cast<u_long> (msg_len);
3685 // Collect the data in the iovec.
3686 iov[iovcnt].iov_base = msg->rd_ptr () + rd_ptr_offset;
3687 iov[iovcnt].iov_len = this_chunk_length;
3688 msg_len -= this_chunk_length;
3689 rd_ptr_offset += this_chunk_length;
3691 // Increment iovec counter if there's more to do.
3692 if (msg_len > 0)
3693 iovcnt++;
3696 while (msg_len > 0 && iovcnt < ACE_IOV_MAX);
3698 if (msg_len > 0) // Ran out of iovecs before msg_space exhausted
3700 errno = ERANGE;
3701 return -1;
3705 // Create the Asynch_Result.
3706 ACE_WIN32_Asynch_Write_Dgram_Result *result = 0;
3707 ACE_NEW_RETURN (result,
3708 ACE_WIN32_Asynch_Write_Dgram_Result (this->handler_proxy_,
3709 this->handle_,
3710 message_block,
3711 bytes_to_write,
3712 flags,
3713 act,
3714 this->win32_proactor_->get_handle (),
3715 priority,
3716 signal_number),
3717 -1);
3719 // do the scatter/gather send
3721 ssize_t initiate_result = ACE_OS::sendto (result->handle (),
3722 iov,
3723 iovcnt,
3724 number_of_bytes_sent,
3725 result->flags_,
3726 (sockaddr *) addr.get_addr (),
3727 addr.get_size(),
3728 result,
3732 if (initiate_result == SOCKET_ERROR)
3734 // If initiate failed, check for a bad error.
3735 ACE_OS::set_errno_to_last_error ();
3736 switch (errno)
3738 case ERROR_IO_PENDING:
3739 // The IO will complete proactively: the OVERLAPPED will still
3740 // get queued.
3741 initiate_result = 0;
3742 break;
3744 default:
3745 // Something else went wrong: the OVERLAPPED will not get
3746 // queued.
3748 if (ACE::debug ())
3750 ACELIB_DEBUG ((LM_ERROR,
3751 ACE_TEXT ("%p\n"),
3752 ACE_TEXT ("WSASendTo")));
3755 delete result;
3756 initiate_result = -1;
3757 break;
3761 else
3763 // Immediate success: the OVERLAPPED will still get queued.
3764 // number_of_bytes_recvd contains the number of bytes recvd
3765 // addr contains the peer address
3766 // flags was updated
3768 // number_of_bytes_sent = bytes_sent;
3769 initiate_result = 1;
3772 return initiate_result;
3776 ACE_WIN32_Asynch_Write_Dgram::open (const ACE_Handler::Proxy_Ptr &handler_proxy,
3777 ACE_HANDLE handle,
3778 const void *completion_key,
3779 ACE_Proactor *proactor)
3781 return ACE_WIN32_Asynch_Operation::open (handler_proxy,
3782 handle,
3783 completion_key,
3784 proactor);
3788 ACE_WIN32_Asynch_Write_Dgram::cancel ()
3790 return ACE_WIN32_Asynch_Operation::cancel ();
3793 ACE_Proactor *
3794 ACE_WIN32_Asynch_Write_Dgram::proactor () const
3796 return ACE_WIN32_Asynch_Operation::proactor ();
3799 ACE_WIN32_Asynch_Write_Dgram::ACE_WIN32_Asynch_Write_Dgram (ACE_WIN32_Proactor *win32_proactor)
3800 : ACE_Asynch_Operation_Impl (),
3801 ACE_Asynch_Write_Dgram_Impl (),
3802 ACE_WIN32_Asynch_Operation (win32_proactor)
3806 ACE_END_VERSIONED_NAMESPACE_DECL
3808 #endif /* ACE_HAS_WIN32_OVERLAPPED_IO && ACE_HAS_WINSOCK2 */