diff options
author | irfan <irfan@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 1999-12-07 03:35:51 +0000 |
---|---|---|
committer | irfan <irfan@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 1999-12-07 03:35:51 +0000 |
commit | 7a1899e8f3a05d76f840805a4a68efaf93cde4bd (patch) | |
tree | 822082ba0117438680286ce346b1d419758935a6 | |
parent | 31bc16e53f375e543cb94a665beedda7958ee170 (diff) | |
download | ATCD-7a1899e8f3a05d76f840805a4a68efaf93cde4bd.tar.gz |
ChangeLogTag: Mon Dec 06 21:16:53 1999 Irfan Pyarali <irfan@cs.wustl.edu>
-rw-r--r-- | ChangeLog-99b | 95 | ||||
-rw-r--r-- | TAO/ChangeLog-99c | 31 | ||||
-rw-r--r-- | TAO/examples/Buffered_Oneways/client.cpp | 3 | ||||
-rw-r--r-- | TAO/tao/IIOP_Connect.cpp | 8 | ||||
-rw-r--r-- | TAO/tao/IIOP_Transport.cpp | 89 | ||||
-rw-r--r-- | TAO/tao/IIOP_Transport.h | 8 | ||||
-rw-r--r-- | TAO/tao/Pluggable.cpp | 123 | ||||
-rw-r--r-- | TAO/tao/Pluggable.h | 20 | ||||
-rw-r--r-- | TAO/tao/Sync_Strategies.cpp | 127 | ||||
-rw-r--r-- | TAO/tao/Sync_Strategies.h | 14 | ||||
-rw-r--r-- | TAO/tao/UIOP_Connect.cpp | 8 | ||||
-rw-r--r-- | TAO/tao/UIOP_Transport.cpp | 89 | ||||
-rw-r--r-- | TAO/tao/UIOP_Transport.h | 8 | ||||
-rw-r--r-- | ace/ACE.cpp | 1940 | ||||
-rw-r--r-- | ace/ACE.h | 422 | ||||
-rw-r--r-- | ace/ACE.i | 58 | ||||
-rw-r--r-- | ace/Handle_Set.h | 6 | ||||
-rw-r--r-- | ace/Handle_Set.i | 37 | ||||
-rw-r--r-- | ace/OS.cpp | 92 | ||||
-rw-r--r-- | ace/OS.h | 53 | ||||
-rw-r--r-- | ace/SOCK_Dgram.cpp | 150 | ||||
-rw-r--r-- | ace/SOCK_Dgram.h | 13 | ||||
-rw-r--r-- | ace/SOCK_IO.cpp | 6 | ||||
-rw-r--r-- | ace/SOCK_IO.h | 113 | ||||
-rw-r--r-- | ace/SOCK_IO.i | 142 | ||||
-rw-r--r-- | ace/SOCK_Stream.h | 92 | ||||
-rw-r--r-- | ace/SOCK_Stream.i | 112 | ||||
-rw-r--r-- | ace/config-win32-common.h | 22 |
28 files changed, 2287 insertions, 1594 deletions
diff --git a/ChangeLog-99b b/ChangeLog-99b index 907fdf84d29..97868106212 100644 --- a/ChangeLog-99b +++ b/ChangeLog-99b @@ -1,3 +1,98 @@ +Mon Dec 06 21:16:53 1999 Irfan Pyarali <irfan@cs.wustl.edu> + + * ace/SOCK_Dgram.cpp (send): Added missing timed send. + + * ace/SOCK_IO.h (ACE_SOCK_IO): Most methods now support an + optional timeout parameter. + + * ace/SOCK_Stream.h (ACE_SOCK_Stream): All methods now support an + optional timeout parameter. Also fixed the <len> parameter type + in recv_urg and send_urg to be size_t instead of int. + + * ace/ACE: + + - All the I/O function were made consistent in ACE. This + included matching send and recv functions, all of which now + support timeouts. + + - Many of the timed functions, e.g., ACE::readv() and + ACE::sendto(), were changed such that the <timeout == 0> case + was made common between the code that expected OS provided timed + functions and the other where the timed function was simulated + by ACE. + + - Certain file I/O operation were made simple by removing the + extra <timeout> parameter. Timeouts are not supported in file + I/O. In some cases, e.g., the timed writev and readv functions, + the function was removed since it was not necessary as taking + the <timeout> parameter made it redundant with the function in + ACE_OS. + + - The "_n" methods were given a performance boost when they are + used with timeouts. We only set the handle into non-blocking + mode only once rather than for every iteration in the loop. + + - Added send/recv/send_n/recv/recv_n methods that take a message + block as the data container. + + - Here is the description of the updated functions from the + documentation: + ________________________________________ + + The <timeout> parameter in the following methods indicates how + long to blocking trying to transfer data. If <timeout> == 0, + then the call behaves as a normal send/recv call, i.e., for + blocking sockets, the call will block until action is possible; + for non-blocking sockets, EWOULDBLOCK will be returned if no + action is immediately possible. + + If <timeout> != 0, the call will wait until the relative time + specified in *<timeout> elapses. + + Errors are reported by -1 and 0 return values. If the operation + times out, -1 is returned with <errno == ETIME>. If it succeeds + the number of bytes transferred is returned. + + The "_n" I/O methods keep looping until all the data has been + transferred. These methods also work for sockets in + non-blocking mode i.e., they keep looping on EWOULDBLOCK. + <timeout> is used to make sure we keep making progress, i.e., + the same timeout value is used for every I/O operation in the + loop and the timeout is not counted down. If the transfer times + out, the number of bytes transferred so far are returned. + + Methods with <iovec> parameter are I/O vector variants of the + I/O operations. + ________________________________________ + + * ace/config-win32-common.h: Set IOV_MAX on Win32 to be 1024. It + seems like Win32 does not have a limit on the number of buffers + that can be transferred by the scatter/gather type of I/O + functions, e.g., WSASend and WSARecv. We are arbitrarily + setting this to be 1k for now. The typically use case is to + create an I/O vector array of size IOV_MAX on the stack and then + filled in. Note that we probably don't want too big a value for + IOV_MAX since it may mostly go to waste or the size of the + activation record may become excessively large. + + * ace/OS: + + The "faked" readv() in ACE for operating systems without it was + calling read_n(). This was changed to call read() since readv() + makes no guarantee that everything requested will be read. Same + changes applied for writev(). + + send_n() does not belong in the OS class. It belongs in the ACE + class. Therefore, it was moved. + + read_n() is only called for file handles (and not for socket + handles). Therefore, there is no point in checking for + EWOULDBLOCK. Same change was made to write_n(). + + * ace/Handle_Set.h (ACE_Handle_Set): Added an explicit fdset() + function to get to the fd_set *. This eliminates the need for + the stupid cast operator. + Mon Dec 6 21:13:08 1999 Douglas C. Schmidt <schmidt@tango.cs.wustl.edu> * ace/Configuration.cpp (set_string_value): When setting a value diff --git a/TAO/ChangeLog-99c b/TAO/ChangeLog-99c index 2278968861d..f8db68e8ba0 100644 --- a/TAO/ChangeLog-99c +++ b/TAO/ChangeLog-99c @@ -1,6 +1,33 @@ +Mon Dec 06 21:16:53 1999 Irfan Pyarali <irfan@cs.wustl.edu> + + * tao/IIOP_Transport.cpp (send/recv): + * tao/UIOP_Transport.cpp (send/recv): + + - Changed to use the new timed I/O APIs in ACE. + + - The <timeout> parameter was made const. + + - Changed how the destructor handles buffered oneways. + + * tao/UIOP_Connect.cpp (handle_timeout): + * tao/IIOP_Connect.cpp (handle_timeout): + + Changed how timeouts handle buffered oneways. + + * tao/Pluggable.cpp (send_buffered_messages): Some of the methods + were moved from the sync strategies to the transport class. + This makes them easier to use without the presence of the stub, + e.g., during the destruction of the transport and when timeouts + occur. + + * examples/Buffered_Oneways/client.cpp (main): Initialized all the + fields of the <buffering_constraint> structure. This will + prevent UMRs from purify. Thanks to Jeff for pointing out the + source of the UMRs. + Mon Dec 6 13:16:21 1999 Balachandran Natarajan <bala@cs.wustl.edu> - * tao/GIOP1_2.pidl (GIOP ): + * tao/GIOP1_2.pidl (GIOP ): * tao/GIOPC.h: * tao/GIOPC.cpp: * tao/GIOPC.i: Some new data types that have been added to GIOP @@ -8,7 +35,7 @@ Mon Dec 6 13:16:21 1999 Balachandran Natarajan <bala@cs.wustl.edu> problem for the CORBA namespace. * tao/Makefile: Added GIOPC.cpp to the list of files and also - updated the dependencies. + updated the dependencies. Sun Dec 5 14:43:42 1999 Carlos O'Ryan <coryan@cs.wustl.edu> diff --git a/TAO/examples/Buffered_Oneways/client.cpp b/TAO/examples/Buffered_Oneways/client.cpp index 2652e1cc529..4732037d4e0 100644 --- a/TAO/examples/Buffered_Oneways/client.cpp +++ b/TAO/examples/Buffered_Oneways/client.cpp @@ -163,6 +163,9 @@ main (int argc, char **argv) // Start off with no constraints. TAO::BufferingConstraint buffering_constraint; + buffering_constraint.message_count = 0; + buffering_constraint.message_bytes = 0; + buffering_constraint.timeout = 0; buffering_constraint.mode = TAO::BUFFER_NONE; // If valid <message_count>, set the implicit flushing to diff --git a/TAO/tao/IIOP_Connect.cpp b/TAO/tao/IIOP_Connect.cpp index dfae9b98595..bb3f62fe0ae 100644 --- a/TAO/tao/IIOP_Connect.cpp +++ b/TAO/tao/IIOP_Connect.cpp @@ -430,8 +430,12 @@ int TAO_IIOP_Client_Connection_Handler::handle_timeout (const ACE_Time_Value &, const void *) { - // Called when buffering timer expires. - this->transport ()->flush_buffered_messages (); + // + // This method is called when buffering timer expires. + // + + // Cannot deal with errors, and therefore they are ignored. + this->transport ()->send_buffered_messages (); return 0; } diff --git a/TAO/tao/IIOP_Transport.cpp b/TAO/tao/IIOP_Transport.cpp index 9471db6b05d..6727a930585 100644 --- a/TAO/tao/IIOP_Transport.cpp +++ b/TAO/tao/IIOP_Transport.cpp @@ -56,7 +56,12 @@ TAO_IIOP_Transport::TAO_IIOP_Transport (TAO_IIOP_Handler_Base *handler, TAO_IIOP_Transport::~TAO_IIOP_Transport (void) { - this->flush_buffered_messages (); + // Cannot deal with errors, and therefore they are ignored. + this->send_buffered_messages (); + + // Note that it also doesn't matter how much of the data was + // actually sent. + this->dequeue_all (); } TAO_IIOP_Handler_Base *& @@ -307,7 +312,7 @@ TAO_IIOP_Client_Transport::register_handler (void) ssize_t TAO_IIOP_Transport::send (TAO_Stub *stub, const ACE_Message_Block *message_block, - ACE_Time_Value *max_wait_time) + const ACE_Time_Value *max_wait_time) { if (stub == 0) { @@ -327,93 +332,37 @@ TAO_IIOP_Transport::send (TAO_Stub *stub, ssize_t TAO_IIOP_Transport::send (const ACE_Message_Block *message_block, - ACE_Time_Value *max_wait_time) + const ACE_Time_Value *max_wait_time) { TAO_FUNCTION_PP_TIMEPROBE (TAO_IIOP_TRANSPORT_SEND_START); - // @@ This code should be refactored into ACE.cpp or something - // similar! - - // For the most part this was copied from GIOP::send_request and - // friends. - - iovec iov[IOV_MAX]; - int iovcnt = 0; - ssize_t n = 0; - ssize_t nbytes = 0; - - for (const ACE_Message_Block *i = message_block; - i != 0; - i = i->cont ()) - { - // Make sure there is something to send! - if (i->length () > 0) - { - iov[iovcnt].iov_base = i->rd_ptr (); - iov[iovcnt].iov_len = i->length (); - iovcnt++; - - // The buffer is full make a OS call. @@ TODO this should - // be optimized on a per-platform basis, for instance, some - // platforms do not implement writev() there we should copy - // the data into a buffer and call send_n(). In other cases - // there may be some limits on the size of the iovec, there - // we should set IOV_MAX to that limit. - if (iovcnt == IOV_MAX) - { - if (max_wait_time == 0) - n = this->handler_->peer ().sendv_n (iov, - iovcnt); - else - n = ACE::writev (this->handler_->peer ().get_handle (), - iov, - iovcnt, - max_wait_time); - - if (n <= 0) - return n; - - nbytes += n; - iovcnt = 0; - } - } - } - - // Check for remaining buffers to be sent! - if (iovcnt != 0) - { - n = this->handler_->peer ().sendv_n (iov, - iovcnt); - if (n < 1) - return n; - - nbytes += n; - } - - return nbytes; + return ACE::send_n (this->handle (), + message_block, + max_wait_time); } ssize_t TAO_IIOP_Transport::send (const u_char *buf, size_t len, - ACE_Time_Value *) + const ACE_Time_Value *max_wait_time) { TAO_FUNCTION_PP_TIMEPROBE (TAO_IIOP_TRANSPORT_SEND_START); - return this->handler_->peer ().send_n (buf, len); + return this->handler_->peer ().send_n (buf, + len, + max_wait_time); } ssize_t TAO_IIOP_Transport::recv (char *buf, size_t len, - ACE_Time_Value *max_wait_time) + const ACE_Time_Value *max_wait_time) { TAO_FUNCTION_PP_TIMEPROBE (TAO_IIOP_TRANSPORT_RECEIVE_START); - return ACE::recv_n (this->handler_->peer ().get_handle (), - buf, - len, - max_wait_time); + return this->handler_->peer ().recv_n (buf, + len, + max_wait_time); } // Default action to be taken for send request. diff --git a/TAO/tao/IIOP_Transport.h b/TAO/tao/IIOP_Transport.h index a82205a4717..90335ab8130 100644 --- a/TAO/tao/IIOP_Transport.h +++ b/TAO/tao/IIOP_Transport.h @@ -63,15 +63,15 @@ public: virtual ACE_Event_Handler *event_handler (void); virtual ssize_t send (TAO_Stub *stub, const ACE_Message_Block *mblk, - ACE_Time_Value *s = 0); + const ACE_Time_Value *s = 0); virtual ssize_t send (const ACE_Message_Block *mblk, - ACE_Time_Value *s = 0); + const ACE_Time_Value *s = 0); virtual ssize_t send (const u_char *buf, size_t len, - ACE_Time_Value *s = 0); + const ACE_Time_Value *s = 0); virtual ssize_t recv (char *buf, size_t len, - ACE_Time_Value *s = 0); + const ACE_Time_Value *s = 0); virtual int send_request (TAO_Stub *stub, TAO_ORB_Core *orb_core , TAO_OutputCDR &stream, diff --git a/TAO/tao/Pluggable.cpp b/TAO/tao/Pluggable.cpp index 612072bb6b7..aa875436e92 100644 --- a/TAO/tao/Pluggable.cpp +++ b/TAO/tao/Pluggable.cpp @@ -51,25 +51,126 @@ TAO_Transport::~TAO_Transport (void) delete this->buffering_queue_; } +ssize_t +TAO_Transport::send_buffered_messages (const ACE_Time_Value *max_wait_time) +{ + // Make sure we have a buffering queue and there are messages in it. + if (this->buffering_queue_ == 0 || + this->buffering_queue_->is_empty ()) + return 0; + + // Get the first message from the queue. + ACE_Message_Block *queued_message = 0; + ssize_t result = this->buffering_queue_->peek_dequeue_head (queued_message); + + // @@ What to do here on failures? + ACE_ASSERT (result != -1); + + // Actual network send. + result = this->send (queued_message, + max_wait_time); + + // Socket closed. + if (result == 0) + { + this->dequeue_all (); + return -1; + } + + // Cannot send. + if (result == -1) + { + // Timeout. + if (errno == ETIME) + { + // Since we queue up the message, this is not an error. We + // can try next time around. + return 0; + } + // Non-timeout error. + else + { + this->dequeue_all (); + return -1; + } + } + + // If successful in sending some or all of the data, reset the queue + // appropriately. + this->reset_queued_message (queued_message, + result); + + // Indicate success. + return result; +} + void -TAO_Transport::flush_buffered_messages (void) +TAO_Transport::dequeue_head (void) { - // If we have a buffering queue. + // Remove from the head of the queue. + ACE_Message_Block *message_block = 0; + int result = this->buffering_queue_->dequeue_head (message_block); + + // @@ What to do here on failures? + ACE_ASSERT (result != -1); + ACE_UNUSED_ARG (result); + + // Release the memory. + message_block->release (); +} + +void +TAO_Transport::dequeue_all (void) +{ + // Flush all queued messages. if (this->buffering_queue_) { - // Flush all queued messages. while (!this->buffering_queue_->is_empty ()) + this->dequeue_head (); + } +} + +void +TAO_Transport::reset_queued_message (ACE_Message_Block *message_block, + size_t bytes_delivered) +{ + while (message_block != 0 && + bytes_delivered != 0) + { + // Partial send. + if (message_block->length () > bytes_delivered) { - // Get the first message from the queue. - ACE_Message_Block *queued_message = 0; - this->buffering_queue_->dequeue_head (queued_message); + // Reset so that we skip this in the next send. + message_block->rd_ptr (bytes_delivered); - // Actual network send. Cannot deal with errors, and - // therefore they are ignored. - this->send (queued_message); + // Hand adjust <message_length>. + this->buffering_queue_->message_length (this->buffering_queue_->message_length () - bytes_delivered); + + break; + } + + // <message_block> was completely sent. + bytes_delivered -= message_block->length (); + + // Check continuation chain. + if (message_block->cont ()) + { + // Reset so that we skip this message block in the next send. + message_block->rd_ptr (message_block->length ()); + + // Hand adjust <message_length>. + this->buffering_queue_->message_length (this->buffering_queue_->message_length () - bytes_delivered); + + // Next selection. + message_block = message_block->cont (); + } + else + { + // Go to the next one. + message_block = message_block->next (); - // Release the memory. - queued_message->release (); + // Release this <message_block>. + this->dequeue_head (); } } } diff --git a/TAO/tao/Pluggable.h b/TAO/tao/Pluggable.h index 2b8b386f670..2f3b601ecaa 100644 --- a/TAO/tao/Pluggable.h +++ b/TAO/tao/Pluggable.h @@ -84,9 +84,9 @@ public: virtual ssize_t send (TAO_Stub *stub, const ACE_Message_Block *mblk, - ACE_Time_Value *s = 0) = 0; + const ACE_Time_Value *s = 0) = 0; virtual ssize_t send (const ACE_Message_Block *mblk, - ACE_Time_Value *s = 0) = 0; + const ACE_Time_Value *s = 0) = 0; // Write the complete Message_Block chain to the connection. // @@ The ACE_Time_Value *s is just a place holder for now. It is // not clear this this is the best place to specify this. The actual @@ -94,12 +94,12 @@ public: virtual ssize_t send (const u_char *buf, size_t len, - ACE_Time_Value *s = 0) = 0; + const ACE_Time_Value *s = 0) = 0; // Write the contents of the buffer of length len to the connection. virtual ssize_t recv (char *buf, size_t len, - ACE_Time_Value *s = 0) = 0; + const ACE_Time_Value *s = 0) = 0; // Read len bytes from into buf. // @@ The ACE_Time_Value *s is just a place holder for now. It is // not clear this this is the best place to specify this. The actual @@ -178,10 +178,18 @@ public: void buffering_timeout_value (const ACE_Time_Value &time); // Timeout value associated with buffering. - void flush_buffered_messages (void); - // Flush any messages that have been buffered. + ssize_t send_buffered_messages (const ACE_Time_Value *max_wait_time = 0); + // Send any messages that have been buffered. protected: + + void dequeue_head (void); + + void dequeue_all (void); + + void reset_queued_message (ACE_Message_Block *message_block, + size_t bytes_delivered); + CORBA::ULong tag_; // IOP protocol tag. diff --git a/TAO/tao/Sync_Strategies.cpp b/TAO/tao/Sync_Strategies.cpp index b1688e4abd3..5456dc10cef 100644 --- a/TAO/tao/Sync_Strategies.cpp +++ b/TAO/tao/Sync_Strategies.cpp @@ -19,7 +19,7 @@ ssize_t TAO_Transport_Sync_Strategy::send (TAO_Transport &transport, TAO_Stub &, const ACE_Message_Block *message_block, - ACE_Time_Value *max_wait_time) + const ACE_Time_Value *max_wait_time) { // Immediate delegation to the transport. return transport.send (message_block, @@ -32,7 +32,7 @@ ssize_t TAO_None_Sync_Strategy::send (TAO_Transport &transport, TAO_Stub &stub, const ACE_Message_Block *message_block, - ACE_Time_Value *max_wait_time) + const ACE_Time_Value *max_wait_time) { ssize_t result = 0; @@ -61,131 +61,14 @@ TAO_None_Sync_Strategy::send (TAO_Transport &transport, stub, buffering_queue)) { - // Copy the timeout value since we don't want to change it. The - // caller will change appropriately. - ACE_Time_Value timeout_value; - ACE_Time_Value *timeout = 0; - if (max_wait_time) - { - timeout_value = *max_wait_time; - timeout = &timeout_value; - } - - ACE_Countdown_Time countdown (timeout); - - // Flush all queued messages. - while (!buffering_queue.is_empty ()) - { - // Get the first message from the queue. - ACE_Message_Block *queued_message = 0; - result = buffering_queue.peek_dequeue_head (queued_message); - - // @@ What to do here on failures? - ACE_ASSERT (result != -1); - - // Actual network send. - result = transport.send (queued_message, - timeout); - - // Socket closed. - if (result == 0) - { - this->dequeue_all (buffering_queue); - return -1; - } - - // Cannot send. - if (result == -1) - { - // Timeout. - if (errno == ETIME) - { - // Since we queue up the message, this is not an - // error. We can try next time around. - return 0; - } - // Non-timeout error. - else - { - this->dequeue_all (buffering_queue); - return -1; - } - } - - ssize_t total_length = queued_message->total_length (); - - // If successful in sending the complete queued message. - if (result == total_length) - { - this->dequeue_head (buffering_queue); - countdown.update (); - } - - // Partial send (re-adjust pointers without dequeuing the - // message). This is not an error. We can try next time - // around. - else - { - this->reset_queued_message (buffering_queue, - queued_message, - result); - return 0; - } - } + return transport.send_buffered_messages (max_wait_time); } - // I am hoping this return value is meaningful. + // Hoping that this return value is meaningful or at least + // acceptable. return message_block->total_length (); } -void -TAO_None_Sync_Strategy::dequeue_head (TAO_Transport_Buffering_Queue &buffering_queue) -{ - ACE_Message_Block *message_block = 0; - - // Remove from the head of the queue. - int result = buffering_queue.dequeue_head (message_block); - - // @@ What to do here on failures? - ACE_ASSERT (result != -1); - ACE_UNUSED_ARG (result); - - // Release the memory. - message_block->release (); -} - -void -TAO_None_Sync_Strategy::dequeue_all (TAO_Transport_Buffering_Queue &buffering_queue) -{ - // Flush all queued messages. - while (!buffering_queue.is_empty ()) - this->dequeue_head (buffering_queue); -} - -void -TAO_None_Sync_Strategy::reset_queued_message (TAO_Transport_Buffering_Queue &buffering_queue, - ACE_Message_Block *message_block, - size_t bytes_delivered) -{ - for (ACE_Message_Block *i = message_block; - i != 0 && bytes_delivered != 0; - i = i->cont ()) - { - if (i->length () > bytes_delivered) - { - i->rd_ptr (bytes_delivered); - bytes_delivered = 0; - } - else - { - bytes_delivered -= i->length (); - i->rd_ptr (i->length ()); - } - } - - buffering_queue.message_length (buffering_queue.message_length () - bytes_delivered); -} - int TAO_None_Sync_Strategy::buffering_constraints_reached (TAO_Transport &transport, TAO_Stub &stub, diff --git a/TAO/tao/Sync_Strategies.h b/TAO/tao/Sync_Strategies.h index 35107737c73..b4cb70e0e4b 100644 --- a/TAO/tao/Sync_Strategies.h +++ b/TAO/tao/Sync_Strategies.h @@ -37,7 +37,7 @@ public: virtual ssize_t send (TAO_Transport &transport, TAO_Stub &stub, const ACE_Message_Block *message_block, - ACE_Time_Value *max_wait_time) = 0; + const ACE_Time_Value *max_wait_time) = 0; }; class TAO_Export TAO_Transport_Sync_Strategy : public TAO_Sync_Strategy @@ -46,7 +46,7 @@ public: ssize_t send (TAO_Transport &transport, TAO_Stub &stub, const ACE_Message_Block *message_block, - ACE_Time_Value *max_wait_time); + const ACE_Time_Value *max_wait_time); }; #if defined (TAO_HAS_CORBA_MESSAGING) @@ -57,7 +57,7 @@ public: ssize_t send (TAO_Transport &transport, TAO_Stub &stub, const ACE_Message_Block *message_block, - ACE_Time_Value *max_wait_time); + const ACE_Time_Value *max_wait_time); virtual int buffering_constraints_reached (TAO_Transport &transport, TAO_Stub &stub, @@ -67,14 +67,6 @@ public: const TAO::BufferingConstraint &buffering_constraint); ACE_Time_Value time_conversion (const TimeBase::TimeT &time); - - void dequeue_head (TAO_Transport_Buffering_Queue &buffering_queue); - - void dequeue_all (TAO_Transport_Buffering_Queue &buffering_queue); - - void reset_queued_message (TAO_Transport_Buffering_Queue &buffering_queue, - ACE_Message_Block *message_block, - size_t bytes_delivered); }; class TAO_Export TAO_Flush_Sync_Strategy : public TAO_None_Sync_Strategy diff --git a/TAO/tao/UIOP_Connect.cpp b/TAO/tao/UIOP_Connect.cpp index 73a4ff1e417..66bed11894a 100644 --- a/TAO/tao/UIOP_Connect.cpp +++ b/TAO/tao/UIOP_Connect.cpp @@ -397,8 +397,12 @@ int TAO_UIOP_Client_Connection_Handler::handle_timeout (const ACE_Time_Value &, const void *) { - // Called when buffering timer expires. - this->transport ()->flush_buffered_messages (); + // + // This method is called when buffering timer expires. + // + + // Cannot deal with errors, and therefore they are ignored. + this->transport ()->send_buffered_messages (); return 0; } diff --git a/TAO/tao/UIOP_Transport.cpp b/TAO/tao/UIOP_Transport.cpp index 64068097a3d..00404ef7df2 100644 --- a/TAO/tao/UIOP_Transport.cpp +++ b/TAO/tao/UIOP_Transport.cpp @@ -59,7 +59,12 @@ TAO_UIOP_Transport::TAO_UIOP_Transport (TAO_UIOP_Handler_Base *handler, TAO_UIOP_Transport::~TAO_UIOP_Transport (void) { - this->flush_buffered_messages (); + // Cannot deal with errors, and therefore they are ignored. + this->send_buffered_messages (); + + // Note that it also doesn't matter how much of the data was + // actually sent. + this->dequeue_all (); } TAO_UIOP_Handler_Base *& @@ -311,7 +316,7 @@ TAO_UIOP_Client_Transport::register_handler (void) ssize_t TAO_UIOP_Transport::send (TAO_Stub *stub, const ACE_Message_Block *message_block, - ACE_Time_Value *max_wait_time) + const ACE_Time_Value *max_wait_time) { if (stub == 0) { @@ -331,93 +336,37 @@ TAO_UIOP_Transport::send (TAO_Stub *stub, ssize_t TAO_UIOP_Transport::send (const ACE_Message_Block *mblk, - ACE_Time_Value *max_time_wait) + const ACE_Time_Value *max_time_wait) { TAO_FUNCTION_PP_TIMEPROBE (TAO_UIOP_TRANSPORT_SEND_START); - // @@ This code should be refactored into ACE.cpp or something - // similar! - - // For the most part this was copied from GIOP::send_request and - // friends. - - iovec iov[IOV_MAX]; - int iovcnt = 0; - ssize_t n = 0; - ssize_t nbytes = 0; - - for (const ACE_Message_Block *i = mblk; - i != 0; - i = i->cont ()) - { - // Make sure there is something to send! - if (i->length () > 0) - { - iov[iovcnt].iov_base = i->rd_ptr (); - iov[iovcnt].iov_len = i->length (); - iovcnt++; - - // The buffer is full make a OS call. @@ TODO this should - // be optimized on a per-platform basis, for instance, some - // platforms do not implement writev() there we should copy - // the data into a buffer and call send_n(). In other cases - // there may be some limits on the size of the iovec, there - // we should set IOV_MAX to that limit. - if (iovcnt == IOV_MAX) - { - if (max_time_wait == 0) - n = this->handler_->peer ().sendv_n (iov, - iovcnt); - else - n = ACE::writev (this->handler_->peer ().get_handle (), - iov, - iovcnt, - max_time_wait); - - if (n <= 0) - return n; - - nbytes += n; - iovcnt = 0; - } - } - } - - // Check for remaining buffers to be sent! - if (iovcnt != 0) - { - n = this->handler_->peer ().sendv_n (iov, - iovcnt); - if (n < 1) - return n; - - nbytes += n; - } - - return nbytes; + return ACE::send_n (this->handle (), + message_block, + max_wait_time); } ssize_t TAO_UIOP_Transport::send (const u_char *buf, size_t len, - ACE_Time_Value *) + const ACE_Time_Value *max_wait_time) { TAO_FUNCTION_PP_TIMEPROBE (TAO_UIOP_TRANSPORT_SEND_START); - return this->handler_->peer ().send_n (buf, len); + return this->handler_->peer ().send_n (buf, + len, + max_wait_time); } ssize_t TAO_UIOP_Transport::recv (char *buf, size_t len, - ACE_Time_Value *max_wait_time) + const ACE_Time_Value *max_wait_time) { TAO_FUNCTION_PP_TIMEPROBE (TAO_UIOP_TRANSPORT_RECEIVE_START); - return ACE::recv_n (this->handler_->peer ().get_handle (), - buf, - len, - max_wait_time); + return this->handler_->peer ().recv_n (buf, + len, + max_wait_time); } // Default action to be taken for send request. diff --git a/TAO/tao/UIOP_Transport.h b/TAO/tao/UIOP_Transport.h index d73779f74e3..481e6232e6a 100644 --- a/TAO/tao/UIOP_Transport.h +++ b/TAO/tao/UIOP_Transport.h @@ -66,15 +66,15 @@ public: virtual ACE_Event_Handler *event_handler (void); virtual ssize_t send (TAO_Stub *stub, const ACE_Message_Block *mblk, - ACE_Time_Value *s = 0); + const ACE_Time_Value *s = 0); virtual ssize_t send (const ACE_Message_Block *mblk, - ACE_Time_Value *s = 0); + const ACE_Time_Value *s = 0); virtual ssize_t send (const u_char *buf, size_t len, - ACE_Time_Value *s = 0); + const ACE_Time_Value *s = 0); virtual ssize_t recv (char *buf, size_t len, - ACE_Time_Value *s = 0); + const ACE_Time_Value *s = 0); virtual int send_request (TAO_Stub *stub, TAO_ORB_Core *orb_core , TAO_OutputCDR &stream, diff --git a/ace/ACE.cpp b/ace/ACE.cpp index 9c2b9a46dbb..d4dabdb72b0 100644 --- a/ace/ACE.cpp +++ b/ace/ACE.cpp @@ -8,6 +8,7 @@ #include "ace/Object_Manager.h" #include "ace/SString.h" #include "ace/Version.h" +#include "ace/Message_Block.h" #if defined (ACE_LACKS_INLINE_FUNCTIONS) #include "ace/ACE.i" @@ -1066,41 +1067,339 @@ ACE::basename (const wchar_t *pathname, wchar_t delim) } #endif /* ACE_HAS_UNICODE */ -// Send N char *ptrs and int lengths. Note that the char *'s precede -// the ints (basically, an varargs version of writev). The count N is -// the *total* number of trailing arguments, *not* a couple of the -// number of tuple pairs! +ssize_t +ACE::recv (ACE_HANDLE handle, + void *buf, + size_t len, + int flags, + const ACE_Time_Value *timeout) +{ + if (timeout == 0) + return ACE_OS::recv (handle, (char *) buf, len, flags); + else + { +#if defined (ACE_HAS_RECV_TIMEDWAIT) + ACE_Time_Value copy = *timeout; + copy += ACE_OS::gettimeofday (); + timespec_t ts = copy; + return ::recv_timedwait (handle, buf, len, flags, &ts); +#else + int val = 0; + if (ACE::enter_recv_timedwait (handle, timeout, val) ==-1) + return -1; + else + { + ssize_t bytes_transferred = ACE_OS::recv (handle, (char *) buf, len, flags); + ACE::restore_non_blocking_mode (handle, val); + return bytes_transferred; + } +#endif /* ACE_HAS_RECV_TIMEDWAIT */ + } +} ssize_t -ACE::send (ACE_HANDLE handle, size_t n, ...) +ACE::recv (ACE_HANDLE handle, + void *buf, + size_t n, + const ACE_Time_Value *timeout) { - ACE_TRACE ("ACE_SOCK_IO::send"); + if (timeout == 0) + return ACE::recv_i (handle, buf, n); + else + { +#if defined (ACE_HAS_READ_TIMEDWAIT) + ACE_Time_Value copy = *timeout; + copy += ACE_OS::gettimeofday (); + timespec_t ts = copy; + return ::read_timedwait (handle, buf, n, &ts); +#else + int val = 0; + if (ACE::enter_recv_timedwait (handle, timeout, val) == -1) + return -1; + else + { + ssize_t bytes_transferred = ACE::recv_i (handle, buf, n); + ACE::restore_non_blocking_mode (handle, val); + return bytes_transferred; + } +#endif /* ACE_HAS_READ_TIMEDWAIT */ + } +} - va_list argp; - size_t total_tuples = n / 2; - iovec *iovp; -#if defined (ACE_HAS_ALLOCA) - iovp = (iovec *) alloca (total_tuples * sizeof (iovec)); +ssize_t +ACE::recvmsg (ACE_HANDLE handle, + struct msghdr *msg, + int flags, + const ACE_Time_Value *timeout) +{ + if (timeout == 0) + return ACE_OS::recvmsg (handle, msg, flags); + else + { +#if defined (ACE_HAS_RECVMSG_TIMEDWAIT) + ACE_Time_Value copy = *timeout; + copy += ACE_OS::gettimeofday (); + timespec_t ts = copy; + return ::recvmsg_timedwait (handle, msg, flags, &ts); #else - ACE_NEW_RETURN (iovp, - iovec[total_tuples], - -1); -#endif /* !defined (ACE_HAS_ALLOCA) */ + int val = 0; + if (ACE::enter_recv_timedwait (handle, timeout, val) == -1) + return -1; + else + { + int bytes_transferred = ACE_OS::recvmsg (handle, msg, flags); + ACE::restore_non_blocking_mode (handle, val); + return bytes_transferred; + } +#endif /* ACE_HAS_RECVMSG_TIMEDWAIT */ + } +} - va_start (argp, n); +ssize_t +ACE::recvfrom (ACE_HANDLE handle, + char *buf, + int len, + int flags, + struct sockaddr *addr, + int *addrlen, + const ACE_Time_Value *timeout) +{ + if (timeout == 0) + return ACE_OS::recvfrom (handle, buf, len, flags, addr, addrlen); + else + { +#if defined (ACE_HAS_RECVFROM_TIMEDWAIT) + ACE_Time_Value copy = *timeout; + copy += ACE_OS::gettimeofday (); + timespec_t ts = copy; + return ::recvfrom_timedwait (handle, buf, len, flags, addr, addrlen, &ts); +#else + int val = 0; + if (ACE::enter_recv_timedwait (handle, timeout, val) == -1) + return -1; + else + { + int bytes_transferred = ACE_OS::recvfrom (handle, buf, len, flags, addr, addrlen); + ACE::restore_non_blocking_mode (handle, val); + return bytes_transferred; + } +#endif /* ACE_HAS_RECVFROM_TIMEDWAIT */ + } +} - for (size_t i = 0; i < total_tuples; i++) +ssize_t +ACE::recv_n (ACE_HANDLE handle, + void *buf, + size_t len, + int flags, + const ACE_Time_Value *timeout) +{ + if (timeout == 0) + return ACE::recv_n_i (handle, + buf, + len, + flags); + else + return ACE::recv_n_i (handle, + buf, + len, + flags, + timeout); +} + +ssize_t +ACE::recv_n_i (ACE_HANDLE handle, + void *buf, + size_t len, + int flags) +{ + size_t bytes_transferred; + ssize_t n; + + for (bytes_transferred = 0; + bytes_transferred < len; + bytes_transferred += n) { - iovp[i].iov_base = va_arg (argp, char *); - iovp[i].iov_len = va_arg (argp, ssize_t); + n = ACE_OS::recv (handle, + (char *) buf + bytes_transferred, + len - bytes_transferred, + flags); + if (n == -1) + { + // If blocked, try again. + if (errno == EWOULDBLOCK) + n = 0; + + // + // No timeouts in this version. + // + + // Other errors. + return -1; + } + else if (n == 0) + return 0; } - ssize_t result = ACE_OS::sendv (handle, iovp, total_tuples); -#if !defined (ACE_HAS_ALLOCA) - delete [] iovp; -#endif /* !defined (ACE_HAS_ALLOCA) */ - va_end (argp); - return result; + return bytes_transferred; +} + +ssize_t +ACE::recv_n_i (ACE_HANDLE handle, + void *buf, + size_t len, + int flags, + const ACE_Time_Value *timeout) +{ + int val = 0; + ACE::record_and_set_non_blocking_mode (handle, val); + + size_t bytes_transferred; + ssize_t n; + int error = 0; + + for (bytes_transferred = 0; + bytes_transferred < len; + bytes_transferred += n) + { + int result = ACE::handle_read_ready (handle, + timeout); + + if (result == -1) + { + // Timed out; return bytes transferred. + if (errno == ETIME) + break; + + // Other errors. + error = 1; + break; + } + + n = ACE_OS::recv (handle, + (char *) buf + bytes_transferred, + len - bytes_transferred, + flags); + + // Errors (note that errno cannot be EWOULDBLOCK since select() + // just told us that data is available to read). + if (n == -1 || n == 0) + { + error = 1; + break; + } + } + + ACE::restore_non_blocking_mode (handle, val); + + if (error) + return -1; + else + return bytes_transferred; +} + +ssize_t +ACE::recv_n (ACE_HANDLE handle, + void *buf, + size_t len, + const ACE_Time_Value *timeout) +{ + if (timeout == 0) + return ACE::recv_n_i (handle, + buf, + len); + else + return ACE::recv_n_i (handle, + buf, + len, + timeout); +} + +ssize_t +ACE::recv_n_i (ACE_HANDLE handle, + void *buf, + size_t len) +{ + size_t bytes_transferred; + ssize_t n; + + for (bytes_transferred = 0; + bytes_transferred < len; + bytes_transferred += n) + { + n = ACE::recv_i (handle, + (char *) buf + bytes_transferred, + len - bytes_transferred); + if (n == -1) + { + // If blocked, try again. + if (errno == EWOULDBLOCK) + n = 0; + + // + // No timeouts in this version. + // + + // Other errors. + return -1; + } + else if (n == 0) + return 0; + } + + return bytes_transferred; +} + +ssize_t +ACE::recv_n_i (ACE_HANDLE handle, + void *buf, + size_t len, + const ACE_Time_Value *timeout) +{ + int val = 0; + ACE::record_and_set_non_blocking_mode (handle, val); + + size_t bytes_transferred; + ssize_t n; + int error = 0; + + for (bytes_transferred = 0; + bytes_transferred < len; + bytes_transferred += n) + { + int result = ACE::handle_read_ready (handle, + timeout); + + if (result == -1) + { + // Timed out; return bytes transferred. + if (errno == ETIME) + break; + + // Other errors. + error = 1; + break; + } + + n = ACE::recv_i (handle, + (char *) buf + bytes_transferred, + len - bytes_transferred); + + // Errors (note that errno cannot be EWOULDBLOCK since select() + // just told us that data is available to read). + if (n == -1 || n == 0) + { + error = 1; + break; + } + } + + ACE::restore_non_blocking_mode (handle, val); + + if (error) + return -1; + else + return bytes_transferred; } // This is basically an interface to ACE_OS::readv, that doesn't use @@ -1112,8 +1411,6 @@ ACE::send (ACE_HANDLE handle, size_t n, ...) ssize_t ACE::recv (ACE_HANDLE handle, size_t n, ...) { - ACE_TRACE ("ACE_SOCK_IO::recv"); - va_list argp; size_t total_tuples = n / 2; iovec *iovp; @@ -1141,239 +1438,368 @@ ACE::recv (ACE_HANDLE handle, size_t n, ...) return result; } -// Miscellaneous static methods used throughout ACE. - ssize_t -ACE::send_n (ACE_HANDLE handle, - const void *buf, - size_t len, - int flags) +ACE::recvv (ACE_HANDLE handle, + iovec *iov, + int iovcnt, + const ACE_Time_Value *timeout) { - ACE_TRACE ("ACE::send_n"); - size_t bytes_written; - ssize_t n; - - for (bytes_written = 0; bytes_written < len; bytes_written += n) + if (timeout == 0) + return ACE_OS::recvv (handle, iov, iovcnt); + else { - n = ACE_OS::send (handle, - (const char *) buf + bytes_written, - len - bytes_written, - flags); - if (n == -1) +#if defined (ACE_HAS_READV_TIMEDWAIT) + ACE_Time_Value copy = *timeout; + copy += ACE_OS::gettimeofday (); + timespec_t ts = copy; + return ::readv_timedwait (handle, iov, iovcnt, &ts); +#else + int val = 0; + if (ACE::enter_recv_timedwait (handle, timeout, val) == -1) + return -1; + else { - if (errno == EWOULDBLOCK) - n = 0; // Keep trying to send. - else - return -1; + ssize_t bytes_transferred = ACE_OS::recvv (handle, iov, iovcnt); + ACE::restore_non_blocking_mode (handle, val); + return bytes_transferred; } +#endif /* ACE_HAS_READV_TIMEDWAIT */ } +} - return bytes_written; +ssize_t +ACE::recvv_n (ACE_HANDLE handle, + iovec *iov, + int iovcnt, + const ACE_Time_Value *timeout) +{ + if (timeout == 0) + return ACE::recvv_n_i (handle, + iov, + iovcnt); + else + return ACE::recvv_n_i (handle, + iov, + iovcnt, + timeout); } ssize_t -ACE::recv_n (ACE_HANDLE handle, void *buf, size_t len) +ACE::recvv_n_i (ACE_HANDLE handle, + iovec *iov, + int iovcnt) { - ACE_TRACE ("ACE::recv_n"); - size_t bytes_read; - ssize_t n; + ssize_t bytes_transferred = 0; - for (bytes_read = 0; bytes_read < len; bytes_read += n) + for (int s = 0; + s < iovcnt; + ) { - n = ACE::recv (handle, - (char *) buf + bytes_read, - len - bytes_read); + ssize_t n = ACE_OS::recvv (handle, + iov + s, + iovcnt - s); if (n == -1) { + // If blocked, try again. if (errno == EWOULDBLOCK) - n = 0; // Keep trying to read. - else - return -1; + n = 0; + + // + // No timeouts in this version. + // + + // Other errors. + return -1; } else if (n == 0) - break; + return 0; + + for (bytes_transferred += n; + s < iovcnt + && n >= ACE_static_cast (ssize_t, + iov[s].iov_len); + s++) + n -= iov[s].iov_len; + + if (n != 0) + { + char *base = ACE_reinterpret_cast (char *, + iov[s].iov_base); + iov[s].iov_base = base + n; + iov[s].iov_len = iov[s].iov_len - n; + } } - return bytes_read; + return bytes_transferred; } ssize_t -ACE::recv_n (ACE_HANDLE handle, void *buf, size_t len, int flags) +ACE::recvv_n_i (ACE_HANDLE handle, + iovec *iov, + int iovcnt, + const ACE_Time_Value *timeout) { - ACE_TRACE ("ACE::recv_n"); - size_t bytes_read; - ssize_t n; + int val = 0; + ACE::record_and_set_non_blocking_mode (handle, val); - for (bytes_read = 0; bytes_read < len; bytes_read += n) + ssize_t bytes_transferred = 0; + int error = 0; + + for (int s = 0; + s < iovcnt; + ) { - n = ACE::recv (handle, - (char *) buf + bytes_read, - len - bytes_read, - flags); + int result = ACE::handle_read_ready (handle, + timeout); - if (n == -1) + if (result == -1) { - if (errno == EWOULDBLOCK) - n = 0; // Keep trying to read. - else - return -1; - } - else if (n == 0) - break; - } + // Timed out; return bytes transferred. + if (errno == ETIME) + break; - return bytes_read; -} - -int -ACE::enter_recv_timedwait (ACE_HANDLE handle, - const ACE_Time_Value *timeout, - int &val) -{ - // Give value a default value to keep Purify happy! - val = 0; + // Other errors. + error = 1; + break; + } - if (timeout == 0) - return 0; + ssize_t n = ACE_OS::recvv (handle, + iov + s, + iovcnt - s); -#if defined (ACE_HAS_POLL) && defined (ACE_HAS_LIMITED_SELECT) + // Errors (note that errno cannot be EWOULDBLOCK since select() + // just told us that data is available to read). + if (n == -1 || n == 0) + { + error = 1; + break; + } - struct pollfd fds; + for (bytes_transferred += n; + s < iovcnt + && n >= ACE_static_cast (ssize_t, + iov[s].iov_len); + s++) + n -= iov[s].iov_len; - fds.fd = handle; - fds.events = POLLIN; - fds.revents = 0; - - int a = ACE_OS::poll (&fds, 1, *timeout); + if (n != 0) + { + char *base = ACE_reinterpret_cast (char *, + iov[s].iov_base); + iov[s].iov_base = base + n; + iov[s].iov_len = iov[s].iov_len - n; + } + } -#else - ACE_Handle_Set handle_set; - handle_set.set_bit (handle); + ACE::restore_non_blocking_mode (handle, val); - // Wait for input to arrive or for the timeout to elapse. - int a = ACE_OS::select (int (handle) + 1, - (fd_set *) handle_set, // read_fds. - (fd_set *) 0, // write_fds. - (fd_set *) 0, // exception_fds. - timeout); -#endif /* ACE_HAS_POLL && ACE_HAS_LIMITED_SELECT */ + if (error) + return -1; + else + return bytes_transferred; +} - switch ( a ) - { - case 0: // Timer expired. return -1 - errno = ETIME; - /* FALLTHRU */ - case -1: // we got here directly - select() returned -1. - return -1; - case 1: // OK to read now. - /* FALLTHRU */ - default: // default is case a > 0; return a - // really should assert if a != 1 - //assert( a == 1 ); - // We need to record whether we are already *in* nonblocking - // mode, so that we can correctly reset the state when we're - // done. - val = ACE::get_flags (handle); - - if (ACE_BIT_DISABLED (val, ACE_NONBLOCK)) - // Set the handle into non-blocking mode if it's not - // already in it. - ACE::set_flags (handle, ACE_NONBLOCK); - return a; - } +ssize_t +ACE::recv (ACE_HANDLE handle, + ACE_Message_Block *message_block, + const ACE_Time_Value *timeout) +{ + return ACE::recv_i (handle, + message_block, + timeout, + 0); } -void -ACE::leave_recv_timedwait (ACE_HANDLE handle, - const ACE_Time_Value *timeout, - int val) +ssize_t +ACE::recv_n (ACE_HANDLE handle, + ACE_Message_Block *message_block, + const ACE_Time_Value *timeout) { - if (timeout != 0 - && ACE_BIT_DISABLED (val, - ACE_NONBLOCK)) - { - // Save/restore errno. - ACE_Errno_Guard error (errno); - // Only disable ACE_NONBLOCK if we weren't in non-blocking mode - // originally. - ACE::clr_flags (handle, ACE_NONBLOCK); - } + return ACE::recv_i (handle, + message_block, + timeout, + 1); } -int -ACE::enter_send_timedwait (ACE_HANDLE handle, - const ACE_Time_Value* timeout, - int &val) +ssize_t +ACE::recv_i (ACE_HANDLE handle, + ACE_Message_Block *message_block, + const ACE_Time_Value *timeout, + int loop) { - // Give value a default value to keep Purify happy! - val = 0; + iovec iov[IOV_MAX]; + int iovcnt = 0; + ssize_t n = 0; + ssize_t nbytes = 0; + ssize_t recv_size = 0; - if (timeout==0) - return 0; + while (message_block != 0) + { + // Check if this block has any space for incoming data. + if (message_block->length () > 0) + { + // Collect the data in the iovec. + iov[iovcnt].iov_base = message_block->rd_ptr (); + iov[iovcnt].iov_len = message_block->length (); -#if defined (ACE_HAS_POLL) && defined (ACE_HAS_LIMITED_SELECT) + // Increment iovec counter. + iovcnt++; - struct pollfd fds; + // Keep track of the number of bytes for this recv. + recv_size += message_block->length (); - fds.fd = handle; - fds.events = POLLOUT; - fds.revents = 0; + // The buffer is full make a OS call. @@ TODO find a way to + // find IOV_MAX for platforms that do not define it rather + // than simply setting IOV_MAX to some arbitrary value such + // as 16. + if (iovcnt == IOV_MAX) + { + if (loop) + n = ACE::recvv_n (handle, + iov, + iovcnt, + timeout); + else + n = ACE::recvv (handle, + iov, + iovcnt, + timeout); + + // Errors. + if (n <= 0) + return n; + + // Success. Add to total bytes transferred. + nbytes += n; + + // Reset iovec counter. + iovcnt = 0; + + // If we sent everything we had accumulated in the last + // call, then keep going. If it was a partial recv, we + // won't continue. + if (recv_size == n) + recv_size = 0; + else + break; + } + } - int a = ACE_OS::poll (&fds, 1, *timeout); + // Selection of the next message block: first check the + // continuation chain; then look at the next message block in + // the queue. + if (message_block->cont ()) + message_block = message_block->cont (); + else + message_block = message_block->next (); + } -#else - ACE_Handle_Set handle_set; - handle_set.set_bit (handle); + // Check for remaining buffers to be sent. This will happen when + // IOV_MAX is not a multiple of the number of message blocks. + if (iovcnt != 0) + { + n = ACE::recvv (handle, + iov, + iovcnt, + timeout); - // On timed writes we always go into select(); only if the - // handle is available for writing within the specified amount - // of time do we put it in non-blocking mode + // Errors. + if (n <= 0) + return n; - int a = ACE_OS::select (int (handle) + 1, - (fd_set *) 0, - (fd_set *) handle_set, - (fd_set *) 0, - timeout); -#endif /* ACE_HAS_POLL && ACE_HAS_LIMITED_SELECT */ + // Success. Add to total bytes transferred. + nbytes += n; + } - switch ( a ) - { - case 0: // Timer expired. - errno = ETIME; - /* FALLTHRU */ - case -1: // we got here directly - select() returned -1. - return -1; - case 1: // Ok to write now. - /* FALLTHRU */ - default: // default is case a > 0; return a - // really should assert if a != 1 - //assert( a == 1 ); - // We need to record whether we are already *in* nonblocking - // mode, so that we can correctly reset the state when we're - // done. - val = ACE::get_flags (handle); + // Return total bytes transferred. + return nbytes; +} - if (ACE_BIT_DISABLED (val, ACE_NONBLOCK)) - // Set the handle into non-blocking mode if it's not - // already in it. - ACE::set_flags (handle, ACE_NONBLOCK); - return a; +ssize_t +ACE::send (ACE_HANDLE handle, + const void *buf, + size_t n, + int flags, + const ACE_Time_Value *timeout) +{ + if (timeout == 0) + return ACE_OS::send (handle, (const char *) buf, n, flags); + else + { +#if defined (ACE_HAS_SEND_TIMEDWAIT) + ACE_Time_Value copy = *timeout; + copy += ACE_OS::gettimeofday(); + timespec_t ts = copy; + return ::send_timedwait (handle, buf, n, flags, &ts); +#else + int val = 0; + if (ACE::enter_send_timedwait (handle, timeout, val) == -1) + return -1; + else + { + ssize_t bytes_transferred = ACE_OS::send (handle, (const char *) buf, n, flags); + ACE::restore_non_blocking_mode (handle, val); + return bytes_transferred; + } +#endif /* ACE_HAS_SEND_TIMEDWAIT */ } } -void -ACE::leave_send_timedwait (ACE_HANDLE handle, - const ACE_Time_Value *timeout, - int val) +ssize_t +ACE::send (ACE_HANDLE handle, + const void *buf, + size_t n, + const ACE_Time_Value *timeout) { - if (timeout != 0 - && ACE_BIT_DISABLED (val, ACE_NONBLOCK)) + if (timeout == 0) + return ACE::send_i (handle, buf, n); + else { - // Save/restore errno. - ACE_Errno_Guard error (errno); - // Only disable ACE_NONBLOCK if we weren't in non-blocking mode - // originally. - ACE::clr_flags (handle, ACE_NONBLOCK); +#if defined (ACE_HAS_WRITE_TIMEDWAIT) + ACE_Time_Value copy = *timeout; + copy += ACE_OS::gettimeofday (); + timespec_t ts = copy; + return ::write_timedwait (handle, buf, n, &ts); +#else + int val = 0; + if (ACE::enter_send_timedwait (handle, timeout, val) == -1) + return -1; + else + { + ssize_t bytes_transferred = ACE::send_i (handle, buf, n); + ACE::restore_non_blocking_mode (handle, val); + return bytes_transferred; + } +#endif /* ACE_HAS_WRITE_TIMEDWAIT */ + } +} + +ssize_t +ACE::sendmsg (ACE_HANDLE handle, + const struct msghdr *msg, + int flags, + const ACE_Time_Value *timeout) +{ + if (timeout == 0) + return ACE_OS::sendmsg (handle, msg, flags); + else + { +#if defined (ACE_HAS_SENDMSG_TIMEDWAIT) + ACE_Time_Value copy = *timeout; + copy += ACE_OS::gettimeofday (); + timespec_t ts = copy; + return ::sendmsg_timedwait (handle, msg, flags, &ts); +#else + int val = 0; + if (ACE::enter_send_timedwait (handle, timeout, val) == -1) + return -1; + else + { + int bytes_transferred = ACE_OS::sendmsg (handle, msg, flags); + ACE::restore_non_blocking_mode (handle, val); + return bytes_transferred; + } +#endif /* ACE_HAS_SENDMSG_TIMEDWAIT */ } } @@ -1386,207 +1812,744 @@ ACE::sendto (ACE_HANDLE handle, int addrlen, const ACE_Time_Value *timeout) { - // ACE_TRACE ("ACE::sendto"); -#if defined (ACE_HAS_SENDTO_TIMEDWAIT) if (timeout == 0) - return ACE_OS::sendto (handle, buf, len, flags, addr, addrlen); + return ACE_OS::sendto (handle, buf, len, flags, addr, addrlen); else { +#if defined (ACE_HAS_SENDTO_TIMEDWAIT) ACE_Time_Value copy = *timeout; copy += ACE_OS::gettimeofday (); timespec_t ts = copy; - return ::sendto_timedwait (handle, - buf, - len, - flags, - addr, - addrlen, - &ts); - } + return ::sendto_timedwait (handle, buf, len, flags, addr, addrlen, ts); #else - int val; - if (ACE::enter_send_timedwait (handle, timeout, val) == -1) - return -1; + int val = 0; + if (ACE::enter_send_timedwait (handle, timeout, val) == -1) + return -1; + else + { + int bytes_transferred = ACE_OS::sendto (handle, buf, len, flags, addr, addrlen); + ACE::restore_non_blocking_mode (handle, val); + return bytes_transferred; + } +#endif /* ACE_HAS_SENDTO_TIMEDWAIT */ + } +} + +ssize_t +ACE::send_n (ACE_HANDLE handle, + const void *buf, + size_t len, + int flags, + const ACE_Time_Value *timeout) +{ + if (timeout == 0) + return ACE::send_n_i (handle, + buf, + len, + flags); else + return ACE::send_n_i (handle, + buf, + len, + flags, + timeout); +} + +ssize_t +ACE::send_n_i (ACE_HANDLE handle, + const void *buf, + size_t len, + int flags) +{ + size_t bytes_transferred; + ssize_t n; + + for (bytes_transferred = 0; + bytes_transferred < len; + bytes_transferred += n) { - int bytes_written = ACE_OS::sendto (handle, - buf, - len, - flags, - addr, - addrlen); - ACE::leave_send_timedwait (handle, timeout, val); - return bytes_written; + n = ACE_OS::send (handle, + (char *) buf + bytes_transferred, + len - bytes_transferred, + flags); + if (n == -1) + { + // If blocked, try again. + if (errno == EWOULDBLOCK) + n = 0; + + // + // No timeouts in this version. + // + + // Other errors. + return -1; + } + else if (n == 0) + return 0; } -#endif /* ACE_HAS_SENDTO_TIMEDWAIT */ + + return bytes_transferred; } ssize_t -ACE::sendmsg (ACE_HANDLE handle, - const struct msghdr *msg, - int flags, - const ACE_Time_Value *timeout) +ACE::send_n_i (ACE_HANDLE handle, + const void *buf, + size_t len, + int flags, + const ACE_Time_Value *timeout) +{ + int val = 0; + ACE::record_and_set_non_blocking_mode (handle, val); + + size_t bytes_transferred; + ssize_t n; + int error = 0; + + for (bytes_transferred = 0; + bytes_transferred < len; + bytes_transferred += n) + { + int result = ACE::handle_write_ready (handle, + timeout); + + if (result == -1) + { + // Timed out; return bytes transferred. + if (errno == ETIME) + break; + + // Other errors. + error = 1; + break; + } + + n = ACE_OS::send (handle, + (char *) buf + bytes_transferred, + len - bytes_transferred, + flags); + + // Errors (note that errno cannot be EWOULDBLOCK since select() + // just told us that data can be written). + if (n == -1 || n == 0) + { + error = 1; + break; + } + } + + ACE::restore_non_blocking_mode (handle, val); + + if (error) + return -1; + else + return bytes_transferred; +} + +ssize_t +ACE::send_n (ACE_HANDLE handle, + const void *buf, + size_t len, + const ACE_Time_Value *timeout) { - // ACE_TRACE ("ACE::sendmsg"); -#if defined (ACE_HAS_SENDMSG_TIMEDWAIT) if (timeout == 0) - return ACE_OS::sendmsg (handle, msg, flags); + return ACE::send_n_i (handle, + buf, + len); else + return ACE::send_n_i (handle, + buf, + len, + timeout); +} + +ssize_t +ACE::send_n_i (ACE_HANDLE handle, + const void *buf, + size_t len) +{ + size_t bytes_transferred; + ssize_t n; + + for (bytes_transferred = 0; + bytes_transferred < len; + bytes_transferred += n) { - ACE_Time_Value copy = *timeout; - copy += ACE_OS::gettimeofday (); - timespec_t ts = copy; - return ::sendmsg_timedwait (handle, msg, flags, &ts); + n = ACE::send_i (handle, + (char *) buf + bytes_transferred, + len - bytes_transferred); + if (n == -1) + { + // If blocked, try again. + if (errno == EWOULDBLOCK) + n = 0; + + // + // No timeouts in this version. + // + + // Other errors. + return -1; + } + else if (n == 0) + return 0; } -#else - int val; - if (ACE::enter_send_timedwait (handle, timeout, val) == -1) + + return bytes_transferred; +} + +ssize_t +ACE::send_n_i (ACE_HANDLE handle, + const void *buf, + size_t len, + const ACE_Time_Value *timeout) +{ + int val = 0; + ACE::record_and_set_non_blocking_mode (handle, val); + + size_t bytes_transferred; + ssize_t n; + int error = 0; + + for (bytes_transferred = 0; + bytes_transferred < len; + bytes_transferred += n) + { + int result = ACE::handle_write_ready (handle, + timeout); + + if (result == -1) + { + // Timed out; return bytes transferred. + if (errno == ETIME) + break; + + // Other errors. + error = 1; + break; + } + + n = ACE::send_i (handle, + (char *) buf + bytes_transferred, + len - bytes_transferred); + + // Errors (note that errno cannot be EWOULDBLOCK since select() + // just told us that data can be written). + if (n == -1 || n == 0) + { + error = 1; + break; + } + } + + ACE::restore_non_blocking_mode (handle, val); + + if (error) return -1; else + return bytes_transferred; +} + +// Send N char *ptrs and int lengths. Note that the char *'s precede +// the ints (basically, an varargs version of writev). The count N is +// the *total* number of trailing arguments, *not* a couple of the +// number of tuple pairs! + +ssize_t +ACE::send (ACE_HANDLE handle, size_t n, ...) +{ + va_list argp; + size_t total_tuples = n / 2; + iovec *iovp; +#if defined (ACE_HAS_ALLOCA) + iovp = (iovec *) alloca (total_tuples * sizeof (iovec)); +#else + ACE_NEW_RETURN (iovp, + iovec[total_tuples], + -1); +#endif /* !defined (ACE_HAS_ALLOCA) */ + + va_start (argp, n); + + for (size_t i = 0; i < total_tuples; i++) { - int bytes_written = ACE_OS::sendmsg (handle, msg, flags); - ACE::leave_send_timedwait (handle, timeout, val); - return bytes_written; + iovp[i].iov_base = va_arg (argp, char *); + iovp[i].iov_len = va_arg (argp, ssize_t); } -#endif /* ACE_HAS_SENDMSG_TIMEDWAIT */ + + ssize_t result = ACE_OS::sendv (handle, iovp, total_tuples); +#if !defined (ACE_HAS_ALLOCA) + delete [] iovp; +#endif /* !defined (ACE_HAS_ALLOCA) */ + va_end (argp); + return result; } ssize_t -ACE::readv (ACE_HANDLE handle, - iovec *iov, +ACE::sendv (ACE_HANDLE handle, + const iovec *iov, int iovcnt, const ACE_Time_Value *timeout) { - // ACE_TRACE ("ACE::readv"); -#if defined (ACE_HAS_READV_TIMEDWAIT) if (timeout == 0) - return ACE_OS::readv (handle, iov, iovcnt); - else { - ACE_Time_Value copy = *timeout; - copy += ACE_OS::gettimeofday (); - timespec_t ts = copy; - return ::readv_timedwait (handle, iov, iovcnt, &ts); - } -#else - int val; - if (ACE::enter_recv_timedwait (handle, timeout, val) == -1) - return -1; + return ACE_OS::sendv (handle, iov, iovcnt); else { - ssize_t bytes_read = ACE_OS::readv (handle, iov, iovcnt); - ACE::leave_recv_timedwait (handle, timeout, val); - return bytes_read; +#if defined (ACE_HAS_WRITEV_TIMEDWAIT) + ACE_Time_Value copy = *timeout; + copy += ACE_OS::gettimeofday (); + timespec_t ts = copy; + return ::sendv_timedwait (handle, iov, iovcnt, &ts); +#else + int val = 0; + if (ACE::enter_send_timedwait (handle, timeout, val) == -1) + return -1; + else + { + ssize_t bytes_transferred = ACE_OS::sendv (handle, iov, iovcnt); + ACE::restore_non_blocking_mode (handle, val); + return bytes_transferred; + } +#endif /* ACE_HAS_WRITEV_TIMEDWAIT */ } -#endif /* ACE_HAS_READV_TIMEDWAIT */ } ssize_t -ACE::writev (ACE_HANDLE handle, - const iovec *iov, - int iovcnt, - const ACE_Time_Value *timeout) +ACE::sendv_n (ACE_HANDLE handle, + const iovec *iov, + int iovcnt, + const ACE_Time_Value *timeout) { - // ACE_TRACE ("ACE::writev"); -#if defined (ACE_HAS_WRITEV_TIMEDWAIT) if (timeout == 0) - return ACE_OS::writev (handle, iov, iovcnt); - else { - ACE_Time_Value copy = *timeout; - copy += ACE_OS::gettimeofday (); - timespec_t ts = copy; - return ::writev_timedwait (handle, iov, iovcnt, &ts); - } -#else - int val; - if (ACE::enter_send_timedwait (handle, timeout, val) == -1) - return -1; + return ACE::sendv_n_i (handle, + iov, + iovcnt); else + return ACE::sendv_n_i (handle, + iov, + iovcnt, + timeout); +} + +ssize_t +ACE::sendv_n_i (ACE_HANDLE handle, + const iovec *i, + int iovcnt) +{ + iovec *iov = ACE_const_cast (iovec *, i); + + ssize_t bytes_transferred = 0; + + for (int s = 0; + s < iovcnt; + ) { - ssize_t bytes_written = ACE_OS::writev (handle, iov, iovcnt); - ACE::leave_send_timedwait (handle, timeout, val); - return bytes_written; + ssize_t n = ACE_OS::sendv (handle, + iov + s, + iovcnt - s); + if (n == -1) + { + // If blocked, try again. + if (errno == EWOULDBLOCK) + n = 0; + + // + // No timeouts in this version. + // + + // Other errors. + return -1; + } + else if (n == 0) + return 0; + + for (bytes_transferred += n; + s < iovcnt + && n >= ACE_static_cast (ssize_t, + iov[s].iov_len); + s++) + n -= iov[s].iov_len; + + if (n != 0) + { + char *base = ACE_reinterpret_cast (char *, + iov[s].iov_base); + iov[s].iov_base = base + n; + iov[s].iov_len = iov[s].iov_len - n; + } } -#endif /* ACE_HAS_WRITEV_TIMEDWAIT */ + + return bytes_transferred; } ssize_t -ACE::writev_n (ACE_HANDLE h, - const iovec *i, - int iovcnt) +ACE::sendv_n_i (ACE_HANDLE handle, + const iovec *i, + int iovcnt, + const ACE_Time_Value *timeout) { - ssize_t writelen = 0; iovec *iov = ACE_const_cast (iovec *, i); + int val = 0; + ACE::record_and_set_non_blocking_mode (handle, val); + + ssize_t bytes_transferred = 0; + int error = 0; + for (int s = 0; s < iovcnt; ) { - ssize_t n = ACE_OS::writev (h, - iov + s, - iovcnt - s); - if (n == -1) - return n; - else + int result = ACE::handle_write_ready (handle, + timeout); + + if (result == -1) + { + // Timed out; return bytes transferred. + if (errno == ETIME) + break; + + // Other errors. + error = 1; + break; + } + + ssize_t n = ACE_OS::sendv (handle, + iov + s, + iovcnt - s); + + // Errors (note that errno cannot be EWOULDBLOCK since select() + // just told us that data can be written). + if (n == -1 || n == 0) + { + error = 1; + break; + } + + for (bytes_transferred += n; + s < iovcnt + && n >= ACE_static_cast (ssize_t, + iov[s].iov_len); + s++) + n -= iov[s].iov_len; + + if (n != 0) + { + char *base = ACE_reinterpret_cast (char *, + iov[s].iov_base); + iov[s].iov_base = base + n; + iov[s].iov_len = iov[s].iov_len - n; + } + } + + ACE::restore_non_blocking_mode (handle, val); + + if (error) + return -1; + else + return bytes_transferred; +} + +ssize_t +ACE::send (ACE_HANDLE handle, + const ACE_Message_Block *message_block, + const ACE_Time_Value *timeout) +{ + return ACE::send_i (handle, + message_block, + timeout, + 0); +} + +ssize_t +ACE::send_n (ACE_HANDLE handle, + const ACE_Message_Block *message_block, + const ACE_Time_Value *timeout) +{ + return ACE::send_i (handle, + message_block, + timeout, + 1); +} + +ssize_t +ACE::send_i (ACE_HANDLE handle, + const ACE_Message_Block *message_block, + const ACE_Time_Value *timeout, + int loop) +{ + iovec iov[IOV_MAX]; + int iovcnt = 0; + ssize_t n = 0; + ssize_t nbytes = 0; + ssize_t send_size = 0; + + while (message_block != 0) + { + // Check if this block has any data to be sent. + if (message_block->length () > 0) { - for (writelen += n; - s < iovcnt - && n >= ACE_static_cast (ssize_t, - iov[s].iov_len); - s++) - n -= iov[s].iov_len; + // Collect the data in the iovec. + iov[iovcnt].iov_base = message_block->rd_ptr (); + iov[iovcnt].iov_len = message_block->length (); + + // Increment iovec counter. + iovcnt++; - if (n != 0) + // Keep track of the number of bytes for this send. + send_size += message_block->length (); + + // The buffer is full make a OS call. @@ TODO find a way to + // find IOV_MAX for platforms that do not define it rather + // than simply setting IOV_MAX to some arbitrary value such + // as 16. + if (iovcnt == IOV_MAX) { - char *base = ACE_reinterpret_cast (char *, - iov[s].iov_base); - iov[s].iov_base = base + n; - iov[s].iov_len = iov[s].iov_len - n; + if (loop) + n = ACE::sendv_n (handle, + iov, + iovcnt, + timeout); + else + n = ACE::sendv (handle, + iov, + iovcnt, + timeout); + + // Errors. + if (n <= 0) + return n; + + // Success. Add to total bytes transferred. + nbytes += n; + + // Reset iovec counter. + iovcnt = 0; + + // If we sent everything we had accumulated in the last + // call, then keep going. If it was a partial send, we + // won't continue. + if (send_size == n) + send_size = 0; + else + break; } } + + // Selection of the next message block: first check the + // continuation chain; then look at the next message block in + // the queue. + if (message_block->cont ()) + message_block = message_block->cont (); + else + message_block = message_block->next (); + } + + // Check for remaining buffers to be sent. This will happen when + // IOV_MAX is not a multiple of the number of message blocks. + if (iovcnt != 0) + { + n = ACE::sendv (handle, + iov, + iovcnt, + timeout); + + // Errors. + if (n <= 0) + return n; + + // Success. Add to total bytes transferred. + nbytes += n; } - return writelen; + // Return total bytes transferred. + return nbytes; } ssize_t -ACE::sendv_n (ACE_HANDLE h, - const iovec *i, +ACE::readv_n (ACE_HANDLE handle, + iovec *iov, int iovcnt) { - ssize_t writelen = 0; - iovec *iov = ACE_const_cast (iovec *, i); + ssize_t bytes_transferred = 0; for (int s = 0; s < iovcnt; ) { - ssize_t n = ACE_OS::sendv (h, + ssize_t n = ACE_OS::readv (handle, iov + s, iovcnt - s); - if (n == -1) + if (n == -1 || n == 0) return n; - else + + for (bytes_transferred += n; + s < iovcnt + && n >= ACE_static_cast (ssize_t, + iov[s].iov_len); + s++) + n -= iov[s].iov_len; + + if (n != 0) { - for (writelen += n; - s < iovcnt - && n >= ACE_static_cast (ssize_t, - iov[s].iov_len); - s++) - n -= iov[s].iov_len; + char *base = ACE_reinterpret_cast (char *, + iov[s].iov_base); + iov[s].iov_base = base + n; + iov[s].iov_len = iov[s].iov_len - n; + } + } - if (n != 0) - { - char *base = ACE_reinterpret_cast (char *, - iov[s].iov_base); - iov[s].iov_base = base + n; - iov[s].iov_len = iov[s].iov_len - n; - } + return bytes_transferred; +} + +ssize_t +ACE::writev_n (ACE_HANDLE handle, + const iovec *i, + int iovcnt) +{ + iovec *iov = ACE_const_cast (iovec *, i); + + ssize_t bytes_transferred = 0; + + for (int s = 0; + s < iovcnt; + ) + { + ssize_t n = ACE_OS::writev (handle, + iov + s, + iovcnt - s); + if (n == -1 || n == 0) + return n; + + for (bytes_transferred += n; + s < iovcnt + && n >= ACE_static_cast (ssize_t, + iov[s].iov_len); + s++) + n -= iov[s].iov_len; + + if (n != 0) + { + char *base = ACE_reinterpret_cast (char *, + iov[s].iov_base); + iov[s].iov_base = base + n; + iov[s].iov_len = iov[s].iov_len - n; } } - return writelen; + return bytes_transferred; } +int +ACE::handle_ready (ACE_HANDLE handle, + const ACE_Time_Value *timeout, + int read_ready, + int write_ready, + int exception_ready) +{ +#if defined (ACE_HAS_POLL) && defined (ACE_HAS_LIMITED_SELECT) + + struct pollfd fds; + + fds.fd = handle; + fds.events = read_ready ? POLLIN : POLLOUT; + fds.revents = 0; + + int result = ACE_OS::poll (&fds, 1, *timeout); + +#else + + ACE_Handle_Set handle_set; + handle_set.set_bit (handle); + + // Wait for data or for the timeout to elapse. + int result = ACE_OS::select (int (handle) + 1, + read_ready ? handle_set.fdset () : 0, // read_fds. + write_ready ? handle_set.fdset () : 0, // write_fds. + exception_ready ? handle_set.fdset () : 0, // exception_fds. + timeout); + +#endif /* ACE_HAS_POLL && ACE_HAS_LIMITED_SELECT */ + + switch (result) + { + case 0: // Timer expired. + errno = ETIME; + /* FALLTHRU */ + case -1: // we got here directly - select() returned -1. + return -1; + case 1: // Handle has data. + /* FALLTHRU */ + default: // default is case result > 0; return a + // ACE_ASSERT (result == 1); + return result; + } +} + +int +ACE::enter_recv_timedwait (ACE_HANDLE handle, + const ACE_Time_Value *timeout, + int &val) +{ + int result = ACE::handle_read_ready (handle, + timeout); + + if (result == -1) + return -1; + + ACE::record_and_set_non_blocking_mode (handle, + val); + + return result; +} + +int +ACE::enter_send_timedwait (ACE_HANDLE handle, + const ACE_Time_Value *timeout, + int &val) +{ + int result = ACE::handle_write_ready (handle, + timeout); + + if (result == -1) + return -1; + + ACE::record_and_set_non_blocking_mode (handle, + val); + + return result; +} + +void +ACE::record_and_set_non_blocking_mode (ACE_HANDLE handle, + int &val) +{ + // We need to record whether we are already *in* nonblocking mode, + // so that we can correctly reset the state when we're done. + val = ACE::get_flags (handle); + + if (ACE_BIT_DISABLED (val, ACE_NONBLOCK)) + // Set the handle into non-blocking mode if it's not already in + // it. + ACE::set_flags (handle, ACE_NONBLOCK); +} + +void +ACE::restore_non_blocking_mode (ACE_HANDLE handle, + int val) +{ + if (ACE_BIT_DISABLED (val, + ACE_NONBLOCK)) + { + // Save/restore errno. + ACE_Errno_Guard error (errno); + // Only disable ACE_NONBLOCK if we weren't in non-blocking mode + // originally. + ACE::clr_flags (handle, ACE_NONBLOCK); + } +} + + // Format buffer into printable format. This is useful for debugging. // Portions taken from mdump by J.P. Knight (J.P.Knight@lut.ac.uk) // Modifications by Todd Montgomery. @@ -2312,329 +3275,6 @@ ACE::map_errno (int error) return error; } -ssize_t -ACE::send (ACE_HANDLE handle, - const void *buf, - size_t n, - int flags, - const ACE_Time_Value *timeout) -{ -#if defined (ACE_HAS_SEND_TIMEDWAIT) - if (timeout == 0) - return ACE::send (handle, buf, n, flags); - else - { - ACE_Time_Value copy = *timeout; - copy += ACE_OS::gettimeofday(); - timespec_t ts = copy; - return ::send_timedwait (handle, buf, n, flags, &ts); - } -#else - int val; - - if (ACE::enter_send_timedwait (handle, timeout, val) == -1) - return -1; - else - { - ssize_t bytes_written = ACE::send (handle, buf, n, flags); - ACE::leave_send_timedwait (handle, timeout, val); - return bytes_written; - } -#endif /* ACE_HAS_SEND_TIMEDWAIT */ -} - -ssize_t -ACE::send (ACE_HANDLE handle, - const void *buf, - size_t n, - const ACE_Time_Value *timeout) -{ - // ACE_TRACE ("ACE_OS::write"); -#if defined (ACE_HAS_WRITE_TIMEDWAIT) - if (timeout == 0) - return ACE::send (handle, buf, n); - else - { - ACE_Time_Value copy = *timeout; - copy += ACE_OS::gettimeofday (); - timespec_t ts = copy; - return ::write_timedwait (handle, buf, n, &ts); - } -#else - int val; - - if (ACE::enter_send_timedwait (handle, timeout, val) == -1) - return -1; - else - { - ssize_t bytes_written = ACE::send (handle, buf, n); - ACE::leave_send_timedwait (handle, timeout, val); - return bytes_written; - } -#endif /* ACE_HAS_WRITE_TIMEDWAIT */ -} - -ssize_t -ACE::send_n (ACE_HANDLE handle, - const void *buf, - size_t len, - int flags, - const ACE_Time_Value *timeout) -{ - // Total number of bytes written. - size_t bytes_written; - - // Actual number of bytes written in each <send> attempt. - ssize_t n; - - for (bytes_written = 0; - bytes_written < len; - bytes_written += n) - { - n = ACE::send (handle, - (char *) buf + bytes_written, - len - bytes_written, - flags, - timeout); - if (n == -1) - if (errno == EWOULDBLOCK) - n = 0; // Keep trying to send. - else - return -1; - } - - return bytes_written; -} - -ssize_t -ACE::send_n (ACE_HANDLE handle, - const void *buf, - size_t len, - const ACE_Time_Value *timeout) -{ - // Total number of bytes written. - size_t bytes_written; - - // Actual number of bytes written in each <send> attempt. - ssize_t n; - - for (bytes_written = 0; - bytes_written < len; - bytes_written += n) - { - n = ACE::send (handle, (char *) buf + bytes_written, - len - bytes_written, timeout); - if (n == -1) - if (errno == EWOULDBLOCK) - n = 0; // Keep trying to send. - else - return -1; - } - - return bytes_written; -} - -ssize_t -ACE::recvfrom (ACE_HANDLE handle, - char *buf, - int len, - int flags, - struct sockaddr *addr, - int *addrlen, - const ACE_Time_Value *timeout) -{ - // ACE_TRACE ("ACE::recvfrom"); -#if defined (ACE_HAS_RECVFROM_TIMEDWAIT) - if (timeout == 0) - return ACE_OS::recvfrom (handle, - buf, - len, - flags, - addr, - addrlen); - else - { - ACE_Time_Value copy = *timeout; - copy += ACE_OS::gettimeofday (); - timespec_t ts = copy; - return ::recvfrom_timedwait (handle, - buf, - len, - flags, - addr, - addrlen, - &ts)a -; - } -#else - int val; - if (ACE::enter_recv_timedwait (handle, - timeout, - val) == -1) - return -1; - else - { - int bytes_read = ACE_OS::recvfrom (handle, - buf, - len, - flags, - addr, - addrlen); - ACE::leave_recv_timedwait (handle, - timeout, - val); - return bytes_read; - } -#endif /* ACE_HAS_RECVFROM_TIMEDWAIT */ -} - -ssize_t -ACE::recvmsg (ACE_HANDLE handle, - struct msghdr *msg, - int flags, - const ACE_Time_Value *timeout) -{ - // ACE_TRACE ("ACE::recvmsg"); -#if defined (ACE_HAS_RECVMSG_TIMEDWAIT) - if (timeout == 0) - return ACE_OS::recvmsg (handle, msg, flags); - else - { - ACE_Time_Value copy = *timeout; - copy += ACE_OS::gettimeofday (); - timespec_t ts = copy; - return ::recvmsg_timedwait (handle, msg, flags, &ts); - } -#else - int val; - if (ACE::enter_recv_timedwait (handle, timeout, val) == -1) - return -1; - else - { - int bytes_read = ACE_OS::recvmsg (handle, msg, flags); - ACE::leave_recv_timedwait (handle, timeout, val); - return bytes_read; - } -#endif /* ACE_HAS_RECVMSG_TIMEDWAIT */ -} - -ssize_t -ACE::recv (ACE_HANDLE handle, - void *buf, - size_t n, - const ACE_Time_Value *timeout) -{ - // ACE_TRACE ("ACE::read"); -#if defined (ACE_HAS_READ_TIMEDWAIT) - if (timeout == 0) - return ACE::recv (handle, buf, n); - else - { - ACE_Time_Value copy = *timeout; - copy += ACE_OS::gettimeofday (); - timespec_t ts = copy; - return ::read_timedwait (handle, buf, n, &ts); - } -#else - int val; - - if (ACE::enter_recv_timedwait (handle, timeout, val) == -1) - return -1; - else - { - ssize_t bytes_read = ACE::recv (handle, buf, n); - ACE::leave_recv_timedwait (handle, timeout, val); - return bytes_read; - } -#endif /* ACE_HAS_READ_TIMEDWAIT */ -} - -ssize_t -ACE::recv (ACE_HANDLE handle, - void *buf, - size_t len, - int flags, - const ACE_Time_Value *timeout) -{ - // ACE_TRACE ("ACE::recv"); -#if defined (ACE_HAS_RECV_TIMEDWAIT) - if (timeout == 0) - return ACE::recv (handle, buf, len, flags); - else - { - ACE_Time_Value copy = *timeout; - copy += ACE_OS::gettimeofday (); - timespec_t ts = copy; - return ::recv_timedwait (handle, buf, len, flags, &ts); - } -#else - int val; - if (ACE::enter_recv_timedwait (handle, timeout, val)==-1) - return -1; - else - { - ssize_t bytes_recv = ACE::recv (handle, buf, len, flags); - ACE::leave_recv_timedwait (handle, timeout, val); - return bytes_recv; - } -#endif /* ACE_HAS_RECV_TIMEDWAIT */ -} - -ssize_t -ACE::recv_n (ACE_HANDLE handle, - void *buf, - size_t len, - int flags, - const ACE_Time_Value *timeout) -{ - size_t bytes_received; - - // Actual number of bytes read in each attempt. - ssize_t n; - - for (bytes_received = 0; - bytes_received < len; - bytes_received += n) - { - n = ACE::recv (handle, - (char *) buf + bytes_received, - len - bytes_received, - flags, - timeout); - if (n == -1 || n == 0) - break; - } - - return bytes_received; -} - -ssize_t -ACE::recv_n (ACE_HANDLE handle, - void *buf, - size_t len, - const ACE_Time_Value *timeout) -{ - size_t bytes_received; - - // Actual number of bytes read in each attempt. - ssize_t n; - - for (bytes_received = 0; - bytes_received < len; - bytes_received += n) - { - n = ACE::recv (handle, - (char *) buf + bytes_received, - len - bytes_received, - timeout); - if (n == -1 || n == 0) - break; - } - - return bytes_received; -} - - // Euclid's greatest common divisor algorithm. u_long ACE::gcd (u_long x, u_long y) diff --git a/ace/ACE.h b/ace/ACE.h index c6ad68687ee..6ff3e15750e 100644 --- a/ace/ACE.h +++ b/ace/ACE.h @@ -27,6 +27,7 @@ // Forward declarations. class ACE_Time_Value; class ACE_INET_Addr; +class ACE_Message_Block; class ACE_Export ACE { @@ -77,75 +78,56 @@ public: // Check if error indicates the process being out of handles (file // descriptors). - // = Recv operations that factor out differences between Win32 and UNIX. - static ssize_t recv (ACE_HANDLE handle, - void *buf, - size_t len, - int flags); - // Receive up to <len> bytes into <buf> from <handle> (uses the - // <ACE_OS::recv> call). - - static ssize_t recv (ACE_HANDLE handle, - void *buf, - size_t len); - // Receive up to <len> bytes into <buf> from <handle> (uses the - // <ACE_OS::read> system call on UNIX and the <ACE_OS::recv> call on - // Win32). - - // = Recv operations that receive exactly n bytes. - static ssize_t recv_n (ACE_HANDLE handle, - void *buf, - size_t len, - int flags); - // Receive <len> bytes into <buf> from <handle> (uses the - // <ACE_OS::recv> call). If <handle> is set to non-blocking mode - // this call will poll until all <len> bytes are received. + // = I/O operations. - static ssize_t recv_n (ACE_HANDLE handle, - void *buf, - size_t len); - // Receive <len> bytes into <buf> from <handle> (uses the - // <ACE_OS::read> system call on UNIX and the <ACE_OS::recv> call on - // Win32). If <handle> is set to non-blocking mode this call will - // poll until all <len> bytes are received. + // = Notes on common parameters: + // + // <handle> is the connected endpoint that will be used for I/O. + // + // <buf> is the buffer to write from or receive into. + // + // <len> is the number of bytes to transfer. + // + // The <timeout> parameter in the following methods indicates how + // long to blocking trying to transfer data. If <timeout> == 0, + // then the call behaves as a normal send/recv call, i.e., for + // blocking sockets, the call will block until action is possible; + // for non-blocking sockets, EWOULDBLOCK will be returned if no + // action is immediately possible. + // + // If <timeout> != 0, the call will wait until the relative time + // specified in *<timeout> elapses. + // + // Errors are reported by -1 and 0 return values. If the operation + // times out, -1 is returned with <errno == ETIME>. If it succeeds + // the number of bytes transferred is returned. + // + // The "_n" I/O methods keep looping until all the data has been + // transferred. These methods also work for sockets in non-blocking + // mode i.e., they keep looping on EWOULDBLOCK. <timeout> is used + // to make sure we keep making progress, i.e., the same timeout + // value is used for every I/O operation in the loop and the timeout + // is not counted down. If the transfer times out, the number of + // bytes transferred so far are returned. + // + // Methods with <iovec> parameter are I/O vector variants of the I/O + // operations. - // = Timed <recv> operations. static ssize_t recv (ACE_HANDLE handle, void *buf, size_t len, int flags, - const ACE_Time_Value *timeout); - // Wait up to <timeout> amount of time to receive up to <len> bytes - // into <buf> from <handle> (uses the <ACE_OS::recv> call). The - // <timeout> indicates how long to blocking trying to receive. If - // <timeout> == 0, the caller will block until action is possible, - // else will wait until the relative time specified in *<timeout> - // elapses). If <recv> times out a -1 is returned with <errno == - // ETIME>. If it succeeds the number of bytes received is returned. + const ACE_Time_Value *timeout = 0); static ssize_t recv (ACE_HANDLE handle, void *buf, size_t len, - const ACE_Time_Value *timeout); - // Wait up to <timeout> amount of time to receive up to <len> bytes - // into <buf> from <handle> (uses the <ACE_OS::read> call). The - // <timeout> indicates how long to blocking trying to receive. If - // <timeout> == 0, the caller will block until action is possible, - // else will wait until the relative time specified in *<timeout> - // elapses). If <recv> times out a -1 is returned with <errno == - // ETIME>. If it succeeds the number of bytes received is returned. + const ACE_Time_Value *timeout = 0); static ssize_t recvmsg (ACE_HANDLE handle, struct msghdr *msg, int flags, - const ACE_Time_Value *timeout); - // Wait up to <timeout> amount of time to receive <msg> from - // <handle> (uses the <ACE_OS::recvmsg> call). The <timeout> - // indicates how long to blocking trying to receive. If <timeout> - // == 0, the caller will block until action is possible, else will - // wait until the relative time specified in *<timeout> elapses). - // If <recvmsg> times out a -1 is returned with <errno == ETIME>. - // If it succeeds the number of bytes received is returned. + const ACE_Time_Value *timeout = 0); static ssize_t recvfrom (ACE_HANDLE handle, char *buf, @@ -153,107 +135,55 @@ public: int flags, struct sockaddr *addr, int *addrlen, - const ACE_Time_Value *timeout); - // Wait up to <timeout> amount of time to recv up to <len> bytes - // into <buf> from <handle> (uses the <ACE_OS::recvfrom> call). The - // <timeout> indicates how long to blocking trying to recv. If - // <timeout> == 0, the caller will block until action is possible, - // else will wait until the relative time specified in *<timeout> - // elapses). If <recvfrom> times out a -1 is returned with <errno - // == ETIME>. If it succeeds the number of bytes received is - // returned. + const ACE_Time_Value *timeout = 0); static ssize_t recv_n (ACE_HANDLE handle, void *buf, size_t len, int flags, - const ACE_Time_Value *timeout); - // Try to recv exactly <len> bytes into <buf> from <handle> (uses - // the <ACE_OS::recv> call). The <timeout> indicates how long to - // blocking trying to receive. If <timeout> == 0, the caller will - // block until action is possible, else will wait until the relative - // time specified in *<timeout> elapses). If <recv> blocks for - // longer than <timeout> the number of bytes actually read is - // returned with <errno == ETIME>. If a timeout does not occur, - // <recv_n> return <len> (i.e., the number of bytes requested to be - // read). + const ACE_Time_Value *timeout = 0); static ssize_t recv_n (ACE_HANDLE handle, void *buf, size_t len, - const ACE_Time_Value *timeout); - // Try to recv exactly <len> bytes into <buf> from <handle> (uses - // the <ACE_OS::recv> call). The <timeout> indicates how long to - // blocking trying to receive. If <timeout> == 0, the caller will - // block until action is possible, else will wait until the relative - // time specified in *<timeout> elapses). If <recv> blocks for - // longer than <timeout> the number of bytes actually read is - // returned with <errno == ETIME>. If a timeout does not occur, - // <recv_n> return <len> (i.e., the number of bytes requested to be - // read). - - // = Send operations that factor out differences between Win32 and UNIX. - static ssize_t send (ACE_HANDLE handle, - const void *buf, - size_t len, - int flags); - // Send up to <len> bytes into <buf> from <handle> (uses the - // <ACE_OS::send> call). + const ACE_Time_Value *timeout = 0); - static ssize_t send (ACE_HANDLE handle, - const void *buf, - size_t len); - // Send up to <len> bytes into <buf> from <handle> (uses the - // <ACE_OS::write> system call on UNIX and the <ACE_OS::send> call - // on Win32). + static ssize_t recv (ACE_HANDLE handle, size_t n, ...); + // Varargs variant. - // = Send operations that send exactly n bytes. - static ssize_t send_n (ACE_HANDLE handle, - const void *buf, - size_t len, - int flags); - // Send <len> bytes from <buf> to <handle> (uses the <ACE_OS::send> - // system call). If <handle> is set to non-blocking mode this call - // will poll until all <len> bytes are sent. + static ssize_t recvv (ACE_HANDLE handle, + iovec *iov, + int iovcnt, + const ACE_Time_Value *timeout = 0); + + static ssize_t recvv_n (ACE_HANDLE handle, + iovec *iov, + int iovcnt, + const ACE_Time_Value *timeout = 0); + + static ssize_t recv (ACE_HANDLE handle, + ACE_Message_Block *message_block, + const ACE_Time_Value *timeout = 0); + + static ssize_t recv_n (ACE_HANDLE handle, + ACE_Message_Block *message_block, + const ACE_Time_Value *timeout = 0); - // = Timed <send> operations. static ssize_t send (ACE_HANDLE handle, const void *buf, size_t len, - const ACE_Time_Value *timeout); - // Wait up to <timeout> amount of time to send up to <len> bytes - // into <buf> from <handle> (uses the <ACE_OS::write> system call on - // UNIX and the <ACE_OS::send> call on Win32). The <timeout> - // indicates how long to blocking trying to send. If <timeout> == - // 0, the caller will block until action is possible, else will wait - // until the relative time specified in *<timeout> elapses). If - // <send> times out a -1 is returned with <errno == ETIME>. If it - // succeeds the number of bytes sent is returned. + const ACE_Time_Value *timeout = 0); static ssize_t send (ACE_HANDLE handle, const void *buf, size_t len, int flags, - const ACE_Time_Value *timeout); - // Wait up to <timeout> amount of time to send up to <len> bytes - // into <buf> from <handle> (uses the <ACE_OS::send> call). The - // <timeout> indicates how long to blocking trying to send. If - // <timeout> == 0, the caller will block until action is possible, - // else will wait until the relative time specified in *<timeout> - // elapses). If <send> times out a -1 is returned with <errno == - // ETIME>. If it succeeds the number of bytes sent is returned. + const ACE_Time_Value *timeout = 0); static ssize_t sendmsg (ACE_HANDLE handle, const struct msghdr *msg, int flags, - const ACE_Time_Value *timeout); - // Wait up to <timeout> amount of time to send the <msg> to <handle> - // (uses the <ACE_OS::sendmsg> call). The <timeout> indicates how - // long to blocking trying to send. If <timeout> == 0, the caller - // will block until action is possible, else will wait until the - // relative time specified in *<timeout> elapses). If <sendmsg> - // times out a -1 is returned with <errno == ETIME>. If it succeeds - // the number of bytes sent is returned. + const ACE_Time_Value *timeout = 0); static ssize_t sendto (ACE_HANDLE handle, const char *buf, @@ -261,101 +191,41 @@ public: int flags, const struct sockaddr *addr, int addrlen, - const ACE_Time_Value *timeout); - // Wait up to <timeout> amount of time to send up to <len> bytes - // into <buf> from <handle> (uses the <ACE_OS::sendto> call). The - // <timeout> indicates how long to blocking trying to send. If - // <timeout> == 0, the caller will block until action is possible, - // else will wait until the relative time specified in *<timeout> - // elapses). If <sendto> times out a -1 is returned with <errno == - // ETIME>. If it succeeds the number of bytes sent is returned. + const ACE_Time_Value *timeout = 0); static ssize_t send_n (ACE_HANDLE handle, const void *buf, size_t len, int flags, - const ACE_Time_Value *timeout); - // Try to send exactly <len> bytes into <buf> from <handle> (uses - // the <ACE_OS::send> call). The <timeout> indicates how long to - // blocking trying to send. If <timeout> == 0, the caller will - // block until action is possible, else will wait until the relative - // time specified in *<timeout> elapses). If <send> blocks for - // longer than <timeout> the number of bytes actually sent is - // returned with <errno == ETIME>. If a timeout does not occur, - // <send_n> return <len> (i.e., the number of bytes requested to be - // sent). + const ACE_Time_Value *timeout = 0); static ssize_t send_n (ACE_HANDLE handle, const void *buf, size_t len, - const ACE_Time_Value *timeout); - // Try to send exactly <len> bytes into <buf> from <handle> (uses - // the <ACE_OS::send> call). The <timeout> indicates how long to - // blocking trying to send. If <timeout> == 0, the caller will - // block until action is possible, else will wait until the relative - // time specified in *<timeout> elapses). If <send> blocks for - // longer than <timeout> the number of bytes actually sent is - // returned with <errno == ETIME>. If a timeout does not occur, - // <send_n> return <len> (i.e., the number of bytes requested to be - // sent). - - // = Timed Scatter-read and gather-write functions. - - static ssize_t sendv_n (ACE_HANDLE handle, - const iovec *iov, - int iovcnt); - // Send all <iovcnt> <iovec> structs to <handle> (uses the - // <ACE_OS::sendv> call). If it succeeds the number of bytes - // written is returned, else -1 is returned. - - static ssize_t writev (ACE_HANDLE handle, - const iovec *iov, - int iovcnt, const ACE_Time_Value *timeout = 0); - // Send <iovcnt> <iovec> structs to <handle> (uses the - // <ACE_OS::writev> call). If <timeout> == 0, the caller will block - // until action is possible, else will wait until the relative time - // specified in *<timeout> elapses). If <writev> times out a -1 is - // returned with <errno == ETIME>. If it succeeds the number of - // bytes written is returned. - static ssize_t writev_n (ACE_HANDLE handle, - const iovec *iov, - int iovcnt); - // Send all <iovcnt> <iovec> structs to <handle> (uses the - // <ACE_OS::writev> call). If it succeeds the number of bytes - // written is returned, else -1 is returned. + static ssize_t send (ACE_HANDLE handle, size_t n, ...); + // Varargs variant. - static ssize_t readv (ACE_HANDLE handle, - iovec *iov, + static ssize_t sendv (ACE_HANDLE handle, + const iovec *iov, int iovcnt, const ACE_Time_Value *timeout = 0); - // Read <iovcnt> <iovec> structs from <handle> (uses the - // <ACE_OS::readv> call). If <timeout> == 0, the caller will block - // until action is possible, else will wait until the relative time - // specified in *<timeout> elapses). If <readv> times out a -1 is - // returned with <errno == ETIME>. If it succeeds the number of - // bytes receieved is returned. - - static ssize_t send (ACE_HANDLE handle, size_t n, ...); - // Send varargs messages to the <handle> using <writev>. - static ssize_t recv (ACE_HANDLE handle, size_t n, ...); - // Recv varargs messages to the <handle> using <readv>. - - // = File system I/O functions. + static ssize_t sendv_n (ACE_HANDLE handle, + const iovec *iov, + int iovcnt, + const ACE_Time_Value *timeout = 0); - // These encapsulate differences between UNIX and Win32 and also - // send and recv exactly n bytes. The definitions have been moved - // to ACE_OS; these remain for backward compatiblity. + static ssize_t send (ACE_HANDLE handle, + const ACE_Message_Block *message_block, + const ACE_Time_Value *timeout = 0); static ssize_t send_n (ACE_HANDLE handle, - const void *buf, - size_t len); - // Send <len> bytes from <buf> to <handle> (uses the <ACE_OS::write> - // system call on UNIX and the <ACE_OS::recv> call on Win32). If - // <handle> is set to non-blocking mode this call will poll until - // all <len> bytes are sent. + const ACE_Message_Block *message_block, + const ACE_Time_Value *timeout = 0); + + // = File system I/O functions (these don't support timeouts). static ssize_t read_n (ACE_HANDLE handle, void *buf, @@ -365,6 +235,14 @@ public: const void *buf, size_t len); + static ssize_t readv_n (ACE_HANDLE handle, + iovec *iov, + int iovcnt); + + static ssize_t writev_n (ACE_HANDLE handle, + const iovec *iov, + int iovcnt); + // = Socket connection establishment calls. static int bind_port (ACE_HANDLE handle, @@ -680,30 +558,132 @@ public: static char debug (void); static void debug (char d); -private: + static int handle_read_ready (ACE_HANDLE handle, + const ACE_Time_Value *timeout); + // Timed wait for handle to get read ready. + + static int handle_write_ready (ACE_HANDLE handle, + const ACE_Time_Value *timeout); + // Timed wait for handle to get write ready. + + static int handle_exception_ready (ACE_HANDLE handle, + const ACE_Time_Value *timeout); + // Timed wait for handle to get exception ready. + + static int handle_ready (ACE_HANDLE handle, + const ACE_Time_Value *timeout, + int read_ready, + int write_ready, + int exception_ready); + // Timed wait for handle to get read, write, or exception ready. + static int enter_recv_timedwait (ACE_HANDLE handle, const ACE_Time_Value *timeout, int &val); // Wait for <timeout> before proceeding to a <recv> operation. // <val> keeps track of whether we're in non-blocking mode or not. - static void leave_recv_timedwait (ACE_HANDLE handle, - const ACE_Time_Value *timeout, - int val); - // Cleanup after a <recv> operation (e.g., restore the appropriate - // non-blocking status of <handle>). - static int enter_send_timedwait (ACE_HANDLE handle, const ACE_Time_Value* timeout, int &val); // Wait for <timeout> before proceeding to a <send> operation. // <val> keeps track of whether we're in non-blocking mode or not. - static void leave_send_timedwait (ACE_HANDLE handle, - const ACE_Time_Value *timeout, - int val); - // Cleanup after the <send> operation (e.g., restore the appropriate - // non-blocking status of <handle>). + static void record_and_set_non_blocking_mode (ACE_HANDLE handle, + int &val); + // This makes sure that <handle> is set into non-blocking mode. + // <val> keeps track of whether were in non-blocking mode or not. + + static void restore_non_blocking_mode (ACE_HANDLE handle, + int val); + // Cleanup after a timed operation, restore the appropriate + // non-blocking status of <handle>. + +private: + + // + // = Recv_n helpers + // + + static ssize_t recv_i (ACE_HANDLE handle, + void *buf, + size_t len); + + static ssize_t recv_n_i (ACE_HANDLE handle, + void *buf, + size_t len, + int flags); + + static ssize_t recv_n_i (ACE_HANDLE handle, + void *buf, + size_t len, + int flags, + const ACE_Time_Value *timeout); + + static ssize_t recv_n_i (ACE_HANDLE handle, + void *buf, + size_t len); + + static ssize_t recv_n_i (ACE_HANDLE handle, + void *buf, + size_t len, + const ACE_Time_Value *timeout); + + static ssize_t recvv_n_i (ACE_HANDLE handle, + iovec *iov, + int iovcnt); + + static ssize_t recvv_n_i (ACE_HANDLE handle, + iovec *iov, + int iovcnt, + const ACE_Time_Value *timeout); + + static ssize_t recv_i (ACE_HANDLE handle, + ACE_Message_Block *message_block, + const ACE_Time_Value *timeout, + int loop); + + // + // = Send_n helpers + // + + static ssize_t send_i (ACE_HANDLE handle, + const void *buf, + size_t len); + + static ssize_t send_n_i (ACE_HANDLE handle, + const void *buf, + size_t len, + int flags); + + static ssize_t send_n_i (ACE_HANDLE handle, + const void *buf, + size_t len, + int flags, + const ACE_Time_Value *timeout); + + static ssize_t send_n_i (ACE_HANDLE handle, + const void *buf, + size_t len); + + static ssize_t send_n_i (ACE_HANDLE handle, + const void *buf, + size_t len, + const ACE_Time_Value *timeout); + + static ssize_t sendv_n_i (ACE_HANDLE handle, + const iovec *iov, + int iovcnt); + + static ssize_t sendv_n_i (ACE_HANDLE handle, + const iovec *iov, + int iovcnt, + const ACE_Time_Value *timeout); + + static ssize_t send_i (ACE_HANDLE handle, + const ACE_Message_Block *message_block, + const ACE_Time_Value *timeout, + int loop); static u_int init_fini_count_; // Counter to match <init>/<fini> calls. <init> must increment it; diff --git a/ace/ACE.i b/ace/ACE.i index a7f6e541661..8d69ea3a139 100644 --- a/ace/ACE.i +++ b/ace/ACE.i @@ -8,33 +8,20 @@ ACE::read_n (ACE_HANDLE handle, void *buf, size_t len) { - ACE_TRACE ("ACE::read_n"); return ACE_OS::read_n (handle, buf, len); } ASYS_INLINE ssize_t -ACE::send_n (ACE_HANDLE handle, const void *buf, size_t len) -{ - ACE_TRACE ("ACE::send_n"); - return ACE_OS::send_n (handle, buf, len); -} - -ASYS_INLINE ssize_t ACE::write_n (ACE_HANDLE handle, const void *buf, size_t len) { - ACE_TRACE ("ACE::write_n"); return ACE_OS::write_n (handle, buf, len); } -// Miscellaneous static methods used throughout ACE. - ASYS_INLINE ssize_t -ACE::send (ACE_HANDLE handle, const void *buf, size_t len) +ACE::send_i (ACE_HANDLE handle, const void *buf, size_t len) { - ACE_TRACE ("ACE::send"); - #if defined (ACE_WIN32) || defined (ACE_PSOS) return ACE_OS::send (handle, (const char *) buf, len); #else @@ -43,16 +30,8 @@ ACE::send (ACE_HANDLE handle, const void *buf, size_t len) } ASYS_INLINE ssize_t -ACE::send (ACE_HANDLE handle, const void *buf, size_t len, int flags) -{ - ACE_TRACE ("ACE::send"); - return ACE_OS::send (handle, (const char *) buf, len, flags); -} - -ASYS_INLINE ssize_t -ACE::recv (ACE_HANDLE handle, void *buf, size_t len) +ACE::recv_i (ACE_HANDLE handle, void *buf, size_t len) { - ACE_TRACE ("ACE::recv"); #if defined (ACE_WIN32) || defined (ACE_PSOS) return ACE_OS::recv (handle, (char *) buf, len); #else @@ -60,12 +39,37 @@ ACE::recv (ACE_HANDLE handle, void *buf, size_t len) #endif /* ACE_WIN32 */ } -ASYS_INLINE ssize_t -ACE::recv (ACE_HANDLE handle, void *buf, size_t len, int flags) +ASYS_INLINE int +ACE::handle_read_ready (ACE_HANDLE handle, + const ACE_Time_Value *timeout) { - ACE_TRACE ("ACE::recv"); + return ACE::handle_ready (handle, + timeout, + 1, + 0, + 0); +} - return ACE_OS::recv (handle, (char *) buf, len, flags); +ASYS_INLINE int +ACE::handle_write_ready (ACE_HANDLE handle, + const ACE_Time_Value *timeout) +{ + return ACE::handle_ready (handle, + timeout, + 0, + 1, + 0); +} + +ASYS_INLINE int +ACE::handle_exception_ready (ACE_HANDLE handle, + const ACE_Time_Value *timeout) +{ + return ACE::handle_ready (handle, + timeout, + 0, + 0, + 1); } ASYS_INLINE char * diff --git a/ace/Handle_Set.h b/ace/Handle_Set.h index a131eabdd15..79811ebc81f 100644 --- a/ace/Handle_Set.h +++ b/ace/Handle_Set.h @@ -27,7 +27,7 @@ class ACE_Export ACE_Handle_Set { // = TITLE // C++ wrapper facade for the socket <fd_set> abstraction. - // + // // = DESCRIPTION // This abstraction is a very efficient wrapper facade over // <fd_set>. In particular, no range checking is performed, so @@ -85,6 +85,10 @@ public: // Returns a pointer to the underlying <fd_set>. Returns 0 if // <size_> == 0. + fd_set *fdset (void); + // Returns a pointer to the underlying <fd_set>. Returns 0 if + // <size_> == 0. + #if defined (ACE_HAS_BIG_FD_SET) ACE_Handle_Set & operator= (const ACE_Handle_Set &); // Assignment operator optimizes for cases where <size_> == 0. diff --git a/ace/Handle_Set.i b/ace/Handle_Set.i index 2076b8ff622..676731ac0bc 100644 --- a/ace/Handle_Set.i +++ b/ace/Handle_Set.i @@ -13,7 +13,7 @@ ACE_Handle_Set::~ACE_Handle_Set (void) } #endif /* ACE_HAS_WINCE */ -ACE_INLINE void +ACE_INLINE void ACE_Handle_Set::reset (void) { ACE_TRACE ("ACE_Handle_Set::reset"); @@ -55,7 +55,7 @@ ACE_Handle_Set::operator= (const ACE_Handle_Set &rhs) // Returns the number of the large bit. -ACE_INLINE ACE_HANDLE +ACE_INLINE ACE_HANDLE ACE_Handle_Set::max_set (void) const { ACE_TRACE ("ACE_Handle_Set::max_set"); @@ -70,7 +70,7 @@ ACE_Handle_Set::is_set (ACE_HANDLE handle) const ACE_TRACE ("ACE_Handle_Set::is_set"); #if defined (ACE_HAS_BIG_FD_SET) return FD_ISSET (handle, - &this->mask_) + &this->mask_) && this->size_ > 0; #else return FD_ISSET (handle, @@ -80,7 +80,7 @@ ACE_Handle_Set::is_set (ACE_HANDLE handle) const // Enables the handle. -ACE_INLINE void +ACE_INLINE void ACE_Handle_Set::set_bit (ACE_HANDLE handle) { ACE_TRACE ("ACE_Handle_Set::set_bit"); @@ -93,25 +93,25 @@ ACE_Handle_Set::set_bit (ACE_HANDLE handle) #else /* ACE_WIN32 */ #if defined (ACE_HAS_BIG_FD_SET) if (this->size_ == 0) - FD_ZERO (&this->mask_); + FD_ZERO (&this->mask_); if (handle < this->min_handle_) this->min_handle_ = handle; #endif /* ACE_HAS_BIG_FD_SET */ - + FD_SET (handle, &this->mask_); this->size_++; - + if (handle > this->max_handle_) - this->max_handle_ = handle; + this->max_handle_ = handle; #endif /* ACE_WIN32 */ } } // Disables the handle. -ACE_INLINE void +ACE_INLINE void ACE_Handle_Set::clr_bit (ACE_HANDLE handle) { ACE_TRACE ("ACE_Handle_Set::clr_bit"); @@ -121,17 +121,17 @@ ACE_Handle_Set::clr_bit (ACE_HANDLE handle) FD_CLR ((ACE_SOCKET) handle, &this->mask_); this->size_--; - + #if !defined (ACE_WIN32) if (handle == this->max_handle_) - this->set_max (this->max_handle_); + this->set_max (this->max_handle_); #endif /* !ACE_WIN32 */ } } // Returns a count of the number of enabled bits. -ACE_INLINE int +ACE_INLINE int ACE_Handle_Set::num_set (void) const { ACE_TRACE ("ACE_Handle_Set::num_set"); @@ -155,6 +155,19 @@ ACE_Handle_Set::operator fd_set *() return (fd_set *) NULL; } +// Returns a pointer to the underlying fd_set. + +ACE_INLINE fd_set * +ACE_Handle_Set::fdset (void) +{ + ACE_TRACE ("ACE_Handle_Set::operator ACE_FD_SET_TYPE *"); + + if (this->size_ > 0) + return (fd_set *) &this->mask_; + else + return (fd_set *) NULL; +} + ACE_INLINE ACE_Handle_Set_Iterator::~ACE_Handle_Set_Iterator (void) { diff --git a/ace/OS.cpp b/ace/OS.cpp index b43f5826314..f87d1235249 100644 --- a/ace/OS.cpp +++ b/ace/OS.cpp @@ -4254,98 +4254,48 @@ ACE_OS::fork_exec (ASYS_TCHAR *argv[]) # endif /* ACE_WIN32 */ } -// Receive <len> bytes into <buf> from <handle> (uses the <read> -// system call on UNIX and the <ReadFile> call on Win32). - ssize_t ACE_OS::read_n (ACE_HANDLE handle, void *buf, size_t len) { - ACE_TRACE ("ACE_OS::read_n"); - - size_t bytes_read; + size_t bytes_transferred; ssize_t n; - for (bytes_read = 0; bytes_read < len; bytes_read += n) + for (bytes_transferred = 0; + bytes_transferred < len; + bytes_transferred += n) { n = ACE_OS::read (handle, - (char *) buf + bytes_read, - len - bytes_read); - - if (n == -1) - { - if (errno == EWOULDBLOCK) - n = 0; // Keep trying to read. - else - return -1; - } - else if (n == 0) - break; + (char *) buf + bytes_transferred, + len - bytes_transferred); + if (n == -1 || n == 0) + return n; } - return bytes_read; + return bytes_transferred; } ssize_t -ACE_OS::send_n (ACE_HANDLE handle, const void *buf, size_t len) -{ - ACE_TRACE ("ACE_OS::send_n"); - size_t bytes_written; - ssize_t n; - - for (bytes_written = 0; bytes_written < len; bytes_written += n) - { - n = -#if defined (ACE_WIN32) || defined (ACE_PSOS) - ACE_OS::send (handle, - (const char *) buf + bytes_written, - len - bytes_written); -#else - ACE_OS::write (handle, - (const char *) buf + bytes_written, - len - bytes_written); -#endif /* ACE_WIN32 */ - - if (n == -1) - { - if (errno == EWOULDBLOCK) - n = 0; // Keep trying to send. - else - return -1; - } - } - - return bytes_written; -} - -// Write <len> bytes from <buf> to <handle> (uses the <write> -// system call on UNIX and the <WriteFile> call on Win32). - -ssize_t ACE_OS::write_n (ACE_HANDLE handle, const void *buf, size_t len) { - ACE_TRACE ("ACE_OS::write_n"); - - size_t bytes_written; + size_t bytes_transferred; ssize_t n; - for (bytes_written = 0; bytes_written < len; bytes_written += n) + for (bytes_transferred = 0; + bytes_transferred < len; + bytes_transferred += n) { - n = ACE_OS::write (handle, (const char *) buf + bytes_written, - len - bytes_written); - if (n == -1) - { - if (errno == EWOULDBLOCK) - n = 0; // Keep trying to send. - else - return -1; - } + n = ACE_OS::write (handle, + (char *) buf + bytes_transferred, + len - bytes_transferred); + if (n == -1 || n == 0) + return n; } - return bytes_written; + return bytes_transferred; } # if defined (ACE_LACKS_WRITEV) @@ -4386,7 +4336,7 @@ writev (ACE_HANDLE handle, ACE_WRITEV_TYPE iov[], int n) ptr += iov[i].iov_len; } - ssize_t result = ACE_OS::write_n (handle, buf, length); + ssize_t result = ACE_OS::write (handle, buf, length); # if !defined (ACE_HAS_ALLOCA) delete [] buf; # endif /* !defined (ACE_HAS_ALLOCA) */ @@ -4424,7 +4374,7 @@ ACE_TRACE ("readv"); -1); # endif /* !defined (ACE_HAS_ALLOCA) */ - length = ACE_OS::read_n (handle, buf, length); + length = ACE_OS::read (handle, buf, length); if (length != -1) { @@ -6345,11 +6345,8 @@ public: ACE_OVERLAPPED_COMPLETION_FUNC func); static int send (ACE_HANDLE handle, const char *buf, - int len, int - flags = 0); - static ssize_t send_n (ACE_HANDLE handle, - const void *buf, - size_t len); + int len, + int flags = 0); static int sendto (ACE_HANDLE handle, const char *buf, int len, @@ -7141,16 +7138,19 @@ int putchar (int c); # endif /* ACE_HAS_WINCE */ # if defined (ACE_LACKS_TIMEDWAIT_PROTOTYPES) -extern "C" ssize_t send_timedwait (ACE_HANDLE handle, - const char *buf, - int len, - int flags, - struct timespec *timeout); extern "C" ssize_t recv_timedwait (ACE_HANDLE handle, char *buf, int len, int flags, struct timespec *timeout); +extern "C" ssize_t read_timedwait (ACE_HANDLE handle, + char *buf, + size_t n, + struct timespec *timeout); +extern "C" ssize_t recvmsg_timedwait (ACE_HANDLE handle, + struct msghdr *msg, + int flags, + struct timespec *timeout); extern "C" ssize_t recvfrom_timedwait (ACE_HANDLE handle, char *buf, int len, @@ -7159,14 +7159,23 @@ extern "C" ssize_t recvfrom_timedwait (ACE_HANDLE handle, int *addrlen, struct timespec *timeout); -extern "C" ssize_t recvmsg_timedwait (ACE_HANDLE handle, - struct msghdr *msg, +extern "C" ssize_t readv_timedwait (ACE_HANDLE handle, + iovec *iov, + int iovcnt, + struct timespec* timeout); +extern "C" ssize_t send_timedwait (ACE_HANDLE handle, + const char *buf, + int len, + int flags, + struct timespec *timeout); +extern "C" ssize_t write_timedwait (ACE_HANDLE handle, + const void *buf, + size_t n, + struct timespec *timeout); +extern "C" ssize_t sendmsg_timedwait (ACE_HANDLE handle, + ACE_SENDMSG_TYPE *msg, int flags, struct timespec *timeout); -extern "C" ssize_t read_timedwait (ACE_HANDLE handle, - void *buf, - size_t len, - struct timespec *timeout); extern "C" ssize_t sendto_timedwait (ACE_HANDLE handle, const char *buf, int len, @@ -7174,18 +7183,6 @@ extern "C" ssize_t sendto_timedwait (ACE_HANDLE handle, const struct sockaddr *addr, int addrlen, struct timespec *timeout); -extern "C" ssize_t sendmsg_timedwait (ACE_HANDLE handle, - ACE_SENDMSG_TYPE *msg, - int flags, - struct timespec *timeout); -extern "C" ssize_t write_timedwait (ACE_HANDLE handle, - const void *buf, - size_t n, - struct timespec *timeout); -extern "C" ssize_t readv_timedwait (ACE_HANDLE handle, - iovec *iov, - int iovcnt, - struct timespec* timeout); extern "C" ssize_t writev_timedwait (ACE_HANDLE handle, ACE_WRITEV_TYPE *iov, int iovcnt, diff --git a/ace/SOCK_Dgram.cpp b/ace/SOCK_Dgram.cpp index ea499be700d..590e07650b8 100644 --- a/ace/SOCK_Dgram.cpp +++ b/ace/SOCK_Dgram.cpp @@ -26,9 +26,9 @@ ACE_SOCK_Dgram::dump (void) const // returns the number of bytes read. ssize_t -ACE_SOCK_Dgram::recv (iovec io_vec[], - ACE_Addr &addr, - int flags, +ACE_SOCK_Dgram::recv (iovec io_vec[], + ACE_Addr &addr, + int flags, const ACE_Time_Value *timeout) const { ACE_TRACE ("ACE_SOCK_Dgram::recv"); @@ -60,7 +60,7 @@ ACE_SOCK_Dgram::recv (iovec io_vec[], int addr_len = addr.get_size (); u_long inlen; - if (ACE_OS::ioctl (this->get_handle (), + if (ACE_OS::ioctl (this->get_handle (), FIONREAD, (u_long *) &inlen) == -1) return -1; else if (inlen > 0) @@ -69,16 +69,16 @@ ACE_SOCK_Dgram::recv (iovec io_vec[], char[inlen], -1); io_vec->iov_len = ACE_OS::recvfrom (this->get_handle (), - (char *) io_vec->iov_base, - inlen, - flags, - (sockaddr *) saddr, + (char *) io_vec->iov_base, + inlen, + flags, + (sockaddr *) saddr, &addr_len); addr.set_size (addr_len); return io_vec->iov_len; } else - return 0; + return 0; #else ACE_UNUSED_ARG (flags); ACE_UNUSED_ARG (addr); @@ -94,13 +94,13 @@ ACE_SOCK_Dgram::recv (iovec io_vec[], // to a portnumber. int -ACE_SOCK_Dgram::shared_open (const ACE_Addr &local, - int protocol_family) +ACE_SOCK_Dgram::shared_open (const ACE_Addr &local, + int protocol_family) { ACE_TRACE ("ACE_SOCK_Dgram::shared_open"); int error = 0; - if (local == ACE_Addr::sap_any + if (local == ACE_Addr::sap_any && protocol_family == PF_INET) { if (ACE::bind_port (this->get_handle ()) == -1) @@ -119,8 +119,8 @@ ACE_SOCK_Dgram::shared_open (const ACE_Addr &local, } int -ACE_SOCK_Dgram::open (const ACE_Addr &local, - int protocol_family, +ACE_SOCK_Dgram::open (const ACE_Addr &local, + int protocol_family, int protocol, ACE_Protocol_Info *protocolinfo, ACE_SOCK_GROUP g, @@ -128,7 +128,7 @@ ACE_SOCK_Dgram::open (const ACE_Addr &local, int reuse_addr) { if (ACE_SOCK::open (SOCK_DGRAM, - protocol_family, + protocol_family, protocol, protocolinfo, g, @@ -145,14 +145,14 @@ ACE_SOCK_Dgram::open (const ACE_Addr &local, // Here's the general-purpose open routine. int -ACE_SOCK_Dgram::open (const ACE_Addr &local, - int protocol_family, +ACE_SOCK_Dgram::open (const ACE_Addr &local, + int protocol_family, int protocol, int reuse_addr) { ACE_TRACE ("ACE_SOCK_Dgram::open"); if (ACE_SOCK::open (SOCK_DGRAM, - protocol_family, + protocol_family, protocol, reuse_addr) == -1) return -1; @@ -164,8 +164,8 @@ ACE_SOCK_Dgram::open (const ACE_Addr &local, // Here's the general-purpose constructor used by a connectionless // datagram ``server''... -ACE_SOCK_Dgram::ACE_SOCK_Dgram (const ACE_Addr &local, - int protocol_family, +ACE_SOCK_Dgram::ACE_SOCK_Dgram (const ACE_Addr &local, + int protocol_family, int protocol, int reuse_addr) { @@ -180,8 +180,8 @@ ACE_SOCK_Dgram::ACE_SOCK_Dgram (const ACE_Addr &local, ASYS_TEXT ("ACE_SOCK_Dgram"))); } -ACE_SOCK_Dgram::ACE_SOCK_Dgram (const ACE_Addr &local, - int protocol_family, +ACE_SOCK_Dgram::ACE_SOCK_Dgram (const ACE_Addr &local, + int protocol_family, int protocol, ACE_Protocol_Info *protocolinfo, ACE_SOCK_GROUP g, @@ -206,13 +206,13 @@ ACE_SOCK_Dgram::ACE_SOCK_Dgram (const ACE_Addr &local, // version). ssize_t -ACE_SOCK_Dgram::send (const iovec iov[], - size_t n, - const ACE_Addr &addr, +ACE_SOCK_Dgram::send (const iovec iov[], + size_t n, + const ACE_Addr &addr, int flags) const { ACE_TRACE ("ACE_SOCK_Dgram::send"); - msghdr send_msg; + msghdr send_msg; send_msg.msg_iov = (iovec *) iov; send_msg.msg_iovlen = n; @@ -226,7 +226,7 @@ ACE_SOCK_Dgram::send (const iovec iov[], #if defined (ACE_HAS_4_4BSD_SENDMSG_RECVMSG) send_msg.msg_control = 0; send_msg.msg_controllen = 0; - send_msg.msg_flags = 0; + send_msg.msg_flags = 0; #else send_msg.msg_accrights = 0; send_msg.msg_accrightslen = 0; @@ -241,13 +241,13 @@ ACE_SOCK_Dgram::send (const iovec iov[], // version). ssize_t -ACE_SOCK_Dgram::recv (iovec iov[], - size_t n, - ACE_Addr &addr, +ACE_SOCK_Dgram::recv (iovec iov[], + size_t n, + ACE_Addr &addr, int flags) const { ACE_TRACE ("ACE_SOCK_Dgram::recv"); - msghdr recv_msg; + msghdr recv_msg; recv_msg.msg_iov = (iovec *) iov; recv_msg.msg_iovlen = n; @@ -266,7 +266,7 @@ ACE_SOCK_Dgram::recv (iovec iov[], recv_msg.msg_accrightslen = 0; #endif /* ACE_HAS_4_4BSD_SENDMSG_RECVMSG */ - ssize_t status = ACE_OS::recvmsg (this->get_handle (), + ssize_t status = ACE_OS::recvmsg (this->get_handle (), &recv_msg, flags); addr.set_size (recv_msg.msg_namelen); @@ -279,9 +279,9 @@ ACE_SOCK_Dgram::recv (iovec iov[], // version). ssize_t -ACE_SOCK_Dgram::send (const iovec iov[], - size_t n, - const ACE_Addr &addr, +ACE_SOCK_Dgram::send (const iovec iov[], + size_t n, + const ACE_Addr &addr, int flags) const { ACE_TRACE ("ACE_SOCK_Dgram::send"); @@ -304,7 +304,7 @@ ACE_SOCK_Dgram::send (const iovec iov[], #if defined (ACE_HAS_ALLOCA) buf = alloca (length); -#else +#else ACE_NEW_RETURN (buf, char[length], -1); @@ -329,9 +329,9 @@ ACE_SOCK_Dgram::send (const iovec iov[], // version). ssize_t -ACE_SOCK_Dgram::recv (iovec iov[], - size_t n, - ACE_Addr &addr, +ACE_SOCK_Dgram::recv (iovec iov[], + size_t n, + ACE_Addr &addr, int flags) const { ACE_TRACE ("ACE_SOCK_Dgram::recv"); @@ -353,7 +353,7 @@ ACE_SOCK_Dgram::recv (iovec iov[], #if defined (ACE_HAS_ALLOCA) buf = alloca (length); -#else +#else ACE_NEW_RETURN (buf, char[length], -1); @@ -365,19 +365,19 @@ ACE_SOCK_Dgram::recv (iovec iov[], { char *ptr = buf; int copyn = length; - - for (i = 0; - i < n && copyn > 0; - i++) - { - ACE_OS::memcpy (iov[i].iov_base, ptr, + + for (i = 0; + i < n && copyn > 0; + i++) + { + ACE_OS::memcpy (iov[i].iov_base, ptr, // iov_len is int on some platforms, size_t on others - copyn > (int) iov[i].iov_len + copyn > (int) iov[i].iov_len ? (size_t) iov[i].iov_len : (size_t) copyn); - ptr += iov[i].iov_len; - copyn -= iov[i].iov_len; - } + ptr += iov[i].iov_len; + copyn -= iov[i].iov_len; + } } #if !defined (ACE_HAS_ALLOCA) @@ -388,12 +388,12 @@ ACE_SOCK_Dgram::recv (iovec iov[], #endif /* ACE_HAS_MSG */ -ssize_t -ACE_SOCK_Dgram::recv (void *buf, - size_t n, - ACE_Addr &addr, - int flags, - const ACE_Time_Value *timeout) const +ssize_t +ACE_SOCK_Dgram::recv (void *buf, + size_t n, + ACE_Addr &addr, + int flags, + const ACE_Time_Value *timeout) const { ACE_Handle_Set handle_set; handle_set.reset (); @@ -401,9 +401,10 @@ ACE_SOCK_Dgram::recv (void *buf, // Check the status of the current socket. switch (ACE_OS::select (int (this->get_handle ()) + 1, - handle_set, - 0, 0, - timeout)) + handle_set, + 0, + 0, + timeout)) { case -1: return -1; @@ -417,3 +418,34 @@ ACE_SOCK_Dgram::recv (void *buf, return this->recv (buf, n, addr, flags); } } + +ssize_t +ACE_SOCK_Dgram::send (const void *buf, + size_t n, + ACE_Addr &addr, + int flags, + const ACE_Time_Value *timeout) const +{ + ACE_Handle_Set handle_set; + handle_set.reset (); + handle_set.set_bit (this->get_handle ()); + + // Check the status of the current socket. + switch (ACE_OS::select (int (this->get_handle ()) + 1, + 0, + handle_set, + 0, + timeout)) + { + case -1: + return -1; + /* NOTREACHED */ + case 0: + errno = ETIME; + return -1; + /* NOTREACHED */ + default: + // Goes fine, call <send> to get data + return this->send (buf, n, addr, flags); + } +} diff --git a/ace/SOCK_Dgram.h b/ace/SOCK_Dgram.h index 111434a3d7e..af31f35a287 100644 --- a/ace/SOCK_Dgram.h +++ b/ace/SOCK_Dgram.h @@ -126,6 +126,19 @@ public: // returned with <errno == ETIME>. If it succeeds the number of // bytes received is returned. + ssize_t send (const void *buf, + size_t n, + ACE_Addr &addr, + int flags, + const ACE_Time_Value *timeout) const; + // Wait up to <timeout> amount of time to receive a datagram into + // <buf>. The <ACE_Time_Value> indicates how long to blocking + // trying to receive. If <timeout> == 0, the caller will block + // until action is possible, else will wait until the relative time + // specified in *<timeout> elapses). If <send> times out a -1 is + // returned with <errno == ETIME>. If it succeeds the number of + // bytes received is returned. + ssize_t send (const iovec buffers[], int buffer_count, size_t &number_of_bytes_sent, diff --git a/ace/SOCK_IO.cpp b/ace/SOCK_IO.cpp index 2431033c70d..1bac103df6d 100644 --- a/ace/SOCK_IO.cpp +++ b/ace/SOCK_IO.cpp @@ -26,7 +26,7 @@ ACE_SOCK_IO::dump (void) const ssize_t ACE_SOCK_IO::recvv (iovec *io_vec, - const ACE_Time_Value *timeout) + const ACE_Time_Value *timeout) const { ACE_TRACE ("ACE_SOCK_IO::recvv"); #if defined (FIONREAD) @@ -147,8 +147,8 @@ ACE_SOCK_IO::recv (size_t n, ...) const iovp[i].iov_len = va_arg (argp, ssize_t); } - ssize_t result = ACE_OS::recvv (this->get_handle (), - iovp, + ssize_t result = ACE_OS::recvv (this->get_handle (), + iovp, total_tuples); #if !defined (ACE_HAS_ALLOCA) delete [] iovp; diff --git a/ace/SOCK_IO.h b/ace/SOCK_IO.h index d3a29106c8e..f7bb6b7454a 100644 --- a/ace/SOCK_IO.h +++ b/ace/SOCK_IO.h @@ -28,6 +28,27 @@ class ACE_Export ACE_SOCK_IO : public ACE_SOCK // = TITLE // Defines the methods for the ACE socket wrapper I/O routines // (e.g., send/recv). + // + // = NOTES + // + // If <timeout> == 0, then the call behaves as a normal + // send/recv call, i.e., for blocking sockets, the call will + // block until action is possible; for non-blocking sockets, + // EWOULDBLOCK will be returned if no action is immediately + // possible. + // + // If <timeout> != 0, the call will wait until the relative time + // specified in *<timeout> elapses. + // + // Errors are reported by -1 and 0 return values. If the + // operation times out, -1 is returned with <errno == ETIME>. + // If it succeeds the number of bytes transferred is returned. + // + // Methods with the extra <flags> argument will always result in + // <send> getting called. Methods without the extra <flags> + // argument will result in <send> getting called on Win32 + // platforms, and <write> getting called on non-Win32 platforms. + // public: // = Initialization and termination methods. @@ -37,38 +58,29 @@ public: ~ACE_SOCK_IO (void); // Destructor. - ssize_t send (const void *buf, - size_t n, - int flags) const; - // Send an <n> byte buffer to the connected socket (uses - // <send(3n)>). - ssize_t recv (void *buf, size_t n, - int flags) const; - // Recv an <n> byte buffer from the connected socket (uses - // <recv(3n)>). - - ssize_t send (const void *buf, - size_t n) const; - // Send an <n> byte buffer to the connected socket (uses - // <write(2)>). + int flags, + const ACE_Time_Value *timeout = 0) const; + // Recv an <n> byte buffer from the connected socket. ssize_t recv (void *buf, - size_t n) const; - // Recv an <n> byte buffer from the connected socket (uses - // <read(2)>). + size_t n, + const ACE_Time_Value *timeout = 0) const; + // Recv an <n> byte buffer from the connected socket. - ssize_t sendv (const iovec iov[], - size_t n) const; - // Send an <iovec> of size <n> to the connected socket. + ssize_t recvv (iovec iov[], + size_t n, + const ACE_Time_Value *timeout = 0) const; + // Recv an <iovec> of size <n> from the connected socket. - ssize_t send (const iovec iov[], - size_t n) const; + ssize_t recv (iovec iov[], + size_t n, + const ACE_Time_Value *timeout = 0) const; // Same as above. Deprecated. ssize_t recvv (iovec *io_vec, - const ACE_Time_Value *timeout = 0); + const ACE_Time_Value *timeout = 0) const; // Allows a client to read from a socket without having to provide a // buffer to read. This method determines how much data is in the // socket, allocates a buffer of this size, reads in the data, and @@ -77,61 +89,48 @@ public: // delete [] io_vec->iov_base. ssize_t recv (iovec *io_vec, - const ACE_Time_Value *timeout = 0); + const ACE_Time_Value *timeout = 0) const; // Same as above. Deprecated. - ssize_t send (const void *buf, - size_t n, - int flags, - const ACE_Time_Value *timeout) const; - // Wait to to <timeout> amount of time to send up to <n> bytes into - // <buf> from <handle> (uses the <send> call). If <send> times out - // a -1 is returned with <errno == ETIME>. If it succeeds the - // number of bytes sent is returned. + ssize_t recv (size_t n, + ...) const; + // Recv <n> varargs messages to the connected socket. ssize_t recv (void *buf, size_t n, + ACE_OVERLAPPED *overlapped) const; + // Recv <n> bytes via Win32 <ReadFile> using overlapped I/O. + + ssize_t send (const void *buf, + size_t n, int flags, - const ACE_Time_Value *timeout) const; - // Wait up to <timeout> amount of time to receive up to <n> bytes - // into <buf> from <handle> (uses the <recv> call). If <recv> times - // out a -1 is returned with <errno == ETIME>. If it succeeds the - // number of bytes received is returned. + const ACE_Time_Value *timeout = 0) const; + // Send an <n> byte buffer to the connected socket. ssize_t send (const void *buf, size_t n, - const ACE_Time_Value *timeout) const; - // Wait to to <timeout> amount of time to send up to <n> bytes into - // <buf> from <handle> (uses the <send> call). If <send> times out - // a -1 is returned with <errno == ETIME>. If it succeeds the - // number of bytes sent is returned. + const ACE_Time_Value *timeout = 0) const; + // Send an <n> byte buffer to the connected socket. - ssize_t recv (void *buf, + ssize_t sendv (const iovec iov[], + size_t n, + const ACE_Time_Value *timeout = 0) const; + // Send an <iovec> of size <n> to the connected socket. + + ssize_t send (const iovec iov[], size_t n, - const ACE_Time_Value *timeout) const; - // Wait up to <timeout> amount of time to receive up to <n> bytes - // into <buf> from <handle> (uses the <recv> call). If <recv> times - // out a -1 is returned with <errno == ETIME>. If it succeeds the - // number of bytes received is returned. + const ACE_Time_Value *timeout = 0) const; + // Same as above. Deprecated. ssize_t send (size_t n, ...) const; // Send <n> varargs messages to the connected socket. - ssize_t recv (size_t n, - ...) const; - // Recv <n> varargs messages to the connected socket. - ssize_t send (const void *buf, size_t n, ACE_OVERLAPPED *overlapped) const; // Send <n> bytes via Win32 <WriteFile> using overlapped I/O. - ssize_t recv (void *buf, - size_t n, - ACE_OVERLAPPED *overlapped) const; - // Recv <n> bytes via Win32 <ReadFile> using overlapped I/O. - void dump (void) const; // Dump the state of an object. diff --git a/ace/SOCK_IO.i b/ace/SOCK_IO.i index db41f079cd7..d46ca3c188f 100644 --- a/ace/SOCK_IO.i +++ b/ace/SOCK_IO.i @@ -18,87 +18,72 @@ ACE_SOCK_IO::~ACE_SOCK_IO (void) } ASYS_INLINE ssize_t -ACE_SOCK_IO::send (const void *buf, size_t n, int flags) const -{ - ACE_TRACE ("ACE_SOCK_IO::send"); - return ACE_OS::send (this->get_handle (), (const char *) buf, n, flags); -} - -// Recv an n byte message from the connected socket. - -ASYS_INLINE ssize_t -ACE_SOCK_IO::recv (void *buf, size_t n, int flags) const +ACE_SOCK_IO::recv (void *buf, + size_t len, + int flags, + const ACE_Time_Value *timeout) const { ACE_TRACE ("ACE_SOCK_IO::recv"); - return ACE_OS::recv (this->get_handle (), (char *) buf, n, flags); + return ACE::recv (this->get_handle (), + buf, + len, + flags, + timeout); } -// Send an n byte message to the connected socket. - ASYS_INLINE ssize_t -ACE_SOCK_IO::send (const void *buf, size_t n) const -{ - ACE_TRACE ("ACE_SOCK_IO::send"); -#if defined (ACE_WIN32) - return ACE_OS::send (this->get_handle (), (const char *) buf, n, 0); -#else - return ACE_OS::write (this->get_handle (), (const char *) buf, n); -#endif /* ACE_WIN32 */ -} - -// Recv an n byte message from the connected socket. - -ASYS_INLINE ssize_t -ACE_SOCK_IO::recv (void *buf, size_t n) const +ACE_SOCK_IO::recv (void *buf, + size_t len, + const ACE_Time_Value *timeout) const { ACE_TRACE ("ACE_SOCK_IO::recv"); -#if defined (ACE_WIN32) - return ACE_OS::recv (this->get_handle (), (char *) buf, n, 0); -#else - return ACE_OS::read (this->get_handle (), (char *) buf, n); -#endif /* ACE_WIN32 */ + return ACE::recv (this->get_handle (), + buf, + len, + timeout); } -// Send a vector of n byte messages to the connected socket. - ASYS_INLINE ssize_t -ACE_SOCK_IO::sendv (const iovec iov[], size_t n) const +ACE_SOCK_IO::recvv (iovec iov[], + size_t n, + const ACE_Time_Value *timeout) const { - ACE_TRACE ("ACE_SOCK_IO::sendv"); - return ACE_OS::sendv (this->get_handle (), iov, n); + ACE_TRACE ("ACE_SOCK_IO::recvv"); + return ACE::recvv (this->get_handle (), + iov, + n, + timeout); } ASYS_INLINE ssize_t -ACE_SOCK_IO::send (const iovec iov[], size_t n) const +ACE_SOCK_IO::recv (iovec iov[], + size_t n, + const ACE_Time_Value *timeout) const { - ACE_TRACE ("ACE_SOCK_IO::send"); - return this->sendv (iov, n); + ACE_TRACE ("ACE_SOCK_IO::recv"); + return this->recvv (iov, + n, + timeout); } ASYS_INLINE ssize_t ACE_SOCK_IO::recv (iovec *io_vec, - const ACE_Time_Value *timeout) + const ACE_Time_Value *timeout) const { ACE_TRACE ("ACE_SOCK_IO::recv"); - return this->recvv (io_vec, timeout); + return this->recvv (io_vec, + timeout); } ASYS_INLINE ssize_t -ACE_SOCK_IO::send (const void *buf, size_t n, - ACE_OVERLAPPED *overlapped) const -{ - ACE_TRACE ("ACE_SOCK_IO::send"); - return ACE_OS::write (this->get_handle (), - (const char *) buf, n, - overlapped); -} - -ASYS_INLINE ssize_t -ACE_SOCK_IO::recv (void *buf, size_t n, +ACE_SOCK_IO::recv (void *buf, + size_t n, ACE_OVERLAPPED *overlapped) const { ACE_TRACE ("ACE_SOCK_IO::recv"); - return ACE_OS::read (this->get_handle (), (char *) buf, n, + return ACE_OS::read (this->get_handle (), + (char *) buf, + n, overlapped); } @@ -109,33 +94,56 @@ ACE_SOCK_IO::send (const void *buf, const ACE_Time_Value *timeout) const { ACE_TRACE ("ACE_SOCK_IO::send"); - return ACE::send (this->get_handle (), buf, len, flags, timeout); + return ACE::send (this->get_handle (), + buf, + len, + flags, + timeout); } ASYS_INLINE ssize_t -ACE_SOCK_IO::recv (void *buf, +ACE_SOCK_IO::send (const void *buf, size_t len, const ACE_Time_Value *timeout) const { - ACE_TRACE ("ACE_SOCK_IO::recv"); - return ACE::recv (this->get_handle (), buf, len, timeout); + ACE_TRACE ("ACE_SOCK_IO::send"); + return ACE::send (this->get_handle (), + buf, + len, + timeout); } ASYS_INLINE ssize_t -ACE_SOCK_IO::send (const void *buf, - size_t len, +ACE_SOCK_IO::sendv (const iovec iov[], + size_t n, + const ACE_Time_Value *timeout) const +{ + ACE_TRACE ("ACE_SOCK_IO::sendv"); + return ACE::sendv (this->get_handle (), + iov, + n, + timeout); +} + +ASYS_INLINE ssize_t +ACE_SOCK_IO::send (const iovec iov[], + size_t n, const ACE_Time_Value *timeout) const { ACE_TRACE ("ACE_SOCK_IO::send"); - return ACE::send (this->get_handle (), buf, len, timeout); + return this->sendv (iov, + n, + timeout); } ASYS_INLINE ssize_t -ACE_SOCK_IO::recv (void *buf, - size_t len, - int flags, - const ACE_Time_Value *timeout) const +ACE_SOCK_IO::send (const void *buf, + size_t n, + ACE_OVERLAPPED *overlapped) const { - ACE_TRACE ("ACE_SOCK_IO::recv"); - return ACE::recv (this->get_handle (), buf, len, flags, timeout); + ACE_TRACE ("ACE_SOCK_IO::send"); + return ACE_OS::write (this->get_handle (), + (const char *) buf, + n, + overlapped); } diff --git a/ace/SOCK_Stream.h b/ace/SOCK_Stream.h index 1e1982a8ebe..504caf6f73e 100644 --- a/ace/SOCK_Stream.h +++ b/ace/SOCK_Stream.h @@ -33,6 +33,25 @@ class ACE_Export ACE_SOCK_Stream : public ACE_SOCK_IO // = DESCRIPTION // This adds additional wrapper methods atop the <ACE_SOCK_IO> // class. + // + // = NOTES + // + // The "_n" I/O methods keep looping until all the data has been + // transferred. These methods also work for sockets in + // non-blocking mode i.e., they keep looping on EWOULDBLOCK. + // <timeout> is used to make sure we keep making progress, i.e., + // the same timeout value is used for every I/O operation in the + // loop and the timeout is not counted down. If the transfer + // times out, the number of bytes transferred so far are + // returned. + // + // Errors are reported by -1 and 0 return values. + // + // Methods with the extra <flags> argument will always result in + // <send> getting called. Methods without the extra <flags> + // argument will result in <send> getting called on Win32 + // platforms, and <write> getting called on non-Win32 platforms. + // public: // Initialization and termination methods. ACE_SOCK_Stream (void); @@ -44,55 +63,48 @@ public: ~ACE_SOCK_Stream (void); // Destructor. - //= The following two methods use write and read system calls. - ssize_t send_n (const void *buf, int n) const; - // Send n bytes, keep trying until n are sent. - ssize_t recv_n (void *buf, int n) const; - // Recv n bytes, keep trying until n are received. - - // = The following two methods use the send and recv system calls. - ssize_t send_n (const void *buf, int n, int flags) const; - // Send n bytes, keep trying until n are sent. - ssize_t recv_n (void *buf, int n, int flags) const; - // Recv n bytes, keep trying until n are received. + // = I/O functions. - ssize_t send_n (const void *buf, + ssize_t recv_n (void *buf, size_t len, int flags, - const ACE_Time_Value *timeout); - // Try to send exactly <len> bytes into <buf> from <handle> (uses - // the <send> call). If <send> blocks for longer than <timeout> the - // number of bytes actually sent is returned with <errno == ETIME>. - // If a timeout does not occur, <send_n> return <len> (i.e., the - // number of bytes requested to be sent). + const ACE_Time_Value *timeout = 0) const; + // Try to recv exactly <len> bytes into <buf> from <handle>. ssize_t recv_n (void *buf, size_t len, - int flags, - const ACE_Time_Value *timeout); - // Try to recv exactly <len> bytes into <buf> from <handle> (uses - // the <ACE::recv_n> call). The <ACE_Time_Value> indicates how long - // to blocking trying to receive. If <timeout> == 0, the caller - // will block until action is possible, else will wait until the - // relative time specified in *<timeout> elapses). If <recv> blocks - // for longer than <timeout> the number of bytes actually read is - // returned with <errno == ETIME>. If a timeout does not occur, - // <recv_n> return <len> (i.e., the number of bytes requested to be - // read). - - ssize_t sendv_n (const iovec iov[], - size_t n) const; - // Send an <iovec> of size <n> to the connected socket (uses - // <ACE::sendv_n>). Will block until all bytes are sent or an error - // occurs. + const ACE_Time_Value *timeout = 0) const; + // Try to recv exactly <len> bytes into <buf> from <handle>. ssize_t recvv_n (iovec iov[], - size_t n) const; - // Receive an <iovec> of size <n> to the connected socket. + size_t iovcnt, + const ACE_Time_Value *timeout = 0) const; + // Receive an <iovec> of size <iovcnt> to the connected socket. - // = Send/receive an ``urgent'' character (see TCP specs...). - ssize_t send_urg (void *ptr, int len = sizeof (char)); - ssize_t recv_urg (void *ptr, int len = sizeof (char)); + ssize_t send_n (const void *buf, + size_t len, + int flags, + const ACE_Time_Value *timeout = 0) const; + // Try to send exactly <len> bytes into <buf> from <handle>. + + ssize_t send_n (const void *buf, + size_t len, + const ACE_Time_Value *timeout = 0) const; + // Try to send exactly <len> bytes into <buf> from <handle>. + + ssize_t sendv_n (iovec iov[], + size_t iovcnt, + const ACE_Time_Value *timeout = 0) const; + // Send an <iovec> of size <iovcnt> to the connected socket. + + // = Send/receive ``urgent'' data (see TCP specs...). + ssize_t send_urg (const void *ptr, + size_t len = sizeof (char), + const ACE_Time_Value *timeout = 0) const; + + ssize_t recv_urg (void *ptr, + size_t len = sizeof (char), + const ACE_Time_Value *timeout = 0) const; // = Selectively close endpoints. int close_reader (void); diff --git a/ace/SOCK_Stream.i b/ace/SOCK_Stream.i index bef8d5c9c82..cb8b2d5f75e 100644 --- a/ace/SOCK_Stream.i +++ b/ace/SOCK_Stream.i @@ -47,91 +47,103 @@ ACE_SOCK_Stream::close_writer (void) } ASYS_INLINE ssize_t -ACE_SOCK_Stream::send_n (const void *buf, size_t len, int flags, - const ACE_Time_Value *timeout) -{ - ACE_TRACE ("ACE_SOCK_Stream::send_n"); - return ACE::send_n (this->get_handle (), buf, len, flags, timeout); -} - -ASYS_INLINE ssize_t -ACE_SOCK_Stream::recv_n (void *buf, size_t len, int flags, - const ACE_Time_Value *timeout) +ACE_SOCK_Stream::recv_n (void *buf, + size_t len, + int flags, + const ACE_Time_Value *timeout) const { ACE_TRACE ("ACE_SOCK_Stream::recv_n"); - return ACE::recv_n (this->get_handle (), buf, len, flags, timeout); + return ACE::recv_n (this->get_handle (), + buf, + len, + flags, + timeout); } -// Receive exactly BUF_SIZE bytes from file descriptor this->handle -// into <buf>. Keep trying until this many bytes are received. - ASYS_INLINE ssize_t -ACE_SOCK_Stream::recv_n (void *buf, int buf_size, int flags) const +ACE_SOCK_Stream::recv_n (void *buf, + size_t len, + const ACE_Time_Value *timeout) const { ACE_TRACE ("ACE_SOCK_Stream::recv_n"); - return ACE::recv_n (this->get_handle (), buf, buf_size, flags); + return ACE::recv_n (this->get_handle (), + buf, + len, + timeout); } -// Send exactly N bytes from <buf> to <handle>. Keeping trying -// until this many bytes are sent. - ASYS_INLINE ssize_t -ACE_SOCK_Stream::send_n (const void *buf, int buf_size, int flags) const +ACE_SOCK_Stream::recvv_n (iovec iov[], + size_t n, + const ACE_Time_Value *timeout) const { - ACE_TRACE ("ACE_SOCK_Stream::send_n"); - return ACE::send_n (this->get_handle (), buf, buf_size, flags); + ACE_TRACE ("ACE_SOCK_Stream::recvv_n"); + return ACE::recvv_n (this->get_handle (), + iov, + n, + timeout); } -// Receive exactly BUF_SIZE bytes from file descriptor -// into BUF. Keep trying until this many bytes are received. - ASYS_INLINE ssize_t -ACE_SOCK_Stream::recv_n (void *buf, int buf_size) const +ACE_SOCK_Stream::send_n (const void *buf, + size_t len, + int flags, + const ACE_Time_Value *timeout) const { - ACE_TRACE ("ACE_SOCK_Stream::recv_n"); - return ACE::recv_n (this->get_handle (), buf, buf_size); + ACE_TRACE ("ACE_SOCK_Stream::send_n"); + return ACE::send_n (this->get_handle (), + buf, + len, + flags, + timeout); } -// Send exactly N bytes from BUF to THIS->SOK_FD. Keeping trying -// until this many bytes are sent. - ASYS_INLINE ssize_t -ACE_SOCK_Stream::send_n (const void *buf, int buf_size) const +ACE_SOCK_Stream::send_n (const void *buf, + size_t len, + const ACE_Time_Value *timeout) const { ACE_TRACE ("ACE_SOCK_Stream::send_n"); - return ACE::send_n (this->get_handle (), buf, buf_size); + return ACE::send_n (this->get_handle (), + buf, + len, + timeout); } ASYS_INLINE ssize_t -ACE_SOCK_Stream::sendv_n (const iovec iov[], size_t n) const +ACE_SOCK_Stream::sendv_n (iovec iov[], + size_t n, + const ACE_Time_Value *timeout) const { ACE_TRACE ("ACE_SOCK_Stream::sendv_n"); return ACE::sendv_n (this->get_handle (), iov, - n); -} - -// Recv an n byte message from the connected socket. - -ASYS_INLINE ssize_t -ACE_SOCK_Stream::recvv_n (iovec iov[], size_t n) const -{ - ACE_TRACE ("ACE_SOCK_Stream::recvv_n"); - // @@ Carlos, can you please update this to call the - // new ACE::recvv_n() method that you write? - return ACE_OS::recvv (this->get_handle (), iov, n); + n, + timeout); } ASYS_INLINE ssize_t -ACE_SOCK_Stream::send_urg (void *ptr, int len) +ACE_SOCK_Stream::send_urg (const void *ptr, + size_t len, + const ACE_Time_Value *timeout) const { ACE_TRACE ("ACE_SOCK_Stream::send_urg"); - return ACE_OS::send (this->get_handle (), (char *) ptr, len, MSG_OOB); + return ACE::send (this->get_handle (), + ptr, + len, + MSG_OOB, + timeout); } ASYS_INLINE ssize_t -ACE_SOCK_Stream::recv_urg (void *ptr, int len) +ACE_SOCK_Stream::recv_urg (void *ptr, + size_t len, + const ACE_Time_Value *timeout) const { ACE_TRACE ("ACE_SOCK_Stream::recv_urg"); - return ACE_OS::recv (this->get_handle (), (char *) ptr, len, MSG_OOB); + return ACE::recv (this->get_handle (), + ptr, + len, + MSG_OOB, + timeout); } diff --git a/ace/config-win32-common.h b/ace/config-win32-common.h index bf3993e0053..7f34486b674 100644 --- a/ace/config-win32-common.h +++ b/ace/config-win32-common.h @@ -14,6 +14,20 @@ // ---------------- platform features or lack of them ------------- +// +// It seems like Win32 does not have a limit on the number of buffers +// that can be transferred by the scatter/gather type of I/O +// functions, e.g., WSASend and WSARecv. We are arbitrarily setting +// this to be 1k for now. The typically use case is to create an I/O +// vector array of size IOV_MAX on the stack and then filled in. Note +// that we probably don't want too big a value for IOV_MAX since it +// may mostly go to waste or the size of the activation record may +// become excessively large. +// +# if !defined (IOV_MAX) +# define IOV_MAX 1024 +# endif /* IOV_MAX */ + #if !defined (ACE_HAS_WINCE) // Platform supports pread() and pwrite() #define ACE_HAS_P_READ_WRITE @@ -400,11 +414,11 @@ typedef unsigned __int64 ACE_UINT64; #include /**/ <winsock2.h> #endif /* _WINSOCK2API */ - #if defined (ACE_HAS_FORE_ATM_WS2) - #include /**/ <ws2atm.h> - #endif /*ACE_HAS_FORE_ATM_WS2 */ + #if defined (ACE_HAS_FORE_ATM_WS2) + #include /**/ <ws2atm.h> + #endif /*ACE_HAS_FORE_ATM_WS2 */ - #if !defined _MSWSOCK_ + #if !defined _MSWSOCK_ #include /**/ <mswsock.h> #endif /* _MSWSOCK_ */ |