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

Unified Diff: net/socket/websocket_transport_connect_sub_job.cc

Issue 240873003: Create WebSocketTransportClientSocketPool (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Rebase. Created 6 years, 6 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
Index: net/socket/websocket_transport_connect_sub_job.cc
diff --git a/net/socket/websocket_transport_connect_sub_job.cc b/net/socket/websocket_transport_connect_sub_job.cc
new file mode 100644
index 0000000000000000000000000000000000000000..fbe8bbcc82c92c107efc0da3e02114df118a02b3
--- /dev/null
+++ b/net/socket/websocket_transport_connect_sub_job.cc
@@ -0,0 +1,170 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/socket/websocket_transport_connect_sub_job.h"
+
+#include "base/logging.h"
+#include "net/base/ip_endpoint.h"
+#include "net/base/net_errors.h"
+#include "net/base/net_log.h"
+#include "net/socket/client_socket_factory.h"
+#include "net/socket/websocket_endpoint_lock_manager.h"
+
+namespace net {
+
+WebSocketTransportConnectSubJob::WebSocketTransportConnectSubJob(
+ const AddressList& addresses,
+ WebSocketTransportConnectJob* parent_job,
+ SubJobType type)
+ : parent_job_(parent_job),
+ addresses_(addresses),
+ current_address_index_(0),
+ next_state_(STATE_NONE),
+ type_(type) {}
+
+WebSocketTransportConnectSubJob::~WebSocketTransportConnectSubJob() {
+ // We don't worry about cancelling the TCP connect, since ~StreamSocket will
+ // take care of it.
+ if (next()) {
+ DCHECK_EQ(STATE_OBTAIN_LOCK_COMPLETE, next_state_);
+ // The ~Waiter destructor will remove this object from the waiting list.
+ } else if (next_state_ == STATE_TRANSPORT_CONNECT_COMPLETE) {
+ WebSocketEndpointLockManager::GetInstance()->UnlockEndpoint(
+ CurrentAddress());
+ }
+}
+
+// Start connecting.
+int WebSocketTransportConnectSubJob::Start() {
+ DCHECK_EQ(STATE_NONE, next_state_);
+ next_state_ = STATE_OBTAIN_LOCK;
+ return DoLoop(OK);
+}
+
+// Called by WebSocketEndpointLockManager when the lock becomes available.
+void WebSocketTransportConnectSubJob::GotEndpointLock() {
+ DCHECK_EQ(STATE_OBTAIN_LOCK_COMPLETE, next_state_);
+ OnIOComplete(OK);
+}
+
+LoadState WebSocketTransportConnectSubJob::GetLoadState() const {
+ switch (next_state_) {
+ case STATE_OBTAIN_LOCK:
+ case STATE_OBTAIN_LOCK_COMPLETE:
+ // TODO(ricea): Add a WebSocket-specific LOAD_STATE ?
+ return LOAD_STATE_WAITING_FOR_AVAILABLE_SOCKET;
+ case STATE_TRANSPORT_CONNECT:
+ case STATE_TRANSPORT_CONNECT_COMPLETE:
+ case STATE_DONE:
+ return LOAD_STATE_CONNECTING;
+ case STATE_NONE:
+ return LOAD_STATE_IDLE;
+ }
+ NOTREACHED();
+ return LOAD_STATE_IDLE;
+}
+
+ClientSocketFactory* WebSocketTransportConnectSubJob::client_socket_factory()
+ const {
+ return parent_job_->helper_.client_socket_factory();
+}
+
+const BoundNetLog& WebSocketTransportConnectSubJob::net_log() const {
+ return parent_job_->net_log();
+}
+
+const IPEndPoint& WebSocketTransportConnectSubJob::CurrentAddress() const {
+ DCHECK_LT(current_address_index_, addresses_.size());
+ return addresses_[current_address_index_];
+}
+
+void WebSocketTransportConnectSubJob::OnIOComplete(int result) {
+ int rv = DoLoop(result);
+ if (rv != ERR_IO_PENDING)
+ parent_job_->OnSubJobComplete(rv, this); // |this| deleted
+}
+
+int WebSocketTransportConnectSubJob::DoLoop(int result) {
+ DCHECK_NE(next_state_, STATE_NONE);
+
+ int rv = result;
+ do {
+ State state = next_state_;
+ next_state_ = STATE_NONE;
+ switch (state) {
+ case STATE_OBTAIN_LOCK:
+ DCHECK_EQ(OK, rv);
+ rv = DoEndpointLock();
+ break;
+ case STATE_OBTAIN_LOCK_COMPLETE:
+ DCHECK_EQ(OK, rv);
+ rv = DoEndpointLockComplete();
+ break;
+ case STATE_TRANSPORT_CONNECT:
+ DCHECK_EQ(OK, rv);
+ rv = DoTransportConnect();
+ break;
+ case STATE_TRANSPORT_CONNECT_COMPLETE:
+ rv = DoTransportConnectComplete(rv);
+ break;
+ default:
+ NOTREACHED();
+ rv = ERR_FAILED;
+ break;
+ }
+ } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE &&
+ next_state_ != STATE_DONE);
+
+ return rv;
+}
+
+int WebSocketTransportConnectSubJob::DoEndpointLock() {
+ int rv = WebSocketEndpointLockManager::GetInstance()->LockEndpoint(
+ CurrentAddress(), this);
+ next_state_ = STATE_OBTAIN_LOCK_COMPLETE;
+ return rv;
+}
+
+int WebSocketTransportConnectSubJob::DoEndpointLockComplete() {
+ next_state_ = STATE_TRANSPORT_CONNECT;
+ return OK;
+}
+
+int WebSocketTransportConnectSubJob::DoTransportConnect() {
+ // TODO(ricea): Update global g_last_connect_time and report
+ // ConnectInterval.
+ next_state_ = STATE_TRANSPORT_CONNECT_COMPLETE;
+ AddressList one_address(CurrentAddress());
+ transport_socket_ = client_socket_factory()->CreateTransportClientSocket(
+ one_address, net_log().net_log(), net_log().source());
+ // This use of base::Unretained() is safe because transport_socket_ is
+ // destroyed in the destructor.
+ return transport_socket_->Connect(base::Bind(
+ &WebSocketTransportConnectSubJob::OnIOComplete, base::Unretained(this)));
+}
+
+int WebSocketTransportConnectSubJob::DoTransportConnectComplete(int result) {
+ next_state_ = STATE_DONE;
+ WebSocketEndpointLockManager* endpoint_lock_manager =
+ WebSocketEndpointLockManager::GetInstance();
+ if (result != OK) {
+ endpoint_lock_manager->UnlockEndpoint(CurrentAddress());
+
+ if (current_address_index_ + 1 < addresses_.size()) {
+ // Try falling back to the next address in the list.
+ next_state_ = STATE_OBTAIN_LOCK;
+ ++current_address_index_;
+ result = OK;
+ }
+
+ return result;
+ }
+
+ endpoint_lock_manager->RememberSocket(transport_socket_.get(),
+ CurrentAddress());
+
+ return result;
+}
+
+} // namespace net

Powered by Google App Engine
This is Rietveld 408576698