From a1991c517598fda9c9c0cf8876886e3968436ff9 Mon Sep 17 00:00:00 2001 From: deadbeef Date: Fri, 3 Mar 2017 10:23:08 -0800 Subject: [PATCH] Removing HTTPS and SOCKS proxy server code. This isn't used any more so there's no point in maintaining it. BUG=None Review-Url: https://codereview.webrtc.org/2731673002 Cr-Commit-Position: refs/heads/master@{#17016} --- webrtc/base/BUILD.gn | 12 - webrtc/base/httpbase.cc | 886 --------------- webrtc/base/httpbase.h | 187 --- webrtc/base/httpbase_unittest.cc | 526 --------- webrtc/base/httpcommon-inl.h | 132 --- webrtc/base/httpcommon.cc | 1009 ----------------- webrtc/base/httpcommon.h | 458 -------- webrtc/base/httpcommon_unittest.cc | 165 --- webrtc/base/httpserver.cc | 288 ----- webrtc/base/httpserver.h | 139 --- webrtc/base/httpserver_unittest.cc | 130 --- webrtc/base/proxy_unittest.cc | 76 -- webrtc/base/proxyinfo.cc | 24 - webrtc/base/proxyinfo.h | 20 +- webrtc/base/proxyserver.cc | 4 - webrtc/base/proxyserver.h | 12 - webrtc/base/socketadapters.cc | 604 ---------- webrtc/base/socketadapters.h | 109 -- webrtc/p2p/base/basicpacketsocketfactory.cc | 10 - .../p2p/base/p2ptransportchannel_unittest.cc | 102 +- webrtc/p2p/base/packetsocketfactory.h | 1 + webrtc/p2p/base/portallocator.h | 10 - webrtc/p2p/base/relayport.cc | 10 +- webrtc/p2p/client/basicportallocator.cc | 2 - 24 files changed, 24 insertions(+), 4892 deletions(-) delete mode 100644 webrtc/base/httpbase.cc delete mode 100644 webrtc/base/httpbase.h delete mode 100644 webrtc/base/httpbase_unittest.cc delete mode 100644 webrtc/base/httpcommon-inl.h delete mode 100644 webrtc/base/httpcommon.cc delete mode 100644 webrtc/base/httpcommon.h delete mode 100644 webrtc/base/httpcommon_unittest.cc delete mode 100644 webrtc/base/httpserver.cc delete mode 100644 webrtc/base/httpserver.h delete mode 100644 webrtc/base/httpserver_unittest.cc delete mode 100644 webrtc/base/proxy_unittest.cc delete mode 100644 webrtc/base/proxyinfo.cc diff --git a/webrtc/base/BUILD.gn b/webrtc/base/BUILD.gn index eb9361bc42..d81720652c 100644 --- a/webrtc/base/BUILD.gn +++ b/webrtc/base/BUILD.gn @@ -402,11 +402,6 @@ rtc_static_library("rtc_base") { "gunit_prod.h", "helpers.cc", "helpers.h", - "httpbase.cc", - "httpbase.h", - "httpcommon-inl.h", - "httpcommon.cc", - "httpcommon.h", "ipaddress.cc", "ipaddress.h", "messagedigest.cc", @@ -434,7 +429,6 @@ rtc_static_library("rtc_base") { "opensslstreamadapter.h", "physicalsocketserver.cc", "physicalsocketserver.h", - "proxyinfo.cc", "proxyinfo.h", "ratelimiter.cc", "ratelimiter.h", @@ -696,8 +690,6 @@ if (rtc_include_tests) { "firewallsocketserver.cc", "firewallsocketserver.h", "gunit.h", - "httpserver.cc", - "httpserver.h", "memory_usage.cc", "memory_usage.h", "natserver.cc", @@ -851,9 +843,6 @@ if (rtc_include_tests) { "crc32_unittest.cc", "fileutils_unittest.cc", "helpers_unittest.cc", - "httpbase_unittest.cc", - "httpcommon_unittest.cc", - "httpserver_unittest.cc", "ipaddress_unittest.cc", "memory_usage_unittest.cc", "messagedigest_unittest.cc", @@ -861,7 +850,6 @@ if (rtc_include_tests) { "nat_unittest.cc", "network_unittest.cc", "optionsfile_unittest.cc", - "proxy_unittest.cc", "ratelimiter_unittest.cc", "rollingaccumulator_unittest.cc", "rtccertificate_unittest.cc", diff --git a/webrtc/base/httpbase.cc b/webrtc/base/httpbase.cc deleted file mode 100644 index bc8ac64c71..0000000000 --- a/webrtc/base/httpbase.cc +++ /dev/null @@ -1,886 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include - -#if defined(WEBRTC_WIN) -#include "webrtc/base/win32.h" -#else // !WEBRTC_WIN -#define SEC_E_CERT_EXPIRED (-2146893016) -#endif // !WEBRTC_WIN - -#include "webrtc/base/checks.h" -#include "webrtc/base/httpbase.h" -#include "webrtc/base/logging.h" -#include "webrtc/base/socket.h" -#include "webrtc/base/stringutils.h" -#include "webrtc/base/thread.h" - -namespace rtc { - -////////////////////////////////////////////////////////////////////// -// Helpers -////////////////////////////////////////////////////////////////////// - -bool MatchHeader(const char* str, size_t len, HttpHeader header) { - const char* const header_str = ToString(header); - const size_t header_len = strlen(header_str); - return (len == header_len) && (_strnicmp(str, header_str, header_len) == 0); -} - -enum { - MSG_READ -}; - -////////////////////////////////////////////////////////////////////// -// HttpParser -////////////////////////////////////////////////////////////////////// - -HttpParser::HttpParser() { - reset(); -} - -HttpParser::~HttpParser() { -} - -void -HttpParser::reset() { - state_ = ST_LEADER; - chunked_ = false; - data_size_ = SIZE_UNKNOWN; -} - -HttpParser::ProcessResult -HttpParser::Process(const char* buffer, size_t len, size_t* processed, - HttpError* error) { - *processed = 0; - *error = HE_NONE; - - if (state_ >= ST_COMPLETE) { - RTC_NOTREACHED(); - return PR_COMPLETE; - } - - while (true) { - if (state_ < ST_DATA) { - size_t pos = *processed; - while ((pos < len) && (buffer[pos] != '\n')) { - pos += 1; - } - if (pos >= len) { - break; // don't have a full header - } - const char* line = buffer + *processed; - size_t len = (pos - *processed); - *processed = pos + 1; - while ((len > 0) && isspace(static_cast(line[len-1]))) { - len -= 1; - } - ProcessResult result = ProcessLine(line, len, error); - LOG(LS_VERBOSE) << "Processed line, result=" << result; - - if (PR_CONTINUE != result) { - return result; - } - } else if (data_size_ == 0) { - if (chunked_) { - state_ = ST_CHUNKTERM; - } else { - return PR_COMPLETE; - } - } else { - size_t available = len - *processed; - if (available <= 0) { - break; // no more data - } - if ((data_size_ != SIZE_UNKNOWN) && (available > data_size_)) { - available = data_size_; - } - size_t read = 0; - ProcessResult result = ProcessData(buffer + *processed, available, read, - error); - LOG(LS_VERBOSE) << "Processed data, result: " << result << " read: " - << read << " err: " << error; - - if (PR_CONTINUE != result) { - return result; - } - *processed += read; - if (data_size_ != SIZE_UNKNOWN) { - data_size_ -= read; - } - } - } - - return PR_CONTINUE; -} - -HttpParser::ProcessResult -HttpParser::ProcessLine(const char* line, size_t len, HttpError* error) { - LOG_F(LS_VERBOSE) << " state: " << state_ << " line: " - << std::string(line, len) << " len: " << len << " err: " - << error; - - switch (state_) { - case ST_LEADER: - state_ = ST_HEADERS; - return ProcessLeader(line, len, error); - - case ST_HEADERS: - if (len > 0) { - const char* value = strchrn(line, len, ':'); - if (!value) { - *error = HE_PROTOCOL; - return PR_COMPLETE; - } - size_t nlen = (value - line); - const char* eol = line + len; - do { - value += 1; - } while ((value < eol) && isspace(static_cast(*value))); - size_t vlen = eol - value; - if (MatchHeader(line, nlen, HH_CONTENT_LENGTH)) { - // sscanf isn't safe with strings that aren't null-terminated, and there - // is no guarantee that |value| is. - // Create a local copy that is null-terminated. - std::string value_str(value, vlen); - unsigned int temp_size; - if (sscanf(value_str.c_str(), "%u", &temp_size) != 1) { - *error = HE_PROTOCOL; - return PR_COMPLETE; - } - data_size_ = static_cast(temp_size); - } else if (MatchHeader(line, nlen, HH_TRANSFER_ENCODING)) { - if ((vlen == 7) && (_strnicmp(value, "chunked", 7) == 0)) { - chunked_ = true; - } else if ((vlen == 8) && (_strnicmp(value, "identity", 8) == 0)) { - chunked_ = false; - } else { - *error = HE_PROTOCOL; - return PR_COMPLETE; - } - } - return ProcessHeader(line, nlen, value, vlen, error); - } else { - state_ = chunked_ ? ST_CHUNKSIZE : ST_DATA; - return ProcessHeaderComplete(chunked_, data_size_, error); - } - break; - - case ST_CHUNKSIZE: - if (len > 0) { - char* ptr = nullptr; - data_size_ = strtoul(line, &ptr, 16); - if (ptr != line + len) { - *error = HE_PROTOCOL; - return PR_COMPLETE; - } - state_ = (data_size_ == 0) ? ST_TRAILERS : ST_DATA; - } else { - *error = HE_PROTOCOL; - return PR_COMPLETE; - } - break; - - case ST_CHUNKTERM: - if (len > 0) { - *error = HE_PROTOCOL; - return PR_COMPLETE; - } else { - state_ = chunked_ ? ST_CHUNKSIZE : ST_DATA; - } - break; - - case ST_TRAILERS: - if (len == 0) { - return PR_COMPLETE; - } - // *error = onHttpRecvTrailer(); - break; - - default: - RTC_NOTREACHED(); - break; - } - - return PR_CONTINUE; -} - -bool -HttpParser::is_valid_end_of_input() const { - return (state_ == ST_DATA) && (data_size_ == SIZE_UNKNOWN); -} - -void -HttpParser::complete(HttpError error) { - if (state_ < ST_COMPLETE) { - state_ = ST_COMPLETE; - OnComplete(error); - } -} - -////////////////////////////////////////////////////////////////////// -// HttpBase::DocumentStream -////////////////////////////////////////////////////////////////////// - -class BlockingMemoryStream : public ExternalMemoryStream { -public: - BlockingMemoryStream(char* buffer, size_t size) - : ExternalMemoryStream(buffer, size) { } - - StreamResult DoReserve(size_t size, int* error) override { - return (buffer_length_ >= size) ? SR_SUCCESS : SR_BLOCK; - } -}; - -class HttpBase::DocumentStream : public StreamInterface { -public: - DocumentStream(HttpBase* base) : base_(base), error_(HE_DEFAULT) { } - - StreamState GetState() const override { - if (nullptr == base_) - return SS_CLOSED; - if (HM_RECV == base_->mode_) - return SS_OPEN; - return SS_OPENING; - } - - StreamResult Read(void* buffer, - size_t buffer_len, - size_t* read, - int* error) override { - if (!base_) { - if (error) *error = error_; - return (HE_NONE == error_) ? SR_EOS : SR_ERROR; - } - - if (HM_RECV != base_->mode_) { - return SR_BLOCK; - } - - // DoReceiveLoop writes http document data to the StreamInterface* document - // member of HttpData. In this case, we want this data to be written - // directly to our buffer. To accomplish this, we wrap our buffer with a - // StreamInterface, and replace the existing document with our wrapper. - // When the method returns, we restore the old document. Ideally, we would - // pass our StreamInterface* to DoReceiveLoop, but due to the callbacks - // of HttpParser, we would still need to store the pointer temporarily. - std::unique_ptr stream( - new BlockingMemoryStream(reinterpret_cast(buffer), buffer_len)); - - // Replace the existing document with our wrapped buffer. - base_->data_->document.swap(stream); - - // Pump the I/O loop. DoReceiveLoop is guaranteed not to attempt to - // complete the I/O process, which means that our wrapper is not in danger - // of being deleted. To ensure this, DoReceiveLoop returns true when it - // wants complete to be called. We make sure to uninstall our wrapper - // before calling complete(). - HttpError http_error; - bool complete = base_->DoReceiveLoop(&http_error); - - // Reinstall the original output document. - base_->data_->document.swap(stream); - - // If we reach the end of the receive stream, we disconnect our stream - // adapter from the HttpBase, and further calls to read will either return - // EOS or ERROR, appropriately. Finally, we call complete(). - StreamResult result = SR_BLOCK; - if (complete) { - HttpBase* base = Disconnect(http_error); - if (error) *error = error_; - result = (HE_NONE == error_) ? SR_EOS : SR_ERROR; - base->complete(http_error); - } - - // Even if we are complete, if some data was read we must return SUCCESS. - // Future Reads will return EOS or ERROR based on the error_ variable. - size_t position; - stream->GetPosition(&position); - if (position > 0) { - if (read) *read = position; - result = SR_SUCCESS; - } - return result; - } - - StreamResult Write(const void* data, - size_t data_len, - size_t* written, - int* error) override { - if (error) *error = -1; - return SR_ERROR; - } - - void Close() override { - if (base_) { - HttpBase* base = Disconnect(HE_NONE); - if (HM_RECV == base->mode_ && base->http_stream_) { - // Read I/O could have been stalled on the user of this DocumentStream, - // so restart the I/O process now that we've removed ourselves. - base->http_stream_->PostEvent(SE_READ, 0); - } - } - } - - bool GetAvailable(size_t* size) const override { - if (!base_ || HM_RECV != base_->mode_) - return false; - size_t data_size = base_->GetDataRemaining(); - if (SIZE_UNKNOWN == data_size) - return false; - if (size) - *size = data_size; - return true; - } - - HttpBase* Disconnect(HttpError error) { - RTC_DCHECK(nullptr != base_); - RTC_DCHECK(nullptr != base_->doc_stream_); - HttpBase* base = base_; - base_->doc_stream_ = nullptr; - base_ = nullptr; - error_ = error; - return base; - } - -private: - HttpBase* base_; - HttpError error_; -}; - -////////////////////////////////////////////////////////////////////// -// HttpBase -////////////////////////////////////////////////////////////////////// - -HttpBase::HttpBase() - : mode_(HM_NONE), - data_(nullptr), - notify_(nullptr), - http_stream_(nullptr), - doc_stream_(nullptr) {} - -HttpBase::~HttpBase() { - RTC_DCHECK(HM_NONE == mode_); -} - -bool -HttpBase::isConnected() const { - return (http_stream_ != nullptr) && (http_stream_->GetState() == SS_OPEN); -} - -bool -HttpBase::attach(StreamInterface* stream) { - if ((mode_ != HM_NONE) || (http_stream_ != nullptr) || (stream == nullptr)) { - RTC_NOTREACHED(); - return false; - } - http_stream_ = stream; - http_stream_->SignalEvent.connect(this, &HttpBase::OnHttpStreamEvent); - mode_ = (http_stream_->GetState() == SS_OPENING) ? HM_CONNECT : HM_NONE; - return true; -} - -StreamInterface* -HttpBase::detach() { - RTC_DCHECK(HM_NONE == mode_); - if (mode_ != HM_NONE) { - return nullptr; - } - StreamInterface* stream = http_stream_; - http_stream_ = nullptr; - if (stream) { - stream->SignalEvent.disconnect(this); - } - return stream; -} - -void -HttpBase::send(HttpData* data) { - RTC_DCHECK(HM_NONE == mode_); - if (mode_ != HM_NONE) { - return; - } else if (!isConnected()) { - OnHttpStreamEvent(http_stream_, SE_CLOSE, HE_DISCONNECTED); - return; - } - - mode_ = HM_SEND; - data_ = data; - len_ = 0; - ignore_data_ = chunk_data_ = false; - - if (data_->document) { - data_->document->SignalEvent.connect(this, &HttpBase::OnDocumentEvent); - } - - std::string encoding; - if (data_->hasHeader(HH_TRANSFER_ENCODING, &encoding) - && (encoding == "chunked")) { - chunk_data_ = true; - } - - len_ = data_->formatLeader(buffer_, sizeof(buffer_)); - len_ += strcpyn(buffer_ + len_, sizeof(buffer_) - len_, "\r\n"); - - header_ = data_->begin(); - if (header_ == data_->end()) { - // We must call this at least once, in the case where there are no headers. - queue_headers(); - } - - flush_data(); -} - -void -HttpBase::recv(HttpData* data) { - RTC_DCHECK(HM_NONE == mode_); - if (mode_ != HM_NONE) { - return; - } else if (!isConnected()) { - OnHttpStreamEvent(http_stream_, SE_CLOSE, HE_DISCONNECTED); - return; - } - - mode_ = HM_RECV; - data_ = data; - len_ = 0; - ignore_data_ = chunk_data_ = false; - - reset(); - if (doc_stream_) { - doc_stream_->SignalEvent(doc_stream_, SE_OPEN | SE_READ, 0); - } else { - read_and_process_data(); - } -} - -void -HttpBase::abort(HttpError err) { - if (mode_ != HM_NONE) { - if (http_stream_ != nullptr) { - http_stream_->Close(); - } - do_complete(err); - } -} - -StreamInterface* HttpBase::GetDocumentStream() { - if (doc_stream_) - return nullptr; - doc_stream_ = new DocumentStream(this); - return doc_stream_; -} - -HttpError HttpBase::HandleStreamClose(int error) { - if (http_stream_ != nullptr) { - http_stream_->Close(); - } - if (error == 0) { - if ((mode_ == HM_RECV) && is_valid_end_of_input()) { - return HE_NONE; - } else { - return HE_DISCONNECTED; - } - } else if (error == SOCKET_EACCES) { - return HE_AUTH; - } else if (error == SEC_E_CERT_EXPIRED) { - return HE_CERTIFICATE_EXPIRED; - } - LOG_F(LS_ERROR) << "(" << error << ")"; - return (HM_CONNECT == mode_) ? HE_CONNECT_FAILED : HE_SOCKET_ERROR; -} - -bool HttpBase::DoReceiveLoop(HttpError* error) { - RTC_DCHECK(HM_RECV == mode_); - RTC_DCHECK(nullptr != error); - - // Do to the latency between receiving read notifications from - // pseudotcpchannel, we rely on repeated calls to read in order to acheive - // ideal throughput. The number of reads is limited to prevent starving - // the caller. - - size_t loop_count = 0; - const size_t kMaxReadCount = 20; - bool process_requires_more_data = false; - do { - // The most frequent use of this function is response to new data available - // on http_stream_. Therefore, we optimize by attempting to read from the - // network first (as opposed to processing existing data first). - - if (len_ < sizeof(buffer_)) { - // Attempt to buffer more data. - size_t read; - int read_error; - StreamResult read_result = http_stream_->Read(buffer_ + len_, - sizeof(buffer_) - len_, - &read, &read_error); - switch (read_result) { - case SR_SUCCESS: - RTC_DCHECK(len_ + read <= sizeof(buffer_)); - len_ += read; - break; - case SR_BLOCK: - if (process_requires_more_data) { - // We're can't make progress until more data is available. - return false; - } - // Attempt to process the data already in our buffer. - break; - case SR_EOS: - // Clean close, with no error. - read_error = 0; - FALLTHROUGH(); // Fall through to HandleStreamClose. - case SR_ERROR: - *error = HandleStreamClose(read_error); - return true; - } - } else if (process_requires_more_data) { - // We have too much unprocessed data in our buffer. This should only - // occur when a single HTTP header is longer than the buffer size (32K). - // Anything longer than that is almost certainly an error. - *error = HE_OVERFLOW; - return true; - } - - // Process data in our buffer. Process is not guaranteed to process all - // the buffered data. In particular, it will wait until a complete - // protocol element (such as http header, or chunk size) is available, - // before processing it in its entirety. Also, it is valid and sometimes - // necessary to call Process with an empty buffer, since the state machine - // may have interrupted state transitions to complete. - size_t processed; - ProcessResult process_result = Process(buffer_, len_, &processed, - error); - RTC_DCHECK(processed <= len_); - len_ -= processed; - memmove(buffer_, buffer_ + processed, len_); - switch (process_result) { - case PR_CONTINUE: - // We need more data to make progress. - process_requires_more_data = true; - break; - case PR_BLOCK: - // We're stalled on writing the processed data. - return false; - case PR_COMPLETE: - // *error already contains the correct code. - return true; - } - } while (++loop_count <= kMaxReadCount); - - LOG_F(LS_WARNING) << "danger of starvation"; - return false; -} - -void -HttpBase::read_and_process_data() { - HttpError error; - if (DoReceiveLoop(&error)) { - complete(error); - } -} - -void -HttpBase::flush_data() { - RTC_DCHECK(HM_SEND == mode_); - - // When send_required is true, no more buffering can occur without a network - // write. - bool send_required = (len_ >= sizeof(buffer_)); - - while (true) { - RTC_DCHECK(len_ <= sizeof(buffer_)); - - // HTTP is inherently sensitive to round trip latency, since a frequent use - // case is for small requests and responses to be sent back and forth, and - // the lack of pipelining forces a single request to take a minimum of the - // round trip time. As a result, it is to our benefit to pack as much data - // into each packet as possible. Thus, we defer network writes until we've - // buffered as much data as possible. - - if (!send_required && (header_ != data_->end())) { - // First, attempt to queue more header data. - send_required = queue_headers(); - } - - if (!send_required && data_->document) { - // Next, attempt to queue document data. - - const size_t kChunkDigits = 8; - size_t offset, reserve; - if (chunk_data_) { - // Reserve characters at the start for X-byte hex value and \r\n - offset = len_ + kChunkDigits + 2; - // ... and 2 characters at the end for \r\n - reserve = offset + 2; - } else { - offset = len_; - reserve = offset; - } - - if (reserve >= sizeof(buffer_)) { - send_required = true; - } else { - size_t read; - int error; - StreamResult result = data_->document->Read(buffer_ + offset, - sizeof(buffer_) - reserve, - &read, &error); - if (result == SR_SUCCESS) { - RTC_DCHECK(reserve + read <= sizeof(buffer_)); - if (chunk_data_) { - // Prepend the chunk length in hex. - // Note: sprintfn appends a null terminator, which is why we can't - // combine it with the line terminator. - sprintfn(buffer_ + len_, kChunkDigits + 1, "%.*x", - kChunkDigits, read); - // Add line terminator to the chunk length. - memcpy(buffer_ + len_ + kChunkDigits, "\r\n", 2); - // Add line terminator to the end of the chunk. - memcpy(buffer_ + offset + read, "\r\n", 2); - } - len_ = reserve + read; - } else if (result == SR_BLOCK) { - // Nothing to do but flush data to the network. - send_required = true; - } else if (result == SR_EOS) { - if (chunk_data_) { - // Append the empty chunk and empty trailers, then turn off - // chunking. - RTC_DCHECK(len_ + 5 <= sizeof(buffer_)); - memcpy(buffer_ + len_, "0\r\n\r\n", 5); - len_ += 5; - chunk_data_ = false; - } else if (0 == len_) { - // No more data to read, and no more data to write. - do_complete(); - return; - } - // Although we are done reading data, there is still data which needs - // to be flushed to the network. - send_required = true; - } else { - LOG_F(LS_ERROR) << "Read error: " << error; - do_complete(HE_STREAM); - return; - } - } - } - - if (0 == len_) { - // No data currently available to send. - if (!data_->document) { - // If there is no source document, that means we're done. - do_complete(); - } - return; - } - - size_t written; - int error; - StreamResult result = http_stream_->Write(buffer_, len_, &written, &error); - if (result == SR_SUCCESS) { - RTC_DCHECK(written <= len_); - len_ -= written; - memmove(buffer_, buffer_ + written, len_); - send_required = false; - } else if (result == SR_BLOCK) { - if (send_required) { - // Nothing more we can do until network is writeable. - return; - } - } else { - RTC_DCHECK(result == SR_ERROR); - LOG_F(LS_ERROR) << "error"; - OnHttpStreamEvent(http_stream_, SE_CLOSE, error); - return; - } - } - - RTC_NOTREACHED(); -} - -bool -HttpBase::queue_headers() { - RTC_DCHECK(HM_SEND == mode_); - while (header_ != data_->end()) { - size_t len = sprintfn(buffer_ + len_, sizeof(buffer_) - len_, - "%.*s: %.*s\r\n", - header_->first.size(), header_->first.data(), - header_->second.size(), header_->second.data()); - if (len_ + len < sizeof(buffer_) - 3) { - len_ += len; - ++header_; - } else if (len_ == 0) { - LOG(WARNING) << "discarding header that is too long: " << header_->first; - ++header_; - } else { - // Not enough room for the next header, write to network first. - return true; - } - } - // End of headers - len_ += strcpyn(buffer_ + len_, sizeof(buffer_) - len_, "\r\n"); - return false; -} - -void -HttpBase::do_complete(HttpError err) { - RTC_DCHECK(mode_ != HM_NONE); - HttpMode mode = mode_; - mode_ = HM_NONE; - if (data_ && data_->document) { - data_->document->SignalEvent.disconnect(this); - } - data_ = nullptr; - if ((HM_RECV == mode) && doc_stream_) { - RTC_DCHECK(HE_NONE != - err); // We should have Disconnected doc_stream_ already. - DocumentStream* ds = doc_stream_; - ds->Disconnect(err); - ds->SignalEvent(ds, SE_CLOSE, err); - } - if (notify_) { - notify_->onHttpComplete(mode, err); - } -} - -// -// Stream Signals -// - -void -HttpBase::OnHttpStreamEvent(StreamInterface* stream, int events, int error) { - RTC_DCHECK(stream == http_stream_); - if ((events & SE_OPEN) && (mode_ == HM_CONNECT)) { - do_complete(); - return; - } - - if ((events & SE_WRITE) && (mode_ == HM_SEND)) { - flush_data(); - return; - } - - if ((events & SE_READ) && (mode_ == HM_RECV)) { - if (doc_stream_) { - doc_stream_->SignalEvent(doc_stream_, SE_READ, 0); - } else { - read_and_process_data(); - } - return; - } - - if ((events & SE_CLOSE) == 0) - return; - - HttpError http_error = HandleStreamClose(error); - if (mode_ == HM_RECV) { - complete(http_error); - } else if (mode_ != HM_NONE) { - do_complete(http_error); - } else if (notify_) { - notify_->onHttpClosed(http_error); - } -} - -void -HttpBase::OnDocumentEvent(StreamInterface* stream, int events, int error) { - RTC_DCHECK(stream == data_->document.get()); - if ((events & SE_WRITE) && (mode_ == HM_RECV)) { - read_and_process_data(); - return; - } - - if ((events & SE_READ) && (mode_ == HM_SEND)) { - flush_data(); - return; - } - - if (events & SE_CLOSE) { - LOG_F(LS_ERROR) << "Read error: " << error; - do_complete(HE_STREAM); - return; - } -} - -// -// HttpParser Implementation -// - -HttpParser::ProcessResult -HttpBase::ProcessLeader(const char* line, size_t len, HttpError* error) { - *error = data_->parseLeader(line, len); - return (HE_NONE == *error) ? PR_CONTINUE : PR_COMPLETE; -} - -HttpParser::ProcessResult -HttpBase::ProcessHeader(const char* name, size_t nlen, const char* value, - size_t vlen, HttpError* error) { - std::string sname(name, nlen), svalue(value, vlen); - data_->addHeader(sname, svalue); - return PR_CONTINUE; -} - -HttpParser::ProcessResult -HttpBase::ProcessHeaderComplete(bool chunked, size_t& data_size, - HttpError* error) { - StreamInterface* old_docstream = doc_stream_; - if (notify_) { - *error = notify_->onHttpHeaderComplete(chunked, data_size); - // The request must not be aborted as a result of this callback. - RTC_DCHECK(nullptr != data_); - } - if ((HE_NONE == *error) && data_->document) { - data_->document->SignalEvent.connect(this, &HttpBase::OnDocumentEvent); - } - if (HE_NONE != *error) { - return PR_COMPLETE; - } - if (old_docstream != doc_stream_) { - // Break out of Process loop, since our I/O model just changed. - return PR_BLOCK; - } - return PR_CONTINUE; -} - -HttpParser::ProcessResult -HttpBase::ProcessData(const char* data, size_t len, size_t& read, - HttpError* error) { - if (ignore_data_ || !data_->document) { - read = len; - return PR_CONTINUE; - } - int write_error = 0; - switch (data_->document->Write(data, len, &read, &write_error)) { - case SR_SUCCESS: - return PR_CONTINUE; - case SR_BLOCK: - return PR_BLOCK; - case SR_EOS: - LOG_F(LS_ERROR) << "Unexpected EOS"; - *error = HE_STREAM; - return PR_COMPLETE; - case SR_ERROR: - default: - LOG_F(LS_ERROR) << "Write error: " << write_error; - *error = HE_STREAM; - return PR_COMPLETE; - } -} - -void -HttpBase::OnComplete(HttpError err) { - LOG_F(LS_VERBOSE); - do_complete(err); -} - -} // namespace rtc diff --git a/webrtc/base/httpbase.h b/webrtc/base/httpbase.h deleted file mode 100644 index 4b834a4e5b..0000000000 --- a/webrtc/base/httpbase.h +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - - -#ifndef WEBRTC_BASE_HTTPBASE_H__ -#define WEBRTC_BASE_HTTPBASE_H__ - -#include "webrtc/base/httpcommon.h" - -namespace rtc { - -class StreamInterface; - -/////////////////////////////////////////////////////////////////////////////// -// HttpParser - Parses an HTTP stream provided via Process and end_of_input, and -// generates events for: -// Structural Elements: Leader, Headers, Document Data -// Events: End of Headers, End of Document, Errors -/////////////////////////////////////////////////////////////////////////////// - -class HttpParser { -public: - enum ProcessResult { PR_CONTINUE, PR_BLOCK, PR_COMPLETE }; - HttpParser(); - virtual ~HttpParser(); - - void reset(); - ProcessResult Process(const char* buffer, size_t len, size_t* processed, - HttpError* error); - bool is_valid_end_of_input() const; - void complete(HttpError err); - - size_t GetDataRemaining() const { return data_size_; } - -protected: - ProcessResult ProcessLine(const char* line, size_t len, HttpError* error); - - // HttpParser Interface - virtual ProcessResult ProcessLeader(const char* line, size_t len, - HttpError* error) = 0; - virtual ProcessResult ProcessHeader(const char* name, size_t nlen, - const char* value, size_t vlen, - HttpError* error) = 0; - virtual ProcessResult ProcessHeaderComplete(bool chunked, size_t& data_size, - HttpError* error) = 0; - virtual ProcessResult ProcessData(const char* data, size_t len, size_t& read, - HttpError* error) = 0; - virtual void OnComplete(HttpError err) = 0; - -private: - enum State { - ST_LEADER, ST_HEADERS, - ST_CHUNKSIZE, ST_CHUNKTERM, ST_TRAILERS, - ST_DATA, ST_COMPLETE - } state_; - bool chunked_; - size_t data_size_; -}; - -/////////////////////////////////////////////////////////////////////////////// -// IHttpNotify -/////////////////////////////////////////////////////////////////////////////// - -enum HttpMode { HM_NONE, HM_CONNECT, HM_RECV, HM_SEND }; - -class IHttpNotify { -public: - virtual ~IHttpNotify() {} - virtual HttpError onHttpHeaderComplete(bool chunked, size_t& data_size) = 0; - virtual void onHttpComplete(HttpMode mode, HttpError err) = 0; - virtual void onHttpClosed(HttpError err) = 0; -}; - -/////////////////////////////////////////////////////////////////////////////// -// HttpBase - Provides a state machine for implementing HTTP-based components. -// Attach HttpBase to a StreamInterface which represents a bidirectional HTTP -// stream, and then call send() or recv() to initiate sending or receiving one -// side of an HTTP transaction. By default, HttpBase operates as an I/O pump, -// moving data from the HTTP stream to the HttpData object and vice versa. -// However, it can also operate in stream mode, in which case the user of the -// stream interface drives I/O via calls to Read(). -/////////////////////////////////////////////////////////////////////////////// - -class HttpBase -: private HttpParser, - public sigslot::has_slots<> -{ -public: - HttpBase(); - ~HttpBase() override; - - void notify(IHttpNotify* notify) { notify_ = notify; } - bool attach(StreamInterface* stream); - StreamInterface* stream() { return http_stream_; } - StreamInterface* detach(); - bool isConnected() const; - - void send(HttpData* data); - void recv(HttpData* data); - void abort(HttpError err); - - HttpMode mode() const { return mode_; } - - void set_ignore_data(bool ignore) { ignore_data_ = ignore; } - bool ignore_data() const { return ignore_data_; } - - // Obtaining this stream puts HttpBase into stream mode until the stream - // is closed. HttpBase can only expose one open stream interface at a time. - // Further calls will return null. - StreamInterface* GetDocumentStream(); - -protected: - // Do cleanup when the http stream closes (error may be 0 for a clean - // shutdown), and return the error code to signal. - HttpError HandleStreamClose(int error); - - // DoReceiveLoop acts as a data pump, pulling data from the http stream, - // pushing it through the HttpParser, and then populating the HttpData object - // based on the callbacks from the parser. One of the most interesting - // callbacks is ProcessData, which provides the actual http document body. - // This data is then written to the HttpData::document. As a result, data - // flows from the network to the document, with some incidental protocol - // parsing in between. - // Ideally, we would pass in the document* to DoReceiveLoop, to more easily - // support GetDocumentStream(). However, since the HttpParser is callback - // driven, we are forced to store the pointer somewhere until the callback - // is triggered. - // Returns true if the received document has finished, and - // HttpParser::complete should be called. - bool DoReceiveLoop(HttpError* err); - - void read_and_process_data(); - void flush_data(); - bool queue_headers(); - void do_complete(HttpError err = HE_NONE); - - void OnHttpStreamEvent(StreamInterface* stream, int events, int error); - void OnDocumentEvent(StreamInterface* stream, int events, int error); - - // HttpParser Interface - ProcessResult ProcessLeader(const char* line, - size_t len, - HttpError* error) override; - ProcessResult ProcessHeader(const char* name, - size_t nlen, - const char* value, - size_t vlen, - HttpError* error) override; - ProcessResult ProcessHeaderComplete(bool chunked, - size_t& data_size, - HttpError* error) override; - ProcessResult ProcessData(const char* data, - size_t len, - size_t& read, - HttpError* error) override; - void OnComplete(HttpError err) override; - -private: - class DocumentStream; - friend class DocumentStream; - - enum { kBufferSize = 32 * 1024 }; - - HttpMode mode_; - HttpData* data_; - IHttpNotify* notify_; - StreamInterface* http_stream_; - DocumentStream* doc_stream_; - char buffer_[kBufferSize]; - size_t len_; - - bool ignore_data_, chunk_data_; - HttpData::const_iterator header_; -}; - -/////////////////////////////////////////////////////////////////////////////// - -} // namespace rtc - -#endif // WEBRTC_BASE_HTTPBASE_H__ diff --git a/webrtc/base/httpbase_unittest.cc b/webrtc/base/httpbase_unittest.cc deleted file mode 100644 index 52c1c53fb1..0000000000 --- a/webrtc/base/httpbase_unittest.cc +++ /dev/null @@ -1,526 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include - -#include "webrtc/base/gunit.h" -#include "webrtc/base/httpbase.h" -#include "webrtc/base/testutils.h" - -namespace rtc { - -const char* const kHttpResponse = - "HTTP/1.1 200\r\n" - "Connection: Keep-Alive\r\n" - "Content-Type: text/plain\r\n" - "Proxy-Authorization: 42\r\n" - "Transfer-Encoding: chunked\r\n" - "\r\n" - "00000008\r\n" - "Goodbye!\r\n" - "0\r\n\r\n"; - -const char* const kHttpEmptyResponse = - "HTTP/1.1 200\r\n" - "Connection: Keep-Alive\r\n" - "Content-Length: 0\r\n" - "Proxy-Authorization: 42\r\n" - "\r\n"; - -const char* const kHttpResponsePrefix = - "HTTP/1.1 200\r\n" - "Connection: Keep-Alive\r\n" - "Content-Type: text/plain\r\n" - "Proxy-Authorization: 42\r\n" - "Transfer-Encoding: chunked\r\n" - "\r\n" - "8\r\n" - "Goodbye!\r\n"; - -class HttpBaseTest : public testing::Test, public IHttpNotify { -public: - enum EventType { E_HEADER_COMPLETE, E_COMPLETE, E_CLOSED }; - struct Event { - EventType event; - bool chunked; - size_t data_size; - HttpMode mode; - HttpError err; - }; - HttpBaseTest() : mem(nullptr), obtain_stream(false), http_stream(nullptr) {} - - virtual void SetUp() { } - virtual void TearDown() { - delete http_stream; - // Avoid an ASSERT, in case a test doesn't clean up properly - base.abort(HE_NONE); - } - - virtual HttpError onHttpHeaderComplete(bool chunked, size_t& data_size) { - LOG_F(LS_VERBOSE) << "chunked: " << chunked << " size: " << data_size; - Event e = { E_HEADER_COMPLETE, chunked, data_size, HM_NONE, HE_NONE}; - events.push_back(e); - if (obtain_stream) { - ObtainDocumentStream(); - } - return HE_NONE; - } - virtual void onHttpComplete(HttpMode mode, HttpError err) { - LOG_F(LS_VERBOSE) << "mode: " << mode << " err: " << err; - Event e = { E_COMPLETE, false, 0, mode, err }; - events.push_back(e); - } - virtual void onHttpClosed(HttpError err) { - LOG_F(LS_VERBOSE) << "err: " << err; - Event e = { E_CLOSED, false, 0, HM_NONE, err }; - events.push_back(e); - } - - void SetupSource(const char* response); - - void VerifyHeaderComplete(size_t event_count, bool empty_doc); - void VerifyDocumentContents(const char* expected_data, - size_t expected_length = SIZE_UNKNOWN); - - void ObtainDocumentStream(); - void VerifyDocumentStreamIsOpening(); - void VerifyDocumentStreamOpenEvent(); - void ReadDocumentStreamData(const char* expected_data); - void VerifyDocumentStreamIsEOS(); - - void SetupDocument(const char* response); - void VerifySourceContents(const char* expected_data, - size_t expected_length = SIZE_UNKNOWN); - - void VerifyTransferComplete(HttpMode mode, HttpError error); - - HttpBase base; - MemoryStream* mem; - HttpResponseData data; - - // The source of http data, and source events - testing::StreamSource src; - std::vector events; - - // Document stream, and stream events - bool obtain_stream; - StreamInterface* http_stream; - testing::StreamSink sink; -}; - -void HttpBaseTest::SetupSource(const char* http_data) { - LOG_F(LS_VERBOSE) << "Enter"; - - src.SetState(SS_OPENING); - src.QueueString(http_data); - - base.notify(this); - base.attach(&src); - EXPECT_TRUE(events.empty()); - - src.SetState(SS_OPEN); - ASSERT_EQ(1U, events.size()); - EXPECT_EQ(E_COMPLETE, events[0].event); - EXPECT_EQ(HM_CONNECT, events[0].mode); - EXPECT_EQ(HE_NONE, events[0].err); - events.clear(); - - mem = new MemoryStream; - data.document.reset(mem); - LOG_F(LS_VERBOSE) << "Exit"; -} - -void HttpBaseTest::VerifyHeaderComplete(size_t event_count, bool empty_doc) { - LOG_F(LS_VERBOSE) << "Enter"; - - ASSERT_EQ(event_count, events.size()); - EXPECT_EQ(E_HEADER_COMPLETE, events[0].event); - - std::string header; - EXPECT_EQ(HVER_1_1, data.version); - EXPECT_EQ(static_cast(HC_OK), data.scode); - EXPECT_TRUE(data.hasHeader(HH_PROXY_AUTHORIZATION, &header)); - EXPECT_EQ("42", header); - EXPECT_TRUE(data.hasHeader(HH_CONNECTION, &header)); - EXPECT_EQ("Keep-Alive", header); - - if (empty_doc) { - EXPECT_FALSE(events[0].chunked); - EXPECT_EQ(0U, events[0].data_size); - - EXPECT_TRUE(data.hasHeader(HH_CONTENT_LENGTH, &header)); - EXPECT_EQ("0", header); - } else { - EXPECT_TRUE(events[0].chunked); - EXPECT_EQ(SIZE_UNKNOWN, events[0].data_size); - - EXPECT_TRUE(data.hasHeader(HH_CONTENT_TYPE, &header)); - EXPECT_EQ("text/plain", header); - EXPECT_TRUE(data.hasHeader(HH_TRANSFER_ENCODING, &header)); - EXPECT_EQ("chunked", header); - } - LOG_F(LS_VERBOSE) << "Exit"; -} - -void HttpBaseTest::VerifyDocumentContents(const char* expected_data, - size_t expected_length) { - LOG_F(LS_VERBOSE) << "Enter"; - - if (SIZE_UNKNOWN == expected_length) { - expected_length = strlen(expected_data); - } - EXPECT_EQ(mem, data.document.get()); - - size_t length; - mem->GetSize(&length); - EXPECT_EQ(expected_length, length); - EXPECT_TRUE(0 == memcmp(expected_data, mem->GetBuffer(), length)); - LOG_F(LS_VERBOSE) << "Exit"; -} - -void HttpBaseTest::ObtainDocumentStream() { - LOG_F(LS_VERBOSE) << "Enter"; - EXPECT_FALSE(http_stream); - http_stream = base.GetDocumentStream(); - ASSERT_TRUE(nullptr != http_stream); - sink.Monitor(http_stream); - LOG_F(LS_VERBOSE) << "Exit"; -} - -void HttpBaseTest::VerifyDocumentStreamIsOpening() { - LOG_F(LS_VERBOSE) << "Enter"; - ASSERT_TRUE(nullptr != http_stream); - EXPECT_EQ(0, sink.Events(http_stream)); - EXPECT_EQ(SS_OPENING, http_stream->GetState()); - - size_t read = 0; - char buffer[5] = { 0 }; - EXPECT_EQ(SR_BLOCK, - http_stream->Read(buffer, sizeof(buffer), &read, nullptr)); - LOG_F(LS_VERBOSE) << "Exit"; -} - -void HttpBaseTest::VerifyDocumentStreamOpenEvent() { - LOG_F(LS_VERBOSE) << "Enter"; - - ASSERT_TRUE(nullptr != http_stream); - EXPECT_EQ(SE_OPEN | SE_READ, sink.Events(http_stream)); - EXPECT_EQ(SS_OPEN, http_stream->GetState()); - - // HTTP headers haven't arrived yet - EXPECT_EQ(0U, events.size()); - EXPECT_EQ(static_cast(HC_INTERNAL_SERVER_ERROR), data.scode); - LOG_F(LS_VERBOSE) << "Exit"; -} - -void HttpBaseTest::ReadDocumentStreamData(const char* expected_data) { - LOG_F(LS_VERBOSE) << "Enter"; - - ASSERT_TRUE(nullptr != http_stream); - EXPECT_EQ(SS_OPEN, http_stream->GetState()); - - // Pump the HTTP I/O using Read, and verify the results. - size_t verified_length = 0; - const size_t expected_length = strlen(expected_data); - while (verified_length < expected_length) { - size_t read = 0; - char buffer[5] = { 0 }; - size_t amt_to_read = - std::min(expected_length - verified_length, sizeof(buffer)); - EXPECT_EQ(SR_SUCCESS, - http_stream->Read(buffer, amt_to_read, &read, nullptr)); - EXPECT_EQ(amt_to_read, read); - EXPECT_TRUE(0 == memcmp(expected_data + verified_length, buffer, read)); - verified_length += read; - } - LOG_F(LS_VERBOSE) << "Exit"; -} - -void HttpBaseTest::VerifyDocumentStreamIsEOS() { - LOG_F(LS_VERBOSE) << "Enter"; - - ASSERT_TRUE(nullptr != http_stream); - size_t read = 0; - char buffer[5] = { 0 }; - EXPECT_EQ(SR_EOS, http_stream->Read(buffer, sizeof(buffer), &read, nullptr)); - EXPECT_EQ(SS_CLOSED, http_stream->GetState()); - - // When EOS is caused by Read, we don't expect SE_CLOSE - EXPECT_EQ(0, sink.Events(http_stream)); - LOG_F(LS_VERBOSE) << "Exit"; -} - -void HttpBaseTest::SetupDocument(const char* document_data) { - LOG_F(LS_VERBOSE) << "Enter"; - src.SetState(SS_OPEN); - - base.notify(this); - base.attach(&src); - EXPECT_TRUE(events.empty()); - - if (document_data) { - // Note: we could just call data.set_success("text/plain", mem), but that - // won't allow us to use the chunked transfer encoding. - mem = new MemoryStream(document_data); - data.document.reset(mem); - data.setHeader(HH_CONTENT_TYPE, "text/plain"); - data.setHeader(HH_TRANSFER_ENCODING, "chunked"); - } else { - data.setHeader(HH_CONTENT_LENGTH, "0"); - } - data.scode = HC_OK; - data.setHeader(HH_PROXY_AUTHORIZATION, "42"); - data.setHeader(HH_CONNECTION, "Keep-Alive"); - LOG_F(LS_VERBOSE) << "Exit"; -} - -void HttpBaseTest::VerifySourceContents(const char* expected_data, - size_t expected_length) { - LOG_F(LS_VERBOSE) << "Enter"; - if (SIZE_UNKNOWN == expected_length) { - expected_length = strlen(expected_data); - } - std::string contents = src.ReadData(); - EXPECT_EQ(expected_length, contents.length()); - EXPECT_TRUE(0 == memcmp(expected_data, contents.data(), expected_length)); - LOG_F(LS_VERBOSE) << "Exit"; -} - -void HttpBaseTest::VerifyTransferComplete(HttpMode mode, HttpError error) { - LOG_F(LS_VERBOSE) << "Enter"; - // Verify that http operation has completed - ASSERT_TRUE(events.size() > 0); - size_t last_event = events.size() - 1; - EXPECT_EQ(E_COMPLETE, events[last_event].event); - EXPECT_EQ(mode, events[last_event].mode); - EXPECT_EQ(error, events[last_event].err); - LOG_F(LS_VERBOSE) << "Exit"; -} - -// -// Tests -// - -TEST_F(HttpBaseTest, SupportsSend) { - // Queue response document - SetupDocument("Goodbye!"); - - // Begin send - base.send(&data); - - // Send completed successfully - VerifyTransferComplete(HM_SEND, HE_NONE); - VerifySourceContents(kHttpResponse); -} - -TEST_F(HttpBaseTest, SupportsSendNoDocument) { - // Queue response document - SetupDocument(nullptr); - - // Begin send - base.send(&data); - - // Send completed successfully - VerifyTransferComplete(HM_SEND, HE_NONE); - VerifySourceContents(kHttpEmptyResponse); -} - -TEST_F(HttpBaseTest, SignalsCompleteOnInterruptedSend) { - // This test is attempting to expose a bug that occurs when a particular - // base objects is used for receiving, and then used for sending. In - // particular, the HttpParser state is different after receiving. Simulate - // that here. - SetupSource(kHttpResponse); - base.recv(&data); - VerifyTransferComplete(HM_RECV, HE_NONE); - - src.Clear(); - data.clear(true); - events.clear(); - base.detach(); - - // Queue response document - SetupDocument("Goodbye!"); - - // Prevent entire response from being sent - const size_t kInterruptedLength = strlen(kHttpResponse) - 1; - src.SetWriteBlock(kInterruptedLength); - - // Begin send - base.send(&data); - - // Document is mostly complete, but no completion signal yet. - EXPECT_TRUE(events.empty()); - VerifySourceContents(kHttpResponse, kInterruptedLength); - - src.SetState(SS_CLOSED); - - // Send completed with disconnect error, and no additional data. - VerifyTransferComplete(HM_SEND, HE_DISCONNECTED); - EXPECT_TRUE(src.ReadData().empty()); -} - -TEST_F(HttpBaseTest, SupportsReceiveViaDocumentPush) { - // Queue response document - SetupSource(kHttpResponse); - - // Begin receive - base.recv(&data); - - // Document completed successfully - VerifyHeaderComplete(2, false); - VerifyTransferComplete(HM_RECV, HE_NONE); - VerifyDocumentContents("Goodbye!"); -} - -TEST_F(HttpBaseTest, SupportsReceiveViaStreamPull) { - // Switch to pull mode - ObtainDocumentStream(); - VerifyDocumentStreamIsOpening(); - - // Queue response document - SetupSource(kHttpResponse); - VerifyDocumentStreamIsOpening(); - - // Begin receive - base.recv(&data); - - // Pull document data - VerifyDocumentStreamOpenEvent(); - ReadDocumentStreamData("Goodbye!"); - VerifyDocumentStreamIsEOS(); - - // Document completed successfully - VerifyHeaderComplete(2, false); - VerifyTransferComplete(HM_RECV, HE_NONE); - VerifyDocumentContents(""); -} - -TEST_F(HttpBaseTest, DISABLED_AllowsCloseStreamBeforeDocumentIsComplete) { - - // TODO: Remove extra logging once test failure is understood - LoggingSeverity old_sev = rtc::LogMessage::GetLogToDebug(); - rtc::LogMessage::LogToDebug(LS_VERBOSE); - - - // Switch to pull mode - ObtainDocumentStream(); - VerifyDocumentStreamIsOpening(); - - // Queue response document - SetupSource(kHttpResponse); - VerifyDocumentStreamIsOpening(); - - // Begin receive - base.recv(&data); - - // Pull some of the data - VerifyDocumentStreamOpenEvent(); - ReadDocumentStreamData("Goodb"); - - // We've seen the header by now - VerifyHeaderComplete(1, false); - - // Close the pull stream, this will transition back to push I/O. - http_stream->Close(); - Thread::Current()->ProcessMessages(0); - - // Remainder of document completed successfully - VerifyTransferComplete(HM_RECV, HE_NONE); - VerifyDocumentContents("ye!"); - - rtc::LogMessage::LogToDebug(old_sev); -} - -TEST_F(HttpBaseTest, AllowsGetDocumentStreamInResponseToHttpHeader) { - // Queue response document - SetupSource(kHttpResponse); - - // Switch to pull mode in response to header arrival - obtain_stream = true; - - // Begin receive - base.recv(&data); - - // We've already seen the header, but not data has arrived - VerifyHeaderComplete(1, false); - VerifyDocumentContents(""); - - // Pull the document data - ReadDocumentStreamData("Goodbye!"); - VerifyDocumentStreamIsEOS(); - - // Document completed successfully - VerifyTransferComplete(HM_RECV, HE_NONE); - VerifyDocumentContents(""); -} - -TEST_F(HttpBaseTest, AllowsGetDocumentStreamWithEmptyDocumentBody) { - // Queue empty response document - SetupSource(kHttpEmptyResponse); - - // Switch to pull mode in response to header arrival - obtain_stream = true; - - // Begin receive - base.recv(&data); - - // We've already seen the header, but not data has arrived - VerifyHeaderComplete(1, true); - VerifyDocumentContents(""); - - // The document is still open, until we attempt to read - ASSERT_TRUE(nullptr != http_stream); - EXPECT_EQ(SS_OPEN, http_stream->GetState()); - - // Attempt to read data, and discover EOS - VerifyDocumentStreamIsEOS(); - - // Document completed successfully - VerifyTransferComplete(HM_RECV, HE_NONE); - VerifyDocumentContents(""); -} - -TEST_F(HttpBaseTest, SignalsDocumentStreamCloseOnUnexpectedClose) { - // Switch to pull mode - ObtainDocumentStream(); - VerifyDocumentStreamIsOpening(); - - // Queue response document - SetupSource(kHttpResponsePrefix); - VerifyDocumentStreamIsOpening(); - - // Begin receive - base.recv(&data); - - // Pull document data - VerifyDocumentStreamOpenEvent(); - ReadDocumentStreamData("Goodbye!"); - - // Simulate unexpected close - src.SetState(SS_CLOSED); - - // Observe error event on document stream - EXPECT_EQ(testing::SSE_ERROR, sink.Events(http_stream)); - - // Future reads give an error - int error = 0; - char buffer[5] = { 0 }; - EXPECT_EQ(SR_ERROR, - http_stream->Read(buffer, sizeof(buffer), nullptr, &error)); - EXPECT_EQ(HE_DISCONNECTED, error); - - // Document completed with error - VerifyHeaderComplete(2, false); - VerifyTransferComplete(HM_RECV, HE_DISCONNECTED); - VerifyDocumentContents(""); -} - -} // namespace rtc diff --git a/webrtc/base/httpcommon-inl.h b/webrtc/base/httpcommon-inl.h deleted file mode 100644 index f29f075998..0000000000 --- a/webrtc/base/httpcommon-inl.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_BASE_HTTPCOMMON_INL_H__ -#define WEBRTC_BASE_HTTPCOMMON_INL_H__ - -#include "webrtc/base/arraysize.h" -#include "webrtc/base/checks.h" -#include "webrtc/base/httpcommon.h" - -namespace rtc { - -/////////////////////////////////////////////////////////////////////////////// -// Url -/////////////////////////////////////////////////////////////////////////////// - -template -void Url::do_set_url(const CTYPE* val, size_t len) { - if (ascnicmp(val, "http://", 7) == 0) { - val += 7; len -= 7; - secure_ = false; - } else if (ascnicmp(val, "https://", 8) == 0) { - val += 8; len -= 8; - secure_ = true; - } else { - clear(); - return; - } - const CTYPE* path = strchrn(val, len, static_cast('/')); - if (!path) { - path = val + len; - } - size_t address_length = (path - val); - do_set_address(val, address_length); - do_set_full_path(path, len - address_length); -} - -template -void Url::do_set_address(const CTYPE* val, size_t len) { - if (const CTYPE* at = strchrn(val, len, static_cast('@'))) { - // Everything before the @ is a user:password combo, so skip it. - len -= at - val + 1; - val = at + 1; - } - if (const CTYPE* colon = strchrn(val, len, static_cast(':'))) { - host_.assign(val, colon - val); - // Note: In every case, we're guaranteed that colon is followed by a null, - // or non-numeric character. - port_ = static_cast(::strtoul(colon + 1, nullptr, 10)); - // TODO: Consider checking for invalid data following port number. - } else { - host_.assign(val, len); - port_ = HttpDefaultPort(secure_); - } -} - -template -void Url::do_set_full_path(const CTYPE* val, size_t len) { - const CTYPE* query = strchrn(val, len, static_cast('?')); - if (!query) { - query = val + len; - } - size_t path_length = (query - val); - if (0 == path_length) { - // TODO: consider failing in this case. - path_.assign(1, static_cast('/')); - } else { - RTC_DCHECK(val[0] == static_cast('/')); - path_.assign(val, path_length); - } - query_.assign(query, len - path_length); -} - -template -void Url::do_get_url(string* val) const { - CTYPE protocol[9]; - asccpyn(protocol, arraysize(protocol), secure_ ? "https://" : "http://"); - val->append(protocol); - do_get_address(val); - do_get_full_path(val); -} - -template -void Url::do_get_address(string* val) const { - val->append(host_); - if (port_ != HttpDefaultPort(secure_)) { - CTYPE format[5], port[32]; - asccpyn(format, arraysize(format), ":%hu"); - sprintfn(port, arraysize(port), format, port_); - val->append(port); - } -} - -template -void Url::do_get_full_path(string* val) const { - val->append(path_); - val->append(query_); -} - -template -bool Url::get_attribute(const string& name, string* value) const { - if (query_.empty()) - return false; - - std::string::size_type pos = query_.find(name, 1); - if (std::string::npos == pos) - return false; - - pos += name.length() + 1; - if ((pos > query_.length()) || (static_cast('=') != query_[pos-1])) - return false; - - std::string::size_type end = query_.find(static_cast('&'), pos); - if (std::string::npos == end) { - end = query_.length(); - } - value->assign(query_.substr(pos, end - pos)); - return true; -} - -/////////////////////////////////////////////////////////////////////////////// - -} // namespace rtc - -#endif // WEBRTC_BASE_HTTPCOMMON_INL_H__ diff --git a/webrtc/base/httpcommon.cc b/webrtc/base/httpcommon.cc deleted file mode 100644 index 031505b7f9..0000000000 --- a/webrtc/base/httpcommon.cc +++ /dev/null @@ -1,1009 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include - -#if defined(WEBRTC_WIN) -#define WIN32_LEAN_AND_MEAN -#include -#include -#include -#define SECURITY_WIN32 -#include -#endif - -#include - -#include "webrtc/base/arraysize.h" -#include "webrtc/base/base64.h" -#include "webrtc/base/checks.h" -#include "webrtc/base/cryptstring.h" -#include "webrtc/base/httpcommon-inl.h" -#include "webrtc/base/httpcommon.h" -#include "webrtc/base/messagedigest.h" -#include "webrtc/base/socketaddress.h" -#include "webrtc/base/stringencode.h" -#include "webrtc/base/stringutils.h" - -namespace rtc { - -#if defined(WEBRTC_WIN) -extern const ConstantLabel SECURITY_ERRORS[]; -#endif - -////////////////////////////////////////////////////////////////////// -// Enum - TODO: expose globally later? -////////////////////////////////////////////////////////////////////// - -bool find_string(size_t& index, const std::string& needle, - const char* const haystack[], size_t max_index) { - for (index=0; index -struct Enum { - static const char** Names; - static size_t Size; - - static inline const char* Name(E val) { return Names[val]; } - static inline bool Parse(E& val, const std::string& name) { - size_t index; - if (!find_string(index, name, Names, Size)) - return false; - val = static_cast(index); - return true; - } - - E val; - - inline operator E&() { return val; } - inline Enum& operator=(E rhs) { val = rhs; return *this; } - - inline const char* name() const { return Name(val); } - inline bool assign(const std::string& name) { return Parse(val, name); } - inline Enum& operator=(const std::string& rhs) { assign(rhs); return *this; } -}; - -#define ENUM(e,n) \ - template<> const char** Enum::Names = n; \ - template<> size_t Enum::Size = sizeof(n)/sizeof(n[0]) - -////////////////////////////////////////////////////////////////////// -// HttpCommon -////////////////////////////////////////////////////////////////////// - -static const char* kHttpVersions[HVER_LAST+1] = { - "1.0", "1.1", "Unknown" -}; -ENUM(HttpVersion, kHttpVersions); - -static const char* kHttpVerbs[HV_LAST+1] = { - "GET", "POST", "PUT", "DELETE", "CONNECT", "HEAD" -}; -ENUM(HttpVerb, kHttpVerbs); - -static const char* kHttpHeaders[HH_LAST+1] = { - "Age", - "Cache-Control", - "Connection", - "Content-Disposition", - "Content-Length", - "Content-Range", - "Content-Type", - "Cookie", - "Date", - "ETag", - "Expires", - "Host", - "If-Modified-Since", - "If-None-Match", - "Keep-Alive", - "Last-Modified", - "Location", - "Proxy-Authenticate", - "Proxy-Authorization", - "Proxy-Connection", - "Range", - "Set-Cookie", - "TE", - "Trailers", - "Transfer-Encoding", - "Upgrade", - "User-Agent", - "WWW-Authenticate", -}; -ENUM(HttpHeader, kHttpHeaders); - -const char* ToString(HttpVersion version) { - return Enum::Name(version); -} - -bool FromString(HttpVersion& version, const std::string& str) { - return Enum::Parse(version, str); -} - -const char* ToString(HttpVerb verb) { - return Enum::Name(verb); -} - -bool FromString(HttpVerb& verb, const std::string& str) { - return Enum::Parse(verb, str); -} - -const char* ToString(HttpHeader header) { - return Enum::Name(header); -} - -bool FromString(HttpHeader& header, const std::string& str) { - return Enum::Parse(header, str); -} - -bool HttpCodeHasBody(uint32_t code) { - return !HttpCodeIsInformational(code) - && (code != HC_NO_CONTENT) && (code != HC_NOT_MODIFIED); -} - -bool HttpCodeIsCacheable(uint32_t code) { - switch (code) { - case HC_OK: - case HC_NON_AUTHORITATIVE: - case HC_PARTIAL_CONTENT: - case HC_MULTIPLE_CHOICES: - case HC_MOVED_PERMANENTLY: - case HC_GONE: - return true; - default: - return false; - } -} - -bool HttpHeaderIsEndToEnd(HttpHeader header) { - switch (header) { - case HH_CONNECTION: - case HH_KEEP_ALIVE: - case HH_PROXY_AUTHENTICATE: - case HH_PROXY_AUTHORIZATION: - case HH_PROXY_CONNECTION: // Note part of RFC... this is non-standard header - case HH_TE: - case HH_TRAILERS: - case HH_TRANSFER_ENCODING: - case HH_UPGRADE: - return false; - default: - return true; - } -} - -bool HttpHeaderIsCollapsible(HttpHeader header) { - switch (header) { - case HH_SET_COOKIE: - case HH_PROXY_AUTHENTICATE: - case HH_WWW_AUTHENTICATE: - return false; - default: - return true; - } -} - -bool HttpShouldKeepAlive(const HttpData& data) { - std::string connection; - if ((data.hasHeader(HH_PROXY_CONNECTION, &connection) - || data.hasHeader(HH_CONNECTION, &connection))) { - return (_stricmp(connection.c_str(), "Keep-Alive") == 0); - } - return (data.version >= HVER_1_1); -} - -namespace { - -inline bool IsEndOfAttributeName(size_t pos, size_t len, const char * data) { - if (pos >= len) - return true; - if (isspace(static_cast(data[pos]))) - return true; - // The reason for this complexity is that some attributes may contain trailing - // equal signs (like base64 tokens in Negotiate auth headers) - if ((pos+1 < len) && (data[pos] == '=') && - !isspace(static_cast(data[pos+1])) && - (data[pos+1] != '=')) { - return true; - } - return false; -} - -// TODO: unittest for EscapeAttribute and HttpComposeAttributes. - -std::string EscapeAttribute(const std::string& attribute) { - const size_t kMaxLength = attribute.length() * 2 + 1; - char* buffer = STACK_ARRAY(char, kMaxLength); - size_t len = escape(buffer, kMaxLength, attribute.data(), attribute.length(), - "\"", '\\'); - return std::string(buffer, len); -} - -} // anonymous namespace - -void HttpComposeAttributes(const HttpAttributeList& attributes, char separator, - std::string* composed) { - std::stringstream ss; - for (size_t i=0; i 0) { - ss << separator << " "; - } - ss << attributes[i].first; - if (!attributes[i].second.empty()) { - ss << "=\"" << EscapeAttribute(attributes[i].second) << "\""; - } - } - *composed = ss.str(); -} - -void HttpParseAttributes(const char * data, size_t len, - HttpAttributeList& attributes) { - size_t pos = 0; - while (true) { - // Skip leading whitespace - while ((pos < len) && isspace(static_cast(data[pos]))) { - ++pos; - } - - // End of attributes? - if (pos >= len) - return; - - // Find end of attribute name - size_t start = pos; - while (!IsEndOfAttributeName(pos, len, data)) { - ++pos; - } - - HttpAttribute attribute; - attribute.first.assign(data + start, data + pos); - - // Attribute has value? - if ((pos < len) && (data[pos] == '=')) { - ++pos; // Skip '=' - // Check if quoted value - if ((pos < len) && (data[pos] == '"')) { - while (++pos < len) { - if (data[pos] == '"') { - ++pos; - break; - } - if ((data[pos] == '\\') && (pos + 1 < len)) - ++pos; - attribute.second.append(1, data[pos]); - } - } else { - while ((pos < len) && - !isspace(static_cast(data[pos])) && - (data[pos] != ',')) { - attribute.second.append(1, data[pos++]); - } - } - } - - attributes.push_back(attribute); - if ((pos < len) && (data[pos] == ',')) ++pos; // Skip ',' - } -} - -bool HttpHasAttribute(const HttpAttributeList& attributes, - const std::string& name, - std::string* value) { - for (HttpAttributeList::const_iterator it = attributes.begin(); - it != attributes.end(); ++it) { - if (it->first == name) { - if (value) { - *value = it->second; - } - return true; - } - } - return false; -} - -bool HttpHasNthAttribute(HttpAttributeList& attributes, - size_t index, - std::string* name, - std::string* value) { - if (index >= attributes.size()) - return false; - - if (name) - *name = attributes[index].first; - if (value) - *value = attributes[index].second; - return true; -} - -bool HttpDateToSeconds(const std::string& date, time_t* seconds) { - const char* const kTimeZones[] = { - "UT", "GMT", "EST", "EDT", "CST", "CDT", "MST", "MDT", "PST", "PDT", - "A", "B", "C", "D", "E", "F", "G", "H", "I", "K", "L", "M", - "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y" - }; - const int kTimeZoneOffsets[] = { - 0, 0, -5, -4, -6, -5, -7, -6, -8, -7, - -1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12, - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 - }; - - RTC_DCHECK(nullptr != seconds); - struct tm tval; - memset(&tval, 0, sizeof(tval)); - char month[4], zone[6]; - memset(month, 0, sizeof(month)); - memset(zone, 0, sizeof(zone)); - - if (7 != sscanf(date.c_str(), "%*3s, %d %3s %d %d:%d:%d %5c", - &tval.tm_mday, month, &tval.tm_year, - &tval.tm_hour, &tval.tm_min, &tval.tm_sec, zone)) { - return false; - } - switch (toupper(month[2])) { - case 'N': tval.tm_mon = (month[1] == 'A') ? 0 : 5; break; - case 'B': tval.tm_mon = 1; break; - case 'R': tval.tm_mon = (month[0] == 'M') ? 2 : 3; break; - case 'Y': tval.tm_mon = 4; break; - case 'L': tval.tm_mon = 6; break; - case 'G': tval.tm_mon = 7; break; - case 'P': tval.tm_mon = 8; break; - case 'T': tval.tm_mon = 9; break; - case 'V': tval.tm_mon = 10; break; - case 'C': tval.tm_mon = 11; break; - } - tval.tm_year -= 1900; - time_t gmt, non_gmt = mktime(&tval); - if ((zone[0] == '+') || (zone[0] == '-')) { - if (!isdigit(zone[1]) || !isdigit(zone[2]) - || !isdigit(zone[3]) || !isdigit(zone[4])) { - return false; - } - int hours = (zone[1] - '0') * 10 + (zone[2] - '0'); - int minutes = (zone[3] - '0') * 10 + (zone[4] - '0'); - int offset = (hours * 60 + minutes) * 60; - gmt = non_gmt + ((zone[0] == '+') ? offset : -offset); - } else { - size_t zindex; - if (!find_string(zindex, zone, kTimeZones, arraysize(kTimeZones))) { - return false; - } - gmt = non_gmt + kTimeZoneOffsets[zindex] * 60 * 60; - } - // TODO: Android should support timezone, see b/2441195 -#if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS) || defined(WEBRTC_ANDROID) || defined(BSD) - tm *tm_for_timezone = localtime(&gmt); - *seconds = gmt + tm_for_timezone->tm_gmtoff; -#else -#if defined(_MSC_VER) && _MSC_VER >= 1900 - long timezone = 0; - _get_timezone(&timezone); -#endif - *seconds = gmt - timezone; -#endif - return true; -} - -std::string HttpAddress(const SocketAddress& address, bool secure) { - return (address.port() == HttpDefaultPort(secure)) - ? address.hostname() : address.ToString(); -} - -////////////////////////////////////////////////////////////////////// -// HttpData -////////////////////////////////////////////////////////////////////// - -HttpData::HttpData() : version(HVER_1_1) { -} - -HttpData::~HttpData() = default; - -void -HttpData::clear(bool release_document) { - // Clear headers first, since releasing a document may have far-reaching - // effects. - headers_.clear(); - if (release_document) { - document.reset(); - } -} - -void -HttpData::copy(const HttpData& src) { - headers_ = src.headers_; -} - -void -HttpData::changeHeader(const std::string& name, const std::string& value, - HeaderCombine combine) { - if (combine == HC_AUTO) { - HttpHeader header; - // Unrecognized headers are collapsible - combine = !FromString(header, name) || HttpHeaderIsCollapsible(header) - ? HC_YES : HC_NO; - } else if (combine == HC_REPLACE) { - headers_.erase(name); - combine = HC_NO; - } - // At this point, combine is one of (YES, NO, NEW) - if (combine != HC_NO) { - HeaderMap::iterator it = headers_.find(name); - if (it != headers_.end()) { - if (combine == HC_YES) { - it->second.append(","); - it->second.append(value); - } - return; - } - } - headers_.insert(HeaderMap::value_type(name, value)); -} - -size_t HttpData::clearHeader(const std::string& name) { - return headers_.erase(name); -} - -HttpData::iterator HttpData::clearHeader(iterator header) { - iterator deprecated = header++; - headers_.erase(deprecated); - return header; -} - -bool -HttpData::hasHeader(const std::string& name, std::string* value) const { - HeaderMap::const_iterator it = headers_.find(name); - if (it == headers_.end()) { - return false; - } else if (value) { - *value = it->second; - } - return true; -} - -void HttpData::setContent(const std::string& content_type, - StreamInterface* document) { - setHeader(HH_CONTENT_TYPE, content_type); - setDocumentAndLength(document); -} - -void HttpData::setDocumentAndLength(StreamInterface* document) { - // TODO: Consider calling Rewind() here? - RTC_DCHECK(!hasHeader(HH_CONTENT_LENGTH, nullptr)); - RTC_DCHECK(!hasHeader(HH_TRANSFER_ENCODING, nullptr)); - RTC_DCHECK(document != nullptr); - this->document.reset(document); - size_t content_length = 0; - if (this->document->GetAvailable(&content_length)) { - char buffer[32]; - sprintfn(buffer, sizeof(buffer), "%d", content_length); - setHeader(HH_CONTENT_LENGTH, buffer); - } else { - setHeader(HH_TRANSFER_ENCODING, "chunked"); - } -} - -// -// HttpRequestData -// - -void -HttpRequestData::clear(bool release_document) { - verb = HV_GET; - path.clear(); - HttpData::clear(release_document); -} - -void -HttpRequestData::copy(const HttpRequestData& src) { - verb = src.verb; - path = src.path; - HttpData::copy(src); -} - -size_t -HttpRequestData::formatLeader(char* buffer, size_t size) const { - RTC_DCHECK(path.find(' ') == std::string::npos); - return sprintfn(buffer, size, "%s %.*s HTTP/%s", ToString(verb), path.size(), - path.data(), ToString(version)); -} - -HttpError -HttpRequestData::parseLeader(const char* line, size_t len) { - unsigned int vmajor, vminor; - int vend, dstart, dend; - // sscanf isn't safe with strings that aren't null-terminated, and there is - // no guarantee that |line| is. Create a local copy that is null-terminated. - std::string line_str(line, len); - line = line_str.c_str(); - if ((sscanf(line, "%*s%n %n%*s%n HTTP/%u.%u", - &vend, &dstart, &dend, &vmajor, &vminor) != 2) - || (vmajor != 1)) { - return HE_PROTOCOL; - } - if (vminor == 0) { - version = HVER_1_0; - } else if (vminor == 1) { - version = HVER_1_1; - } else { - return HE_PROTOCOL; - } - std::string sverb(line, vend); - if (!FromString(verb, sverb.c_str())) { - return HE_PROTOCOL; // !?! HC_METHOD_NOT_SUPPORTED? - } - path.assign(line + dstart, line + dend); - return HE_NONE; -} - -bool HttpRequestData::getAbsoluteUri(std::string* uri) const { - if (HV_CONNECT == verb) - return false; - Url url(path); - if (url.valid()) { - uri->assign(path); - return true; - } - std::string host; - if (!hasHeader(HH_HOST, &host)) - return false; - url.set_address(host); - url.set_full_path(path); - uri->assign(url.url()); - return url.valid(); -} - -bool HttpRequestData::getRelativeUri(std::string* host, - std::string* path) const -{ - if (HV_CONNECT == verb) - return false; - Url url(this->path); - if (url.valid()) { - host->assign(url.address()); - path->assign(url.full_path()); - return true; - } - if (!hasHeader(HH_HOST, host)) - return false; - path->assign(this->path); - return true; -} - -// -// HttpResponseData -// - -void -HttpResponseData::clear(bool release_document) { - scode = HC_INTERNAL_SERVER_ERROR; - message.clear(); - HttpData::clear(release_document); -} - -void -HttpResponseData::copy(const HttpResponseData& src) { - scode = src.scode; - message = src.message; - HttpData::copy(src); -} - -void HttpResponseData::set_success(uint32_t scode) { - this->scode = scode; - message.clear(); - setHeader(HH_CONTENT_LENGTH, "0", false); -} - -void HttpResponseData::set_success(const std::string& content_type, - StreamInterface* document, - uint32_t scode) { - this->scode = scode; - message.erase(message.begin(), message.end()); - setContent(content_type, document); -} - -void HttpResponseData::set_redirect(const std::string& location, - uint32_t scode) { - this->scode = scode; - message.clear(); - setHeader(HH_LOCATION, location); - setHeader(HH_CONTENT_LENGTH, "0", false); -} - -void HttpResponseData::set_error(uint32_t scode) { - this->scode = scode; - message.clear(); - setHeader(HH_CONTENT_LENGTH, "0", false); -} - -size_t -HttpResponseData::formatLeader(char* buffer, size_t size) const { - size_t len = sprintfn(buffer, size, "HTTP/%s %lu", ToString(version), scode); - if (!message.empty()) { - len += sprintfn(buffer + len, size - len, " %.*s", - message.size(), message.data()); - } - return len; -} - -HttpError -HttpResponseData::parseLeader(const char* line, size_t len) { - size_t pos = 0; - unsigned int vmajor, vminor, temp_scode; - int temp_pos; - // sscanf isn't safe with strings that aren't null-terminated, and there is - // no guarantee that |line| is. Create a local copy that is null-terminated. - std::string line_str(line, len); - line = line_str.c_str(); - if (sscanf(line, "HTTP %u%n", - &temp_scode, &temp_pos) == 1) { - // This server's response has no version. :( NOTE: This happens for every - // response to requests made from Chrome plugins, regardless of the server's - // behaviour. - LOG(LS_VERBOSE) << "HTTP version missing from response"; - version = HVER_UNKNOWN; - } else if ((sscanf(line, "HTTP/%u.%u %u%n", - &vmajor, &vminor, &temp_scode, &temp_pos) == 3) - && (vmajor == 1)) { - // This server's response does have a version. - if (vminor == 0) { - version = HVER_1_0; - } else if (vminor == 1) { - version = HVER_1_1; - } else { - return HE_PROTOCOL; - } - } else { - return HE_PROTOCOL; - } - scode = temp_scode; - pos = static_cast(temp_pos); - while ((pos < len) && isspace(static_cast(line[pos]))) ++pos; - message.assign(line + pos, len - pos); - return HE_NONE; -} - -////////////////////////////////////////////////////////////////////// -// Http Authentication -////////////////////////////////////////////////////////////////////// - -std::string quote(const std::string& str) { - std::string result; - result.push_back('"'); - for (size_t i=0; iauth_method != auth_method)) - return HAR_IGNORE; - - // BASIC - if (_stricmp(auth_method.c_str(), "basic") == 0) { - if (context) - return HAR_CREDENTIALS; // Bad credentials - if (username.empty()) - return HAR_CREDENTIALS; // Missing credentials - - context = new HttpAuthContext(auth_method); - - // TODO: convert sensitive to a secure buffer that gets securely deleted - //std::string decoded = username + ":" + password; - size_t len = username.size() + password.GetLength() + 2; - char * sensitive = new char[len]; - size_t pos = strcpyn(sensitive, len, username.data(), username.size()); - pos += strcpyn(sensitive + pos, len - pos, ":"); - password.CopyTo(sensitive + pos, true); - - response = auth_method; - response.append(" "); - // TODO: create a sensitive-source version of Base64::encode - response.append(Base64::Encode(sensitive)); - memset(sensitive, 0, len); - delete [] sensitive; - return HAR_RESPONSE; - } - - // DIGEST - if (_stricmp(auth_method.c_str(), "digest") == 0) { - if (context) - return HAR_CREDENTIALS; // Bad credentials - if (username.empty()) - return HAR_CREDENTIALS; // Missing credentials - - context = new HttpAuthContext(auth_method); - - std::string cnonce, ncount; - char buffer[256]; - sprintf(buffer, "%d", static_cast(time(0))); - cnonce = MD5(buffer); - ncount = "00000001"; - - std::string realm, nonce, qop, opaque; - HttpHasAttribute(args, "realm", &realm); - HttpHasAttribute(args, "nonce", &nonce); - bool has_qop = HttpHasAttribute(args, "qop", &qop); - bool has_opaque = HttpHasAttribute(args, "opaque", &opaque); - - // TODO: convert sensitive to be secure buffer - //std::string A1 = username + ":" + realm + ":" + password; - size_t len = username.size() + realm.size() + password.GetLength() + 3; - char * sensitive = new char[len]; // A1 - size_t pos = strcpyn(sensitive, len, username.data(), username.size()); - pos += strcpyn(sensitive + pos, len - pos, ":"); - pos += strcpyn(sensitive + pos, len - pos, realm.c_str()); - pos += strcpyn(sensitive + pos, len - pos, ":"); - password.CopyTo(sensitive + pos, true); - - std::string A2 = method + ":" + uri; - std::string middle; - if (has_qop) { - qop = "auth"; - middle = nonce + ":" + ncount + ":" + cnonce + ":" + qop; - } else { - middle = nonce; - } - std::string HA1 = MD5(sensitive); - memset(sensitive, 0, len); - delete [] sensitive; - std::string HA2 = MD5(A2); - std::string dig_response = MD5(HA1 + ":" + middle + ":" + HA2); - - std::stringstream ss; - ss << auth_method; - ss << " username=" << quote(username); - ss << ", realm=" << quote(realm); - ss << ", nonce=" << quote(nonce); - ss << ", uri=" << quote(uri); - if (has_qop) { - ss << ", qop=" << qop; - ss << ", nc=" << ncount; - ss << ", cnonce=" << quote(cnonce); - } - ss << ", response=\"" << dig_response << "\""; - if (has_opaque) { - ss << ", opaque=" << quote(opaque); - } - response = ss.str(); - return HAR_RESPONSE; - } - -#if defined(WEBRTC_WIN) -#if 1 - bool want_negotiate = (_stricmp(auth_method.c_str(), "negotiate") == 0); - bool want_ntlm = (_stricmp(auth_method.c_str(), "ntlm") == 0); - // SPNEGO & NTLM - if (want_negotiate || want_ntlm) { - const size_t MAX_MESSAGE = 12000, MAX_SPN = 256; - char out_buf[MAX_MESSAGE], spn[MAX_SPN]; - -#if 0 // Requires funky windows versions - DWORD len = MAX_SPN; - if (DsMakeSpn("HTTP", server.HostAsURIString().c_str(), nullptr, - server.port(), - 0, &len, spn) != ERROR_SUCCESS) { - LOG_F(WARNING) << "(Negotiate) - DsMakeSpn failed"; - return HAR_IGNORE; - } -#else - sprintfn(spn, MAX_SPN, "HTTP/%s", server.ToString().c_str()); -#endif - - SecBuffer out_sec; - out_sec.pvBuffer = out_buf; - out_sec.cbBuffer = sizeof(out_buf); - out_sec.BufferType = SECBUFFER_TOKEN; - - SecBufferDesc out_buf_desc; - out_buf_desc.ulVersion = 0; - out_buf_desc.cBuffers = 1; - out_buf_desc.pBuffers = &out_sec; - - const ULONG NEG_FLAGS_DEFAULT = - //ISC_REQ_ALLOCATE_MEMORY - ISC_REQ_CONFIDENTIALITY - //| ISC_REQ_EXTENDED_ERROR - //| ISC_REQ_INTEGRITY - | ISC_REQ_REPLAY_DETECT - | ISC_REQ_SEQUENCE_DETECT - //| ISC_REQ_STREAM - //| ISC_REQ_USE_SUPPLIED_CREDS - ; - - ::TimeStamp lifetime; - SECURITY_STATUS ret = S_OK; - ULONG ret_flags = 0, flags = NEG_FLAGS_DEFAULT; - - bool specify_credentials = !username.empty(); - size_t steps = 0; - - // uint32_t now = Time(); - - NegotiateAuthContext * neg = static_cast(context); - if (neg) { - const size_t max_steps = 10; - if (++neg->steps >= max_steps) { - LOG(WARNING) << "AsyncHttpsProxySocket::Authenticate(Negotiate) too many retries"; - return HAR_ERROR; - } - steps = neg->steps; - - std::string challenge, decoded_challenge; - if (HttpHasNthAttribute(args, 1, &challenge, nullptr) && - Base64::Decode(challenge, Base64::DO_STRICT, &decoded_challenge, - nullptr)) { - SecBuffer in_sec; - in_sec.pvBuffer = const_cast(decoded_challenge.data()); - in_sec.cbBuffer = static_cast(decoded_challenge.size()); - in_sec.BufferType = SECBUFFER_TOKEN; - - SecBufferDesc in_buf_desc; - in_buf_desc.ulVersion = 0; - in_buf_desc.cBuffers = 1; - in_buf_desc.pBuffers = &in_sec; - - ret = InitializeSecurityContextA(&neg->cred, &neg->ctx, spn, flags, 0, SECURITY_NATIVE_DREP, &in_buf_desc, 0, &neg->ctx, &out_buf_desc, &ret_flags, &lifetime); - //LOG(INFO) << "$$$ InitializeSecurityContext @ " << TimeSince(now); - if (FAILED(ret)) { - LOG(LS_ERROR) << "InitializeSecurityContext returned: " - << ErrorName(ret, SECURITY_ERRORS); - return HAR_ERROR; - } - } else if (neg->specified_credentials) { - // Try again with default credentials - specify_credentials = false; - delete context; - context = neg = 0; - } else { - return HAR_CREDENTIALS; - } - } - - if (!neg) { - unsigned char userbuf[256], passbuf[256], domainbuf[16]; - SEC_WINNT_AUTH_IDENTITY_A auth_id, * pauth_id = 0; - if (specify_credentials) { - memset(&auth_id, 0, sizeof(auth_id)); - size_t len = password.GetLength()+1; - char * sensitive = new char[len]; - password.CopyTo(sensitive, true); - std::string::size_type pos = username.find('\\'); - if (pos == std::string::npos) { - auth_id.UserLength = static_cast( - std::min(sizeof(userbuf) - 1, username.size())); - memcpy(userbuf, username.c_str(), auth_id.UserLength); - userbuf[auth_id.UserLength] = 0; - auth_id.DomainLength = 0; - domainbuf[auth_id.DomainLength] = 0; - auth_id.PasswordLength = static_cast( - std::min(sizeof(passbuf) - 1, password.GetLength())); - memcpy(passbuf, sensitive, auth_id.PasswordLength); - passbuf[auth_id.PasswordLength] = 0; - } else { - auth_id.UserLength = static_cast( - std::min(sizeof(userbuf) - 1, username.size() - pos - 1)); - memcpy(userbuf, username.c_str() + pos + 1, auth_id.UserLength); - userbuf[auth_id.UserLength] = 0; - auth_id.DomainLength = - static_cast(std::min(sizeof(domainbuf) - 1, pos)); - memcpy(domainbuf, username.c_str(), auth_id.DomainLength); - domainbuf[auth_id.DomainLength] = 0; - auth_id.PasswordLength = static_cast( - std::min(sizeof(passbuf) - 1, password.GetLength())); - memcpy(passbuf, sensitive, auth_id.PasswordLength); - passbuf[auth_id.PasswordLength] = 0; - } - memset(sensitive, 0, len); - delete [] sensitive; - auth_id.User = userbuf; - auth_id.Domain = domainbuf; - auth_id.Password = passbuf; - auth_id.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI; - pauth_id = &auth_id; - LOG(LS_VERBOSE) << "Negotiate protocol: Using specified credentials"; - } else { - LOG(LS_VERBOSE) << "Negotiate protocol: Using default credentials"; - } - - CredHandle cred; - ret = AcquireCredentialsHandleA( - 0, const_cast(want_negotiate ? NEGOSSP_NAME_A : NTLMSP_NAME_A), - SECPKG_CRED_OUTBOUND, 0, pauth_id, 0, 0, &cred, &lifetime); - //LOG(INFO) << "$$$ AcquireCredentialsHandle @ " << TimeSince(now); - if (ret != SEC_E_OK) { - LOG(LS_ERROR) << "AcquireCredentialsHandle error: " - << ErrorName(ret, SECURITY_ERRORS); - return HAR_IGNORE; - } - - //CSecBufferBundle<5, CSecBufferBase::FreeSSPI> sb_out; - - CtxtHandle ctx; - ret = InitializeSecurityContextA(&cred, 0, spn, flags, 0, SECURITY_NATIVE_DREP, 0, 0, &ctx, &out_buf_desc, &ret_flags, &lifetime); - //LOG(INFO) << "$$$ InitializeSecurityContext @ " << TimeSince(now); - if (FAILED(ret)) { - LOG(LS_ERROR) << "InitializeSecurityContext returned: " - << ErrorName(ret, SECURITY_ERRORS); - FreeCredentialsHandle(&cred); - return HAR_IGNORE; - } - - RTC_DCHECK(!context); - context = neg = new NegotiateAuthContext(auth_method, cred, ctx); - neg->specified_credentials = specify_credentials; - neg->steps = steps; - } - - if ((ret == SEC_I_COMPLETE_NEEDED) || (ret == SEC_I_COMPLETE_AND_CONTINUE)) { - ret = CompleteAuthToken(&neg->ctx, &out_buf_desc); - //LOG(INFO) << "$$$ CompleteAuthToken @ " << TimeSince(now); - LOG(LS_VERBOSE) << "CompleteAuthToken returned: " - << ErrorName(ret, SECURITY_ERRORS); - if (FAILED(ret)) { - return HAR_ERROR; - } - } - - //LOG(INFO) << "$$$ NEGOTIATE took " << TimeSince(now) << "ms"; - - std::string decoded(out_buf, out_buf + out_sec.cbBuffer); - response = auth_method; - response.append(" "); - response.append(Base64::Encode(decoded)); - return HAR_RESPONSE; - } -#endif -#endif // WEBRTC_WIN - - return HAR_IGNORE; -} - -////////////////////////////////////////////////////////////////////// - -} // namespace rtc diff --git a/webrtc/base/httpcommon.h b/webrtc/base/httpcommon.h deleted file mode 100644 index 7182aa2f85..0000000000 --- a/webrtc/base/httpcommon.h +++ /dev/null @@ -1,458 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_BASE_HTTPCOMMON_H__ -#define WEBRTC_BASE_HTTPCOMMON_H__ - -#include -#include -#include -#include -#include "webrtc/base/basictypes.h" -#include "webrtc/base/checks.h" -#include "webrtc/base/stringutils.h" -#include "webrtc/base/stream.h" - -namespace rtc { - -class CryptString; -class SocketAddress; - -////////////////////////////////////////////////////////////////////// -// Constants -////////////////////////////////////////////////////////////////////// - -enum HttpCode { - HC_OK = 200, - HC_NON_AUTHORITATIVE = 203, - HC_NO_CONTENT = 204, - HC_PARTIAL_CONTENT = 206, - - HC_MULTIPLE_CHOICES = 300, - HC_MOVED_PERMANENTLY = 301, - HC_FOUND = 302, - HC_SEE_OTHER = 303, - HC_NOT_MODIFIED = 304, - HC_MOVED_TEMPORARILY = 307, - - HC_BAD_REQUEST = 400, - HC_UNAUTHORIZED = 401, - HC_FORBIDDEN = 403, - HC_NOT_FOUND = 404, - HC_PROXY_AUTHENTICATION_REQUIRED = 407, - HC_GONE = 410, - - HC_INTERNAL_SERVER_ERROR = 500, - HC_NOT_IMPLEMENTED = 501, - HC_SERVICE_UNAVAILABLE = 503, -}; - -enum HttpVersion { - HVER_1_0, HVER_1_1, HVER_UNKNOWN, - HVER_LAST = HVER_UNKNOWN -}; - -enum HttpVerb { - HV_GET, HV_POST, HV_PUT, HV_DELETE, HV_CONNECT, HV_HEAD, - HV_LAST = HV_HEAD -}; - -enum HttpError { - HE_NONE, - HE_PROTOCOL, // Received non-valid HTTP data - HE_DISCONNECTED, // Connection closed unexpectedly - HE_OVERFLOW, // Received too much data for internal buffers - HE_CONNECT_FAILED, // The socket failed to connect. - HE_SOCKET_ERROR, // An error occurred on a connected socket - HE_SHUTDOWN, // Http object is being destroyed - HE_OPERATION_CANCELLED, // Connection aborted locally - HE_AUTH, // Proxy Authentication Required - HE_CERTIFICATE_EXPIRED, // During SSL negotiation - HE_STREAM, // Problem reading or writing to the document - HE_CACHE, // Problem reading from cache - HE_DEFAULT -}; - -enum HttpHeader { - HH_AGE, - HH_CACHE_CONTROL, - HH_CONNECTION, - HH_CONTENT_DISPOSITION, - HH_CONTENT_LENGTH, - HH_CONTENT_RANGE, - HH_CONTENT_TYPE, - HH_COOKIE, - HH_DATE, - HH_ETAG, - HH_EXPIRES, - HH_HOST, - HH_IF_MODIFIED_SINCE, - HH_IF_NONE_MATCH, - HH_KEEP_ALIVE, - HH_LAST_MODIFIED, - HH_LOCATION, - HH_PROXY_AUTHENTICATE, - HH_PROXY_AUTHORIZATION, - HH_PROXY_CONNECTION, - HH_RANGE, - HH_SET_COOKIE, - HH_TE, - HH_TRAILERS, - HH_TRANSFER_ENCODING, - HH_UPGRADE, - HH_USER_AGENT, - HH_WWW_AUTHENTICATE, - HH_LAST = HH_WWW_AUTHENTICATE -}; - -const uint16_t HTTP_DEFAULT_PORT = 80; -const uint16_t HTTP_SECURE_PORT = 443; - -////////////////////////////////////////////////////////////////////// -// Utility Functions -////////////////////////////////////////////////////////////////////// - -inline HttpError mkerr(HttpError err, HttpError def_err = HE_DEFAULT) { - return (err != HE_NONE) ? err : def_err; -} - -const char* ToString(HttpVersion version); -bool FromString(HttpVersion& version, const std::string& str); - -const char* ToString(HttpVerb verb); -bool FromString(HttpVerb& verb, const std::string& str); - -const char* ToString(HttpHeader header); -bool FromString(HttpHeader& header, const std::string& str); - -inline bool HttpCodeIsInformational(uint32_t code) { - return ((code / 100) == 1); -} -inline bool HttpCodeIsSuccessful(uint32_t code) { - return ((code / 100) == 2); -} -inline bool HttpCodeIsRedirection(uint32_t code) { - return ((code / 100) == 3); -} -inline bool HttpCodeIsClientError(uint32_t code) { - return ((code / 100) == 4); -} -inline bool HttpCodeIsServerError(uint32_t code) { - return ((code / 100) == 5); -} - -bool HttpCodeHasBody(uint32_t code); -bool HttpCodeIsCacheable(uint32_t code); -bool HttpHeaderIsEndToEnd(HttpHeader header); -bool HttpHeaderIsCollapsible(HttpHeader header); - -struct HttpData; -bool HttpShouldKeepAlive(const HttpData& data); - -typedef std::pair HttpAttribute; -typedef std::vector HttpAttributeList; -void HttpComposeAttributes(const HttpAttributeList& attributes, char separator, - std::string* composed); -void HttpParseAttributes(const char * data, size_t len, - HttpAttributeList& attributes); -bool HttpHasAttribute(const HttpAttributeList& attributes, - const std::string& name, - std::string* value); -bool HttpHasNthAttribute(HttpAttributeList& attributes, - size_t index, - std::string* name, - std::string* value); - -// Convert RFC1123 date (DoW, DD Mon YYYY HH:MM:SS TZ) to unix timestamp -bool HttpDateToSeconds(const std::string& date, time_t* seconds); - -inline uint16_t HttpDefaultPort(bool secure) { - return secure ? HTTP_SECURE_PORT : HTTP_DEFAULT_PORT; -} - -// Returns the http server notation for a given address -std::string HttpAddress(const SocketAddress& address, bool secure); - -// functional for insensitive std::string compare -struct iless { - bool operator()(const std::string& lhs, const std::string& rhs) const { - return (::_stricmp(lhs.c_str(), rhs.c_str()) < 0); - } -}; - -// put quotes around a string and escape any quotes inside it -std::string quote(const std::string& str); - -////////////////////////////////////////////////////////////////////// -// Url -////////////////////////////////////////////////////////////////////// - -template -class Url { -public: - typedef typename Traits::string string; - - // TODO: Implement Encode/Decode - static int Encode(const CTYPE* source, CTYPE* destination, size_t len); - static int Encode(const string& source, string& destination); - static int Decode(const CTYPE* source, CTYPE* destination, size_t len); - static int Decode(const string& source, string& destination); - - Url(const string& url) { do_set_url(url.c_str(), url.size()); } - Url(const string& path, const string& host, uint16_t port = HTTP_DEFAULT_PORT) - : host_(host), port_(port), secure_(HTTP_SECURE_PORT == port) { - set_full_path(path); - } - - bool valid() const { return !host_.empty(); } - void clear() { - host_.clear(); - port_ = HTTP_DEFAULT_PORT; - secure_ = false; - path_.assign(1, static_cast('/')); - query_.clear(); - } - - void set_url(const string& val) { - do_set_url(val.c_str(), val.size()); - } - string url() const { - string val; do_get_url(&val); return val; - } - - void set_address(const string& val) { - do_set_address(val.c_str(), val.size()); - } - string address() const { - string val; do_get_address(&val); return val; - } - - void set_full_path(const string& val) { - do_set_full_path(val.c_str(), val.size()); - } - string full_path() const { - string val; do_get_full_path(&val); return val; - } - - void set_host(const string& val) { host_ = val; } - const string& host() const { return host_; } - - void set_port(uint16_t val) { port_ = val; } - uint16_t port() const { return port_; } - - void set_secure(bool val) { secure_ = val; } - bool secure() const { return secure_; } - - void set_path(const string& val) { - if (val.empty()) { - path_.assign(1, static_cast('/')); - } else { - RTC_DCHECK(val[0] == static_cast('/')); - path_ = val; - } - } - const string& path() const { return path_; } - - void set_query(const string& val) { - RTC_DCHECK(val.empty() || (val[0] == static_cast('?'))); - query_ = val; - } - const string& query() const { return query_; } - - bool get_attribute(const string& name, string* value) const; - -private: - void do_set_url(const CTYPE* val, size_t len); - void do_set_address(const CTYPE* val, size_t len); - void do_set_full_path(const CTYPE* val, size_t len); - - void do_get_url(string* val) const; - void do_get_address(string* val) const; - void do_get_full_path(string* val) const; - - string host_, path_, query_; - uint16_t port_; - bool secure_; -}; - -////////////////////////////////////////////////////////////////////// -// HttpData -////////////////////////////////////////////////////////////////////// - -struct HttpData { - typedef std::multimap HeaderMap; - typedef HeaderMap::const_iterator const_iterator; - typedef HeaderMap::iterator iterator; - - HttpVersion version; - std::unique_ptr document; - - HttpData(); - - enum HeaderCombine { HC_YES, HC_NO, HC_AUTO, HC_REPLACE, HC_NEW }; - void changeHeader(const std::string& name, const std::string& value, - HeaderCombine combine); - inline void addHeader(const std::string& name, const std::string& value, - bool append = true) { - changeHeader(name, value, append ? HC_AUTO : HC_NO); - } - inline void setHeader(const std::string& name, const std::string& value, - bool overwrite = true) { - changeHeader(name, value, overwrite ? HC_REPLACE : HC_NEW); - } - // Returns count of erased headers - size_t clearHeader(const std::string& name); - // Returns iterator to next header - iterator clearHeader(iterator header); - - // keep in mind, this may not do what you want in the face of multiple headers - bool hasHeader(const std::string& name, std::string* value) const; - - inline const_iterator begin() const { - return headers_.begin(); - } - inline const_iterator end() const { - return headers_.end(); - } - inline iterator begin() { - return headers_.begin(); - } - inline iterator end() { - return headers_.end(); - } - inline const_iterator begin(const std::string& name) const { - return headers_.lower_bound(name); - } - inline const_iterator end(const std::string& name) const { - return headers_.upper_bound(name); - } - inline iterator begin(const std::string& name) { - return headers_.lower_bound(name); - } - inline iterator end(const std::string& name) { - return headers_.upper_bound(name); - } - - // Convenience methods using HttpHeader - inline void changeHeader(HttpHeader header, const std::string& value, - HeaderCombine combine) { - changeHeader(ToString(header), value, combine); - } - inline void addHeader(HttpHeader header, const std::string& value, - bool append = true) { - addHeader(ToString(header), value, append); - } - inline void setHeader(HttpHeader header, const std::string& value, - bool overwrite = true) { - setHeader(ToString(header), value, overwrite); - } - inline void clearHeader(HttpHeader header) { - clearHeader(ToString(header)); - } - inline bool hasHeader(HttpHeader header, std::string* value) const { - return hasHeader(ToString(header), value); - } - inline const_iterator begin(HttpHeader header) const { - return headers_.lower_bound(ToString(header)); - } - inline const_iterator end(HttpHeader header) const { - return headers_.upper_bound(ToString(header)); - } - inline iterator begin(HttpHeader header) { - return headers_.lower_bound(ToString(header)); - } - inline iterator end(HttpHeader header) { - return headers_.upper_bound(ToString(header)); - } - - void setContent(const std::string& content_type, StreamInterface* document); - void setDocumentAndLength(StreamInterface* document); - - virtual size_t formatLeader(char* buffer, size_t size) const = 0; - virtual HttpError parseLeader(const char* line, size_t len) = 0; - -protected: - virtual ~HttpData(); - void clear(bool release_document); - void copy(const HttpData& src); - -private: - HeaderMap headers_; -}; - -struct HttpRequestData : public HttpData { - HttpVerb verb; - std::string path; - - HttpRequestData() : verb(HV_GET) { } - - void clear(bool release_document); - void copy(const HttpRequestData& src); - - size_t formatLeader(char* buffer, size_t size) const override; - HttpError parseLeader(const char* line, size_t len) override; - - bool getAbsoluteUri(std::string* uri) const; - bool getRelativeUri(std::string* host, std::string* path) const; -}; - -struct HttpResponseData : public HttpData { - uint32_t scode; - std::string message; - - HttpResponseData() : scode(HC_INTERNAL_SERVER_ERROR) { } - void clear(bool release_document); - void copy(const HttpResponseData& src); - - // Convenience methods - void set_success(uint32_t scode = HC_OK); - void set_success(const std::string& content_type, - StreamInterface* document, - uint32_t scode = HC_OK); - void set_redirect(const std::string& location, - uint32_t scode = HC_MOVED_TEMPORARILY); - void set_error(uint32_t scode); - - size_t formatLeader(char* buffer, size_t size) const override; - HttpError parseLeader(const char* line, size_t len) override; -}; - -struct HttpTransaction { - HttpRequestData request; - HttpResponseData response; -}; - -////////////////////////////////////////////////////////////////////// -// Http Authentication -////////////////////////////////////////////////////////////////////// - -struct HttpAuthContext { - std::string auth_method; - HttpAuthContext(const std::string& auth) : auth_method(auth) { } - virtual ~HttpAuthContext() { } -}; - -enum HttpAuthResult { HAR_RESPONSE, HAR_IGNORE, HAR_CREDENTIALS, HAR_ERROR }; - -// 'context' is used by this function to record information between calls. -// Start by passing a null pointer, then pass the same pointer each additional -// call. When the authentication attempt is finished, delete the context. -HttpAuthResult HttpAuthenticate( - const char * challenge, size_t len, - const SocketAddress& server, - const std::string& method, const std::string& uri, - const std::string& username, const CryptString& password, - HttpAuthContext *& context, std::string& response, std::string& auth_method); - -////////////////////////////////////////////////////////////////////// - -} // namespace rtc - -#endif // WEBRTC_BASE_HTTPCOMMON_H__ diff --git a/webrtc/base/httpcommon_unittest.cc b/webrtc/base/httpcommon_unittest.cc deleted file mode 100644 index 10e378987a..0000000000 --- a/webrtc/base/httpcommon_unittest.cc +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "webrtc/base/gunit.h" -#include "webrtc/base/httpcommon-inl.h" -#include "webrtc/base/httpcommon.h" - -namespace rtc { - -#define TEST_PROTOCOL "http://" -#define TEST_HOST "www.google.com" -#define TEST_PATH "/folder/file.html" -#define TEST_QUERY "?query=x&attr=y" -#define TEST_URL TEST_PROTOCOL TEST_HOST TEST_PATH TEST_QUERY - -TEST(Url, DecomposesUrls) { - Url url(TEST_URL); - EXPECT_TRUE(url.valid()); - EXPECT_FALSE(url.secure()); - EXPECT_STREQ(TEST_HOST, url.host().c_str()); - EXPECT_EQ(80, url.port()); - EXPECT_STREQ(TEST_PATH, url.path().c_str()); - EXPECT_STREQ(TEST_QUERY, url.query().c_str()); - EXPECT_STREQ(TEST_HOST, url.address().c_str()); - EXPECT_STREQ(TEST_PATH TEST_QUERY, url.full_path().c_str()); - EXPECT_STREQ(TEST_URL, url.url().c_str()); -} - -TEST(Url, ComposesUrls) { - // Set in constructor - Url url(TEST_PATH TEST_QUERY, TEST_HOST, 80); - EXPECT_TRUE(url.valid()); - EXPECT_FALSE(url.secure()); - EXPECT_STREQ(TEST_HOST, url.host().c_str()); - EXPECT_EQ(80, url.port()); - EXPECT_STREQ(TEST_PATH, url.path().c_str()); - EXPECT_STREQ(TEST_QUERY, url.query().c_str()); - EXPECT_STREQ(TEST_HOST, url.address().c_str()); - EXPECT_STREQ(TEST_PATH TEST_QUERY, url.full_path().c_str()); - EXPECT_STREQ(TEST_URL, url.url().c_str()); - - url.clear(); - EXPECT_FALSE(url.valid()); - EXPECT_FALSE(url.secure()); - EXPECT_STREQ("", url.host().c_str()); - EXPECT_EQ(80, url.port()); - EXPECT_STREQ("/", url.path().c_str()); - EXPECT_STREQ("", url.query().c_str()); - - // Set component-wise - url.set_host(TEST_HOST); - url.set_port(80); - url.set_path(TEST_PATH); - url.set_query(TEST_QUERY); - EXPECT_TRUE(url.valid()); - EXPECT_FALSE(url.secure()); - EXPECT_STREQ(TEST_HOST, url.host().c_str()); - EXPECT_EQ(80, url.port()); - EXPECT_STREQ(TEST_PATH, url.path().c_str()); - EXPECT_STREQ(TEST_QUERY, url.query().c_str()); - EXPECT_STREQ(TEST_HOST, url.address().c_str()); - EXPECT_STREQ(TEST_PATH TEST_QUERY, url.full_path().c_str()); - EXPECT_STREQ(TEST_URL, url.url().c_str()); -} - -TEST(Url, EnsuresNonEmptyPath) { - Url url(TEST_PROTOCOL TEST_HOST); - EXPECT_TRUE(url.valid()); - EXPECT_STREQ("/", url.path().c_str()); - - url.clear(); - EXPECT_STREQ("/", url.path().c_str()); - url.set_path(""); - EXPECT_STREQ("/", url.path().c_str()); - - url.clear(); - EXPECT_STREQ("/", url.path().c_str()); - url.set_full_path(""); - EXPECT_STREQ("/", url.path().c_str()); -} - -TEST(Url, GetQueryAttributes) { - Url url(TEST_URL); - std::string value; - EXPECT_TRUE(url.get_attribute("query", &value)); - EXPECT_STREQ("x", value.c_str()); - value.clear(); - EXPECT_TRUE(url.get_attribute("attr", &value)); - EXPECT_STREQ("y", value.c_str()); - value.clear(); - EXPECT_FALSE(url.get_attribute("Query", &value)); - EXPECT_TRUE(value.empty()); -} - -TEST(Url, SkipsUserAndPassword) { - Url url("https://mail.google.com:pwd@badsite.com:12345/asdf"); - EXPECT_TRUE(url.valid()); - EXPECT_TRUE(url.secure()); - EXPECT_STREQ("badsite.com", url.host().c_str()); - EXPECT_EQ(12345, url.port()); - EXPECT_STREQ("/asdf", url.path().c_str()); - EXPECT_STREQ("badsite.com:12345", url.address().c_str()); -} - -TEST(Url, SkipsUser) { - Url url("https://mail.google.com@badsite.com:12345/asdf"); - EXPECT_TRUE(url.valid()); - EXPECT_TRUE(url.secure()); - EXPECT_STREQ("badsite.com", url.host().c_str()); - EXPECT_EQ(12345, url.port()); - EXPECT_STREQ("/asdf", url.path().c_str()); - EXPECT_STREQ("badsite.com:12345", url.address().c_str()); -} - -TEST(HttpResponseData, parseLeaderHttp1_0) { - static const char kResponseString[] = "HTTP/1.0 200 OK"; - HttpResponseData response; - EXPECT_EQ(HE_NONE, response.parseLeader(kResponseString, - sizeof(kResponseString) - 1)); - EXPECT_EQ(HVER_1_0, response.version); - EXPECT_EQ(200U, response.scode); -} - -TEST(HttpResponseData, parseLeaderHttp1_1) { - static const char kResponseString[] = "HTTP/1.1 200 OK"; - HttpResponseData response; - EXPECT_EQ(HE_NONE, response.parseLeader(kResponseString, - sizeof(kResponseString) - 1)); - EXPECT_EQ(HVER_1_1, response.version); - EXPECT_EQ(200U, response.scode); -} - -TEST(HttpResponseData, parseLeaderHttpUnknown) { - static const char kResponseString[] = "HTTP 200 OK"; - HttpResponseData response; - EXPECT_EQ(HE_NONE, response.parseLeader(kResponseString, - sizeof(kResponseString) - 1)); - EXPECT_EQ(HVER_UNKNOWN, response.version); - EXPECT_EQ(200U, response.scode); -} - -TEST(HttpResponseData, parseLeaderHttpFailure) { - static const char kResponseString[] = "HTTP/1.1 503 Service Unavailable"; - HttpResponseData response; - EXPECT_EQ(HE_NONE, response.parseLeader(kResponseString, - sizeof(kResponseString) - 1)); - EXPECT_EQ(HVER_1_1, response.version); - EXPECT_EQ(503U, response.scode); -} - -TEST(HttpResponseData, parseLeaderHttpInvalid) { - static const char kResponseString[] = "Durrrrr, what's HTTP?"; - HttpResponseData response; - EXPECT_EQ(HE_PROTOCOL, response.parseLeader(kResponseString, - sizeof(kResponseString) - 1)); -} - -} // namespace rtc diff --git a/webrtc/base/httpserver.cc b/webrtc/base/httpserver.cc deleted file mode 100644 index b19069123b..0000000000 --- a/webrtc/base/httpserver.cc +++ /dev/null @@ -1,288 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include - -#include "webrtc/base/httpcommon-inl.h" - -#include "webrtc/base/asyncsocket.h" -#include "webrtc/base/checks.h" -#include "webrtc/base/httpserver.h" -#include "webrtc/base/logging.h" -#include "webrtc/base/socketstream.h" -#include "webrtc/base/thread.h" - -namespace rtc { - -/////////////////////////////////////////////////////////////////////////////// -// HttpServer -/////////////////////////////////////////////////////////////////////////////// - -HttpServer::HttpServer() : next_connection_id_(1), closing_(false) { -} - -HttpServer::~HttpServer() { - if (closing_) { - LOG(LS_WARNING) << "HttpServer::CloseAll has not completed"; - } - for (ConnectionMap::iterator it = connections_.begin(); - it != connections_.end(); - ++it) { - StreamInterface* stream = it->second->EndProcess(); - delete stream; - delete it->second; - } -} - -int -HttpServer::HandleConnection(StreamInterface* stream) { - int connection_id = next_connection_id_++; - RTC_DCHECK(connection_id != HTTP_INVALID_CONNECTION_ID); - Connection* connection = new Connection(connection_id, this); - connections_.insert(ConnectionMap::value_type(connection_id, connection)); - connection->BeginProcess(stream); - return connection_id; -} - -void -HttpServer::Respond(HttpServerTransaction* transaction) { - int connection_id = transaction->connection_id(); - if (Connection* connection = Find(connection_id)) { - connection->Respond(transaction); - } else { - delete transaction; - // We may be tempted to SignalHttpComplete, but that implies that a - // connection still exists. - } -} - -void -HttpServer::Close(int connection_id, bool force) { - if (Connection* connection = Find(connection_id)) { - connection->InitiateClose(force); - } -} - -void -HttpServer::CloseAll(bool force) { - if (connections_.empty()) { - SignalCloseAllComplete(this); - return; - } - closing_ = true; - std::list connections; - for (ConnectionMap::const_iterator it = connections_.begin(); - it != connections_.end(); ++it) { - connections.push_back(it->second); - } - for (std::list::const_iterator it = connections.begin(); - it != connections.end(); ++it) { - (*it)->InitiateClose(force); - } -} - -HttpServer::Connection* -HttpServer::Find(int connection_id) { - ConnectionMap::iterator it = connections_.find(connection_id); - if (it == connections_.end()) - return nullptr; - return it->second; -} - -void -HttpServer::Remove(int connection_id) { - ConnectionMap::iterator it = connections_.find(connection_id); - if (it == connections_.end()) { - RTC_NOTREACHED(); - return; - } - Connection* connection = it->second; - connections_.erase(it); - SignalConnectionClosed(this, connection_id, connection->EndProcess()); - delete connection; - if (closing_ && connections_.empty()) { - closing_ = false; - SignalCloseAllComplete(this); - } -} - -/////////////////////////////////////////////////////////////////////////////// -// HttpServer::Connection -/////////////////////////////////////////////////////////////////////////////// - -HttpServer::Connection::Connection(int connection_id, HttpServer* server) - : connection_id_(connection_id), - server_(server), - current_(nullptr), - signalling_(false), - close_(false) {} - -HttpServer::Connection::~Connection() { - // It's possible that an object hosted inside this transaction signalled - // an event which caused the connection to close. - Thread::Current()->Dispose(current_); -} - -void -HttpServer::Connection::BeginProcess(StreamInterface* stream) { - base_.notify(this); - base_.attach(stream); - current_ = new HttpServerTransaction(connection_id_); - if (base_.mode() != HM_CONNECT) - base_.recv(¤t_->request); -} - -StreamInterface* -HttpServer::Connection::EndProcess() { - base_.notify(nullptr); - base_.abort(HE_DISCONNECTED); - return base_.detach(); -} - -void -HttpServer::Connection::Respond(HttpServerTransaction* transaction) { - RTC_DCHECK(current_ == nullptr); - current_ = transaction; - if (current_->response.begin() == current_->response.end()) { - current_->response.set_error(HC_INTERNAL_SERVER_ERROR); - } - bool keep_alive = HttpShouldKeepAlive(current_->request); - current_->response.setHeader(HH_CONNECTION, - keep_alive ? "Keep-Alive" : "Close", - false); - close_ = !HttpShouldKeepAlive(current_->response); - base_.send(¤t_->response); -} - -void -HttpServer::Connection::InitiateClose(bool force) { - bool request_in_progress = (HM_SEND == base_.mode()) || (nullptr == current_); - if (!signalling_ && (force || !request_in_progress)) { - server_->Remove(connection_id_); - } else { - close_ = true; - } -} - -// -// IHttpNotify Implementation -// - -HttpError -HttpServer::Connection::onHttpHeaderComplete(bool chunked, size_t& data_size) { - if (data_size == SIZE_UNKNOWN) { - data_size = 0; - } - RTC_DCHECK(current_ != nullptr); - bool custom_document = false; - server_->SignalHttpRequestHeader(server_, current_, &custom_document); - if (!custom_document) { - current_->request.document.reset(new MemoryStream); - } - return HE_NONE; -} - -void -HttpServer::Connection::onHttpComplete(HttpMode mode, HttpError err) { - if (mode == HM_SEND) { - RTC_DCHECK(current_ != nullptr); - signalling_ = true; - server_->SignalHttpRequestComplete(server_, current_, err); - signalling_ = false; - if (close_) { - // Force a close - err = HE_DISCONNECTED; - } - } - if (err != HE_NONE) { - server_->Remove(connection_id_); - } else if (mode == HM_CONNECT) { - base_.recv(¤t_->request); - } else if (mode == HM_RECV) { - RTC_DCHECK(current_ != nullptr); - // TODO: do we need this? - //request_.document_->rewind(); - HttpServerTransaction* transaction = current_; - current_ = nullptr; - server_->SignalHttpRequest(server_, transaction); - } else if (mode == HM_SEND) { - Thread::Current()->Dispose(current_->response.document.release()); - current_->request.clear(true); - current_->response.clear(true); - base_.recv(¤t_->request); - } else { - RTC_NOTREACHED(); - } -} - -void -HttpServer::Connection::onHttpClosed(HttpError err) { - server_->Remove(connection_id_); -} - -/////////////////////////////////////////////////////////////////////////////// -// HttpListenServer -/////////////////////////////////////////////////////////////////////////////// - -HttpListenServer::HttpListenServer() { - SignalConnectionClosed.connect(this, &HttpListenServer::OnConnectionClosed); -} - -HttpListenServer::~HttpListenServer() { -} - -int HttpListenServer::Listen(const SocketAddress& address) { - AsyncSocket* sock = - Thread::Current()->socketserver()->CreateAsyncSocket(address.family(), - SOCK_STREAM); - if (!sock) { - return SOCKET_ERROR; - } - listener_.reset(sock); - listener_->SignalReadEvent.connect(this, &HttpListenServer::OnReadEvent); - if ((listener_->Bind(address) != SOCKET_ERROR) && - (listener_->Listen(5) != SOCKET_ERROR)) - return 0; - return listener_->GetError(); -} - -bool HttpListenServer::GetAddress(SocketAddress* address) const { - if (!listener_) { - return false; - } - *address = listener_->GetLocalAddress(); - return !address->IsNil(); -} - -void HttpListenServer::StopListening() { - if (listener_) { - listener_->Close(); - } -} - -void HttpListenServer::OnReadEvent(AsyncSocket* socket) { - RTC_DCHECK(socket == listener_.get()); - AsyncSocket* incoming = listener_->Accept(nullptr); - if (incoming) { - StreamInterface* stream = new SocketStream(incoming); - //stream = new LoggingAdapter(stream, LS_VERBOSE, "HttpServer", false); - HandleConnection(stream); - } -} - -void HttpListenServer::OnConnectionClosed(HttpServer* server, - int connection_id, - StreamInterface* stream) { - Thread::Current()->Dispose(stream); -} - -/////////////////////////////////////////////////////////////////////////////// - -} // namespace rtc diff --git a/webrtc/base/httpserver.h b/webrtc/base/httpserver.h deleted file mode 100644 index cbee734873..0000000000 --- a/webrtc/base/httpserver.h +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_BASE_HTTPSERVER_H__ -#define WEBRTC_BASE_HTTPSERVER_H__ - -#include -#include - -#include "webrtc/base/httpbase.h" - -namespace rtc { - -class AsyncSocket; -class HttpServer; -class SocketAddress; - -////////////////////////////////////////////////////////////////////// -// HttpServer -////////////////////////////////////////////////////////////////////// - -const int HTTP_INVALID_CONNECTION_ID = 0; - -struct HttpServerTransaction : public HttpTransaction { -public: - HttpServerTransaction(int id) : connection_id_(id) { } - int connection_id() const { return connection_id_; } - -private: - int connection_id_; -}; - -class HttpServer { -public: - HttpServer(); - virtual ~HttpServer(); - - int HandleConnection(StreamInterface* stream); - // Due to sigslot issues, we can't destroy some streams at an arbitrary time. - sigslot::signal3 SignalConnectionClosed; - - // This signal occurs when the HTTP request headers have been received, but - // before the request body is written to the request document. By default, - // the request document is a MemoryStream. By handling this signal, the - // document can be overridden, in which case the third signal argument should - // be set to true. In the case where the request body should be ignored, - // the document can be set to null. Note that the transaction object is still - // owened by the HttpServer at this point. - sigslot::signal3 - SignalHttpRequestHeader; - - // An HTTP request has been made, and is available in the transaction object. - // Populate the transaction's response, and then return the object via the - // Respond method. Note that during this time, ownership of the transaction - // object is transferred, so it may be passed between threads, although - // respond must be called on the server's active thread. - sigslot::signal2 SignalHttpRequest; - void Respond(HttpServerTransaction* transaction); - - // If you want to know when a request completes, listen to this event. - sigslot::signal3 - SignalHttpRequestComplete; - - // Stop processing the connection indicated by connection_id. - // Unless force is true, the server will complete sending a response that is - // in progress. - void Close(int connection_id, bool force); - void CloseAll(bool force); - - // After calling CloseAll, this event is signalled to indicate that all - // outstanding connections have closed. - sigslot::signal1 SignalCloseAllComplete; - -private: - class Connection : private IHttpNotify { - public: - Connection(int connection_id, HttpServer* server); - ~Connection() override; - - void BeginProcess(StreamInterface* stream); - StreamInterface* EndProcess(); - - void Respond(HttpServerTransaction* transaction); - void InitiateClose(bool force); - - // IHttpNotify Interface - HttpError onHttpHeaderComplete(bool chunked, size_t& data_size) override; - void onHttpComplete(HttpMode mode, HttpError err) override; - void onHttpClosed(HttpError err) override; - - int connection_id_; - HttpServer* server_; - HttpBase base_; - HttpServerTransaction* current_; - bool signalling_, close_; - }; - - Connection* Find(int connection_id); - void Remove(int connection_id); - - friend class Connection; - typedef std::map ConnectionMap; - - ConnectionMap connections_; - int next_connection_id_; - bool closing_; -}; - -////////////////////////////////////////////////////////////////////// - -class HttpListenServer : public HttpServer, public sigslot::has_slots<> { -public: - HttpListenServer(); - ~HttpListenServer() override; - - int Listen(const SocketAddress& address); - bool GetAddress(SocketAddress* address) const; - void StopListening(); - -private: - void OnReadEvent(AsyncSocket* socket); - void OnConnectionClosed(HttpServer* server, int connection_id, - StreamInterface* stream); - - std::unique_ptr listener_; -}; - -////////////////////////////////////////////////////////////////////// - -} // namespace rtc - -#endif // WEBRTC_BASE_HTTPSERVER_H__ diff --git a/webrtc/base/httpserver_unittest.cc b/webrtc/base/httpserver_unittest.cc deleted file mode 100644 index 96d5fb64b4..0000000000 --- a/webrtc/base/httpserver_unittest.cc +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright 2007 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "webrtc/base/gunit.h" -#include "webrtc/base/httpserver.h" -#include "webrtc/base/testutils.h" - -using namespace testing; - -namespace rtc { - -namespace { - const char* const kRequest = - "GET /index.html HTTP/1.1\r\n" - "Host: localhost\r\n" - "\r\n"; - - struct HttpServerMonitor : public sigslot::has_slots<> { - HttpServerTransaction* transaction; - bool server_closed, connection_closed; - - HttpServerMonitor(HttpServer* server) - : transaction(nullptr), server_closed(false), connection_closed(false) { - server->SignalCloseAllComplete.connect(this, - &HttpServerMonitor::OnClosed); - server->SignalHttpRequest.connect(this, &HttpServerMonitor::OnRequest); - server->SignalHttpRequestComplete.connect(this, - &HttpServerMonitor::OnRequestComplete); - server->SignalConnectionClosed.connect(this, - &HttpServerMonitor::OnConnectionClosed); - } - void OnRequest(HttpServer*, HttpServerTransaction* t) { - ASSERT_FALSE(transaction); - transaction = t; - transaction->response.set_success(); - transaction->response.setHeader(HH_CONNECTION, "Close"); - } - void OnRequestComplete(HttpServer*, HttpServerTransaction* t, int) { - ASSERT_EQ(transaction, t); - transaction = nullptr; - } - void OnClosed(HttpServer*) { - server_closed = true; - } - void OnConnectionClosed(HttpServer*, int, StreamInterface* stream) { - connection_closed = true; - delete stream; - } - }; - - void CreateClientConnection(HttpServer& server, - HttpServerMonitor& monitor, - bool send_request) { - StreamSource* client = new StreamSource; - client->SetState(SS_OPEN); - server.HandleConnection(client); - EXPECT_FALSE(monitor.server_closed); - EXPECT_FALSE(monitor.transaction); - - if (send_request) { - // Simulate a request - client->QueueString(kRequest); - EXPECT_FALSE(monitor.server_closed); - } - } -} // anonymous namespace - -TEST(HttpServer, DoesNotSignalCloseUnlessCloseAllIsCalled) { - HttpServer server; - HttpServerMonitor monitor(&server); - // Add an active client connection - CreateClientConnection(server, monitor, true); - // Simulate a response - ASSERT_TRUE(nullptr != monitor.transaction); - server.Respond(monitor.transaction); - EXPECT_FALSE(monitor.transaction); - // Connection has closed, but no server close signal - EXPECT_FALSE(monitor.server_closed); - EXPECT_TRUE(monitor.connection_closed); -} - -TEST(HttpServer, SignalsCloseWhenNoConnectionsAreActive) { - HttpServer server; - HttpServerMonitor monitor(&server); - // Add an idle client connection - CreateClientConnection(server, monitor, false); - // Perform graceful close - server.CloseAll(false); - // Connections have all closed - EXPECT_TRUE(monitor.server_closed); - EXPECT_TRUE(monitor.connection_closed); -} - -TEST(HttpServer, SignalsCloseAfterGracefulCloseAll) { - HttpServer server; - HttpServerMonitor monitor(&server); - // Add an active client connection - CreateClientConnection(server, monitor, true); - // Initiate a graceful close - server.CloseAll(false); - EXPECT_FALSE(monitor.server_closed); - // Simulate a response - ASSERT_TRUE(nullptr != monitor.transaction); - server.Respond(monitor.transaction); - EXPECT_FALSE(monitor.transaction); - // Connections have all closed - EXPECT_TRUE(monitor.server_closed); - EXPECT_TRUE(monitor.connection_closed); -} - -TEST(HttpServer, SignalsCloseAfterForcedCloseAll) { - HttpServer server; - HttpServerMonitor monitor(&server); - // Add an active client connection - CreateClientConnection(server, monitor, true); - // Initiate a forceful close - server.CloseAll(true); - // Connections have all closed - EXPECT_TRUE(monitor.server_closed); - EXPECT_TRUE(monitor.connection_closed); -} - -} // namespace rtc diff --git a/webrtc/base/proxy_unittest.cc b/webrtc/base/proxy_unittest.cc deleted file mode 100644 index b72d228ea0..0000000000 --- a/webrtc/base/proxy_unittest.cc +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2009 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include -#include -#include "webrtc/base/gunit.h" -#include "webrtc/base/httpserver.h" -#include "webrtc/base/proxyserver.h" -#include "webrtc/base/socketadapters.h" -#include "webrtc/base/testclient.h" -#include "webrtc/base/testechoserver.h" -#include "webrtc/base/virtualsocketserver.h" - -using rtc::Socket; -using rtc::Thread; -using rtc::SocketAddress; - -static const SocketAddress kSocksProxyIntAddr("1.2.3.4", 1080); -static const SocketAddress kSocksProxyExtAddr("1.2.3.5", 0); -static const SocketAddress kHttpsProxyIntAddr("1.2.3.4", 443); -static const SocketAddress kHttpsProxyExtAddr("1.2.3.5", 0); -static const SocketAddress kBogusProxyIntAddr("1.2.3.4", 999); - -// Sets up a virtual socket server and HTTPS/SOCKS5 proxy servers. -class ProxyTest : public testing::Test { - public: - ProxyTest() : ss_(new rtc::VirtualSocketServer(nullptr)) { - Thread::Current()->set_socketserver(ss_.get()); - socks_.reset(new rtc::SocksProxyServer( - ss_.get(), kSocksProxyIntAddr, ss_.get(), kSocksProxyExtAddr)); - https_.reset(new rtc::HttpListenServer()); - https_->Listen(kHttpsProxyIntAddr); - } - ~ProxyTest() { Thread::Current()->set_socketserver(nullptr); } - - rtc::SocketServer* ss() { return ss_.get(); } - - private: - std::unique_ptr ss_; - std::unique_ptr socks_; - // TODO: Make this a real HTTPS proxy server. - std::unique_ptr https_; -}; - -// Tests whether we can use a SOCKS5 proxy to connect to a server. -TEST_F(ProxyTest, TestSocks5Connect) { - rtc::AsyncSocket* socket = - ss()->CreateAsyncSocket(kSocksProxyIntAddr.family(), SOCK_STREAM); - rtc::AsyncSocksProxySocket* proxy_socket = - new rtc::AsyncSocksProxySocket(socket, kSocksProxyIntAddr, - "", rtc::CryptString()); - // TODO: IPv6-ize these tests when proxy supports IPv6. - - rtc::TestEchoServer server(Thread::Current(), - SocketAddress(INADDR_ANY, 0)); - - rtc::AsyncTCPSocket* packet_socket = rtc::AsyncTCPSocket::Create( - proxy_socket, SocketAddress(INADDR_ANY, 0), server.address()); - EXPECT_TRUE(packet_socket != nullptr); - rtc::TestClient client(packet_socket); - - EXPECT_EQ(Socket::CS_CONNECTING, proxy_socket->GetState()); - EXPECT_TRUE(client.CheckConnected()); - EXPECT_EQ(Socket::CS_CONNECTED, proxy_socket->GetState()); - EXPECT_EQ(server.address(), client.remote_address()); - client.Send("foo", 3); - EXPECT_TRUE(client.CheckNextPacket("foo", 3, nullptr)); - EXPECT_TRUE(client.CheckNoPacket()); -} diff --git a/webrtc/base/proxyinfo.cc b/webrtc/base/proxyinfo.cc deleted file mode 100644 index 76c7708286..0000000000 --- a/webrtc/base/proxyinfo.cc +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "webrtc/base/proxyinfo.h" - -namespace rtc { - -const char * ProxyToString(ProxyType proxy) { - const char * const PROXY_NAMES[] = { "none", "https", "socks5", "unknown" }; - return PROXY_NAMES[proxy]; -} - -ProxyInfo::ProxyInfo() : type(PROXY_NONE), autodetect(false) { -} -ProxyInfo::~ProxyInfo() = default; - -} // namespace rtc diff --git a/webrtc/base/proxyinfo.h b/webrtc/base/proxyinfo.h index 2251b13ee2..cd5c3875dd 100644 --- a/webrtc/base/proxyinfo.h +++ b/webrtc/base/proxyinfo.h @@ -11,31 +11,15 @@ #ifndef WEBRTC_BASE_PROXYINFO_H__ #define WEBRTC_BASE_PROXYINFO_H__ -#include -#include "webrtc/base/socketaddress.h" -#include "webrtc/base/cryptstring.h" - namespace rtc { +// TODO(deadbeef): Remove this; it's not used any more but it's referenced in +// some places, including chromium. enum ProxyType { PROXY_NONE, - PROXY_HTTPS, - PROXY_SOCKS5, - PROXY_UNKNOWN }; -const char * ProxyToString(ProxyType proxy); struct ProxyInfo { - ProxyType type; - SocketAddress address; - std::string autoconfig_url; - bool autodetect; - std::string bypass_list; - std::string username; - CryptString password; - - ProxyInfo(); - ~ProxyInfo(); }; } // namespace rtc diff --git a/webrtc/base/proxyserver.cc b/webrtc/base/proxyserver.cc index 713a98679a..fd36ef123e 100644 --- a/webrtc/base/proxyserver.cc +++ b/webrtc/base/proxyserver.cc @@ -149,8 +149,4 @@ void ProxyBinding::Destroy() { SignalDestroyed(this); } -AsyncProxyServerSocket* SocksProxyServer::WrapSocket(AsyncSocket* socket) { - return new AsyncSocksProxyServerSocket(socket); -} - } // namespace rtc diff --git a/webrtc/base/proxyserver.h b/webrtc/base/proxyserver.h index 86007c3606..1622daf13b 100644 --- a/webrtc/base/proxyserver.h +++ b/webrtc/base/proxyserver.h @@ -83,18 +83,6 @@ class ProxyServer : public sigslot::has_slots<> { RTC_DISALLOW_COPY_AND_ASSIGN(ProxyServer); }; -// SocksProxyServer is a simple extension of ProxyServer to implement SOCKS. -class SocksProxyServer : public ProxyServer { - public: - SocksProxyServer(SocketFactory* int_factory, const SocketAddress& int_addr, - SocketFactory* ext_factory, const SocketAddress& ext_ip) - : ProxyServer(int_factory, int_addr, ext_factory, ext_ip) { - } - protected: - AsyncProxyServerSocket* WrapSocket(AsyncSocket* socket) override; - RTC_DISALLOW_COPY_AND_ASSIGN(SocksProxyServer); -}; - } // namespace rtc #endif // WEBRTC_BASE_PROXYSERVER_H_ diff --git a/webrtc/base/socketadapters.cc b/webrtc/base/socketadapters.cc index 060029c1c7..bc15b870c1 100644 --- a/webrtc/base/socketadapters.cc +++ b/webrtc/base/socketadapters.cc @@ -28,7 +28,6 @@ #include "webrtc/base/bytebuffer.h" #include "webrtc/base/checks.h" -#include "webrtc/base/httpcommon.h" #include "webrtc/base/logging.h" #include "webrtc/base/socketadapters.h" #include "webrtc/base/stringencode.h" @@ -242,607 +241,4 @@ void AsyncSSLServerSocket::ProcessInput(char* data, size_t* len) { BufferInput(false); } -/////////////////////////////////////////////////////////////////////////////// - -AsyncHttpsProxySocket::AsyncHttpsProxySocket(AsyncSocket* socket, - const std::string& user_agent, - const SocketAddress& proxy, - const std::string& username, - const CryptString& password) - : BufferedReadAdapter(socket, 1024), proxy_(proxy), agent_(user_agent), - user_(username), pass_(password), force_connect_(false), state_(PS_ERROR), - context_(0) { -} - -AsyncHttpsProxySocket::~AsyncHttpsProxySocket() { - delete context_; -} - -int AsyncHttpsProxySocket::Connect(const SocketAddress& addr) { - int ret; - LOG(LS_VERBOSE) << "AsyncHttpsProxySocket::Connect(" - << proxy_.ToSensitiveString() << ")"; - dest_ = addr; - state_ = PS_INIT; - if (ShouldIssueConnect()) { - BufferInput(true); - } - ret = BufferedReadAdapter::Connect(proxy_); - // TODO: Set state_ appropriately if Connect fails. - return ret; -} - -SocketAddress AsyncHttpsProxySocket::GetRemoteAddress() const { - return dest_; -} - -int AsyncHttpsProxySocket::Close() { - headers_.clear(); - state_ = PS_ERROR; - dest_.Clear(); - delete context_; - context_ = nullptr; - return BufferedReadAdapter::Close(); -} - -Socket::ConnState AsyncHttpsProxySocket::GetState() const { - if (state_ < PS_TUNNEL) { - return CS_CONNECTING; - } else if (state_ == PS_TUNNEL) { - return CS_CONNECTED; - } else { - return CS_CLOSED; - } -} - -void AsyncHttpsProxySocket::OnConnectEvent(AsyncSocket * socket) { - LOG(LS_VERBOSE) << "AsyncHttpsProxySocket::OnConnectEvent"; - if (!ShouldIssueConnect()) { - state_ = PS_TUNNEL; - BufferedReadAdapter::OnConnectEvent(socket); - return; - } - SendRequest(); -} - -void AsyncHttpsProxySocket::OnCloseEvent(AsyncSocket * socket, int err) { - LOG(LS_VERBOSE) << "AsyncHttpsProxySocket::OnCloseEvent(" << err << ")"; - if ((state_ == PS_WAIT_CLOSE) && (err == 0)) { - state_ = PS_ERROR; - Connect(dest_); - } else { - BufferedReadAdapter::OnCloseEvent(socket, err); - } -} - -void AsyncHttpsProxySocket::ProcessInput(char* data, size_t* len) { - size_t start = 0; - for (size_t pos = start; state_ < PS_TUNNEL && pos < *len;) { - if (state_ == PS_SKIP_BODY) { - size_t consume = std::min(*len - pos, content_length_); - pos += consume; - start = pos; - content_length_ -= consume; - if (content_length_ == 0) { - EndResponse(); - } - continue; - } - - if (data[pos++] != '\n') - continue; - - size_t len = pos - start - 1; - if ((len > 0) && (data[start + len - 1] == '\r')) - --len; - - data[start + len] = 0; - ProcessLine(data + start, len); - start = pos; - } - - *len -= start; - if (*len > 0) { - memmove(data, data + start, *len); - } - - if (state_ != PS_TUNNEL) - return; - - bool remainder = (*len > 0); - BufferInput(false); - SignalConnectEvent(this); - - // FIX: if SignalConnect causes the socket to be destroyed, we are in trouble - if (remainder) - SignalReadEvent(this); // TODO: signal this?? -} - -bool AsyncHttpsProxySocket::ShouldIssueConnect() const { - // TODO: Think about whether a more sophisticated test - // than dest port == 80 is needed. - return force_connect_ || (dest_.port() != 80); -} - -void AsyncHttpsProxySocket::SendRequest() { - std::stringstream ss; - ss << "CONNECT " << dest_.ToString() << " HTTP/1.0\r\n"; - ss << "User-Agent: " << agent_ << "\r\n"; - ss << "Host: " << dest_.HostAsURIString() << "\r\n"; - ss << "Content-Length: 0\r\n"; - ss << "Proxy-Connection: Keep-Alive\r\n"; - ss << headers_; - ss << "\r\n"; - std::string str = ss.str(); - DirectSend(str.c_str(), str.size()); - state_ = PS_LEADER; - expect_close_ = true; - content_length_ = 0; - headers_.clear(); - - LOG(LS_VERBOSE) << "AsyncHttpsProxySocket >> " << str; -} - -void AsyncHttpsProxySocket::ProcessLine(char * data, size_t len) { - LOG(LS_VERBOSE) << "AsyncHttpsProxySocket << " << data; - - if (len == 0) { - if (state_ == PS_TUNNEL_HEADERS) { - state_ = PS_TUNNEL; - } else if (state_ == PS_ERROR_HEADERS) { - Error(defer_error_); - return; - } else if (state_ == PS_SKIP_HEADERS) { - if (content_length_) { - state_ = PS_SKIP_BODY; - } else { - EndResponse(); - return; - } - } else { - static bool report = false; - if (!unknown_mechanisms_.empty() && !report) { - report = true; - std::string msg( - "Unable to connect to the Google Talk service due to an incompatibility " - "with your proxy.\r\nPlease help us resolve this issue by submitting the " - "following information to us using our technical issue submission form " - "at:\r\n\r\n" - "http://www.google.com/support/talk/bin/request.py\r\n\r\n" - "We apologize for the inconvenience.\r\n\r\n" - "Information to submit to Google: " - ); - //std::string msg("Please report the following information to foo@bar.com:\r\nUnknown methods: "); - msg.append(unknown_mechanisms_); -#if defined(WEBRTC_WIN) - MessageBoxA(0, msg.c_str(), "Oops!", MB_OK); -#endif -#if defined(WEBRTC_POSIX) - // TODO: Raise a signal so the UI can be separated. - LOG(LS_ERROR) << "Oops!\n\n" << msg; -#endif - } - // Unexpected end of headers - Error(0); - return; - } - } else if (state_ == PS_LEADER) { - unsigned int code; - if (sscanf(data, "HTTP/%*u.%*u %u", &code) != 1) { - Error(0); - return; - } - switch (code) { - case 200: - // connection good! - state_ = PS_TUNNEL_HEADERS; - return; -#if defined(HTTP_STATUS_PROXY_AUTH_REQ) && (HTTP_STATUS_PROXY_AUTH_REQ != 407) -#error Wrong code for HTTP_STATUS_PROXY_AUTH_REQ -#endif - case 407: // HTTP_STATUS_PROXY_AUTH_REQ - state_ = PS_AUTHENTICATE; - return; - default: - defer_error_ = 0; - state_ = PS_ERROR_HEADERS; - return; - } - } else if ((state_ == PS_AUTHENTICATE) - && (_strnicmp(data, "Proxy-Authenticate:", 19) == 0)) { - std::string response, auth_method; - switch (HttpAuthenticate(data + 19, len - 19, - proxy_, "CONNECT", "/", - user_, pass_, context_, response, auth_method)) { - case HAR_IGNORE: - LOG(LS_VERBOSE) << "Ignoring Proxy-Authenticate: " << auth_method; - if (!unknown_mechanisms_.empty()) - unknown_mechanisms_.append(", "); - unknown_mechanisms_.append(auth_method); - break; - case HAR_RESPONSE: - headers_ = "Proxy-Authorization: "; - headers_.append(response); - headers_.append("\r\n"); - state_ = PS_SKIP_HEADERS; - unknown_mechanisms_.clear(); - break; - case HAR_CREDENTIALS: - defer_error_ = SOCKET_EACCES; - state_ = PS_ERROR_HEADERS; - unknown_mechanisms_.clear(); - break; - case HAR_ERROR: - defer_error_ = 0; - state_ = PS_ERROR_HEADERS; - unknown_mechanisms_.clear(); - break; - } - } else if (_strnicmp(data, "Content-Length:", 15) == 0) { - content_length_ = strtoul(data + 15, 0, 0); - } else if (_strnicmp(data, "Proxy-Connection: Keep-Alive", 28) == 0) { - expect_close_ = false; - /* - } else if (_strnicmp(data, "Connection: close", 17) == 0) { - expect_close_ = true; - */ - } -} - -void AsyncHttpsProxySocket::EndResponse() { - if (!expect_close_) { - SendRequest(); - return; - } - - // No point in waiting for the server to close... let's close now - // TODO: Refactor out PS_WAIT_CLOSE - state_ = PS_WAIT_CLOSE; - BufferedReadAdapter::Close(); - OnCloseEvent(this, 0); -} - -void AsyncHttpsProxySocket::Error(int error) { - BufferInput(false); - Close(); - SetError(error); - SignalCloseEvent(this, error); -} - -/////////////////////////////////////////////////////////////////////////////// - -AsyncSocksProxySocket::AsyncSocksProxySocket(AsyncSocket* socket, - const SocketAddress& proxy, - const std::string& username, - const CryptString& password) - : BufferedReadAdapter(socket, 1024), state_(SS_ERROR), proxy_(proxy), - user_(username), pass_(password) { -} - -AsyncSocksProxySocket::~AsyncSocksProxySocket() = default; - -int AsyncSocksProxySocket::Connect(const SocketAddress& addr) { - int ret; - dest_ = addr; - state_ = SS_INIT; - BufferInput(true); - ret = BufferedReadAdapter::Connect(proxy_); - // TODO: Set state_ appropriately if Connect fails. - return ret; -} - -SocketAddress AsyncSocksProxySocket::GetRemoteAddress() const { - return dest_; -} - -int AsyncSocksProxySocket::Close() { - state_ = SS_ERROR; - dest_.Clear(); - return BufferedReadAdapter::Close(); -} - -Socket::ConnState AsyncSocksProxySocket::GetState() const { - if (state_ < SS_TUNNEL) { - return CS_CONNECTING; - } else if (state_ == SS_TUNNEL) { - return CS_CONNECTED; - } else { - return CS_CLOSED; - } -} - -void AsyncSocksProxySocket::OnConnectEvent(AsyncSocket* socket) { - SendHello(); -} - -void AsyncSocksProxySocket::ProcessInput(char* data, size_t* len) { - RTC_DCHECK(state_ < SS_TUNNEL); - - ByteBufferReader response(data, *len); - - if (state_ == SS_HELLO) { - uint8_t ver, method; - if (!response.ReadUInt8(&ver) || - !response.ReadUInt8(&method)) - return; - - if (ver != 5) { - Error(0); - return; - } - - if (method == 0) { - SendConnect(); - } else if (method == 2) { - SendAuth(); - } else { - Error(0); - return; - } - } else if (state_ == SS_AUTH) { - uint8_t ver, status; - if (!response.ReadUInt8(&ver) || - !response.ReadUInt8(&status)) - return; - - if ((ver != 1) || (status != 0)) { - Error(SOCKET_EACCES); - return; - } - - SendConnect(); - } else if (state_ == SS_CONNECT) { - uint8_t ver, rep, rsv, atyp; - if (!response.ReadUInt8(&ver) || - !response.ReadUInt8(&rep) || - !response.ReadUInt8(&rsv) || - !response.ReadUInt8(&atyp)) - return; - - if ((ver != 5) || (rep != 0)) { - Error(0); - return; - } - - uint16_t port; - if (atyp == 1) { - uint32_t addr; - if (!response.ReadUInt32(&addr) || - !response.ReadUInt16(&port)) - return; - LOG(LS_VERBOSE) << "Bound on " << addr << ":" << port; - } else if (atyp == 3) { - uint8_t len; - std::string addr; - if (!response.ReadUInt8(&len) || - !response.ReadString(&addr, len) || - !response.ReadUInt16(&port)) - return; - LOG(LS_VERBOSE) << "Bound on " << addr << ":" << port; - } else if (atyp == 4) { - std::string addr; - if (!response.ReadString(&addr, 16) || - !response.ReadUInt16(&port)) - return; - LOG(LS_VERBOSE) << "Bound on :" << port; - } else { - Error(0); - return; - } - - state_ = SS_TUNNEL; - } - - // Consume parsed data - *len = response.Length(); - memmove(data, response.Data(), *len); - - if (state_ != SS_TUNNEL) - return; - - bool remainder = (*len > 0); - BufferInput(false); - SignalConnectEvent(this); - - // FIX: if SignalConnect causes the socket to be destroyed, we are in trouble - if (remainder) - SignalReadEvent(this); // TODO: signal this?? -} - -void AsyncSocksProxySocket::SendHello() { - ByteBufferWriter request; - request.WriteUInt8(5); // Socks Version - if (user_.empty()) { - request.WriteUInt8(1); // Authentication Mechanisms - request.WriteUInt8(0); // No authentication - } else { - request.WriteUInt8(2); // Authentication Mechanisms - request.WriteUInt8(0); // No authentication - request.WriteUInt8(2); // Username/Password - } - DirectSend(request.Data(), request.Length()); - state_ = SS_HELLO; -} - -void AsyncSocksProxySocket::SendAuth() { - ByteBufferWriter request; - request.WriteUInt8(1); // Negotiation Version - request.WriteUInt8(static_cast(user_.size())); - request.WriteString(user_); // Username - request.WriteUInt8(static_cast(pass_.GetLength())); - size_t len = pass_.GetLength() + 1; - char * sensitive = new char[len]; - pass_.CopyTo(sensitive, true); - request.WriteString(sensitive); // Password - memset(sensitive, 0, len); - delete [] sensitive; - DirectSend(request.Data(), request.Length()); - state_ = SS_AUTH; -} - -void AsyncSocksProxySocket::SendConnect() { - ByteBufferWriter request; - request.WriteUInt8(5); // Socks Version - request.WriteUInt8(1); // CONNECT - request.WriteUInt8(0); // Reserved - if (dest_.IsUnresolvedIP()) { - std::string hostname = dest_.hostname(); - request.WriteUInt8(3); // DOMAINNAME - request.WriteUInt8(static_cast(hostname.size())); - request.WriteString(hostname); // Destination Hostname - } else { - request.WriteUInt8(1); // IPV4 - request.WriteUInt32(dest_.ip()); // Destination IP - } - request.WriteUInt16(dest_.port()); // Destination Port - DirectSend(request.Data(), request.Length()); - state_ = SS_CONNECT; -} - -void AsyncSocksProxySocket::Error(int error) { - state_ = SS_ERROR; - BufferInput(false); - Close(); - SetError(SOCKET_EACCES); - SignalCloseEvent(this, error); -} - -AsyncSocksProxyServerSocket::AsyncSocksProxyServerSocket(AsyncSocket* socket) - : AsyncProxyServerSocket(socket, kBufferSize), state_(SS_HELLO) { - BufferInput(true); -} - -void AsyncSocksProxyServerSocket::ProcessInput(char* data, size_t* len) { - // TODO: See if the whole message has arrived - RTC_DCHECK(state_ < SS_CONNECT_PENDING); - - ByteBufferReader response(data, *len); - if (state_ == SS_HELLO) { - HandleHello(&response); - } else if (state_ == SS_AUTH) { - HandleAuth(&response); - } else if (state_ == SS_CONNECT) { - HandleConnect(&response); - } - - // Consume parsed data - *len = response.Length(); - memmove(data, response.Data(), *len); -} - -void AsyncSocksProxyServerSocket::DirectSend(const ByteBufferWriter& buf) { - BufferedReadAdapter::DirectSend(buf.Data(), buf.Length()); -} - -void AsyncSocksProxyServerSocket::HandleHello(ByteBufferReader* request) { - uint8_t ver, num_methods; - if (!request->ReadUInt8(&ver) || - !request->ReadUInt8(&num_methods)) { - Error(0); - return; - } - - if (ver != 5) { - Error(0); - return; - } - - // Handle either no-auth (0) or user/pass auth (2) - uint8_t method = 0xFF; - if (num_methods > 0 && !request->ReadUInt8(&method)) { - Error(0); - return; - } - - // TODO: Ask the server which method to use. - SendHelloReply(method); - if (method == 0) { - state_ = SS_CONNECT; - } else if (method == 2) { - state_ = SS_AUTH; - } else { - state_ = SS_ERROR; - } -} - -void AsyncSocksProxyServerSocket::SendHelloReply(uint8_t method) { - ByteBufferWriter response; - response.WriteUInt8(5); // Socks Version - response.WriteUInt8(method); // Auth method - DirectSend(response); -} - -void AsyncSocksProxyServerSocket::HandleAuth(ByteBufferReader* request) { - uint8_t ver, user_len, pass_len; - std::string user, pass; - if (!request->ReadUInt8(&ver) || - !request->ReadUInt8(&user_len) || - !request->ReadString(&user, user_len) || - !request->ReadUInt8(&pass_len) || - !request->ReadString(&pass, pass_len)) { - Error(0); - return; - } - - // TODO: Allow for checking of credentials. - SendAuthReply(0); - state_ = SS_CONNECT; -} - -void AsyncSocksProxyServerSocket::SendAuthReply(uint8_t result) { - ByteBufferWriter response; - response.WriteUInt8(1); // Negotiation Version - response.WriteUInt8(result); - DirectSend(response); -} - -void AsyncSocksProxyServerSocket::HandleConnect(ByteBufferReader* request) { - uint8_t ver, command, reserved, addr_type; - uint32_t ip; - uint16_t port; - if (!request->ReadUInt8(&ver) || - !request->ReadUInt8(&command) || - !request->ReadUInt8(&reserved) || - !request->ReadUInt8(&addr_type) || - !request->ReadUInt32(&ip) || - !request->ReadUInt16(&port)) { - Error(0); - return; - } - - if (ver != 5 || command != 1 || - reserved != 0 || addr_type != 1) { - Error(0); - return; - } - - SignalConnectRequest(this, SocketAddress(ip, port)); - state_ = SS_CONNECT_PENDING; -} - -void AsyncSocksProxyServerSocket::SendConnectResult(int result, - const SocketAddress& addr) { - if (state_ != SS_CONNECT_PENDING) - return; - - ByteBufferWriter response; - response.WriteUInt8(5); // Socks version - response.WriteUInt8((result != 0)); // 0x01 is generic error - response.WriteUInt8(0); // reserved - response.WriteUInt8(1); // IPv4 address - response.WriteUInt32(addr.ip()); - response.WriteUInt16(addr.port()); - DirectSend(response); - BufferInput(false); - state_ = SS_TUNNEL; -} - -void AsyncSocksProxyServerSocket::Error(int error) { - state_ = SS_ERROR; - BufferInput(false); - Close(); - SetError(SOCKET_EACCES); - SignalCloseEvent(this, error); -} - } // namespace rtc diff --git a/webrtc/base/socketadapters.h b/webrtc/base/socketadapters.h index 3b5be10c61..57e1f9eeb1 100644 --- a/webrtc/base/socketadapters.h +++ b/webrtc/base/socketadapters.h @@ -21,7 +21,6 @@ namespace rtc { -struct HttpAuthContext; class ByteBufferReader; class ByteBufferWriter; @@ -94,114 +93,6 @@ class AsyncSSLServerSocket : public BufferedReadAdapter { RTC_DISALLOW_COPY_AND_ASSIGN(AsyncSSLServerSocket); }; -/////////////////////////////////////////////////////////////////////////////// - -// Implements a socket adapter that speaks the HTTP/S proxy protocol. -class AsyncHttpsProxySocket : public BufferedReadAdapter { - public: - AsyncHttpsProxySocket(AsyncSocket* socket, const std::string& user_agent, - const SocketAddress& proxy, - const std::string& username, const CryptString& password); - ~AsyncHttpsProxySocket() override; - - // If connect is forced, the adapter will always issue an HTTP CONNECT to the - // target address. Otherwise, it will connect only if the destination port - // is not port 80. - void SetForceConnect(bool force) { force_connect_ = force; } - - int Connect(const SocketAddress& addr) override; - SocketAddress GetRemoteAddress() const override; - int Close() override; - ConnState GetState() const override; - - protected: - void OnConnectEvent(AsyncSocket* socket) override; - void OnCloseEvent(AsyncSocket* socket, int err) override; - void ProcessInput(char* data, size_t* len) override; - - bool ShouldIssueConnect() const; - void SendRequest(); - void ProcessLine(char* data, size_t len); - void EndResponse(); - void Error(int error); - - private: - SocketAddress proxy_, dest_; - std::string agent_, user_, headers_; - CryptString pass_; - bool force_connect_; - size_t content_length_; - int defer_error_; - bool expect_close_; - enum ProxyState { - PS_INIT, PS_LEADER, PS_AUTHENTICATE, PS_SKIP_HEADERS, PS_ERROR_HEADERS, - PS_TUNNEL_HEADERS, PS_SKIP_BODY, PS_TUNNEL, PS_WAIT_CLOSE, PS_ERROR - } state_; - HttpAuthContext * context_; - std::string unknown_mechanisms_; - RTC_DISALLOW_COPY_AND_ASSIGN(AsyncHttpsProxySocket); -}; - -/////////////////////////////////////////////////////////////////////////////// - -// Implements a socket adapter that speaks the SOCKS proxy protocol. -class AsyncSocksProxySocket : public BufferedReadAdapter { - public: - AsyncSocksProxySocket(AsyncSocket* socket, const SocketAddress& proxy, - const std::string& username, const CryptString& password); - ~AsyncSocksProxySocket() override; - - int Connect(const SocketAddress& addr) override; - SocketAddress GetRemoteAddress() const override; - int Close() override; - ConnState GetState() const override; - - protected: - void OnConnectEvent(AsyncSocket* socket) override; - void ProcessInput(char* data, size_t* len) override; - - void SendHello(); - void SendConnect(); - void SendAuth(); - void Error(int error); - - private: - enum State { - SS_INIT, SS_HELLO, SS_AUTH, SS_CONNECT, SS_TUNNEL, SS_ERROR - }; - State state_; - SocketAddress proxy_, dest_; - std::string user_; - CryptString pass_; - RTC_DISALLOW_COPY_AND_ASSIGN(AsyncSocksProxySocket); -}; - -// Implements a proxy server socket for the SOCKS protocol. -class AsyncSocksProxyServerSocket : public AsyncProxyServerSocket { - public: - explicit AsyncSocksProxyServerSocket(AsyncSocket* socket); - - private: - void ProcessInput(char* data, size_t* len) override; - void DirectSend(const ByteBufferWriter& buf); - - void HandleHello(ByteBufferReader* request); - void SendHelloReply(uint8_t method); - void HandleAuth(ByteBufferReader* request); - void SendAuthReply(uint8_t result); - void HandleConnect(ByteBufferReader* request); - void SendConnectResult(int result, const SocketAddress& addr) override; - - void Error(int error); - - static const int kBufferSize = 1024; - enum State { - SS_HELLO, SS_AUTH, SS_CONNECT, SS_CONNECT_PENDING, SS_TUNNEL, SS_ERROR - }; - State state_; - RTC_DISALLOW_COPY_AND_ASSIGN(AsyncSocksProxyServerSocket); -}; - } // namespace rtc #endif // WEBRTC_BASE_SOCKETADAPTERS_H_ diff --git a/webrtc/p2p/base/basicpacketsocketfactory.cc b/webrtc/p2p/base/basicpacketsocketfactory.cc index c478d63112..1519135882 100644 --- a/webrtc/p2p/base/basicpacketsocketfactory.cc +++ b/webrtc/p2p/base/basicpacketsocketfactory.cc @@ -120,16 +120,6 @@ AsyncPacketSocket* BasicPacketSocketFactory::CreateClientTcpSocket( return NULL; } - // If using a proxy, wrap the socket in a proxy socket. - if (proxy_info.type == PROXY_SOCKS5) { - socket = new AsyncSocksProxySocket( - socket, proxy_info.address, proxy_info.username, proxy_info.password); - } else if (proxy_info.type == PROXY_HTTPS) { - socket = - new AsyncHttpsProxySocket(socket, user_agent, proxy_info.address, - proxy_info.username, proxy_info.password); - } - // Assert that at most one TLS option is used. int tlsOpts = opts & (PacketSocketFactory::OPT_TLS | PacketSocketFactory::OPT_TLS_FAKE | diff --git a/webrtc/p2p/base/p2ptransportchannel_unittest.cc b/webrtc/p2p/base/p2ptransportchannel_unittest.cc index d1548a2224..da0bfb0414 100644 --- a/webrtc/p2p/base/p2ptransportchannel_unittest.cc +++ b/webrtc/p2p/base/p2ptransportchannel_unittest.cc @@ -23,7 +23,6 @@ #include "webrtc/base/natserver.h" #include "webrtc/base/natsocketfactory.h" #include "webrtc/base/physicalsocketserver.h" -#include "webrtc/base/proxyserver.h" #include "webrtc/base/socketaddress.h" #include "webrtc/base/ssladapter.h" #include "webrtc/base/thread.h" @@ -64,12 +63,6 @@ static const SocketAddress kAlternateAddrs[2] = { static const SocketAddress kIPv6AlternateAddrs[2] = { SocketAddress("2401:4030:1:2c00:be30:abcd:efab:cdef", 0), SocketAddress("2601:0:1000:1b03:2e41:38ff:fea6:f2a4", 0)}; -// Addresses for HTTP proxy servers. -static const SocketAddress kHttpsProxyAddrs[2] = - { SocketAddress("11.11.11.1", 443), SocketAddress("22.22.22.1", 443) }; -// Addresses for SOCKS proxy servers. -static const SocketAddress kSocksProxyAddrs[2] = - { SocketAddress("11.11.11.1", 1080), SocketAddress("22.22.22.1", 1080) }; // Internal addresses for NAT boxes. static const SocketAddress kNatAddrs[2] = { SocketAddress("192.168.1.1", 0), SocketAddress("192.168.2.1", 0) }; @@ -189,14 +182,6 @@ class P2PTransportChannelTestBase : public testing::Test, ss_scope_(ss_.get()), stun_server_(TestStunServer::Create(main_, kStunAddr)), turn_server_(main_, kTurnUdpIntAddr, kTurnUdpExtAddr), - socks_server1_(ss_.get(), - kSocksProxyAddrs[0], - ss_.get(), - kSocksProxyAddrs[0]), - socks_server2_(ss_.get(), - kSocksProxyAddrs[1], - ss_.get(), - kSocksProxyAddrs[1]), force_relay_(false) { ep1_.role_ = ICEROLE_CONTROLLING; ep2_.role_ = ICEROLE_CONTROLLED; @@ -228,9 +213,6 @@ class P2PTransportChannelTestBase : public testing::Test, NAT_SYMMETRIC_THEN_CONE, // Double NAT, symmetric outer, cone inner BLOCK_UDP, // Firewall, UDP in/out blocked BLOCK_UDP_AND_INCOMING_TCP, // Firewall, UDP in/out and TCP in blocked - BLOCK_ALL_BUT_OUTGOING_HTTP, // Firewall, only TCP out on 80/443 - PROXY_HTTPS, // All traffic through HTTPS proxy - PROXY_SOCKS, // All traffic through SOCKS proxy NUM_CONFIGS }; @@ -453,13 +435,6 @@ class P2PTransportChannelTestBase : public testing::Test, GetEndpoint(endpoint)->network_manager_.RemoveInterface(addr); fw()->AddRule(false, rtc::FP_ANY, rtc::FD_ANY, addr); } - void SetProxy(int endpoint, rtc::ProxyType type) { - rtc::ProxyInfo info; - info.type = type; - info.address = (type == rtc::PROXY_HTTPS) ? - kHttpsProxyAddrs[endpoint] : kSocksProxyAddrs[endpoint]; - GetAllocator(endpoint)->set_proxy("unittest/1.0", info); - } void SetAllocatorFlags(int endpoint, int flags) { GetAllocator(endpoint)->set_flags(flags); } @@ -882,8 +857,6 @@ class P2PTransportChannelTestBase : public testing::Test, rtc::SocketServerScope ss_scope_; std::unique_ptr stun_server_; TestTurnServer turn_server_; - rtc::SocksProxyServer socks_server1_; - rtc::SocksProxyServer socks_server2_; Endpoint ep1_; Endpoint ep2_; RemoteIceParameterSource remote_ice_parameter_source_ = FROM_CANDIDATE; @@ -1025,9 +998,6 @@ class P2PTransportChannelTest : public P2PTransportChannelTestBase { break; case BLOCK_UDP: case BLOCK_UDP_AND_INCOMING_TCP: - case BLOCK_ALL_BUT_OUTGOING_HTTP: - case PROXY_HTTPS: - case PROXY_SOCKS: AddAddress(endpoint, kPublicAddrs[endpoint]); // Block all UDP fw()->AddRule(false, rtc::FP_UDP, rtc::FD_ANY, @@ -1036,28 +1006,6 @@ class P2PTransportChannelTest : public P2PTransportChannelTestBase { // Block TCP inbound to the endpoint fw()->AddRule(false, rtc::FP_TCP, SocketAddress(), kPublicAddrs[endpoint]); - } else if (config == BLOCK_ALL_BUT_OUTGOING_HTTP) { - // Block all TCP to/from the endpoint except 80/443 out - fw()->AddRule(true, rtc::FP_TCP, kPublicAddrs[endpoint], - SocketAddress(rtc::IPAddress(INADDR_ANY), 80)); - fw()->AddRule(true, rtc::FP_TCP, kPublicAddrs[endpoint], - SocketAddress(rtc::IPAddress(INADDR_ANY), 443)); - fw()->AddRule(false, rtc::FP_TCP, rtc::FD_ANY, - kPublicAddrs[endpoint]); - } else if (config == PROXY_HTTPS) { - // Block all TCP to/from the endpoint except to the proxy server - fw()->AddRule(true, rtc::FP_TCP, kPublicAddrs[endpoint], - kHttpsProxyAddrs[endpoint]); - fw()->AddRule(false, rtc::FP_TCP, rtc::FD_ANY, - kPublicAddrs[endpoint]); - SetProxy(endpoint, rtc::PROXY_HTTPS); - } else if (config == PROXY_SOCKS) { - // Block all TCP to/from the endpoint except to the proxy server - fw()->AddRule(true, rtc::FP_TCP, kPublicAddrs[endpoint], - kSocksProxyAddrs[endpoint]); - fw()->AddRule(false, rtc::FP_TCP, rtc::FD_ANY, - kPublicAddrs[endpoint]); - SetProxy(endpoint, rtc::PROXY_SOCKS5); } break; default: @@ -1088,23 +1036,19 @@ class P2PTransportChannelTest : public P2PTransportChannelTestBase { // Test matrix. Originator behavior defined by rows, receiever by columns. // TODO: Fix NULLs caused by lack of TCP support in NATSocket. -// TODO: Fix NULLs caused by no HTTP proxy support. // TODO: Rearrange rows/columns from best to worst. const P2PTransportChannelTest::Result* P2PTransportChannelTest::kMatrix[NUM_CONFIGS][NUM_CONFIGS] = { -// OPEN CONE ADDR PORT SYMM 2CON SCON !UDP !TCP HTTP PRXH PRXS -/*OP*/ {LULU, LUSU, LUSU, LUSU, LUPU, LUSU, LUPU, LTPT, LTPT, LSRS, NULL, LTPT}, -/*CO*/ {SULU, SUSU, SUSU, SUSU, SUPU, SUSU, SUPU, NULL, NULL, LSRS, NULL, LTRT}, -/*AD*/ {SULU, SUSU, SUSU, SUSU, SUPU, SUSU, SUPU, NULL, NULL, LSRS, NULL, LTRT}, -/*PO*/ {SULU, SUSU, SUSU, SUSU, RUPU, SUSU, RUPU, NULL, NULL, LSRS, NULL, LTRT}, -/*SY*/ {PULU, PUSU, PUSU, PURU, PURU, PUSU, PURU, NULL, NULL, LSRS, NULL, LTRT}, -/*2C*/ {SULU, SUSU, SUSU, SUSU, SUPU, SUSU, SUPU, NULL, NULL, LSRS, NULL, LTRT}, -/*SC*/ {PULU, PUSU, PUSU, PURU, PURU, PUSU, PURU, NULL, NULL, LSRS, NULL, LTRT}, -/*!U*/ {LTPT, NULL, NULL, NULL, NULL, NULL, NULL, LTPT, LTPT, LSRS, NULL, LTRT}, -/*!T*/ {PTLT, NULL, NULL, NULL, NULL, NULL, NULL, PTLT, LTRT, LSRS, NULL, LTRT}, -/*HT*/ {LSRS, LSRS, LSRS, LSRS, LSRS, LSRS, LSRS, LSRS, LSRS, LSRS, NULL, LSRS}, -/*PR*/ {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, -/*PR*/ {LTRT, LTRT, LTRT, LTRT, LTRT, LTRT, LTRT, LTRT, LTRT, LSRS, NULL, LTRT}, + // OPEN CONE ADDR PORT SYMM 2CON SCON !UDP !TCP + /*OP*/ {LULU, LUSU, LUSU, LUSU, LUPU, LUSU, LUPU, LTPT, LTPT}, + /*CO*/ {SULU, SUSU, SUSU, SUSU, SUPU, SUSU, SUPU, NULL, NULL}, + /*AD*/ {SULU, SUSU, SUSU, SUSU, SUPU, SUSU, SUPU, NULL, NULL}, + /*PO*/ {SULU, SUSU, SUSU, SUSU, RUPU, SUSU, RUPU, NULL, NULL}, + /*SY*/ {PULU, PUSU, PUSU, PURU, PURU, PUSU, PURU, NULL, NULL}, + /*2C*/ {SULU, SUSU, SUSU, SUSU, SUPU, SUSU, SUPU, NULL, NULL}, + /*SC*/ {PULU, PUSU, PUSU, PURU, PURU, PUSU, PURU, NULL, NULL}, + /*!U*/ {LTPT, NULL, NULL, NULL, NULL, NULL, NULL, LTPT, LTPT}, + /*!T*/ {PTLT, NULL, NULL, NULL, NULL, NULL, NULL, PTLT, LTRT}, }; // The actual tests that exercise all the various configurations. @@ -1122,19 +1066,16 @@ const P2PTransportChannelTest::Result* #define P2P_TEST(x, y) \ P2P_TEST_DECLARATION(x, y,) -#define P2P_TEST_SET(x) \ - P2P_TEST(x, OPEN) \ - P2P_TEST(x, NAT_FULL_CONE) \ - P2P_TEST(x, NAT_ADDR_RESTRICTED) \ - P2P_TEST(x, NAT_PORT_RESTRICTED) \ - P2P_TEST(x, NAT_SYMMETRIC) \ - P2P_TEST(x, NAT_DOUBLE_CONE) \ - P2P_TEST(x, NAT_SYMMETRIC_THEN_CONE) \ - P2P_TEST(x, BLOCK_UDP) \ - P2P_TEST(x, BLOCK_UDP_AND_INCOMING_TCP) \ - P2P_TEST(x, BLOCK_ALL_BUT_OUTGOING_HTTP) \ - P2P_TEST(x, PROXY_HTTPS) \ - P2P_TEST(x, PROXY_SOCKS) +#define P2P_TEST_SET(x) \ + P2P_TEST(x, OPEN) \ + P2P_TEST(x, NAT_FULL_CONE) \ + P2P_TEST(x, NAT_ADDR_RESTRICTED) \ + P2P_TEST(x, NAT_PORT_RESTRICTED) \ + P2P_TEST(x, NAT_SYMMETRIC) \ + P2P_TEST(x, NAT_DOUBLE_CONE) \ + P2P_TEST(x, NAT_SYMMETRIC_THEN_CONE) \ + P2P_TEST(x, BLOCK_UDP) \ + P2P_TEST(x, BLOCK_UDP_AND_INCOMING_TCP) P2P_TEST_SET(OPEN) P2P_TEST_SET(NAT_FULL_CONE) @@ -1145,9 +1086,6 @@ P2P_TEST_SET(NAT_DOUBLE_CONE) P2P_TEST_SET(NAT_SYMMETRIC_THEN_CONE) P2P_TEST_SET(BLOCK_UDP) P2P_TEST_SET(BLOCK_UDP_AND_INCOMING_TCP) -P2P_TEST_SET(BLOCK_ALL_BUT_OUTGOING_HTTP) -P2P_TEST_SET(PROXY_HTTPS) -P2P_TEST_SET(PROXY_SOCKS) // Test that we restart candidate allocation when local ufrag&pwd changed. // Standard Ice protocol is used. diff --git a/webrtc/p2p/base/packetsocketfactory.h b/webrtc/p2p/base/packetsocketfactory.h index c3b2417526..dac0408297 100644 --- a/webrtc/p2p/base/packetsocketfactory.h +++ b/webrtc/p2p/base/packetsocketfactory.h @@ -13,6 +13,7 @@ #include "webrtc/base/constructormagic.h" #include "webrtc/base/proxyinfo.h" +#include "webrtc/base/socketaddress.h" namespace rtc { diff --git a/webrtc/p2p/base/portallocator.h b/webrtc/p2p/base/portallocator.h index 51474297f7..016a7dc996 100644 --- a/webrtc/p2p/base/portallocator.h +++ b/webrtc/p2p/base/portallocator.h @@ -19,7 +19,6 @@ #include "webrtc/p2p/base/port.h" #include "webrtc/p2p/base/portinterface.h" #include "webrtc/base/helpers.h" -#include "webrtc/base/proxyinfo.h" #include "webrtc/base/sigslot.h" #include "webrtc/base/thread.h" @@ -366,13 +365,6 @@ class PortAllocator : public sigslot::has_slots<> { uint32_t flags() const { return flags_; } void set_flags(uint32_t flags) { flags_ = flags; } - const std::string& user_agent() const { return agent_; } - const rtc::ProxyInfo& proxy() const { return proxy_; } - void set_proxy(const std::string& agent, const rtc::ProxyInfo& proxy) { - agent_ = agent; - proxy_ = proxy; - } - // Gets/Sets the port range to use when choosing client ports. int min_port() const { return min_port_; } int max_port() const { return max_port_; } @@ -425,8 +417,6 @@ class PortAllocator : public sigslot::has_slots<> { } uint32_t flags_; - std::string agent_; - rtc::ProxyInfo proxy_; int min_port_; int max_port_; uint32_t step_delay_; diff --git a/webrtc/p2p/base/relayport.cc b/webrtc/p2p/base/relayport.cc index 2ab71dc3e4..3d56c4acb4 100644 --- a/webrtc/p2p/base/relayport.cc +++ b/webrtc/p2p/base/relayport.cc @@ -210,15 +210,7 @@ RelayPort::~RelayPort() { } void RelayPort::AddServerAddress(const ProtocolAddress& addr) { - // Since HTTP proxies usually only allow 443, - // let's up the priority on PROTO_SSLTCP - if (addr.proto == PROTO_SSLTCP && - (proxy().type == rtc::PROXY_HTTPS || - proxy().type == rtc::PROXY_UNKNOWN)) { - server_addr_.push_front(addr); - } else { - server_addr_.push_back(addr); - } + server_addr_.push_back(addr); } void RelayPort::AddExternalAddress(const ProtocolAddress& addr) { diff --git a/webrtc/p2p/client/basicportallocator.cc b/webrtc/p2p/client/basicportallocator.cc index 629218f89a..49ab142d46 100644 --- a/webrtc/p2p/client/basicportallocator.cc +++ b/webrtc/p2p/client/basicportallocator.cc @@ -689,8 +689,6 @@ void BasicPortAllocatorSession::AddAllocatedPort(Port* port, port->set_content_name(content_name()); port->set_component(component()); port->set_generation(generation()); - if (allocator_->proxy().type != rtc::PROXY_NONE) - port->set_proxy(allocator_->user_agent(), allocator_->proxy()); port->set_send_retransmit_count_attribute( (flags() & PORTALLOCATOR_ENABLE_STUN_RETRANSMIT_ATTRIBUTE) != 0);