summaryrefslogtreecommitdiffstats
path: root/jingle/notifier/communicator/connection_settings.cc
blob: a16ce39e6cd06e56cfece03479249ac4406f57f1 (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
97
98
99
100
101
102
103
// Copyright (c) 2009 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 <algorithm>
#include <deque>
#include <string>
#include <vector>

#include "base/logging.h"
#include "jingle/notifier/communicator/connection_settings.h"
#include "talk/base/helpers.h"
#include "talk/xmpp/xmppclientsettings.h"

namespace notifier {

class RandomGenerator {
 public:
  int operator()(int ceiling) {
    return static_cast<int>(talk_base::CreateRandomId() % ceiling);
  }
};

void ConnectionSettings::FillXmppClientSettings(
    buzz::XmppClientSettings* xcs) const {
  DCHECK(xcs);
  xcs->set_protocol(protocol_);
  xcs->set_server(server_);
  xcs->set_proxy(talk_base::PROXY_NONE);
  xcs->set_use_proxy_auth(false);
}

void ConnectionSettingsList::AddPermutations(const std::string& hostname,
                                             const std::vector<uint32>& iplist,
                                             int16 port,
                                             bool special_port_magic,
                                             bool try_ssltcp_first) {
  // randomize the list. This ensures the iplist isn't always
  // evaluated in the order returned by DNS
  std::vector<uint32> iplist_random = iplist;
  RandomGenerator rg;
  std::random_shuffle(iplist_random.begin(), iplist_random.end(), rg);

  // Put generated addresses in a new deque, then append on the list_, since
  // there are order dependencies and AddPermutations() may be called more
  // than once.
  std::deque<ConnectionSettings> list_temp;

  // Permute addresses for this server. In some cases we haven't resolved the
  // to ip addresses.
  talk_base::SocketAddress server(hostname, port);
  if (iplist_random.empty()) {
    // We couldn't pre-resolve the hostname, so let's hope it will resolve
    // further down the pipeline (by a proxy, for example).
    PermuteForAddress(server, special_port_magic, try_ssltcp_first,
                      &list_temp);
  } else {
    // Generate a set of possibilities for each server address.
    // Don't do permute duplicates.
    for (size_t index = 0; index < iplist_random.size(); ++index) {
      if (std::find(iplist_seen_.begin(), iplist_seen_.end(),
                    iplist_random[index]) != iplist_seen_.end()) {
        continue;
      }
      iplist_seen_.push_back(iplist_random[index]);
      server.SetResolvedIP(iplist_random[index]);
      PermuteForAddress(server, special_port_magic, try_ssltcp_first,
                        &list_temp);
    }
  }

  // Add this list to the instance list
  while (list_temp.size() != 0) {
    list_.push_back(list_temp[0]);
    list_temp.pop_front();
  }
}


void ConnectionSettingsList::PermuteForAddress(
    const talk_base::SocketAddress& server,
    bool special_port_magic,
    bool try_ssltcp_first,
    std::deque<ConnectionSettings>* list_temp) {
  DCHECK(list_temp);
  *(template_.mutable_server()) = server;

  // Use all of the original settings
  list_temp->push_back(template_);

  // Try alternate port
  if (special_port_magic) {
    ConnectionSettings settings(template_);
    settings.set_protocol(cricket::PROTO_SSLTCP);
    settings.mutable_server()->SetPort(443);
    if (try_ssltcp_first) {
      list_temp->push_front(settings);
    } else {
      list_temp->push_back(settings);
    }
  }
}
}  // namespace notifier