Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(470)

Unified Diff: net/tools/quic/quic_simple_client.cc

Issue 1015353003: Revert of Add a chromium based simple QUIC client. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/tools/quic/quic_simple_client.h ('k') | net/tools/quic/quic_simple_client_bin.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/tools/quic/quic_simple_client.cc
diff --git a/net/tools/quic/quic_simple_client.cc b/net/tools/quic/quic_simple_client.cc
index 74fa541d4a832b4264734f1d37ced8c0589c71b5..dccec95aa663d4d6a31574f80075c4cf455dda97 100644
--- a/net/tools/quic/quic_simple_client.cc
+++ b/net/tools/quic/quic_simple_client.cc
@@ -2,102 +2,154 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/tools/quic/quic_simple_client.h"
+#include "net/tools/quic/quic_client.h"
+
+#include <errno.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <unistd.h>
#include "base/logging.h"
-#include "base/run_loop.h"
-#include "net/base/net_errors.h"
-#include "net/http/http_request_info.h"
#include "net/quic/crypto/quic_random.h"
#include "net/quic/quic_connection.h"
-#include "net/quic/quic_connection_helper.h"
-#include "net/quic/quic_default_packet_writer.h"
+#include "net/quic/quic_data_reader.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/quic_server_id.h"
-#include "net/udp/udp_client_socket.h"
+#include "net/tools/balsa/balsa_headers.h"
+#include "net/tools/epoll_server/epoll_server.h"
+#include "net/tools/quic/quic_epoll_connection_helper.h"
+#include "net/tools/quic/quic_socket_utils.h"
+#include "net/tools/quic/quic_spdy_client_stream.h"
+
+#ifndef SO_RXQ_OVFL
+#define SO_RXQ_OVFL 40
+#endif
using std::string;
-using std::vector;
namespace net {
namespace tools {
-namespace {
-
-// Allocate some extra space so we can send an error if the server goes over
-// the limit.
-const int kReadBufferSize = 2 * kMaxPacketSize;
-
-} // namespace
-
-QuicSimpleClient::QuicSimpleClient(IPEndPoint server_address,
- const QuicServerId& server_id,
- const QuicVersionVector& supported_versions)
+
+const PollBits kEpollFlags = PollBits(NET_POLLIN | NET_POLLOUT | NET_POLLET);
+
+QuicClient::QuicClient(IPEndPoint server_address,
+ const QuicServerId& server_id,
+ const QuicVersionVector& supported_versions,
+ EpollServer* epoll_server)
: server_address_(server_address),
server_id_(server_id),
local_port_(0),
+ epoll_server_(epoll_server),
+ fd_(-1),
helper_(CreateQuicConnectionHelper()),
initialized_(false),
+ packets_dropped_(0),
+ overflow_supported_(false),
supported_versions_(supported_versions),
- read_pending_(false),
- synchronous_read_count_(0),
- read_buffer_(new IOBufferWithSize(kReadBufferSize)),
- weak_factory_(this) {
-}
-
-QuicSimpleClient::QuicSimpleClient(IPEndPoint server_address,
- const QuicServerId& server_id,
- const QuicVersionVector& supported_versions,
- const QuicConfig& config)
+ store_response_(false),
+ latest_response_code_(-1) {
+}
+
+QuicClient::QuicClient(IPEndPoint server_address,
+ const QuicServerId& server_id,
+ const QuicVersionVector& supported_versions,
+ const QuicConfig& config,
+ EpollServer* epoll_server)
: server_address_(server_address),
server_id_(server_id),
config_(config),
local_port_(0),
+ epoll_server_(epoll_server),
+ fd_(-1),
helper_(CreateQuicConnectionHelper()),
initialized_(false),
+ packets_dropped_(0),
+ overflow_supported_(false),
supported_versions_(supported_versions),
- read_pending_(false),
- synchronous_read_count_(0),
- read_buffer_(new IOBufferWithSize(kReadBufferSize)),
- weak_factory_(this) {
-}
-
-QuicSimpleClient::~QuicSimpleClient() {
+ store_response_(false),
+ latest_response_code_(-1) {
+}
+
+QuicClient::~QuicClient() {
if (connected()) {
session()->connection()->SendConnectionClosePacket(
QUIC_PEER_GOING_AWAY, "");
}
-}
-
-bool QuicSimpleClient::Initialize() {
+
+ CleanUpUDPSocket();
+}
+
+bool QuicClient::Initialize() {
DCHECK(!initialized_);
+ // If an initial flow control window has not explicitly been set, then use the
+ // same value that Chrome uses: 10 Mb.
+ const uint32 kInitialFlowControlWindow = 10 * 1024 * 1024; // 10 Mb
+ if (config_.GetInitialStreamFlowControlWindowToSend() ==
+ kMinimumFlowControlSendWindow) {
+ config_.SetInitialStreamFlowControlWindowToSend(kInitialFlowControlWindow);
+ }
+ if (config_.GetInitialSessionFlowControlWindowToSend() ==
+ kMinimumFlowControlSendWindow) {
+ config_.SetInitialSessionFlowControlWindowToSend(kInitialFlowControlWindow);
+ }
+
+ epoll_server_->set_timeout_in_us(50 * 1000);
+
if (!CreateUDPSocket()) {
return false;
}
+ epoll_server_->RegisterFD(fd_, this, kEpollFlags);
initialized_ = true;
return true;
}
-QuicSimpleClient::DummyPacketWriterFactory::DummyPacketWriterFactory(
+QuicClient::DummyPacketWriterFactory::DummyPacketWriterFactory(
QuicPacketWriter* writer)
: writer_(writer) {}
-QuicSimpleClient::DummyPacketWriterFactory::~DummyPacketWriterFactory() {}
-
-QuicPacketWriter* QuicSimpleClient::DummyPacketWriterFactory::Create(
+QuicClient::DummyPacketWriterFactory::~DummyPacketWriterFactory() {}
+
+QuicPacketWriter* QuicClient::DummyPacketWriterFactory::Create(
QuicConnection* /*connection*/) const {
return writer_;
}
-bool QuicSimpleClient::CreateUDPSocket() {
- scoped_ptr<UDPClientSocket> socket(
- new UDPClientSocket(DatagramSocket::DEFAULT_BIND,
- RandIntCallback(),
- &net_log_,
- NetLog::Source()));
-
+
+bool QuicClient::CreateUDPSocket() {
int address_family = server_address_.GetSockAddrFamily();
+ fd_ = QuicSocketUtils::CreateNonBlockingSocket(address_family, SOCK_DGRAM,
+ IPPROTO_UDP);
+ if (fd_ < 0) {
+ return false; // failure already logged
+ }
+
+ int get_overflow = 1;
+ int rc = setsockopt(fd_, SOL_SOCKET, SO_RXQ_OVFL, &get_overflow,
+ sizeof(get_overflow));
+ if (rc < 0) {
+ DLOG(WARNING) << "Socket overflow detection not supported";
+ } else {
+ overflow_supported_ = true;
+ }
+
+ if (!QuicSocketUtils::SetReceiveBufferSize(fd_,
+ kDefaultSocketReceiveBuffer)) {
+ return false;
+ }
+
+ if (!QuicSocketUtils::SetSendBufferSize(fd_, kDefaultSocketReceiveBuffer)) {
+ return false;
+ }
+
+ rc = QuicSocketUtils::SetGetAddressInfo(fd_, address_family);
+ if (rc < 0) {
+ LOG(ERROR) << "IP detection not supported" << strerror(errno);
+ return false;
+ }
+
if (bind_to_address_.size() != 0) {
client_address_ = IPEndPoint(bind_to_address_, local_port_);
} else if (address_family == AF_INET) {
@@ -110,91 +162,88 @@
client_address_ = IPEndPoint(any6, local_port_);
}
- int rc = socket->Connect(server_address_);
- if (rc != OK) {
- LOG(ERROR) << "Connect failed: " << ErrorToString(rc);
- return false;
- }
-
- rc = socket->SetReceiveBufferSize(kDefaultSocketReceiveBuffer);
- if (rc != OK) {
- LOG(ERROR) << "SetReceiveBufferSize() failed: " << ErrorToString(rc);
- return false;
- }
-
- rc = socket->SetSendBufferSize(kDefaultSocketReceiveBuffer);
- if (rc != OK) {
- LOG(ERROR) << "SetSendBufferSize() failed: " << ErrorToString(rc);
- return false;
- }
-
- rc = socket->GetLocalAddress(&client_address_);
- if (rc != OK) {
- LOG(ERROR) << "GetLocalAddress failed: " << ErrorToString(rc);
- return false;
- }
-
- socket_.swap(socket);
-
- read_pending_ = false;
-
- if (socket != nullptr) {
- socket->Close();
+ sockaddr_storage raw_addr;
+ socklen_t raw_addr_len = sizeof(raw_addr);
+ CHECK(client_address_.ToSockAddr(reinterpret_cast<sockaddr*>(&raw_addr),
+ &raw_addr_len));
+ rc = bind(fd_,
+ reinterpret_cast<const sockaddr*>(&raw_addr),
+ sizeof(raw_addr));
+ if (rc < 0) {
+ LOG(ERROR) << "Bind failed: " << strerror(errno);
+ return false;
+ }
+
+ SockaddrStorage storage;
+ if (getsockname(fd_, storage.addr, &storage.addr_len) != 0 ||
+ !client_address_.FromSockAddr(storage.addr, storage.addr_len)) {
+ LOG(ERROR) << "Unable to get self address. Error: " << strerror(errno);
}
return true;
}
-bool QuicSimpleClient::Connect() {
+bool QuicClient::Connect() {
StartConnect();
- StartReading();
while (EncryptionBeingEstablished()) {
WaitForEvents();
}
return session_->connection()->connected();
}
-void QuicSimpleClient::StartConnect() {
+void QuicClient::StartConnect() {
DCHECK(initialized_);
DCHECK(!connected());
- writer_.reset(CreateQuicPacketWriter());
- connection_ = new QuicConnection(GenerateConnectionId(),
- server_address_,
- helper_.get(),
- DummyPacketWriterFactory(writer_.get()),
- /* owns_writer= */ false,
- Perspective::IS_CLIENT,
- server_id_.is_https(),
- supported_versions_);
- session_.reset(new QuicSimpleClientSession(config_, connection_));
+ QuicPacketWriter* writer = CreateQuicPacketWriter();
+
+ DummyPacketWriterFactory factory(writer);
+
+ session_.reset(new QuicClientSession(
+ config_,
+ new QuicConnection(GenerateConnectionId(), server_address_, helper_.get(),
+ factory,
+ /* owns_writer= */ false, Perspective::IS_CLIENT,
+ server_id_.is_https(), supported_versions_)));
+
+ // Reset |writer_| after |session_| so that the old writer outlives the old
+ // session.
+ if (writer_.get() != writer) {
+ writer_.reset(writer);
+ }
session_->InitializeSession(server_id_, &crypto_config_);
session_->CryptoConnect();
}
-bool QuicSimpleClient::EncryptionBeingEstablished() {
+bool QuicClient::EncryptionBeingEstablished() {
return !session_->IsEncryptionEstablished() &&
session_->connection()->connected();
}
-void QuicSimpleClient::Disconnect() {
+void QuicClient::Disconnect() {
DCHECK(initialized_);
if (connected()) {
session()->connection()->SendConnectionClose(QUIC_PEER_GOING_AWAY);
}
- writer_.reset();
-
- read_pending_ = false;
+ CleanUpUDPSocket();
initialized_ = false;
}
-void QuicSimpleClient::SendRequest(const HttpRequestInfo& headers,
- base::StringPiece body,
- bool fin) {
- QuicSimpleClientStream* stream = CreateReliableClientStream();
+void QuicClient::CleanUpUDPSocket() {
+ if (fd_ > -1) {
+ epoll_server_->UnregisterFD(fd_);
+ close(fd_);
+ fd_ = -1;
+ }
+}
+
+void QuicClient::SendRequest(const BalsaHeaders& headers,
+ StringPiece body,
+ bool fin) {
+ QuicSpdyClientStream* stream = CreateReliableClientStream();
if (stream == nullptr) {
LOG(DFATAL) << "stream creation failed!";
return;
@@ -203,27 +252,25 @@
stream->set_visitor(this);
}
-void QuicSimpleClient::SendRequestAndWaitForResponse(
- const HttpRequestInfo& request,
- base::StringPiece body,
- bool fin) {
- SendRequest(request, body, fin);
+void QuicClient::SendRequestAndWaitForResponse(const BalsaHeaders& headers,
+ StringPiece body,
+ bool fin) {
+ SendRequest(headers, "", true);
+ while (WaitForEvents()) {
+ }
+}
+
+void QuicClient::SendRequestsAndWaitForResponse(
+ const base::CommandLine::StringVector& args) {
+ for (size_t i = 0; i < args.size(); ++i) {
+ BalsaHeaders headers;
+ headers.SetRequestFirstlineFromStringPieces("GET", args[i], "HTTP/1.1");
+ SendRequest(headers, "", true);
+ }
while (WaitForEvents()) {}
}
-void QuicSimpleClient::SendRequestsAndWaitForResponse(
- const base::CommandLine::StringVector& url_list) {
- for (size_t i = 0; i < url_list.size(); ++i) {
- HttpRequestInfo request;
- request.method = "GET";
- request.url = GURL(url_list[i]);
- SendRequest(request, "", true);
- }
-
- while (WaitForEvents()) {}
-}
-
-QuicSimpleClientStream* QuicSimpleClient::CreateReliableClientStream() {
+QuicSpdyClientStream* QuicClient::CreateReliableClientStream() {
if (!connected()) {
return nullptr;
}
@@ -231,136 +278,127 @@
return session_->CreateOutgoingDataStream();
}
-void QuicSimpleClient::WaitForStreamToClose(QuicStreamId id) {
+void QuicClient::WaitForStreamToClose(QuicStreamId id) {
DCHECK(connected());
while (connected() && !session_->IsClosedStream(id)) {
- WaitForEvents();
- }
-}
-
-void QuicSimpleClient::WaitForCryptoHandshakeConfirmed() {
+ epoll_server_->WaitForEventsAndExecuteCallbacks();
+ }
+}
+
+void QuicClient::WaitForCryptoHandshakeConfirmed() {
DCHECK(connected());
while (connected() && !session_->IsCryptoHandshakeConfirmed()) {
- WaitForEvents();
- }
-}
-
-bool QuicSimpleClient::WaitForEvents() {
+ epoll_server_->WaitForEventsAndExecuteCallbacks();
+ }
+}
+
+bool QuicClient::WaitForEvents() {
DCHECK(connected());
- base::RunLoop().RunUntilIdle();
+ epoll_server_->WaitForEventsAndExecuteCallbacks();
return session_->num_active_requests() != 0;
}
-void QuicSimpleClient::OnClose(QuicDataStream* stream) {
- QuicSimpleClientStream* client_stream =
- static_cast<QuicSimpleClientStream*>(stream);
+void QuicClient::OnEvent(int fd, EpollEvent* event) {
+ DCHECK_EQ(fd, fd_);
+
+ if (event->in_events & NET_POLLIN) {
+ while (connected() && ReadAndProcessPacket()) {
+ }
+ }
+ if (connected() && (event->in_events & NET_POLLOUT)) {
+ writer_->SetWritable();
+ session_->connection()->OnCanWrite();
+ }
+ if (event->in_events & NET_POLLERR) {
+ DVLOG(1) << "NET_POLLERR";
+ }
+}
+
+void QuicClient::OnClose(QuicDataStream* stream) {
+ QuicSpdyClientStream* client_stream =
+ static_cast<QuicSpdyClientStream*>(stream);
if (response_listener_.get() != nullptr) {
response_listener_->OnCompleteResponse(
- stream->id(), *client_stream->headers(), client_stream->data());
+ stream->id(), client_stream->headers(), client_stream->data());
}
// Store response headers and body.
if (store_response_) {
- latest_response_code_ = client_stream->headers()->response_code();
- client_stream->headers()->GetNormalizedHeaders(&latest_response_headers_);
+ latest_response_code_ = client_stream->headers().parsed_response_code();
+ client_stream->headers().DumpHeadersToString(&latest_response_headers_);
latest_response_body_ = client_stream->data();
}
}
-bool QuicSimpleClient::connected() const {
+bool QuicClient::connected() const {
return session_.get() && session_->connection() &&
session_->connection()->connected();
}
-bool QuicSimpleClient::goaway_received() const {
+bool QuicClient::goaway_received() const {
return session_ != nullptr && session_->goaway_received();
}
-size_t QuicSimpleClient::latest_response_code() const {
+size_t QuicClient::latest_response_code() const {
LOG_IF(DFATAL, !store_response_) << "Response not stored!";
return latest_response_code_;
}
-const string& QuicSimpleClient::latest_response_headers() const {
+const string& QuicClient::latest_response_headers() const {
LOG_IF(DFATAL, !store_response_) << "Response not stored!";
return latest_response_headers_;
}
-const string& QuicSimpleClient::latest_response_body() const {
+const string& QuicClient::latest_response_body() const {
LOG_IF(DFATAL, !store_response_) << "Response not stored!";
return latest_response_body_;
}
-QuicConnectionId QuicSimpleClient::GenerateConnectionId() {
- return helper_->GetRandomGenerator()->RandUint64();
-}
-
-QuicConnectionHelper* QuicSimpleClient::CreateQuicConnectionHelper() {
- return new QuicConnectionHelper(
- base::MessageLoop::current()->message_loop_proxy().get(),
- &clock_,
- QuicRandom::GetInstance());
-}
-
-QuicPacketWriter* QuicSimpleClient::CreateQuicPacketWriter() {
- return new QuicDefaultPacketWriter(socket_.get());
-}
-
-void QuicSimpleClient::StartReading() {
- if (read_pending_) {
- return;
- }
- read_pending_ = true;
-
- int result = socket_->Read(
- read_buffer_.get(),
- read_buffer_->size(),
- base::Bind(&QuicSimpleClient::OnReadComplete,
- weak_factory_.GetWeakPtr()));
-
- if (result == ERR_IO_PENDING) {
- synchronous_read_count_ = 0;
- return;
- }
-
- if (++synchronous_read_count_ > 32) {
- synchronous_read_count_ = 0;
- // Schedule the processing through the message loop to 1) prevent infinite
- // recursion and 2) avoid blocking the thread for too long.
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&QuicSimpleClient::OnReadComplete,
- weak_factory_.GetWeakPtr(), result));
- } else {
- OnReadComplete(result);
- }
-}
-
-void QuicSimpleClient::OnReadComplete(int result) {
- read_pending_ = false;
- if (result == 0)
- result = ERR_CONNECTION_CLOSED;
-
- if (result < 0) {
- LOG(ERROR) << "QuicSimpleClient read failed: " << ErrorToString(result);
- Disconnect();
- return;
- }
-
- QuicEncryptedPacket packet(read_buffer_->data(), result);
- IPEndPoint local_address;
- IPEndPoint peer_address;
- socket_->GetLocalAddress(&local_address);
- socket_->GetPeerAddress(&peer_address);
- session_->connection()->ProcessUdpPacket(local_address, peer_address, packet);
- if (!session_->connection()->connected()) {
- return;
- }
-
- StartReading();
+QuicConnectionId QuicClient::GenerateConnectionId() {
+ return QuicRandom::GetInstance()->RandUint64();
+}
+
+QuicEpollConnectionHelper* QuicClient::CreateQuicConnectionHelper() {
+ return new QuicEpollConnectionHelper(epoll_server_);
+}
+
+QuicPacketWriter* QuicClient::CreateQuicPacketWriter() {
+ return new QuicDefaultPacketWriter(fd_);
+}
+
+int QuicClient::ReadPacket(char* buffer,
+ int buffer_len,
+ IPEndPoint* server_address,
+ IPAddressNumber* client_ip) {
+ return QuicSocketUtils::ReadPacket(
+ fd_, buffer, buffer_len,
+ overflow_supported_ ? &packets_dropped_ : nullptr, client_ip,
+ server_address);
+}
+
+bool QuicClient::ReadAndProcessPacket() {
+ // Allocate some extra space so we can send an error if the server goes over
+ // the limit.
+ char buf[2 * kMaxPacketSize];
+
+ IPEndPoint server_address;
+ IPAddressNumber client_ip;
+
+ int bytes_read = ReadPacket(buf, arraysize(buf), &server_address, &client_ip);
+
+ if (bytes_read < 0) {
+ return false;
+ }
+
+ QuicEncryptedPacket packet(buf, bytes_read, false);
+
+ IPEndPoint client_address(client_ip, client_address_.port());
+ session_->connection()->ProcessUdpPacket(
+ client_address, server_address, packet);
+ return true;
}
} // namespace tools
« no previous file with comments | « net/tools/quic/quic_simple_client.h ('k') | net/tools/quic/quic_simple_client_bin.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698