16 , _incompleteheadersection( 0 )
17 , _content_length( 0 )
18 , _send_more_data( false )
22 timeToNextRequest = 0;
25 this->_remote_ip = remote_ip;
29 readingchunked =
false;
38 if ( (
int) (
queryTime()-1) < timeToNextRequest )
41 return !dataToSend.empty();
45 if (x >=
'0' && x <=
'9')
return true;
46 if (x >=
'a' && x <=
'f')
return true;
47 if (x >=
'A' && x <=
'F')
return true;
48 if (x ==
'x' || x ==
'X')
return true;
59 std::string &fullhost,
61 unsigned short &port )
63 std::string protocol = uri.substr( 0, 7 );
64 std::string::size_type pos = 0;
65 if (protocol ==
"http://")
67 std::string::size_type endhost = uri.find(
':', pos );
68 std::string::size_type endhostport = uri.find(
'/', pos );
69 if (endhost == std::string::npos || endhost >= endhostport)
70 endhost = endhostport;
71 host = uri.substr( pos, endhost-pos );
72 fullhost = uri.substr( pos, endhostport-pos );
73 port = atoi( uri.substr( endhost+1, endhostport-endhost-1 ).c_str() );
76 path = uri.substr( endhostport );
83 std::string dummy1, dummy2;
94 return _content_length == 0 && !dataToReceive.empty();
99 , _incompleteheadersection( 0 )
100 , _content_length( 0 )
101 , _send_more_data( false )
105 timeToNextRequest = 0;
110 hostFromURI( uri, dummy, this->_hostheader, this->_path, port );
112 readingchunked =
false;
119 if (dataToReceive.length() == 0)
120 waitingToReceive = std::string();
121 _send_more_data =
true;
123 if (this->
_fd >= 0) {
127 _incompleteheadersection = 0;
128 _incompleteheader = std::string();
142 ostr<<
"URI: http://"<<_remote_ip<<_path;
147 dataToSend.push_back( data );
153 if ( !waitingToReceive.empty() ) {
154 if ( _content_length == 0 && !dataToReceive.empty() ) {
155 waitingToReceive = std::string();
156 data = dataToReceive;
157 dataToReceive = std::string();
158 _incompleteheader = std::string();
173 if (waitingToReceive.empty() && this->
_fd == -1)
179 if ( !waitingToReceive.empty() )
181 if (this->
_fd == -1) {
182 printf(
"reopening from lower_sendbuf...\n" );
187 if ( !( _send_more_data || _content_length
188 || _incompleteheader.length() || _header.size() ) ) {
189 COUT<<
"Error: HTTP data being sent while incomplete header exists";
193 std::string data = dataToSend.front();
194 char endHeaderLen[50];
195 std::string httpData;
198 sprintf( endHeaderLen,
"Content-Length: %u\r\n\r\n", (
unsigned int) data.length() );
199 httpData =
"POST "+this->_path+
" HTTP/1.1\r\n"
200 "Host: "+this->_hostheader+
"\r\n"
201 "User-Agent: Vsnet/1.0\r\n"
202 "Connection: keep-alive\r\n"
203 "Accept: message/x-vsnet-packet\r\n"
204 "Keep-Alive: 300\r\n"
205 "Content-Type: message/x-vsnet-packet\r\n"
208 const char *httpDataStr = httpData.data();
209 unsigned int pos = sendDataPos;
213 int len = httpData.length()-pos;
215 netsent = ::send(
_fd, &httpDataStr[pos], len, 0 );
244 if ( pos >= httpData.length() )
247 waitingToReceive = dataToSend.front();
248 dataToSend.pop_front();
253 bool VsnetHTTPSocket::parseHeaderByte(
char rcvchr )
255 if (rcvchr ==
'\r' && _incompleteheadersection != 1) {
256 _incompleteheadersection++;
257 if (_incompleteheadersection == 1)
260 if (rcvchr ==
'\n' && _incompleteheadersection > 0) {
261 if (_incompleteheadersection > 2) {
262 _incompleteheadersection = 0;
265 _incompleteheadersection++;
269 while (_incompleteheadersection >= 2) {
270 if (_incompleteheadersection == 2)
271 _incompleteheadersection = 0;
272 if ( _incompleteheadersection > 2 || !isspace( rcvchr ) ) {
273 if ( _header.empty() ) {
274 std::string::size_type sp1, sp2;
275 sp1 = _incompleteheader.find(
' ' );
276 if (sp1 == std::string::npos)
break;
279 _header.insert( std::pair< std::string, std::string > (
280 "Status", _incompleteheader.substr( sp1+1 ) ) );
282 std::string::size_type colon, colonsp;
283 colon = _incompleteheader.find(
':' );
284 if (colon == std::string::npos)
break;
288 while ( colonsp < _incompleteheader.length()
289 && isspace( _incompleteheader[colonsp] ) );
290 _header.insert( std::pair< std::string, std::string > (
291 _incompleteheader.substr( 0, colon ), _incompleteheader.substr( colonsp ) ) );
293 _incompleteheader =
"";
297 if (rcvchr ==
'\r' && _incompleteheadersection != 1 && _incompleteheadersection > 2)
299 _incompleteheader += (rcvchr);
308 if ( waitingToReceive.empty() )
310 if (numRetries >= 10) {
311 waitingToReceive = std::string();
317 dataToSend.push_front( waitingToReceive );
319 waitingToReceive = std::string();
323 readingchunked =
false;
325 _send_more_data =
false;
327 _incompleteheadersection = 0;
332 if ( waitingToReceive.empty() ) {
333 if (this->
_fd >= 0) {
340 if (this->
_fd == -1) {
347 while (datalen != 0) {
349 int dataIWantToRead = 1400;
350 if (_content_length > 0)
351 dataIWantToRead = _content_length;
352 dataToRead = dataIWantToRead;
354 dataToRead = datalen < dataIWantToRead ? datalen : dataIWantToRead;
357 if (ret > 0) cout<<
"READ DATA: "<<std::string( rcvbuf, ret )<<endl;
358 if (ret <= 0) cout<<
"recv returned "<<ret<<endl;
361 if ( _content_length >= 0
362 && ( (readHeader ==
false && dataToReceive.length()
363 == 0) || readHeader ==
true ) ) {
365 printf(
"Server closed in reading...resending\n" );
372 }
else if (ret < 0) {
378 perror(
"Error in reading HTTP socket" );
383 if (datalen > 0 || datalen < 0) {
384 if (datalen != -1) datalen -= ret;
386 if (_content_length == 0) {
387 for (bufpos = 0; bufpos < ret; bufpos++) {
388 char rcvchr = rcvbuf[bufpos];
389 if ( parseHeaderByte( rcvchr ) ) {
390 std::map< std::string, std::string >::const_iterator iter;
392 _content_length = -1;
394 _send_more_data =
true;
396 iter = _header.find(
"Status" );
397 if ( iter == _header.end() ) {
398 COUT<<
"Missing status, resending\n";
402 if ( (*iter).second.find(
"100" ) != std::string::npos ) {
405 printf(
"100 found in header at marker %d... rest of string looks like:%s\n", bufpos, rcvbuf+bufpos );
407 }
else if ( (*iter).second.find(
"200" ) == std::string::npos ) {
408 if ( (*iter).second.find(
"301" ) != std::string::npos
409 || (*iter).second.find(
"302" ) != std::string::npos
410 || (*iter).second.find(
"303" ) != std::string::npos
411 || (*iter).second.find(
"307" ) != std::string::npos ) {
413 iter = _header.find(
"Location" );
414 if ( iter == _header.end() ) {
415 COUT<<
"Failed to find a Location header after a 3xx message";
420 hostFromURI( (*iter).second, dummy, this->_hostheader, this->_path, port );
425 COUT<<
"Received HTTP error: status is "+(*iter).second<<std::endl;
430 iter = _header.find(
"Content-Length" );
431 if ( iter != _header.end() ) {
432 _content_length = atoi( (*iter).second.c_str() );
433 if (_content_length == 0)
434 _content_length = -1;
437 iter = _header.find(
"Content-Type" );
438 if ( iter != _header.end() )
439 if ( (*iter).second !=
"message/x-vsnet-packet" && (*iter).second !=
"text/html" )
440 COUT<<
"content type "<<(*iter).second<<std::endl;
441 iter = _header.find(
"Connection" );
442 if ( iter != _header.end() ) {
443 if ( (*iter).second ==
"close" )
444 _send_more_data =
false;
447 _send_more_data =
false;
449 iter = _header.find(
"Transfer-Encoding" );
450 if ( iter != _header.end() ) {
451 if ( (*iter).second ==
"chunked" )
460 readingchunked =
true;
467 while (bufpos < ret) {
468 for (; bufpos < ret && readingchunked; bufpos++) {
469 char rcvchr = rcvbuf[bufpos];
470 if (rcvchr ==
'\n' && chunkedchar !=
'\0' ) {
471 readingchunked =
false;
475 if (
ishex( rcvchr ) && (
ishex( chunkedchar ) || chunkedchar ==
'\0') ) {
476 if (rcvchr >=
'0' && rcvchr <=
'9') {
478 chunkedlen += rcvchr-
'0';
479 chunkedchar = rcvchr;
480 }
else if (rcvchr >=
'A' && rcvchr <=
'F') {
482 chunkedlen += rcvchr-
'A'+10;
483 chunkedchar = rcvchr;
484 }
else if (rcvchr >=
'a' && rcvchr <=
'f') {
486 chunkedlen += rcvchr-
'a'+10;
487 chunkedchar = rcvchr;
489 chunkedchar = rcvchr;
491 if (rcvchr ==
';') chunkedchar =
';';
493 if (readingchunked ==
false && _content_length != 0 && bufpos < ret) {
495 int delta = ret-bufpos;
496 if (delta > chunkedlen && ischunked)
498 dataToReceive += std::string( rcvbuf+bufpos, (std::string::size_type) delta );
501 if (chunkedlen == 0) {
503 readingchunked =
true;
507 if (_content_length > 0) {
508 _content_length -= ret;
509 if (_content_length <= 0) {
517 if (datalen != -1 && datalen <= 0)
529 if (_content_length == 0 && !_send_more_data &&
_fd != -1) {
533 if ( dataToReceive.length() == 0 || (dataToReceive[0] ==
'!' && dataToReceive.length() < 4) ) {
535 dataToReceive = std::string();
536 waitingToReceive = std::string();