| Index: chrome/browser/sync/notifier/communicator/xmpp_connection_generator.cc
|
| ===================================================================
|
| --- chrome/browser/sync/notifier/communicator/xmpp_connection_generator.cc (revision 0)
|
| +++ chrome/browser/sync/notifier/communicator/xmpp_connection_generator.cc (revision 0)
|
| @@ -0,0 +1,210 @@
|
| +// 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.
|
| +
|
| +// XmppConnectionGenerator does the following algorithm:
|
| +// proxy = ResolveProxyInformation(connection_options)
|
| +// for server in server_list
|
| +// get dns_addresses for server
|
| +// connection_list = (dns_addresses X connection methods X proxy).shuffle()
|
| +// for connection in connection_list
|
| +// yield connection
|
| +
|
| +#include "chrome/browser/sync/notifier/communicator/xmpp_connection_generator.h"
|
| +
|
| +#include <vector>
|
| +
|
| +#include "chrome/browser/sync/notifier/base/async_dns_lookup.h"
|
| +#include "chrome/browser/sync/notifier/base/signal_thread_task.h"
|
| +#include "chrome/browser/sync/notifier/communicator/connection_options.h"
|
| +#include "chrome/browser/sync/notifier/communicator/connection_settings.h"
|
| +#include "chrome/browser/sync/notifier/communicator/product_info.h"
|
| +#include "talk/base/autodetectproxy.h"
|
| +#include "talk/base/httpcommon.h"
|
| +#include "talk/base/logging.h"
|
| +#include "talk/base/task.h"
|
| +#include "talk/base/thread.h"
|
| +#include "talk/xmpp/prexmppauth.h"
|
| +#include "talk/xmpp/xmppclientsettings.h"
|
| +#include "talk/xmpp/xmppengine.h"
|
| +
|
| +namespace notifier {
|
| +
|
| +XmppConnectionGenerator::XmppConnectionGenerator(
|
| + talk_base::Task* parent,
|
| + const ConnectionOptions* options,
|
| + bool proxy_only,
|
| + const ServerInformation* server_list,
|
| + int server_count)
|
| + : settings_list_(new ConnectionSettingsList()),
|
| + settings_index_(0),
|
| + server_list_(new ServerInformation[server_count]),
|
| + server_count_(server_count),
|
| + server_index_(-1),
|
| + proxy_only_(proxy_only),
|
| + successfully_resolved_dns_(false),
|
| + first_dns_error_(0),
|
| + options_(options),
|
| + parent_(parent) {
|
| + assert(parent);
|
| + assert(options);
|
| + assert(server_count_ > 0);
|
| + for (int i = 0; i < server_count_; ++i) {
|
| + server_list_[i] = server_list[i];
|
| + }
|
| +}
|
| +
|
| +XmppConnectionGenerator::~XmppConnectionGenerator() {
|
| + LOG(LS_VERBOSE) << "XmppConnectionGenerator::~XmppConnectionGenerator";
|
| +}
|
| +
|
| +const talk_base::ProxyInfo& XmppConnectionGenerator::proxy() const {
|
| + assert(settings_list_.get());
|
| + if (settings_index_ >= settings_list_->GetCount()) {
|
| + return settings_list_->proxy();
|
| + }
|
| +
|
| + ConnectionSettings* settings = settings_list_->GetSettings(settings_index_);
|
| + return settings->proxy();
|
| +}
|
| +
|
| +// Starts resolving proxy information
|
| +void XmppConnectionGenerator::StartGenerating() {
|
| + LOG(LS_VERBOSE) << "XmppConnectionGenerator::StartGenerating";
|
| +
|
| + talk_base::AutoDetectProxy* proxy_detect =
|
| + new talk_base::AutoDetectProxy(GetUserAgentString());
|
| +
|
| + if (options_->autodetect_proxy()) {
|
| + // Pretend the xmpp server is https, when detecting whether a proxy is
|
| + // required to connect.
|
| + talk_base::Url<char> host_url("/",
|
| + server_list_[0].server.IPAsString().c_str(),
|
| + server_list_[0].server.port());
|
| + host_url.set_secure(true);
|
| + proxy_detect->set_server_url(host_url.url());
|
| + } else if (options_->proxy_host().length()) {
|
| + talk_base::SocketAddress proxy(options_->proxy_host(),
|
| + options_->proxy_port());
|
| + proxy_detect->set_proxy(proxy);
|
| + }
|
| + proxy_detect->set_auth_info(options_->use_proxy_auth(),
|
| + options_->auth_user(),
|
| + talk_base::CryptString(options_->auth_pass()));
|
| +
|
| + SignalThreadTask<talk_base::AutoDetectProxy>* wrapper_task =
|
| + new SignalThreadTask<talk_base::AutoDetectProxy>(parent_, &proxy_detect);
|
| + wrapper_task->SignalWorkDone.connect(
|
| + this,
|
| + &XmppConnectionGenerator::OnProxyDetect);
|
| + wrapper_task->Start();
|
| +}
|
| +
|
| +void XmppConnectionGenerator::OnProxyDetect(
|
| + talk_base::AutoDetectProxy* proxy_detect) {
|
| + LOG(LS_VERBOSE) << "XmppConnectionGenerator::OnProxyDetect";
|
| +
|
| + ASSERT(settings_list_.get());
|
| + ASSERT(proxy_detect);
|
| + settings_list_->SetProxy(proxy_detect->proxy());
|
| +
|
| + // Start iterating through the connections (which
|
| + // are generated on demand).
|
| + UseNextConnection();
|
| +}
|
| +
|
| +void XmppConnectionGenerator::UseNextConnection() {
|
| + // Trying to connect
|
| +
|
| + // Iterate to the next possible connection
|
| + settings_index_++;
|
| + if (settings_index_ < settings_list_->GetCount()) {
|
| + // We have more connection settings in the settings_list_ to try, kick
|
| + // off the next one.
|
| + UseCurrentConnection();
|
| + return;
|
| + }
|
| +
|
| + // Iterate to the next possible server
|
| + server_index_++;
|
| + if (server_index_ < server_count_) {
|
| + AsyncDNSLookup* dns_lookup = new AsyncDNSLookup(
|
| + server_list_[server_index_].server);
|
| + SignalThreadTask<AsyncDNSLookup>* wrapper_task =
|
| + new SignalThreadTask<AsyncDNSLookup>(parent_, &dns_lookup);
|
| + wrapper_task->SignalWorkDone.connect(
|
| + this,
|
| + &XmppConnectionGenerator::OnServerDNSResolved);
|
| + wrapper_task->Start();
|
| + return;
|
| + }
|
| +
|
| + // All out of possibilities
|
| + HandleExhaustedConnections();
|
| +}
|
| +
|
| +void XmppConnectionGenerator::OnServerDNSResolved(
|
| + AsyncDNSLookup* dns_lookup) {
|
| + LOG(LS_VERBOSE) << "XmppConnectionGenerator::OnServerDNSResolved";
|
| +
|
| + // Print logging info
|
| + LOG(LS_VERBOSE) << " server: " <<
|
| + server_list_[server_index_].server.ToString() <<
|
| + " error: " << dns_lookup->error();
|
| + if (first_dns_error_ == 0 && dns_lookup->error() != 0) {
|
| + first_dns_error_ = dns_lookup->error();
|
| + }
|
| +
|
| + if (!successfully_resolved_dns_ && dns_lookup->ip_list().size() > 0) {
|
| + successfully_resolved_dns_ = true;
|
| + }
|
| +
|
| + for (int i = 0; i < static_cast<int>(dns_lookup->ip_list().size()); ++i) {
|
| + LOG(LS_VERBOSE)
|
| + << " ip " << i << " : "
|
| + << talk_base::SocketAddress::IPToString(dns_lookup->ip_list()[i]);
|
| + }
|
| +
|
| + // Build the ip list
|
| + assert(settings_list_.get());
|
| + settings_index_ = -1;
|
| + settings_list_->ClearPermutations();
|
| + settings_list_->AddPermutations(
|
| + server_list_[server_index_].server.IPAsString(),
|
| + dns_lookup->ip_list(),
|
| + server_list_[server_index_].server.port(),
|
| + server_list_[server_index_].special_port_magic,
|
| + proxy_only_);
|
| +
|
| + UseNextConnection();
|
| +}
|
| +
|
| +static const char * const PROTO_NAMES[cricket::PROTO_LAST+1] = {
|
| + "udp", "tcp", "ssltcp"
|
| +};
|
| +
|
| +static const char* ProtocolToString(cricket::ProtocolType proto) {
|
| + return PROTO_NAMES[proto];
|
| +}
|
| +
|
| +void XmppConnectionGenerator::UseCurrentConnection() {
|
| + LOG(LS_VERBOSE) << "XmppConnectionGenerator::UseCurrentConnection";
|
| +
|
| + ConnectionSettings* settings = settings_list_->GetSettings(settings_index_);
|
| + LOG(LS_INFO) << "*** Attempting "
|
| + << ProtocolToString(settings->protocol()) << " connection to "
|
| + << settings->server().IPAsString() << ":"
|
| + << settings->server().port()
|
| + << " (via " << ProxyToString(settings->proxy().type)
|
| + << " proxy @ " << settings->proxy().address.IPAsString() << ":"
|
| + << settings->proxy().address.port() << ")";
|
| +
|
| + SignalNewSettings(*settings);
|
| +}
|
| +
|
| +void XmppConnectionGenerator::HandleExhaustedConnections() {
|
| + LOG_F(LS_VERBOSE) << "(" << buzz::XmppEngine::ERROR_SOCKET
|
| + << ", " << first_dns_error_ << ")";
|
| + SignalExhaustedSettings(successfully_resolved_dns_, first_dns_error_);
|
| +}
|
| +} // namespace notifier
|
|
|
| Property changes on: chrome\browser\sync\notifier\communicator\xmpp_connection_generator.cc
|
| ___________________________________________________________________
|
| Added: svn:eol-style
|
| + LF
|
|
|
|
|