1/*
2 *  Copyright 2010 The WebRTC Project Authors. All rights reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11#ifndef WEBRTC_P2P_CLIENT_FAKEPORTALLOCATOR_H_
12#define WEBRTC_P2P_CLIENT_FAKEPORTALLOCATOR_H_
13
14#include <string>
15#include "webrtc/p2p/base/basicpacketsocketfactory.h"
16#include "webrtc/p2p/base/portallocator.h"
17#include "webrtc/p2p/base/udpport.h"
18#include "webrtc/base/scoped_ptr.h"
19
20namespace rtc {
21class SocketFactory;
22class Thread;
23}
24
25namespace cricket {
26
27class TestUDPPort : public UDPPort {
28 public:
29  static TestUDPPort* Create(rtc::Thread* thread,
30                             rtc::PacketSocketFactory* factory,
31                             rtc::Network* network,
32                             const rtc::IPAddress& ip,
33                             uint16_t min_port,
34                             uint16_t max_port,
35                             const std::string& username,
36                             const std::string& password,
37                             const std::string& origin,
38                             bool emit_localhost_for_anyaddress) {
39    TestUDPPort* port = new TestUDPPort(thread, factory, network, ip, min_port,
40                                        max_port, username, password, origin,
41                                        emit_localhost_for_anyaddress);
42    if (!port->Init()) {
43      delete port;
44      port = nullptr;
45    }
46    return port;
47  }
48  void SendBindingResponse(StunMessage* request,
49                           const rtc::SocketAddress& addr) override {
50    UDPPort::SendBindingResponse(request, addr);
51    sent_binding_response_ = true;
52  }
53  bool sent_binding_response() { return sent_binding_response_; }
54  void set_sent_binding_response(bool response) {
55    sent_binding_response_ = response;
56  }
57
58 protected:
59  TestUDPPort(rtc::Thread* thread,
60              rtc::PacketSocketFactory* factory,
61              rtc::Network* network,
62              const rtc::IPAddress& ip,
63              uint16_t min_port,
64              uint16_t max_port,
65              const std::string& username,
66              const std::string& password,
67              const std::string& origin,
68              bool emit_localhost_for_anyaddress)
69      : UDPPort(thread,
70                factory,
71                network,
72                ip,
73                min_port,
74                max_port,
75                username,
76                password,
77                origin,
78                emit_localhost_for_anyaddress) {}
79
80  bool sent_binding_response_ = false;
81};
82
83class FakePortAllocatorSession : public PortAllocatorSession {
84 public:
85  FakePortAllocatorSession(rtc::Thread* worker_thread,
86                           rtc::PacketSocketFactory* factory,
87                           const std::string& content_name,
88                           int component,
89                           const std::string& ice_ufrag,
90                           const std::string& ice_pwd)
91      : PortAllocatorSession(content_name, component, ice_ufrag, ice_pwd,
92                             cricket::kDefaultPortAllocatorFlags),
93        worker_thread_(worker_thread),
94        factory_(factory),
95        network_("network", "unittest",
96                 rtc::IPAddress(INADDR_LOOPBACK), 8),
97        port_(), running_(false),
98        port_config_count_(0) {
99    network_.AddIP(rtc::IPAddress(INADDR_LOOPBACK));
100  }
101
102  virtual void StartGettingPorts() {
103    if (!port_) {
104      port_.reset(TestUDPPort::Create(worker_thread_, factory_, &network_,
105                                      network_.GetBestIP(), 0, 0, username(),
106                                      password(), std::string(), false));
107      AddPort(port_.get());
108    }
109    ++port_config_count_;
110    running_ = true;
111  }
112
113  virtual void StopGettingPorts() { running_ = false; }
114  virtual bool IsGettingPorts() { return running_; }
115  virtual void ClearGettingPorts() {}
116
117  int port_config_count() { return port_config_count_; }
118
119  void AddPort(cricket::Port* port) {
120    port->set_component(component_);
121    port->set_generation(0);
122    port->SignalPortComplete.connect(
123        this, &FakePortAllocatorSession::OnPortComplete);
124    port->PrepareAddress();
125    SignalPortReady(this, port);
126  }
127  void OnPortComplete(cricket::Port* port) {
128    SignalCandidatesReady(this, port->Candidates());
129    SignalCandidatesAllocationDone(this);
130  }
131
132 private:
133  rtc::Thread* worker_thread_;
134  rtc::PacketSocketFactory* factory_;
135  rtc::Network network_;
136  rtc::scoped_ptr<cricket::Port> port_;
137  bool running_;
138  int port_config_count_;
139};
140
141class FakePortAllocator : public cricket::PortAllocator {
142 public:
143  FakePortAllocator(rtc::Thread* worker_thread,
144                    rtc::PacketSocketFactory* factory)
145      : worker_thread_(worker_thread), factory_(factory) {
146    if (factory_ == NULL) {
147      owned_factory_.reset(new rtc::BasicPacketSocketFactory(
148          worker_thread_));
149      factory_ = owned_factory_.get();
150    }
151  }
152
153  void SetIceServers(
154      const ServerAddresses& stun_servers,
155      const std::vector<RelayServerConfig>& turn_servers) override {
156    stun_servers_ = stun_servers;
157    turn_servers_ = turn_servers;
158  }
159
160  void SetNetworkIgnoreMask(int network_ignore_mask) override {}
161
162  const ServerAddresses& stun_servers() const { return stun_servers_; }
163
164  const std::vector<RelayServerConfig>& turn_servers() const {
165    return turn_servers_;
166  }
167
168  virtual cricket::PortAllocatorSession* CreateSessionInternal(
169      const std::string& content_name,
170      int component,
171      const std::string& ice_ufrag,
172      const std::string& ice_pwd) override {
173    return new FakePortAllocatorSession(
174        worker_thread_, factory_, content_name, component, ice_ufrag, ice_pwd);
175  }
176
177 private:
178  rtc::Thread* worker_thread_;
179  rtc::PacketSocketFactory* factory_;
180  rtc::scoped_ptr<rtc::BasicPacketSocketFactory> owned_factory_;
181  ServerAddresses stun_servers_;
182  std::vector<RelayServerConfig> turn_servers_;
183};
184
185}  // namespace cricket
186
187#endif  // WEBRTC_P2P_CLIENT_FAKEPORTALLOCATOR_H_
188