summaryrefslogtreecommitdiffstats
path: root/blimp/net/client_connection_manager.cc
blob: 7ffc77a235214f662ee9c7b35069fc7225cbe12b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
// Copyright 2015 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 "blimp/net/client_connection_manager.h"

#include "base/logging.h"
#include "blimp/common/create_blimp_message.h"
#include "blimp/common/proto/blimp_message.pb.h"
#include "blimp/common/protocol_version.h"
#include "blimp/net/blimp_connection.h"
#include "blimp/net/blimp_message_processor.h"
#include "blimp/net/blimp_transport.h"
#include "blimp/net/browser_connection_handler.h"
#include "blimp/net/connection_handler.h"
#include "net/base/net_errors.h"

namespace blimp {

ClientConnectionManager::ClientConnectionManager(
    ConnectionHandler* connection_handler)
    : connection_handler_(connection_handler), weak_factory_(this) {
  DCHECK(connection_handler_);
}

ClientConnectionManager::~ClientConnectionManager() {}

void ClientConnectionManager::AddTransport(
    scoped_ptr<BlimpTransport> transport) {
  DCHECK(transport);
  transports_.push_back(std::move(transport));
}

void ClientConnectionManager::Connect() {
  // A |transport| added first is used first. When it fails to connect,
  // the next transport is used.
  DCHECK(!transports_.empty());
  Connect(0);
}

void ClientConnectionManager::Connect(int transport_index) {
  DVLOG(1) << "ClientConnectionManager::Connect(" << transport_index << ")";
  if (static_cast<size_t>(transport_index) < transports_.size()) {
    transports_[transport_index]->Connect(
        base::Bind(&ClientConnectionManager::OnConnectResult,
                   base::Unretained(this), transport_index));
  } else {
    // TODO(haibinlu): add an error reporting path out for this.
    LOG(WARNING) << "All transports failed to connect";
  }
}

void ClientConnectionManager::OnConnectResult(int transport_index, int result) {
  DCHECK_NE(result, net::ERR_IO_PENDING);
  const auto& transport = transports_[transport_index];
  if (result == net::OK) {
    scoped_ptr<BlimpConnection> connection = transport->TakeConnection();
    connection->AddConnectionErrorObserver(this);
    SendAuthenticationMessage(std::move(connection));
  } else {
    DVLOG(1) << "Transport " << transport->GetName()
             << " failed to connect:" << net::ErrorToString(result);
    Connect(transport_index + 1);
  }
}

void ClientConnectionManager::SendAuthenticationMessage(
    scoped_ptr<BlimpConnection> connection) {
  DVLOG(1) << "Sending authentication message.";
  connection->GetOutgoingMessageProcessor()->ProcessMessage(
      CreateStartConnectionMessage(client_token_, kProtocolVersion),
      base::Bind(&ClientConnectionManager::OnAuthenticationMessageSent,
                 weak_factory_.GetWeakPtr(),
                 base::Passed(std::move(connection))));
}

void ClientConnectionManager::OnAuthenticationMessageSent(
    scoped_ptr<BlimpConnection> connection,
    int result) {
  DVLOG(1) << "AuthenticationMessageSent, result=" << result;
  if (result != net::OK) {
    // If a write error occurred, just throw away |connection|.
    // We don't need to propagate the error code here because the connection
    // will already have done so via the ErrorObserver object.
    return;
  }
  connection_handler_->HandleConnection(std::move(connection));
}

void ClientConnectionManager::OnConnectionError(int error) {
  // TODO(kmarshall): Replace this with actual reconnection logic.
  VLOG(0) << "Connection dropped, error=" << error;
  Connect();
}

}  // namespace blimp