summaryrefslogtreecommitdiff
path: root/ACE/apps/JAWS/server/JAWS_IO.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ACE/apps/JAWS/server/JAWS_IO.cpp')
-rw-r--r--ACE/apps/JAWS/server/JAWS_IO.cpp558
1 files changed, 558 insertions, 0 deletions
diff --git a/ACE/apps/JAWS/server/JAWS_IO.cpp b/ACE/apps/JAWS/server/JAWS_IO.cpp
new file mode 100644
index 00000000000..8a6f12acce5
--- /dev/null
+++ b/ACE/apps/JAWS/server/JAWS_IO.cpp
@@ -0,0 +1,558 @@
+// $Id$
+
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_sys_uio.h"
+#include "ace/OS_NS_sys_socket.h"
+#include "ace/Message_Block.h"
+#include "ace/Min_Max.h"
+#include "ace/SOCK_Stream.h"
+#include "ace/Filecache.h"
+#include "JAWS_IO.h"
+#include "HTTP_Helpers.h"
+
+#include "ace/OS_NS_fcntl.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_sys_stat.h"
+#include "ace/Auto_Ptr.h"
+#include "ace/Basic_Types.h"
+
+JAWS_IO::JAWS_IO (void)
+ : handler_ (0)
+{
+}
+
+JAWS_IO::~JAWS_IO (void)
+{
+}
+
+void
+JAWS_IO::handler (JAWS_IO_Handler *handler)
+{
+ this->handler_ = handler;
+}
+
+JAWS_IO_Handler::~JAWS_IO_Handler (void)
+{
+}
+
+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 (ACE_TEXT_CHAR_TO_TCHAR (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 (ACE_TEXT_CHAR_TO_TCHAR (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 = const_cast<char*> (header);
+ iov[iovcnt].iov_len = header_size;
+ iovcnt++;
+ }
+ if (handle.size () > 0)
+ {
+ iov[iovcnt].iov_base = reinterpret_cast<char*> (handle.address ());
+ iov[iovcnt].iov_len = handle.size ();
+ iovcnt++;
+ }
+ if (trailer_size > 0)
+ {
+ iov[iovcnt].iov_base = 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_HAS_WIN32_OVERLAPPED_IO)
+
+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 = 0;
+ 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 *) static_cast<intptr_t> (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_HAS_WIN32_OVERLAPPED_IO */
+
+//-------------------Adding SYNCH IO no Caching
+
+JAWS_Synch_IO_No_Cache::JAWS_Synch_IO_No_Cache (void)
+ : handle_ (ACE_INVALID_HANDLE)
+{
+}
+
+JAWS_Synch_IO_No_Cache::~JAWS_Synch_IO_No_Cache (void)
+{
+ ACE_OS::closesocket (this->handle_);
+}
+
+ACE_HANDLE
+JAWS_Synch_IO_No_Cache::handle (void) const
+{
+ return this->handle_;
+}
+
+void
+JAWS_Synch_IO_No_Cache::handle (ACE_HANDLE handle)
+{
+ this->handle_ = handle;
+}
+
+void
+JAWS_Synch_IO_No_Cache::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_No_Cache::receive_file (const char *,
+ void *,
+ int,
+ int)
+{
+ //ugly hack to send HTTP_Status_Code::STATUS_FORBIDDEN
+ this->handler_->receive_file_error (5);
+}
+
+void
+JAWS_Synch_IO_No_Cache::transmit_file (const char *filename,
+ const char *header,
+ int header_size,
+ const char *trailer,
+ int trailer_size)
+{
+ int result = 0;
+
+ // Can we access the file?
+ if (ACE_OS::access (filename, R_OK) == -1)
+ {
+ //ugly hack to send in HTTP_Status_Code::STATUS_NOT_FOUND
+ result = ACE_Filecache_Handle::ACE_ACCESS_FAILED;
+ this->handler_->transmit_file_error (result);
+ return;
+ }
+
+ ACE_stat stat;
+
+ // Can we stat the file?
+ if (ACE_OS::stat (filename, &stat) == -1)
+ {
+ //ugly hack to send HTTP_Status_Code::STATUS_FORBIDDEN
+ result = ACE_Filecache_Handle::ACE_STAT_FAILED;
+ this->handler_->transmit_file_error (result);
+ return;
+ }
+
+ ACE_OFF_T size = stat.st_size;
+
+ // Can we open the file?
+ ACE_HANDLE handle = ACE_OS::open (filename, O_RDONLY);
+ if (handle == ACE_INVALID_HANDLE)
+ {
+ //ugly hack to send HTTP_Status_Code::STATUS_FORBIDDEN
+ result = ACE_Filecache_Handle::ACE_OPEN_FAILED;
+ this->handler_->transmit_file_error (result);
+ return;
+ }
+
+ char* f = new char[size];
+ ACE_Auto_Basic_Array_Ptr<char> file (f);
+
+ ACE_OS::read_n (handle, f, size);
+
+ ACE_SOCK_Stream stream;
+ stream.set_handle (this->handle_);
+
+ if ((stream.send_n (header, header_size) == header_size)
+ && (stream.send_n (f, size) == size)
+ && (stream.send_n (trailer, trailer_size) == trailer_size))
+ {
+ this->handler_->transmit_file_complete ();
+ }
+ else
+ {
+ //ugly hack to default to HTTP_Status_Code::STATUS_INTERNAL_SERVER_ERROR
+ result = -1;
+ this->handler_->transmit_file_error (result);
+ }
+
+ ACE_OS::close (handle);
+}
+
+void
+JAWS_Synch_IO_No_Cache::send_confirmation_message (const char *buffer,
+ int length)
+{
+ this->send_message (buffer, length);
+ this->handler_->confirmation_message_complete ();
+}
+
+void
+JAWS_Synch_IO_No_Cache::send_error_message (const char *buffer, int length)
+{
+ this->send_message (buffer, length);
+ this->handler_->error_message_complete ();
+}
+
+void
+JAWS_Synch_IO_No_Cache::send_message (const char *buffer, int length)
+{
+ ACE_SOCK_Stream stream;
+ stream.set_handle (this->handle_);
+ stream.send_n (buffer, length);
+}
+