2013-07-10 02:45:36 +02:00
|
|
|
// Copyright 2011 Google Inc. All Rights Reserved.
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef TALK_P2P_CLIENT_CONNECTIVITYCHECKER_H_
|
|
|
|
#define TALK_P2P_CLIENT_CONNECTIVITYCHECKER_H_
|
|
|
|
|
|
|
|
#include <map>
|
|
|
|
#include <string>
|
|
|
|
|
2014-08-13 19:26:08 +02:00
|
|
|
#include "talk/p2p/base/basicpacketsocketfactory.h"
|
|
|
|
#include "talk/p2p/client/httpportallocator.h"
|
2014-07-29 19:36:52 +02:00
|
|
|
#include "webrtc/base/basictypes.h"
|
|
|
|
#include "webrtc/base/messagehandler.h"
|
2014-08-13 19:26:08 +02:00
|
|
|
#include "webrtc/base/network.h"
|
2014-07-29 19:36:52 +02:00
|
|
|
#include "webrtc/base/proxyinfo.h"
|
|
|
|
#include "webrtc/base/scoped_ptr.h"
|
|
|
|
#include "webrtc/base/sigslot.h"
|
|
|
|
#include "webrtc/base/socketaddress.h"
|
2013-07-10 02:45:36 +02:00
|
|
|
|
2014-07-29 19:36:52 +02:00
|
|
|
namespace rtc {
|
2013-07-10 02:45:36 +02:00
|
|
|
class AsyncHttpRequest;
|
|
|
|
class AutoDetectProxy;
|
|
|
|
class BasicPacketSocketFactory;
|
|
|
|
class NetworkManager;
|
|
|
|
class PacketSocketFactory;
|
|
|
|
class SignalThread;
|
|
|
|
class TestHttpPortAllocatorSession;
|
|
|
|
class Thread;
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace cricket {
|
|
|
|
class HttpPortAllocator;
|
|
|
|
class Port;
|
|
|
|
class PortAllocatorSession;
|
|
|
|
struct PortConfiguration;
|
|
|
|
class RelayPort;
|
|
|
|
class StunPort;
|
|
|
|
|
|
|
|
// Contains details about a discovered firewall that are of interest
|
|
|
|
// when debugging call failures.
|
|
|
|
struct FirewallInfo {
|
|
|
|
std::string brand;
|
|
|
|
std::string model;
|
|
|
|
|
|
|
|
// TODO: List of current port mappings.
|
|
|
|
};
|
|
|
|
|
|
|
|
// Contains details about a specific connect attempt.
|
|
|
|
struct ConnectInfo {
|
|
|
|
ConnectInfo()
|
|
|
|
: rtt(-1), error(0) {}
|
|
|
|
// Time when the connection was initiated. Needed for calculating
|
|
|
|
// the round trip time.
|
|
|
|
uint32 start_time_ms;
|
|
|
|
// Round trip time in milliseconds or -1 for failed connection.
|
|
|
|
int32 rtt;
|
|
|
|
// Error code representing low level errors like socket errors.
|
|
|
|
int error;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Identifier for a network interface and proxy address pair.
|
|
|
|
struct NicId {
|
2014-07-29 19:36:52 +02:00
|
|
|
NicId(const rtc::IPAddress& ip,
|
|
|
|
const rtc::SocketAddress& proxy_address)
|
2013-07-10 02:45:36 +02:00
|
|
|
: ip(ip),
|
|
|
|
proxy_address(proxy_address) {
|
|
|
|
}
|
2014-07-29 19:36:52 +02:00
|
|
|
rtc::IPAddress ip;
|
|
|
|
rtc::SocketAddress proxy_address;
|
2013-07-10 02:45:36 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
// Comparator implementation identifying unique network interface and
|
|
|
|
// proxy address pairs.
|
|
|
|
class NicIdComparator {
|
|
|
|
public:
|
|
|
|
int compare(const NicId &first, const NicId &second) const {
|
|
|
|
if (first.ip == second.ip) {
|
|
|
|
// Compare proxy address.
|
|
|
|
if (first.proxy_address == second.proxy_address) {
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
return first.proxy_address < second.proxy_address? -1 : 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return first.ip < second.ip ? -1 : 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator()(const NicId &first, const NicId &second) const {
|
|
|
|
return (compare(first, second) < 0);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Contains information of a network interface and proxy address pair.
|
|
|
|
struct NicInfo {
|
|
|
|
NicInfo() {}
|
2014-07-29 19:36:52 +02:00
|
|
|
rtc::IPAddress ip;
|
|
|
|
rtc::ProxyInfo proxy_info;
|
|
|
|
rtc::SocketAddress external_address;
|
2014-07-29 00:26:15 +02:00
|
|
|
ServerAddresses stun_server_addresses;
|
2014-07-29 19:36:52 +02:00
|
|
|
rtc::SocketAddress media_server_address;
|
2013-07-10 02:45:36 +02:00
|
|
|
ConnectInfo stun;
|
|
|
|
ConnectInfo http;
|
|
|
|
ConnectInfo https;
|
|
|
|
ConnectInfo udp;
|
|
|
|
ConnectInfo tcp;
|
|
|
|
ConnectInfo ssltcp;
|
|
|
|
FirewallInfo firewall;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Holds the result of the connectivity check.
|
|
|
|
class NicMap : public std::map<NicId, NicInfo, NicIdComparator> {
|
|
|
|
};
|
|
|
|
|
|
|
|
class TestHttpPortAllocatorSession : public HttpPortAllocatorSession {
|
|
|
|
public:
|
|
|
|
TestHttpPortAllocatorSession(
|
|
|
|
HttpPortAllocator* allocator,
|
|
|
|
const std::string& content_name,
|
|
|
|
int component,
|
|
|
|
const std::string& ice_ufrag,
|
|
|
|
const std::string& ice_pwd,
|
2014-07-29 19:36:52 +02:00
|
|
|
const std::vector<rtc::SocketAddress>& stun_hosts,
|
2013-07-10 02:45:36 +02:00
|
|
|
const std::vector<std::string>& relay_hosts,
|
|
|
|
const std::string& relay_token,
|
|
|
|
const std::string& user_agent)
|
|
|
|
: HttpPortAllocatorSession(
|
|
|
|
allocator, content_name, component, ice_ufrag, ice_pwd, stun_hosts,
|
|
|
|
relay_hosts, relay_token, user_agent) {
|
|
|
|
}
|
2014-07-29 19:36:52 +02:00
|
|
|
void set_proxy(const rtc::ProxyInfo& proxy) {
|
2013-07-10 02:45:36 +02:00
|
|
|
proxy_ = proxy;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ConfigReady(PortConfiguration* config);
|
|
|
|
|
2014-07-29 19:36:52 +02:00
|
|
|
void OnRequestDone(rtc::SignalThread* data);
|
2013-07-10 02:45:36 +02:00
|
|
|
|
|
|
|
sigslot::signal4<const std::string&, const std::string&,
|
|
|
|
const PortConfiguration*,
|
2014-07-29 19:36:52 +02:00
|
|
|
const rtc::ProxyInfo&> SignalConfigReady;
|
|
|
|
sigslot::signal1<rtc::AsyncHttpRequest*> SignalRequestDone;
|
2013-07-10 02:45:36 +02:00
|
|
|
|
|
|
|
private:
|
2014-07-29 19:36:52 +02:00
|
|
|
rtc::ProxyInfo proxy_;
|
2013-07-10 02:45:36 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
// Runs a request/response check on all network interface and proxy
|
|
|
|
// address combinations. The check is considered done either when all
|
|
|
|
// checks has been successful or when the check times out.
|
|
|
|
class ConnectivityChecker
|
2014-07-29 19:36:52 +02:00
|
|
|
: public rtc::MessageHandler, public sigslot::has_slots<> {
|
2013-07-10 02:45:36 +02:00
|
|
|
public:
|
2014-07-29 19:36:52 +02:00
|
|
|
ConnectivityChecker(rtc::Thread* worker,
|
2013-07-10 02:45:36 +02:00
|
|
|
const std::string& jid,
|
|
|
|
const std::string& session_id,
|
|
|
|
const std::string& user_agent,
|
|
|
|
const std::string& relay_token,
|
|
|
|
const std::string& connection);
|
|
|
|
virtual ~ConnectivityChecker();
|
|
|
|
|
|
|
|
// Virtual for gMock.
|
|
|
|
virtual bool Initialize();
|
|
|
|
virtual void Start();
|
|
|
|
|
|
|
|
// MessageHandler implementation.
|
2014-07-29 19:36:52 +02:00
|
|
|
virtual void OnMessage(rtc::Message *msg);
|
2013-07-10 02:45:36 +02:00
|
|
|
|
|
|
|
// Instruct checker to stop and wait until that's done.
|
|
|
|
// Virtual for gMock.
|
|
|
|
virtual void Stop() {
|
|
|
|
worker_->Stop();
|
|
|
|
}
|
|
|
|
|
|
|
|
const NicMap& GetResults() const {
|
|
|
|
return nics_;
|
|
|
|
}
|
|
|
|
|
|
|
|
void set_timeout_ms(uint32 timeout) {
|
|
|
|
timeout_ms_ = timeout;
|
|
|
|
}
|
|
|
|
|
2014-07-29 19:36:52 +02:00
|
|
|
void set_stun_address(const rtc::SocketAddress& stun_address) {
|
2013-07-10 02:45:36 +02:00
|
|
|
stun_address_ = stun_address;
|
|
|
|
}
|
|
|
|
|
|
|
|
const std::string& connection() const {
|
|
|
|
return connection_;
|
|
|
|
}
|
|
|
|
|
|
|
|
const std::string& jid() const {
|
|
|
|
return jid_;
|
|
|
|
}
|
|
|
|
|
|
|
|
const std::string& session_id() const {
|
|
|
|
return session_id_;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Context: Main Thread. Signalled when the connectivity check is complete.
|
|
|
|
sigslot::signal1<ConnectivityChecker*> SignalCheckDone;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
// Can be overridden for test.
|
2014-07-29 19:36:52 +02:00
|
|
|
virtual rtc::NetworkManager* CreateNetworkManager() {
|
|
|
|
return new rtc::BasicNetworkManager();
|
2013-07-10 02:45:36 +02:00
|
|
|
}
|
2014-07-29 19:36:52 +02:00
|
|
|
virtual rtc::BasicPacketSocketFactory* CreateSocketFactory(
|
|
|
|
rtc::Thread* thread) {
|
|
|
|
return new rtc::BasicPacketSocketFactory(thread);
|
2013-07-10 02:45:36 +02:00
|
|
|
}
|
|
|
|
virtual HttpPortAllocator* CreatePortAllocator(
|
2014-07-29 19:36:52 +02:00
|
|
|
rtc::NetworkManager* network_manager,
|
2013-07-10 02:45:36 +02:00
|
|
|
const std::string& user_agent,
|
|
|
|
const std::string& relay_token);
|
|
|
|
virtual StunPort* CreateStunPort(
|
|
|
|
const std::string& username, const std::string& password,
|
2014-07-29 19:36:52 +02:00
|
|
|
const PortConfiguration* config, rtc::Network* network);
|
2013-07-10 02:45:36 +02:00
|
|
|
virtual RelayPort* CreateRelayPort(
|
|
|
|
const std::string& username, const std::string& password,
|
2014-07-29 19:36:52 +02:00
|
|
|
const PortConfiguration* config, rtc::Network* network);
|
2013-07-10 02:45:36 +02:00
|
|
|
virtual void InitiateProxyDetection();
|
2014-07-29 19:36:52 +02:00
|
|
|
virtual void SetProxyInfo(const rtc::ProxyInfo& info);
|
|
|
|
virtual rtc::ProxyInfo GetProxyInfo() const;
|
2013-07-10 02:45:36 +02:00
|
|
|
|
2014-07-29 19:36:52 +02:00
|
|
|
rtc::Thread* worker() {
|
2013-07-10 02:45:36 +02:00
|
|
|
return worker_;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2014-07-29 19:36:52 +02:00
|
|
|
bool AddNic(const rtc::IPAddress& ip,
|
|
|
|
const rtc::SocketAddress& proxy_address);
|
2013-07-10 02:45:36 +02:00
|
|
|
void AllocatePorts();
|
|
|
|
void AllocateRelayPorts();
|
|
|
|
void CheckNetworks();
|
|
|
|
void CreateRelayPorts(
|
|
|
|
const std::string& username, const std::string& password,
|
2014-07-29 19:36:52 +02:00
|
|
|
const PortConfiguration* config, const rtc::ProxyInfo& proxy_info);
|
2013-07-10 02:45:36 +02:00
|
|
|
|
|
|
|
// Must be called by the worker thread.
|
|
|
|
void CleanUp();
|
|
|
|
|
2014-07-29 19:36:52 +02:00
|
|
|
void OnRequestDone(rtc::AsyncHttpRequest* request);
|
2013-07-10 02:45:36 +02:00
|
|
|
void OnRelayPortComplete(Port* port);
|
|
|
|
void OnStunPortComplete(Port* port);
|
|
|
|
void OnRelayPortError(Port* port);
|
|
|
|
void OnStunPortError(Port* port);
|
|
|
|
void OnNetworksChanged();
|
2014-07-29 19:36:52 +02:00
|
|
|
void OnProxyDetect(rtc::SignalThread* thread);
|
2013-07-10 02:45:36 +02:00
|
|
|
void OnConfigReady(
|
|
|
|
const std::string& username, const std::string& password,
|
2014-07-29 19:36:52 +02:00
|
|
|
const PortConfiguration* config, const rtc::ProxyInfo& proxy);
|
2013-07-10 02:45:36 +02:00
|
|
|
void OnConfigWithProxyReady(const PortConfiguration*);
|
|
|
|
void RegisterHttpStart(int port);
|
2014-07-29 19:36:52 +02:00
|
|
|
rtc::Thread* worker_;
|
2013-07-10 02:45:36 +02:00
|
|
|
std::string jid_;
|
|
|
|
std::string session_id_;
|
|
|
|
std::string user_agent_;
|
|
|
|
std::string relay_token_;
|
|
|
|
std::string connection_;
|
2014-07-29 19:36:52 +02:00
|
|
|
rtc::AutoDetectProxy* proxy_detect_;
|
|
|
|
rtc::scoped_ptr<rtc::NetworkManager> network_manager_;
|
|
|
|
rtc::scoped_ptr<rtc::BasicPacketSocketFactory> socket_factory_;
|
|
|
|
rtc::scoped_ptr<HttpPortAllocator> port_allocator_;
|
2013-07-10 02:45:36 +02:00
|
|
|
NicMap nics_;
|
|
|
|
std::vector<Port*> ports_;
|
|
|
|
std::vector<PortAllocatorSession*> sessions_;
|
|
|
|
uint32 timeout_ms_;
|
2014-07-29 19:36:52 +02:00
|
|
|
rtc::SocketAddress stun_address_;
|
|
|
|
rtc::Thread* main_;
|
2013-07-10 02:45:36 +02:00
|
|
|
bool started_;
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace cricket
|
|
|
|
|
|
|
|
#endif // TALK_P2P_CLIENT_CONNECTIVITYCHECKER_H_
|