1 #include "Blob_Handler.h"
2 #include "ace/OS_NS_stdio.h"
3 #include "ace/OS_NS_string.h"
4 #include "ace/OS_NS_strings.h"
6 // Empty constructor for compliance with new Connector behavior.
7 ACE_Blob_Handler::ACE_Blob_Handler ()
11 // Always use this constructor
12 ACE_Blob_Handler::ACE_Blob_Handler (ACE_Message_Block
* mb
,
15 ACE_TCHAR
*filename
) :
19 filename_ (ACE_OS::strdup (filename
)),
24 ACE_Blob_Handler::~ACE_Blob_Handler ()
28 ACE_OS::free ((void *) filename_
);
33 // Called by Connector after connection is established
35 ACE_Blob_Handler::open (void *)
37 if (this->send_request () != 0)
38 ACE_ERROR_RETURN ((LM_ERROR
, "%p\n", "ACE_Blob_Handler::open():send_request failed"), -1);
40 if (this->receive_reply () != 0)
41 ACE_ERROR_RETURN ((LM_ERROR
, "%p\n", "ACE_Blob_Handler::open():receive_reply failed"), -1);
47 ACE_Blob_Handler::close (u_long flags
)
49 ACE_UNUSED_ARG (flags
);
54 // Always overridden by the derived classes
56 ACE_Blob_Handler::send_request ()
61 // Always overridden by the derived classes
63 ACE_Blob_Handler::receive_reply ()
68 // used to retrieve the number of bytes read/written by the
69 // last operation on the Blob
71 ACE_Blob_Handler::byte_count ()
76 // Reader **************************************************
78 ACE_Blob_Reader::ACE_Blob_Reader (ACE_Message_Block
* mb
,
82 const char *request_prefix
,
83 const char *request_suffix
) :
84 ACE_Blob_Handler (mb
, length
, offset
, filename
),
85 request_prefix_ (request_prefix
),
86 request_suffix_ (request_suffix
)
90 // Send the HTTP request
92 ACE_Blob_Reader::send_request ()
94 char mesg
[MAX_HEADER_SIZE
];
96 // Check to see if the request is too big
97 if (MAX_HEADER_SIZE
< (ACE_OS::strlen (request_prefix_
)
98 + ACE_OS::strlen (filename_
)
99 + ACE_OS::strlen (request_suffix_
) + 4))
100 ACE_ERROR_RETURN((LM_ERROR
,"Request too large!"), -1);
102 // Create a message to send to the server requesting retrieval of the file
103 int len
= ACE_OS::sprintf (mesg
, "%s %s %s",
105 ACE_TEXT_ALWAYS_CHAR (filename_
),
108 // Send the message to server
109 if (peer ().send_n (mesg
, len
) != len
)
110 ACE_ERROR_RETURN((LM_ERROR
,"Error sending request"), -1);
116 // Recieve the HTTP Reply
118 ACE_Blob_Reader::receive_reply ()
121 char buf
[MAX_HEADER_SIZE
+ 1];
123 size_t bytes_read
= 0;
124 size_t bytes_left
= this->length_
;
125 size_t offset_left
= this->offset_
;
127 // Receive the first MAX_HEADER_SIZE bytes to be able to strip off the
128 // header. Note that we assume that the header will fit into the
129 // first MAX_HEADER_SIZE bytes of the transmitted data.
130 if ((len
= peer ().recv_n (buf
, MAX_HEADER_SIZE
)) >= 0)
134 // Search for the header termination string "\r\n\r\n", or "\n\n". If
135 // found, move past it to get to the data portion.
136 if ((buf_ptr
= ACE_OS::strstr (buf
,"\r\n\r\n")) != 0)
138 else if ((buf_ptr
= ACE_OS::strstr (buf
, "\n\n")) != 0)
143 // Determine number of data bytes read. This is equal to the
144 // total bytes read minus number of header bytes.
145 bytes_read
= (buf
+ len
) - buf_ptr
;
148 ACE_ERROR_RETURN ((LM_ERROR
, "%p\n", "ACE_Blob_Reader::receiveReply():Error while reading header"), -1);
150 // ***************************************************************
151 // At this point, we have stripped off the header and are ready to
152 // process data. buf_ptr points to the data
154 // First adjust for offset. There are two cases:
155 // (1) The first block of data encountered the offset. In this case
156 // we simply increment the buf_ptr by offset.
157 // (2) The first block of data did not encounter the offset. That
158 // is, the offset needs to go past the number of data bytes already read.
159 if (bytes_read
> offset_left
)
161 // The first case is true -- that is offset is less than the
162 // data bytes we just read.
163 buf_ptr
+= offset_left
;
165 // Determine how many data bytes are actually there. This is
166 // basically the total number of data bytes we read minus any
168 size_t data_bytes
= bytes_read
- offset_left
;
170 // Check for the case where the bytes read are enough to fulfill
171 // our request (for length bytes). If this is the case, then we
172 // don't need to do any extra recvs and can simply return with
174 if (data_bytes
>= bytes_left
)
176 // The first block contains enough data to satisfy the
177 // length. So copy the data into the message buffer.
178 if (mb_
->copy (buf_ptr
, bytes_left
) == -1)
179 ACE_ERROR_RETURN ((LM_ERROR
, "%p\n",
180 "ACE Blob_Reader::receiveReply():Error copying data into Message_Block"), -1);
181 bytecount_
= length_
;
185 // Copy over all the data bytes into our message buffer.
186 if (mb_
->copy (buf_ptr
, data_bytes
) == -1)
187 ACE_ERROR_RETURN ((LM_ERROR
, "%p\n",
188 "ACE_Blob_Reader::receiveReply():Error copying data into Message_Block" ), -1);
191 bytes_left
-= data_bytes
;
193 // No more offset left. So set it to zero.
198 // The second case is true -- that is offset is greater than
199 // the data bytes we just read.
200 offset_left
-= bytes_read
;
203 // If we ad any offset left, take care of that.
204 while (offset_left
> 0)
206 // MAX_HEADER_SIZE in which case we should do a receive of
207 // offset bytes into a temporary buffer. Otherwise, we should
208 // receive MAX_HEADER_SIZE bytes into temporary buffer and
209 // decrement offset_left.
210 if (offset_left
< (sizeof buf
))
214 if (peer().recv_n (buf
, len
) != len
)
215 ACE_ERROR_RETURN ((LM_ERROR
, "%p\n",
216 "ACE_Blob_Reader::receiveReply():Read error" ),
221 // *****************************************************************
222 // At this point we are all set to receive the actual data which the
223 // user wants. We have made adjustments for offset and are ready to
224 // receive the actual data. Receive the data directly into the
227 len
= peer().recv_n (mb_
->wr_ptr (), bytes_left
);
229 if (len
< 0 || static_cast<size_t> (len
) != bytes_left
)
230 ACE_ERROR_RETURN ((LM_ERROR
, "%p\n",
231 "ACE_Blob_Reader::receiveReply():Read error" ),
234 // Adjust the message buffer write pointer by number of bytes we
238 // Set the byte count to number of bytes received
239 this->bytecount_
= length_
;
244 // Writer **************************************************
246 ACE_Blob_Writer::ACE_Blob_Writer (ACE_Message_Block
* mb
,
250 const char *request_prefix
,
251 const char *request_suffix
) :
252 ACE_Blob_Handler (mb
, length
, offset
, filename
),
253 request_prefix_ (request_prefix
),
254 request_suffix_ (request_suffix
)
259 ACE_Blob_Writer::send_request ()
261 // Check for sanity -- check if we have any data to send.
262 if (offset_
+ length_
> mb_
->length ())
263 ACE_ERROR_RETURN((LM_ERROR
, "%p\n",
264 "ACE_Blob_Writer::sendRequest():Invalid offset/length"), -1);
266 // Determine the length of the header message we will be sending to
267 // the server. Note that we add 32 for safety -- this corresponds to
268 // the number of bytes needed for the length field.
270 ACE_OS::strlen (request_prefix_
)
271 + ACE_OS::strlen (filename_
)
272 + ACE_OS::strlen (request_suffix_
)
275 // Allocate a buffer to hold the header
277 ACE_NEW_RETURN (mesg
, char [mesglen
], -1);
279 // Create the header, store the actual length in mesglen.
280 mesglen
= ACE_OS::sprintf (mesg
, "%s /%s %s " ACE_SIZE_T_FORMAT_SPECIFIER_ASCII
"\n\n",
281 request_prefix_
, ACE_TEXT_ALWAYS_CHAR (filename_
),
282 request_suffix_
, length_
);
284 // Send the header followed by the data
286 // First send the header
287 if (peer ().send_n (mesg
, mesglen
) == -1)
288 ACE_ERROR_RETURN((LM_ERROR
, "%p\n", "Error sending request"), -1);
290 // "Consume" the offset by moving the read pointer of the message
292 mb_
->rd_ptr (offset_
);
295 if (peer ().send_n (mb_
->rd_ptr (), length_
) != (int)length_
)
296 ACE_ERROR_RETURN((LM_ERROR
, "%p\n", "Error sending file"), -1);
298 // Adjust the read pointer of the mesage buffer
299 mb_
->rd_ptr (length_
);
305 ACE_Blob_Writer::receive_reply ()
307 // Allocate a buffer big enough to hold the header
308 char buf
[MAX_HEADER_SIZE
];
310 // Receive the reply from the server
311 size_t num_recvd
= 0;
312 ssize_t len
= peer ().recv_n (buf
, sizeof buf
- 1, 0, &num_recvd
); // reserve one byte to store the \0
314 ACE_ERROR_RETURN((LM_ERROR
, "%p\n", "Error reading header"), -1);
321 // First check if this was a valid header -- HTTP/1.0
322 char *token
= ACE_OS::strtok_r (buf
, " \t", &lasts
);
324 if ( (token
== 0) || (ACE_OS::strcasecmp (token
, "HTTP/1.0") != 0))
325 ACE_ERROR_RETURN((LM_ERROR
, "%p\n", "Did not receive a HTTP/1.0 response"), -1);
327 // Get the return code.
328 int return_code
= ACE_OS::atoi (ACE_OS::strtok_r (0, " \t", &lasts
));
330 // Check if the transaction succeeded. The only success codes are in
331 // the range of 200-299 (HTTP specification).
332 if (return_code
>= 200 && return_code
< 300)
336 // Something went wrong!
337 // Get the description from the header message of what went wrong.
338 char *description
= ACE_OS::strtok_r (0, "\n\r", &lasts
);
339 ACE_ERROR_RETURN((LM_ERROR
, "%p\n", description
), -1);
341 ACE_NOTREACHED(return 0);