// $Id$ #include "ace/Message_Block.h" #include "ace/SOCK_Stream.h" #include "ace/Filecache.h" #include "IO.h" #include "HTTP_Helpers.h" #include "ace/OS_NS_sys_uio.h" #include "ace/OS_NS_sys_socket.h" ACE_RCSID(server, IO, "$Id$") JAWS_IO::JAWS_IO (void) : handler_ (0) { } JAWS_IO::~JAWS_IO (void) { } void JAWS_IO::handler (JAWS_IO_Handler *handler) { this->handler_ = handler; } JAWS_Synch_IO::JAWS_Synch_IO (void) : handle_ (ACE_INVALID_HANDLE) { } JAWS_Synch_IO::~JAWS_Synch_IO (void) { ACE_OS::closesocket (this->handle_); } ACE_HANDLE JAWS_Synch_IO::handle (void) const { return this->handle_; } void JAWS_Synch_IO::handle (ACE_HANDLE handle) { this->handle_ = handle; } void JAWS_Synch_IO::read (ACE_Message_Block &mb, int size) { ACE_SOCK_Stream stream; stream.set_handle (this->handle_); int result = stream.recv (mb.wr_ptr (), size); if (result <= 0) this->handler_->read_error (); else { mb.wr_ptr (result); this->handler_->read_complete (mb); } } void JAWS_Synch_IO::receive_file (const char *filename, void *initial_data, int initial_data_length, int entire_length) { ACE_Filecache_Handle handle (filename, entire_length); int result = handle.error (); if (result == ACE_Filecache_Handle::ACE_SUCCESS) { ACE_SOCK_Stream stream; stream.set_handle (this->handle_); int bytes_to_memcpy = ACE_MIN (entire_length, initial_data_length); ACE_OS::memcpy (handle.address (), initial_data, bytes_to_memcpy); int bytes_to_read = entire_length - bytes_to_memcpy; int bytes = stream.recv_n ((char *) handle.address () + initial_data_length, bytes_to_read); if (bytes == bytes_to_read) this->handler_->receive_file_complete (); else result = -1; } if (result != ACE_Filecache_Handle::ACE_SUCCESS) this->handler_->receive_file_error (result); } void JAWS_Synch_IO::transmit_file (const char *filename, const char *header, int header_size, const char *trailer, int trailer_size) { ACE_Filecache_Handle handle (filename); int result = handle.error (); if (result == ACE_Filecache_Handle::ACE_SUCCESS) { #if defined (ACE_JAWS_BASELINE) || defined (ACE_WIN32) ACE_SOCK_Stream stream; stream.set_handle (this->handle_); if ((stream.send_n (header, header_size) == header_size) && (stream.send_n (handle.address (), handle.size ()) == handle.size ()) && (stream.send_n (trailer, trailer_size) == trailer_size)) this->handler_->transmit_file_complete (); else result = -1; #else // Attempting to use writev // Is this faster? iovec iov[3]; int iovcnt = 0; if (header_size > 0) { iov[iovcnt].iov_base = ACE_const_cast(char*, header); iov[iovcnt].iov_len = header_size; iovcnt++; } if (handle.size () > 0) { iov[iovcnt].iov_base = ACE_reinterpret_cast(char*,handle.address ()); iov[iovcnt].iov_len = handle.size (); iovcnt++; } if (trailer_size > 0) { iov[iovcnt].iov_base = ACE_const_cast(char*, trailer); iov[iovcnt].iov_len = trailer_size; iovcnt++; } if (ACE_OS::writev (this->handle_, iov, iovcnt) < 0) result = -1; else this->handler_->transmit_file_complete (); #endif /* ACE_JAWS_BASELINE */ } if (result != ACE_Filecache_Handle::ACE_SUCCESS) this->handler_->transmit_file_error (result); } void JAWS_Synch_IO::send_confirmation_message (const char *buffer, int length) { this->send_message (buffer, length); this->handler_->confirmation_message_complete (); } void JAWS_Synch_IO::send_error_message (const char *buffer, int length) { this->send_message (buffer, length); this->handler_->error_message_complete (); } void JAWS_Synch_IO::send_message (const char *buffer, int length) { ACE_SOCK_Stream stream; stream.set_handle (this->handle_); stream.send_n (buffer, length); } // This only works on Win32 #if defined (ACE_WIN32) JAWS_Asynch_IO::JAWS_Asynch_IO (void) { } JAWS_Asynch_IO::~JAWS_Asynch_IO (void) { ACE_OS::closesocket (this->handle_); } void JAWS_Asynch_IO::read (ACE_Message_Block& mb, int size) { ACE_Asynch_Read_Stream ar; if (ar.open (*this, this->handle_) == -1 || ar.read (mb, size) == -1) this->handler_->read_error (); } // This method will be called when an asynchronous read completes on a // stream. void JAWS_Asynch_IO::handle_read_stream (const ACE_Asynch_Read_Stream::Result &result) { // This callback is for this->receive_file() if (result.act () != 0) { int code = 0; if (result.success () && result.bytes_transferred () != 0) { if (result.message_block ().length () == result.message_block ().size ()) code = ACE_Filecache_Handle::ACE_SUCCESS; else { ACE_Asynch_Read_Stream ar; if (ar.open (*this, this->handle_) == -1 || ar.read (result.message_block (), result.message_block ().size () - result.message_block ().length (), result.act ()) == -1) code = -1; else return; } } else code = -1; if (code == ACE_Filecache_Handle::ACE_SUCCESS) this->handler_->receive_file_complete (); else this->handler_->receive_file_error (code); delete &result.message_block (); delete (ACE_Filecache_Handle *) result.act (); } else { // This callback is for this->read() if (result.success () && result.bytes_transferred () != 0) this->handler_->read_complete (result.message_block ()); else this->handler_->read_error (); } } void JAWS_Asynch_IO::receive_file (const char *filename, void *initial_data, int initial_data_length, int entire_length) { ACE_Message_Block *mb = 0; ACE_Filecache_Handle *handle; ACE_NEW (handle, ACE_Filecache_Handle (filename, entire_length, ACE_NOMAP)); int result = handle->error (); if (result == ACE_Filecache_Handle::ACE_SUCCESS) { ACE_OS::memcpy (handle->address (), initial_data, initial_data_length); int bytes_to_read = entire_length - initial_data_length; ACE_NEW (mb, ACE_Message_Block ((char *)handle->address () + initial_data_length, bytes_to_read)); if (mb == 0) { errno = ENOMEM; result = -1; } else { ACE_Asynch_Read_Stream ar; if (ar.open (*this, this->handle_) == -1 || ar.read (*mb, mb->size () - mb->length (), handle) == -1) result = -1; } } if (result != ACE_Filecache_Handle::ACE_SUCCESS) { this->handler_->receive_file_error (result); delete mb; delete handle; } } void JAWS_Asynch_IO::transmit_file (const char *filename, const char *header, int header_size, const char *trailer, int trailer_size) { ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer = 0; ACE_Filecache_Handle *handle = new ACE_Filecache_Handle (filename, ACE_NOMAP); int result = handle->error (); if (result == ACE_Filecache_Handle::ACE_SUCCESS) { ACE_Message_Block header_mb (header, header_size); ACE_Message_Block trailer_mb (trailer, trailer_size); header_and_trailer = new ACE_Asynch_Transmit_File::Header_And_Trailer (&header_mb, header_size, &trailer_mb, trailer_size); ACE_Asynch_Transmit_File tf; if (tf.open (*this, this->handle_) == -1 || tf.transmit_file (handle->handle (), // file handle header_and_trailer, // header and trailer data 0, // bytes_to_write 0, // offset 0, // offset_high 0, // bytes_per_send 0, // flags handle // act ) == -1) result = -1; } if (result != ACE_Filecache_Handle::ACE_SUCCESS) { this->handler_->transmit_file_error (result); delete header_and_trailer; delete handle; } } // This method will be called when an asynchronous transmit file completes. void JAWS_Asynch_IO::handle_transmit_file (const ACE_Asynch_Transmit_File::Result &result) { if (result.success ()) this->handler_->transmit_file_complete (); else this->handler_->transmit_file_error (-1); delete result.header_and_trailer (); delete (ACE_Filecache_Handle *) result.act (); } void JAWS_Asynch_IO::send_confirmation_message (const char *buffer, int length) { this->send_message (buffer, length, CONFORMATION); } void JAWS_Asynch_IO::send_error_message (const char *buffer, int length) { this->send_message (buffer, length, ERROR_MESSAGE); } void JAWS_Asynch_IO::send_message (const char *buffer, int length, int act) { ACE_Message_Block *mb; ACE_NEW (mb, ACE_Message_Block (buffer, length)); if (mb == 0) { this->handler_->error_message_complete (); return; } ACE_Asynch_Write_Stream aw; if (aw.open (*this, this->handle_) == -1 || aw.write (*mb, length, (void *) act) == -1) { mb->release (); if (act == CONFORMATION) this->handler_->confirmation_message_complete (); else this->handler_->error_message_complete (); } } void JAWS_Asynch_IO::handle_write_stream (const ACE_Asynch_Write_Stream::Result &result) { result.message_block ().release (); if (result.act () == (void *) CONFORMATION) this->handler_->confirmation_message_complete (); else this->handler_->error_message_complete (); } #endif /* ACE_WIN32 */ // #if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) // template class ACE_Singleton; // #elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) // #pragma instantiate ACE_Singleton // #endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */