server/dep/ACE_wrappers/ace/WIN32_Asynch_IO.cpp
Neo2003 23c920ca4b [10643] Update the ACE part we use to 5.8.2
Signed-off-by: Neo2003 <Neo.2003@Hotmail.fr>
2010-10-25 20:36:51 +02:00

3778 lines
106 KiB
C++

// $Id: WIN32_Asynch_IO.cpp 91368 2010-08-16 13:03:34Z mhengstmengel $
#include "ace/WIN32_Asynch_IO.h"
#if defined (ACE_HAS_WIN32_OVERLAPPED_IO) && \
(defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 == 1))
#include "ace/WIN32_Proactor.h"
#include "ace/Proactor.h"
#include "ace/Message_Block.h"
#include "ace/Service_Config.h"
#include "ace/INET_Addr.h"
#include "ace/Task_T.h"
#include "ace/OS_NS_errno.h"
#include "ace/OS_NS_unistd.h"
#include "ace/OS_NS_sys_socket.h"
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
size_t
ACE_WIN32_Asynch_Result::bytes_transferred (void) const
{
return this->bytes_transferred_;
}
const void *
ACE_WIN32_Asynch_Result::act (void) const
{
return this->act_;
}
int
ACE_WIN32_Asynch_Result::success (void) const
{
return this->success_;
}
const void *
ACE_WIN32_Asynch_Result::completion_key (void) const
{
return this->completion_key_;
}
u_long
ACE_WIN32_Asynch_Result::error (void) const
{
return this->error_;
}
ACE_HANDLE
ACE_WIN32_Asynch_Result::event (void) const
{
return this->hEvent;
}
u_long
ACE_WIN32_Asynch_Result::offset (void) const
{
return this->Offset;
}
u_long
ACE_WIN32_Asynch_Result::offset_high (void) const
{
return this->OffsetHigh;
}
int
ACE_WIN32_Asynch_Result::priority (void) const
{
ACE_NOTSUP_RETURN (0);
}
int
ACE_WIN32_Asynch_Result::signal_number (void) const
{
ACE_NOTSUP_RETURN (0);
}
int
ACE_WIN32_Asynch_Result::post_completion (ACE_Proactor_Impl *proactor)
{
// Get to the platform specific implementation.
ACE_WIN32_Proactor *win32_proactor = dynamic_cast<ACE_WIN32_Proactor *> (proactor);
if (win32_proactor == 0)
ACE_ERROR_RETURN ((LM_ERROR,
ACE_TEXT ("Dynamic cast to WIN32 Proactor failed\n")),
-1);
// Post myself.
return win32_proactor->post_completion (this);
}
void
ACE_WIN32_Asynch_Result::set_bytes_transferred (size_t nbytes)
{
this->bytes_transferred_ = nbytes;
}
void
ACE_WIN32_Asynch_Result::set_error (u_long errcode)
{
this->error_ = errcode;
}
ACE_WIN32_Asynch_Result::~ACE_WIN32_Asynch_Result (void)
{
}
ACE_WIN32_Asynch_Result::ACE_WIN32_Asynch_Result
(const ACE_Handler::Proxy_Ptr &handler_proxy,
const void* act,
ACE_HANDLE event,
u_long offset,
u_long offset_high,
int priority,
int signal_number)
: ACE_Asynch_Result_Impl (),
OVERLAPPED (),
handler_proxy_ (handler_proxy),
act_ (act),
bytes_transferred_ (0),
success_ (0),
completion_key_ (0),
error_ (0)
{
// Set the ACE_OVERLAPPED structure
this->Internal = 0;
this->InternalHigh = 0;
this->Offset = offset;
this->OffsetHigh = offset_high;
this->hEvent = event;
ACE_UNUSED_ARG (priority);
ACE_UNUSED_ARG (signal_number);
}
int
ACE_WIN32_Asynch_Operation::open (const ACE_Handler::Proxy_Ptr &handler_proxy,
ACE_HANDLE handle,
const void *completion_key,
ACE_Proactor *proactor)
{
this->proactor_ = proactor;
this->handler_proxy_ = handler_proxy;
this->handle_ = handle;
// Grab the handle from the <handler> if <handle> is invalid
if (this->handle_ == ACE_INVALID_HANDLE)
{
ACE_Handler *handler = handler_proxy.get ()->handler ();
if (handler != 0)
this->handle_ = handler->handle ();
}
if (this->handle_ == ACE_INVALID_HANDLE)
return -1;
if (this->proactor_!= 0)
// update implementation.
this->win32_proactor_ =
dynamic_cast <ACE_WIN32_Proactor *>(this->proactor_->implementation ());
// Register with the <proactor>.
return this->win32_proactor_->register_handle (this->handle_,
completion_key);
}
int
ACE_WIN32_Asynch_Operation::cancel (void)
{
#if defined (ACE_HAS_WIN32_OVERLAPPED_IO)
// All I/O operations that are canceled will complete with the error
// ERROR_OPERATION_ABORTED. All completion notifications for the I/O
// operations will occur normally.
// @@ This API returns 0 on failure. So, I am returning -1 in that
// case. Is that right? (Alex).
int const result = (int) ::CancelIo (this->handle_);
if (result == 0)
// Couldn't cancel the operations.
return 2;
// result is non-zero. All the operations are cancelled then.
return 0;
#else /* !ACE_HAS_WIN32_OVERLAPPED_IO */
ACE_NOTSUP_RETURN (-1);
#endif /* ACE_HAS_AIO_CALLS */
}
ACE_Proactor *
ACE_WIN32_Asynch_Operation::proactor (void) const
{
return this->proactor_;
}
ACE_WIN32_Asynch_Operation::ACE_WIN32_Asynch_Operation (ACE_WIN32_Proactor *win32_proactor)
: ACE_Asynch_Operation_Impl (),
win32_proactor_ (win32_proactor),
proactor_ (0),
handle_ (ACE_INVALID_HANDLE)
{
}
ACE_WIN32_Asynch_Operation::~ACE_WIN32_Asynch_Operation (void)
{
}
// ************************************************************
size_t
ACE_WIN32_Asynch_Read_Stream_Result::bytes_to_read (void) const
{
return this->bytes_to_read_;
}
ACE_Message_Block &
ACE_WIN32_Asynch_Read_Stream_Result::message_block (void) const
{
return this->message_block_;
}
ACE_HANDLE
ACE_WIN32_Asynch_Read_Stream_Result::handle (void) const
{
return this->handle_;
}
ACE_WIN32_Asynch_Read_Stream_Result::ACE_WIN32_Asynch_Read_Stream_Result (
const ACE_Handler::Proxy_Ptr &handler_proxy,
ACE_HANDLE handle,
ACE_Message_Block &message_block,
size_t bytes_to_read,
const void* act,
ACE_HANDLE event,
int priority,
int signal_number,
int scatter_enabled)
: ACE_Asynch_Result_Impl (),
ACE_Asynch_Read_Stream_Result_Impl (),
ACE_WIN32_Asynch_Result (handler_proxy,
act,
event,
0,
0,
priority,
signal_number),
bytes_to_read_ (bytes_to_read),
message_block_ (message_block),
handle_ (handle),
scatter_enabled_ (scatter_enabled)
{
}
void
ACE_WIN32_Asynch_Read_Stream_Result::complete (size_t bytes_transferred,
int success,
const void *completion_key,
u_long error)
{
// Copy the data which was returned by GetQueuedCompletionStatus
this->bytes_transferred_ = bytes_transferred;
this->success_ = success;
this->completion_key_ = completion_key;
this->error_ = error;
// Appropriately move the pointers in the message block.
if (!this->scatter_enabled ())
this->message_block_.wr_ptr (bytes_transferred);
else
{
for (ACE_Message_Block* mb = &this->message_block_;
(mb != 0) && (bytes_transferred > 0);
mb = mb->cont ())
{
size_t len_part = mb->space ();
if (len_part > bytes_transferred)
len_part = bytes_transferred;
mb->wr_ptr (len_part);
bytes_transferred -= len_part;
}
}
// Create the interface result class.
ACE_Asynch_Read_Stream::Result result (this);
// Call the application handler.
ACE_Handler *handler = this->handler_proxy_.get ()->handler ();
if (handler != 0)
handler->handle_read_stream (result);
}
ACE_WIN32_Asynch_Read_Stream_Result::~ACE_WIN32_Asynch_Read_Stream_Result (void)
{
}
// Base class operations. These operations are here to kill dominance
// warnings. These methods call the base class methods.
size_t
ACE_WIN32_Asynch_Read_Stream_Result::bytes_transferred (void) const
{
return ACE_WIN32_Asynch_Result::bytes_transferred ();
}
const void *
ACE_WIN32_Asynch_Read_Stream_Result::act (void) const
{
return ACE_WIN32_Asynch_Result::act ();
}
int
ACE_WIN32_Asynch_Read_Stream_Result::success (void) const
{
return ACE_WIN32_Asynch_Result::success ();
}
const void *
ACE_WIN32_Asynch_Read_Stream_Result::completion_key (void) const
{
return ACE_WIN32_Asynch_Result::completion_key ();
}
u_long
ACE_WIN32_Asynch_Read_Stream_Result::error (void) const
{
return ACE_WIN32_Asynch_Result::error ();
}
ACE_HANDLE
ACE_WIN32_Asynch_Read_Stream_Result::event (void) const
{
return ACE_WIN32_Asynch_Result::event ();
}
u_long
ACE_WIN32_Asynch_Read_Stream_Result::offset (void) const
{
return ACE_WIN32_Asynch_Result::offset ();
}
u_long
ACE_WIN32_Asynch_Read_Stream_Result::offset_high (void) const
{
return ACE_WIN32_Asynch_Result::offset_high ();
}
int
ACE_WIN32_Asynch_Read_Stream_Result::priority (void) const
{
return ACE_WIN32_Asynch_Result::priority ();
}
int
ACE_WIN32_Asynch_Read_Stream_Result::signal_number (void) const
{
return ACE_WIN32_Asynch_Result::signal_number ();
}
int
ACE_WIN32_Asynch_Read_Stream_Result::post_completion (ACE_Proactor_Impl *proactor)
{
return ACE_WIN32_Asynch_Result::post_completion (proactor);
}
int
ACE_WIN32_Asynch_Read_Stream_Result::scatter_enabled (void) const
{
return this->scatter_enabled_;
}
ACE_WIN32_Asynch_Read_Stream::ACE_WIN32_Asynch_Read_Stream (ACE_WIN32_Proactor *win32_proactor)
: ACE_Asynch_Operation_Impl (),
ACE_Asynch_Read_Stream_Impl (),
ACE_WIN32_Asynch_Operation (win32_proactor)
{
}
int
ACE_WIN32_Asynch_Read_Stream::read (ACE_Message_Block &message_block,
size_t bytes_to_read,
const void *act,
int priority,
int signal_number)
{
size_t space = message_block.space ();
if (bytes_to_read > space)
bytes_to_read = space;
if (bytes_to_read == 0)
{
errno = ENOSPC;
return -1;
}
// Create the Asynch_Result.
ACE_WIN32_Asynch_Read_Stream_Result *result = 0;
ACE_NEW_RETURN (result,
ACE_WIN32_Asynch_Read_Stream_Result (this->handler_proxy_,
this->handle_,
message_block,
bytes_to_read,
act,
this->win32_proactor_->get_handle (),
priority,
signal_number),
-1);
// Shared read
int const return_val = this->shared_read (result);
// Upon errors
if (return_val == -1)
delete result;
return return_val;
}
int
ACE_WIN32_Asynch_Read_Stream::readv (ACE_Message_Block &message_block,
size_t bytes_to_read,
const void *act,
int priority,
int signal_number)
{
#if (defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0))
iovec iov[ACE_IOV_MAX];
int iovcnt = 0;
// We should not read more than user requested,
// but it is allowed to read less
for (const ACE_Message_Block* msg = &message_block;
msg != 0 && bytes_to_read > 0 && iovcnt < ACE_IOV_MAX;
msg = msg->cont () , ++iovcnt )
{
size_t msg_space = msg->space ();
// OS should correctly process zero length buffers
// if ( msg_space == 0 )
// ACE_ERROR_RETURN ((LM_ERROR,
// ACE_TEXT ("ACE_WIN32_Asynch_Read_Stream::readv:")
// ACE_TEXT ("No space in the message block\n")),
// -1);
if (msg_space > bytes_to_read)
msg_space = bytes_to_read;
bytes_to_read -= msg_space;
// Make as many iovec as needed to fit all of msg_space.
size_t wr_ptr_offset = 0;
while (msg_space > 0 && iovcnt < ACE_IOV_MAX)
{
u_long this_chunk_length;
if (msg_space > ULONG_MAX)
this_chunk_length = ULONG_MAX;
else
this_chunk_length = static_cast<u_long> (msg_space);
// Collect the data in the iovec.
iov[iovcnt].iov_base = msg->wr_ptr () + wr_ptr_offset;
iov[iovcnt].iov_len = this_chunk_length;
msg_space -= this_chunk_length;
wr_ptr_offset += this_chunk_length;
// Increment iovec counter if there's more to do.
if (msg_space > 0)
++iovcnt;
}
if (msg_space > 0) // Ran out of iovecs before msg_space exhausted
{
errno = ERANGE;
return -1;
}
}
// Re-calculate number bytes to read
bytes_to_read = 0;
for (int i = 0; i < iovcnt ; ++i)
bytes_to_read += iov[i].iov_len;
if (bytes_to_read == 0)
ACE_ERROR_RETURN ((LM_ERROR,
ACE_TEXT ("ACE_WIN32_Asynch_Read_Stream::readv:")
ACE_TEXT ("Attempt to read 0 bytes\n")),
-1);
// Create the Asynch_Result.
ACE_WIN32_Asynch_Read_Stream_Result *result = 0;
ACE_NEW_RETURN (result,
ACE_WIN32_Asynch_Read_Stream_Result (this->handler_proxy_,
this->handle_,
message_block,
bytes_to_read,
act,
this->win32_proactor_->get_handle (),
priority,
signal_number,
1), // scatter read enabled
-1);
// do the scatter recv
result->set_error (0); // Clear error before starting IO.
DWORD bytes_recvd = 0;
u_long flags = 0;
int initiate_result = ::WSARecv (reinterpret_cast<SOCKET> (result->handle ()),
reinterpret_cast<WSABUF *> (iov),
iovcnt,
&bytes_recvd,
&flags,
result,
0);
if (0 == initiate_result)
// Immediate success: the OVERLAPPED will still get queued.
return 1;
ACE_ASSERT (initiate_result == SOCKET_ERROR);
// If initiate failed, check for a bad error.
ACE_OS::set_errno_to_last_error ();
switch (errno)
{
case ERROR_IO_PENDING:
// The IO will complete proactively: the OVERLAPPED will still
// get queued.
initiate_result = 0;
break;
default:
// Something else went wrong: the OVERLAPPED will not get
// queued.
if (ACE::debug ())
{
ACE_DEBUG ((LM_ERROR,
ACE_TEXT ("%p\n"),
ACE_TEXT ("WSARecv")));
}
delete result;
initiate_result = -1;
break;
}
return initiate_result;
#else
ACE_UNUSED_ARG (message_block);
ACE_UNUSED_ARG (bytes_to_read);
ACE_UNUSED_ARG (act);
ACE_UNUSED_ARG (priority);
ACE_UNUSED_ARG (signal_number);
ACE_NOTSUP_RETURN (-1);
#endif /* ACE_HAS_WINSOCK2 && ACE_HAS_WINSOCK2 != 0 */
}
ACE_WIN32_Asynch_Read_Stream::~ACE_WIN32_Asynch_Read_Stream (void)
{
}
int
ACE_WIN32_Asynch_Read_Stream::shared_read (ACE_WIN32_Asynch_Read_Stream_Result *result)
{
// ReadFile API limits us to DWORD range.
if (result->bytes_to_read () > MAXDWORD)
{
errno = ERANGE;
return -1;
}
DWORD bytes_to_read = static_cast<DWORD> (result->bytes_to_read ());
u_long bytes_read;
result->set_error (0); // Clear error before starting IO.
// Initiate the read
int initiate_result = ::ReadFile (result->handle (),
result->message_block ().wr_ptr (),
bytes_to_read,
&bytes_read,
result);
if (initiate_result == 1)
// Immediate success: the OVERLAPPED will still get queued.
return 0;
// If initiate failed, check for a bad error.
ACE_OS::set_errno_to_last_error ();
switch (errno)
{
case ERROR_IO_PENDING:
/* FALLTHRU */
case ERROR_MORE_DATA:
// The IO will complete proactively: the OVERLAPPED will still
// get queued.
return 0;
default:
// Something else went wrong: the OVERLAPPED will not get
// queued.
if (ACE::debug ())
{
ACE_DEBUG ((LM_ERROR,
ACE_TEXT ("%p\n"),
ACE_TEXT ("ReadFile")));
}
return -1;
}
}
// Methods belong to ACE_WIN32_Asynch_Operation base class. These
// methods are defined here to avoid VC++ warnings. They route the
// call to the ACE_WIN32_Asynch_Operation base class.
int
ACE_WIN32_Asynch_Read_Stream::open (const ACE_Handler::Proxy_Ptr &handler_proxy,
ACE_HANDLE handle,
const void *completion_key,
ACE_Proactor *proactor)
{
return ACE_WIN32_Asynch_Operation::open (handler_proxy,
handle,
completion_key,
proactor);
}
int
ACE_WIN32_Asynch_Read_Stream::cancel (void)
{
return ACE_WIN32_Asynch_Operation::cancel ();
}
ACE_Proactor *
ACE_WIN32_Asynch_Read_Stream::proactor (void) const
{
return ACE_WIN32_Asynch_Operation::proactor ();
}
size_t
ACE_WIN32_Asynch_Write_Stream_Result::bytes_to_write (void) const
{
return this->bytes_to_write_;
}
ACE_Message_Block &
ACE_WIN32_Asynch_Write_Stream_Result::message_block (void) const
{
return this->message_block_;
}
ACE_HANDLE
ACE_WIN32_Asynch_Write_Stream_Result::handle (void) const
{
return this->handle_;
}
ACE_WIN32_Asynch_Write_Stream_Result::ACE_WIN32_Asynch_Write_Stream_Result (
const ACE_Handler::Proxy_Ptr &handler_proxy,
ACE_HANDLE handle,
ACE_Message_Block &message_block,
size_t bytes_to_write,
const void* act,
ACE_HANDLE event,
int priority,
int signal_number,
int gather_enabled)
: ACE_Asynch_Result_Impl (),
ACE_Asynch_Write_Stream_Result_Impl (),
ACE_WIN32_Asynch_Result
(handler_proxy, act, event, 0, 0, priority, signal_number),
bytes_to_write_ (bytes_to_write),
message_block_ (message_block),
handle_ (handle),
gather_enabled_ (gather_enabled)
{
}
void
ACE_WIN32_Asynch_Write_Stream_Result::complete (size_t bytes_transferred,
int success,
const void *completion_key,
u_long error)
{
// Copy the data which was returned by <GetQueuedCompletionStatus>.
this->bytes_transferred_ = bytes_transferred;
this->success_ = success;
this->completion_key_ = completion_key;
this->error_ = error;
// Appropriately move the pointers in the message block.
if (!this->gather_enabled ())
this->message_block_.rd_ptr (bytes_transferred);
else
{
for (ACE_Message_Block* mb = &this->message_block_;
(mb != 0) && (bytes_transferred > 0);
mb = mb->cont ())
{
size_t len_part = mb->length ();
if ( len_part > bytes_transferred)
len_part = bytes_transferred;
mb->rd_ptr (len_part);
bytes_transferred -= len_part;
}
}
// Create the interface result class.
ACE_Asynch_Write_Stream::Result result (this);
// Call the application handler.
ACE_Handler *handler = this->handler_proxy_.get ()->handler ();
if (handler != 0)
handler->handle_write_stream (result);
}
ACE_WIN32_Asynch_Write_Stream_Result::~ACE_WIN32_Asynch_Write_Stream_Result (void)
{
}
// Base class operations. These operations are here to kill dominance
// warnings. These methods call the base class methods.
size_t
ACE_WIN32_Asynch_Write_Stream_Result::bytes_transferred (void) const
{
return ACE_WIN32_Asynch_Result::bytes_transferred ();
}
const void *
ACE_WIN32_Asynch_Write_Stream_Result::act (void) const
{
return ACE_WIN32_Asynch_Result::act ();
}
int
ACE_WIN32_Asynch_Write_Stream_Result::success (void) const
{
return ACE_WIN32_Asynch_Result::success ();
}
const void *
ACE_WIN32_Asynch_Write_Stream_Result::completion_key (void) const
{
return ACE_WIN32_Asynch_Result::completion_key ();
}
u_long
ACE_WIN32_Asynch_Write_Stream_Result::error (void) const
{
return ACE_WIN32_Asynch_Result::error ();
}
ACE_HANDLE
ACE_WIN32_Asynch_Write_Stream_Result::event (void) const
{
return ACE_WIN32_Asynch_Result::event ();
}
u_long
ACE_WIN32_Asynch_Write_Stream_Result::offset (void) const
{
return ACE_WIN32_Asynch_Result::offset ();
}
u_long
ACE_WIN32_Asynch_Write_Stream_Result::offset_high (void) const
{
return ACE_WIN32_Asynch_Result::offset_high ();
}
int
ACE_WIN32_Asynch_Write_Stream_Result::priority (void) const
{
return ACE_WIN32_Asynch_Result::priority ();
}
int
ACE_WIN32_Asynch_Write_Stream_Result::signal_number (void) const
{
return ACE_WIN32_Asynch_Result::signal_number ();
}
int
ACE_WIN32_Asynch_Write_Stream_Result::post_completion (ACE_Proactor_Impl *proactor)
{
return ACE_WIN32_Asynch_Result::post_completion (proactor);
}
int
ACE_WIN32_Asynch_Write_Stream_Result::gather_enabled (void) const
{
return this->gather_enabled_;
}
ACE_WIN32_Asynch_Write_Stream::ACE_WIN32_Asynch_Write_Stream (ACE_WIN32_Proactor *win32_proactor)
: ACE_Asynch_Operation_Impl (),
ACE_Asynch_Write_Stream_Impl (),
ACE_WIN32_Asynch_Operation (win32_proactor)
{
}
int
ACE_WIN32_Asynch_Write_Stream::write (ACE_Message_Block &message_block,
size_t bytes_to_write,
const void *act,
int priority,
int signal_number)
{
size_t len = message_block.length();
if (bytes_to_write > len)
bytes_to_write = len ;
if (bytes_to_write == 0)
ACE_ERROR_RETURN
((LM_ERROR,
ACE_TEXT ("ACE_WIN32_Asynch_Write_Stream::write:")
ACE_TEXT ("Attempt to write 0 bytes\n")),
-1);
ACE_WIN32_Asynch_Write_Stream_Result *result = 0;
ACE_NEW_RETURN (result,
ACE_WIN32_Asynch_Write_Stream_Result (this->handler_proxy_,
this->handle_,
message_block,
bytes_to_write,
act,
this->win32_proactor_->get_handle (),
priority,
signal_number),
-1);
// Shared write
int const return_val = this->shared_write (result);
// Upon errors
if (return_val == -1)
{
delete result;
}
return return_val;
}
int
ACE_WIN32_Asynch_Write_Stream::writev (ACE_Message_Block &message_block,
size_t bytes_to_write,
const void *act,
int priority,
int signal_number)
{
#if (defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0))
iovec iov[ACE_IOV_MAX];
int iovcnt = 0;
// We should not write more than user requested,
// but it is allowed to write less
for (const ACE_Message_Block* msg = &message_block;
msg != 0 && bytes_to_write > 0 && iovcnt < ACE_IOV_MAX;
msg = msg->cont ())
{
size_t msg_len = msg->length ();
// Skip 0-length blocks.
if (msg_len == 0)
continue;
if (msg_len > bytes_to_write)
msg_len = bytes_to_write;
bytes_to_write -= msg_len;
// Make as many iovec as needed to fit all of msg_len.
size_t rd_ptr_offset = 0;
while (msg_len > 0 && iovcnt < ACE_IOV_MAX)
{
u_long this_chunk_length;
if (msg_len > ULONG_MAX)
this_chunk_length = ULONG_MAX;
else
this_chunk_length = static_cast<u_long> (msg_len);
// Collect the data in the iovec.
iov[iovcnt].iov_base = msg->rd_ptr () + rd_ptr_offset;
iov[iovcnt].iov_len = this_chunk_length;
msg_len -= this_chunk_length;
rd_ptr_offset += this_chunk_length;
// Increment iovec counter if there's more to do.
if (msg_len > 0)
iovcnt++;
}
if (msg_len > 0) // Ran out of iovecs before msg_space exhausted
{
errno = ERANGE;
return -1;
}
++iovcnt;
}
// Re-calculate number bytes to write
bytes_to_write = 0;
for ( int i=0; i < iovcnt ; ++i )
bytes_to_write += iov[i].iov_len;
if ( bytes_to_write == 0 )
ACE_ERROR_RETURN ((LM_ERROR,
ACE_TEXT ("ACE_WIN32_Asynch_Write_Stream::writev:")
ACE_TEXT ("Attempt to write 0 bytes\n")),
-1);
ACE_WIN32_Asynch_Write_Stream_Result *result = 0;
ACE_NEW_RETURN (result,
ACE_WIN32_Asynch_Write_Stream_Result (this->handler_proxy_,
this->handle_,
message_block,
bytes_to_write,
act,
this->win32_proactor_->get_handle (),
priority,
signal_number,
1), // gather write enabled
-1);
// do the gather send
u_long bytes_sent = 0;
int initiate_result = ::WSASend (reinterpret_cast<SOCKET> (result->handle ()),
reinterpret_cast<WSABUF *> (iov),
iovcnt,
&bytes_sent,
0, // flags
result,
0);
if (0 == initiate_result)
// Immediate success: the OVERLAPPED will still get queued.
return 1;
ACE_ASSERT (initiate_result == SOCKET_ERROR);
// If initiate failed, check for a bad error.
ACE_OS::set_errno_to_last_error ();
switch (errno)
{
case ERROR_IO_PENDING:
// The IO will complete proactively: the OVERLAPPED will still
// get queued.
initiate_result = 0;
break;
default:
// Something else went wrong: the OVERLAPPED will not get
// queued.
if (ACE::debug ())
{
ACE_DEBUG ((LM_ERROR,
ACE_TEXT ("%p\n"),
ACE_TEXT ("WSASend")));
}
delete result;
initiate_result = -1;
break;
}
return initiate_result;
#else
ACE_UNUSED_ARG (message_block);
ACE_UNUSED_ARG (bytes_to_write);
ACE_UNUSED_ARG (act);
ACE_UNUSED_ARG (priority);
ACE_UNUSED_ARG (signal_number);
ACE_NOTSUP_RETURN (-1);
#endif /* ACE_HAS_WINSOCK2 && ACE_HAS_WINSOCK2 != 0 */
}
ACE_WIN32_Asynch_Write_Stream::~ACE_WIN32_Asynch_Write_Stream (void)
{
}
int
ACE_WIN32_Asynch_Write_Stream::shared_write (ACE_WIN32_Asynch_Write_Stream_Result *result)
{
u_long bytes_written;
if (result->bytes_to_write () > MAXDWORD)
{
errno = ERANGE;
return -1;
}
DWORD bytes_to_write = static_cast<DWORD> (result->bytes_to_write ());
result->set_error (0); // Clear error before starting IO.
// Initiate the write; Winsock 2 is required for the higher-performing
// WSASend() function. For Winsock 1, fall back to the slower WriteFile().
int initiate_result = 0;
#if (defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0))
WSABUF iov;
iov.buf = result->message_block ().rd_ptr ();
iov.len = bytes_to_write;
initiate_result = ::WSASend (reinterpret_cast<SOCKET> (result->handle ()),
&iov,
1,
&bytes_written,
0, // flags
result,
0);
if (initiate_result == 0)
{
// Immediate success: the OVERLAPPED will still get queued.
return 0;
}
#else
initiate_result = ::WriteFile (result->handle (),
result->message_block ().rd_ptr (),
bytes_to_write,
&bytes_written,
result);
if (initiate_result == 1)
// Immediate success: the OVERLAPPED will still get queued.
return 0;
#endif /* ACE_HAS_WINSOCK2 */
// If initiate failed, check for a bad error.
ACE_OS::set_errno_to_last_error ();
switch (errno)
{
case ERROR_IO_PENDING:
// The IO will complete proactively: the OVERLAPPED will still
// get queued.
return 0;
default:
// Something else went wrong: the OVERLAPPED will not get
// queued.
if (ACE::debug ())
ACE_DEBUG ((LM_ERROR,
ACE_TEXT ("%p\n"),
ACE_TEXT ("Initiating write")));
return -1;
}
}
// Methods belong to ACE_WIN32_Asynch_Operation base class. These
// methods are defined here to avoid VC++ warnings. They route the
// call to the ACE_WIN32_Asynch_Operation base class.
int
ACE_WIN32_Asynch_Write_Stream::open (const ACE_Handler::Proxy_Ptr &handler_proxy,
ACE_HANDLE handle,
const void *completion_key,
ACE_Proactor *proactor)
{
return ACE_WIN32_Asynch_Operation::open (handler_proxy,
handle,
completion_key,
proactor);
}
int
ACE_WIN32_Asynch_Write_Stream::cancel (void)
{
return ACE_WIN32_Asynch_Operation::cancel ();
}
ACE_Proactor *
ACE_WIN32_Asynch_Write_Stream::proactor (void) const
{
return ACE_WIN32_Asynch_Operation::proactor ();
}
ACE_WIN32_Asynch_Read_File_Result::ACE_WIN32_Asynch_Read_File_Result (
const ACE_Handler::Proxy_Ptr &handler_proxy,
ACE_HANDLE handle,
ACE_Message_Block &message_block,
size_t bytes_to_read,
const void* act,
u_long offset,
u_long offset_high,
ACE_HANDLE event,
int priority,
int signal_number,
int scatter_enabled)
: ACE_Asynch_Result_Impl (),
ACE_Asynch_Read_Stream_Result_Impl (),
ACE_Asynch_Read_File_Result_Impl (),
ACE_WIN32_Asynch_Read_Stream_Result (handler_proxy,
handle,
message_block,
bytes_to_read,
act,
event,
priority,
signal_number,
scatter_enabled)
{
this->Offset = offset;
this->OffsetHigh = offset_high;
}
void
ACE_WIN32_Asynch_Read_File_Result::complete (size_t bytes_transferred,
int success,
const void *completion_key,
u_long error)
{
// Copy the data which was returned by GetQueuedCompletionStatus.
this->bytes_transferred_ = bytes_transferred;
this->success_ = success;
this->completion_key_ = completion_key;
this->error_ = error;
// Appropriately move the pointers in the message block.
if (!this->scatter_enabled ())
this->message_block_.wr_ptr (bytes_transferred);
else
{
static const size_t page_size = ACE_OS::getpagesize();
for (ACE_Message_Block* mb = &this->message_block_;
(mb != 0) && (bytes_transferred > 0);
mb = mb->cont ())
{
// mb->space () is ought to be >= page_size.
// this is verified in the readv method
// ACE_ASSERT (mb->space () >= page_size);
size_t len_part = page_size ;
if ( len_part > bytes_transferred)
len_part = bytes_transferred;
mb->wr_ptr (len_part);
bytes_transferred -= len_part;
}
}
// Create the interface result class.
ACE_Asynch_Read_File::Result result (this);
// Call the application handler.
ACE_Handler *handler = this->handler_proxy_.get ()->handler ();
if (handler != 0)
handler->handle_read_file (result);
}
ACE_WIN32_Asynch_Read_File_Result::~ACE_WIN32_Asynch_Read_File_Result (void)
{
}
// Base class operations. These operations are here to kill dominance
// warnings. These methods call the base class methods.
size_t
ACE_WIN32_Asynch_Read_File_Result::bytes_transferred (void) const
{
return ACE_WIN32_Asynch_Result::bytes_transferred ();
}
const void *
ACE_WIN32_Asynch_Read_File_Result::act (void) const
{
return ACE_WIN32_Asynch_Result::act ();
}
int
ACE_WIN32_Asynch_Read_File_Result::success (void) const
{
return ACE_WIN32_Asynch_Result::success ();
}
const void *
ACE_WIN32_Asynch_Read_File_Result::completion_key (void) const
{
return ACE_WIN32_Asynch_Result::completion_key ();
}
u_long
ACE_WIN32_Asynch_Read_File_Result::error (void) const
{
return ACE_WIN32_Asynch_Result::error ();
}
ACE_HANDLE
ACE_WIN32_Asynch_Read_File_Result::event (void) const
{
return ACE_WIN32_Asynch_Result::event ();
}
u_long
ACE_WIN32_Asynch_Read_File_Result::offset (void) const
{
return ACE_WIN32_Asynch_Result::offset ();
}
u_long
ACE_WIN32_Asynch_Read_File_Result::offset_high (void) const
{
return ACE_WIN32_Asynch_Result::offset_high ();
}
int
ACE_WIN32_Asynch_Read_File_Result::priority (void) const
{
return ACE_WIN32_Asynch_Result::priority ();
}
int
ACE_WIN32_Asynch_Read_File_Result::signal_number (void) const
{
return ACE_WIN32_Asynch_Result::signal_number ();
}
// The following methods belong to
// ACE_WIN32_Asynch_Read_Stream_Result. They are here to avoid VC++
// warnings. These methods route their call to the
// ACE_WIN32_Asynch_Read_Stream_Result base class.
size_t
ACE_WIN32_Asynch_Read_File_Result::bytes_to_read (void) const
{
return ACE_WIN32_Asynch_Read_Stream_Result::bytes_to_read ();
}
ACE_Message_Block &
ACE_WIN32_Asynch_Read_File_Result::message_block (void) const
{
return ACE_WIN32_Asynch_Read_Stream_Result::message_block ();
}
ACE_HANDLE
ACE_WIN32_Asynch_Read_File_Result::handle (void) const
{
return ACE_WIN32_Asynch_Read_Stream_Result::handle ();
}
int
ACE_WIN32_Asynch_Read_File_Result::post_completion (ACE_Proactor_Impl *proactor)
{
return ACE_WIN32_Asynch_Result::post_completion (proactor);
}
// ************************************************************
ACE_WIN32_Asynch_Read_File::ACE_WIN32_Asynch_Read_File (ACE_WIN32_Proactor *win32_proactor)
: ACE_Asynch_Operation_Impl (),
ACE_Asynch_Read_Stream_Impl (),
ACE_Asynch_Read_File_Impl (),
ACE_WIN32_Asynch_Read_Stream (win32_proactor)
{
}
int
ACE_WIN32_Asynch_Read_File::read (ACE_Message_Block &message_block,
size_t bytes_to_read,
u_long offset,
u_long offset_high,
const void *act,
int priority,
int signal_number)
{
size_t space = message_block.space ();
if ( bytes_to_read > space )
bytes_to_read = space;
if ( bytes_to_read == 0 )
ACE_ERROR_RETURN
((LM_ERROR,
ACE_TEXT ("ACE_WIN32_Asynch_Read_File::read:")
ACE_TEXT ("Attempt to read 0 bytes or no space in the message block\n")),
-1);
ACE_WIN32_Asynch_Read_File_Result *result = 0;
ACE_NEW_RETURN (result,
ACE_WIN32_Asynch_Read_File_Result (this->handler_proxy_,
this->handle_,
message_block,
bytes_to_read,
act,
offset,
offset_high,
this->win32_proactor_->get_handle (),
priority,
signal_number),
-1);
// Shared read
int return_val = this->shared_read (result);
// Upon errors
if (return_val == -1)
delete result;
return return_val;
}
int
ACE_WIN32_Asynch_Read_File::readv (ACE_Message_Block &message_block,
size_t bytes_to_read,
u_long offset,
u_long offset_high,
const void *act,
int priority,
int signal_number)
{
#if defined (ACE_HAS_WIN32_OVERLAPPED_IO)
static const size_t page_size = ACE_OS::getpagesize();
FILE_SEGMENT_ELEMENT buffer_pointers[ACE_IOV_MAX + 1];
int buffer_pointers_count = 0;
// Each buffer must be at least the size of a system memory page
// and must be aligned on a system memory page size boundary
// We should not read more than user requested,
// but it is allowed to read less
size_t total_space = 0;
for (const ACE_Message_Block* msg = &message_block;
msg != 0 && buffer_pointers_count < ACE_IOV_MAX && total_space < bytes_to_read;
msg = msg->cont(), ++buffer_pointers_count )
{
size_t msg_space = msg->space ();
if (msg_space < page_size)
ACE_ERROR_RETURN ((LM_ERROR,
ACE_TEXT ("ACE_WIN32_Asynch_Read_File::readv:")
ACE_TEXT ("Invalid message block size\n")),
-1);
buffer_pointers[buffer_pointers_count].Buffer = msg->wr_ptr ();
total_space += page_size;
}
// not read more than buffers space
if (bytes_to_read > total_space)
bytes_to_read = total_space;
// ReadFileScatter API limits us to DWORD range.
if (bytes_to_read > MAXDWORD)
{
errno = ERANGE;
return -1;
}
DWORD dword_bytes_to_read = static_cast<DWORD> (bytes_to_read);
// last one should be completely 0
buffer_pointers[buffer_pointers_count].Buffer = 0;
ACE_WIN32_Asynch_Read_File_Result *result = 0;
ACE_NEW_RETURN (result,
ACE_WIN32_Asynch_Read_File_Result (this->handler_proxy_,
this->handle_,
message_block,
bytes_to_read,
act,
offset,
offset_high,
this->win32_proactor_->get_handle (),
priority,
signal_number,
1), // scatter read enabled
-1);
// do the scatter read
result->set_error (0); // Clear error before starting IO.
int initiate_result = ::ReadFileScatter (result->handle (),
buffer_pointers,
dword_bytes_to_read,
0, // reserved, must be NULL
result);
if (0 != initiate_result)
// Immediate success: the OVERLAPPED will still get queued.
return 1;
// If initiate failed, check for a bad error.
ACE_OS::set_errno_to_last_error ();
switch (errno)
{
case ERROR_IO_PENDING:
// The IO will complete proactively: the OVERLAPPED will still
// get queued.
initiate_result = 0;
break;
default:
// Something else went wrong: the OVERLAPPED will not get
// queued.
if (ACE::debug ())
{
ACE_DEBUG ((LM_ERROR,
ACE_TEXT ("%p\n"),
ACE_TEXT ("ReadFileScatter")));
}
delete result;
initiate_result = -1;
break;
}
return initiate_result;
#else
ACE_NOTSUP_RETURN (-1);
#endif /* ACE_WIN32_OVERLAPPED_IO */
}
ACE_WIN32_Asynch_Read_File::~ACE_WIN32_Asynch_Read_File (void)
{
}
int
ACE_WIN32_Asynch_Read_File::read (ACE_Message_Block &message_block,
size_t bytes_to_read,
const void *act,
int priority,
int signal_number)
{
return ACE_WIN32_Asynch_Read_Stream::read (message_block,
bytes_to_read,
act,
priority,
signal_number);
}
int
ACE_WIN32_Asynch_Read_File::readv (ACE_Message_Block &message_block,
size_t bytes_to_read,
const void *act,
int priority,
int signal_number)
{
return ACE_WIN32_Asynch_Read_Stream::readv (message_block,
bytes_to_read,
act,
priority,
signal_number);
}
// Methods belong to ACE_WIN32_Asynch_Operation base class. These
// methods are defined here to avoid VC++ warnings. They route the
// call to the ACE_WIN32_Asynch_Operation base class.
int
ACE_WIN32_Asynch_Read_File::open (const ACE_Handler::Proxy_Ptr &handler_proxy,
ACE_HANDLE handle,
const void *completion_key,
ACE_Proactor *proactor)
{
return ACE_WIN32_Asynch_Operation::open (handler_proxy,
handle,
completion_key,
proactor);
}
int
ACE_WIN32_Asynch_Read_File::cancel (void)
{
return ACE_WIN32_Asynch_Operation::cancel ();
}
ACE_Proactor *
ACE_WIN32_Asynch_Read_File::proactor (void) const
{
return ACE_WIN32_Asynch_Operation::proactor ();
}
ACE_WIN32_Asynch_Write_File_Result::ACE_WIN32_Asynch_Write_File_Result (
const ACE_Handler::Proxy_Ptr &handler_proxy,
ACE_HANDLE handle,
ACE_Message_Block &message_block,
size_t bytes_to_write,
const void* act,
u_long offset,
u_long offset_high,
ACE_HANDLE event,
int priority,
int signal_number,
int gather_enabled)
: ACE_Asynch_Result_Impl (),
ACE_Asynch_Write_Stream_Result_Impl (),
ACE_Asynch_Write_File_Result_Impl (),
ACE_WIN32_Asynch_Write_Stream_Result (handler_proxy,
handle,
message_block,
bytes_to_write,
act,
event,
priority,
signal_number,
gather_enabled)
{
this->Offset = offset;
this->OffsetHigh = offset_high;
}
void
ACE_WIN32_Asynch_Write_File_Result::complete (size_t bytes_transferred,
int success,
const void *completion_key,
u_long error)
{
// Copy the data which was returned by GetQueuedCompletionStatus
this->bytes_transferred_ = bytes_transferred;
this->success_ = success;
this->completion_key_ = completion_key;
this->error_ = error;
// Appropriately move the pointers in the message block.
if (!this->gather_enabled ())
this->message_block_.rd_ptr (bytes_transferred);
else
{
static const size_t page_size = ACE_OS::getpagesize();
for (ACE_Message_Block* mb = &this->message_block_;
(mb != 0) && (bytes_transferred > 0);
mb = mb->cont ())
{
// mb->length () is ought to be >= page_size.
// this is verified in the writev method
// ACE_ASSERT (mb->length () >= page_size);
size_t len_part = page_size;
if ( len_part > bytes_transferred)
len_part = bytes_transferred;
mb->rd_ptr (len_part);
bytes_transferred -= len_part;
}
}
// Create the interface result class.
ACE_Asynch_Write_File::Result result (this);
// Call the application handler.
ACE_Handler *handler = this->handler_proxy_.get ()->handler ();
if (handler != 0)
handler->handle_write_file (result);
}
ACE_WIN32_Asynch_Write_File_Result::~ACE_WIN32_Asynch_Write_File_Result (void)
{
}
// Base class operations. These operations are here to kill dominance
// warnings. These methods call the base class methods.
size_t
ACE_WIN32_Asynch_Write_File_Result::bytes_transferred (void) const
{
return ACE_WIN32_Asynch_Result::bytes_transferred ();
}
const void *
ACE_WIN32_Asynch_Write_File_Result::act (void) const
{
return ACE_WIN32_Asynch_Result::act ();
}
int
ACE_WIN32_Asynch_Write_File_Result::success (void) const
{
return ACE_WIN32_Asynch_Result::success ();
}
const void *
ACE_WIN32_Asynch_Write_File_Result::completion_key (void) const
{
return ACE_WIN32_Asynch_Result::completion_key ();
}
u_long
ACE_WIN32_Asynch_Write_File_Result::error (void) const
{
return ACE_WIN32_Asynch_Result::error ();
}
ACE_HANDLE
ACE_WIN32_Asynch_Write_File_Result::event (void) const
{
return ACE_WIN32_Asynch_Result::event ();
}
u_long
ACE_WIN32_Asynch_Write_File_Result::offset (void) const
{
return ACE_WIN32_Asynch_Result::offset ();
}
u_long
ACE_WIN32_Asynch_Write_File_Result::offset_high (void) const
{
return ACE_WIN32_Asynch_Result::offset_high ();
}
int
ACE_WIN32_Asynch_Write_File_Result::priority (void) const
{
return ACE_WIN32_Asynch_Result::priority ();
}
int
ACE_WIN32_Asynch_Write_File_Result::signal_number (void) const
{
return ACE_WIN32_Asynch_Result::signal_number ();
}
// The following methods belong to
// ACE_WIN32_Asynch_Write_Stream_Result. They are here to avoid VC++
// warnings. These methods route their call to the
// ACE_WIN32_Asynch_Write_Stream_Result base class.
size_t
ACE_WIN32_Asynch_Write_File_Result::bytes_to_write (void) const
{
return ACE_WIN32_Asynch_Write_Stream_Result::bytes_to_write ();
}
ACE_Message_Block &
ACE_WIN32_Asynch_Write_File_Result::message_block (void) const
{
return ACE_WIN32_Asynch_Write_Stream_Result::message_block ();
}
ACE_HANDLE
ACE_WIN32_Asynch_Write_File_Result::handle (void) const
{
return ACE_WIN32_Asynch_Write_Stream_Result::handle ();
}
int
ACE_WIN32_Asynch_Write_File_Result::post_completion (ACE_Proactor_Impl *proactor)
{
return ACE_WIN32_Asynch_Result::post_completion (proactor);
}
ACE_WIN32_Asynch_Write_File::ACE_WIN32_Asynch_Write_File (ACE_WIN32_Proactor *win32_proactor)
: ACE_Asynch_Operation_Impl (),
ACE_Asynch_Write_Stream_Impl (),
ACE_Asynch_Write_File_Impl (),
ACE_WIN32_Asynch_Write_Stream (win32_proactor)
{
}
int
ACE_WIN32_Asynch_Write_File::write (ACE_Message_Block &message_block,
size_t bytes_to_write,
u_long offset,
u_long offset_high,
const void *act,
int priority,
int signal_number)
{
size_t len = message_block.length ();
if ( bytes_to_write > len )
bytes_to_write = len;
if ( bytes_to_write == 0 )
ACE_ERROR_RETURN
((LM_ERROR,
ACE_TEXT ("ACE_WIN32_Asynch_Write_File::write:")
ACE_TEXT ("Attempt to read 0 bytes\n")),
-1);
ACE_WIN32_Asynch_Write_File_Result *result = 0;
ACE_NEW_RETURN (result,
ACE_WIN32_Asynch_Write_File_Result (this->handler_proxy_,
this->handle_,
message_block,
bytes_to_write,
act,
offset,
offset_high,
this->win32_proactor_->get_handle (),
priority,
signal_number),
-1);
// Shared write
int return_val = this->shared_write (result);
// Upon errors
if (return_val == -1)
delete result;
return return_val;
}
int
ACE_WIN32_Asynch_Write_File::writev (ACE_Message_Block &message_block,
size_t bytes_to_write,
u_long offset,
u_long offset_high,
const void *act,
int priority,
int signal_number)
{
#if defined (ACE_HAS_WIN32_OVERLAPPED_IO)
static const size_t page_size = ACE_OS::getpagesize();
FILE_SEGMENT_ELEMENT buffer_pointers[ACE_IOV_MAX + 1];
int buffer_pointers_count = 0;
// Each buffer must be at least the size of a system memory page
// and must be aligned on a system memory page size boundary
// We should not read more than user requested,
// but it is allowed to read less
size_t total_len = 0;
for (const ACE_Message_Block* msg = &message_block;
msg != 0 && buffer_pointers_count < ACE_IOV_MAX && total_len < bytes_to_write;
msg = msg->cont (), ++buffer_pointers_count )
{
size_t msg_len = msg->length ();
// Don't allow writing less than page_size, unless
// the size of the message block is big enough (so we don't write from
// memory which does not belong to the message block), and the message
// block is the last in the chain.
if (msg_len < page_size &&
(msg->size () - (msg->rd_ptr () - msg->base ()) < page_size || // message block too small
bytes_to_write - total_len > page_size ))// NOT last chunk
ACE_ERROR_RETURN ((LM_ERROR,
ACE_TEXT ("ACE_WIN32_Asynch_Write_File::writev:")
ACE_TEXT ("Invalid message block length\n")),
-1);
buffer_pointers[buffer_pointers_count].Buffer = msg->rd_ptr ();
total_len += page_size;
}
// not write more than we have in buffers
if (bytes_to_write > total_len)
bytes_to_write = total_len;
// WriteFileGather API limits us to DWORD range.
if (bytes_to_write > MAXDWORD)
{
errno = ERANGE;
return -1;
}
DWORD dword_bytes_to_write = static_cast<DWORD> (bytes_to_write);
// last one should be completely 0
buffer_pointers[buffer_pointers_count].Buffer = 0;
ACE_WIN32_Asynch_Write_File_Result *result = 0;
ACE_NEW_RETURN (result,
ACE_WIN32_Asynch_Write_File_Result (this->handler_proxy_,
this->handle_,
message_block,
bytes_to_write,
act,
offset,
offset_high,
this->win32_proactor_->get_handle (),
priority,
signal_number,
1), // gather write enabled
-1);
result->set_error(0);
// do the gather write
int initiate_result = ::WriteFileGather (result->handle (),
buffer_pointers,
dword_bytes_to_write,
0, // reserved, must be NULL
result);
if (0 != initiate_result)
// Immediate success: the OVERLAPPED will still get queued.
return 1;
// If initiate failed, check for a bad error.
ACE_OS::set_errno_to_last_error ();
switch (errno)
{
case ERROR_IO_PENDING:
// The IO will complete proactively: the OVERLAPPED will still
// get queued.
initiate_result = 0;
break;
default:
// Something else went wrong: the OVERLAPPED will not get
// queued.
if (ACE::debug ())
{
ACE_DEBUG ((LM_ERROR,
ACE_TEXT ("%p\n"),
ACE_TEXT ("WriteFileGather")));
}
delete result;
initiate_result = -1;
break;
}
return initiate_result;
#else
ACE_NOTSUP_RETURN (-1);
#endif /* ACE_HAS_WIN32_OVERLAPPED_IO */
}
ACE_WIN32_Asynch_Write_File::~ACE_WIN32_Asynch_Write_File (void)
{
}
int
ACE_WIN32_Asynch_Write_File::write (ACE_Message_Block &message_block,
size_t bytes_to_write,
const void *act,
int priority,
int signal_number)
{
return ACE_WIN32_Asynch_Write_Stream::write (message_block,
bytes_to_write,
act,
priority,
signal_number);
}
int
ACE_WIN32_Asynch_Write_File::writev (ACE_Message_Block &message_block,
size_t bytes_to_write,
const void *act,
int priority,
int signal_number)
{
return ACE_WIN32_Asynch_Write_Stream::writev (message_block,
bytes_to_write,
act,
priority,
signal_number);
}
// Methods belong to ACE_WIN32_Asynch_Operation base class. These
// methods are defined here to avoid VC++ warnings. They route the
// call to the ACE_WIN32_Asynch_Operation base class.
int
ACE_WIN32_Asynch_Write_File::open (const ACE_Handler::Proxy_Ptr &handler_proxy,
ACE_HANDLE handle,
const void *completion_key,
ACE_Proactor *proactor)
{
return ACE_WIN32_Asynch_Operation::open (handler_proxy,
handle,
completion_key,
proactor);
}
int
ACE_WIN32_Asynch_Write_File::cancel (void)
{
return ACE_WIN32_Asynch_Operation::cancel ();
}
ACE_Proactor *
ACE_WIN32_Asynch_Write_File::proactor (void) const
{
return ACE_WIN32_Asynch_Operation::proactor ();
}
size_t
ACE_WIN32_Asynch_Accept_Result::bytes_to_read (void) const
{
return this->bytes_to_read_;
}
ACE_Message_Block &
ACE_WIN32_Asynch_Accept_Result::message_block (void) const
{
return this->message_block_;
}
ACE_HANDLE
ACE_WIN32_Asynch_Accept_Result::listen_handle (void) const
{
return this->listen_handle_;
}
ACE_HANDLE
ACE_WIN32_Asynch_Accept_Result::accept_handle (void) const
{
return this->accept_handle_;
}
ACE_WIN32_Asynch_Accept_Result::ACE_WIN32_Asynch_Accept_Result (
const ACE_Handler::Proxy_Ptr &handler_proxy,
ACE_HANDLE listen_handle,
ACE_HANDLE accept_handle,
ACE_Message_Block &message_block,
size_t bytes_to_read,
const void* act,
ACE_HANDLE event,
int priority,
int signal_number)
: ACE_Asynch_Result_Impl (),
ACE_Asynch_Accept_Result_Impl (),
ACE_WIN32_Asynch_Result (handler_proxy,
act,
event,
0,
0,
priority,
signal_number),
bytes_to_read_ (bytes_to_read),
message_block_ (message_block),
listen_handle_ (listen_handle),
accept_handle_ (accept_handle)
{
}
void
ACE_WIN32_Asynch_Accept_Result::complete (size_t bytes_transferred,
int success,
const void *completion_key,
u_long error)
{
// Copy the data which was returned by GetQueuedCompletionStatus
this->bytes_transferred_ = bytes_transferred;
this->success_ = success;
this->completion_key_ = completion_key;
this->error_ = error;
// Appropriately move the pointers in the message block.
this->message_block_.wr_ptr (bytes_transferred);
if (!success && this->accept_handle_ != ACE_INVALID_HANDLE)
{
ACE_OS::closesocket (this->accept_handle_);
this->accept_handle_ = ACE_INVALID_HANDLE;
}
// Create the interface result class.
ACE_Asynch_Accept::Result result (this);
// Call the application handler.
ACE_Handler *handler = this->handler_proxy_.get ()->handler ();
if (handler != 0)
handler->handle_accept (result);
}
ACE_WIN32_Asynch_Accept_Result::~ACE_WIN32_Asynch_Accept_Result (void)
{
}
// Base class operations. These operations are here to kill dominance
// warnings. These methods call the base class methods.
size_t
ACE_WIN32_Asynch_Accept_Result::bytes_transferred (void) const
{
return ACE_WIN32_Asynch_Result::bytes_transferred ();
}
const void *
ACE_WIN32_Asynch_Accept_Result::act (void) const
{
return ACE_WIN32_Asynch_Result::act ();
}
int
ACE_WIN32_Asynch_Accept_Result::success (void) const
{
return ACE_WIN32_Asynch_Result::success ();
}
const void *
ACE_WIN32_Asynch_Accept_Result::completion_key (void) const
{
return ACE_WIN32_Asynch_Result::completion_key ();
}
u_long
ACE_WIN32_Asynch_Accept_Result::error (void) const
{
return ACE_WIN32_Asynch_Result::error ();
}
ACE_HANDLE
ACE_WIN32_Asynch_Accept_Result::event (void) const
{
return ACE_WIN32_Asynch_Result::event ();
}
u_long
ACE_WIN32_Asynch_Accept_Result::offset (void) const
{
return ACE_WIN32_Asynch_Result::offset ();
}
u_long
ACE_WIN32_Asynch_Accept_Result::offset_high (void) const
{
return ACE_WIN32_Asynch_Result::offset_high ();
}
int
ACE_WIN32_Asynch_Accept_Result::priority (void) const
{
return ACE_WIN32_Asynch_Result::priority ();
}
int
ACE_WIN32_Asynch_Accept_Result::signal_number (void) const
{
return ACE_WIN32_Asynch_Result::signal_number ();
}
int
ACE_WIN32_Asynch_Accept_Result::post_completion (ACE_Proactor_Impl *proactor)
{
return ACE_WIN32_Asynch_Result::post_completion (proactor);
}
ACE_WIN32_Asynch_Accept::ACE_WIN32_Asynch_Accept (ACE_WIN32_Proactor *win32_proactor)
: ACE_Asynch_Operation_Impl (),
ACE_Asynch_Accept_Impl (),
ACE_WIN32_Asynch_Operation (win32_proactor)
{
}
int
ACE_WIN32_Asynch_Accept::accept (ACE_Message_Block &message_block,
size_t bytes_to_read,
ACE_HANDLE accept_handle,
const void *act,
int priority,
int signal_number,
int addr_family)
{
#if defined (ACE_HAS_WIN32_OVERLAPPED_IO) || (defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0))
// Sanity check: make sure that enough space has been allocated by
// the caller.
size_t address_size =
#if defined (ACE_HAS_IPV6)
addr_family == AF_INET ? sizeof (sockaddr_in) : sizeof (sockaddr_in6);
#else
sizeof (sockaddr_in);
#endif /* ACE_HAS_IPV6 */
address_size += 16; // AcceptEx requires address size + 16 (minimum)
size_t available_space = message_block.space ();
size_t space_needed = bytes_to_read + 2 * address_size;
if (available_space < space_needed)
ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("Buffer too small\n")), -1);
// WIN Specific.
// AcceptEx API limits us to DWORD range.
if (bytes_to_read > MAXDWORD)
{
errno = ERANGE;
return -1;
}
DWORD dword_bytes_to_read = static_cast<DWORD> (bytes_to_read);
int close_accept_handle = 0;
// If the <accept_handle> is invalid, we will create a new socket.
if (accept_handle == ACE_INVALID_HANDLE)
{
accept_handle = ACE_OS::socket (addr_family,
SOCK_STREAM,
0);
if (accept_handle == ACE_INVALID_HANDLE)
{
if (ACE::debug ())
{
ACE_DEBUG ((LM_ERROR,
ACE_TEXT ("%p\n"),
ACE_TEXT ("ACE_OS::socket")));
}
return -1;
}
else
// Remember to close the socket down if failures occur.
close_accept_handle = 1;
}
// Common code for both WIN and POSIX.
ACE_WIN32_Asynch_Accept_Result *result = 0;
ACE_NEW_RETURN (result,
ACE_WIN32_Asynch_Accept_Result (this->handler_proxy_,
this->handle_,
accept_handle,
message_block,
bytes_to_read,
act,
this->win32_proactor_->get_handle (),
priority,
signal_number),
-1);
u_long bytes_read;
// Initiate the accept.
int initiate_result = ::AcceptEx ((SOCKET) result->listen_handle (),
(SOCKET) result->accept_handle (),
result->message_block ().wr_ptr (),
dword_bytes_to_read,
static_cast<DWORD> (address_size),
static_cast<DWORD> (address_size),
&bytes_read,
result);
if (initiate_result == 1)
// Immediate success: the OVERLAPPED will still get queued.
return 1;
// If initiate failed, check for a bad error.
ACE_OS::set_errno_to_last_error ();
switch (errno)
{
case ERROR_IO_PENDING:
// The IO will complete proactively: the OVERLAPPED will still
// get queued.
return 0;
default:
// Something else went wrong: the OVERLAPPED will not get
// queued.
if (close_accept_handle == 1)
// Close the newly created socket
ACE_OS::closesocket (accept_handle);
// Cleanup dynamically allocated Asynch_Result.
delete result;
if (ACE::debug ())
{
ACE_DEBUG ((LM_ERROR,
ACE_TEXT ("%p\n"),
ACE_TEXT ("AcceptEx")));
}
return -1;
}
#else
ACE_UNUSED_ARG (message_block);
ACE_UNUSED_ARG (bytes_to_read);
ACE_UNUSED_ARG (accept_handle);
ACE_UNUSED_ARG (act);
ACE_UNUSED_ARG (priority);
ACE_UNUSED_ARG (signal_number);
ACE_UNUSED_ARG (addr_family);
ACE_NOTSUP_RETURN (-1);
#endif /* defined (ACE_HAS_WIN32_OVERLAPPED_IO) || (defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)) */
}
ACE_WIN32_Asynch_Accept::~ACE_WIN32_Asynch_Accept (void)
{
}
// Methods belong to ACE_WIN32_Asynch_Operation base class. These
// methods are defined here to avoid VC++ warnings. They route the
// call to the ACE_WIN32_Asynch_Operation base class.
int
ACE_WIN32_Asynch_Accept::open (const ACE_Handler::Proxy_Ptr &handler_proxy,
ACE_HANDLE handle,
const void *completion_key,
ACE_Proactor *proactor)
{
return ACE_WIN32_Asynch_Operation::open (handler_proxy,
handle,
completion_key,
proactor);
}
int
ACE_WIN32_Asynch_Accept::cancel (void)
{
return ACE_WIN32_Asynch_Operation::cancel ();
}
ACE_Proactor *
ACE_WIN32_Asynch_Accept::proactor (void) const
{
return ACE_WIN32_Asynch_Operation::proactor ();
}
// *********************************************************************
ACE_HANDLE
ACE_WIN32_Asynch_Connect_Result::connect_handle (void) const
{
return this->connect_handle_;
}
void ACE_WIN32_Asynch_Connect_Result::connect_handle ( ACE_HANDLE handle )
{
this->connect_handle_ = handle;
}
ACE_WIN32_Asynch_Connect_Result::ACE_WIN32_Asynch_Connect_Result
(const ACE_Handler::Proxy_Ptr &handler_proxy,
ACE_HANDLE connect_handle,
const void* act,
ACE_HANDLE event,
int priority,
int signal_number)
: ACE_Asynch_Result_Impl (),
ACE_Asynch_Connect_Result_Impl (),
ACE_WIN32_Asynch_Result
(handler_proxy, act, event, 0, 0, priority, signal_number),
connect_handle_ (connect_handle)
{
;
}
void
ACE_WIN32_Asynch_Connect_Result::complete (size_t bytes_transferred,
int success,
const void *completion_key,
u_long error)
{
// Copy the data.
this->bytes_transferred_ = bytes_transferred;
this->success_ = success;
this->completion_key_ = completion_key;
this->error_ = error;
// Create the interface result class.
ACE_Asynch_Connect::Result result (this);
// Call the application handler.
ACE_Handler *handler = this->handler_proxy_.get ()->handler ();
if (handler != 0)
handler->handle_connect (result);
}
ACE_WIN32_Asynch_Connect_Result::~ACE_WIN32_Asynch_Connect_Result (void)
{
}
// Base class operations. These operations are here to kill dominance
// warnings. These methods call the base class methods.
size_t
ACE_WIN32_Asynch_Connect_Result::bytes_transferred (void) const
{
return ACE_WIN32_Asynch_Result::bytes_transferred ();
}
const void *
ACE_WIN32_Asynch_Connect_Result::act (void) const
{
return ACE_WIN32_Asynch_Result::act ();
}
int
ACE_WIN32_Asynch_Connect_Result::success (void) const
{
return ACE_WIN32_Asynch_Result::success ();
}
const void *
ACE_WIN32_Asynch_Connect_Result::completion_key (void) const
{
return ACE_WIN32_Asynch_Result::completion_key ();
}
u_long
ACE_WIN32_Asynch_Connect_Result::error (void) const
{
return ACE_WIN32_Asynch_Result::error ();
}
ACE_HANDLE
ACE_WIN32_Asynch_Connect_Result::event (void) const
{
return ACE_WIN32_Asynch_Result::event ();
}
u_long
ACE_WIN32_Asynch_Connect_Result::offset (void) const
{
return ACE_WIN32_Asynch_Result::offset ();
}
u_long
ACE_WIN32_Asynch_Connect_Result::offset_high (void) const
{
return ACE_WIN32_Asynch_Result::offset_high ();
}
int
ACE_WIN32_Asynch_Connect_Result::priority (void) const
{
return ACE_WIN32_Asynch_Result::priority ();
}
int
ACE_WIN32_Asynch_Connect_Result::signal_number (void) const
{
return ACE_WIN32_Asynch_Result::signal_number ();
}
int
ACE_WIN32_Asynch_Connect_Result::post_completion (ACE_Proactor_Impl *proactor)
{
return ACE_WIN32_Asynch_Result::post_completion (proactor);
}
// *********************************************************************
ACE_WIN32_Asynch_Connect::ACE_WIN32_Asynch_Connect (ACE_WIN32_Proactor * win32_proactor)
: ACE_Asynch_Operation_Impl (),
ACE_Asynch_Connect_Impl (),
ACE_WIN32_Asynch_Operation (win32_proactor),
flg_open_ (false)
{
}
ACE_WIN32_Asynch_Connect::~ACE_WIN32_Asynch_Connect (void)
{
this->close ();
this->reactor (0); // to avoid purge_pending_notifications
}
ACE_Proactor *
ACE_WIN32_Asynch_Connect::proactor (void) const
{
return ACE_WIN32_Asynch_Operation::proactor ();
}
ACE_HANDLE
ACE_WIN32_Asynch_Connect::get_handle (void) const
{
ACE_ASSERT (0);
return ACE_INVALID_HANDLE;
}
void
ACE_WIN32_Asynch_Connect::set_handle (ACE_HANDLE)
{
ACE_ASSERT (0) ;
}
int
ACE_WIN32_Asynch_Connect::open (const ACE_Handler::Proxy_Ptr &handler_proxy,
ACE_HANDLE,
const void *completion_key,
ACE_Proactor *proactor)
{
ACE_TRACE ("ACE_WIN32_Asynch_Connect::open");
// if we are already opened,
// we could not create a new handler without closing the previous
if (this->flg_open_)
ACE_ERROR_RETURN ((LM_ERROR,
ACE_TEXT ("%N:%l:ACE_WIN32_Asynch_Connect::open:")
ACE_TEXT ("connector already open\n")),
-1);
//int result =
ACE_WIN32_Asynch_Operation::open (handler_proxy,
ACE_INVALID_HANDLE,
completion_key,
proactor);
// Ignore result as we pass ACE_INVALID_HANDLE
//if (result == -1)
// return result;
this->flg_open_ = true;
return 0;
}
int
ACE_WIN32_Asynch_Connect::connect (ACE_HANDLE connect_handle,
const ACE_Addr & remote_sap,
const ACE_Addr & local_sap,
int reuse_addr,
const void *act,
int priority,
int signal_number)
{
ACE_TRACE ("ACE_WIN32_Asynch_Connect::connect");
if (!this->flg_open_)
ACE_ERROR_RETURN ((LM_ERROR,
ACE_TEXT ("%N:%l:ACE_WIN32_Asynch_Connect::connect")
ACE_TEXT ("connector was not opened before\n")),
-1);
// Common code for both WIN and WIN32.
// Create future Asynch_Connect_Result
ACE_WIN32_Asynch_Connect_Result *result = 0;
ACE_NEW_RETURN (result,
ACE_WIN32_Asynch_Connect_Result (this->handler_proxy_,
connect_handle,
act,
this->win32_proactor_->get_handle (),
priority,
signal_number),
-1);
int rc = connect_i (result,
remote_sap,
local_sap,
reuse_addr);
// update handle
connect_handle = result->connect_handle ();
if (rc != 0)
return post_result (result, true);
// Enqueue result we will wait for completion
{
ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1));
if (this->result_map_.bind (connect_handle, result) == -1)
{
ACE_ERROR ((LM_ERROR,
ACE_TEXT ("ACE_WIN32_Asynch_Connect::connect: %p\n"),
ACE_TEXT ("bind")));
result->set_error (EFAULT);
return post_result (result, true);
}
}
ACE_Asynch_Pseudo_Task & task =
this->win32_proactor_->get_asynch_pseudo_task ();
if (-1 == task.register_io_handler (connect_handle,
this,
ACE_Event_Handler::CONNECT_MASK,
0)) // not to suspend after register
{
result = 0;
{
ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1));
this->result_map_.unbind (connect_handle, result);
}
if (result != 0)
{
result->set_error (EFAULT);
this->post_result (result, true);
}
}
return 0;
}
int ACE_WIN32_Asynch_Connect::post_result (ACE_WIN32_Asynch_Connect_Result * result,
bool post_enable)
{
ACE_HANDLE handle = result->connect_handle ();
if (this->flg_open_ && post_enable)
{
// NOTE: result is invalid after post_completion(). It's either deleted
// or will be shortly via the proactor dispatch, regardless of success
// or fail of the call.
if (this->win32_proactor_ ->post_completion (result) == 0)
return 0;
ACE_ERROR ((LM_ERROR,
ACE_TEXT ("Error:(%P | %t):%p\n"),
ACE_TEXT ("ACE_WIN32_Asynch_Connect::post_result: ")
ACE_TEXT (" <post_completion> failed")));
}
else
{
// There was no call to post_completion() so manually delete result.
delete result;
}
if (handle != ACE_INVALID_HANDLE)
ACE_OS::closesocket (handle);
return -1;
}
// connect_i
// return code :
// -1 errors before attempt to connect
// 0 connect started
// 1 connect finished ( may be unsuccessfully)
int
ACE_WIN32_Asynch_Connect::connect_i (ACE_WIN32_Asynch_Connect_Result *result,
const ACE_Addr & remote_sap,
const ACE_Addr & local_sap,
int reuse_addr)
{
result->set_bytes_transferred (0);
ACE_HANDLE handle = result->connect_handle ();
if (handle == ACE_INVALID_HANDLE)
{
int protocol_family = remote_sap.get_type ();
handle = ACE_OS::socket (protocol_family,
SOCK_STREAM,
0);
// save it
result->connect_handle (handle);
if (handle == ACE_INVALID_HANDLE)
{
result->set_error (errno);
ACE_ERROR_RETURN
((LM_ERROR,
ACE_TEXT ("ACE_WIN32_Asynch_Connect::connect_i: %p\n"),
ACE_TEXT ("socket")),
-1);
}
// Reuse the address
int one = 1;
if (protocol_family != PF_UNIX &&
reuse_addr != 0 &&
ACE_OS::setsockopt (handle,
SOL_SOCKET,
SO_REUSEADDR,
(const char*) &one,
sizeof one) == -1)
{
result->set_error (errno);
ACE_ERROR_RETURN
((LM_ERROR,
ACE_TEXT ("ACE_WIN32_Asynch_Connect::connect_i: %p\n"),
ACE_TEXT ("setsockopt")),
-1);
}
}
if (local_sap != ACE_Addr::sap_any)
{
sockaddr * laddr = reinterpret_cast<sockaddr *> (local_sap.get_addr ());
int size = local_sap.get_size ();
if (ACE_OS::bind (handle, laddr, size) == -1)
{
result->set_error (errno);
ACE_ERROR_RETURN
((LM_ERROR,
ACE_TEXT ("ACE_WIN32_Asynch_Connect::connect_i: %p\n"),
ACE_TEXT ("bind")),
-1);
}
}
// set non blocking mode
if (ACE::set_flags (handle, ACE_NONBLOCK) != 0)
{
result->set_error (errno);
ACE_ERROR_RETURN
((LM_ERROR,
ACE_TEXT ("ACE_WIN32_Asynch_Connect::connect_i: %p\n"),
ACE_TEXT ("set_flags")),
-1);
}
for (;;)
{
int rc = ACE_OS::connect
(handle,
reinterpret_cast<sockaddr *> (remote_sap.get_addr ()),
remote_sap.get_size ());
if (rc < 0) // failure
{
if (errno == EWOULDBLOCK || errno == EINPROGRESS)
return 0; // connect started
if (errno == EINTR)
continue;
result->set_error (errno);
}
return 1 ; // connect finished
}
}
// cancel_uncompleted
// It performs cancellation of all pending requests
//
// Parameter flg_notify can be
// 0 - don't send notifications about canceled accepts
// !0 - notify user about canceled accepts
// according WIN32 standards we should receive notifications
// on canceled AIO requests
//
// Return value : number of cancelled requests
//
int
ACE_WIN32_Asynch_Connect::cancel_uncompleted (bool flg_notify,
ACE_Handle_Set &set)
{
ACE_TRACE ("ACE_WIN32_Asynch_Connect::cancel_uncompleted");
int retval = 0;
MAP_MANAGER::ITERATOR iter (result_map_);
MAP_MANAGER::ENTRY * me = 0;
set.reset ();
for (; iter.next (me) != 0; retval++, iter.advance ())
{
ACE_HANDLE handle = me->ext_id_;
ACE_WIN32_Asynch_Connect_Result* result = me->int_id_ ;
set.set_bit (handle);
result->set_bytes_transferred (0);
result->set_error (ERROR_OPERATION_ABORTED);
this->post_result (result, flg_notify);
}
result_map_.unbind_all ();
return retval;
}
int
ACE_WIN32_Asynch_Connect::cancel (void)
{
ACE_TRACE ("ACE_WIN32_Asynch_Connect::cancel");
int rc = -1 ; // ERRORS
ACE_Handle_Set set;
int num_cancelled = 0;
{
ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1));
num_cancelled = cancel_uncompleted (flg_open_, set);
}
if (num_cancelled == 0)
rc = 1; // AIO_ALLDONE
else if (num_cancelled > 0)
rc = 0; // AIO_CANCELED
if (!this->flg_open_)
return rc;
ACE_Asynch_Pseudo_Task & task =
this->win32_proactor_->get_asynch_pseudo_task ();
task.remove_io_handler (set);
return rc;
}
int
ACE_WIN32_Asynch_Connect::close (void)
{
ACE_TRACE ("ACE_WIN32_Asynch_Connect::close");
ACE_Handle_Set set;
int num_cancelled = 0;
{
ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, -1));
num_cancelled = cancel_uncompleted (flg_open_, set);
}
if (num_cancelled == 0 || this->flg_open_ == 0)
{
this->flg_open_ = false;
return 0;
}
ACE_Asynch_Pseudo_Task & task =
this->win32_proactor_->get_asynch_pseudo_task ();
task.remove_io_handler (set);
return 0;
}
int
ACE_WIN32_Asynch_Connect::handle_exception (ACE_HANDLE fd)
{
ACE_TRACE ("ACE_WIN32_Asynch_Connect::handle_exception");
return handle_output (fd);
}
int
ACE_WIN32_Asynch_Connect::handle_input (ACE_HANDLE fd)
{
ACE_TRACE ("ACE_WIN32_Asynch_Connect::handle_input");
return handle_output (fd);
}
int
ACE_WIN32_Asynch_Connect::handle_output (ACE_HANDLE fd)
{
ACE_TRACE ("ACE_WIN32_Asynch_Connect::handle_output");
ACE_WIN32_Asynch_Connect_Result* result = 0;
{
ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, 0));
if (this->result_map_.unbind (fd, result) != 0) // not found
return -1;
}
int sockerror = 0 ;
int lsockerror = sizeof sockerror;
ACE_OS::getsockopt (fd,
SOL_SOCKET,
SO_ERROR,
(char*) & sockerror,
& lsockerror);
// This previously just did a "return -1" and let handle_close() clean
// things up. However, this entire object may be gone as a result of
// the application's completion handler, so don't count on 'this' being
// legitimate on return from post_result().
// remove_io_handler() contains flag DONT_CALL
this->win32_proactor_->get_asynch_pseudo_task().remove_io_handler (fd);
result->set_bytes_transferred (0);
result->set_error (sockerror);
this->post_result (result, this->flg_open_);
return 0;
}
int
ACE_WIN32_Asynch_Connect::handle_close (ACE_HANDLE fd, ACE_Reactor_Mask)
{
ACE_TRACE ("ACE_WIN32_Asynch_Connect::handle_close");
ACE_Asynch_Pseudo_Task & task =
this->win32_proactor_->get_asynch_pseudo_task ();
task.remove_io_handler (fd);
ACE_WIN32_Asynch_Connect_Result* result = 0;
{
ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->lock_, 0));
if (this->result_map_.unbind (fd, result) != 0) // not found
return -1;
}
result->set_bytes_transferred (0);
result->set_error (ERROR_OPERATION_ABORTED);
this->post_result (result, this->flg_open_);
return 0;
}
// *********************************************************************
ACE_HANDLE
ACE_WIN32_Asynch_Transmit_File_Result::socket (void) const
{
return this->socket_;
}
ACE_HANDLE
ACE_WIN32_Asynch_Transmit_File_Result::file (void) const
{
return this->file_;
}
ACE_Asynch_Transmit_File::Header_And_Trailer *
ACE_WIN32_Asynch_Transmit_File_Result::header_and_trailer (void) const
{
return this->header_and_trailer_;
}
size_t
ACE_WIN32_Asynch_Transmit_File_Result::bytes_to_write (void) const
{
return this->bytes_to_write_;
}
size_t
ACE_WIN32_Asynch_Transmit_File_Result::bytes_per_send (void) const
{
return this->bytes_per_send_;
}
u_long
ACE_WIN32_Asynch_Transmit_File_Result::flags (void) const
{
return this->flags_;
}
ACE_WIN32_Asynch_Transmit_File_Result::ACE_WIN32_Asynch_Transmit_File_Result (
const ACE_Handler::Proxy_Ptr &handler_proxy,
ACE_HANDLE socket,
ACE_HANDLE file,
ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer,
size_t bytes_to_write,
u_long offset,
u_long offset_high,
size_t bytes_per_send,
u_long flags,
const void *act,
ACE_HANDLE event,
int priority,
int signal_number)
: ACE_Asynch_Result_Impl (),
ACE_Asynch_Transmit_File_Result_Impl (),
ACE_WIN32_Asynch_Result (handler_proxy,
act,
event,
offset,
offset_high,
priority,
signal_number),
socket_ (socket),
file_ (file),
header_and_trailer_ (header_and_trailer),
bytes_to_write_ (bytes_to_write),
bytes_per_send_ (bytes_per_send),
flags_ (flags)
{
}
void
ACE_WIN32_Asynch_Transmit_File_Result::complete (size_t bytes_transferred,
int success,
const void *completion_key,
u_long error)
{
// Copy the data which was returned by GetQueuedCompletionStatus
this->bytes_transferred_ = bytes_transferred;
this->success_ = success;
this->completion_key_ = completion_key;
this->error_ = error;
// We will not do this because (a) the header and trailer blocks may
// be the same message_blocks and (b) in cases of failures we have
// no idea how much of what (header, data, trailer) was sent.
/*
if (this->success_ && this->header_and_trailer_ != 0)
{
ACE_Message_Block *header = this->header_and_trailer_->header ();
if (header != 0)
header->rd_ptr (this->header_and_trailer_->header_bytes ());
ACE_Message_Block *trailer = this->header_and_trailer_->trailer ();
if (trailer != 0)
trailer->rd_ptr (this->header_and_trailer_->trailer_bytes ());
}
*/
// Create the interface result class.
ACE_Asynch_Transmit_File::Result result (this);
// Call the application handler.
ACE_Handler *handler = this->handler_proxy_.get ()->handler ();
if (handler != 0)
handler->handle_transmit_file (result);
}
ACE_WIN32_Asynch_Transmit_File_Result::~ACE_WIN32_Asynch_Transmit_File_Result (void)
{
}
// Base class operations. These operations are here to kill dominance
// warnings. These methods call the base class methods.
size_t
ACE_WIN32_Asynch_Transmit_File_Result::bytes_transferred (void) const
{
return ACE_WIN32_Asynch_Result::bytes_transferred ();
}
const void *
ACE_WIN32_Asynch_Transmit_File_Result::act (void) const
{
return ACE_WIN32_Asynch_Result::act ();
}
int
ACE_WIN32_Asynch_Transmit_File_Result::success (void) const
{
return ACE_WIN32_Asynch_Result::success ();
}
const void *
ACE_WIN32_Asynch_Transmit_File_Result::completion_key (void) const
{
return ACE_WIN32_Asynch_Result::completion_key ();
}
u_long
ACE_WIN32_Asynch_Transmit_File_Result::error (void) const
{
return ACE_WIN32_Asynch_Result::error ();
}
ACE_HANDLE
ACE_WIN32_Asynch_Transmit_File_Result::event (void) const
{
return ACE_WIN32_Asynch_Result::event ();
}
u_long
ACE_WIN32_Asynch_Transmit_File_Result::offset (void) const
{
return ACE_WIN32_Asynch_Result::offset ();
}
u_long
ACE_WIN32_Asynch_Transmit_File_Result::offset_high (void) const
{
return ACE_WIN32_Asynch_Result::offset_high ();
}
int
ACE_WIN32_Asynch_Transmit_File_Result::priority (void) const
{
return ACE_WIN32_Asynch_Result::priority ();
}
int
ACE_WIN32_Asynch_Transmit_File_Result::signal_number (void) const
{
return ACE_WIN32_Asynch_Result::signal_number ();
}
int
ACE_WIN32_Asynch_Transmit_File_Result::post_completion (ACE_Proactor_Impl *proactor)
{
return ACE_WIN32_Asynch_Result::post_completion (proactor);
}
ACE_WIN32_Asynch_Transmit_File::ACE_WIN32_Asynch_Transmit_File (ACE_WIN32_Proactor *win32_proactor)
: ACE_Asynch_Operation_Impl (),
ACE_Asynch_Transmit_File_Impl (),
ACE_WIN32_Asynch_Operation (win32_proactor)
{
}
int
ACE_WIN32_Asynch_Transmit_File::transmit_file (ACE_HANDLE file,
ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer,
size_t bytes_to_write,
u_long offset,
u_long offset_high,
size_t bytes_per_send,
u_long flags,
const void *act,
int priority,
int signal_number)
{
#if defined (ACE_HAS_WIN32_OVERLAPPED_IO) || (defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0))
// TransmitFile API limits us to DWORD range.
if (bytes_to_write > MAXDWORD || bytes_per_send > MAXDWORD)
{
errno = ERANGE;
return -1;
}
DWORD dword_bytes_to_write = static_cast<DWORD> (bytes_to_write);
DWORD dword_bytes_per_send = static_cast<DWORD> (bytes_per_send);
ACE_WIN32_Asynch_Transmit_File_Result *result = 0;
ACE_NEW_RETURN (result,
ACE_WIN32_Asynch_Transmit_File_Result (this->handler_proxy_,
this->handle_,
file,
header_and_trailer,
bytes_to_write,
offset,
offset_high,
bytes_per_send,
flags,
act,
this->win32_proactor_->get_handle (),
priority,
signal_number),
-1);
ACE_LPTRANSMIT_FILE_BUFFERS transmit_buffers = 0;
if (result->header_and_trailer () != 0)
transmit_buffers = result->header_and_trailer ()->transmit_buffers ();
// Initiate the transmit file
int initiate_result = ::TransmitFile ((SOCKET) result->socket (),
result->file (),
dword_bytes_to_write,
dword_bytes_per_send,
result,
transmit_buffers,
result->flags ());
if (initiate_result == 1)
// Immediate success: the OVERLAPPED will still get queued.
return 1;
// If initiate failed, check for a bad error.
ACE_OS::set_errno_to_last_error ();
switch (errno)
{
case ERROR_IO_PENDING:
// The IO will complete proactively: the OVERLAPPED will still
// get queued.
return 0;
default:
// Something else went wrong: the OVERLAPPED will not get
// queued.
// Cleanup dynamically allocated Asynch_Result
delete result;
if (ACE::debug ())
{
ACE_DEBUG ((LM_ERROR,
ACE_TEXT ("%p\n"),
ACE_TEXT ("TransmitFile")));
}
return -1;
}
#else
ACE_UNUSED_ARG (file);
ACE_UNUSED_ARG (header_and_trailer);
ACE_UNUSED_ARG (bytes_to_write);
ACE_UNUSED_ARG (offset);
ACE_UNUSED_ARG (offset_high);
ACE_UNUSED_ARG (bytes_per_send);
ACE_UNUSED_ARG (flags);
ACE_UNUSED_ARG (act);
ACE_UNUSED_ARG (priority);
ACE_UNUSED_ARG (signal_number);
ACE_NOTSUP_RETURN (-1);
#endif /* ACE_HAS_WIN32_OVERLAPPED_IO || ACE_HAS_WINSOCK2 */
}
ACE_WIN32_Asynch_Transmit_File::~ACE_WIN32_Asynch_Transmit_File (void)
{
}
// Methods belong to ACE_WIN32_Asynch_Operation base class. These
// methods are defined here to avoid VC++ warnings. They route the
// call to the ACE_WIN32_Asynch_Operation base class.
int
ACE_WIN32_Asynch_Transmit_File::open (const ACE_Handler::Proxy_Ptr &handler_proxy,
ACE_HANDLE handle,
const void *completion_key,
ACE_Proactor *proactor)
{
return ACE_WIN32_Asynch_Operation::open (handler_proxy,
handle,
completion_key,
proactor);
}
int
ACE_WIN32_Asynch_Transmit_File::cancel (void)
{
return ACE_WIN32_Asynch_Operation::cancel ();
}
ACE_Proactor *
ACE_WIN32_Asynch_Transmit_File::proactor (void) const
{
return ACE_WIN32_Asynch_Operation::proactor ();
}
size_t
ACE_WIN32_Asynch_Read_Dgram_Result::bytes_to_read (void) const
{
return this->bytes_to_read_;
}
ACE_Message_Block*
ACE_WIN32_Asynch_Read_Dgram_Result::message_block (void) const
{
return this->message_block_;
}
int
ACE_WIN32_Asynch_Read_Dgram_Result::remote_address (ACE_Addr& addr) const
{
int retVal = -1; // failure
// make sure the addresses are of the same type
if (addr.get_type () == this->remote_address_->get_type ())
{ // copy the remote_address_ into addr
addr.set_addr (this->remote_address_->get_addr (),
this->remote_address_->get_size ());
retVal = 0; // success
}
return retVal;
}
sockaddr *
ACE_WIN32_Asynch_Read_Dgram_Result::saddr () const
{
return (sockaddr *) this->remote_address_->get_addr ();
}
int
ACE_WIN32_Asynch_Read_Dgram_Result::flags (void) const
{
return this->flags_;
}
ACE_HANDLE
ACE_WIN32_Asynch_Read_Dgram_Result::handle (void) const
{
return this->handle_;
}
size_t
ACE_WIN32_Asynch_Read_Dgram_Result::bytes_transferred (void) const
{
return ACE_WIN32_Asynch_Result::bytes_transferred ();
}
const void *
ACE_WIN32_Asynch_Read_Dgram_Result::act (void) const
{
return ACE_WIN32_Asynch_Result::act ();
}
int
ACE_WIN32_Asynch_Read_Dgram_Result::success (void) const
{
return ACE_WIN32_Asynch_Result::success ();
}
const void *
ACE_WIN32_Asynch_Read_Dgram_Result::completion_key (void) const
{
return ACE_WIN32_Asynch_Result::completion_key ();
}
u_long
ACE_WIN32_Asynch_Read_Dgram_Result::error (void) const
{
return ACE_WIN32_Asynch_Result::error ();
}
ACE_HANDLE
ACE_WIN32_Asynch_Read_Dgram_Result::event (void) const
{
return ACE_WIN32_Asynch_Result::event ();
}
u_long
ACE_WIN32_Asynch_Read_Dgram_Result::offset (void) const
{
return ACE_WIN32_Asynch_Result::offset ();
}
u_long
ACE_WIN32_Asynch_Read_Dgram_Result::offset_high (void) const
{
return ACE_WIN32_Asynch_Result::offset_high ();
}
int
ACE_WIN32_Asynch_Read_Dgram_Result::priority (void) const
{
return ACE_WIN32_Asynch_Result::priority ();
}
int
ACE_WIN32_Asynch_Read_Dgram_Result::signal_number (void) const
{
return ACE_WIN32_Asynch_Result::signal_number ();
}
int
ACE_WIN32_Asynch_Read_Dgram_Result::post_completion (ACE_Proactor_Impl *proactor)
{
return ACE_WIN32_Asynch_Result::post_completion (proactor);
}
ACE_WIN32_Asynch_Read_Dgram_Result::ACE_WIN32_Asynch_Read_Dgram_Result (
const ACE_Handler::Proxy_Ptr &handler_proxy,
ACE_HANDLE handle,
ACE_Message_Block *message_block,
size_t bytes_to_read,
int flags,
int protocol_family,
const void* act,
ACE_HANDLE event,
int priority,
int signal_number)
: ACE_Asynch_Result_Impl (),
ACE_Asynch_Read_Dgram_Result_Impl(),
ACE_WIN32_Asynch_Result (handler_proxy, act, event, 0, 0, priority, signal_number),
bytes_to_read_ (bytes_to_read),
message_block_ (message_block),
remote_address_ (0),
addr_len_ (0),
flags_ (flags),
handle_ (handle)
{
ACE_ASSERT (protocol_family == PF_INET); // only supporting INET addresses
ACE_NEW (remote_address_, ACE_INET_Addr);
addr_len_ = remote_address_->get_size ();
ACE_UNUSED_ARG (protocol_family);
}
void
ACE_WIN32_Asynch_Read_Dgram_Result::complete (size_t bytes_transferred,
int success,
const void *completion_key,
u_long error)
{
// Copy the data which was returned by GetQueuedCompletionStatus
this->bytes_transferred_ = bytes_transferred;
this->success_ = success;
this->completion_key_ = completion_key;
this->error_ = error;
// Appropriately move the pointers in the message block.
for (ACE_Message_Block* mb = this->message_block_;
(mb != 0) && (bytes_transferred > 0);
mb = mb->cont ())
{
size_t len_part = mb->space ();
if ( len_part > bytes_transferred)
len_part = bytes_transferred;
mb->wr_ptr (len_part);
bytes_transferred -= len_part;
}
// Adjust the address length
this->remote_address_->set_size (this->addr_len_);
// Create the interface result class.
ACE_Asynch_Read_Dgram::Result result (this);
// Call the application handler.
ACE_Handler *handler = this->handler_proxy_.get ()->handler ();
if (handler != 0)
handler->handle_read_dgram (result);
}
ACE_WIN32_Asynch_Read_Dgram_Result::~ACE_WIN32_Asynch_Read_Dgram_Result (void)
{
delete this->remote_address_;
}
//***************************************************************************
ACE_WIN32_Asynch_Read_Dgram::~ACE_WIN32_Asynch_Read_Dgram (void)
{
}
ssize_t
ACE_WIN32_Asynch_Read_Dgram::recv (ACE_Message_Block *message_block,
size_t & number_of_bytes_recvd,
int flags,
int protocol_family,
const void *act,
int priority,
int signal_number)
{
number_of_bytes_recvd = 0;
size_t bytes_to_read = 0;
iovec iov[ACE_IOV_MAX];
int iovcnt = 0;
for (const ACE_Message_Block* msg = message_block;
msg != 0 && iovcnt < ACE_IOV_MAX;
msg = msg->cont () , ++iovcnt )
{
size_t msg_space = msg->space ();
// OS should correctly process zero length buffers
// if ( msg_space == 0 )
// ACE_ERROR_RETURN ((LM_ERROR,
// ACE_TEXT ("ACE_WIN32_Asynch_Read_Dgram::recv:")
// ACE_TEXT ("No space in the message block\n")),
// -1);
bytes_to_read += msg_space;
// Make as many iovec as needed to fit all of msg_len.
size_t wr_ptr_offset = 0;
while (msg_space > 0 && iovcnt < ACE_IOV_MAX)
{
u_long this_chunk_length;
if (msg_space > ULONG_MAX)
this_chunk_length = ULONG_MAX;
else
this_chunk_length = static_cast<u_long> (msg_space);
// Collect the data in the iovec.
iov[iovcnt].iov_base = msg->wr_ptr () + wr_ptr_offset;
iov[iovcnt].iov_len = this_chunk_length;
msg_space -= this_chunk_length;
wr_ptr_offset += this_chunk_length;
// Increment iovec counter if there's more to do.
if (msg_space > 0)
iovcnt++;
}
if (msg_space > 0) // Ran out of iovecs before msg_space exhausted
{
errno = ERANGE;
return -1;
}
}
if (bytes_to_read == 0)
ACE_ERROR_RETURN ((LM_ERROR,
ACE_TEXT ("ACE_WIN32_Asynch_Read_Dgram::recv:")
ACE_TEXT ("Attempt to read 0 bytes\n")),
-1);
// Create the Asynch_Result.
ACE_WIN32_Asynch_Read_Dgram_Result *result = 0;
ACE_NEW_RETURN (result,
ACE_WIN32_Asynch_Read_Dgram_Result (this->handler_proxy_,
this->handle_,
message_block,
bytes_to_read,
flags,
protocol_family,
act,
this->win32_proactor_->get_handle (),
priority,
signal_number),
-1);
// do the scatter/gather recv
ssize_t initiate_result = ACE_OS::recvfrom (result->handle (),
iov,
iovcnt,
number_of_bytes_recvd,
result->flags_,
result->saddr (),
&(result->addr_len_),
result,
0);
if (initiate_result == SOCKET_ERROR)
{
// If initiate failed, check for a bad error.
ACE_OS::set_errno_to_last_error ();
switch (errno)
{
case ERROR_IO_PENDING:
// The IO will complete proactively: the OVERLAPPED will still
// get queued.
initiate_result = 0;
break;
default:
// Something else went wrong: the OVERLAPPED will not get
// queued.
if (ACE::debug ())
{
ACE_DEBUG ((LM_ERROR,
ACE_TEXT ("%p\n"),
ACE_TEXT ("WSARecvFrom")));
}
delete result;
initiate_result = -1;
break;
}
}
else
{
// Immediate success: the OVERLAPPED will still get queued.
// number_of_bytes_recvd contains the number of bytes recvd
// addr contains the peer address
// flags was updated
// number_of_bytes_recvd = bytes_recvd;
initiate_result = 1;
}
return initiate_result;
}
int
ACE_WIN32_Asynch_Read_Dgram::open (const ACE_Handler::Proxy_Ptr &handler_proxy,
ACE_HANDLE handle,
const void *completion_key,
ACE_Proactor *proactor)
{
return ACE_WIN32_Asynch_Operation::open (handler_proxy,
handle,
completion_key,
proactor);
}
int
ACE_WIN32_Asynch_Read_Dgram::cancel (void)
{
return ACE_WIN32_Asynch_Operation::cancel ();
}
ACE_Proactor *
ACE_WIN32_Asynch_Read_Dgram::proactor (void) const
{
return ACE_WIN32_Asynch_Operation::proactor ();
}
ACE_WIN32_Asynch_Read_Dgram::ACE_WIN32_Asynch_Read_Dgram (ACE_WIN32_Proactor *win32_proactor)
: ACE_Asynch_Operation_Impl (),
ACE_Asynch_Read_Dgram_Impl (),
ACE_WIN32_Asynch_Operation (win32_proactor)
{
}
//***********************************************
size_t
ACE_WIN32_Asynch_Write_Dgram_Result::bytes_to_write (void) const
{
return this->bytes_to_write_;
}
ACE_Message_Block*
ACE_WIN32_Asynch_Write_Dgram_Result::message_block () const
{
return this->message_block_;
}
int
ACE_WIN32_Asynch_Write_Dgram_Result::flags (void) const
{
return this->flags_;
}
ACE_HANDLE
ACE_WIN32_Asynch_Write_Dgram_Result::handle (void) const
{
return this->handle_;
}
size_t
ACE_WIN32_Asynch_Write_Dgram_Result::bytes_transferred (void) const
{
return ACE_WIN32_Asynch_Result::bytes_transferred ();
}
const void *
ACE_WIN32_Asynch_Write_Dgram_Result::act (void) const
{
return ACE_WIN32_Asynch_Result::act ();
}
int
ACE_WIN32_Asynch_Write_Dgram_Result::success (void) const
{
return ACE_WIN32_Asynch_Result::success ();
}
const void *
ACE_WIN32_Asynch_Write_Dgram_Result::completion_key (void) const
{
return ACE_WIN32_Asynch_Result::completion_key ();
}
u_long
ACE_WIN32_Asynch_Write_Dgram_Result::error (void) const
{
return ACE_WIN32_Asynch_Result::error ();
}
ACE_HANDLE
ACE_WIN32_Asynch_Write_Dgram_Result::event (void) const
{
return ACE_WIN32_Asynch_Result::event ();
}
u_long
ACE_WIN32_Asynch_Write_Dgram_Result::offset (void) const
{
return ACE_WIN32_Asynch_Result::offset ();
}
u_long
ACE_WIN32_Asynch_Write_Dgram_Result::offset_high (void) const
{
return ACE_WIN32_Asynch_Result::offset_high ();
}
int
ACE_WIN32_Asynch_Write_Dgram_Result::priority (void) const
{
return ACE_WIN32_Asynch_Result::priority ();
}
int
ACE_WIN32_Asynch_Write_Dgram_Result::signal_number (void) const
{
return ACE_WIN32_Asynch_Result::signal_number ();
}
int
ACE_WIN32_Asynch_Write_Dgram_Result::post_completion (ACE_Proactor_Impl *proactor)
{
return ACE_WIN32_Asynch_Result::post_completion (proactor);
}
ACE_WIN32_Asynch_Write_Dgram_Result::ACE_WIN32_Asynch_Write_Dgram_Result (
const ACE_Handler::Proxy_Ptr &handler_proxy,
ACE_HANDLE handle,
ACE_Message_Block *message_block,
size_t bytes_to_write,
int flags,
const void* act,
ACE_HANDLE event,
int priority,
int signal_number)
: ACE_Asynch_Result_Impl (),
ACE_Asynch_Write_Dgram_Result_Impl(),
ACE_WIN32_Asynch_Result (handler_proxy,
act,
event,
0,
0,
priority,
signal_number),
bytes_to_write_ (bytes_to_write),
message_block_ (message_block),
flags_ (flags),
handle_ (handle)
{
}
void
ACE_WIN32_Asynch_Write_Dgram_Result::complete (size_t bytes_transferred,
int success,
const void *completion_key,
u_long error)
{
// Copy the data which was returned by GetQueuedCompletionStatus
this->bytes_transferred_ = bytes_transferred;
this->success_ = success;
this->completion_key_ = completion_key;
this->error_ = error;
// Appropriately move the pointers in the message block.
for (ACE_Message_Block* mb = this->message_block_;
(mb != 0) && (bytes_transferred > 0);
mb = mb->cont ())
{
size_t len_part = mb->length ();
if ( len_part > bytes_transferred)
len_part = bytes_transferred;
mb->rd_ptr (len_part);
bytes_transferred -= len_part;
}
// Create the interface result class.
ACE_Asynch_Write_Dgram::Result result (this);
// Call the application handler.
ACE_Handler *handler = this->handler_proxy_.get ()->handler ();
if (handler != 0)
handler->handle_write_dgram (result);
}
ACE_WIN32_Asynch_Write_Dgram_Result::~ACE_WIN32_Asynch_Write_Dgram_Result (void)
{
}
//***********************************************
ACE_WIN32_Asynch_Write_Dgram::~ACE_WIN32_Asynch_Write_Dgram (void)
{
}
ssize_t
ACE_WIN32_Asynch_Write_Dgram::send (ACE_Message_Block *message_block,
size_t &number_of_bytes_sent,
int flags,
const ACE_Addr &addr,
const void *act,
int priority,
int signal_number)
{
number_of_bytes_sent = 0;
size_t bytes_to_write = 0;
iovec iov[ACE_IOV_MAX];
int iovcnt = 0;
for (const ACE_Message_Block* msg = message_block;
msg != 0 && iovcnt < ACE_IOV_MAX;
msg = msg->cont () , ++iovcnt )
{
size_t msg_len = msg->length ();
bytes_to_write += msg_len;
// Make as many iovec as needed to fit all of msg_len.
size_t rd_ptr_offset = 0;
do
{
if (msg_len >= 0 && iovcnt < ACE_IOV_MAX)
{
u_long this_chunk_length;
if (msg_len > ULONG_MAX)
this_chunk_length = ULONG_MAX;
else
this_chunk_length = static_cast<u_long> (msg_len);
// Collect the data in the iovec.
iov[iovcnt].iov_base = msg->rd_ptr () + rd_ptr_offset;
iov[iovcnt].iov_len = this_chunk_length;
msg_len -= this_chunk_length;
rd_ptr_offset += this_chunk_length;
// Increment iovec counter if there's more to do.
if (msg_len > 0)
iovcnt++;
}
}
while (msg_len > 0 && iovcnt < ACE_IOV_MAX);
if (msg_len > 0) // Ran out of iovecs before msg_space exhausted
{
errno = ERANGE;
return -1;
}
}
// Create the Asynch_Result.
ACE_WIN32_Asynch_Write_Dgram_Result *result = 0;
ACE_NEW_RETURN (result,
ACE_WIN32_Asynch_Write_Dgram_Result (this->handler_proxy_,
this->handle_,
message_block,
bytes_to_write,
flags,
act,
this->win32_proactor_->get_handle (),
priority,
signal_number),
-1);
// do the scatter/gather send
ssize_t initiate_result = ACE_OS::sendto (result->handle (),
iov,
iovcnt,
number_of_bytes_sent,
result->flags_,
(sockaddr *) addr.get_addr (),
addr.get_size(),
result,
0);
if (initiate_result == SOCKET_ERROR)
{
// If initiate failed, check for a bad error.
ACE_OS::set_errno_to_last_error ();
switch (errno)
{
case ERROR_IO_PENDING:
// The IO will complete proactively: the OVERLAPPED will still
// get queued.
initiate_result = 0;
break;
default:
// Something else went wrong: the OVERLAPPED will not get
// queued.
if (ACE::debug ())
{
ACE_DEBUG ((LM_ERROR,
ACE_TEXT ("%p\n"),
ACE_TEXT ("WSASendTo")));
}
delete result;
initiate_result = -1;
break;
}
}
else
{
// Immediate success: the OVERLAPPED will still get queued.
// number_of_bytes_recvd contains the number of bytes recvd
// addr contains the peer address
// flags was updated
// number_of_bytes_sent = bytes_sent;
initiate_result = 1;
}
return initiate_result;
}
int
ACE_WIN32_Asynch_Write_Dgram::open (const ACE_Handler::Proxy_Ptr &handler_proxy,
ACE_HANDLE handle,
const void *completion_key,
ACE_Proactor *proactor)
{
return ACE_WIN32_Asynch_Operation::open (handler_proxy,
handle,
completion_key,
proactor);
}
int
ACE_WIN32_Asynch_Write_Dgram::cancel (void)
{
return ACE_WIN32_Asynch_Operation::cancel ();
}
ACE_Proactor *
ACE_WIN32_Asynch_Write_Dgram::proactor (void) const
{
return ACE_WIN32_Asynch_Operation::proactor ();
}
ACE_WIN32_Asynch_Write_Dgram::ACE_WIN32_Asynch_Write_Dgram (ACE_WIN32_Proactor *win32_proactor)
: ACE_Asynch_Operation_Impl (),
ACE_Asynch_Write_Dgram_Impl (),
ACE_WIN32_Asynch_Operation (win32_proactor)
{
}
ACE_END_VERSIONED_NAMESPACE_DECL
#endif /* ACE_HAS_WIN32_OVERLAPPED_IO && ACE_HAS_WINSOCK2 */