summaryrefslogtreecommitdiff
path: root/ACE/apps/JAWS/clients/Blobby/Blob_Handler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ACE/apps/JAWS/clients/Blobby/Blob_Handler.cpp')
-rw-r--r--ACE/apps/JAWS/clients/Blobby/Blob_Handler.cpp342
1 files changed, 342 insertions, 0 deletions
diff --git a/ACE/apps/JAWS/clients/Blobby/Blob_Handler.cpp b/ACE/apps/JAWS/clients/Blobby/Blob_Handler.cpp
new file mode 100644
index 00000000000..6e01a715908
--- /dev/null
+++ b/ACE/apps/JAWS/clients/Blobby/Blob_Handler.cpp
@@ -0,0 +1,342 @@
+// $Id$
+
+#include "Blob_Handler.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_strings.h"
+
+// Empty constructor for compliance with new Connector behavior.
+ACE_Blob_Handler::ACE_Blob_Handler (void)
+{
+}
+
+// Always use this constructor
+ACE_Blob_Handler::ACE_Blob_Handler (ACE_Message_Block * mb,
+ size_t length,
+ size_t offset,
+ ACE_TCHAR *filename) :
+ mb_ (mb),
+ length_ (length),
+ offset_ (offset),
+ filename_ (ACE_OS::strdup (filename)),
+ bytecount_ (0)
+{
+}
+
+ACE_Blob_Handler::~ACE_Blob_Handler (void)
+{
+ if (filename_)
+ {
+ ACE_OS::free ((void *) filename_);
+ filename_ = 0;
+ }
+}
+
+// Called by Connector after connection is established
+int
+ACE_Blob_Handler::open (void *)
+{
+ if (this->send_request () != 0)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "ACE_Blob_Handler::open():send_request failed"), -1);
+
+ if (this->receive_reply () != 0)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "ACE_Blob_Handler::open():receive_reply failed"), -1);
+ return 0;
+
+}
+
+// No-op
+int
+ACE_Blob_Handler::close (u_long flags)
+{
+ ACE_UNUSED_ARG (flags);
+ return 0;
+}
+
+
+// Always overridden by the derived classes
+int
+ACE_Blob_Handler::send_request (void)
+{
+ return -1;
+}
+
+// Always overridden by the derived classes
+int
+ACE_Blob_Handler::receive_reply (void)
+{
+ return -1;
+}
+
+// used to retrieve the number of bytes read/written by the
+// last operation on the Blob
+int
+ACE_Blob_Handler::byte_count (void)
+{
+ return bytecount_;
+}
+
+// Reader **************************************************
+
+ACE_Blob_Reader::ACE_Blob_Reader (ACE_Message_Block * mb,
+ size_t length,
+ size_t offset,
+ ACE_TCHAR *filename,
+ const char *request_prefix,
+ const char *request_suffix) :
+ ACE_Blob_Handler (mb, length, offset, filename),
+ request_prefix_ (request_prefix),
+ request_suffix_ (request_suffix)
+{
+}
+
+// Send the HTTP request
+int
+ACE_Blob_Reader::send_request (void)
+{
+ char mesg [MAX_HEADER_SIZE];
+
+ // Check to see if the request is too big
+ if (MAX_HEADER_SIZE < (ACE_OS::strlen (request_prefix_)
+ + ACE_OS::strlen (filename_)
+ + ACE_OS::strlen (request_suffix_) + 4))
+ ACE_ERROR_RETURN((LM_ERROR,"Request too large!"), -1);
+
+ // Create a message to send to the server requesting retrieval of the file
+ int len = ACE_OS::sprintf (mesg, "%s %s %s", request_prefix_, filename_, request_suffix_);
+
+ // Send the message to server
+ if (peer ().send_n (mesg, len) != len)
+ ACE_ERROR_RETURN((LM_ERROR,"Error sending request"), -1);
+
+
+ return 0;
+}
+
+// Recieve the HTTP Reply
+int
+ACE_Blob_Reader::receive_reply (void)
+{
+ ssize_t len;
+ char buf [MAX_HEADER_SIZE + 1];
+ char *buf_ptr;
+ size_t bytes_read = 0;
+ size_t bytes_left = this->length_;
+ size_t offset_left = this->offset_;
+
+ // Receive the first MAX_HEADER_SIZE bytes to be able to strip off the
+ // header. Note that we assume that the header will fit into the
+ // first MAX_HEADER_SIZE bytes of the transmitted data.
+ if ((len = peer ().recv_n (buf, MAX_HEADER_SIZE)) >= 0)
+ {
+ buf[len] = '\0';
+
+ // Search for the header termination string "\r\n\r\n", or "\n\n". If
+ // found, move past it to get to the data portion.
+ if ((buf_ptr = ACE_OS::strstr (buf,"\r\n\r\n")) != 0)
+ buf_ptr += 4;
+ else if ((buf_ptr = ACE_OS::strstr (buf, "\n\n")) != 0)
+ buf_ptr += 2;
+ else
+ buf_ptr = buf;
+
+ // Determine number of data bytes read. This is equal to the
+ // total bytes read minus number of header bytes.
+ bytes_read = (buf + len) - buf_ptr;
+ }
+ else
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "ACE_Blob_Reader::receiveReply():Error while reading header"), -1);
+
+ // ***************************************************************
+ // At this point, we have stripped off the header and are ready to
+ // process data. buf_ptr points to the data
+
+ // First adjust for offset. There are two cases:
+ // (1) The first block of data encountered the offset. In this case
+ // we simply increment the buf_ptr by offset.
+ // (2) The first block of data did not encounter the offset. That
+ // is, the offset needs to go past the number of data bytes already read.
+ if (bytes_read > offset_left)
+ {
+ // The first case is true -- that is offset is less than the
+ // data bytes we just read.
+ buf_ptr += offset_left;
+
+ // Determine how many data bytes are actually there. This is
+ // basically the total number of data bytes we read minus any
+ // offset we have.
+ size_t data_bytes = bytes_read - offset_left;
+
+ // Check for the case where the bytes read are enough to fulfill
+ // our request (for length bytes). If this is the case, then we
+ // don't need to do any extra recvs and can simply return with
+ // the data.
+ if (data_bytes >= bytes_left)
+ {
+ // The first block contains enough data to satisfy the
+ // length. So copy the data into the message buffer.
+ if (mb_->copy (buf_ptr, bytes_left) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n",
+ "ACE Blob_Reader::receiveReply():Error copying data into Message_Block"), -1);
+ bytecount_ = length_;
+ return 0;
+ }
+
+ // Copy over all the data bytes into our message buffer.
+ if (mb_->copy (buf_ptr, data_bytes) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n",
+ "ACE_Blob_Reader::receiveReply():Error copying data into Message_Block" ), -1);
+
+ // Adjust bytes left
+ bytes_left -= data_bytes;
+
+ // No more offset left. So set it to zero.
+ offset_left = 0;
+ }
+ else
+ {
+ // The second case is true -- that is offset is greater than
+ // the data bytes we just read.
+ offset_left -= bytes_read;
+ }
+
+ // If we ad any offset left, take care of that.
+ while (offset_left > 0)
+ {
+ // MAX_HEADER_SIZE in which case we should do a receive of
+ // offset bytes into a temporary buffer. Otherwise, we should
+ // receive MAX_HEADER_SIZE bytes into temporary buffer and
+ // decrement offset_left.
+ if (offset_left < (sizeof buf))
+ len = offset_left;
+ else
+ len = sizeof buf;
+ if (peer().recv_n (buf, len) != len)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n",
+ "ACE_Blob_Reader::receiveReply():Read error" ),
+ -1);
+ offset_left -= len;
+ }
+
+ // *****************************************************************
+ // At this point we are all set to receive the actual data which the
+ // user wants. We have made adjustments for offset and are ready to
+ // receive the actual data. Receive the data directly into the
+ // message buffer.
+
+ len = peer().recv_n (mb_->wr_ptr (), bytes_left);
+
+ if (len < 0 || static_cast<size_t> (len) != bytes_left)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n",
+ "ACE_Blob_Reader::receiveReply():Read error" ),
+ -1);
+
+ // Adjust the message buffer write pointer by number of bytes we
+ // received.
+ mb_->wr_ptr (len);
+
+ // Set the byte count to number of bytes received
+ this->bytecount_ = length_;
+
+ return 0;
+}
+
+// Writer **************************************************
+
+ACE_Blob_Writer::ACE_Blob_Writer (ACE_Message_Block * mb,
+ size_t length,
+ size_t offset,
+ ACE_TCHAR *filename,
+ const char *request_prefix,
+ const char *request_suffix) :
+ ACE_Blob_Handler (mb, length, offset, filename),
+ request_prefix_ (request_prefix),
+ request_suffix_ (request_suffix)
+{
+}
+
+int
+ACE_Blob_Writer::send_request (void)
+{
+ // Check for sanity -- check if we have any data to send.
+ if (offset_+ length_ > mb_->length ())
+ ACE_ERROR_RETURN((LM_ERROR, "%p\n",
+ "ACE_Blob_Writer::sendRequest():Invalid offset/length"), -1);
+
+ // Determine the length of the header message we will be sending to
+ // the server. Note that we add 32 for safety -- this corresponds to
+ // the number of bytes needed for the length field.
+ size_t mesglen =
+ ACE_OS::strlen (request_prefix_)
+ + ACE_OS::strlen (filename_)
+ + ACE_OS::strlen (request_suffix_)
+ + 32; // safety
+
+ // Allocate a buffer to hold the header
+ char *mesg = 0;
+ ACE_NEW_RETURN (mesg, char [mesglen], -1);
+
+ // Create the header, store the actual length in mesglen.
+ mesglen = ACE_OS::sprintf (mesg, "%s /%s %s " ACE_SIZE_T_FORMAT_SPECIFIER_ASCII "\n\n",
+ request_prefix_, filename_, request_suffix_, length_);
+
+ // Send the header followed by the data
+
+ // First send the header
+ if (peer ().send_n (mesg, mesglen) == -1)
+ ACE_ERROR_RETURN((LM_ERROR, "%p\n", "Error sending request"), -1);
+
+ // "Consume" the offset by moving the read pointer of the message
+ // buffer
+ mb_->rd_ptr (offset_);
+
+ // Now send the data
+ if (peer ().send_n (mb_->rd_ptr (), length_) != (int)length_)
+ ACE_ERROR_RETURN((LM_ERROR, "%p\n", "Error sending file"), -1);
+
+ // Adjust the read pointer of the mesage buffer
+ mb_->rd_ptr (length_);
+
+ return 0;
+}
+
+int
+ACE_Blob_Writer::receive_reply (void)
+{
+ // Allocate a buffer big enough to hold the header
+ char buf[MAX_HEADER_SIZE];
+
+ // Receive the reply from the server
+ size_t num_recvd = 0;
+ ssize_t len = peer ().recv_n (buf, sizeof buf - 1, 0, &num_recvd); // reserve one byte to store the \0
+ if (len ==-1)
+ ACE_ERROR_RETURN((LM_ERROR, "%p\n", "Error reading header"), -1);
+
+ buf [num_recvd] = 0;
+
+ // Parse the header
+ char *lasts = 0;
+
+ // First check if this was a valid header -- HTTP/1.0
+ char *token = ACE_OS::strtok_r (buf, " \t", &lasts);
+
+ if ( (token == 0) || (ACE_OS::strcasecmp (token, "HTTP/1.0") != 0))
+ ACE_ERROR_RETURN((LM_ERROR, "%p\n", "Did not receive a HTTP/1.0 response"), -1);
+
+ // Get the return code.
+ int return_code = ACE_OS::atoi (ACE_OS::strtok_r (0, " \t", &lasts));
+
+ // Check if the transaction succeeded. The only success codes are in
+ // the range of 200-299 (HTTP specification).
+ if (return_code >= 200 && return_code < 300)
+ return 0;
+ else
+ {
+ // Something went wrong!
+ // Get the description from the header message of what went wrong.
+ char *description = ACE_OS::strtok_r (0, "\n\r", &lasts);
+ ACE_ERROR_RETURN((LM_ERROR, "%p\n", description), -1);
+ }
+ ACE_NOTREACHED(return 0);
+}
+