Home | History | Annotate | Download | only in client
      1 // Copyright 2011 Google Inc. All Rights Reserved.
      2 
      3 
      4 #ifndef TALK_P2P_CLIENT_CONNECTIVITYCHECKER_H_
      5 #define TALK_P2P_CLIENT_CONNECTIVITYCHECKER_H_
      6 
      7 #include <map>
      8 #include <string>
      9 
     10 #include "talk/p2p/base/basicpacketsocketfactory.h"
     11 #include "talk/p2p/client/httpportallocator.h"
     12 #include "webrtc/base/basictypes.h"
     13 #include "webrtc/base/messagehandler.h"
     14 #include "webrtc/base/network.h"
     15 #include "webrtc/base/proxyinfo.h"
     16 #include "webrtc/base/scoped_ptr.h"
     17 #include "webrtc/base/sigslot.h"
     18 #include "webrtc/base/socketaddress.h"
     19 
     20 namespace rtc {
     21 class AsyncHttpRequest;
     22 class AutoDetectProxy;
     23 class BasicPacketSocketFactory;
     24 class NetworkManager;
     25 class PacketSocketFactory;
     26 class SignalThread;
     27 class TestHttpPortAllocatorSession;
     28 class Thread;
     29 }
     30 
     31 namespace cricket {
     32 class HttpPortAllocator;
     33 class Port;
     34 class PortAllocatorSession;
     35 struct PortConfiguration;
     36 class RelayPort;
     37 class StunPort;
     38 
     39 // Contains details about a discovered firewall that are of interest
     40 // when debugging call failures.
     41 struct FirewallInfo {
     42   std::string brand;
     43   std::string model;
     44 
     45   // TODO: List of current port mappings.
     46 };
     47 
     48 // Contains details about a specific connect attempt.
     49 struct ConnectInfo {
     50   ConnectInfo()
     51       : rtt(-1), error(0) {}
     52   // Time when the connection was initiated. Needed for calculating
     53   // the round trip time.
     54   uint32 start_time_ms;
     55   // Round trip time in milliseconds or -1 for failed connection.
     56   int32 rtt;
     57   // Error code representing low level errors like socket errors.
     58   int error;
     59 };
     60 
     61 // Identifier for a network interface and proxy address pair.
     62 struct NicId {
     63   NicId(const rtc::IPAddress& ip,
     64         const rtc::SocketAddress& proxy_address)
     65       : ip(ip),
     66         proxy_address(proxy_address) {
     67   }
     68   rtc::IPAddress ip;
     69   rtc::SocketAddress proxy_address;
     70 };
     71 
     72 // Comparator implementation identifying unique network interface and
     73 // proxy address pairs.
     74 class NicIdComparator {
     75  public:
     76   int compare(const NicId &first, const NicId &second) const {
     77     if (first.ip == second.ip) {
     78       // Compare proxy address.
     79       if (first.proxy_address == second.proxy_address) {
     80         return 0;
     81       } else {
     82         return first.proxy_address < second.proxy_address? -1 : 1;
     83       }
     84     }
     85     return first.ip < second.ip ? -1 : 1;
     86   }
     87 
     88   bool operator()(const NicId &first, const NicId &second) const {
     89     return (compare(first, second) < 0);
     90   }
     91 };
     92 
     93 // Contains information of a network interface and proxy address pair.
     94 struct NicInfo {
     95   NicInfo() {}
     96   rtc::IPAddress ip;
     97   rtc::ProxyInfo proxy_info;
     98   rtc::SocketAddress external_address;
     99   ServerAddresses stun_server_addresses;
    100   rtc::SocketAddress media_server_address;
    101   ConnectInfo stun;
    102   ConnectInfo http;
    103   ConnectInfo https;
    104   ConnectInfo udp;
    105   ConnectInfo tcp;
    106   ConnectInfo ssltcp;
    107   FirewallInfo firewall;
    108 };
    109 
    110 // Holds the result of the connectivity check.
    111 class NicMap : public std::map<NicId, NicInfo, NicIdComparator> {
    112 };
    113 
    114 class TestHttpPortAllocatorSession : public HttpPortAllocatorSession {
    115  public:
    116   TestHttpPortAllocatorSession(
    117       HttpPortAllocator* allocator,
    118       const std::string& content_name,
    119       int component,
    120       const std::string& ice_ufrag,
    121       const std::string& ice_pwd,
    122       const std::vector<rtc::SocketAddress>& stun_hosts,
    123       const std::vector<std::string>& relay_hosts,
    124       const std::string& relay_token,
    125       const std::string& user_agent)
    126       : HttpPortAllocatorSession(
    127           allocator, content_name, component, ice_ufrag, ice_pwd, stun_hosts,
    128           relay_hosts, relay_token, user_agent) {
    129   }
    130   void set_proxy(const rtc::ProxyInfo& proxy) {
    131     proxy_ = proxy;
    132   }
    133 
    134   void ConfigReady(PortConfiguration* config);
    135 
    136   void OnRequestDone(rtc::SignalThread* data);
    137 
    138   sigslot::signal4<const std::string&, const std::string&,
    139                    const PortConfiguration*,
    140                    const rtc::ProxyInfo&> SignalConfigReady;
    141   sigslot::signal1<rtc::AsyncHttpRequest*> SignalRequestDone;
    142 
    143  private:
    144   rtc::ProxyInfo proxy_;
    145 };
    146 
    147 // Runs a request/response check on all network interface and proxy
    148 // address combinations. The check is considered done either when all
    149 // checks has been successful or when the check times out.
    150 class ConnectivityChecker
    151     : public rtc::MessageHandler, public sigslot::has_slots<> {
    152  public:
    153   ConnectivityChecker(rtc::Thread* worker,
    154                       const std::string& jid,
    155                       const std::string& session_id,
    156                       const std::string& user_agent,
    157                       const std::string& relay_token,
    158                       const std::string& connection);
    159   virtual ~ConnectivityChecker();
    160 
    161   // Virtual for gMock.
    162   virtual bool Initialize();
    163   virtual void Start();
    164 
    165   // MessageHandler implementation.
    166   virtual void OnMessage(rtc::Message *msg);
    167 
    168   // Instruct checker to stop and wait until that's done.
    169   // Virtual for gMock.
    170   virtual void Stop() {
    171     worker_->Stop();
    172   }
    173 
    174   const NicMap& GetResults() const {
    175     return nics_;
    176   }
    177 
    178   void set_timeout_ms(uint32 timeout) {
    179     timeout_ms_ = timeout;
    180   }
    181 
    182   void set_stun_address(const rtc::SocketAddress& stun_address) {
    183     stun_address_ = stun_address;
    184   }
    185 
    186   const std::string& connection() const {
    187     return connection_;
    188   }
    189 
    190   const std::string& jid() const {
    191     return jid_;
    192   }
    193 
    194   const std::string& session_id() const {
    195     return session_id_;
    196   }
    197 
    198   // Context: Main Thread. Signalled when the connectivity check is complete.
    199   sigslot::signal1<ConnectivityChecker*> SignalCheckDone;
    200 
    201  protected:
    202   // Can be overridden for test.
    203   virtual rtc::NetworkManager* CreateNetworkManager() {
    204     return new rtc::BasicNetworkManager();
    205   }
    206   virtual rtc::BasicPacketSocketFactory* CreateSocketFactory(
    207       rtc::Thread* thread) {
    208     return new rtc::BasicPacketSocketFactory(thread);
    209   }
    210   virtual HttpPortAllocator* CreatePortAllocator(
    211       rtc::NetworkManager* network_manager,
    212       const std::string& user_agent,
    213       const std::string& relay_token);
    214   virtual StunPort* CreateStunPort(
    215       const std::string& username, const std::string& password,
    216       const PortConfiguration* config, rtc::Network* network);
    217   virtual RelayPort* CreateRelayPort(
    218       const std::string& username, const std::string& password,
    219       const PortConfiguration* config, rtc::Network* network);
    220   virtual void InitiateProxyDetection();
    221   virtual void SetProxyInfo(const rtc::ProxyInfo& info);
    222   virtual rtc::ProxyInfo GetProxyInfo() const;
    223 
    224   rtc::Thread* worker() {
    225     return worker_;
    226   }
    227 
    228  private:
    229   bool AddNic(const rtc::IPAddress& ip,
    230               const rtc::SocketAddress& proxy_address);
    231   void AllocatePorts();
    232   void AllocateRelayPorts();
    233   void CheckNetworks();
    234   void CreateRelayPorts(
    235       const std::string& username, const std::string& password,
    236       const PortConfiguration* config, const rtc::ProxyInfo& proxy_info);
    237 
    238   // Must be called by the worker thread.
    239   void CleanUp();
    240 
    241   void OnRequestDone(rtc::AsyncHttpRequest* request);
    242   void OnRelayPortComplete(Port* port);
    243   void OnStunPortComplete(Port* port);
    244   void OnRelayPortError(Port* port);
    245   void OnStunPortError(Port* port);
    246   void OnNetworksChanged();
    247   void OnProxyDetect(rtc::SignalThread* thread);
    248   void OnConfigReady(
    249       const std::string& username, const std::string& password,
    250       const PortConfiguration* config, const rtc::ProxyInfo& proxy);
    251   void OnConfigWithProxyReady(const PortConfiguration*);
    252   void RegisterHttpStart(int port);
    253   rtc::Thread* worker_;
    254   std::string jid_;
    255   std::string session_id_;
    256   std::string user_agent_;
    257   std::string relay_token_;
    258   std::string connection_;
    259   rtc::AutoDetectProxy* proxy_detect_;
    260   rtc::scoped_ptr<rtc::NetworkManager> network_manager_;
    261   rtc::scoped_ptr<rtc::BasicPacketSocketFactory> socket_factory_;
    262   rtc::scoped_ptr<HttpPortAllocator> port_allocator_;
    263   NicMap nics_;
    264   std::vector<Port*> ports_;
    265   std::vector<PortAllocatorSession*> sessions_;
    266   uint32 timeout_ms_;
    267   rtc::SocketAddress stun_address_;
    268   rtc::Thread* main_;
    269   bool started_;
    270 };
    271 
    272 }  // namespace cricket
    273 
    274 #endif  // TALK_P2P_CLIENT_CONNECTIVITYCHECKER_H_
    275