/* */ #include "HttpConnection.h" #include #include "util.h" #include "message.h" #include "prefs.h" #include "LogFactory.h" #include "DlRetryEx.h" #include "DlAbortEx.h" #include "Request.h" #include "Segment.h" #include "HttpRequest.h" #include "HttpResponse.h" #include "HttpHeaderProcessor.h" #include "HttpHeader.h" #include "Logger.h" #include "Socket.h" #include "Option.h" #include "CookieStorage.h" #include "AuthConfigFactory.h" #include "AuthConfig.h" #include "a2functional.h" #include "fmt.h" #include "SocketRecvBuffer.h" namespace aria2 { HttpRequestEntry::HttpRequestEntry (const SharedHandle& httpRequest) : httpRequest_(httpRequest), proc_(new HttpHeaderProcessor()) {} HttpRequestEntry::~HttpRequestEntry() {} HttpConnection::HttpConnection (cuid_t cuid, const SocketHandle& socket, const SharedHandle& socketRecvBuffer) : cuid_(cuid), socket_(socket), socketRecvBuffer_(socketRecvBuffer), socketBuffer_(socket) {} HttpConnection::~HttpConnection() {} std::string HttpConnection::eraseConfidentialInfo(const std::string& request) { std::istringstream istr(request); std::string result; std::string line; while(getline(istr, line)) { static const std::string AUTH_HEADER("Authorization: Basic"); static const std::string PROXY_AUTH_HEADER("Proxy-Authorization: Basic"); if(util::startsWith(line, AUTH_HEADER)) { result += "Authorization: Basic ********\n"; } else if(util::startsWith(line, PROXY_AUTH_HEADER)) { result += "Proxy-Authorization: Basic ********\n"; } else { strappend(result, line, "\n"); } } return result; } void HttpConnection::sendRequest(const SharedHandle& httpRequest) { std::string request = httpRequest->createRequest(); A2_LOG_INFO(fmt(MSG_SENDING_REQUEST, cuid_, eraseConfidentialInfo(request).c_str())); socketBuffer_.pushStr(request); socketBuffer_.send(); SharedHandle entry(new HttpRequestEntry(httpRequest)); outstandingHttpRequests_.push_back(entry); } void HttpConnection::sendProxyRequest (const SharedHandle& httpRequest) { std::string request = httpRequest->createProxyRequest(); A2_LOG_INFO(fmt(MSG_SENDING_REQUEST, cuid_, eraseConfidentialInfo(request).c_str())); socketBuffer_.pushStr(request); socketBuffer_.send(); SharedHandle entry(new HttpRequestEntry(httpRequest)); outstandingHttpRequests_.push_back(entry); } SharedHandle HttpConnection::receiveResponse() { if(outstandingHttpRequests_.empty()) { throw DL_ABORT_EX(EX_NO_HTTP_REQUEST_ENTRY_FOUND); } HttpRequestEntryHandle entry = outstandingHttpRequests_.front(); HttpHeaderProcessorHandle proc = entry->getHttpHeaderProcessor(); if(socketRecvBuffer_->bufferEmpty()) { if(socketRecvBuffer_->recv() == 0 && !socket_->wantRead() && !socket_->wantWrite()) { throw DL_RETRY_EX(EX_GOT_EOF); } } proc->update(socketRecvBuffer_->getBuffer(), socketRecvBuffer_->getBufferLength()); SharedHandle httpResponse; size_t shiftBufferLength; if(proc->eoh()) { SharedHandle httpHeader = proc->getHttpResponseHeader(); size_t putbackDataLength = proc->getPutBackDataLength(); A2_LOG_INFO(fmt(MSG_RECEIVE_RESPONSE, cuid_, proc->getHeaderString().c_str())); assert(socketRecvBuffer_->getBufferLength() >= putbackDataLength); shiftBufferLength = socketRecvBuffer_->getBufferLength()-putbackDataLength; httpResponse.reset(new HttpResponse()); httpResponse->setCuid(cuid_); httpResponse->setHttpHeader(httpHeader); httpResponse->setHttpRequest(entry->getHttpRequest()); outstandingHttpRequests_.pop_front(); } else { shiftBufferLength = socketRecvBuffer_->getBufferLength(); } socketRecvBuffer_->shiftBuffer(shiftBufferLength); return httpResponse; } bool HttpConnection::isIssued(const SharedHandle& segment) const { for(HttpRequestEntries::const_iterator itr = outstandingHttpRequests_.begin(), eoi = outstandingHttpRequests_.end(); itr != eoi; ++itr) { SharedHandle httpRequest = (*itr)->getHttpRequest(); if(*httpRequest->getSegment() == *segment) { return true; } } return false; } SharedHandle HttpConnection::getFirstHttpRequest() const { if(outstandingHttpRequests_.empty()) { return SharedHandle(); } else { return outstandingHttpRequests_.front()->getHttpRequest(); } } bool HttpConnection::sendBufferIsEmpty() const { return socketBuffer_.sendBufferIsEmpty(); } void HttpConnection::sendPendingData() { socketBuffer_.send(); } } // namespace aria2