~ubuntu-branches/ubuntu/utopic/nordugrid-arc/utopic

« back to all changes in this revision

Viewing changes to src/hed/mcc/http/PayloadHTTP.cpp

  • Committer: Package Import Robot
  • Author(s): Mattias Ellert
  • Date: 2014-05-01 20:51:02 UTC
  • mfrom: (1.1.11)
  • Revision ID: package-import@ubuntu.com-20140501205102-icy9t3348uxobyx7
Tags: 4.1.0-1
* 4.1.0 Release
* Call dh_autoreconf to support ppc64le (Closes: #744639)

Show diffs side-by-side

added added

removed removed

Lines of Context:
37
37
 
38
38
// -------------------- PayloadHTTP -----------------------------
39
39
 
40
 
const std::string& PayloadHTTP::Attribute(const std::string& name) {
41
 
  std::multimap<std::string,std::string>::iterator it = attributes_.find(name);
 
40
const std::string& PayloadHTTP::Attribute(const std::string& name) const {
 
41
  std::multimap<std::string,std::string>::const_iterator it = attributes_.find(name);
42
42
  if(it == attributes_.end()) return empty_string;
43
43
  return it->second;
44
44
}
45
45
 
46
 
const std::multimap<std::string,std::string>& PayloadHTTP::Attributes(void) {
 
46
const std::list<std::string> PayloadHTTP::Attributes(const std::string& name) const {
 
47
  std::list<std::string> attrs;
 
48
  for(std::multimap<std::string,std::string>::const_iterator attr = attributes_.begin();
 
49
                          attr != attributes_.end(); ++attr) {
 
50
    if(attr->first == name) attrs.push_back(attr->second);
 
51
  };
 
52
  return attrs;
 
53
}
 
54
 
 
55
const std::multimap<std::string,std::string>& PayloadHTTP::Attributes(void) const {
47
56
  return attributes_;
48
57
}
49
58
 
 
59
bool PayloadHTTP::AttributeMatch(const std::string& name, const std::string& value) const {
 
60
  std::multimap<std::string,std::string>::const_iterator attr = attributes_.begin();
 
61
  for(;attr != attributes_.end();++attr) {
 
62
    if(attr->first == name) {
 
63
      std::string sattr = Arc::lower(Arc::trim(attr->second," \r\n"));
 
64
      if(sattr == value) return true;
 
65
    };
 
66
  };
 
67
  return false;
 
68
}
 
69
 
50
70
PayloadHTTP::PayloadHTTP(void):
51
71
    valid_(false),version_major_(1),version_minor_(1),
52
72
    code_(0),length_(0),offset_(0),size_(0),end_(0),keep_alive_(true) {
104
124
}
105
125
 
106
126
bool PayloadHTTPIn::read(char* buf,int64_t& size) {
 
127
char* sbuf = buf;
107
128
  if(tbuflen_ >= size) {
108
129
    memcpy(buf,tbuf_,size);
109
130
    memmove(tbuf_,tbuf_+size,tbuflen_-size+1);
445
466
    if(pos3 == std::string::npos) return false;
446
467
    code_=strtol(line.c_str()+pos2+1,NULL,10);
447
468
    reason_=line.substr(pos3+1);
 
469
    if(code_ == 100) {
 
470
      // TODO: skip 100 response
 
471
    }
448
472
  } else {
449
473
    // Request
450
474
    std::string::size_type pos3 = line.rfind(' ');
493
517
  valid_=false; // But object is invalid till whole body is available
494
518
  if(body_) free(body_);
495
519
  body_ = NULL; body_size_ = 0;
496
 
  // TODO: Check for methods and responses which can't have body
 
520
  if(head_response_ && (code_ == 200)) {
 
521
    // Successful response to HEAD contains no body
 
522
    valid_=true;
 
523
    flush_multipart();
 
524
    flush_chunked();
 
525
    body_read_=true;
 
526
    return true;
 
527
  };
497
528
  char* result = NULL;
498
529
  int64_t result_size = 0;
499
530
  if(length_ == 0) {
535
566
  return true;
536
567
}
537
568
 
538
 
PayloadHTTPIn::PayloadHTTPIn(PayloadStreamInterface& stream,bool own):
539
 
    chunked_(CHUNKED_NONE),chunk_size_(0),
 
569
PayloadHTTPIn::PayloadHTTPIn(PayloadStreamInterface& stream,bool own,bool head_response):
 
570
    head_response_(head_response),chunked_(CHUNKED_NONE),chunk_size_(0),
540
571
    multipart_(MULTIPART_NONE),stream_(&stream),stream_offset_(0),
541
572
    stream_own_(own),fetched_(false),header_read_(false),body_read_(false),
542
573
    body_(NULL),body_size_(0) {
735
766
    PayloadHTTP(method,url),
736
767
    head_response_(false),rbody_(NULL),sbody_(NULL),sbody_size_(0),
737
768
    body_own_(false),to_stream_(false),use_chunked_transfer_(false),
738
 
    stream_offset_(0) {
 
769
    stream_offset_(0),stream_finished_(false),
 
770
    enable_header_out_(true), enable_body_out_(true) {
739
771
  valid_ = true;
740
772
}
741
773
 
743
775
    PayloadHTTP(code,reason),
744
776
    head_response_(head_response),rbody_(NULL),sbody_(NULL),sbody_size_(0),
745
777
    body_own_(false),to_stream_(false),use_chunked_transfer_(false),
746
 
    stream_offset_(0) {
 
778
    stream_offset_(0), stream_finished_(false),
 
779
    enable_header_out_(true), enable_body_out_(true) {
747
780
  valid_ = true;
748
781
}
749
782
 
753
786
}
754
787
 
755
788
PayloadHTTPOutStream::PayloadHTTPOutStream(const std::string& method,const std::string& url):
756
 
  PayloadHTTPOut(method,url),stream_finished_(false) /*,chunk_size_offset_(0)*/ {
 
789
  PayloadHTTPOut(method,url) /*,chunk_size_offset_(0)*/ {
757
790
}
758
791
 
759
792
PayloadHTTPOutStream::PayloadHTTPOutStream(int code,const std::string& reason,bool head_response):
760
 
  PayloadHTTPOut(code,reason,head_response),stream_finished_(false) /*,chunk_size_offset_(0)*/ {
 
793
  PayloadHTTPOut(code,reason,head_response) /*,chunk_size_offset_(0)*/ {
761
794
}
762
795
 
763
796
PayloadHTTPOutStream::~PayloadHTTPOutStream(void) {
925
958
}
926
959
 
927
960
bool PayloadHTTPOut::Flush(PayloadStreamInterface& stream) {
928
 
  std::string header;
929
 
  //bool to_stream = (stream_ != NULL);
930
 
  //bool to_stream = true;
 
961
  if(enable_header_out_) {
 
962
    if(!FlushHeader(stream)) return false;
 
963
  }
 
964
  if(enable_body_out_) {
 
965
    if(!FlushBody(stream)) return false;
 
966
  }
 
967
  return true;
 
968
}
 
969
 
 
970
bool PayloadHTTPOut::FlushHeader(PayloadStreamInterface& stream) {
931
971
  if(!make_header(true)) return false;
932
 
  //if(to_stream) {
933
 
    if(!stream.Put(header_)) {
934
 
      error_ = IString("Failed to write header to output stream").str();
935
 
      return false;
936
 
    };
 
972
  if(!stream.Put(header_)) {
 
973
    error_ = IString("Failed to write header to output stream").str();
 
974
    return false;
 
975
  };
 
976
  return true;
 
977
}
 
978
 
 
979
bool PayloadHTTPOut::FlushBody(PayloadStreamInterface& stream) {
 
980
    // TODO: process 100 request/response
937
981
    if((length_ > 0) || (use_chunked_transfer_)) {
938
982
      if(sbody_) {
939
983
        // stream to stream transfer
1016
1060
        };
1017
1061
      };
1018
1062
    };
1019
 
    //if(!keep_alive) stream_->Close();
1020
 
  //} else {
1021
 
  //  Insert(header_.c_str(),0,header.length());
1022
 
  //};
1023
 
  return true;
 
1063
    return true;
1024
1064
}
1025
1065
 
1026
1066
void PayloadHTTPOutRaw::Body(PayloadRawInterface& body,bool ownership) {
1042
1082
  if(pos < size) sbody_size_ = (size-pos);
1043
1083
}
1044
1084
 
 
1085
void PayloadHTTPOut::ResetOutput(bool enable_header, bool enable_body) {
 
1086
  stream_offset_ = 0;
 
1087
  stream_finished_ = false;
 
1088
  // Because we can't/do not want to reset state
 
1089
  // body stream then actual body size need to be
 
1090
  // recomputed.
 
1091
  sbody_size_ = 0;
 
1092
  if(sbody_) {
 
1093
    PayloadStreamInterface::Size_t pos = sbody_->Pos();
 
1094
    PayloadStreamInterface::Size_t size = sbody_->Size();
 
1095
    PayloadStreamInterface::Size_t limit = sbody_->Limit();
 
1096
    if((size == 0) || (size > limit)) size = limit;
 
1097
    if(pos < size) sbody_size_ = (size-pos);
 
1098
  }
 
1099
  enable_header_out_ = enable_header;
 
1100
  enable_body_out_ = enable_body;
 
1101
}
 
1102
 
 
1103
 
1045
1104
char PayloadHTTPOutRaw::operator[](PayloadRawInterface::Size_t pos) const {
1046
1105
  if(!((PayloadHTTPOutRaw&)(*this)).remake_header(false)) return 0;
1047
1106
  if(pos == -1) pos = 0;
1197
1256
  if(stream_finished_) return false;
1198
1257
  // Read header
1199
1258
  uint64_t bo = 0; // buf offset
1200
 
  uint64_t bs = header_.length(); // buf size
 
1259
  uint64_t bs = enable_header_out_?header_.length():0; // buf size
1201
1260
  int l = 0;
1202
1261
  if(l >= size) { size = l; return true; };
1203
1262
  if((bo+bs) > stream_offset_) {
1212
1271
  bo+=bs;
1213
1272
  if(l >= size) { size = l; return true; }; // buffer is full
1214
1273
  // Read data
1215
 
  if(rbody_) {
 
1274
  if(rbody_ && enable_body_out_) {
1216
1275
    /* This code is only needed if stream and raw are mixed.
1217
1276
       Currently it is not possible hence it is not needed.
1218
1277
       But code is kept for future use. Code is not tested.
1249
1308
    size = 0;
1250
1309
    return false;
1251
1310
  };
1252
 
  if(sbody_) {
 
1311
  if(sbody_ && enable_body_out_) {
1253
1312
    if(use_chunked_transfer_) {
1254
1313
      // It is impossible to know size of chunk
1255
1314
      // in advance. So first prelimnary size is
1311
1370
}
1312
1371
 
1313
1372
bool PayloadHTTPOutStream::Get(PayloadStreamInterface& dest,int& size) {
1314
 
  if(stream_offset_ > 0) return PayloadStreamInterface::Get(dest,size);
1315
 
  if(size != -1) return PayloadStreamInterface::Get(dest,size);
 
1373
  if((stream_offset_ > 0) || (size >= 0)) {
 
1374
    // If it is not first call or if size control is requested
 
1375
    // then convenience method PayloadStreamInterface::Get is
 
1376
    // used, which finally calls PayloadHTTPOutStream::Get.
 
1377
    return PayloadStreamInterface::Get(dest,size);
 
1378
  }
 
1379
  // But if whole content is requested at once we use faster Flush* methods
1316
1380
  Flush(dest);
1317
1381
  return false; // stream finished
1318
1382
}
1337
1401
 
1338
1402
PayloadStreamInterface::Size_t PayloadHTTPOutStream::Limit(void) const {
1339
1403
  if(!((PayloadHTTPOutStream&)(*this)).remake_header(true)) return 0;
1340
 
  return header_.length()+body_size();
 
1404
  PayloadStreamInterface::Size_t limit = 0;
 
1405
  if(enable_header_out_) limit += header_.length();
 
1406
  if(enable_body_out_) limit += body_size();
 
1407
  return limit;
1341
1408
}
1342
1409
 
1343
1410
//-------------------------------------------------------------------