httpload.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. #include "httpload.h"
  2. /************************************************************/
  3. /************************************************************/
  4. httpAgentReader::httpAgentReader(httpSpecialAgent& agent,
  5. const char* baseUrl,
  6. bool assumeConnectionClosed,
  7. bool use_auth,
  8. int bufSize)
  9. : Header_()
  10. , Agent_(agent)
  11. , Buffer_(new char[bufSize])
  12. , BufPtr_(Buffer_)
  13. , BufSize_(bufSize)
  14. , BufRest_(0)
  15. {
  16. HeadRequest = false;
  17. Header = &Header_;
  18. if (use_auth)
  19. HeaderParser.Init(&Header_);
  20. else
  21. HeaderParser.Init(Header);
  22. setAssumeConnectionClosed(assumeConnectionClosed ? 1 : 0);
  23. Header_.SetBase(baseUrl);
  24. if (Header_.error)
  25. State = hp_error;
  26. else
  27. State = hp_in_header;
  28. }
  29. /************************************************************/
  30. httpAgentReader::~httpAgentReader() {
  31. delete[] Buffer_;
  32. }
  33. /************************************************************/
  34. void httpAgentReader::readBuf() {
  35. assert(BufRest_ == 0);
  36. if (!BufPtr_) {
  37. BufRest_ = -1;
  38. return;
  39. }
  40. BufRest_ = Agent_.read(Buffer_, BufSize_);
  41. if (BufRest_ <= 0) {
  42. BufRest_ = -1;
  43. BufPtr_ = nullptr;
  44. } else {
  45. BufPtr_ = Buffer_;
  46. //cout << "BUF: " << mBuffer << endl << endl;
  47. }
  48. }
  49. /************************************************************/
  50. const THttpHeader* httpAgentReader::readHeader() {
  51. while (State == hp_in_header) {
  52. if (!step()) {
  53. Header_.error = HTTP_CONNECTION_LOST;
  54. return nullptr;
  55. }
  56. ParseGeneric(BufPtr_, BufRest_);
  57. }
  58. if (State == hp_eof || State == hp_error) {
  59. BufPtr_ = nullptr;
  60. BufRest_ = -1;
  61. }
  62. if (State == hp_error || Header_.error)
  63. return nullptr;
  64. return &Header_;
  65. }
  66. /************************************************************/
  67. long httpAgentReader::readPortion(void*& buf) {
  68. assert(State != hp_in_header);
  69. long Chunk = 0;
  70. do {
  71. if (BufSize_ == 0 && !BufPtr_)
  72. return 0;
  73. if (!step())
  74. return 0;
  75. Chunk = ParseGeneric(BufPtr_, BufRest_);
  76. buf = BufPtr_;
  77. if (State == hp_error && Header_.entity_size > Header_.content_length) {
  78. Chunk -= (Header_.entity_size - Header_.content_length);
  79. BufPtr_ = (char*)BufPtr_ + Chunk;
  80. BufRest_ = 0;
  81. State = hp_eof;
  82. Header_.error = 0;
  83. break;
  84. }
  85. BufPtr_ = (char*)BufPtr_ + Chunk;
  86. BufRest_ -= Chunk;
  87. if (State == hp_eof || State == hp_error) {
  88. BufRest_ = -1;
  89. BufPtr_ = nullptr;
  90. }
  91. } while (!Chunk);
  92. return Chunk;
  93. }
  94. /************************************************************/
  95. bool httpAgentReader::skipTheRest() {
  96. void* b;
  97. while (!eof())
  98. readPortion(b);
  99. return (State == hp_eof);
  100. }
  101. /************************************************************/
  102. /************************************************************/
  103. httpLoadAgent::httpLoadAgent(bool handleAuthorization,
  104. socketHandlerFactory& factory)
  105. : Factory_(factory)
  106. , HandleAuthorization_(handleAuthorization)
  107. , URL_()
  108. , PersistentConn_(false)
  109. , Reader_(nullptr)
  110. , Headers_()
  111. , ErrCode_(0)
  112. , RealHost_(nullptr)
  113. {
  114. }
  115. /************************************************************/
  116. httpLoadAgent::~httpLoadAgent() {
  117. delete Reader_;
  118. free(RealHost_);
  119. }
  120. /************************************************************/
  121. void httpLoadAgent::clearReader() {
  122. if (Reader_) {
  123. bool opened = false;
  124. if (PersistentConn_) {
  125. const THttpHeader* H = Reader_->readHeader();
  126. if (H && !H->connection_closed) {
  127. Reader_->skipTheRest();
  128. opened = true;
  129. }
  130. }
  131. if (!opened)
  132. Disconnect();
  133. delete Reader_;
  134. Reader_ = nullptr;
  135. }
  136. ErrCode_ = 0;
  137. }
  138. /************************************************************/
  139. void httpLoadAgent::setRealHost(const char* hostname) {
  140. free(RealHost_);
  141. if (hostname)
  142. RealHost_ = strdup(hostname);
  143. else
  144. RealHost_ = nullptr;
  145. ErrCode_ = 0;
  146. }
  147. /************************************************************/
  148. void httpLoadAgent::setIMS(const char* ifModifiedSince) {
  149. char ims_buf[100];
  150. snprintf(ims_buf, 100, "If-Modified-Since: %s\r\n",
  151. ifModifiedSince);
  152. Headers_.push_back(ims_buf);
  153. }
  154. /************************************************************/
  155. void httpLoadAgent::addHeaderInstruction(const char* instr) {
  156. Headers_.push_back(instr);
  157. }
  158. /************************************************************/
  159. void httpLoadAgent::dropHeaderInstructions() {
  160. Headers_.clear();
  161. }
  162. /************************************************************/
  163. bool httpLoadAgent::startRequest(const THttpURL& url,
  164. bool persistent,
  165. const TAddrList& addrs)
  166. {
  167. clearReader();
  168. ErrCode_ = 0;
  169. URL_.Clear();
  170. URL_ = url;
  171. PersistentConn_ = persistent;
  172. if (!URL_.IsValidAbs())
  173. return false;
  174. if (!HandleAuthorization_ && !URL_.IsNull(THttpURL::FlagAuth))
  175. return false;
  176. return doSetHost(addrs) && doStartRequest();
  177. }
  178. /************************************************************/
  179. bool httpLoadAgent::startRequest(const char* url,
  180. const char* url_to_merge,
  181. bool persistent,
  182. const TAddrList& addrs) {
  183. clearReader();
  184. URL_.Clear();
  185. PersistentConn_ = persistent;
  186. ui64 flags = THttpURL::FeatureSchemeKnown | THttpURL::FeaturesNormalizeSet;
  187. if (HandleAuthorization_)
  188. flags |= THttpURL::FeatureAuthSupported;
  189. if (URL_.Parse(url, flags, url_to_merge) || !URL_.IsValidGlobal())
  190. return false;
  191. return doSetHost(addrs) && doStartRequest();
  192. }
  193. /************************************************************/
  194. bool httpLoadAgent::startRequest(const char* url,
  195. const char* url_to_merge,
  196. bool persistent,
  197. ui32 ip) {
  198. clearReader();
  199. URL_.Clear();
  200. PersistentConn_ = persistent;
  201. ui64 flags = THttpURL::FeatureSchemeKnown | THttpURL::FeaturesNormalizeSet;
  202. if (HandleAuthorization_)
  203. flags |= THttpURL::FeatureAuthSupported;
  204. if (URL_.Parse(url, flags, url_to_merge) || !URL_.IsValidGlobal())
  205. return false;
  206. return doSetHost(TAddrList::MakeV4Addr(ip, URL_.GetPort())) && doStartRequest();
  207. }
  208. /************************************************************/
  209. bool httpLoadAgent::doSetHost(const TAddrList& addrs) {
  210. socketAbstractHandler* h = Factory_.chooseHandler(URL_);
  211. if (!h)
  212. return false;
  213. Socket.setHandler(h);
  214. if (addrs.size()) {
  215. ErrCode_ = SetHost(URL_.Get(THttpURL::FieldHost),
  216. URL_.GetPort(), addrs);
  217. } else {
  218. ErrCode_ = SetHost(URL_.Get(THttpURL::FieldHost),
  219. URL_.GetPort());
  220. }
  221. if (ErrCode_)
  222. return false;
  223. if (RealHost_) {
  224. size_t reqHostheaderLen = strlen(RealHost_) + 20;
  225. free(Hostheader);
  226. Hostheader = (char*)malloc((HostheaderLen = reqHostheaderLen));
  227. snprintf(Hostheader, HostheaderLen, "Host: %s\r\n", RealHost_);
  228. }
  229. if (!URL_.IsNull(THttpURL::FlagAuth)) {
  230. if (!HandleAuthorization_) {
  231. ErrCode_ = HTTP_UNAUTHORIZED;
  232. return false;
  233. }
  234. Digest_.setAuthorization(URL_.Get(THttpURL::FieldUsername),
  235. URL_.Get(THttpURL::FieldPassword));
  236. }
  237. return true;
  238. }
  239. /************************************************************/
  240. bool httpLoadAgent::setHost(const char* host_url,
  241. const TAddrList& addrs) {
  242. clearReader();
  243. URL_.Clear();
  244. PersistentConn_ = true;
  245. ui64 flags = THttpURL::FeatureSchemeKnown | THttpURL::FeaturesNormalizeSet;
  246. if (HandleAuthorization_)
  247. flags |= THttpURL::FeatureAuthSupported;
  248. if (URL_.Parse(host_url, flags) || !URL_.IsValidGlobal())
  249. return false;
  250. return doSetHost(addrs);
  251. }
  252. /************************************************************/
  253. bool httpLoadAgent::startOneRequest(const char* local_url) {
  254. clearReader();
  255. THttpURL lURL;
  256. if (lURL.Parse(local_url, THttpURL::FeaturesNormalizeSet) || lURL.IsValidGlobal())
  257. return false;
  258. URL_.SetInMemory(THttpURL::FieldPath, lURL.Get(THttpURL::FieldPath));
  259. URL_.SetInMemory(THttpURL::FieldQuery, lURL.Get(THttpURL::FieldQuery));
  260. URL_.Rewrite();
  261. return doStartRequest();
  262. }
  263. /************************************************************/
  264. bool httpLoadAgent::doStartRequest() {
  265. TString urlStr = URL_.PrintS(THttpURL::FlagPath | THttpURL::FlagQuery);
  266. if (!urlStr)
  267. urlStr = "/";
  268. for (int step = 0; step < 10; step++) {
  269. const char* digestHeader = Digest_.getHeaderInstruction();
  270. unsigned i = (digestHeader) ? 2 : 1;
  271. const char** headers =
  272. (const char**)(alloca((i + Headers_.size()) * sizeof(char*)));
  273. for (i = 0; i < Headers_.size(); i++)
  274. headers[i] = Headers_[i].c_str();
  275. if (digestHeader)
  276. headers[i++] = digestHeader;
  277. headers[i] = nullptr;
  278. ErrCode_ = RequestGet(urlStr.c_str(), headers, PersistentConn_);
  279. if (ErrCode_) {
  280. Disconnect();
  281. return false;
  282. }
  283. TString urlBaseStr = URL_.PrintS(THttpURL::FlagNoFrag);
  284. clearReader();
  285. Reader_ = new httpAgentReader(*this, urlBaseStr.c_str(),
  286. !PersistentConn_, !Digest_.empty());
  287. if (Reader_->readHeader()) {
  288. //mReader->getHeader()->Print();
  289. if (getHeader()->http_status == HTTP_UNAUTHORIZED &&
  290. step < 1 &&
  291. Digest_.processHeader(getAuthHeader(),
  292. urlStr.c_str(),
  293. "GET")) {
  294. //mReader->skipTheRest();
  295. delete Reader_;
  296. Reader_ = nullptr;
  297. ErrCode_ = 0;
  298. Disconnect();
  299. continue;
  300. }
  301. return true;
  302. }
  303. Disconnect();
  304. clearReader();
  305. return false;
  306. }
  307. ErrCode_ = HTTP_UNAUTHORIZED;
  308. return false;
  309. }
  310. /************************************************************/
  311. /************************************************************/