blob: c3ec3115133e46aa3b152c494049d3a135d2fe72 [file] [log] [blame]
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001/*
2 * Copyright 2004 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
Jonas Olssona4d87372019-07-05 19:08:33 +020011#include "p2p/base/port.h"
12
Yves Gerey3e707812018-11-28 16:47:49 +010013#include <string.h>
Jonas Olssona4d87372019-07-05 19:08:33 +020014
Yves Gerey3e707812018-11-28 16:47:49 +010015#include <cstdint>
Jonas Orelandef60c2b2020-03-26 15:10:39 +010016#include <limits>
deadbeef5c3c1042017-08-04 15:01:57 -070017#include <list>
kwiberg3ec46792016-04-27 07:22:53 -070018#include <memory>
Yves Gerey3e707812018-11-28 16:47:49 +010019#include <string>
20#include <utility>
21#include <vector>
kwiberg3ec46792016-04-27 07:22:53 -070022
Yves Gerey3e707812018-11-28 16:47:49 +010023#include "absl/types/optional.h"
24#include "api/candidate.h"
Patrik Höglund7d003422019-09-17 12:16:35 +020025#include "api/packet_socket_factory.h"
Patrik Höglund56d94522019-11-18 15:53:32 +010026#include "api/transport/stun.h"
Yves Gerey3e707812018-11-28 16:47:49 +010027#include "api/units/time_delta.h"
Steve Anton10542f22019-01-11 09:11:00 -080028#include "p2p/base/basic_packet_socket_factory.h"
29#include "p2p/base/p2p_constants.h"
Steve Anton10542f22019-01-11 09:11:00 -080030#include "p2p/base/port_allocator.h"
31#include "p2p/base/port_interface.h"
Steve Anton10542f22019-01-11 09:11:00 -080032#include "p2p/base/stun_port.h"
33#include "p2p/base/stun_server.h"
34#include "p2p/base/tcp_port.h"
Steve Anton10542f22019-01-11 09:11:00 -080035#include "p2p/base/test_stun_server.h"
36#include "p2p/base/test_turn_server.h"
37#include "p2p/base/transport_description.h"
38#include "p2p/base/turn_port.h"
39#include "p2p/base/turn_server.h"
40#include "p2p/client/relay_port_factory_interface.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020041#include "rtc_base/arraysize.h"
Steve Anton10542f22019-01-11 09:11:00 -080042#include "rtc_base/async_packet_socket.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020043#include "rtc_base/buffer.h"
Steve Anton10542f22019-01-11 09:11:00 -080044#include "rtc_base/byte_buffer.h"
Yves Gerey3e707812018-11-28 16:47:49 +010045#include "rtc_base/checks.h"
46#include "rtc_base/dscp.h"
Steve Anton10542f22019-01-11 09:11:00 -080047#include "rtc_base/fake_clock.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020048#include "rtc_base/gunit.h"
49#include "rtc_base/helpers.h"
50#include "rtc_base/logging.h"
Steve Anton10542f22019-01-11 09:11:00 -080051#include "rtc_base/nat_server.h"
52#include "rtc_base/nat_socket_factory.h"
53#include "rtc_base/nat_types.h"
54#include "rtc_base/net_helper.h"
Yves Gerey3e707812018-11-28 16:47:49 +010055#include "rtc_base/network.h"
56#include "rtc_base/network/sent_packet.h"
57#include "rtc_base/network_constants.h"
Steve Anton10542f22019-01-11 09:11:00 -080058#include "rtc_base/proxy_info.h"
Yves Gerey3e707812018-11-28 16:47:49 +010059#include "rtc_base/socket.h"
Steve Anton10542f22019-01-11 09:11:00 -080060#include "rtc_base/socket_adapters.h"
61#include "rtc_base/socket_address.h"
Yves Gerey3e707812018-11-28 16:47:49 +010062#include "rtc_base/third_party/sigslot/sigslot.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020063#include "rtc_base/thread.h"
Steve Anton10542f22019-01-11 09:11:00 -080064#include "rtc_base/time_utils.h"
65#include "rtc_base/virtual_socket_server.h"
Jonas Oreland21433ca2020-05-13 14:11:25 +020066#include "test/field_trial.h"
Yves Gerey3e707812018-11-28 16:47:49 +010067#include "test/gtest.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000068
Niels Möller6d19d142021-10-06 11:19:03 +020069using rtc::AsyncListenSocket;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000070using rtc::AsyncPacketSocket;
jbauchf1f87202016-03-30 06:43:37 -070071using rtc::ByteBufferReader;
72using rtc::ByteBufferWriter;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000073using rtc::NAT_ADDR_RESTRICTED;
Jonas Olssona4d87372019-07-05 19:08:33 +020074using rtc::NAT_OPEN_CONE;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000075using rtc::NAT_PORT_RESTRICTED;
76using rtc::NAT_SYMMETRIC;
Jonas Olssona4d87372019-07-05 19:08:33 +020077using rtc::NATType;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000078using rtc::PacketSocketFactory;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000079using rtc::Socket;
80using rtc::SocketAddress;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000081
Steve Antonbabf9172017-11-29 10:19:02 -080082namespace cricket {
83namespace {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000084
Steve Antonbabf9172017-11-29 10:19:02 -080085constexpr int kDefaultTimeout = 3000;
86constexpr int kShortTimeout = 1000;
Qingsi Wang22e623a2018-03-13 10:53:57 -070087constexpr int kMaxExpectedSimulatedRtt = 200;
Steve Antonbabf9172017-11-29 10:19:02 -080088const SocketAddress kLocalAddr1("192.168.1.2", 0);
89const SocketAddress kLocalAddr2("192.168.1.3", 0);
90const SocketAddress kNatAddr1("77.77.77.77", rtc::NAT_SERVER_UDP_PORT);
91const SocketAddress kNatAddr2("88.88.88.88", rtc::NAT_SERVER_UDP_PORT);
92const SocketAddress kStunAddr("99.99.99.1", STUN_SERVER_PORT);
Steve Antonbabf9172017-11-29 10:19:02 -080093const SocketAddress kTurnUdpIntAddr("99.99.99.4", STUN_SERVER_PORT);
94const SocketAddress kTurnTcpIntAddr("99.99.99.4", 5010);
95const SocketAddress kTurnUdpExtAddr("99.99.99.5", 0);
96const RelayCredentials kRelayCredentials("test", "test");
97
98// TODO(?): Update these when RFC5245 is completely supported.
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000099// Magic value of 30 is from RFC3484, for IPv4 addresses.
Steve Antonbabf9172017-11-29 10:19:02 -0800100const uint32_t kDefaultPrflxPriority = ICE_TYPE_PREFERENCE_PRFLX << 24 |
101 30 << 8 |
102 (256 - ICE_CANDIDATE_COMPONENT_DEFAULT);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000103
Steve Antonbabf9172017-11-29 10:19:02 -0800104constexpr int kTiebreaker1 = 11111;
105constexpr int kTiebreaker2 = 22222;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000106
Steve Antonbabf9172017-11-29 10:19:02 -0800107const char* data = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
Guo-wei Shiehbe508a12015-04-06 12:48:47 -0700108
Steve Antonbabf9172017-11-29 10:19:02 -0800109Candidate GetCandidate(Port* port) {
110 RTC_DCHECK_GE(port->Candidates().size(), 1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000111 return port->Candidates()[0];
112}
113
Steve Antonbabf9172017-11-29 10:19:02 -0800114SocketAddress GetAddress(Port* port) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000115 return GetCandidate(port).address();
116}
117
Steve Anton11358fe2018-10-09 15:39:19 -0700118std::unique_ptr<IceMessage> CopyStunMessage(const IceMessage& src) {
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200119 auto dst = std::make_unique<IceMessage>();
jbauchf1f87202016-03-30 06:43:37 -0700120 ByteBufferWriter buf;
Steve Anton11358fe2018-10-09 15:39:19 -0700121 src.Write(&buf);
jbauchf1f87202016-03-30 06:43:37 -0700122 ByteBufferReader read_buf(buf);
123 dst->Read(&read_buf);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000124 return dst;
125}
126
Steve Anton11358fe2018-10-09 15:39:19 -0700127bool WriteStunMessage(const StunMessage& msg, ByteBufferWriter* buf) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000128 buf->Resize(0); // clear out any existing buffer contents
Steve Anton11358fe2018-10-09 15:39:19 -0700129 return msg.Write(buf);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000130}
131
Steve Antonbabf9172017-11-29 10:19:02 -0800132} // namespace
133
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000134// Stub port class for testing STUN generation and processing.
135class TestPort : public Port {
136 public:
pkasting@chromium.org332331f2014-11-06 20:19:22 +0000137 TestPort(rtc::Thread* thread,
138 const std::string& type,
139 rtc::PacketSocketFactory* factory,
140 rtc::Network* network,
Peter Boström0c4e06b2015-10-07 12:23:21 +0200141 uint16_t min_port,
142 uint16_t max_port,
pkasting@chromium.org332331f2014-11-06 20:19:22 +0000143 const std::string& username_fragment,
144 const std::string& password)
Peter Boström0c4e06b2015-10-07 12:23:21 +0200145 : Port(thread,
146 type,
147 factory,
148 network,
Peter Boström0c4e06b2015-10-07 12:23:21 +0200149 min_port,
150 max_port,
151 username_fragment,
152 password) {}
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000153 ~TestPort() {}
154
155 // Expose GetStunMessage so that we can test it.
156 using cricket::Port::GetStunMessage;
157
158 // The last StunMessage that was sent on this Port.
Steve Antonbabf9172017-11-29 10:19:02 -0800159 // TODO(?): Make these const; requires changes to SendXXXXResponse.
Karl Wiberg4b6c2ec2018-10-03 15:17:14 +0200160 rtc::BufferT<uint8_t>* last_stun_buf() { return last_stun_buf_.get(); }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000161 IceMessage* last_stun_msg() { return last_stun_msg_.get(); }
162 int last_stun_error_code() {
163 int code = 0;
164 if (last_stun_msg_) {
165 const StunErrorCodeAttribute* error_attr = last_stun_msg_->GetErrorCode();
166 if (error_attr) {
167 code = error_attr->code();
168 }
169 }
170 return code;
171 }
172
173 virtual void PrepareAddress() {
deadbeef5c3c1042017-08-04 15:01:57 -0700174 // Act as if the socket was bound to the best IP on the network, to the
175 // first port in the allowed range.
176 rtc::SocketAddress addr(Network()->GetBestIP(), min_port());
Guo-wei Shieh3d564c12015-08-19 16:51:15 -0700177 AddAddress(addr, addr, rtc::SocketAddress(), "udp", "", "", Type(),
zhihuang26d99c22017-02-13 12:47:27 -0800178 ICE_TYPE_PREFERENCE_HOST, 0, "", true);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000179 }
180
Honghai Zhangf9945b22015-12-15 12:20:13 -0800181 virtual bool SupportsProtocol(const std::string& protocol) const {
182 return true;
183 }
184
Honghai Zhangb9e7b4a2016-06-30 20:52:02 -0700185 virtual ProtocolType GetProtocol() const { return PROTO_UDP; }
186
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000187 // Exposed for testing candidate building.
188 void AddCandidateAddress(const rtc::SocketAddress& addr) {
Guo-wei Shieh3d564c12015-08-19 16:51:15 -0700189 AddAddress(addr, addr, rtc::SocketAddress(), "udp", "", "", Type(),
zhihuang26d99c22017-02-13 12:47:27 -0800190 type_preference_, 0, "", false);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000191 }
192 void AddCandidateAddress(const rtc::SocketAddress& addr,
193 const rtc::SocketAddress& base_address,
194 const std::string& type,
195 int type_preference,
196 bool final) {
Guo-wei Shieh3d564c12015-08-19 16:51:15 -0700197 AddAddress(addr, base_address, rtc::SocketAddress(), "udp", "", "", type,
zhihuang26d99c22017-02-13 12:47:27 -0800198 type_preference, 0, "", final);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000199 }
200
201 virtual Connection* CreateConnection(const Candidate& remote_candidate,
202 CandidateOrigin origin) {
203 Connection* conn = new ProxyConnection(this, 0, remote_candidate);
honghaiz36f50e82016-06-01 15:57:03 -0700204 AddOrReplaceConnection(conn);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000205 // Set use-candidate attribute flag as this will add USE-CANDIDATE attribute
206 // in STUN binding requests.
207 conn->set_use_candidate_attr(true);
208 return conn;
209 }
Yves Gerey665174f2018-06-19 15:03:05 +0200210 virtual int SendTo(const void* data,
211 size_t size,
212 const rtc::SocketAddress& addr,
213 const rtc::PacketOptions& options,
214 bool payload) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000215 if (!payload) {
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200216 auto msg = std::make_unique<IceMessage>();
217 auto buf = std::make_unique<rtc::BufferT<uint8_t>>(
Steve Anton11358fe2018-10-09 15:39:19 -0700218 static_cast<const char*>(data), size);
jbauchf1f87202016-03-30 06:43:37 -0700219 ByteBufferReader read_buf(*buf);
220 if (!msg->Read(&read_buf)) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000221 return -1;
222 }
Steve Anton11358fe2018-10-09 15:39:19 -0700223 last_stun_buf_ = std::move(buf);
224 last_stun_msg_ = std::move(msg);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000225 }
226 return static_cast<int>(size);
227 }
Yves Gerey665174f2018-06-19 15:03:05 +0200228 virtual int SetOption(rtc::Socket::Option opt, int value) { return 0; }
229 virtual int GetOption(rtc::Socket::Option opt, int* value) { return -1; }
230 virtual int GetError() { return 0; }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000231 void Reset() {
232 last_stun_buf_.reset();
233 last_stun_msg_.reset();
234 }
235 void set_type_preference(int type_preference) {
236 type_preference_ = type_preference;
237 }
238
239 private:
Stefan Holmer55674ff2016-01-14 15:49:16 +0100240 void OnSentPacket(rtc::AsyncPacketSocket* socket,
241 const rtc::SentPacket& sent_packet) {
242 PortInterface::SignalSentPacket(sent_packet);
243 }
Karl Wiberg4b6c2ec2018-10-03 15:17:14 +0200244 std::unique_ptr<rtc::BufferT<uint8_t>> last_stun_buf_;
kwiberg3ec46792016-04-27 07:22:53 -0700245 std::unique_ptr<IceMessage> last_stun_msg_;
pbos7640ffa2015-11-30 09:16:59 -0800246 int type_preference_ = 0;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000247};
248
Yves Gerey665174f2018-06-19 15:03:05 +0200249static void SendPingAndReceiveResponse(Connection* lconn,
250 TestPort* lport,
251 Connection* rconn,
252 TestPort* rport,
253 rtc::ScopedFakeClock* clock,
254 int64_t ms) {
hbosbf8d3e52017-02-28 06:34:47 -0800255 lconn->Ping(rtc::TimeMillis());
256 ASSERT_TRUE_WAIT(lport->last_stun_msg(), kDefaultTimeout);
257 ASSERT_TRUE(lport->last_stun_buf());
258 rconn->OnReadPacket(lport->last_stun_buf()->data<char>(),
Niels Möllere6933812018-11-05 13:01:41 +0100259 lport->last_stun_buf()->size(), /* packet_time_us */ -1);
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100260 clock->AdvanceTime(webrtc::TimeDelta::Millis(ms));
hbosbf8d3e52017-02-28 06:34:47 -0800261 ASSERT_TRUE_WAIT(rport->last_stun_msg(), kDefaultTimeout);
262 ASSERT_TRUE(rport->last_stun_buf());
263 lconn->OnReadPacket(rport->last_stun_buf()->data<char>(),
Niels Möllere6933812018-11-05 13:01:41 +0100264 rport->last_stun_buf()->size(), /* packet_time_us */ -1);
hbosbf8d3e52017-02-28 06:34:47 -0800265}
266
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000267class TestChannel : public sigslot::has_slots<> {
268 public:
Artem Titov2dbb4c92021-07-26 15:12:41 +0200269 // Takes ownership of `p1` (but not `p2`).
Steve Anton11358fe2018-10-09 15:39:19 -0700270 explicit TestChannel(std::unique_ptr<Port> p1) : port_(std::move(p1)) {
Guo-wei Shieh1eb87c72015-08-25 11:02:55 -0700271 port_->SignalPortComplete.connect(this, &TestChannel::OnPortComplete);
272 port_->SignalUnknownAddress.connect(this, &TestChannel::OnUnknownAddress);
Lahiru Ginnaliya Gamathige3ba7beb2021-02-01 02:06:11 -0800273 port_->SubscribePortDestroyed(
274 [this](PortInterface* port) { OnSrcPortDestroyed(port); });
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000275 }
276
277 int complete_count() { return complete_count_; }
278 Connection* conn() { return conn_; }
279 const SocketAddress& remote_address() { return remote_address_; }
280 const std::string remote_fragment() { return remote_frag_; }
281
Guo-wei Shieh1eb87c72015-08-25 11:02:55 -0700282 void Start() { port_->PrepareAddress(); }
283 void CreateConnection(const Candidate& remote_candidate) {
284 conn_ = port_->CreateConnection(remote_candidate, Port::ORIGIN_MESSAGE);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000285 IceMode remote_ice_mode =
286 (ice_mode_ == ICEMODE_FULL) ? ICEMODE_LITE : ICEMODE_FULL;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000287 conn_->set_use_candidate_attr(remote_ice_mode == ICEMODE_FULL);
Yves Gerey665174f2018-06-19 15:03:05 +0200288 conn_->SignalStateChange.connect(this,
289 &TestChannel::OnConnectionStateChange);
Guo-wei Shiehbe508a12015-04-06 12:48:47 -0700290 conn_->SignalDestroyed.connect(this, &TestChannel::OnDestroyed);
Guo-wei Shiehb5940412015-08-24 11:58:03 -0700291 conn_->SignalReadyToSend.connect(this,
292 &TestChannel::OnConnectionReadyToSend);
293 connection_ready_to_send_ = false;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000294 }
295 void OnConnectionStateChange(Connection* conn) {
296 if (conn->write_state() == Connection::STATE_WRITABLE) {
297 conn->set_use_candidate_attr(true);
298 nominated_ = true;
299 }
300 }
Guo-wei Shieh1eb87c72015-08-25 11:02:55 -0700301 void AcceptConnection(const Candidate& remote_candidate) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000302 ASSERT_TRUE(remote_request_.get() != NULL);
Guo-wei Shieh1eb87c72015-08-25 11:02:55 -0700303 Candidate c = remote_candidate;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000304 c.set_address(remote_address_);
Guo-wei Shieh1eb87c72015-08-25 11:02:55 -0700305 conn_ = port_->CreateConnection(c, Port::ORIGIN_MESSAGE);
Guo-wei Shiehbe508a12015-04-06 12:48:47 -0700306 conn_->SignalDestroyed.connect(this, &TestChannel::OnDestroyed);
Jonas Oreland9a52bd72019-12-11 11:35:48 +0100307 conn_->SendStunBindingResponse(remote_request_.get());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000308 remote_request_.reset();
309 }
Yves Gerey665174f2018-06-19 15:03:05 +0200310 void Ping() { Ping(0); }
honghaiz34b11eb2016-03-16 08:55:44 -0700311 void Ping(int64_t now) { conn_->Ping(now); }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000312 void Stop() {
Guo-wei Shiehbe508a12015-04-06 12:48:47 -0700313 if (conn_) {
314 conn_->Destroy();
315 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000316 }
317
Yves Gerey665174f2018-06-19 15:03:05 +0200318 void OnPortComplete(Port* port) { complete_count_++; }
319 void SetIceMode(IceMode ice_mode) { ice_mode_ = ice_mode; }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000320
Guo-wei Shiehbe508a12015-04-06 12:48:47 -0700321 int SendData(const char* data, size_t len) {
322 rtc::PacketOptions options;
323 return conn_->Send(data, len, options);
324 }
325
Yves Gerey665174f2018-06-19 15:03:05 +0200326 void OnUnknownAddress(PortInterface* port,
327 const SocketAddress& addr,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000328 ProtocolType proto,
Yves Gerey665174f2018-06-19 15:03:05 +0200329 IceMessage* msg,
330 const std::string& rf,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000331 bool /*port_muxed*/) {
Guo-wei Shieh1eb87c72015-08-25 11:02:55 -0700332 ASSERT_EQ(port_.get(), port);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000333 if (!remote_address_.IsNil()) {
334 ASSERT_EQ(remote_address_, addr);
335 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000336 const cricket::StunUInt32Attribute* priority_attr =
337 msg->GetUInt32(STUN_ATTR_PRIORITY);
338 const cricket::StunByteStringAttribute* mi_attr =
339 msg->GetByteString(STUN_ATTR_MESSAGE_INTEGRITY);
340 const cricket::StunUInt32Attribute* fingerprint_attr =
341 msg->GetUInt32(STUN_ATTR_FINGERPRINT);
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700342 EXPECT_TRUE(priority_attr != NULL);
343 EXPECT_TRUE(mi_attr != NULL);
344 EXPECT_TRUE(fingerprint_attr != NULL);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000345 remote_address_ = addr;
Steve Anton11358fe2018-10-09 15:39:19 -0700346 remote_request_ = CopyStunMessage(*msg);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000347 remote_frag_ = rf;
348 }
349
350 void OnDestroyed(Connection* conn) {
351 ASSERT_EQ(conn_, conn);
Harald Alvestrand97597c02021-11-04 12:01:23 +0000352 RTC_LOG(LS_INFO) << "OnDestroy connection " << conn << " deleted";
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000353 conn_ = NULL;
Guo-wei Shiehbe508a12015-04-06 12:48:47 -0700354 // When the connection is destroyed, also clear these fields so future
355 // connections are possible.
356 remote_request_.reset();
357 remote_address_.Clear();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000358 }
359
360 void OnSrcPortDestroyed(PortInterface* port) {
Guo-wei Shieh1eb87c72015-08-25 11:02:55 -0700361 Port* destroyed_src = port_.release();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000362 ASSERT_EQ(destroyed_src, port);
363 }
364
Guo-wei Shieh1eb87c72015-08-25 11:02:55 -0700365 Port* port() { return port_.get(); }
Guo-wei Shiehbe508a12015-04-06 12:48:47 -0700366
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000367 bool nominated() const { return nominated_; }
368
Guo-wei Shiehb5940412015-08-24 11:58:03 -0700369 void set_connection_ready_to_send(bool ready) {
370 connection_ready_to_send_ = ready;
371 }
Yves Gerey665174f2018-06-19 15:03:05 +0200372 bool connection_ready_to_send() const { return connection_ready_to_send_; }
Guo-wei Shiehb5940412015-08-24 11:58:03 -0700373
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000374 private:
skvladc309e0e2016-07-28 17:15:20 -0700375 // ReadyToSend will only issue after a Connection recovers from ENOTCONN
Guo-wei Shiehb5940412015-08-24 11:58:03 -0700376 void OnConnectionReadyToSend(Connection* conn) {
377 ASSERT_EQ(conn, conn_);
378 connection_ready_to_send_ = true;
379 }
380
Steve Anton11358fe2018-10-09 15:39:19 -0700381 IceMode ice_mode_ = ICEMODE_FULL;
kwiberg3ec46792016-04-27 07:22:53 -0700382 std::unique_ptr<Port> port_;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000383
Steve Anton11358fe2018-10-09 15:39:19 -0700384 int complete_count_ = 0;
385 Connection* conn_ = nullptr;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000386 SocketAddress remote_address_;
kwiberg3ec46792016-04-27 07:22:53 -0700387 std::unique_ptr<StunMessage> remote_request_;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000388 std::string remote_frag_;
Steve Anton11358fe2018-10-09 15:39:19 -0700389 bool nominated_ = false;
Guo-wei Shiehb5940412015-08-24 11:58:03 -0700390 bool connection_ready_to_send_ = false;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000391};
392
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200393class PortTest : public ::testing::Test, public sigslot::has_slots<> {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000394 public:
395 PortTest()
deadbeef98e186c2017-05-16 18:00:06 -0700396 : ss_(new rtc::VirtualSocketServer()),
nisse7eaa4ea2017-05-08 05:25:41 -0700397 main_(ss_.get()),
Niels Möller9def9942021-09-07 09:16:49 +0200398 socket_factory_(ss_.get()),
deadbeefc5d0d952015-07-16 10:22:21 -0700399 nat_factory1_(ss_.get(), kNatAddr1, SocketAddress()),
400 nat_factory2_(ss_.get(), kNatAddr2, SocketAddress()),
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000401 nat_socket_factory1_(&nat_factory1_),
402 nat_socket_factory2_(&nat_factory2_),
Niels Möller091617d2020-12-02 15:32:08 +0100403 stun_server_(TestStunServer::Create(ss_.get(), kStunAddr)),
Niels Möller6dd49972021-11-24 14:05:55 +0100404 turn_server_(&main_, ss_.get(), kTurnUdpIntAddr, kTurnUdpExtAddr),
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000405 username_(rtc::CreateRandomString(ICE_UFRAG_LENGTH)),
406 password_(rtc::CreateRandomString(ICE_PWD_LENGTH)),
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000407 role_conflict_(false),
Yves Gerey665174f2018-06-19 15:03:05 +0200408 ports_destroyed_(0) {}
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000409
410 protected:
Jonas Oreland9a52bd72019-12-11 11:35:48 +0100411 std::string password() { return password_; }
412
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000413 void TestLocalToLocal() {
Steve Anton11358fe2018-10-09 15:39:19 -0700414 auto port1 = CreateUdpPort(kLocalAddr1);
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700415 port1->SetIceRole(cricket::ICEROLE_CONTROLLING);
Steve Anton11358fe2018-10-09 15:39:19 -0700416 auto port2 = CreateUdpPort(kLocalAddr2);
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700417 port2->SetIceRole(cricket::ICEROLE_CONTROLLED);
Steve Anton11358fe2018-10-09 15:39:19 -0700418 TestConnectivity("udp", std::move(port1), "udp", std::move(port2), true,
419 true, true, true);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000420 }
421 void TestLocalToStun(NATType ntype) {
Steve Anton11358fe2018-10-09 15:39:19 -0700422 auto port1 = CreateUdpPort(kLocalAddr1);
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700423 port1->SetIceRole(cricket::ICEROLE_CONTROLLING);
Steve Anton11358fe2018-10-09 15:39:19 -0700424 nat_server2_ = CreateNatServer(kNatAddr2, ntype);
425 auto port2 = CreateStunPort(kLocalAddr2, &nat_socket_factory2_);
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700426 port2->SetIceRole(cricket::ICEROLE_CONTROLLED);
Steve Anton11358fe2018-10-09 15:39:19 -0700427 TestConnectivity("udp", std::move(port1), StunName(ntype), std::move(port2),
Yves Gerey665174f2018-06-19 15:03:05 +0200428 ntype == NAT_OPEN_CONE, true, ntype != NAT_SYMMETRIC,
429 true);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000430 }
Niels Möller191e38f2019-11-04 08:49:12 +0100431 void TestLocalToRelay(ProtocolType proto) {
Steve Anton11358fe2018-10-09 15:39:19 -0700432 auto port1 = CreateUdpPort(kLocalAddr1);
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700433 port1->SetIceRole(cricket::ICEROLE_CONTROLLING);
Niels Möller191e38f2019-11-04 08:49:12 +0100434 auto port2 = CreateRelayPort(kLocalAddr2, proto, PROTO_UDP);
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700435 port2->SetIceRole(cricket::ICEROLE_CONTROLLED);
Niels Möller191e38f2019-11-04 08:49:12 +0100436 TestConnectivity("udp", std::move(port1), RelayName(proto),
437 std::move(port2), false, true, true, true);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000438 }
439 void TestStunToLocal(NATType ntype) {
Steve Anton11358fe2018-10-09 15:39:19 -0700440 nat_server1_ = CreateNatServer(kNatAddr1, ntype);
441 auto port1 = CreateStunPort(kLocalAddr1, &nat_socket_factory1_);
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700442 port1->SetIceRole(cricket::ICEROLE_CONTROLLING);
Steve Anton11358fe2018-10-09 15:39:19 -0700443 auto port2 = CreateUdpPort(kLocalAddr2);
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700444 port2->SetIceRole(cricket::ICEROLE_CONTROLLED);
Steve Anton11358fe2018-10-09 15:39:19 -0700445 TestConnectivity(StunName(ntype), std::move(port1), "udp", std::move(port2),
446 true, ntype != NAT_SYMMETRIC, true, true);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000447 }
448 void TestStunToStun(NATType ntype1, NATType ntype2) {
Steve Anton11358fe2018-10-09 15:39:19 -0700449 nat_server1_ = CreateNatServer(kNatAddr1, ntype1);
450 auto port1 = CreateStunPort(kLocalAddr1, &nat_socket_factory1_);
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700451 port1->SetIceRole(cricket::ICEROLE_CONTROLLING);
Steve Anton11358fe2018-10-09 15:39:19 -0700452 nat_server2_ = CreateNatServer(kNatAddr2, ntype2);
453 auto port2 = CreateStunPort(kLocalAddr2, &nat_socket_factory2_);
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700454 port2->SetIceRole(cricket::ICEROLE_CONTROLLED);
Steve Anton11358fe2018-10-09 15:39:19 -0700455 TestConnectivity(StunName(ntype1), std::move(port1), StunName(ntype2),
456 std::move(port2), ntype2 == NAT_OPEN_CONE,
457 ntype1 != NAT_SYMMETRIC, ntype2 != NAT_SYMMETRIC,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000458 ntype1 + ntype2 < (NAT_PORT_RESTRICTED + NAT_SYMMETRIC));
459 }
Niels Möller191e38f2019-11-04 08:49:12 +0100460 void TestStunToRelay(NATType ntype, ProtocolType proto) {
Steve Anton11358fe2018-10-09 15:39:19 -0700461 nat_server1_ = CreateNatServer(kNatAddr1, ntype);
462 auto port1 = CreateStunPort(kLocalAddr1, &nat_socket_factory1_);
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700463 port1->SetIceRole(cricket::ICEROLE_CONTROLLING);
Niels Möller191e38f2019-11-04 08:49:12 +0100464 auto port2 = CreateRelayPort(kLocalAddr2, proto, PROTO_UDP);
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700465 port2->SetIceRole(cricket::ICEROLE_CONTROLLED);
Niels Möller191e38f2019-11-04 08:49:12 +0100466 TestConnectivity(StunName(ntype), std::move(port1), RelayName(proto),
467 std::move(port2), false, ntype != NAT_SYMMETRIC, true,
468 true);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000469 }
470 void TestTcpToTcp() {
Steve Anton11358fe2018-10-09 15:39:19 -0700471 auto port1 = CreateTcpPort(kLocalAddr1);
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700472 port1->SetIceRole(cricket::ICEROLE_CONTROLLING);
Steve Anton11358fe2018-10-09 15:39:19 -0700473 auto port2 = CreateTcpPort(kLocalAddr2);
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700474 port2->SetIceRole(cricket::ICEROLE_CONTROLLED);
Steve Anton11358fe2018-10-09 15:39:19 -0700475 TestConnectivity("tcp", std::move(port1), "tcp", std::move(port2), true,
476 false, true, true);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000477 }
Niels Möller191e38f2019-11-04 08:49:12 +0100478 void TestTcpToRelay(ProtocolType proto) {
Steve Anton11358fe2018-10-09 15:39:19 -0700479 auto port1 = CreateTcpPort(kLocalAddr1);
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700480 port1->SetIceRole(cricket::ICEROLE_CONTROLLING);
Niels Möller191e38f2019-11-04 08:49:12 +0100481 auto port2 = CreateRelayPort(kLocalAddr2, proto, PROTO_TCP);
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700482 port2->SetIceRole(cricket::ICEROLE_CONTROLLED);
Niels Möller191e38f2019-11-04 08:49:12 +0100483 TestConnectivity("tcp", std::move(port1), RelayName(proto),
484 std::move(port2), false, false, true, true);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000485 }
Niels Möller191e38f2019-11-04 08:49:12 +0100486 void TestSslTcpToRelay(ProtocolType proto) {
Steve Anton11358fe2018-10-09 15:39:19 -0700487 auto port1 = CreateTcpPort(kLocalAddr1);
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700488 port1->SetIceRole(cricket::ICEROLE_CONTROLLING);
Niels Möller191e38f2019-11-04 08:49:12 +0100489 auto port2 = CreateRelayPort(kLocalAddr2, proto, PROTO_SSLTCP);
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700490 port2->SetIceRole(cricket::ICEROLE_CONTROLLED);
Niels Möller191e38f2019-11-04 08:49:12 +0100491 TestConnectivity("ssltcp", std::move(port1), RelayName(proto),
492 std::move(port2), false, false, true, true);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000493 }
deadbeef5c3c1042017-08-04 15:01:57 -0700494
495 rtc::Network* MakeNetwork(const SocketAddress& addr) {
496 networks_.emplace_back("unittest", "unittest", addr.ipaddr(), 32);
497 networks_.back().AddIP(addr.ipaddr());
498 return &networks_.back();
499 }
500
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000501 // helpers for above functions
Steve Anton11358fe2018-10-09 15:39:19 -0700502 std::unique_ptr<UDPPort> CreateUdpPort(const SocketAddress& addr) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000503 return CreateUdpPort(addr, &socket_factory_);
504 }
Steve Anton11358fe2018-10-09 15:39:19 -0700505 std::unique_ptr<UDPPort> CreateUdpPort(const SocketAddress& addr,
506 PacketSocketFactory* socket_factory) {
Steve Antona8f1e562018-10-10 11:29:44 -0700507 return UDPPort::Create(&main_, socket_factory, MakeNetwork(addr), 0, 0,
Philipp Hancke08a6e352021-10-26 20:39:47 +0200508 username_, password_, true, absl::nullopt);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000509 }
Steve Anton11358fe2018-10-09 15:39:19 -0700510 std::unique_ptr<TCPPort> CreateTcpPort(const SocketAddress& addr) {
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700511 return CreateTcpPort(addr, &socket_factory_);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000512 }
Steve Anton11358fe2018-10-09 15:39:19 -0700513 std::unique_ptr<TCPPort> CreateTcpPort(const SocketAddress& addr,
514 PacketSocketFactory* socket_factory) {
Steve Antona8f1e562018-10-10 11:29:44 -0700515 return TCPPort::Create(&main_, socket_factory, MakeNetwork(addr), 0, 0,
516 username_, password_, true);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000517 }
Steve Anton11358fe2018-10-09 15:39:19 -0700518 std::unique_ptr<StunPort> CreateStunPort(const SocketAddress& addr,
519 rtc::PacketSocketFactory* factory) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000520 ServerAddresses stun_servers;
521 stun_servers.insert(kStunAddr);
Steve Antona8f1e562018-10-10 11:29:44 -0700522 return StunPort::Create(&main_, factory, MakeNetwork(addr), 0, 0, username_,
Philipp Hancke08a6e352021-10-26 20:39:47 +0200523 password_, stun_servers, absl::nullopt);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000524 }
Steve Anton11358fe2018-10-09 15:39:19 -0700525 std::unique_ptr<Port> CreateRelayPort(const SocketAddress& addr,
Steve Anton11358fe2018-10-09 15:39:19 -0700526 ProtocolType int_proto,
527 ProtocolType ext_proto) {
Niels Möller191e38f2019-11-04 08:49:12 +0100528 return CreateTurnPort(addr, &socket_factory_, int_proto, ext_proto);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000529 }
Steve Anton11358fe2018-10-09 15:39:19 -0700530 std::unique_ptr<TurnPort> CreateTurnPort(const SocketAddress& addr,
531 PacketSocketFactory* socket_factory,
532 ProtocolType int_proto,
533 ProtocolType ext_proto) {
Honghai Zhang80f1db92016-01-27 11:54:45 -0800534 SocketAddress server_addr =
535 int_proto == PROTO_TCP ? kTurnTcpIntAddr : kTurnUdpIntAddr;
536 return CreateTurnPort(addr, socket_factory, int_proto, ext_proto,
537 server_addr);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000538 }
Steve Anton11358fe2018-10-09 15:39:19 -0700539 std::unique_ptr<TurnPort> CreateTurnPort(
540 const SocketAddress& addr,
541 PacketSocketFactory* socket_factory,
542 ProtocolType int_proto,
543 ProtocolType ext_proto,
544 const rtc::SocketAddress& server_addr) {
Steve Antonf7dd9df2018-10-10 15:06:28 -0700545 return TurnPort::Create(&main_, socket_factory, MakeNetwork(addr), 0, 0,
546 username_, password_,
547 ProtocolAddress(server_addr, int_proto),
Philipp Hancke08a6e352021-10-26 20:39:47 +0200548 kRelayCredentials, 0, {}, {}, nullptr, nullptr);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000549 }
Steve Anton11358fe2018-10-09 15:39:19 -0700550 std::unique_ptr<rtc::NATServer> CreateNatServer(const SocketAddress& addr,
551 rtc::NATType type) {
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200552 return std::make_unique<rtc::NATServer>(type, ss_.get(), addr, addr,
553 ss_.get(), addr);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000554 }
555 static const char* StunName(NATType type) {
556 switch (type) {
hnsl277b2502016-12-13 05:17:23 -0800557 case NAT_OPEN_CONE:
558 return "stun(open cone)";
559 case NAT_ADDR_RESTRICTED:
560 return "stun(addr restricted)";
561 case NAT_PORT_RESTRICTED:
562 return "stun(port restricted)";
563 case NAT_SYMMETRIC:
564 return "stun(symmetric)";
565 default:
566 return "stun(?)";
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000567 }
568 }
Niels Möller191e38f2019-11-04 08:49:12 +0100569 static const char* RelayName(ProtocolType proto) {
570 switch (proto) {
571 case PROTO_UDP:
572 return "turn(udp)";
573 case PROTO_TCP:
574 return "turn(tcp)";
575 case PROTO_SSLTCP:
576 return "turn(ssltcp)";
577 case PROTO_TLS:
578 return "turn(tls)";
579 default:
580 return "turn(?)";
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000581 }
582 }
583
584 void TestCrossFamilyPorts(int type);
585
Peter Thatcherb8b01432015-07-07 16:45:53 -0700586 void ExpectPortsCanConnect(bool can_connect, Port* p1, Port* p2);
587
Artem Titov2dbb4c92021-07-26 15:12:41 +0200588 // This does all the work and then deletes `port1` and `port2`.
Yves Gerey665174f2018-06-19 15:03:05 +0200589 void TestConnectivity(const char* name1,
Steve Anton11358fe2018-10-09 15:39:19 -0700590 std::unique_ptr<Port> port1,
Yves Gerey665174f2018-06-19 15:03:05 +0200591 const char* name2,
Steve Anton11358fe2018-10-09 15:39:19 -0700592 std::unique_ptr<Port> port2,
Yves Gerey665174f2018-06-19 15:03:05 +0200593 bool accept,
594 bool same_addr1,
595 bool same_addr2,
596 bool possible);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000597
Artem Titov2dbb4c92021-07-26 15:12:41 +0200598 // This connects the provided channels which have already started. `ch1`
Guo-wei Shiehbe508a12015-04-06 12:48:47 -0700599 // should have its Connection created (either through CreateConnection() or
600 // TCP reconnecting mechanism before entering this function.
601 void ConnectStartedChannels(TestChannel* ch1, TestChannel* ch2) {
602 ASSERT_TRUE(ch1->conn());
Honghai Zhang161a5862016-10-20 11:47:02 -0700603 EXPECT_TRUE_WAIT(ch1->conn()->connected(),
604 kDefaultTimeout); // for TCP connect
Guo-wei Shiehbe508a12015-04-06 12:48:47 -0700605 ch1->Ping();
Honghai Zhang161a5862016-10-20 11:47:02 -0700606 WAIT(!ch2->remote_address().IsNil(), kShortTimeout);
Guo-wei Shiehbe508a12015-04-06 12:48:47 -0700607
608 // Send a ping from dst to src.
Guo-wei Shieh1eb87c72015-08-25 11:02:55 -0700609 ch2->AcceptConnection(GetCandidate(ch1->port()));
Guo-wei Shiehbe508a12015-04-06 12:48:47 -0700610 ch2->Ping();
611 EXPECT_EQ_WAIT(Connection::STATE_WRITABLE, ch2->conn()->write_state(),
Honghai Zhang161a5862016-10-20 11:47:02 -0700612 kDefaultTimeout);
Guo-wei Shiehbe508a12015-04-06 12:48:47 -0700613 }
614
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000615 // This connects and disconnects the provided channels in the same sequence as
Artem Titov2dbb4c92021-07-26 15:12:41 +0200616 // TestConnectivity with all options set to `true`. It does not delete either
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000617 // channel.
Guo-wei Shiehbe508a12015-04-06 12:48:47 -0700618 void StartConnectAndStopChannels(TestChannel* ch1, TestChannel* ch2) {
619 // Acquire addresses.
620 ch1->Start();
621 ch2->Start();
622
Guo-wei Shieh1eb87c72015-08-25 11:02:55 -0700623 ch1->CreateConnection(GetCandidate(ch2->port()));
Guo-wei Shiehbe508a12015-04-06 12:48:47 -0700624 ConnectStartedChannels(ch1, ch2);
625
626 // Destroy the connections.
627 ch1->Stop();
628 ch2->Stop();
629 }
630
631 // This disconnects both end's Connection and make sure ch2 ready for new
632 // connection.
633 void DisconnectTcpTestChannels(TestChannel* ch1, TestChannel* ch2) {
Guo-wei Shieh1eb87c72015-08-25 11:02:55 -0700634 TCPConnection* tcp_conn1 = static_cast<TCPConnection*>(ch1->conn());
635 TCPConnection* tcp_conn2 = static_cast<TCPConnection*>(ch2->conn());
636 ASSERT_TRUE(
637 ss_->CloseTcpConnections(tcp_conn1->socket()->GetLocalAddress(),
638 tcp_conn2->socket()->GetLocalAddress()));
Guo-wei Shiehbe508a12015-04-06 12:48:47 -0700639
640 // Wait for both OnClose are delivered.
Honghai Zhang161a5862016-10-20 11:47:02 -0700641 EXPECT_TRUE_WAIT(!ch1->conn()->connected(), kDefaultTimeout);
642 EXPECT_TRUE_WAIT(!ch2->conn()->connected(), kDefaultTimeout);
Guo-wei Shiehbe508a12015-04-06 12:48:47 -0700643
Guo-wei Shieh1eb87c72015-08-25 11:02:55 -0700644 // Ensure redundant SignalClose events on TcpConnection won't break tcp
645 // reconnection. Chromium will fire SignalClose for all outstanding IPC
646 // packets during reconnection.
647 tcp_conn1->socket()->SignalClose(tcp_conn1->socket(), 0);
648 tcp_conn2->socket()->SignalClose(tcp_conn2->socket(), 0);
649
650 // Speed up destroying ch2's connection such that the test is ready to
651 // accept a new connection from ch1 before ch1's connection destroys itself.
Guo-wei Shiehbe508a12015-04-06 12:48:47 -0700652 ch2->conn()->Destroy();
Honghai Zhang161a5862016-10-20 11:47:02 -0700653 EXPECT_TRUE_WAIT(ch2->conn() == NULL, kDefaultTimeout);
Guo-wei Shiehbe508a12015-04-06 12:48:47 -0700654 }
655
656 void TestTcpReconnect(bool ping_after_disconnected,
657 bool send_after_disconnected) {
Steve Anton11358fe2018-10-09 15:39:19 -0700658 auto port1 = CreateTcpPort(kLocalAddr1);
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700659 port1->SetIceRole(cricket::ICEROLE_CONTROLLING);
Steve Anton11358fe2018-10-09 15:39:19 -0700660 auto port2 = CreateTcpPort(kLocalAddr2);
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700661 port2->SetIceRole(cricket::ICEROLE_CONTROLLED);
Guo-wei Shiehbe508a12015-04-06 12:48:47 -0700662
663 port1->set_component(cricket::ICE_CANDIDATE_COMPONENT_DEFAULT);
664 port2->set_component(cricket::ICE_CANDIDATE_COMPONENT_DEFAULT);
665
666 // Set up channels and ensure both ports will be deleted.
Steve Anton11358fe2018-10-09 15:39:19 -0700667 TestChannel ch1(std::move(port1));
668 TestChannel ch2(std::move(port2));
Guo-wei Shiehbe508a12015-04-06 12:48:47 -0700669 EXPECT_EQ(0, ch1.complete_count());
670 EXPECT_EQ(0, ch2.complete_count());
671
672 ch1.Start();
673 ch2.Start();
Honghai Zhang161a5862016-10-20 11:47:02 -0700674 ASSERT_EQ_WAIT(1, ch1.complete_count(), kDefaultTimeout);
675 ASSERT_EQ_WAIT(1, ch2.complete_count(), kDefaultTimeout);
Guo-wei Shiehbe508a12015-04-06 12:48:47 -0700676
677 // Initial connecting the channel, create connection on channel1.
Steve Anton11358fe2018-10-09 15:39:19 -0700678 ch1.CreateConnection(GetCandidate(ch2.port()));
Guo-wei Shiehbe508a12015-04-06 12:48:47 -0700679 ConnectStartedChannels(&ch1, &ch2);
680
681 // Shorten the timeout period.
Honghai Zhang161a5862016-10-20 11:47:02 -0700682 const int kTcpReconnectTimeout = kDefaultTimeout;
Guo-wei Shiehbe508a12015-04-06 12:48:47 -0700683 static_cast<TCPConnection*>(ch1.conn())
684 ->set_reconnection_timeout(kTcpReconnectTimeout);
685 static_cast<TCPConnection*>(ch2.conn())
686 ->set_reconnection_timeout(kTcpReconnectTimeout);
687
Guo-wei Shiehb5940412015-08-24 11:58:03 -0700688 EXPECT_FALSE(ch1.connection_ready_to_send());
689 EXPECT_FALSE(ch2.connection_ready_to_send());
690
Guo-wei Shiehbe508a12015-04-06 12:48:47 -0700691 // Once connected, disconnect them.
692 DisconnectTcpTestChannels(&ch1, &ch2);
693
694 if (send_after_disconnected || ping_after_disconnected) {
695 if (send_after_disconnected) {
696 // First SendData after disconnect should fail but will trigger
697 // reconnect.
698 EXPECT_EQ(-1, ch1.SendData(data, static_cast<int>(strlen(data))));
699 }
700
701 if (ping_after_disconnected) {
702 // Ping should trigger reconnect.
703 ch1.Ping();
704 }
705
706 // Wait for channel's outgoing TCPConnection connected.
Honghai Zhang161a5862016-10-20 11:47:02 -0700707 EXPECT_TRUE_WAIT(ch1.conn()->connected(), kDefaultTimeout);
Guo-wei Shiehbe508a12015-04-06 12:48:47 -0700708
709 // Verify that we could still connect channels.
710 ConnectStartedChannels(&ch1, &ch2);
Yves Gerey665174f2018-06-19 15:03:05 +0200711 EXPECT_TRUE_WAIT(ch1.connection_ready_to_send(), kTcpReconnectTimeout);
Guo-wei Shiehb5940412015-08-24 11:58:03 -0700712 // Channel2 is the passive one so a new connection is created during
skvladc309e0e2016-07-28 17:15:20 -0700713 // reconnect. This new connection should never have issued ENOTCONN
Guo-wei Shiehb5940412015-08-24 11:58:03 -0700714 // hence the connection_ready_to_send() should be false.
715 EXPECT_FALSE(ch2.connection_ready_to_send());
Guo-wei Shiehbe508a12015-04-06 12:48:47 -0700716 } else {
717 EXPECT_EQ(ch1.conn()->write_state(), Connection::STATE_WRITABLE);
Guo-wei Shieh1eb87c72015-08-25 11:02:55 -0700718 // Since the reconnection never happens, the connections should have been
719 // destroyed after the timeout.
Honghai Zhang161a5862016-10-20 11:47:02 -0700720 EXPECT_TRUE_WAIT(!ch1.conn(), kTcpReconnectTimeout + kDefaultTimeout);
Guo-wei Shieh1eb87c72015-08-25 11:02:55 -0700721 EXPECT_TRUE(!ch2.conn());
Guo-wei Shiehbe508a12015-04-06 12:48:47 -0700722 }
723
724 // Tear down and ensure that goes smoothly.
725 ch1.Stop();
726 ch2.Stop();
Honghai Zhang161a5862016-10-20 11:47:02 -0700727 EXPECT_TRUE_WAIT(ch1.conn() == NULL, kDefaultTimeout);
728 EXPECT_TRUE_WAIT(ch2.conn() == NULL, kDefaultTimeout);
Guo-wei Shiehbe508a12015-04-06 12:48:47 -0700729 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000730
Steve Anton11358fe2018-10-09 15:39:19 -0700731 std::unique_ptr<IceMessage> CreateStunMessage(int type) {
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200732 auto msg = std::make_unique<IceMessage>();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000733 msg->SetType(type);
734 msg->SetTransactionID("TESTTESTTEST");
735 return msg;
736 }
Steve Anton11358fe2018-10-09 15:39:19 -0700737 std::unique_ptr<IceMessage> CreateStunMessageWithUsername(
738 int type,
739 const std::string& username) {
740 std::unique_ptr<IceMessage> msg = CreateStunMessage(type);
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200741 msg->AddAttribute(std::make_unique<StunByteStringAttribute>(
Karl Wiberg918f50c2018-07-05 11:40:33 +0200742 STUN_ATTR_USERNAME, username));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000743 return msg;
744 }
Steve Anton11358fe2018-10-09 15:39:19 -0700745 std::unique_ptr<TestPort> CreateTestPort(const rtc::SocketAddress& addr,
746 const std::string& username,
747 const std::string& password) {
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200748 auto port =
749 std::make_unique<TestPort>(&main_, "test", &socket_factory_,
750 MakeNetwork(addr), 0, 0, username, password);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000751 port->SignalRoleConflict.connect(this, &PortTest::OnRoleConflict);
752 return port;
753 }
Steve Anton11358fe2018-10-09 15:39:19 -0700754 std::unique_ptr<TestPort> CreateTestPort(const rtc::SocketAddress& addr,
755 const std::string& username,
756 const std::string& password,
757 cricket::IceRole role,
758 int tiebreaker) {
759 auto port = CreateTestPort(addr, username, password);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000760 port->SetIceRole(role);
761 port->SetIceTiebreaker(tiebreaker);
762 return port;
763 }
deadbeef5c3c1042017-08-04 15:01:57 -0700764 // Overload to create a test port given an rtc::Network directly.
Steve Anton11358fe2018-10-09 15:39:19 -0700765 std::unique_ptr<TestPort> CreateTestPort(rtc::Network* network,
766 const std::string& username,
767 const std::string& password) {
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200768 auto port = std::make_unique<TestPort>(&main_, "test", &socket_factory_,
769 network, 0, 0, username, password);
deadbeef5c3c1042017-08-04 15:01:57 -0700770 port->SignalRoleConflict.connect(this, &PortTest::OnRoleConflict);
771 return port;
772 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000773
Yves Gerey665174f2018-06-19 15:03:05 +0200774 void OnRoleConflict(PortInterface* port) { role_conflict_ = true; }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000775 bool role_conflict() const { return role_conflict_; }
776
777 void ConnectToSignalDestroyed(PortInterface* port) {
Lahiru Ginnaliya Gamathigec3a486c2021-02-09 00:31:39 -0800778 port->SubscribePortDestroyed(
779 [this](PortInterface* port) { OnDestroyed(port); });
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000780 }
781
Honghai Zhanga74363c2016-07-28 18:06:15 -0700782 void OnDestroyed(PortInterface* port) { ++ports_destroyed_; }
783 int ports_destroyed() const { return ports_destroyed_; }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000784
785 rtc::BasicPacketSocketFactory* nat_socket_factory1() {
786 return &nat_socket_factory1_;
787 }
788
Guo-wei Shieh1eb87c72015-08-25 11:02:55 -0700789 rtc::VirtualSocketServer* vss() { return ss_.get(); }
790
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000791 private:
deadbeef5c3c1042017-08-04 15:01:57 -0700792 // When a "create port" helper method is called with an IP, we create a
793 // Network with that IP and add it to this list. Using a list instead of a
794 // vector so that when it grows, pointers aren't invalidated.
795 std::list<rtc::Network> networks_;
kwiberg3ec46792016-04-27 07:22:53 -0700796 std::unique_ptr<rtc::VirtualSocketServer> ss_;
nisse7eaa4ea2017-05-08 05:25:41 -0700797 rtc::AutoSocketServerThread main_;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000798 rtc::BasicPacketSocketFactory socket_factory_;
kwiberg3ec46792016-04-27 07:22:53 -0700799 std::unique_ptr<rtc::NATServer> nat_server1_;
800 std::unique_ptr<rtc::NATServer> nat_server2_;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000801 rtc::NATSocketFactory nat_factory1_;
802 rtc::NATSocketFactory nat_factory2_;
803 rtc::BasicPacketSocketFactory nat_socket_factory1_;
804 rtc::BasicPacketSocketFactory nat_socket_factory2_;
kwiberg3ec46792016-04-27 07:22:53 -0700805 std::unique_ptr<TestStunServer> stun_server_;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000806 TestTurnServer turn_server_;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000807 std::string username_;
808 std::string password_;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000809 bool role_conflict_;
Honghai Zhanga74363c2016-07-28 18:06:15 -0700810 int ports_destroyed_;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000811};
812
Yves Gerey665174f2018-06-19 15:03:05 +0200813void PortTest::TestConnectivity(const char* name1,
Steve Anton11358fe2018-10-09 15:39:19 -0700814 std::unique_ptr<Port> port1,
Yves Gerey665174f2018-06-19 15:03:05 +0200815 const char* name2,
Steve Anton11358fe2018-10-09 15:39:19 -0700816 std::unique_ptr<Port> port2,
Yves Gerey665174f2018-06-19 15:03:05 +0200817 bool accept,
818 bool same_addr1,
819 bool same_addr2,
820 bool possible) {
Honghai Zhang161a5862016-10-20 11:47:02 -0700821 rtc::ScopedFakeClock clock;
Mirko Bonadei675513b2017-11-09 11:09:25 +0100822 RTC_LOG(LS_INFO) << "Test: " << name1 << " to " << name2 << ": ";
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000823 port1->set_component(cricket::ICE_CANDIDATE_COMPONENT_DEFAULT);
824 port2->set_component(cricket::ICE_CANDIDATE_COMPONENT_DEFAULT);
825
826 // Set up channels and ensure both ports will be deleted.
Steve Anton11358fe2018-10-09 15:39:19 -0700827 TestChannel ch1(std::move(port1));
828 TestChannel ch2(std::move(port2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000829 EXPECT_EQ(0, ch1.complete_count());
830 EXPECT_EQ(0, ch2.complete_count());
831
832 // Acquire addresses.
833 ch1.Start();
834 ch2.Start();
Honghai Zhang161a5862016-10-20 11:47:02 -0700835 ASSERT_EQ_SIMULATED_WAIT(1, ch1.complete_count(), kDefaultTimeout, clock);
836 ASSERT_EQ_SIMULATED_WAIT(1, ch2.complete_count(), kDefaultTimeout, clock);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000837
838 // Send a ping from src to dst. This may or may not make it.
Steve Anton11358fe2018-10-09 15:39:19 -0700839 ch1.CreateConnection(GetCandidate(ch2.port()));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000840 ASSERT_TRUE(ch1.conn() != NULL);
Honghai Zhang161a5862016-10-20 11:47:02 -0700841 EXPECT_TRUE_SIMULATED_WAIT(ch1.conn()->connected(), kDefaultTimeout,
842 clock); // for TCP connect
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000843 ch1.Ping();
Honghai Zhang161a5862016-10-20 11:47:02 -0700844 SIMULATED_WAIT(!ch2.remote_address().IsNil(), kShortTimeout, clock);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000845
846 if (accept) {
847 // We are able to send a ping from src to dst. This is the case when
848 // sending to UDP ports and cone NATs.
849 EXPECT_TRUE(ch1.remote_address().IsNil());
Steve Anton11358fe2018-10-09 15:39:19 -0700850 EXPECT_EQ(ch2.remote_fragment(), ch1.port()->username_fragment());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000851
852 // Ensure the ping came from the same address used for src.
853 // This is the case unless the source NAT was symmetric.
Yves Gerey665174f2018-06-19 15:03:05 +0200854 if (same_addr1)
Steve Anton11358fe2018-10-09 15:39:19 -0700855 EXPECT_EQ(ch2.remote_address(), GetAddress(ch1.port()));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000856 EXPECT_TRUE(same_addr2);
857
858 // Send a ping from dst to src.
Steve Anton11358fe2018-10-09 15:39:19 -0700859 ch2.AcceptConnection(GetCandidate(ch1.port()));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000860 ASSERT_TRUE(ch2.conn() != NULL);
861 ch2.Ping();
Honghai Zhang161a5862016-10-20 11:47:02 -0700862 EXPECT_EQ_SIMULATED_WAIT(Connection::STATE_WRITABLE,
863 ch2.conn()->write_state(), kDefaultTimeout, clock);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000864 } else {
865 // We can't send a ping from src to dst, so flip it around. This will happen
866 // when the destination NAT is addr/port restricted or symmetric.
867 EXPECT_TRUE(ch1.remote_address().IsNil());
868 EXPECT_TRUE(ch2.remote_address().IsNil());
869
870 // Send a ping from dst to src. Again, this may or may not make it.
Steve Anton11358fe2018-10-09 15:39:19 -0700871 ch2.CreateConnection(GetCandidate(ch1.port()));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000872 ASSERT_TRUE(ch2.conn() != NULL);
873 ch2.Ping();
Honghai Zhang161a5862016-10-20 11:47:02 -0700874 SIMULATED_WAIT(ch2.conn()->write_state() == Connection::STATE_WRITABLE,
875 kShortTimeout, clock);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000876
877 if (same_addr1 && same_addr2) {
878 // The new ping got back to the source.
Peter Thatcher04ac81f2015-09-21 11:48:28 -0700879 EXPECT_TRUE(ch1.conn()->receiving());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000880 EXPECT_EQ(Connection::STATE_WRITABLE, ch2.conn()->write_state());
881
882 // First connection may not be writable if the first ping did not get
883 // through. So we will have to do another.
884 if (ch1.conn()->write_state() == Connection::STATE_WRITE_INIT) {
885 ch1.Ping();
Honghai Zhang161a5862016-10-20 11:47:02 -0700886 EXPECT_EQ_SIMULATED_WAIT(Connection::STATE_WRITABLE,
887 ch1.conn()->write_state(), kDefaultTimeout,
888 clock);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000889 }
890 } else if (!same_addr1 && possible) {
891 // The new ping went to the candidate address, but that address was bad.
892 // This will happen when the source NAT is symmetric.
893 EXPECT_TRUE(ch1.remote_address().IsNil());
894 EXPECT_TRUE(ch2.remote_address().IsNil());
895
896 // However, since we have now sent a ping to the source IP, we should be
897 // able to get a ping from it. This gives us the real source address.
898 ch1.Ping();
Honghai Zhang161a5862016-10-20 11:47:02 -0700899 EXPECT_TRUE_SIMULATED_WAIT(!ch2.remote_address().IsNil(), kDefaultTimeout,
900 clock);
Peter Thatcher04ac81f2015-09-21 11:48:28 -0700901 EXPECT_FALSE(ch2.conn()->receiving());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000902 EXPECT_TRUE(ch1.remote_address().IsNil());
903
904 // Pick up the actual address and establish the connection.
Steve Anton11358fe2018-10-09 15:39:19 -0700905 ch2.AcceptConnection(GetCandidate(ch1.port()));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000906 ASSERT_TRUE(ch2.conn() != NULL);
907 ch2.Ping();
Honghai Zhang161a5862016-10-20 11:47:02 -0700908 EXPECT_EQ_SIMULATED_WAIT(Connection::STATE_WRITABLE,
909 ch2.conn()->write_state(), kDefaultTimeout,
910 clock);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000911 } else if (!same_addr2 && possible) {
912 // The new ping came in, but from an unexpected address. This will happen
913 // when the destination NAT is symmetric.
914 EXPECT_FALSE(ch1.remote_address().IsNil());
Peter Thatcher04ac81f2015-09-21 11:48:28 -0700915 EXPECT_FALSE(ch1.conn()->receiving());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000916
917 // Update our address and complete the connection.
Steve Anton11358fe2018-10-09 15:39:19 -0700918 ch1.AcceptConnection(GetCandidate(ch2.port()));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000919 ch1.Ping();
Honghai Zhang161a5862016-10-20 11:47:02 -0700920 EXPECT_EQ_SIMULATED_WAIT(Connection::STATE_WRITABLE,
921 ch1.conn()->write_state(), kDefaultTimeout,
922 clock);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000923 } else { // (!possible)
924 // There should be s no way for the pings to reach each other. Check it.
925 EXPECT_TRUE(ch1.remote_address().IsNil());
926 EXPECT_TRUE(ch2.remote_address().IsNil());
927 ch1.Ping();
Honghai Zhang161a5862016-10-20 11:47:02 -0700928 SIMULATED_WAIT(!ch2.remote_address().IsNil(), kShortTimeout, clock);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000929 EXPECT_TRUE(ch1.remote_address().IsNil());
930 EXPECT_TRUE(ch2.remote_address().IsNil());
931 }
932 }
933
934 // Everything should be good, unless we know the situation is impossible.
935 ASSERT_TRUE(ch1.conn() != NULL);
936 ASSERT_TRUE(ch2.conn() != NULL);
937 if (possible) {
Peter Thatcher04ac81f2015-09-21 11:48:28 -0700938 EXPECT_TRUE(ch1.conn()->receiving());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000939 EXPECT_EQ(Connection::STATE_WRITABLE, ch1.conn()->write_state());
Peter Thatcher04ac81f2015-09-21 11:48:28 -0700940 EXPECT_TRUE(ch2.conn()->receiving());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000941 EXPECT_EQ(Connection::STATE_WRITABLE, ch2.conn()->write_state());
942 } else {
Peter Thatcher04ac81f2015-09-21 11:48:28 -0700943 EXPECT_FALSE(ch1.conn()->receiving());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000944 EXPECT_NE(Connection::STATE_WRITABLE, ch1.conn()->write_state());
Peter Thatcher04ac81f2015-09-21 11:48:28 -0700945 EXPECT_FALSE(ch2.conn()->receiving());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000946 EXPECT_NE(Connection::STATE_WRITABLE, ch2.conn()->write_state());
947 }
948
949 // Tear down and ensure that goes smoothly.
950 ch1.Stop();
951 ch2.Stop();
Honghai Zhang161a5862016-10-20 11:47:02 -0700952 EXPECT_TRUE_SIMULATED_WAIT(ch1.conn() == NULL, kDefaultTimeout, clock);
953 EXPECT_TRUE_SIMULATED_WAIT(ch2.conn() == NULL, kDefaultTimeout, clock);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000954}
955
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000956class FakePacketSocketFactory : public rtc::PacketSocketFactory {
957 public:
958 FakePacketSocketFactory()
Jonas Oreland7a284e12020-01-28 09:21:54 +0100959 : next_udp_socket_(NULL), next_server_tcp_socket_(NULL) {}
Yves Gerey665174f2018-06-19 15:03:05 +0200960 ~FakePacketSocketFactory() override {}
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000961
pkasting@chromium.org332331f2014-11-06 20:19:22 +0000962 AsyncPacketSocket* CreateUdpSocket(const SocketAddress& address,
Peter Boström0c4e06b2015-10-07 12:23:21 +0200963 uint16_t min_port,
964 uint16_t max_port) override {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000965 EXPECT_TRUE(next_udp_socket_ != NULL);
966 AsyncPacketSocket* result = next_udp_socket_;
967 next_udp_socket_ = NULL;
968 return result;
969 }
970
Niels Möller6d19d142021-10-06 11:19:03 +0200971 AsyncListenSocket* CreateServerTcpSocket(const SocketAddress& local_address,
Peter Boström0c4e06b2015-10-07 12:23:21 +0200972 uint16_t min_port,
973 uint16_t max_port,
pkasting@chromium.org332331f2014-11-06 20:19:22 +0000974 int opts) override {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000975 EXPECT_TRUE(next_server_tcp_socket_ != NULL);
Niels Möller6d19d142021-10-06 11:19:03 +0200976 AsyncListenSocket* result = next_server_tcp_socket_;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000977 next_server_tcp_socket_ = NULL;
978 return result;
979 }
980
Patrik Höglund662e31f2019-09-05 14:35:04 +0200981 AsyncPacketSocket* CreateClientTcpSocket(
982 const SocketAddress& local_address,
983 const SocketAddress& remote_address,
984 const rtc::ProxyInfo& proxy_info,
985 const std::string& user_agent,
986 const rtc::PacketSocketTcpOptions& opts) override {
Jonas Oreland7a284e12020-01-28 09:21:54 +0100987 EXPECT_TRUE(next_client_tcp_socket_.has_value());
988 AsyncPacketSocket* result = *next_client_tcp_socket_;
989 next_client_tcp_socket_ = nullptr;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000990 return result;
991 }
992
993 void set_next_udp_socket(AsyncPacketSocket* next_udp_socket) {
994 next_udp_socket_ = next_udp_socket;
995 }
Niels Möller6d19d142021-10-06 11:19:03 +0200996 void set_next_server_tcp_socket(AsyncListenSocket* next_server_tcp_socket) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000997 next_server_tcp_socket_ = next_server_tcp_socket;
998 }
999 void set_next_client_tcp_socket(AsyncPacketSocket* next_client_tcp_socket) {
1000 next_client_tcp_socket_ = next_client_tcp_socket;
1001 }
Harald Alvestrand6f8fa5a2021-10-14 13:57:07 +00001002 std::unique_ptr<webrtc::AsyncDnsResolverInterface> CreateAsyncDnsResolver()
1003 override {
1004 return nullptr;
1005 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001006
1007 private:
1008 AsyncPacketSocket* next_udp_socket_;
Niels Möller6d19d142021-10-06 11:19:03 +02001009 AsyncListenSocket* next_server_tcp_socket_;
Jonas Oreland7a284e12020-01-28 09:21:54 +01001010 absl::optional<AsyncPacketSocket*> next_client_tcp_socket_;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001011};
1012
1013class FakeAsyncPacketSocket : public AsyncPacketSocket {
1014 public:
1015 // Returns current local address. Address may be set to NULL if the
1016 // socket is not bound yet (GetState() returns STATE_BINDING).
Jonas Oreland7a284e12020-01-28 09:21:54 +01001017 virtual SocketAddress GetLocalAddress() const { return local_address_; }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001018
1019 // Returns remote address. Returns zeroes if this is not a client TCP socket.
Jonas Oreland7a284e12020-01-28 09:21:54 +01001020 virtual SocketAddress GetRemoteAddress() const { return remote_address_; }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001021
1022 // Send a packet.
Yves Gerey665174f2018-06-19 15:03:05 +02001023 virtual int Send(const void* pv,
1024 size_t cb,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001025 const rtc::PacketOptions& options) {
Jonas Oreland7a284e12020-01-28 09:21:54 +01001026 if (error_ == 0) {
1027 return static_cast<int>(cb);
1028 } else {
1029 return -1;
1030 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001031 }
Yves Gerey665174f2018-06-19 15:03:05 +02001032 virtual int SendTo(const void* pv,
1033 size_t cb,
1034 const SocketAddress& addr,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001035 const rtc::PacketOptions& options) {
Jonas Oreland7a284e12020-01-28 09:21:54 +01001036 if (error_ == 0) {
1037 return static_cast<int>(cb);
1038 } else {
1039 return -1;
1040 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001041 }
Yves Gerey665174f2018-06-19 15:03:05 +02001042 virtual int Close() { return 0; }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001043
1044 virtual State GetState() const { return state_; }
1045 virtual int GetOption(Socket::Option opt, int* value) { return 0; }
1046 virtual int SetOption(Socket::Option opt, int value) { return 0; }
1047 virtual int GetError() const { return 0; }
Jonas Oreland7a284e12020-01-28 09:21:54 +01001048 virtual void SetError(int error) { error_ = error; }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001049
1050 void set_state(State state) { state_ = state; }
1051
Jonas Oreland7a284e12020-01-28 09:21:54 +01001052 SocketAddress local_address_;
1053 SocketAddress remote_address_;
1054
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001055 private:
Jonas Oreland7a284e12020-01-28 09:21:54 +01001056 int error_ = 0;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001057 State state_;
1058};
1059
Niels Möllerd30ece12021-10-19 10:11:02 +02001060class FakeAsyncListenSocket : public AsyncListenSocket {
1061 public:
1062 // Returns current local address. Address may be set to NULL if the
1063 // socket is not bound yet (GetState() returns STATE_BINDING).
1064 virtual SocketAddress GetLocalAddress() const { return local_address_; }
1065 void Bind(const SocketAddress& address) {
1066 local_address_ = address;
1067 state_ = State::kBound;
1068 }
1069 virtual int GetOption(Socket::Option opt, int* value) { return 0; }
1070 virtual int SetOption(Socket::Option opt, int value) { return 0; }
1071 virtual State GetState() const { return state_; }
1072
1073 private:
1074 SocketAddress local_address_;
1075 State state_ = State::kClosed;
1076};
1077
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001078// Local -> XXXX
1079TEST_F(PortTest, TestLocalToLocal) {
1080 TestLocalToLocal();
1081}
1082
1083TEST_F(PortTest, TestLocalToConeNat) {
1084 TestLocalToStun(NAT_OPEN_CONE);
1085}
1086
1087TEST_F(PortTest, TestLocalToARNat) {
1088 TestLocalToStun(NAT_ADDR_RESTRICTED);
1089}
1090
1091TEST_F(PortTest, TestLocalToPRNat) {
1092 TestLocalToStun(NAT_PORT_RESTRICTED);
1093}
1094
1095TEST_F(PortTest, TestLocalToSymNat) {
1096 TestLocalToStun(NAT_SYMMETRIC);
1097}
1098
1099// Flaky: https://code.google.com/p/webrtc/issues/detail?id=3316.
1100TEST_F(PortTest, DISABLED_TestLocalToTurn) {
Niels Möller191e38f2019-11-04 08:49:12 +01001101 TestLocalToRelay(PROTO_UDP);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001102}
1103
1104// Cone NAT -> XXXX
1105TEST_F(PortTest, TestConeNatToLocal) {
1106 TestStunToLocal(NAT_OPEN_CONE);
1107}
1108
1109TEST_F(PortTest, TestConeNatToConeNat) {
1110 TestStunToStun(NAT_OPEN_CONE, NAT_OPEN_CONE);
1111}
1112
1113TEST_F(PortTest, TestConeNatToARNat) {
1114 TestStunToStun(NAT_OPEN_CONE, NAT_ADDR_RESTRICTED);
1115}
1116
1117TEST_F(PortTest, TestConeNatToPRNat) {
1118 TestStunToStun(NAT_OPEN_CONE, NAT_PORT_RESTRICTED);
1119}
1120
1121TEST_F(PortTest, TestConeNatToSymNat) {
1122 TestStunToStun(NAT_OPEN_CONE, NAT_SYMMETRIC);
1123}
1124
1125TEST_F(PortTest, TestConeNatToTurn) {
Niels Möller191e38f2019-11-04 08:49:12 +01001126 TestStunToRelay(NAT_OPEN_CONE, PROTO_UDP);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001127}
1128
1129// Address-restricted NAT -> XXXX
1130TEST_F(PortTest, TestARNatToLocal) {
1131 TestStunToLocal(NAT_ADDR_RESTRICTED);
1132}
1133
1134TEST_F(PortTest, TestARNatToConeNat) {
1135 TestStunToStun(NAT_ADDR_RESTRICTED, NAT_OPEN_CONE);
1136}
1137
1138TEST_F(PortTest, TestARNatToARNat) {
1139 TestStunToStun(NAT_ADDR_RESTRICTED, NAT_ADDR_RESTRICTED);
1140}
1141
1142TEST_F(PortTest, TestARNatToPRNat) {
1143 TestStunToStun(NAT_ADDR_RESTRICTED, NAT_PORT_RESTRICTED);
1144}
1145
1146TEST_F(PortTest, TestARNatToSymNat) {
1147 TestStunToStun(NAT_ADDR_RESTRICTED, NAT_SYMMETRIC);
1148}
1149
1150TEST_F(PortTest, TestARNatToTurn) {
Niels Möller191e38f2019-11-04 08:49:12 +01001151 TestStunToRelay(NAT_ADDR_RESTRICTED, PROTO_UDP);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001152}
1153
1154// Port-restricted NAT -> XXXX
1155TEST_F(PortTest, TestPRNatToLocal) {
1156 TestStunToLocal(NAT_PORT_RESTRICTED);
1157}
1158
1159TEST_F(PortTest, TestPRNatToConeNat) {
1160 TestStunToStun(NAT_PORT_RESTRICTED, NAT_OPEN_CONE);
1161}
1162
1163TEST_F(PortTest, TestPRNatToARNat) {
1164 TestStunToStun(NAT_PORT_RESTRICTED, NAT_ADDR_RESTRICTED);
1165}
1166
1167TEST_F(PortTest, TestPRNatToPRNat) {
1168 TestStunToStun(NAT_PORT_RESTRICTED, NAT_PORT_RESTRICTED);
1169}
1170
1171TEST_F(PortTest, TestPRNatToSymNat) {
1172 // Will "fail"
1173 TestStunToStun(NAT_PORT_RESTRICTED, NAT_SYMMETRIC);
1174}
1175
1176TEST_F(PortTest, TestPRNatToTurn) {
Niels Möller191e38f2019-11-04 08:49:12 +01001177 TestStunToRelay(NAT_PORT_RESTRICTED, PROTO_UDP);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001178}
1179
1180// Symmetric NAT -> XXXX
1181TEST_F(PortTest, TestSymNatToLocal) {
1182 TestStunToLocal(NAT_SYMMETRIC);
1183}
1184
1185TEST_F(PortTest, TestSymNatToConeNat) {
1186 TestStunToStun(NAT_SYMMETRIC, NAT_OPEN_CONE);
1187}
1188
1189TEST_F(PortTest, TestSymNatToARNat) {
1190 TestStunToStun(NAT_SYMMETRIC, NAT_ADDR_RESTRICTED);
1191}
1192
1193TEST_F(PortTest, TestSymNatToPRNat) {
1194 // Will "fail"
1195 TestStunToStun(NAT_SYMMETRIC, NAT_PORT_RESTRICTED);
1196}
1197
1198TEST_F(PortTest, TestSymNatToSymNat) {
1199 // Will "fail"
1200 TestStunToStun(NAT_SYMMETRIC, NAT_SYMMETRIC);
1201}
1202
1203TEST_F(PortTest, TestSymNatToTurn) {
Niels Möller191e38f2019-11-04 08:49:12 +01001204 TestStunToRelay(NAT_SYMMETRIC, PROTO_UDP);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001205}
1206
1207// Outbound TCP -> XXXX
1208TEST_F(PortTest, TestTcpToTcp) {
1209 TestTcpToTcp();
1210}
1211
Guo-wei Shiehbe508a12015-04-06 12:48:47 -07001212TEST_F(PortTest, TestTcpReconnectOnSendPacket) {
1213 TestTcpReconnect(false /* ping */, true /* send */);
1214}
1215
1216TEST_F(PortTest, TestTcpReconnectOnPing) {
1217 TestTcpReconnect(true /* ping */, false /* send */);
1218}
1219
1220TEST_F(PortTest, TestTcpReconnectTimeout) {
1221 TestTcpReconnect(false /* ping */, false /* send */);
1222}
1223
Guo-wei Shieh1eb87c72015-08-25 11:02:55 -07001224// Test when TcpConnection never connects, the OnClose() will be called to
1225// destroy the connection.
1226TEST_F(PortTest, TestTcpNeverConnect) {
Steve Anton11358fe2018-10-09 15:39:19 -07001227 auto port1 = CreateTcpPort(kLocalAddr1);
Guo-wei Shieh1eb87c72015-08-25 11:02:55 -07001228 port1->SetIceRole(cricket::ICEROLE_CONTROLLING);
1229 port1->set_component(cricket::ICE_CANDIDATE_COMPONENT_DEFAULT);
1230
1231 // Set up a channel and ensure the port will be deleted.
Steve Anton11358fe2018-10-09 15:39:19 -07001232 TestChannel ch1(std::move(port1));
Guo-wei Shieh1eb87c72015-08-25 11:02:55 -07001233 EXPECT_EQ(0, ch1.complete_count());
1234
1235 ch1.Start();
Honghai Zhang161a5862016-10-20 11:47:02 -07001236 ASSERT_EQ_WAIT(1, ch1.complete_count(), kDefaultTimeout);
Guo-wei Shieh1eb87c72015-08-25 11:02:55 -07001237
Niels Möllerd0b88792021-08-12 10:32:30 +02001238 std::unique_ptr<rtc::Socket> server(
1239 vss()->CreateSocket(kLocalAddr2.family(), SOCK_STREAM));
Guo-wei Shieh1eb87c72015-08-25 11:02:55 -07001240 // Bind but not listen.
1241 EXPECT_EQ(0, server->Bind(kLocalAddr2));
1242
Steve Anton11358fe2018-10-09 15:39:19 -07001243 Candidate c = GetCandidate(ch1.port());
Guo-wei Shieh1eb87c72015-08-25 11:02:55 -07001244 c.set_address(server->GetLocalAddress());
1245
1246 ch1.CreateConnection(c);
1247 EXPECT_TRUE(ch1.conn());
Honghai Zhang161a5862016-10-20 11:47:02 -07001248 EXPECT_TRUE_WAIT(!ch1.conn(), kDefaultTimeout); // for TCP connect
Guo-wei Shieh1eb87c72015-08-25 11:02:55 -07001249}
1250
Steve Antonbabf9172017-11-29 10:19:02 -08001251/* TODO(?): Enable these once testrelayserver can accept external TCP.
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001252TEST_F(PortTest, TestTcpToTcpRelay) {
1253 TestTcpToRelay(PROTO_TCP);
1254}
1255
1256TEST_F(PortTest, TestTcpToSslTcpRelay) {
1257 TestTcpToRelay(PROTO_SSLTCP);
1258}
1259*/
1260
1261// Outbound SSLTCP -> XXXX
Steve Antonbabf9172017-11-29 10:19:02 -08001262/* TODO(?): Enable these once testrelayserver can accept external SSL.
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001263TEST_F(PortTest, TestSslTcpToTcpRelay) {
1264 TestSslTcpToRelay(PROTO_TCP);
1265}
1266
1267TEST_F(PortTest, TestSslTcpToSslTcpRelay) {
1268 TestSslTcpToRelay(PROTO_SSLTCP);
1269}
1270*/
1271
Honghai Zhang2cd7afe2015-11-12 11:14:33 -08001272// Test that a connection will be dead and deleted if
1273// i) it has never received anything for MIN_CONNECTION_LIFETIME milliseconds
1274// since it was created, or
1275// ii) it has not received anything for DEAD_CONNECTION_RECEIVE_TIMEOUT
1276// milliseconds since last receiving.
1277TEST_F(PortTest, TestConnectionDead) {
Steve Anton11358fe2018-10-09 15:39:19 -07001278 TestChannel ch1(CreateUdpPort(kLocalAddr1));
1279 TestChannel ch2(CreateUdpPort(kLocalAddr2));
Honghai Zhang2cd7afe2015-11-12 11:14:33 -08001280 // Acquire address.
1281 ch1.Start();
1282 ch2.Start();
Honghai Zhang161a5862016-10-20 11:47:02 -07001283 ASSERT_EQ_WAIT(1, ch1.complete_count(), kDefaultTimeout);
1284 ASSERT_EQ_WAIT(1, ch2.complete_count(), kDefaultTimeout);
Honghai Zhang2cd7afe2015-11-12 11:14:33 -08001285
honghaiz37389b42016-01-04 21:57:33 -08001286 // Test case that the connection has never received anything.
nisse1bffc1d2016-05-02 08:18:55 -07001287 int64_t before_created = rtc::TimeMillis();
Steve Anton11358fe2018-10-09 15:39:19 -07001288 ch1.CreateConnection(GetCandidate(ch2.port()));
nisse1bffc1d2016-05-02 08:18:55 -07001289 int64_t after_created = rtc::TimeMillis();
Honghai Zhang2cd7afe2015-11-12 11:14:33 -08001290 Connection* conn = ch1.conn();
nissec8ee8822017-01-18 07:20:55 -08001291 ASSERT_NE(conn, nullptr);
honghaiz37389b42016-01-04 21:57:33 -08001292 // It is not dead if it is after MIN_CONNECTION_LIFETIME but not pruned.
1293 conn->UpdateState(after_created + MIN_CONNECTION_LIFETIME + 1);
1294 rtc::Thread::Current()->ProcessMessages(0);
Honghai Zhang2cd7afe2015-11-12 11:14:33 -08001295 EXPECT_TRUE(ch1.conn() != nullptr);
honghaiz37389b42016-01-04 21:57:33 -08001296 // It is not dead if it is before MIN_CONNECTION_LIFETIME and pruned.
1297 conn->UpdateState(before_created + MIN_CONNECTION_LIFETIME - 1);
1298 conn->Prune();
1299 rtc::Thread::Current()->ProcessMessages(0);
1300 EXPECT_TRUE(ch1.conn() != nullptr);
1301 // It will be dead after MIN_CONNECTION_LIFETIME and pruned.
Honghai Zhang2cd7afe2015-11-12 11:14:33 -08001302 conn->UpdateState(after_created + MIN_CONNECTION_LIFETIME + 1);
Honghai Zhang161a5862016-10-20 11:47:02 -07001303 EXPECT_TRUE_WAIT(ch1.conn() == nullptr, kDefaultTimeout);
Honghai Zhang2cd7afe2015-11-12 11:14:33 -08001304
honghaiz37389b42016-01-04 21:57:33 -08001305 // Test case that the connection has received something.
Honghai Zhang2cd7afe2015-11-12 11:14:33 -08001306 // Create a connection again and receive a ping.
Steve Anton11358fe2018-10-09 15:39:19 -07001307 ch1.CreateConnection(GetCandidate(ch2.port()));
Honghai Zhang2cd7afe2015-11-12 11:14:33 -08001308 conn = ch1.conn();
nissec8ee8822017-01-18 07:20:55 -08001309 ASSERT_NE(conn, nullptr);
nisse1bffc1d2016-05-02 08:18:55 -07001310 int64_t before_last_receiving = rtc::TimeMillis();
Honghai Zhang2cd7afe2015-11-12 11:14:33 -08001311 conn->ReceivedPing();
nisse1bffc1d2016-05-02 08:18:55 -07001312 int64_t after_last_receiving = rtc::TimeMillis();
Honghai Zhang2cd7afe2015-11-12 11:14:33 -08001313 // The connection will be dead after DEAD_CONNECTION_RECEIVE_TIMEOUT
Yves Gerey665174f2018-06-19 15:03:05 +02001314 conn->UpdateState(before_last_receiving + DEAD_CONNECTION_RECEIVE_TIMEOUT -
1315 1);
Honghai Zhang2cd7afe2015-11-12 11:14:33 -08001316 rtc::Thread::Current()->ProcessMessages(100);
1317 EXPECT_TRUE(ch1.conn() != nullptr);
1318 conn->UpdateState(after_last_receiving + DEAD_CONNECTION_RECEIVE_TIMEOUT + 1);
Honghai Zhang161a5862016-10-20 11:47:02 -07001319 EXPECT_TRUE_WAIT(ch1.conn() == nullptr, kDefaultTimeout);
Honghai Zhang2cd7afe2015-11-12 11:14:33 -08001320}
1321
Jonas Oreland21433ca2020-05-13 14:11:25 +02001322TEST_F(PortTest, TestConnectionDeadWithDeadConnectionTimeout) {
1323 TestChannel ch1(CreateUdpPort(kLocalAddr1));
1324 TestChannel ch2(CreateUdpPort(kLocalAddr2));
1325 // Acquire address.
1326 ch1.Start();
1327 ch2.Start();
1328 ASSERT_EQ_WAIT(1, ch1.complete_count(), kDefaultTimeout);
1329 ASSERT_EQ_WAIT(1, ch2.complete_count(), kDefaultTimeout);
1330
1331 // Note: set field trials manually since they are parsed by
1332 // P2PTransportChannel but P2PTransportChannel is not used in this test.
1333 IceFieldTrials field_trials;
1334 field_trials.dead_connection_timeout_ms = 90000;
1335
1336 // Create a connection again and receive a ping.
1337 ch1.CreateConnection(GetCandidate(ch2.port()));
1338 auto conn = ch1.conn();
1339 conn->SetIceFieldTrials(&field_trials);
1340
1341 ASSERT_NE(conn, nullptr);
1342 int64_t before_last_receiving = rtc::TimeMillis();
1343 conn->ReceivedPing();
1344 int64_t after_last_receiving = rtc::TimeMillis();
1345 // The connection will be dead after 90s
1346 conn->UpdateState(before_last_receiving + 90000 - 1);
1347 rtc::Thread::Current()->ProcessMessages(100);
1348 EXPECT_TRUE(ch1.conn() != nullptr);
1349 conn->UpdateState(after_last_receiving + 90000 + 1);
1350 EXPECT_TRUE_WAIT(ch1.conn() == nullptr, kDefaultTimeout);
1351}
1352
1353TEST_F(PortTest, TestConnectionDeadOutstandingPing) {
1354 auto port1 = CreateUdpPort(kLocalAddr1);
1355 port1->SetIceRole(cricket::ICEROLE_CONTROLLING);
1356 port1->SetIceTiebreaker(kTiebreaker1);
1357 auto port2 = CreateUdpPort(kLocalAddr2);
1358 port2->SetIceRole(cricket::ICEROLE_CONTROLLED);
1359 port2->SetIceTiebreaker(kTiebreaker2);
1360
1361 TestChannel ch1(std::move(port1));
1362 TestChannel ch2(std::move(port2));
1363 // Acquire address.
1364 ch1.Start();
1365 ch2.Start();
1366 ASSERT_EQ_WAIT(1, ch1.complete_count(), kDefaultTimeout);
1367 ASSERT_EQ_WAIT(1, ch2.complete_count(), kDefaultTimeout);
1368
1369 // Note: set field trials manually since they are parsed by
1370 // P2PTransportChannel but P2PTransportChannel is not used in this test.
1371 IceFieldTrials field_trials;
1372 field_trials.dead_connection_timeout_ms = 360000;
1373
1374 // Create a connection again and receive a ping and then send
1375 // a ping and keep it outstanding.
1376 ch1.CreateConnection(GetCandidate(ch2.port()));
1377 auto conn = ch1.conn();
1378 conn->SetIceFieldTrials(&field_trials);
1379
1380 ASSERT_NE(conn, nullptr);
1381 conn->ReceivedPing();
1382 int64_t send_ping_timestamp = rtc::TimeMillis();
1383 conn->Ping(send_ping_timestamp);
1384
1385 // The connection will be dead 30s after the ping was sent.
1386 conn->UpdateState(send_ping_timestamp + DEAD_CONNECTION_RECEIVE_TIMEOUT - 1);
1387 rtc::Thread::Current()->ProcessMessages(100);
1388 EXPECT_TRUE(ch1.conn() != nullptr);
1389 conn->UpdateState(send_ping_timestamp + DEAD_CONNECTION_RECEIVE_TIMEOUT + 1);
1390 EXPECT_TRUE_WAIT(ch1.conn() == nullptr, kDefaultTimeout);
1391}
1392
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001393// This test case verifies standard ICE features in STUN messages. Currently it
1394// verifies Message Integrity attribute in STUN messages and username in STUN
1395// binding request will have colon (":") between remote and local username.
Peter Thatcher7cbd1882015-09-17 18:54:52 -07001396TEST_F(PortTest, TestLocalToLocalStandard) {
Steve Anton11358fe2018-10-09 15:39:19 -07001397 auto port1 = CreateUdpPort(kLocalAddr1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001398 port1->SetIceRole(cricket::ICEROLE_CONTROLLING);
1399 port1->SetIceTiebreaker(kTiebreaker1);
Steve Anton11358fe2018-10-09 15:39:19 -07001400 auto port2 = CreateUdpPort(kLocalAddr2);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001401 port2->SetIceRole(cricket::ICEROLE_CONTROLLED);
1402 port2->SetIceTiebreaker(kTiebreaker2);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001403 // Same parameters as TestLocalToLocal above.
Steve Anton11358fe2018-10-09 15:39:19 -07001404 TestConnectivity("udp", std::move(port1), "udp", std::move(port2), true, true,
1405 true, true);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001406}
1407
1408// This test is trying to validate a successful and failure scenario in a
1409// loopback test when protocol is RFC5245. For success IceTiebreaker, username
1410// should remain equal to the request generated by the port and role of port
1411// must be in controlling.
Honghai Zhang161a5862016-10-20 11:47:02 -07001412TEST_F(PortTest, TestLoopbackCall) {
Steve Anton11358fe2018-10-09 15:39:19 -07001413 auto lport = CreateTestPort(kLocalAddr1, "lfrag", "lpass");
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001414 lport->SetIceRole(cricket::ICEROLE_CONTROLLING);
1415 lport->SetIceTiebreaker(kTiebreaker1);
1416 lport->PrepareAddress();
1417 ASSERT_FALSE(lport->Candidates().empty());
Yves Gerey665174f2018-06-19 15:03:05 +02001418 Connection* conn =
1419 lport->CreateConnection(lport->Candidates()[0], Port::ORIGIN_MESSAGE);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001420 conn->Ping(0);
1421
Honghai Zhang161a5862016-10-20 11:47:02 -07001422 ASSERT_TRUE_WAIT(lport->last_stun_msg() != NULL, kDefaultTimeout);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001423 IceMessage* msg = lport->last_stun_msg();
1424 EXPECT_EQ(STUN_BINDING_REQUEST, msg->type());
jbauchf1f87202016-03-30 06:43:37 -07001425 conn->OnReadPacket(lport->last_stun_buf()->data<char>(),
Niels Möllere6933812018-11-05 13:01:41 +01001426 lport->last_stun_buf()->size(), /* packet_time_us */ -1);
Honghai Zhang161a5862016-10-20 11:47:02 -07001427 ASSERT_TRUE_WAIT(lport->last_stun_msg() != NULL, kDefaultTimeout);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001428 msg = lport->last_stun_msg();
1429 EXPECT_EQ(STUN_BINDING_RESPONSE, msg->type());
1430
1431 // If the tiebreaker value is different from port, we expect a error
1432 // response.
1433 lport->Reset();
1434 lport->AddCandidateAddress(kLocalAddr2);
Artem Titov2dbb4c92021-07-26 15:12:41 +02001435 // Creating a different connection as `conn` is receiving.
Yves Gerey665174f2018-06-19 15:03:05 +02001436 Connection* conn1 =
1437 lport->CreateConnection(lport->Candidates()[1], Port::ORIGIN_MESSAGE);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001438 conn1->Ping(0);
1439
Honghai Zhang161a5862016-10-20 11:47:02 -07001440 ASSERT_TRUE_WAIT(lport->last_stun_msg() != NULL, kDefaultTimeout);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001441 msg = lport->last_stun_msg();
1442 EXPECT_EQ(STUN_BINDING_REQUEST, msg->type());
kwiberg3ec46792016-04-27 07:22:53 -07001443 std::unique_ptr<IceMessage> modified_req(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001444 CreateStunMessage(STUN_BINDING_REQUEST));
Yves Gerey665174f2018-06-19 15:03:05 +02001445 const StunByteStringAttribute* username_attr =
1446 msg->GetByteString(STUN_ATTR_USERNAME);
Mirko Bonadei317a1f02019-09-17 17:06:18 +02001447 modified_req->AddAttribute(std::make_unique<StunByteStringAttribute>(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001448 STUN_ATTR_USERNAME, username_attr->GetString()));
1449 // To make sure we receive error response, adding tiebreaker less than
1450 // what's present in request.
Mirko Bonadei317a1f02019-09-17 17:06:18 +02001451 modified_req->AddAttribute(std::make_unique<StunUInt64Attribute>(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001452 STUN_ATTR_ICE_CONTROLLING, kTiebreaker1 - 1));
1453 modified_req->AddMessageIntegrity("lpass");
1454 modified_req->AddFingerprint();
1455
1456 lport->Reset();
Mirko Bonadei317a1f02019-09-17 17:06:18 +02001457 auto buf = std::make_unique<ByteBufferWriter>();
Steve Anton11358fe2018-10-09 15:39:19 -07001458 WriteStunMessage(*modified_req, buf.get());
Niels Möllere6933812018-11-05 13:01:41 +01001459 conn1->OnReadPacket(buf->Data(), buf->Length(), /* packet_time_us */ -1);
Honghai Zhang161a5862016-10-20 11:47:02 -07001460 ASSERT_TRUE_WAIT(lport->last_stun_msg() != NULL, kDefaultTimeout);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001461 msg = lport->last_stun_msg();
1462 EXPECT_EQ(STUN_BINDING_ERROR_RESPONSE, msg->type());
1463}
1464
1465// This test verifies role conflict signal is received when there is
1466// conflict in the role. In this case both ports are in controlling and
Artem Titov2dbb4c92021-07-26 15:12:41 +02001467// `rport` has higher tiebreaker value than `lport`. Since `lport` has lower
1468// value of tiebreaker, when it receives ping request from `rport` it will
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001469// send role conflict signal.
1470TEST_F(PortTest, TestIceRoleConflict) {
Steve Anton11358fe2018-10-09 15:39:19 -07001471 auto lport = CreateTestPort(kLocalAddr1, "lfrag", "lpass");
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001472 lport->SetIceRole(cricket::ICEROLE_CONTROLLING);
1473 lport->SetIceTiebreaker(kTiebreaker1);
Steve Anton11358fe2018-10-09 15:39:19 -07001474 auto rport = CreateTestPort(kLocalAddr2, "rfrag", "rpass");
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001475 rport->SetIceRole(cricket::ICEROLE_CONTROLLING);
1476 rport->SetIceTiebreaker(kTiebreaker2);
1477
1478 lport->PrepareAddress();
1479 rport->PrepareAddress();
1480 ASSERT_FALSE(lport->Candidates().empty());
1481 ASSERT_FALSE(rport->Candidates().empty());
Yves Gerey665174f2018-06-19 15:03:05 +02001482 Connection* lconn =
1483 lport->CreateConnection(rport->Candidates()[0], Port::ORIGIN_MESSAGE);
1484 Connection* rconn =
1485 rport->CreateConnection(lport->Candidates()[0], Port::ORIGIN_MESSAGE);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001486 rconn->Ping(0);
1487
Honghai Zhang161a5862016-10-20 11:47:02 -07001488 ASSERT_TRUE_WAIT(rport->last_stun_msg() != NULL, kDefaultTimeout);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001489 IceMessage* msg = rport->last_stun_msg();
1490 EXPECT_EQ(STUN_BINDING_REQUEST, msg->type());
1491 // Send rport binding request to lport.
jbauchf1f87202016-03-30 06:43:37 -07001492 lconn->OnReadPacket(rport->last_stun_buf()->data<char>(),
Niels Möllere6933812018-11-05 13:01:41 +01001493 rport->last_stun_buf()->size(), /* packet_time_us */ -1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001494
Honghai Zhang161a5862016-10-20 11:47:02 -07001495 ASSERT_TRUE_WAIT(lport->last_stun_msg() != NULL, kDefaultTimeout);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001496 EXPECT_EQ(STUN_BINDING_RESPONSE, lport->last_stun_msg()->type());
1497 EXPECT_TRUE(role_conflict());
1498}
1499
1500TEST_F(PortTest, TestTcpNoDelay) {
Niels Möller646fddc2021-11-02 15:56:05 +01001501 rtc::ScopedFakeClock clock;
Steve Anton11358fe2018-10-09 15:39:19 -07001502 auto port1 = CreateTcpPort(kLocalAddr1);
Peter Thatcher7cbd1882015-09-17 18:54:52 -07001503 port1->SetIceRole(cricket::ICEROLE_CONTROLLING);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001504 int option_value = -1;
Yves Gerey665174f2018-06-19 15:03:05 +02001505 int success = port1->GetOption(rtc::Socket::OPT_NODELAY, &option_value);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001506 ASSERT_EQ(0, success); // GetOption() should complete successfully w/ 0
Niels Möller646fddc2021-11-02 15:56:05 +01001507 EXPECT_EQ(1, option_value);
1508
1509 auto port2 = CreateTcpPort(kLocalAddr2);
1510 port2->SetIceRole(cricket::ICEROLE_CONTROLLED);
1511
1512 // Set up a connection, and verify that option is set on connected sockets at
1513 // both ends.
1514 TestChannel ch1(std::move(port1));
1515 TestChannel ch2(std::move(port2));
1516 // Acquire addresses.
1517 ch1.Start();
1518 ch2.Start();
1519 ASSERT_EQ_SIMULATED_WAIT(1, ch1.complete_count(), kDefaultTimeout, clock);
1520 ASSERT_EQ_SIMULATED_WAIT(1, ch2.complete_count(), kDefaultTimeout, clock);
1521 // Connect and send a ping from src to dst.
1522 ch1.CreateConnection(GetCandidate(ch2.port()));
1523 ASSERT_TRUE(ch1.conn() != NULL);
1524 EXPECT_TRUE_SIMULATED_WAIT(ch1.conn()->connected(), kDefaultTimeout,
1525 clock); // for TCP connect
1526 ch1.Ping();
1527 SIMULATED_WAIT(!ch2.remote_address().IsNil(), kShortTimeout, clock);
1528
1529 // Accept the connection.
1530 ch2.AcceptConnection(GetCandidate(ch1.port()));
1531 ASSERT_TRUE(ch2.conn() != NULL);
1532
1533 option_value = -1;
1534 success = static_cast<TCPConnection*>(ch1.conn())
1535 ->socket()
1536 ->GetOption(rtc::Socket::OPT_NODELAY, &option_value);
1537 ASSERT_EQ(0, success);
1538 EXPECT_EQ(1, option_value);
1539
1540 option_value = -1;
1541 success = static_cast<TCPConnection*>(ch2.conn())
1542 ->socket()
1543 ->GetOption(rtc::Socket::OPT_NODELAY, &option_value);
1544 ASSERT_EQ(0, success);
1545 EXPECT_EQ(1, option_value);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001546}
1547
1548TEST_F(PortTest, TestDelayedBindingUdp) {
Benjamin Wrightd6f86e82018-05-08 13:12:25 -07001549 FakeAsyncPacketSocket* socket = new FakeAsyncPacketSocket();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001550 FakePacketSocketFactory socket_factory;
1551
1552 socket_factory.set_next_udp_socket(socket);
Steve Anton11358fe2018-10-09 15:39:19 -07001553 auto port = CreateUdpPort(kLocalAddr1, &socket_factory);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001554
1555 socket->set_state(AsyncPacketSocket::STATE_BINDING);
1556 port->PrepareAddress();
1557
1558 EXPECT_EQ(0U, port->Candidates().size());
1559 socket->SignalAddressReady(socket, kLocalAddr2);
1560
1561 EXPECT_EQ(1U, port->Candidates().size());
1562}
1563
Jonas Oreland7a284e12020-01-28 09:21:54 +01001564TEST_F(PortTest, TestDisableInterfaceOfTcpPort) {
Niels Möllerd30ece12021-10-19 10:11:02 +02001565 FakeAsyncListenSocket* lsocket = new FakeAsyncListenSocket();
1566 FakeAsyncListenSocket* rsocket = new FakeAsyncListenSocket();
Jonas Oreland7a284e12020-01-28 09:21:54 +01001567 FakePacketSocketFactory socket_factory;
1568
1569 socket_factory.set_next_server_tcp_socket(lsocket);
1570 auto lport = CreateTcpPort(kLocalAddr1, &socket_factory);
1571
1572 socket_factory.set_next_server_tcp_socket(rsocket);
1573 auto rport = CreateTcpPort(kLocalAddr2, &socket_factory);
1574
Niels Möllerd30ece12021-10-19 10:11:02 +02001575 lsocket->Bind(kLocalAddr1);
1576 rsocket->Bind(kLocalAddr2);
Jonas Oreland7a284e12020-01-28 09:21:54 +01001577
1578 lport->SetIceRole(cricket::ICEROLE_CONTROLLING);
1579 lport->SetIceTiebreaker(kTiebreaker1);
1580 rport->SetIceRole(cricket::ICEROLE_CONTROLLED);
1581 rport->SetIceTiebreaker(kTiebreaker2);
1582
1583 lport->PrepareAddress();
1584 rport->PrepareAddress();
1585 ASSERT_FALSE(rport->Candidates().empty());
1586
1587 // A client socket.
1588 FakeAsyncPacketSocket* socket = new FakeAsyncPacketSocket();
1589 socket->local_address_ = kLocalAddr1;
1590 socket->remote_address_ = kLocalAddr2;
1591 socket_factory.set_next_client_tcp_socket(socket);
1592 Connection* lconn =
1593 lport->CreateConnection(rport->Candidates()[0], Port::ORIGIN_MESSAGE);
1594 ASSERT_NE(lconn, nullptr);
1595 socket->SignalConnect(socket);
1596 lconn->Ping(0);
1597
1598 // Now disconnect the client socket...
1599 socket->SignalClose(socket, 1);
1600
1601 // And prevent new sockets from being created.
1602 socket_factory.set_next_client_tcp_socket(nullptr);
1603
1604 // Test that Ping() does not cause SEGV.
1605 lconn->Ping(0);
1606}
1607
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001608void PortTest::TestCrossFamilyPorts(int type) {
1609 FakePacketSocketFactory factory;
kwiberg3ec46792016-04-27 07:22:53 -07001610 std::unique_ptr<Port> ports[4];
Yves Gerey665174f2018-06-19 15:03:05 +02001611 SocketAddress addresses[4] = {
1612 SocketAddress("192.168.1.3", 0), SocketAddress("192.168.1.4", 0),
1613 SocketAddress("2001:db8::1", 0), SocketAddress("2001:db8::2", 0)};
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001614 for (int i = 0; i < 4; i++) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001615 if (type == SOCK_DGRAM) {
Niels Möllerd30ece12021-10-19 10:11:02 +02001616 FakeAsyncPacketSocket* socket = new FakeAsyncPacketSocket();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001617 factory.set_next_udp_socket(socket);
Steve Anton11358fe2018-10-09 15:39:19 -07001618 ports[i] = CreateUdpPort(addresses[i], &factory);
Niels Möller4a1c2c42021-09-28 10:17:07 +02001619 socket->set_state(AsyncPacketSocket::STATE_BINDING);
1620 socket->SignalAddressReady(socket, addresses[i]);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001621 } else if (type == SOCK_STREAM) {
Niels Möllerd30ece12021-10-19 10:11:02 +02001622 FakeAsyncListenSocket* socket = new FakeAsyncListenSocket();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001623 factory.set_next_server_tcp_socket(socket);
Steve Anton11358fe2018-10-09 15:39:19 -07001624 ports[i] = CreateTcpPort(addresses[i], &factory);
Niels Möllerd30ece12021-10-19 10:11:02 +02001625 socket->Bind(addresses[i]);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001626 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001627 ports[i]->PrepareAddress();
1628 }
1629
1630 // IPv4 Port, connects to IPv6 candidate and then to IPv4 candidate.
1631 if (type == SOCK_STREAM) {
1632 FakeAsyncPacketSocket* clientsocket = new FakeAsyncPacketSocket();
1633 factory.set_next_client_tcp_socket(clientsocket);
1634 }
1635 Connection* c = ports[0]->CreateConnection(GetCandidate(ports[2].get()),
1636 Port::ORIGIN_MESSAGE);
1637 EXPECT_TRUE(NULL == c);
1638 EXPECT_EQ(0U, ports[0]->connections().size());
1639 c = ports[0]->CreateConnection(GetCandidate(ports[1].get()),
1640 Port::ORIGIN_MESSAGE);
1641 EXPECT_FALSE(NULL == c);
1642 EXPECT_EQ(1U, ports[0]->connections().size());
1643
1644 // IPv6 Port, connects to IPv4 candidate and to IPv6 candidate.
1645 if (type == SOCK_STREAM) {
1646 FakeAsyncPacketSocket* clientsocket = new FakeAsyncPacketSocket();
1647 factory.set_next_client_tcp_socket(clientsocket);
1648 }
1649 c = ports[2]->CreateConnection(GetCandidate(ports[0].get()),
1650 Port::ORIGIN_MESSAGE);
1651 EXPECT_TRUE(NULL == c);
1652 EXPECT_EQ(0U, ports[2]->connections().size());
1653 c = ports[2]->CreateConnection(GetCandidate(ports[3].get()),
1654 Port::ORIGIN_MESSAGE);
1655 EXPECT_FALSE(NULL == c);
1656 EXPECT_EQ(1U, ports[2]->connections().size());
1657}
1658
1659TEST_F(PortTest, TestSkipCrossFamilyTcp) {
1660 TestCrossFamilyPorts(SOCK_STREAM);
1661}
1662
1663TEST_F(PortTest, TestSkipCrossFamilyUdp) {
1664 TestCrossFamilyPorts(SOCK_DGRAM);
1665}
1666
Peter Thatcherb8b01432015-07-07 16:45:53 -07001667void PortTest::ExpectPortsCanConnect(bool can_connect, Port* p1, Port* p2) {
Yves Gerey665174f2018-06-19 15:03:05 +02001668 Connection* c = p1->CreateConnection(GetCandidate(p2), Port::ORIGIN_MESSAGE);
Peter Thatcherb8b01432015-07-07 16:45:53 -07001669 if (can_connect) {
1670 EXPECT_FALSE(NULL == c);
1671 EXPECT_EQ(1U, p1->connections().size());
1672 } else {
1673 EXPECT_TRUE(NULL == c);
1674 EXPECT_EQ(0U, p1->connections().size());
1675 }
1676}
1677
1678TEST_F(PortTest, TestUdpV6CrossTypePorts) {
1679 FakePacketSocketFactory factory;
kwiberg3ec46792016-04-27 07:22:53 -07001680 std::unique_ptr<Port> ports[4];
Yves Gerey665174f2018-06-19 15:03:05 +02001681 SocketAddress addresses[4] = {
1682 SocketAddress("2001:db8::1", 0), SocketAddress("fe80::1", 0),
1683 SocketAddress("fe80::2", 0), SocketAddress("::1", 0)};
Peter Thatcherb8b01432015-07-07 16:45:53 -07001684 for (int i = 0; i < 4; i++) {
Benjamin Wrightd6f86e82018-05-08 13:12:25 -07001685 FakeAsyncPacketSocket* socket = new FakeAsyncPacketSocket();
Peter Thatcherb8b01432015-07-07 16:45:53 -07001686 factory.set_next_udp_socket(socket);
Steve Anton11358fe2018-10-09 15:39:19 -07001687 ports[i] = CreateUdpPort(addresses[i], &factory);
Peter Thatcherb8b01432015-07-07 16:45:53 -07001688 socket->set_state(AsyncPacketSocket::STATE_BINDING);
1689 socket->SignalAddressReady(socket, addresses[i]);
1690 ports[i]->PrepareAddress();
1691 }
1692
1693 Port* standard = ports[0].get();
1694 Port* link_local1 = ports[1].get();
1695 Port* link_local2 = ports[2].get();
1696 Port* localhost = ports[3].get();
1697
1698 ExpectPortsCanConnect(false, link_local1, standard);
1699 ExpectPortsCanConnect(false, standard, link_local1);
1700 ExpectPortsCanConnect(false, link_local1, localhost);
1701 ExpectPortsCanConnect(false, localhost, link_local1);
1702
1703 ExpectPortsCanConnect(true, link_local1, link_local2);
1704 ExpectPortsCanConnect(true, localhost, standard);
1705 ExpectPortsCanConnect(true, standard, localhost);
1706}
1707
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001708// This test verifies DSCP value set through SetOption interface can be
1709// get through DefaultDscpValue.
1710TEST_F(PortTest, TestDefaultDscpValue) {
1711 int dscp;
Steve Anton11358fe2018-10-09 15:39:19 -07001712 auto udpport = CreateUdpPort(kLocalAddr1);
Yves Gerey665174f2018-06-19 15:03:05 +02001713 EXPECT_EQ(0, udpport->SetOption(rtc::Socket::OPT_DSCP, rtc::DSCP_CS6));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001714 EXPECT_EQ(0, udpport->GetOption(rtc::Socket::OPT_DSCP, &dscp));
Steve Anton11358fe2018-10-09 15:39:19 -07001715 auto tcpport = CreateTcpPort(kLocalAddr1);
Yves Gerey665174f2018-06-19 15:03:05 +02001716 EXPECT_EQ(0, tcpport->SetOption(rtc::Socket::OPT_DSCP, rtc::DSCP_AF31));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001717 EXPECT_EQ(0, tcpport->GetOption(rtc::Socket::OPT_DSCP, &dscp));
1718 EXPECT_EQ(rtc::DSCP_AF31, dscp);
Steve Anton11358fe2018-10-09 15:39:19 -07001719 auto stunport = CreateStunPort(kLocalAddr1, nat_socket_factory1());
Yves Gerey665174f2018-06-19 15:03:05 +02001720 EXPECT_EQ(0, stunport->SetOption(rtc::Socket::OPT_DSCP, rtc::DSCP_AF41));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001721 EXPECT_EQ(0, stunport->GetOption(rtc::Socket::OPT_DSCP, &dscp));
1722 EXPECT_EQ(rtc::DSCP_AF41, dscp);
Steve Anton11358fe2018-10-09 15:39:19 -07001723 auto turnport1 =
1724 CreateTurnPort(kLocalAddr1, nat_socket_factory1(), PROTO_UDP, PROTO_UDP);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001725 // Socket is created in PrepareAddress.
1726 turnport1->PrepareAddress();
Yves Gerey665174f2018-06-19 15:03:05 +02001727 EXPECT_EQ(0, turnport1->SetOption(rtc::Socket::OPT_DSCP, rtc::DSCP_CS7));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001728 EXPECT_EQ(0, turnport1->GetOption(rtc::Socket::OPT_DSCP, &dscp));
1729 EXPECT_EQ(rtc::DSCP_CS7, dscp);
1730 // This will verify correct value returned without the socket.
Steve Anton11358fe2018-10-09 15:39:19 -07001731 auto turnport2 =
1732 CreateTurnPort(kLocalAddr1, nat_socket_factory1(), PROTO_UDP, PROTO_UDP);
Yves Gerey665174f2018-06-19 15:03:05 +02001733 EXPECT_EQ(0, turnport2->SetOption(rtc::Socket::OPT_DSCP, rtc::DSCP_CS6));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001734 EXPECT_EQ(0, turnport2->GetOption(rtc::Socket::OPT_DSCP, &dscp));
1735 EXPECT_EQ(rtc::DSCP_CS6, dscp);
1736}
1737
Peter Thatcher7cbd1882015-09-17 18:54:52 -07001738// Test sending STUN messages.
1739TEST_F(PortTest, TestSendStunMessage) {
Steve Anton11358fe2018-10-09 15:39:19 -07001740 auto lport = CreateTestPort(kLocalAddr1, "lfrag", "lpass");
1741 auto rport = CreateTestPort(kLocalAddr2, "rfrag", "rpass");
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001742 lport->SetIceRole(cricket::ICEROLE_CONTROLLING);
1743 lport->SetIceTiebreaker(kTiebreaker1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001744 rport->SetIceRole(cricket::ICEROLE_CONTROLLED);
1745 rport->SetIceTiebreaker(kTiebreaker2);
1746
1747 // Send a fake ping from lport to rport.
1748 lport->PrepareAddress();
1749 rport->PrepareAddress();
1750 ASSERT_FALSE(rport->Candidates().empty());
Yves Gerey665174f2018-06-19 15:03:05 +02001751 Connection* lconn =
1752 lport->CreateConnection(rport->Candidates()[0], Port::ORIGIN_MESSAGE);
1753 Connection* rconn =
1754 rport->CreateConnection(lport->Candidates()[0], Port::ORIGIN_MESSAGE);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001755 lconn->Ping(0);
1756
1757 // Check that it's a proper BINDING-REQUEST.
Honghai Zhang161a5862016-10-20 11:47:02 -07001758 ASSERT_TRUE_WAIT(lport->last_stun_msg() != NULL, kDefaultTimeout);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001759 IceMessage* msg = lport->last_stun_msg();
1760 EXPECT_EQ(STUN_BINDING_REQUEST, msg->type());
1761 EXPECT_FALSE(msg->IsLegacy());
1762 const StunByteStringAttribute* username_attr =
1763 msg->GetByteString(STUN_ATTR_USERNAME);
1764 ASSERT_TRUE(username_attr != NULL);
1765 const StunUInt32Attribute* priority_attr = msg->GetUInt32(STUN_ATTR_PRIORITY);
1766 ASSERT_TRUE(priority_attr != NULL);
1767 EXPECT_EQ(kDefaultPrflxPriority, priority_attr->value());
1768 EXPECT_EQ("rfrag:lfrag", username_attr->GetString());
1769 EXPECT_TRUE(msg->GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001770 EXPECT_EQ(StunMessage::IntegrityStatus::kIntegrityOk,
1771 msg->ValidateMessageIntegrity("rpass"));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001772 const StunUInt64Attribute* ice_controlling_attr =
1773 msg->GetUInt64(STUN_ATTR_ICE_CONTROLLING);
1774 ASSERT_TRUE(ice_controlling_attr != NULL);
1775 EXPECT_EQ(lport->IceTiebreaker(), ice_controlling_attr->value());
1776 EXPECT_TRUE(msg->GetByteString(STUN_ATTR_ICE_CONTROLLED) == NULL);
1777 EXPECT_TRUE(msg->GetByteString(STUN_ATTR_USE_CANDIDATE) != NULL);
1778 EXPECT_TRUE(msg->GetUInt32(STUN_ATTR_FINGERPRINT) != NULL);
1779 EXPECT_TRUE(StunMessage::ValidateFingerprint(
jbauchf1f87202016-03-30 06:43:37 -07001780 lport->last_stun_buf()->data<char>(), lport->last_stun_buf()->size()));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001781
1782 // Request should not include ping count.
1783 ASSERT_TRUE(msg->GetUInt32(STUN_ATTR_RETRANSMIT_COUNT) == NULL);
1784
1785 // Save a copy of the BINDING-REQUEST for use below.
Steve Anton11358fe2018-10-09 15:39:19 -07001786 std::unique_ptr<IceMessage> request = CopyStunMessage(*msg);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001787
zhihuang5ecf16c2016-06-01 17:09:15 -07001788 // Receive the BINDING-REQUEST and respond with BINDING-RESPONSE.
1789 rconn->OnReadPacket(lport->last_stun_buf()->data<char>(),
Niels Möllere6933812018-11-05 13:01:41 +01001790 lport->last_stun_buf()->size(), /* packet_time_us */ -1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001791 msg = rport->last_stun_msg();
1792 ASSERT_TRUE(msg != NULL);
1793 EXPECT_EQ(STUN_BINDING_RESPONSE, msg->type());
zhihuang5ecf16c2016-06-01 17:09:15 -07001794 // Received a BINDING-RESPONSE.
1795 lconn->OnReadPacket(rport->last_stun_buf()->data<char>(),
Niels Möllere6933812018-11-05 13:01:41 +01001796 rport->last_stun_buf()->size(), /* packet_time_us */ -1);
zhihuang5ecf16c2016-06-01 17:09:15 -07001797 // Verify the STUN Stats.
1798 EXPECT_EQ(1U, lconn->stats().sent_ping_requests_total);
1799 EXPECT_EQ(1U, lconn->stats().sent_ping_requests_before_first_response);
1800 EXPECT_EQ(1U, lconn->stats().recv_ping_responses);
1801 EXPECT_EQ(1U, rconn->stats().recv_ping_requests);
1802 EXPECT_EQ(1U, rconn->stats().sent_ping_responses);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001803
1804 EXPECT_FALSE(msg->IsLegacy());
Yves Gerey665174f2018-06-19 15:03:05 +02001805 const StunAddressAttribute* addr_attr =
1806 msg->GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001807 ASSERT_TRUE(addr_attr != NULL);
1808 EXPECT_EQ(lport->Candidates()[0].address(), addr_attr->GetAddress());
1809 EXPECT_TRUE(msg->GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001810 EXPECT_EQ(StunMessage::IntegrityStatus::kIntegrityOk,
1811 msg->ValidateMessageIntegrity("rpass"));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001812 EXPECT_TRUE(msg->GetUInt32(STUN_ATTR_FINGERPRINT) != NULL);
1813 EXPECT_TRUE(StunMessage::ValidateFingerprint(
jbauchf1f87202016-03-30 06:43:37 -07001814 lport->last_stun_buf()->data<char>(), lport->last_stun_buf()->size()));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001815 // No USERNAME or PRIORITY in ICE responses.
1816 EXPECT_TRUE(msg->GetByteString(STUN_ATTR_USERNAME) == NULL);
1817 EXPECT_TRUE(msg->GetByteString(STUN_ATTR_PRIORITY) == NULL);
1818 EXPECT_TRUE(msg->GetByteString(STUN_ATTR_MAPPED_ADDRESS) == NULL);
1819 EXPECT_TRUE(msg->GetByteString(STUN_ATTR_ICE_CONTROLLING) == NULL);
1820 EXPECT_TRUE(msg->GetByteString(STUN_ATTR_ICE_CONTROLLED) == NULL);
1821 EXPECT_TRUE(msg->GetByteString(STUN_ATTR_USE_CANDIDATE) == NULL);
1822
1823 // Response should not include ping count.
1824 ASSERT_TRUE(msg->GetUInt32(STUN_ATTR_RETRANSMIT_COUNT) == NULL);
1825
1826 // Respond with a BINDING-ERROR-RESPONSE. This wouldn't happen in real life,
1827 // but we can do it here.
Yves Gerey665174f2018-06-19 15:03:05 +02001828 rport->SendBindingErrorResponse(
1829 request.get(), lport->Candidates()[0].address(), STUN_ERROR_SERVER_ERROR,
1830 STUN_ERROR_REASON_SERVER_ERROR);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001831 msg = rport->last_stun_msg();
1832 ASSERT_TRUE(msg != NULL);
1833 EXPECT_EQ(STUN_BINDING_ERROR_RESPONSE, msg->type());
1834 EXPECT_FALSE(msg->IsLegacy());
1835 const StunErrorCodeAttribute* error_attr = msg->GetErrorCode();
1836 ASSERT_TRUE(error_attr != NULL);
1837 EXPECT_EQ(STUN_ERROR_SERVER_ERROR, error_attr->code());
1838 EXPECT_EQ(std::string(STUN_ERROR_REASON_SERVER_ERROR), error_attr->reason());
1839 EXPECT_TRUE(msg->GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
Harald Alvestrand07d83c82021-03-02 08:09:53 +00001840 EXPECT_EQ(StunMessage::IntegrityStatus::kIntegrityOk,
1841 msg->ValidateMessageIntegrity("rpass"));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001842 EXPECT_TRUE(msg->GetUInt32(STUN_ATTR_FINGERPRINT) != NULL);
1843 EXPECT_TRUE(StunMessage::ValidateFingerprint(
jbauchf1f87202016-03-30 06:43:37 -07001844 lport->last_stun_buf()->data<char>(), lport->last_stun_buf()->size()));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001845 // No USERNAME with ICE.
1846 EXPECT_TRUE(msg->GetByteString(STUN_ATTR_USERNAME) == NULL);
1847 EXPECT_TRUE(msg->GetByteString(STUN_ATTR_PRIORITY) == NULL);
1848
1849 // Testing STUN binding requests from rport --> lport, having ICE_CONTROLLED
1850 // and (incremented) RETRANSMIT_COUNT attributes.
1851 rport->Reset();
1852 rport->set_send_retransmit_count_attribute(true);
1853 rconn->Ping(0);
1854 rconn->Ping(0);
1855 rconn->Ping(0);
Honghai Zhang161a5862016-10-20 11:47:02 -07001856 ASSERT_TRUE_WAIT(rport->last_stun_msg() != NULL, kDefaultTimeout);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001857 msg = rport->last_stun_msg();
1858 EXPECT_EQ(STUN_BINDING_REQUEST, msg->type());
1859 const StunUInt64Attribute* ice_controlled_attr =
1860 msg->GetUInt64(STUN_ATTR_ICE_CONTROLLED);
1861 ASSERT_TRUE(ice_controlled_attr != NULL);
1862 EXPECT_EQ(rport->IceTiebreaker(), ice_controlled_attr->value());
1863 EXPECT_TRUE(msg->GetByteString(STUN_ATTR_USE_CANDIDATE) == NULL);
1864
1865 // Request should include ping count.
1866 const StunUInt32Attribute* retransmit_attr =
1867 msg->GetUInt32(STUN_ATTR_RETRANSMIT_COUNT);
1868 ASSERT_TRUE(retransmit_attr != NULL);
1869 EXPECT_EQ(2U, retransmit_attr->value());
1870
1871 // Respond with a BINDING-RESPONSE.
Steve Anton11358fe2018-10-09 15:39:19 -07001872 request = CopyStunMessage(*msg);
zhihuang5ecf16c2016-06-01 17:09:15 -07001873 lconn->OnReadPacket(rport->last_stun_buf()->data<char>(),
Niels Möllere6933812018-11-05 13:01:41 +01001874 rport->last_stun_buf()->size(), /* packet_time_us */ -1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001875 msg = lport->last_stun_msg();
zhihuang5ecf16c2016-06-01 17:09:15 -07001876 // Receive the BINDING-RESPONSE.
1877 rconn->OnReadPacket(lport->last_stun_buf()->data<char>(),
Niels Möllere6933812018-11-05 13:01:41 +01001878 lport->last_stun_buf()->size(), /* packet_time_us */ -1);
zhihuang5ecf16c2016-06-01 17:09:15 -07001879
1880 // Verify the Stun ping stats.
1881 EXPECT_EQ(3U, rconn->stats().sent_ping_requests_total);
1882 EXPECT_EQ(3U, rconn->stats().sent_ping_requests_before_first_response);
1883 EXPECT_EQ(1U, rconn->stats().recv_ping_responses);
1884 EXPECT_EQ(1U, lconn->stats().sent_ping_responses);
1885 EXPECT_EQ(1U, lconn->stats().recv_ping_requests);
1886 // Ping after receiver the first response
1887 rconn->Ping(0);
1888 rconn->Ping(0);
1889 EXPECT_EQ(5U, rconn->stats().sent_ping_requests_total);
1890 EXPECT_EQ(3U, rconn->stats().sent_ping_requests_before_first_response);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001891
1892 // Response should include same ping count.
1893 retransmit_attr = msg->GetUInt32(STUN_ATTR_RETRANSMIT_COUNT);
1894 ASSERT_TRUE(retransmit_attr != NULL);
1895 EXPECT_EQ(2U, retransmit_attr->value());
1896}
1897
hbos92eaec62017-02-27 01:38:08 -08001898TEST_F(PortTest, TestNomination) {
Steve Anton11358fe2018-10-09 15:39:19 -07001899 auto lport = CreateTestPort(kLocalAddr1, "lfrag", "lpass");
1900 auto rport = CreateTestPort(kLocalAddr2, "rfrag", "rpass");
hbos92eaec62017-02-27 01:38:08 -08001901 lport->SetIceRole(cricket::ICEROLE_CONTROLLING);
1902 lport->SetIceTiebreaker(kTiebreaker1);
1903 rport->SetIceRole(cricket::ICEROLE_CONTROLLED);
1904 rport->SetIceTiebreaker(kTiebreaker2);
1905
1906 lport->PrepareAddress();
1907 rport->PrepareAddress();
1908 ASSERT_FALSE(lport->Candidates().empty());
1909 ASSERT_FALSE(rport->Candidates().empty());
Yves Gerey665174f2018-06-19 15:03:05 +02001910 Connection* lconn =
1911 lport->CreateConnection(rport->Candidates()[0], Port::ORIGIN_MESSAGE);
1912 Connection* rconn =
1913 rport->CreateConnection(lport->Candidates()[0], Port::ORIGIN_MESSAGE);
hbos92eaec62017-02-27 01:38:08 -08001914
Artem Titov2dbb4c92021-07-26 15:12:41 +02001915 // `lconn` is controlling, `rconn` is controlled.
hbos92eaec62017-02-27 01:38:08 -08001916 uint32_t nomination = 1234;
1917 lconn->set_nomination(nomination);
1918
1919 EXPECT_FALSE(lconn->nominated());
1920 EXPECT_FALSE(rconn->nominated());
1921 EXPECT_EQ(lconn->nominated(), lconn->stats().nominated);
1922 EXPECT_EQ(rconn->nominated(), rconn->stats().nominated);
1923
Artem Titov2dbb4c92021-07-26 15:12:41 +02001924 // Send ping (including the nomination value) from `lconn` to `rconn`. This
1925 // should set the remote nomination of `rconn`.
hbos92eaec62017-02-27 01:38:08 -08001926 lconn->Ping(0);
1927 ASSERT_TRUE_WAIT(lport->last_stun_msg(), kDefaultTimeout);
1928 ASSERT_TRUE(lport->last_stun_buf());
1929 rconn->OnReadPacket(lport->last_stun_buf()->data<char>(),
Niels Möllere6933812018-11-05 13:01:41 +01001930 lport->last_stun_buf()->size(), /* packet_time_us */ -1);
hbos92eaec62017-02-27 01:38:08 -08001931 EXPECT_EQ(nomination, rconn->remote_nomination());
1932 EXPECT_FALSE(lconn->nominated());
1933 EXPECT_TRUE(rconn->nominated());
1934 EXPECT_EQ(lconn->nominated(), lconn->stats().nominated);
1935 EXPECT_EQ(rconn->nominated(), rconn->stats().nominated);
1936
Artem Titov2dbb4c92021-07-26 15:12:41 +02001937 // This should result in an acknowledgment sent back from `rconn` to `lconn`,
1938 // updating the acknowledged nomination of `lconn`.
hbos92eaec62017-02-27 01:38:08 -08001939 ASSERT_TRUE_WAIT(rport->last_stun_msg(), kDefaultTimeout);
1940 ASSERT_TRUE(rport->last_stun_buf());
1941 lconn->OnReadPacket(rport->last_stun_buf()->data<char>(),
Niels Möllere6933812018-11-05 13:01:41 +01001942 rport->last_stun_buf()->size(), /* packet_time_us */ -1);
hbos92eaec62017-02-27 01:38:08 -08001943 EXPECT_EQ(nomination, lconn->acked_nomination());
1944 EXPECT_TRUE(lconn->nominated());
1945 EXPECT_TRUE(rconn->nominated());
1946 EXPECT_EQ(lconn->nominated(), lconn->stats().nominated);
1947 EXPECT_EQ(rconn->nominated(), rconn->stats().nominated);
1948}
1949
hbosbf8d3e52017-02-28 06:34:47 -08001950TEST_F(PortTest, TestRoundTripTime) {
1951 rtc::ScopedFakeClock clock;
1952
Steve Anton11358fe2018-10-09 15:39:19 -07001953 auto lport = CreateTestPort(kLocalAddr1, "lfrag", "lpass");
1954 auto rport = CreateTestPort(kLocalAddr2, "rfrag", "rpass");
hbosbf8d3e52017-02-28 06:34:47 -08001955 lport->SetIceRole(cricket::ICEROLE_CONTROLLING);
1956 lport->SetIceTiebreaker(kTiebreaker1);
1957 rport->SetIceRole(cricket::ICEROLE_CONTROLLED);
1958 rport->SetIceTiebreaker(kTiebreaker2);
1959
1960 lport->PrepareAddress();
1961 rport->PrepareAddress();
1962 ASSERT_FALSE(lport->Candidates().empty());
1963 ASSERT_FALSE(rport->Candidates().empty());
Yves Gerey665174f2018-06-19 15:03:05 +02001964 Connection* lconn =
1965 lport->CreateConnection(rport->Candidates()[0], Port::ORIGIN_MESSAGE);
1966 Connection* rconn =
1967 rport->CreateConnection(lport->Candidates()[0], Port::ORIGIN_MESSAGE);
hbosbf8d3e52017-02-28 06:34:47 -08001968
1969 EXPECT_EQ(0u, lconn->stats().total_round_trip_time_ms);
1970 EXPECT_FALSE(lconn->stats().current_round_trip_time_ms);
1971
Yves Gerey665174f2018-06-19 15:03:05 +02001972 SendPingAndReceiveResponse(lconn, lport.get(), rconn, rport.get(), &clock,
1973 10);
hbosbf8d3e52017-02-28 06:34:47 -08001974 EXPECT_EQ(10u, lconn->stats().total_round_trip_time_ms);
1975 ASSERT_TRUE(lconn->stats().current_round_trip_time_ms);
1976 EXPECT_EQ(10u, *lconn->stats().current_round_trip_time_ms);
1977
Yves Gerey665174f2018-06-19 15:03:05 +02001978 SendPingAndReceiveResponse(lconn, lport.get(), rconn, rport.get(), &clock,
1979 20);
hbosbf8d3e52017-02-28 06:34:47 -08001980 EXPECT_EQ(30u, lconn->stats().total_round_trip_time_ms);
1981 ASSERT_TRUE(lconn->stats().current_round_trip_time_ms);
1982 EXPECT_EQ(20u, *lconn->stats().current_round_trip_time_ms);
1983
Yves Gerey665174f2018-06-19 15:03:05 +02001984 SendPingAndReceiveResponse(lconn, lport.get(), rconn, rport.get(), &clock,
1985 30);
hbosbf8d3e52017-02-28 06:34:47 -08001986 EXPECT_EQ(60u, lconn->stats().total_round_trip_time_ms);
1987 ASSERT_TRUE(lconn->stats().current_round_trip_time_ms);
1988 EXPECT_EQ(30u, *lconn->stats().current_round_trip_time_ms);
1989}
1990
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001991TEST_F(PortTest, TestUseCandidateAttribute) {
Steve Anton11358fe2018-10-09 15:39:19 -07001992 auto lport = CreateTestPort(kLocalAddr1, "lfrag", "lpass");
1993 auto rport = CreateTestPort(kLocalAddr2, "rfrag", "rpass");
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001994 lport->SetIceRole(cricket::ICEROLE_CONTROLLING);
1995 lport->SetIceTiebreaker(kTiebreaker1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001996 rport->SetIceRole(cricket::ICEROLE_CONTROLLED);
1997 rport->SetIceTiebreaker(kTiebreaker2);
1998
1999 // Send a fake ping from lport to rport.
2000 lport->PrepareAddress();
2001 rport->PrepareAddress();
2002 ASSERT_FALSE(rport->Candidates().empty());
Yves Gerey665174f2018-06-19 15:03:05 +02002003 Connection* lconn =
2004 lport->CreateConnection(rport->Candidates()[0], Port::ORIGIN_MESSAGE);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002005 lconn->Ping(0);
Honghai Zhang161a5862016-10-20 11:47:02 -07002006 ASSERT_TRUE_WAIT(lport->last_stun_msg() != NULL, kDefaultTimeout);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002007 IceMessage* msg = lport->last_stun_msg();
2008 const StunUInt64Attribute* ice_controlling_attr =
2009 msg->GetUInt64(STUN_ATTR_ICE_CONTROLLING);
2010 ASSERT_TRUE(ice_controlling_attr != NULL);
Yves Gerey665174f2018-06-19 15:03:05 +02002011 const StunByteStringAttribute* use_candidate_attr =
2012 msg->GetByteString(STUN_ATTR_USE_CANDIDATE);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002013 ASSERT_TRUE(use_candidate_attr != NULL);
2014}
2015
Honghai Zhang351d77b2016-05-20 15:08:29 -07002016// Tests that when the network type changes, the network cost of the port will
2017// change, the network cost of the local candidates will change. Also tests that
2018// the remote network costs are updated with the stun binding requests.
2019TEST_F(PortTest, TestNetworkCostChange) {
deadbeef5c3c1042017-08-04 15:01:57 -07002020 rtc::Network* test_network = MakeNetwork(kLocalAddr1);
Steve Anton11358fe2018-10-09 15:39:19 -07002021 auto lport = CreateTestPort(test_network, "lfrag", "lpass");
2022 auto rport = CreateTestPort(test_network, "rfrag", "rpass");
Honghai Zhang351d77b2016-05-20 15:08:29 -07002023 lport->SetIceRole(cricket::ICEROLE_CONTROLLING);
2024 lport->SetIceTiebreaker(kTiebreaker1);
2025 rport->SetIceRole(cricket::ICEROLE_CONTROLLED);
2026 rport->SetIceTiebreaker(kTiebreaker2);
2027 lport->PrepareAddress();
2028 rport->PrepareAddress();
2029
2030 // Default local port cost is rtc::kNetworkCostUnknown.
2031 EXPECT_EQ(rtc::kNetworkCostUnknown, lport->network_cost());
2032 ASSERT_TRUE(!lport->Candidates().empty());
2033 for (const cricket::Candidate& candidate : lport->Candidates()) {
2034 EXPECT_EQ(rtc::kNetworkCostUnknown, candidate.network_cost());
2035 }
2036
2037 // Change the network type to wifi.
deadbeef5c3c1042017-08-04 15:01:57 -07002038 test_network->set_type(rtc::ADAPTER_TYPE_WIFI);
Honghai Zhang351d77b2016-05-20 15:08:29 -07002039 EXPECT_EQ(rtc::kNetworkCostLow, lport->network_cost());
2040 for (const cricket::Candidate& candidate : lport->Candidates()) {
2041 EXPECT_EQ(rtc::kNetworkCostLow, candidate.network_cost());
2042 }
2043
2044 // Add a connection and then change the network type.
2045 Connection* lconn =
2046 lport->CreateConnection(rport->Candidates()[0], Port::ORIGIN_MESSAGE);
2047 // Change the network type to cellular.
deadbeef5c3c1042017-08-04 15:01:57 -07002048 test_network->set_type(rtc::ADAPTER_TYPE_CELLULAR);
Honghai Zhang351d77b2016-05-20 15:08:29 -07002049 EXPECT_EQ(rtc::kNetworkCostHigh, lport->network_cost());
2050 for (const cricket::Candidate& candidate : lport->Candidates()) {
2051 EXPECT_EQ(rtc::kNetworkCostHigh, candidate.network_cost());
2052 }
2053
deadbeef5c3c1042017-08-04 15:01:57 -07002054 test_network->set_type(rtc::ADAPTER_TYPE_WIFI);
Honghai Zhang351d77b2016-05-20 15:08:29 -07002055 Connection* rconn =
2056 rport->CreateConnection(lport->Candidates()[0], Port::ORIGIN_MESSAGE);
deadbeef5c3c1042017-08-04 15:01:57 -07002057 test_network->set_type(rtc::ADAPTER_TYPE_CELLULAR);
Honghai Zhang351d77b2016-05-20 15:08:29 -07002058 lconn->Ping(0);
2059 // The rconn's remote candidate cost is rtc::kNetworkCostLow, but the ping
2060 // contains an attribute of network cost of rtc::kNetworkCostHigh. Once the
2061 // message is handled in rconn, The rconn's remote candidate will have cost
2062 // rtc::kNetworkCostHigh;
2063 EXPECT_EQ(rtc::kNetworkCostLow, rconn->remote_candidate().network_cost());
Honghai Zhang161a5862016-10-20 11:47:02 -07002064 ASSERT_TRUE_WAIT(lport->last_stun_msg() != NULL, kDefaultTimeout);
Honghai Zhang351d77b2016-05-20 15:08:29 -07002065 IceMessage* msg = lport->last_stun_msg();
2066 EXPECT_EQ(STUN_BINDING_REQUEST, msg->type());
2067 // Pass the binding request to rport.
2068 rconn->OnReadPacket(lport->last_stun_buf()->data<char>(),
Niels Möllere6933812018-11-05 13:01:41 +01002069 lport->last_stun_buf()->size(), /* packet_time_us */ -1);
Honghai Zhang351d77b2016-05-20 15:08:29 -07002070 // Wait until rport sends the response and then check the remote network cost.
Honghai Zhang161a5862016-10-20 11:47:02 -07002071 ASSERT_TRUE_WAIT(rport->last_stun_msg() != NULL, kDefaultTimeout);
Honghai Zhang351d77b2016-05-20 15:08:29 -07002072 EXPECT_EQ(rtc::kNetworkCostHigh, rconn->remote_candidate().network_cost());
2073}
2074
honghaiza0c44ea2016-03-23 16:07:48 -07002075TEST_F(PortTest, TestNetworkInfoAttribute) {
deadbeef5c3c1042017-08-04 15:01:57 -07002076 rtc::Network* test_network = MakeNetwork(kLocalAddr1);
Steve Anton11358fe2018-10-09 15:39:19 -07002077 auto lport = CreateTestPort(test_network, "lfrag", "lpass");
2078 auto rport = CreateTestPort(test_network, "rfrag", "rpass");
honghaiza0c44ea2016-03-23 16:07:48 -07002079 lport->SetIceRole(cricket::ICEROLE_CONTROLLING);
2080 lport->SetIceTiebreaker(kTiebreaker1);
2081 rport->SetIceRole(cricket::ICEROLE_CONTROLLED);
2082 rport->SetIceTiebreaker(kTiebreaker2);
2083
2084 uint16_t lnetwork_id = 9;
2085 lport->Network()->set_id(lnetwork_id);
2086 // Send a fake ping from lport to rport.
2087 lport->PrepareAddress();
2088 rport->PrepareAddress();
2089 Connection* lconn =
2090 lport->CreateConnection(rport->Candidates()[0], Port::ORIGIN_MESSAGE);
2091 lconn->Ping(0);
Honghai Zhang161a5862016-10-20 11:47:02 -07002092 ASSERT_TRUE_WAIT(lport->last_stun_msg() != NULL, kDefaultTimeout);
honghaiza0c44ea2016-03-23 16:07:48 -07002093 IceMessage* msg = lport->last_stun_msg();
2094 const StunUInt32Attribute* network_info_attr =
Jonas Orelandfa543642020-09-16 10:44:54 +02002095 msg->GetUInt32(STUN_ATTR_GOOG_NETWORK_INFO);
honghaiza0c44ea2016-03-23 16:07:48 -07002096 ASSERT_TRUE(network_info_attr != NULL);
2097 uint32_t network_info = network_info_attr->value();
2098 EXPECT_EQ(lnetwork_id, network_info >> 16);
Honghai Zhang351d77b2016-05-20 15:08:29 -07002099 // Default network has unknown type and cost kNetworkCostUnknown.
2100 EXPECT_EQ(rtc::kNetworkCostUnknown, network_info & 0xFFFF);
honghaiza0c44ea2016-03-23 16:07:48 -07002101
Honghai Zhang351d77b2016-05-20 15:08:29 -07002102 // Set the network type to be cellular so its cost will be kNetworkCostHigh.
honghaiza0c44ea2016-03-23 16:07:48 -07002103 // Send a fake ping from rport to lport.
deadbeef5c3c1042017-08-04 15:01:57 -07002104 test_network->set_type(rtc::ADAPTER_TYPE_CELLULAR);
honghaiza0c44ea2016-03-23 16:07:48 -07002105 uint16_t rnetwork_id = 8;
2106 rport->Network()->set_id(rnetwork_id);
2107 Connection* rconn =
2108 rport->CreateConnection(lport->Candidates()[0], Port::ORIGIN_MESSAGE);
2109 rconn->Ping(0);
Honghai Zhang161a5862016-10-20 11:47:02 -07002110 ASSERT_TRUE_WAIT(rport->last_stun_msg() != NULL, kDefaultTimeout);
honghaiza0c44ea2016-03-23 16:07:48 -07002111 msg = rport->last_stun_msg();
Jonas Orelandfa543642020-09-16 10:44:54 +02002112 network_info_attr = msg->GetUInt32(STUN_ATTR_GOOG_NETWORK_INFO);
honghaiza0c44ea2016-03-23 16:07:48 -07002113 ASSERT_TRUE(network_info_attr != NULL);
2114 network_info = network_info_attr->value();
2115 EXPECT_EQ(rnetwork_id, network_info >> 16);
Honghai Zhang351d77b2016-05-20 15:08:29 -07002116 EXPECT_EQ(rtc::kNetworkCostHigh, network_info & 0xFFFF);
honghaiza0c44ea2016-03-23 16:07:48 -07002117}
2118
Peter Thatcher7cbd1882015-09-17 18:54:52 -07002119// Test handling STUN messages.
2120TEST_F(PortTest, TestHandleStunMessage) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002121 // Our port will act as the "remote" port.
Steve Anton11358fe2018-10-09 15:39:19 -07002122 auto port = CreateTestPort(kLocalAddr2, "rfrag", "rpass");
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002123
kwiberg3ec46792016-04-27 07:22:53 -07002124 std::unique_ptr<IceMessage> in_msg, out_msg;
Mirko Bonadei317a1f02019-09-17 17:06:18 +02002125 auto buf = std::make_unique<ByteBufferWriter>();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002126 rtc::SocketAddress addr(kLocalAddr1);
2127 std::string username;
2128
2129 // BINDING-REQUEST from local to remote with valid ICE username,
2130 // MESSAGE-INTEGRITY, and FINGERPRINT.
Steve Anton11358fe2018-10-09 15:39:19 -07002131 in_msg = CreateStunMessageWithUsername(STUN_BINDING_REQUEST, "rfrag:lfrag");
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002132 in_msg->AddMessageIntegrity("rpass");
2133 in_msg->AddFingerprint();
Steve Anton11358fe2018-10-09 15:39:19 -07002134 WriteStunMessage(*in_msg, buf.get());
kwiberg6baec032016-03-15 11:09:39 -07002135 EXPECT_TRUE(port->GetStunMessage(buf->Data(), buf->Length(), addr, &out_msg,
2136 &username));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002137 EXPECT_TRUE(out_msg.get() != NULL);
2138 EXPECT_EQ("lfrag", username);
2139
2140 // BINDING-RESPONSE without username, with MESSAGE-INTEGRITY and FINGERPRINT.
Steve Anton11358fe2018-10-09 15:39:19 -07002141 in_msg = CreateStunMessage(STUN_BINDING_RESPONSE);
Mirko Bonadei317a1f02019-09-17 17:06:18 +02002142 in_msg->AddAttribute(std::make_unique<StunXorAddressAttribute>(
zsteinf42cc9d2017-03-27 16:17:19 -07002143 STUN_ATTR_XOR_MAPPED_ADDRESS, kLocalAddr2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002144 in_msg->AddMessageIntegrity("rpass");
2145 in_msg->AddFingerprint();
Steve Anton11358fe2018-10-09 15:39:19 -07002146 WriteStunMessage(*in_msg, buf.get());
kwiberg6baec032016-03-15 11:09:39 -07002147 EXPECT_TRUE(port->GetStunMessage(buf->Data(), buf->Length(), addr, &out_msg,
2148 &username));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002149 EXPECT_TRUE(out_msg.get() != NULL);
2150 EXPECT_EQ("", username);
2151
2152 // BINDING-ERROR-RESPONSE without username, with error, M-I, and FINGERPRINT.
Steve Anton11358fe2018-10-09 15:39:19 -07002153 in_msg = CreateStunMessage(STUN_BINDING_ERROR_RESPONSE);
Mirko Bonadei317a1f02019-09-17 17:06:18 +02002154 in_msg->AddAttribute(std::make_unique<StunErrorCodeAttribute>(
zsteinf42cc9d2017-03-27 16:17:19 -07002155 STUN_ATTR_ERROR_CODE, STUN_ERROR_SERVER_ERROR,
2156 STUN_ERROR_REASON_SERVER_ERROR));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002157 in_msg->AddFingerprint();
Steve Anton11358fe2018-10-09 15:39:19 -07002158 WriteStunMessage(*in_msg, buf.get());
kwiberg6baec032016-03-15 11:09:39 -07002159 EXPECT_TRUE(port->GetStunMessage(buf->Data(), buf->Length(), addr, &out_msg,
2160 &username));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002161 EXPECT_TRUE(out_msg.get() != NULL);
2162 EXPECT_EQ("", username);
2163 ASSERT_TRUE(out_msg->GetErrorCode() != NULL);
2164 EXPECT_EQ(STUN_ERROR_SERVER_ERROR, out_msg->GetErrorCode()->code());
2165 EXPECT_EQ(std::string(STUN_ERROR_REASON_SERVER_ERROR),
Yves Gerey665174f2018-06-19 15:03:05 +02002166 out_msg->GetErrorCode()->reason());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002167}
2168
guoweisd12140a2015-09-10 13:32:11 -07002169// Tests handling of ICE binding requests with missing or incorrect usernames.
Peter Thatcher7cbd1882015-09-17 18:54:52 -07002170TEST_F(PortTest, TestHandleStunMessageBadUsername) {
Steve Anton11358fe2018-10-09 15:39:19 -07002171 auto port = CreateTestPort(kLocalAddr2, "rfrag", "rpass");
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002172
kwiberg3ec46792016-04-27 07:22:53 -07002173 std::unique_ptr<IceMessage> in_msg, out_msg;
Mirko Bonadei317a1f02019-09-17 17:06:18 +02002174 auto buf = std::make_unique<ByteBufferWriter>();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002175 rtc::SocketAddress addr(kLocalAddr1);
2176 std::string username;
2177
2178 // BINDING-REQUEST with no username.
Steve Anton11358fe2018-10-09 15:39:19 -07002179 in_msg = CreateStunMessage(STUN_BINDING_REQUEST);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002180 in_msg->AddMessageIntegrity("rpass");
2181 in_msg->AddFingerprint();
Steve Anton11358fe2018-10-09 15:39:19 -07002182 WriteStunMessage(*in_msg, buf.get());
kwiberg6baec032016-03-15 11:09:39 -07002183 EXPECT_TRUE(port->GetStunMessage(buf->Data(), buf->Length(), addr, &out_msg,
2184 &username));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002185 EXPECT_TRUE(out_msg.get() == NULL);
2186 EXPECT_EQ("", username);
2187 EXPECT_EQ(STUN_ERROR_BAD_REQUEST, port->last_stun_error_code());
2188
2189 // BINDING-REQUEST with empty username.
Steve Anton11358fe2018-10-09 15:39:19 -07002190 in_msg = CreateStunMessageWithUsername(STUN_BINDING_REQUEST, "");
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002191 in_msg->AddMessageIntegrity("rpass");
2192 in_msg->AddFingerprint();
Steve Anton11358fe2018-10-09 15:39:19 -07002193 WriteStunMessage(*in_msg, buf.get());
kwiberg6baec032016-03-15 11:09:39 -07002194 EXPECT_TRUE(port->GetStunMessage(buf->Data(), buf->Length(), addr, &out_msg,
2195 &username));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002196 EXPECT_TRUE(out_msg.get() == NULL);
2197 EXPECT_EQ("", username);
2198 EXPECT_EQ(STUN_ERROR_UNAUTHORIZED, port->last_stun_error_code());
2199
2200 // BINDING-REQUEST with too-short username.
Steve Anton11358fe2018-10-09 15:39:19 -07002201 in_msg = CreateStunMessageWithUsername(STUN_BINDING_REQUEST, "rfra");
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002202 in_msg->AddMessageIntegrity("rpass");
2203 in_msg->AddFingerprint();
Steve Anton11358fe2018-10-09 15:39:19 -07002204 WriteStunMessage(*in_msg, buf.get());
kwiberg6baec032016-03-15 11:09:39 -07002205 EXPECT_TRUE(port->GetStunMessage(buf->Data(), buf->Length(), addr, &out_msg,
2206 &username));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002207 EXPECT_TRUE(out_msg.get() == NULL);
2208 EXPECT_EQ("", username);
2209 EXPECT_EQ(STUN_ERROR_UNAUTHORIZED, port->last_stun_error_code());
2210
2211 // BINDING-REQUEST with reversed username.
Steve Anton11358fe2018-10-09 15:39:19 -07002212 in_msg = CreateStunMessageWithUsername(STUN_BINDING_REQUEST, "lfrag:rfrag");
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002213 in_msg->AddMessageIntegrity("rpass");
2214 in_msg->AddFingerprint();
Steve Anton11358fe2018-10-09 15:39:19 -07002215 WriteStunMessage(*in_msg, buf.get());
kwiberg6baec032016-03-15 11:09:39 -07002216 EXPECT_TRUE(port->GetStunMessage(buf->Data(), buf->Length(), addr, &out_msg,
2217 &username));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002218 EXPECT_TRUE(out_msg.get() == NULL);
2219 EXPECT_EQ("", username);
2220 EXPECT_EQ(STUN_ERROR_UNAUTHORIZED, port->last_stun_error_code());
2221
2222 // BINDING-REQUEST with garbage username.
Steve Anton11358fe2018-10-09 15:39:19 -07002223 in_msg = CreateStunMessageWithUsername(STUN_BINDING_REQUEST, "abcd:efgh");
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002224 in_msg->AddMessageIntegrity("rpass");
2225 in_msg->AddFingerprint();
Steve Anton11358fe2018-10-09 15:39:19 -07002226 WriteStunMessage(*in_msg, buf.get());
kwiberg6baec032016-03-15 11:09:39 -07002227 EXPECT_TRUE(port->GetStunMessage(buf->Data(), buf->Length(), addr, &out_msg,
2228 &username));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002229 EXPECT_TRUE(out_msg.get() == NULL);
2230 EXPECT_EQ("", username);
2231 EXPECT_EQ(STUN_ERROR_UNAUTHORIZED, port->last_stun_error_code());
2232}
2233
Peter Thatcher7cbd1882015-09-17 18:54:52 -07002234// Test handling STUN messages with missing or malformed M-I.
2235TEST_F(PortTest, TestHandleStunMessageBadMessageIntegrity) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002236 // Our port will act as the "remote" port.
Steve Anton11358fe2018-10-09 15:39:19 -07002237 auto port = CreateTestPort(kLocalAddr2, "rfrag", "rpass");
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002238
kwiberg3ec46792016-04-27 07:22:53 -07002239 std::unique_ptr<IceMessage> in_msg, out_msg;
Mirko Bonadei317a1f02019-09-17 17:06:18 +02002240 auto buf = std::make_unique<ByteBufferWriter>();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002241 rtc::SocketAddress addr(kLocalAddr1);
2242 std::string username;
2243
2244 // BINDING-REQUEST from local to remote with valid ICE username and
2245 // FINGERPRINT, but no MESSAGE-INTEGRITY.
Steve Anton11358fe2018-10-09 15:39:19 -07002246 in_msg = CreateStunMessageWithUsername(STUN_BINDING_REQUEST, "rfrag:lfrag");
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002247 in_msg->AddFingerprint();
Steve Anton11358fe2018-10-09 15:39:19 -07002248 WriteStunMessage(*in_msg, buf.get());
kwiberg6baec032016-03-15 11:09:39 -07002249 EXPECT_TRUE(port->GetStunMessage(buf->Data(), buf->Length(), addr, &out_msg,
2250 &username));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002251 EXPECT_TRUE(out_msg.get() == NULL);
2252 EXPECT_EQ("", username);
2253 EXPECT_EQ(STUN_ERROR_BAD_REQUEST, port->last_stun_error_code());
2254
2255 // BINDING-REQUEST from local to remote with valid ICE username and
2256 // FINGERPRINT, but invalid MESSAGE-INTEGRITY.
Steve Anton11358fe2018-10-09 15:39:19 -07002257 in_msg = CreateStunMessageWithUsername(STUN_BINDING_REQUEST, "rfrag:lfrag");
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002258 in_msg->AddMessageIntegrity("invalid");
2259 in_msg->AddFingerprint();
Steve Anton11358fe2018-10-09 15:39:19 -07002260 WriteStunMessage(*in_msg, buf.get());
kwiberg6baec032016-03-15 11:09:39 -07002261 EXPECT_TRUE(port->GetStunMessage(buf->Data(), buf->Length(), addr, &out_msg,
2262 &username));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002263 EXPECT_TRUE(out_msg.get() == NULL);
2264 EXPECT_EQ("", username);
2265 EXPECT_EQ(STUN_ERROR_UNAUTHORIZED, port->last_stun_error_code());
2266
Steve Antonbabf9172017-11-29 10:19:02 -08002267 // TODO(?): BINDING-RESPONSES and BINDING-ERROR-RESPONSES are checked
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002268 // by the Connection, not the Port, since they require the remote username.
2269 // Change this test to pass in data via Connection::OnReadPacket instead.
2270}
2271
Peter Thatcher7cbd1882015-09-17 18:54:52 -07002272// Test handling STUN messages with missing or malformed FINGERPRINT.
2273TEST_F(PortTest, TestHandleStunMessageBadFingerprint) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002274 // Our port will act as the "remote" port.
Steve Anton11358fe2018-10-09 15:39:19 -07002275 auto port = CreateTestPort(kLocalAddr2, "rfrag", "rpass");
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002276
kwiberg3ec46792016-04-27 07:22:53 -07002277 std::unique_ptr<IceMessage> in_msg, out_msg;
Mirko Bonadei317a1f02019-09-17 17:06:18 +02002278 auto buf = std::make_unique<ByteBufferWriter>();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002279 rtc::SocketAddress addr(kLocalAddr1);
2280 std::string username;
2281
2282 // BINDING-REQUEST from local to remote with valid ICE username and
2283 // MESSAGE-INTEGRITY, but no FINGERPRINT; GetStunMessage should fail.
Steve Anton11358fe2018-10-09 15:39:19 -07002284 in_msg = CreateStunMessageWithUsername(STUN_BINDING_REQUEST, "rfrag:lfrag");
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002285 in_msg->AddMessageIntegrity("rpass");
Steve Anton11358fe2018-10-09 15:39:19 -07002286 WriteStunMessage(*in_msg, buf.get());
kwiberg6baec032016-03-15 11:09:39 -07002287 EXPECT_FALSE(port->GetStunMessage(buf->Data(), buf->Length(), addr, &out_msg,
2288 &username));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002289 EXPECT_EQ(0, port->last_stun_error_code());
2290
2291 // Now, add a fingerprint, but munge the message so it's not valid.
2292 in_msg->AddFingerprint();
2293 in_msg->SetTransactionID("TESTTESTBADD");
Steve Anton11358fe2018-10-09 15:39:19 -07002294 WriteStunMessage(*in_msg, buf.get());
kwiberg6baec032016-03-15 11:09:39 -07002295 EXPECT_FALSE(port->GetStunMessage(buf->Data(), buf->Length(), addr, &out_msg,
2296 &username));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002297 EXPECT_EQ(0, port->last_stun_error_code());
2298
2299 // Valid BINDING-RESPONSE, except no FINGERPRINT.
Steve Anton11358fe2018-10-09 15:39:19 -07002300 in_msg = CreateStunMessage(STUN_BINDING_RESPONSE);
Mirko Bonadei317a1f02019-09-17 17:06:18 +02002301 in_msg->AddAttribute(std::make_unique<StunXorAddressAttribute>(
zsteinf42cc9d2017-03-27 16:17:19 -07002302 STUN_ATTR_XOR_MAPPED_ADDRESS, kLocalAddr2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002303 in_msg->AddMessageIntegrity("rpass");
Steve Anton11358fe2018-10-09 15:39:19 -07002304 WriteStunMessage(*in_msg, buf.get());
kwiberg6baec032016-03-15 11:09:39 -07002305 EXPECT_FALSE(port->GetStunMessage(buf->Data(), buf->Length(), addr, &out_msg,
2306 &username));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002307 EXPECT_EQ(0, port->last_stun_error_code());
2308
2309 // Now, add a fingerprint, but munge the message so it's not valid.
2310 in_msg->AddFingerprint();
2311 in_msg->SetTransactionID("TESTTESTBADD");
Steve Anton11358fe2018-10-09 15:39:19 -07002312 WriteStunMessage(*in_msg, buf.get());
kwiberg6baec032016-03-15 11:09:39 -07002313 EXPECT_FALSE(port->GetStunMessage(buf->Data(), buf->Length(), addr, &out_msg,
2314 &username));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002315 EXPECT_EQ(0, port->last_stun_error_code());
2316
2317 // Valid BINDING-ERROR-RESPONSE, except no FINGERPRINT.
Steve Anton11358fe2018-10-09 15:39:19 -07002318 in_msg = CreateStunMessage(STUN_BINDING_ERROR_RESPONSE);
Mirko Bonadei317a1f02019-09-17 17:06:18 +02002319 in_msg->AddAttribute(std::make_unique<StunErrorCodeAttribute>(
zsteinf42cc9d2017-03-27 16:17:19 -07002320 STUN_ATTR_ERROR_CODE, STUN_ERROR_SERVER_ERROR,
2321 STUN_ERROR_REASON_SERVER_ERROR));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002322 in_msg->AddMessageIntegrity("rpass");
Steve Anton11358fe2018-10-09 15:39:19 -07002323 WriteStunMessage(*in_msg, buf.get());
kwiberg6baec032016-03-15 11:09:39 -07002324 EXPECT_FALSE(port->GetStunMessage(buf->Data(), buf->Length(), addr, &out_msg,
2325 &username));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002326 EXPECT_EQ(0, port->last_stun_error_code());
2327
2328 // Now, add a fingerprint, but munge the message so it's not valid.
2329 in_msg->AddFingerprint();
2330 in_msg->SetTransactionID("TESTTESTBADD");
Steve Anton11358fe2018-10-09 15:39:19 -07002331 WriteStunMessage(*in_msg, buf.get());
kwiberg6baec032016-03-15 11:09:39 -07002332 EXPECT_FALSE(port->GetStunMessage(buf->Data(), buf->Length(), addr, &out_msg,
2333 &username));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002334 EXPECT_EQ(0, port->last_stun_error_code());
2335}
2336
Taylor Brandstetterfb4351b2020-03-23 16:00:31 -07002337// Test handling a STUN message with unknown attributes in the
2338// "comprehension-required" range. Should respond with an error with the
2339// unknown attributes' IDs.
2340TEST_F(PortTest,
2341 TestHandleStunRequestWithUnknownComprehensionRequiredAttribute) {
2342 // Our port will act as the "remote" port.
2343 std::unique_ptr<TestPort> port(CreateTestPort(kLocalAddr2, "rfrag", "rpass"));
2344
2345 std::unique_ptr<IceMessage> in_msg, out_msg;
2346 auto buf = std::make_unique<ByteBufferWriter>();
2347 rtc::SocketAddress addr(kLocalAddr1);
2348 std::string username;
2349
2350 // Build ordinary message with valid ufrag/pass.
2351 in_msg = CreateStunMessageWithUsername(STUN_BINDING_REQUEST, "rfrag:lfrag");
2352 in_msg->AddMessageIntegrity("rpass");
2353 // Add a couple attributes with ID in comprehension-required range.
2354 in_msg->AddAttribute(StunAttribute::CreateUInt32(0x7777));
2355 in_msg->AddAttribute(StunAttribute::CreateUInt32(0x4567));
2356 // ... And one outside the range.
2357 in_msg->AddAttribute(StunAttribute::CreateUInt32(0xdead));
2358 in_msg->AddFingerprint();
2359 WriteStunMessage(*in_msg, buf.get());
2360 ASSERT_TRUE(port->GetStunMessage(buf->Data(), buf->Length(), addr, &out_msg,
2361 &username));
2362 IceMessage* error_response = port->last_stun_msg();
2363 ASSERT_NE(nullptr, error_response);
2364
2365 // Verify that the "unknown attribute" error response has the right error
2366 // code, and includes an attribute that lists out the unrecognized attribute
2367 // types.
2368 EXPECT_EQ(STUN_ERROR_UNKNOWN_ATTRIBUTE, error_response->GetErrorCodeValue());
2369 const StunUInt16ListAttribute* unknown_attributes =
2370 error_response->GetUnknownAttributes();
2371 ASSERT_NE(nullptr, unknown_attributes);
2372 ASSERT_EQ(2u, unknown_attributes->Size());
2373 EXPECT_EQ(0x7777, unknown_attributes->GetType(0));
2374 EXPECT_EQ(0x4567, unknown_attributes->GetType(1));
2375}
2376
2377// Similar to the above, but with a response instead of a request. In this
2378// case the response should just be ignored and transaction treated is failed.
2379TEST_F(PortTest,
2380 TestHandleStunResponseWithUnknownComprehensionRequiredAttribute) {
2381 // Generic setup.
2382 auto lport = CreateTestPort(kLocalAddr1, "lfrag", "lpass");
2383 lport->SetIceRole(cricket::ICEROLE_CONTROLLING);
2384 auto rport = CreateTestPort(kLocalAddr2, "rfrag", "rpass");
2385 rport->SetIceRole(cricket::ICEROLE_CONTROLLED);
2386 lport->PrepareAddress();
2387 rport->PrepareAddress();
2388 ASSERT_FALSE(lport->Candidates().empty());
2389 ASSERT_FALSE(rport->Candidates().empty());
2390 Connection* lconn =
2391 lport->CreateConnection(rport->Candidates()[0], Port::ORIGIN_MESSAGE);
2392 Connection* rconn =
2393 rport->CreateConnection(lport->Candidates()[0], Port::ORIGIN_MESSAGE);
2394
2395 // Send request.
2396 lconn->Ping(0);
2397 ASSERT_TRUE_WAIT(lport->last_stun_msg() != NULL, kDefaultTimeout);
2398 rconn->OnReadPacket(lport->last_stun_buf()->data<char>(),
2399 lport->last_stun_buf()->size(), /* packet_time_us */ -1);
2400
2401 // Intercept request and add comprehension required attribute.
2402 ASSERT_TRUE_WAIT(rport->last_stun_msg() != NULL, kDefaultTimeout);
2403 auto modified_response = rport->last_stun_msg()->Clone();
2404 modified_response->AddAttribute(StunAttribute::CreateUInt32(0x7777));
2405 modified_response->RemoveAttribute(STUN_ATTR_FINGERPRINT);
2406 modified_response->AddFingerprint();
2407 ByteBufferWriter buf;
2408 WriteStunMessage(*modified_response, &buf);
2409 lconn->OnReadPacket(buf.Data(), buf.Length(), /* packet_time_us */ -1);
2410 // Response should have been ignored, leaving us unwritable still.
2411 EXPECT_FALSE(lconn->writable());
2412}
2413
2414// Similar to the above, but with an indication. As with a response, it should
2415// just be ignored.
2416TEST_F(PortTest,
2417 TestHandleStunIndicationWithUnknownComprehensionRequiredAttribute) {
2418 // Generic set up.
2419 auto lport = CreateTestPort(kLocalAddr2, "lfrag", "lpass");
2420 lport->SetIceRole(cricket::ICEROLE_CONTROLLING);
2421 auto rport = CreateTestPort(kLocalAddr2, "rfrag", "rpass");
2422 rport->SetIceRole(cricket::ICEROLE_CONTROLLED);
2423 lport->PrepareAddress();
2424 rport->PrepareAddress();
2425 ASSERT_FALSE(lport->Candidates().empty());
2426 ASSERT_FALSE(rport->Candidates().empty());
2427 Connection* lconn =
2428 lport->CreateConnection(rport->Candidates()[0], Port::ORIGIN_MESSAGE);
2429
2430 // Generate indication with comprehension required attribute and verify it
2431 // doesn't update last_ping_received.
2432 auto in_msg = CreateStunMessage(STUN_BINDING_INDICATION);
2433 in_msg->AddAttribute(StunAttribute::CreateUInt32(0x7777));
2434 in_msg->AddFingerprint();
2435 ByteBufferWriter buf;
2436 WriteStunMessage(*in_msg, &buf);
2437 lconn->OnReadPacket(buf.Data(), buf.Length(), /* packet_time_us */ -1);
2438 EXPECT_EQ(0u, lconn->last_ping_received());
2439}
2440
Peter Thatcher7cbd1882015-09-17 18:54:52 -07002441// Test handling of STUN binding indication messages . STUN binding
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002442// indications are allowed only to the connection which is in read mode.
2443TEST_F(PortTest, TestHandleStunBindingIndication) {
Steve Anton11358fe2018-10-09 15:39:19 -07002444 auto lport = CreateTestPort(kLocalAddr2, "lfrag", "lpass");
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002445 lport->SetIceRole(cricket::ICEROLE_CONTROLLING);
2446 lport->SetIceTiebreaker(kTiebreaker1);
2447
2448 // Verifying encoding and decoding STUN indication message.
kwiberg3ec46792016-04-27 07:22:53 -07002449 std::unique_ptr<IceMessage> in_msg, out_msg;
2450 std::unique_ptr<ByteBufferWriter> buf(new ByteBufferWriter());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002451 rtc::SocketAddress addr(kLocalAddr1);
2452 std::string username;
2453
Steve Anton11358fe2018-10-09 15:39:19 -07002454 in_msg = CreateStunMessage(STUN_BINDING_INDICATION);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002455 in_msg->AddFingerprint();
Steve Anton11358fe2018-10-09 15:39:19 -07002456 WriteStunMessage(*in_msg, buf.get());
kwiberg6baec032016-03-15 11:09:39 -07002457 EXPECT_TRUE(lport->GetStunMessage(buf->Data(), buf->Length(), addr, &out_msg,
2458 &username));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002459 EXPECT_TRUE(out_msg.get() != NULL);
2460 EXPECT_EQ(out_msg->type(), STUN_BINDING_INDICATION);
2461 EXPECT_EQ("", username);
2462
2463 // Verify connection can handle STUN indication and updates
2464 // last_ping_received.
Steve Anton11358fe2018-10-09 15:39:19 -07002465 auto rport = CreateTestPort(kLocalAddr2, "rfrag", "rpass");
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002466 rport->SetIceRole(cricket::ICEROLE_CONTROLLED);
2467 rport->SetIceTiebreaker(kTiebreaker2);
2468
2469 lport->PrepareAddress();
2470 rport->PrepareAddress();
2471 ASSERT_FALSE(lport->Candidates().empty());
2472 ASSERT_FALSE(rport->Candidates().empty());
2473
Yves Gerey665174f2018-06-19 15:03:05 +02002474 Connection* lconn =
2475 lport->CreateConnection(rport->Candidates()[0], Port::ORIGIN_MESSAGE);
2476 Connection* rconn =
2477 rport->CreateConnection(lport->Candidates()[0], Port::ORIGIN_MESSAGE);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002478 rconn->Ping(0);
2479
Honghai Zhang161a5862016-10-20 11:47:02 -07002480 ASSERT_TRUE_WAIT(rport->last_stun_msg() != NULL, kDefaultTimeout);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002481 IceMessage* msg = rport->last_stun_msg();
2482 EXPECT_EQ(STUN_BINDING_REQUEST, msg->type());
2483 // Send rport binding request to lport.
jbauchf1f87202016-03-30 06:43:37 -07002484 lconn->OnReadPacket(rport->last_stun_buf()->data<char>(),
Niels Möllere6933812018-11-05 13:01:41 +01002485 rport->last_stun_buf()->size(), /* packet_time_us */ -1);
Honghai Zhang161a5862016-10-20 11:47:02 -07002486 ASSERT_TRUE_WAIT(lport->last_stun_msg() != NULL, kDefaultTimeout);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002487 EXPECT_EQ(STUN_BINDING_RESPONSE, lport->last_stun_msg()->type());
honghaiz34b11eb2016-03-16 08:55:44 -07002488 int64_t last_ping_received1 = lconn->last_ping_received();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002489
2490 // Adding a delay of 100ms.
2491 rtc::Thread::Current()->ProcessMessages(100);
2492 // Pinging lconn using stun indication message.
Niels Möllere6933812018-11-05 13:01:41 +01002493 lconn->OnReadPacket(buf->Data(), buf->Length(), /* packet_time_us */ -1);
honghaiz34b11eb2016-03-16 08:55:44 -07002494 int64_t last_ping_received2 = lconn->last_ping_received();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002495 EXPECT_GT(last_ping_received2, last_ping_received1);
2496}
2497
2498TEST_F(PortTest, TestComputeCandidatePriority) {
Steve Anton11358fe2018-10-09 15:39:19 -07002499 auto port = CreateTestPort(kLocalAddr1, "name", "pass");
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002500 port->set_type_preference(90);
2501 port->set_component(177);
2502 port->AddCandidateAddress(SocketAddress("192.168.1.4", 1234));
2503 port->AddCandidateAddress(SocketAddress("2001:db8::1234", 1234));
2504 port->AddCandidateAddress(SocketAddress("fc12:3456::1234", 1234));
2505 port->AddCandidateAddress(SocketAddress("::ffff:192.168.1.4", 1234));
2506 port->AddCandidateAddress(SocketAddress("::192.168.1.4", 1234));
2507 port->AddCandidateAddress(SocketAddress("2002::1234:5678", 1234));
2508 port->AddCandidateAddress(SocketAddress("2001::1234:5678", 1234));
2509 port->AddCandidateAddress(SocketAddress("fecf::1234:5678", 1234));
2510 port->AddCandidateAddress(SocketAddress("3ffe::1234:5678", 1234));
2511 // These should all be:
2512 // (90 << 24) | ([rfc3484 pref value] << 8) | (256 - 177)
Peter Boström0c4e06b2015-10-07 12:23:21 +02002513 uint32_t expected_priority_v4 = 1509957199U;
2514 uint32_t expected_priority_v6 = 1509959759U;
2515 uint32_t expected_priority_ula = 1509962319U;
2516 uint32_t expected_priority_v4mapped = expected_priority_v4;
2517 uint32_t expected_priority_v4compat = 1509949775U;
2518 uint32_t expected_priority_6to4 = 1509954639U;
2519 uint32_t expected_priority_teredo = 1509952079U;
2520 uint32_t expected_priority_sitelocal = 1509949775U;
2521 uint32_t expected_priority_6bone = 1509949775U;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002522 ASSERT_EQ(expected_priority_v4, port->Candidates()[0].priority());
2523 ASSERT_EQ(expected_priority_v6, port->Candidates()[1].priority());
2524 ASSERT_EQ(expected_priority_ula, port->Candidates()[2].priority());
2525 ASSERT_EQ(expected_priority_v4mapped, port->Candidates()[3].priority());
2526 ASSERT_EQ(expected_priority_v4compat, port->Candidates()[4].priority());
2527 ASSERT_EQ(expected_priority_6to4, port->Candidates()[5].priority());
2528 ASSERT_EQ(expected_priority_teredo, port->Candidates()[6].priority());
2529 ASSERT_EQ(expected_priority_sitelocal, port->Candidates()[7].priority());
2530 ASSERT_EQ(expected_priority_6bone, port->Candidates()[8].priority());
2531}
2532
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002533// In the case of shared socket, one port may be shared by local and stun.
2534// Test that candidates with different types will have different foundation.
2535TEST_F(PortTest, TestFoundation) {
Steve Anton11358fe2018-10-09 15:39:19 -07002536 auto testport = CreateTestPort(kLocalAddr1, "name", "pass");
Yves Gerey665174f2018-06-19 15:03:05 +02002537 testport->AddCandidateAddress(kLocalAddr1, kLocalAddr1, LOCAL_PORT_TYPE,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002538 cricket::ICE_TYPE_PREFERENCE_HOST, false);
Yves Gerey665174f2018-06-19 15:03:05 +02002539 testport->AddCandidateAddress(kLocalAddr2, kLocalAddr1, STUN_PORT_TYPE,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002540 cricket::ICE_TYPE_PREFERENCE_SRFLX, true);
2541 EXPECT_NE(testport->Candidates()[0].foundation(),
2542 testport->Candidates()[1].foundation());
2543}
2544
2545// This test verifies the foundation of different types of ICE candidates.
2546TEST_F(PortTest, TestCandidateFoundation) {
kwiberg3ec46792016-04-27 07:22:53 -07002547 std::unique_ptr<rtc::NATServer> nat_server(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002548 CreateNatServer(kNatAddr1, NAT_OPEN_CONE));
Steve Anton11358fe2018-10-09 15:39:19 -07002549 auto udpport1 = CreateUdpPort(kLocalAddr1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002550 udpport1->PrepareAddress();
Steve Anton11358fe2018-10-09 15:39:19 -07002551 auto udpport2 = CreateUdpPort(kLocalAddr1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002552 udpport2->PrepareAddress();
2553 EXPECT_EQ(udpport1->Candidates()[0].foundation(),
2554 udpport2->Candidates()[0].foundation());
Steve Anton11358fe2018-10-09 15:39:19 -07002555 auto tcpport1 = CreateTcpPort(kLocalAddr1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002556 tcpport1->PrepareAddress();
Steve Anton11358fe2018-10-09 15:39:19 -07002557 auto tcpport2 = CreateTcpPort(kLocalAddr1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002558 tcpport2->PrepareAddress();
2559 EXPECT_EQ(tcpport1->Candidates()[0].foundation(),
2560 tcpport2->Candidates()[0].foundation());
Steve Anton11358fe2018-10-09 15:39:19 -07002561 auto stunport = CreateStunPort(kLocalAddr1, nat_socket_factory1());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002562 stunport->PrepareAddress();
Honghai Zhang161a5862016-10-20 11:47:02 -07002563 ASSERT_EQ_WAIT(1U, stunport->Candidates().size(), kDefaultTimeout);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002564 EXPECT_NE(tcpport1->Candidates()[0].foundation(),
2565 stunport->Candidates()[0].foundation());
2566 EXPECT_NE(tcpport2->Candidates()[0].foundation(),
2567 stunport->Candidates()[0].foundation());
2568 EXPECT_NE(udpport1->Candidates()[0].foundation(),
2569 stunport->Candidates()[0].foundation());
2570 EXPECT_NE(udpport2->Candidates()[0].foundation(),
2571 stunport->Candidates()[0].foundation());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002572 // Verifying TURN candidate foundation.
Steve Anton11358fe2018-10-09 15:39:19 -07002573 auto turnport1 =
2574 CreateTurnPort(kLocalAddr1, nat_socket_factory1(), PROTO_UDP, PROTO_UDP);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002575 turnport1->PrepareAddress();
Honghai Zhang161a5862016-10-20 11:47:02 -07002576 ASSERT_EQ_WAIT(1U, turnport1->Candidates().size(), kDefaultTimeout);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002577 EXPECT_NE(udpport1->Candidates()[0].foundation(),
2578 turnport1->Candidates()[0].foundation());
2579 EXPECT_NE(udpport2->Candidates()[0].foundation(),
2580 turnport1->Candidates()[0].foundation());
2581 EXPECT_NE(stunport->Candidates()[0].foundation(),
2582 turnport1->Candidates()[0].foundation());
Steve Anton11358fe2018-10-09 15:39:19 -07002583 auto turnport2 =
2584 CreateTurnPort(kLocalAddr1, nat_socket_factory1(), PROTO_UDP, PROTO_UDP);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002585 turnport2->PrepareAddress();
Honghai Zhang161a5862016-10-20 11:47:02 -07002586 ASSERT_EQ_WAIT(1U, turnport2->Candidates().size(), kDefaultTimeout);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002587 EXPECT_EQ(turnport1->Candidates()[0].foundation(),
2588 turnport2->Candidates()[0].foundation());
2589
2590 // Running a second turn server, to get different base IP address.
2591 SocketAddress kTurnUdpIntAddr2("99.99.98.4", STUN_SERVER_PORT);
2592 SocketAddress kTurnUdpExtAddr2("99.99.98.5", 0);
Niels Möller6dd49972021-11-24 14:05:55 +01002593 TestTurnServer turn_server2(rtc::Thread::Current(), vss(), kTurnUdpIntAddr2,
Yves Gerey665174f2018-06-19 15:03:05 +02002594 kTurnUdpExtAddr2);
Steve Anton11358fe2018-10-09 15:39:19 -07002595 auto turnport3 = CreateTurnPort(kLocalAddr1, nat_socket_factory1(), PROTO_UDP,
2596 PROTO_UDP, kTurnUdpIntAddr2);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002597 turnport3->PrepareAddress();
Honghai Zhang161a5862016-10-20 11:47:02 -07002598 ASSERT_EQ_WAIT(1U, turnport3->Candidates().size(), kDefaultTimeout);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002599 EXPECT_NE(turnport3->Candidates()[0].foundation(),
2600 turnport2->Candidates()[0].foundation());
Honghai Zhang80f1db92016-01-27 11:54:45 -08002601
2602 // Start a TCP turn server, and check that two turn candidates have
2603 // different foundations if their relay protocols are different.
Niels Möller6dd49972021-11-24 14:05:55 +01002604 TestTurnServer turn_server3(rtc::Thread::Current(), vss(), kTurnTcpIntAddr,
Honghai Zhang80f1db92016-01-27 11:54:45 -08002605 kTurnUdpExtAddr, PROTO_TCP);
Steve Anton11358fe2018-10-09 15:39:19 -07002606 auto turnport4 =
2607 CreateTurnPort(kLocalAddr1, nat_socket_factory1(), PROTO_TCP, PROTO_UDP);
Honghai Zhang80f1db92016-01-27 11:54:45 -08002608 turnport4->PrepareAddress();
Honghai Zhang161a5862016-10-20 11:47:02 -07002609 ASSERT_EQ_WAIT(1U, turnport4->Candidates().size(), kDefaultTimeout);
Honghai Zhang80f1db92016-01-27 11:54:45 -08002610 EXPECT_NE(turnport2->Candidates()[0].foundation(),
2611 turnport4->Candidates()[0].foundation());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002612}
2613
2614// This test verifies the related addresses of different types of
2615// ICE candiates.
2616TEST_F(PortTest, TestCandidateRelatedAddress) {
Steve Anton11358fe2018-10-09 15:39:19 -07002617 auto nat_server = CreateNatServer(kNatAddr1, NAT_OPEN_CONE);
2618 auto udpport = CreateUdpPort(kLocalAddr1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002619 udpport->PrepareAddress();
2620 // For UDPPort, related address will be empty.
2621 EXPECT_TRUE(udpport->Candidates()[0].related_address().IsNil());
2622 // Testing related address for stun candidates.
2623 // For stun candidate related address must be equal to the base
2624 // socket address.
Steve Anton11358fe2018-10-09 15:39:19 -07002625 auto stunport = CreateStunPort(kLocalAddr1, nat_socket_factory1());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002626 stunport->PrepareAddress();
Honghai Zhang161a5862016-10-20 11:47:02 -07002627 ASSERT_EQ_WAIT(1U, stunport->Candidates().size(), kDefaultTimeout);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002628 // Check STUN candidate address.
Yves Gerey665174f2018-06-19 15:03:05 +02002629 EXPECT_EQ(stunport->Candidates()[0].address().ipaddr(), kNatAddr1.ipaddr());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002630 // Check STUN candidate related address.
2631 EXPECT_EQ(stunport->Candidates()[0].related_address(),
2632 stunport->GetLocalAddress());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002633 // Verifying the related address for TURN candidate.
2634 // For TURN related address must be equal to the mapped address.
Steve Anton11358fe2018-10-09 15:39:19 -07002635 auto turnport =
2636 CreateTurnPort(kLocalAddr1, nat_socket_factory1(), PROTO_UDP, PROTO_UDP);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002637 turnport->PrepareAddress();
Honghai Zhang161a5862016-10-20 11:47:02 -07002638 ASSERT_EQ_WAIT(1U, turnport->Candidates().size(), kDefaultTimeout);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002639 EXPECT_EQ(kTurnUdpExtAddr.ipaddr(),
2640 turnport->Candidates()[0].address().ipaddr());
2641 EXPECT_EQ(kNatAddr1.ipaddr(),
2642 turnport->Candidates()[0].related_address().ipaddr());
2643}
2644
2645// Test priority value overflow handling when preference is set to 3.
Peter Thatcher7cbd1882015-09-17 18:54:52 -07002646TEST_F(PortTest, TestCandidatePriority) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002647 cricket::Candidate cand1;
Peter Thatcher7cbd1882015-09-17 18:54:52 -07002648 cand1.set_priority(3);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002649 cricket::Candidate cand2;
Peter Thatcher7cbd1882015-09-17 18:54:52 -07002650 cand2.set_priority(1);
2651 EXPECT_TRUE(cand1.priority() > cand2.priority());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002652}
2653
2654// Test the Connection priority is calculated correctly.
2655TEST_F(PortTest, TestConnectionPriority) {
Steve Anton11358fe2018-10-09 15:39:19 -07002656 auto lport = CreateTestPort(kLocalAddr1, "lfrag", "lpass");
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002657 lport->set_type_preference(cricket::ICE_TYPE_PREFERENCE_HOST);
Steve Anton11358fe2018-10-09 15:39:19 -07002658 auto rport = CreateTestPort(kLocalAddr2, "rfrag", "rpass");
hnsl277b2502016-12-13 05:17:23 -08002659 rport->set_type_preference(cricket::ICE_TYPE_PREFERENCE_RELAY_UDP);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002660 lport->set_component(123);
2661 lport->AddCandidateAddress(SocketAddress("192.168.1.4", 1234));
2662 rport->set_component(23);
2663 rport->AddCandidateAddress(SocketAddress("10.1.1.100", 1234));
2664
2665 EXPECT_EQ(0x7E001E85U, lport->Candidates()[0].priority());
2666 EXPECT_EQ(0x2001EE9U, rport->Candidates()[0].priority());
2667
2668 // RFC 5245
2669 // pair priority = 2^32*MIN(G,D) + 2*MAX(G,D) + (G>D?1:0)
2670 lport->SetIceRole(cricket::ICEROLE_CONTROLLING);
2671 rport->SetIceRole(cricket::ICEROLE_CONTROLLED);
Yves Gerey665174f2018-06-19 15:03:05 +02002672 Connection* lconn =
2673 lport->CreateConnection(rport->Candidates()[0], Port::ORIGIN_MESSAGE);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002674#if defined(WEBRTC_WIN)
2675 EXPECT_EQ(0x2001EE9FC003D0BU, lconn->priority());
2676#else
2677 EXPECT_EQ(0x2001EE9FC003D0BLLU, lconn->priority());
2678#endif
2679
2680 lport->SetIceRole(cricket::ICEROLE_CONTROLLED);
2681 rport->SetIceRole(cricket::ICEROLE_CONTROLLING);
Yves Gerey665174f2018-06-19 15:03:05 +02002682 Connection* rconn =
2683 rport->CreateConnection(lport->Candidates()[0], Port::ORIGIN_MESSAGE);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002684#if defined(WEBRTC_WIN)
2685 EXPECT_EQ(0x2001EE9FC003D0AU, rconn->priority());
2686#else
2687 EXPECT_EQ(0x2001EE9FC003D0ALLU, rconn->priority());
2688#endif
2689}
2690
Qingsi Wang22e623a2018-03-13 10:53:57 -07002691// Note that UpdateState takes into account the estimated RTT, and the
Artem Titov2dbb4c92021-07-26 15:12:41 +02002692// correctness of using `kMaxExpectedSimulatedRtt` as an upper bound of RTT in
Qingsi Wang22e623a2018-03-13 10:53:57 -07002693// the following tests depends on the link rate and the delay distriubtion
2694// configured in VirtualSocketServer::AddPacketToNetwork. The tests below use
2695// the default setup where the RTT is deterministically one, which generates an
Artem Titov2dbb4c92021-07-26 15:12:41 +02002696// estimate given by `MINIMUM_RTT` = 100.
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002697TEST_F(PortTest, TestWritableState) {
Honghai Zhang161a5862016-10-20 11:47:02 -07002698 rtc::ScopedFakeClock clock;
Steve Anton11358fe2018-10-09 15:39:19 -07002699 auto port1 = CreateUdpPort(kLocalAddr1);
Peter Thatcher7cbd1882015-09-17 18:54:52 -07002700 port1->SetIceRole(cricket::ICEROLE_CONTROLLING);
Steve Anton11358fe2018-10-09 15:39:19 -07002701 auto port2 = CreateUdpPort(kLocalAddr2);
Peter Thatcher7cbd1882015-09-17 18:54:52 -07002702 port2->SetIceRole(cricket::ICEROLE_CONTROLLED);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002703
2704 // Set up channels.
Steve Anton11358fe2018-10-09 15:39:19 -07002705 TestChannel ch1(std::move(port1));
2706 TestChannel ch2(std::move(port2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002707
2708 // Acquire addresses.
2709 ch1.Start();
2710 ch2.Start();
Honghai Zhang161a5862016-10-20 11:47:02 -07002711 ASSERT_EQ_SIMULATED_WAIT(1, ch1.complete_count(), kDefaultTimeout, clock);
2712 ASSERT_EQ_SIMULATED_WAIT(1, ch2.complete_count(), kDefaultTimeout, clock);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002713
2714 // Send a ping from src to dst.
Steve Anton11358fe2018-10-09 15:39:19 -07002715 ch1.CreateConnection(GetCandidate(ch2.port()));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002716 ASSERT_TRUE(ch1.conn() != NULL);
2717 EXPECT_EQ(Connection::STATE_WRITE_INIT, ch1.conn()->write_state());
Honghai Zhang161a5862016-10-20 11:47:02 -07002718 // for TCP connect
2719 EXPECT_TRUE_SIMULATED_WAIT(ch1.conn()->connected(), kDefaultTimeout, clock);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002720 ch1.Ping();
Honghai Zhang161a5862016-10-20 11:47:02 -07002721 SIMULATED_WAIT(!ch2.remote_address().IsNil(), kShortTimeout, clock);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002722
Taylor Brandstetter6bb1ef22016-06-27 18:09:03 -07002723 // Data should be sendable before the connection is accepted.
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002724 char data[] = "abcd";
tfarina5237aaf2015-11-10 23:44:30 -08002725 int data_size = arraysize(data);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002726 rtc::PacketOptions options;
Taylor Brandstetter6bb1ef22016-06-27 18:09:03 -07002727 EXPECT_EQ(data_size, ch1.conn()->Send(data, data_size, options));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002728
2729 // Accept the connection to return the binding response, transition to
2730 // writable, and allow data to be sent.
Steve Anton11358fe2018-10-09 15:39:19 -07002731 ch2.AcceptConnection(GetCandidate(ch1.port()));
Honghai Zhang161a5862016-10-20 11:47:02 -07002732 EXPECT_EQ_SIMULATED_WAIT(Connection::STATE_WRITABLE,
2733 ch1.conn()->write_state(), kDefaultTimeout, clock);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002734 EXPECT_EQ(data_size, ch1.conn()->Send(data, data_size, options));
2735
2736 // Ask the connection to update state as if enough time has passed to lose
2737 // full writability and 5 pings went unresponded to. We'll accomplish the
2738 // latter by sending pings but not pumping messages.
Peter Boström0c4e06b2015-10-07 12:23:21 +02002739 for (uint32_t i = 1; i <= CONNECTION_WRITE_CONNECT_FAILURES; ++i) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002740 ch1.Ping(i);
2741 }
Qingsi Wang22e623a2018-03-13 10:53:57 -07002742 int unreliable_timeout_delay =
2743 CONNECTION_WRITE_CONNECT_TIMEOUT + kMaxExpectedSimulatedRtt;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002744 ch1.conn()->UpdateState(unreliable_timeout_delay);
2745 EXPECT_EQ(Connection::STATE_WRITE_UNRELIABLE, ch1.conn()->write_state());
2746
2747 // Data should be able to be sent in this state.
2748 EXPECT_EQ(data_size, ch1.conn()->Send(data, data_size, options));
2749
2750 // And now allow the other side to process the pings and send binding
2751 // responses.
Honghai Zhang161a5862016-10-20 11:47:02 -07002752 EXPECT_EQ_SIMULATED_WAIT(Connection::STATE_WRITABLE,
2753 ch1.conn()->write_state(), kDefaultTimeout, clock);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002754 // Wait long enough for a full timeout (past however long we've already
2755 // waited).
Peter Boström0c4e06b2015-10-07 12:23:21 +02002756 for (uint32_t i = 1; i <= CONNECTION_WRITE_CONNECT_FAILURES; ++i) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002757 ch1.Ping(unreliable_timeout_delay + i);
2758 }
2759 ch1.conn()->UpdateState(unreliable_timeout_delay + CONNECTION_WRITE_TIMEOUT +
Qingsi Wang22e623a2018-03-13 10:53:57 -07002760 kMaxExpectedSimulatedRtt);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002761 EXPECT_EQ(Connection::STATE_WRITE_TIMEOUT, ch1.conn()->write_state());
2762
Taylor Brandstetter6bb1ef22016-06-27 18:09:03 -07002763 // Even if the connection has timed out, the Connection shouldn't block
2764 // the sending of data.
2765 EXPECT_EQ(data_size, ch1.conn()->Send(data, data_size, options));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002766
2767 ch1.Stop();
2768 ch2.Stop();
2769}
2770
Qingsi Wang22e623a2018-03-13 10:53:57 -07002771// Test writability states using the configured threshold value to replace
Artem Titov2dbb4c92021-07-26 15:12:41 +02002772// the default value given by `CONNECTION_WRITE_CONNECT_TIMEOUT` and
2773// `CONNECTION_WRITE_CONNECT_FAILURES`.
Qingsi Wang22e623a2018-03-13 10:53:57 -07002774TEST_F(PortTest, TestWritableStateWithConfiguredThreshold) {
2775 rtc::ScopedFakeClock clock;
Steve Anton11358fe2018-10-09 15:39:19 -07002776 auto port1 = CreateUdpPort(kLocalAddr1);
Qingsi Wang22e623a2018-03-13 10:53:57 -07002777 port1->SetIceRole(cricket::ICEROLE_CONTROLLING);
Steve Anton11358fe2018-10-09 15:39:19 -07002778 auto port2 = CreateUdpPort(kLocalAddr2);
Qingsi Wang22e623a2018-03-13 10:53:57 -07002779 port2->SetIceRole(cricket::ICEROLE_CONTROLLED);
2780
2781 // Set up channels.
Steve Anton11358fe2018-10-09 15:39:19 -07002782 TestChannel ch1(std::move(port1));
2783 TestChannel ch2(std::move(port2));
Qingsi Wang22e623a2018-03-13 10:53:57 -07002784
2785 // Acquire addresses.
2786 ch1.Start();
2787 ch2.Start();
2788 ASSERT_EQ_SIMULATED_WAIT(1, ch1.complete_count(), kDefaultTimeout, clock);
2789 ASSERT_EQ_SIMULATED_WAIT(1, ch2.complete_count(), kDefaultTimeout, clock);
2790
2791 // Send a ping from src to dst.
Steve Anton11358fe2018-10-09 15:39:19 -07002792 ch1.CreateConnection(GetCandidate(ch2.port()));
Qingsi Wang22e623a2018-03-13 10:53:57 -07002793 ASSERT_TRUE(ch1.conn() != NULL);
2794 ch1.Ping();
2795 SIMULATED_WAIT(!ch2.remote_address().IsNil(), kShortTimeout, clock);
2796
2797 // Accept the connection to return the binding response, transition to
2798 // writable, and allow data to be sent.
Steve Anton11358fe2018-10-09 15:39:19 -07002799 ch2.AcceptConnection(GetCandidate(ch1.port()));
Qingsi Wang22e623a2018-03-13 10:53:57 -07002800 EXPECT_EQ_SIMULATED_WAIT(Connection::STATE_WRITABLE,
2801 ch1.conn()->write_state(), kDefaultTimeout, clock);
2802
2803 ch1.conn()->set_unwritable_timeout(1000);
2804 ch1.conn()->set_unwritable_min_checks(3);
2805 // Send two checks.
2806 ch1.Ping(1);
2807 ch1.Ping(2);
2808 // We have not reached the timeout nor have we sent the minimum number of
2809 // checks to change the state to Unreliable.
2810 ch1.conn()->UpdateState(999);
2811 EXPECT_EQ(Connection::STATE_WRITABLE, ch1.conn()->write_state());
2812 // We have not sent the minimum number of checks without responses.
2813 ch1.conn()->UpdateState(1000 + kMaxExpectedSimulatedRtt);
2814 EXPECT_EQ(Connection::STATE_WRITABLE, ch1.conn()->write_state());
2815 // Last ping after which the candidate pair should become Unreliable after
2816 // timeout.
2817 ch1.Ping(3);
2818 // We have not reached the timeout.
2819 ch1.conn()->UpdateState(999);
2820 EXPECT_EQ(Connection::STATE_WRITABLE, ch1.conn()->write_state());
2821 // We should be in the state Unreliable now.
2822 ch1.conn()->UpdateState(1000 + kMaxExpectedSimulatedRtt);
2823 EXPECT_EQ(Connection::STATE_WRITE_UNRELIABLE, ch1.conn()->write_state());
2824
2825 ch1.Stop();
2826 ch2.Stop();
2827}
2828
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002829TEST_F(PortTest, TestTimeoutForNeverWritable) {
Steve Anton11358fe2018-10-09 15:39:19 -07002830 auto port1 = CreateUdpPort(kLocalAddr1);
Peter Thatcher7cbd1882015-09-17 18:54:52 -07002831 port1->SetIceRole(cricket::ICEROLE_CONTROLLING);
Steve Anton11358fe2018-10-09 15:39:19 -07002832 auto port2 = CreateUdpPort(kLocalAddr2);
Peter Thatcher7cbd1882015-09-17 18:54:52 -07002833 port2->SetIceRole(cricket::ICEROLE_CONTROLLED);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002834
2835 // Set up channels.
Steve Anton11358fe2018-10-09 15:39:19 -07002836 TestChannel ch1(std::move(port1));
2837 TestChannel ch2(std::move(port2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002838
2839 // Acquire addresses.
2840 ch1.Start();
2841 ch2.Start();
2842
Steve Anton11358fe2018-10-09 15:39:19 -07002843 ch1.CreateConnection(GetCandidate(ch2.port()));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002844 ASSERT_TRUE(ch1.conn() != NULL);
2845 EXPECT_EQ(Connection::STATE_WRITE_INIT, ch1.conn()->write_state());
2846
2847 // Attempt to go directly to write timeout.
Peter Boström0c4e06b2015-10-07 12:23:21 +02002848 for (uint32_t i = 1; i <= CONNECTION_WRITE_CONNECT_FAILURES; ++i) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002849 ch1.Ping(i);
2850 }
Qingsi Wang22e623a2018-03-13 10:53:57 -07002851 ch1.conn()->UpdateState(CONNECTION_WRITE_TIMEOUT + kMaxExpectedSimulatedRtt);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002852 EXPECT_EQ(Connection::STATE_WRITE_TIMEOUT, ch1.conn()->write_state());
2853}
2854
2855// This test verifies the connection setup between ICEMODE_FULL
2856// and ICEMODE_LITE.
Artem Titov2dbb4c92021-07-26 15:12:41 +02002857// In this test `ch1` behaves like FULL mode client and we have created
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002858// port which responds to the ping message just like LITE client.
2859TEST_F(PortTest, TestIceLiteConnectivity) {
Steve Anton11358fe2018-10-09 15:39:19 -07002860 auto ice_full_port =
Yves Gerey665174f2018-06-19 15:03:05 +02002861 CreateTestPort(kLocalAddr1, "lfrag", "lpass",
2862 cricket::ICEROLE_CONTROLLING, kTiebreaker1);
Steve Anton11358fe2018-10-09 15:39:19 -07002863 auto* ice_full_port_ptr = ice_full_port.get();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002864
Steve Anton11358fe2018-10-09 15:39:19 -07002865 auto ice_lite_port = CreateTestPort(
2866 kLocalAddr2, "rfrag", "rpass", cricket::ICEROLE_CONTROLLED, kTiebreaker2);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002867 // Setup TestChannel. This behaves like FULL mode client.
Steve Anton11358fe2018-10-09 15:39:19 -07002868 TestChannel ch1(std::move(ice_full_port));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002869 ch1.SetIceMode(ICEMODE_FULL);
2870
2871 // Start gathering candidates.
2872 ch1.Start();
2873 ice_lite_port->PrepareAddress();
2874
Honghai Zhang161a5862016-10-20 11:47:02 -07002875 ASSERT_EQ_WAIT(1, ch1.complete_count(), kDefaultTimeout);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002876 ASSERT_FALSE(ice_lite_port->Candidates().empty());
2877
Guo-wei Shieh1eb87c72015-08-25 11:02:55 -07002878 ch1.CreateConnection(GetCandidate(ice_lite_port.get()));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002879 ASSERT_TRUE(ch1.conn() != NULL);
2880 EXPECT_EQ(Connection::STATE_WRITE_INIT, ch1.conn()->write_state());
2881
2882 // Send ping from full mode client.
2883 // This ping must not have USE_CANDIDATE_ATTR.
2884 ch1.Ping();
2885
2886 // Verify stun ping is without USE_CANDIDATE_ATTR. Getting message directly
2887 // from port.
Steve Anton11358fe2018-10-09 15:39:19 -07002888 ASSERT_TRUE_WAIT(ice_full_port_ptr->last_stun_msg() != NULL, kDefaultTimeout);
2889 IceMessage* msg = ice_full_port_ptr->last_stun_msg();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002890 EXPECT_TRUE(msg->GetByteString(STUN_ATTR_USE_CANDIDATE) == NULL);
2891
2892 // Respond with a BINDING-RESPONSE from litemode client.
2893 // NOTE: Ideally we should't create connection at this stage from lite
2894 // port, as it should be done only after receiving ping with USE_CANDIDATE.
2895 // But we need a connection to send a response message.
Jonas Orelandd0036622019-11-29 15:58:13 +01002896 auto* con = ice_lite_port->CreateConnection(
2897 ice_full_port_ptr->Candidates()[0], cricket::Port::ORIGIN_MESSAGE);
Steve Anton11358fe2018-10-09 15:39:19 -07002898 std::unique_ptr<IceMessage> request = CopyStunMessage(*msg);
Jonas Oreland9a52bd72019-12-11 11:35:48 +01002899 con->SendStunBindingResponse(request.get());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002900
2901 // Feeding the respone message from litemode to the full mode connection.
jbauchf1f87202016-03-30 06:43:37 -07002902 ch1.conn()->OnReadPacket(ice_lite_port->last_stun_buf()->data<char>(),
2903 ice_lite_port->last_stun_buf()->size(),
Niels Möllere6933812018-11-05 13:01:41 +01002904 /* packet_time_us */ -1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002905 // Verifying full mode connection becomes writable from the response.
2906 EXPECT_EQ_WAIT(Connection::STATE_WRITABLE, ch1.conn()->write_state(),
Honghai Zhang161a5862016-10-20 11:47:02 -07002907 kDefaultTimeout);
2908 EXPECT_TRUE_WAIT(ch1.nominated(), kDefaultTimeout);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002909
2910 // Clear existing stun messsages. Otherwise we will process old stun
2911 // message right after we send ping.
Steve Anton11358fe2018-10-09 15:39:19 -07002912 ice_full_port_ptr->Reset();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002913 // Send ping. This must have USE_CANDIDATE_ATTR.
2914 ch1.Ping();
Steve Anton11358fe2018-10-09 15:39:19 -07002915 ASSERT_TRUE_WAIT(ice_full_port_ptr->last_stun_msg() != NULL, kDefaultTimeout);
2916 msg = ice_full_port_ptr->last_stun_msg();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00002917 EXPECT_TRUE(msg->GetByteString(STUN_ATTR_USE_CANDIDATE) != NULL);
2918 ch1.Stop();
2919}
2920
Jonas Oreland9a52bd72019-12-11 11:35:48 +01002921namespace {
2922
2923// Utility function for testing goog ping.
Jonas Oreland219d8ce2020-01-15 15:29:48 +01002924absl::optional<int> GetSupportedGoogPingVersion(const StunMessage* msg) {
2925 auto goog_misc = msg->GetUInt16List(STUN_ATTR_GOOG_MISC_INFO);
Jonas Oreland9a52bd72019-12-11 11:35:48 +01002926 if (goog_misc == nullptr) {
2927 return absl::nullopt;
2928 }
2929
Jonas Oreland219d8ce2020-01-15 15:29:48 +01002930 if (msg->type() == STUN_BINDING_REQUEST) {
2931 if (goog_misc->Size() <
2932 static_cast<int>(cricket::IceGoogMiscInfoBindingRequestAttributeIndex::
2933 SUPPORT_GOOG_PING_VERSION)) {
2934 return absl::nullopt;
2935 }
2936
2937 return goog_misc->GetType(
2938 static_cast<int>(cricket::IceGoogMiscInfoBindingRequestAttributeIndex::
2939 SUPPORT_GOOG_PING_VERSION));
Jonas Oreland9a52bd72019-12-11 11:35:48 +01002940 }
2941
Jonas Oreland219d8ce2020-01-15 15:29:48 +01002942 if (msg->type() == STUN_BINDING_RESPONSE) {
2943 if (goog_misc->Size() <
2944 static_cast<int>(cricket::IceGoogMiscInfoBindingResponseAttributeIndex::
2945 SUPPORT_GOOG_PING_VERSION)) {
2946 return absl::nullopt;
2947 }
2948
2949 return goog_misc->GetType(
2950 static_cast<int>(cricket::IceGoogMiscInfoBindingResponseAttributeIndex::
2951 SUPPORT_GOOG_PING_VERSION));
2952 }
2953 return absl::nullopt;
Jonas Oreland9a52bd72019-12-11 11:35:48 +01002954}
2955
2956} // namespace
2957
2958class GoogPingTest
2959 : public PortTest,
2960 public ::testing::WithParamInterface<std::pair<bool, bool>> {};
2961
2962// This test verifies the announce/enable on/off behavior
2963TEST_P(GoogPingTest, TestGoogPingAnnounceEnable) {
2964 IceFieldTrials trials;
2965 trials.announce_goog_ping = GetParam().first;
2966 trials.enable_goog_ping = GetParam().second;
2967 RTC_LOG(LS_INFO) << "Testing combination: "
Jonas Olssonb2b20312020-01-14 12:11:31 +01002968 " announce: "
2969 << trials.announce_goog_ping
Jonas Oreland9a52bd72019-12-11 11:35:48 +01002970 << " enable:" << trials.enable_goog_ping;
2971
2972 auto port1_unique =
2973 CreateTestPort(kLocalAddr1, "lfrag", "lpass",
2974 cricket::ICEROLE_CONTROLLING, kTiebreaker1);
2975 auto* port1 = port1_unique.get();
2976 auto port2 = CreateTestPort(kLocalAddr2, "rfrag", "rpass",
2977 cricket::ICEROLE_CONTROLLED, kTiebreaker2);
2978
2979 TestChannel ch1(std::move(port1_unique));
2980 // Block usage of STUN_ATTR_USE_CANDIDATE so that
2981 // ch1.conn() will sent GOOG_PING_REQUEST directly.
2982 // This only makes test a bit shorter...
2983 ch1.SetIceMode(ICEMODE_LITE);
2984 // Start gathering candidates.
2985 ch1.Start();
2986 port2->PrepareAddress();
2987
2988 ASSERT_EQ_WAIT(1, ch1.complete_count(), kDefaultTimeout);
2989 ASSERT_FALSE(port2->Candidates().empty());
2990
2991 ch1.CreateConnection(GetCandidate(port2.get()));
2992 ASSERT_TRUE(ch1.conn() != NULL);
2993 EXPECT_EQ(Connection::STATE_WRITE_INIT, ch1.conn()->write_state());
2994 ch1.conn()->SetIceFieldTrials(&trials);
2995
2996 // Send ping.
2997 ch1.Ping();
2998
2999 ASSERT_TRUE_WAIT(port1->last_stun_msg() != NULL, kDefaultTimeout);
3000 const IceMessage* request1 = port1->last_stun_msg();
Jonas Oreland219d8ce2020-01-15 15:29:48 +01003001
3002 ASSERT_EQ(trials.enable_goog_ping,
3003 GetSupportedGoogPingVersion(request1) &&
3004 GetSupportedGoogPingVersion(request1) >= kGoogPingVersion);
3005
Jonas Oreland9a52bd72019-12-11 11:35:48 +01003006 auto* con = port2->CreateConnection(port1->Candidates()[0],
3007 cricket::Port::ORIGIN_MESSAGE);
3008 con->SetIceFieldTrials(&trials);
3009
3010 con->SendStunBindingResponse(request1);
3011
3012 // Then check the response matches the settings.
3013 const auto* response = port2->last_stun_msg();
Jonas Oreland219d8ce2020-01-15 15:29:48 +01003014 EXPECT_EQ(response->type(), STUN_BINDING_RESPONSE);
3015 EXPECT_EQ(trials.enable_goog_ping && trials.announce_goog_ping,
Jonas Oreland9a52bd72019-12-11 11:35:48 +01003016 GetSupportedGoogPingVersion(response) &&
3017 GetSupportedGoogPingVersion(response) >= kGoogPingVersion);
3018
3019 // Feeding the respone message back.
3020 ch1.conn()->OnReadPacket(port2->last_stun_buf()->data<char>(),
3021 port2->last_stun_buf()->size(),
3022 /* packet_time_us */ -1);
3023
3024 port1->Reset();
3025 port2->Reset();
3026
3027 ch1.Ping();
3028 ASSERT_TRUE_WAIT(port1->last_stun_msg() != NULL, kDefaultTimeout);
3029 const IceMessage* request2 = port1->last_stun_msg();
3030
3031 // It should be a GOOG_PING if both of these are TRUE
3032 if (trials.announce_goog_ping && trials.enable_goog_ping) {
3033 ASSERT_EQ(request2->type(), GOOG_PING_REQUEST);
3034 con->SendGoogPingResponse(request2);
3035 } else {
3036 ASSERT_EQ(request2->type(), STUN_BINDING_REQUEST);
Jonas Oreland219d8ce2020-01-15 15:29:48 +01003037 // If we sent a BINDING with enable, and we got a reply that
3038 // didn't contain announce, the next ping should not contain
3039 // the enable again.
3040 ASSERT_FALSE(GetSupportedGoogPingVersion(request2).has_value());
Jonas Oreland9a52bd72019-12-11 11:35:48 +01003041 con->SendStunBindingResponse(request2);
3042 }
3043
3044 const auto* response2 = port2->last_stun_msg();
3045 ASSERT_TRUE(response2 != nullptr);
3046
3047 // It should be a GOOG_PING_RESPONSE if both of these are TRUE
3048 if (trials.announce_goog_ping && trials.enable_goog_ping) {
3049 ASSERT_EQ(response2->type(), GOOG_PING_RESPONSE);
3050 } else {
3051 ASSERT_EQ(response2->type(), STUN_BINDING_RESPONSE);
3052 }
3053
3054 ch1.Stop();
3055}
3056
Jonas Oreland219d8ce2020-01-15 15:29:48 +01003057// This test if a someone send a STUN_BINDING with unsupported version
3058// (kGoogPingVersion == 0)
3059TEST_F(PortTest, TestGoogPingUnsupportedVersionInStunBinding) {
3060 IceFieldTrials trials;
3061 trials.announce_goog_ping = true;
3062 trials.enable_goog_ping = true;
3063
3064 auto port1_unique =
3065 CreateTestPort(kLocalAddr1, "lfrag", "lpass",
3066 cricket::ICEROLE_CONTROLLING, kTiebreaker1);
3067 auto* port1 = port1_unique.get();
3068 auto port2 = CreateTestPort(kLocalAddr2, "rfrag", "rpass",
3069 cricket::ICEROLE_CONTROLLED, kTiebreaker2);
3070
3071 TestChannel ch1(std::move(port1_unique));
3072 // Block usage of STUN_ATTR_USE_CANDIDATE so that
3073 // ch1.conn() will sent GOOG_PING_REQUEST directly.
3074 // This only makes test a bit shorter...
3075 ch1.SetIceMode(ICEMODE_LITE);
3076 // Start gathering candidates.
3077 ch1.Start();
3078 port2->PrepareAddress();
3079
3080 ASSERT_EQ_WAIT(1, ch1.complete_count(), kDefaultTimeout);
3081 ASSERT_FALSE(port2->Candidates().empty());
3082
3083 ch1.CreateConnection(GetCandidate(port2.get()));
3084 ASSERT_TRUE(ch1.conn() != NULL);
3085 EXPECT_EQ(Connection::STATE_WRITE_INIT, ch1.conn()->write_state());
3086 ch1.conn()->SetIceFieldTrials(&trials);
3087
3088 // Send ping.
3089 ch1.Ping();
3090
3091 ASSERT_TRUE_WAIT(port1->last_stun_msg() != NULL, kDefaultTimeout);
3092 const IceMessage* request1 = port1->last_stun_msg();
3093
3094 ASSERT_TRUE(GetSupportedGoogPingVersion(request1) &&
3095 GetSupportedGoogPingVersion(request1) >= kGoogPingVersion);
3096
3097 // Modify the STUN message request1 to send GetSupportedGoogPingVersion == 0
3098 auto modified_request1 = request1->Clone();
3099 ASSERT_TRUE(modified_request1->RemoveAttribute(STUN_ATTR_GOOG_MISC_INFO) !=
3100 nullptr);
3101 ASSERT_TRUE(modified_request1->RemoveAttribute(STUN_ATTR_MESSAGE_INTEGRITY) !=
3102 nullptr);
3103 {
3104 auto list =
3105 StunAttribute::CreateUInt16ListAttribute(STUN_ATTR_GOOG_MISC_INFO);
3106 list->AddTypeAtIndex(
3107 static_cast<uint16_t>(
3108 cricket::IceGoogMiscInfoBindingRequestAttributeIndex::
3109 SUPPORT_GOOG_PING_VERSION),
3110 /* version */ 0);
3111 modified_request1->AddAttribute(std::move(list));
3112 modified_request1->AddMessageIntegrity("rpass");
3113 }
3114 auto* con = port2->CreateConnection(port1->Candidates()[0],
3115 cricket::Port::ORIGIN_MESSAGE);
3116 con->SetIceFieldTrials(&trials);
3117
3118 con->SendStunBindingResponse(modified_request1.get());
3119
3120 // Then check the response matches the settings.
3121 const auto* response = port2->last_stun_msg();
3122 EXPECT_EQ(response->type(), STUN_BINDING_RESPONSE);
3123 EXPECT_FALSE(GetSupportedGoogPingVersion(response));
3124
3125 ch1.Stop();
3126}
3127
3128// This test if a someone send a STUN_BINDING_RESPONSE with unsupported version
3129// (kGoogPingVersion == 0)
3130TEST_F(PortTest, TestGoogPingUnsupportedVersionInStunBindingResponse) {
3131 IceFieldTrials trials;
3132 trials.announce_goog_ping = true;
3133 trials.enable_goog_ping = true;
3134
3135 auto port1_unique =
3136 CreateTestPort(kLocalAddr1, "lfrag", "lpass",
3137 cricket::ICEROLE_CONTROLLING, kTiebreaker1);
3138 auto* port1 = port1_unique.get();
3139 auto port2 = CreateTestPort(kLocalAddr2, "rfrag", "rpass",
3140 cricket::ICEROLE_CONTROLLED, kTiebreaker2);
3141
3142 TestChannel ch1(std::move(port1_unique));
3143 // Block usage of STUN_ATTR_USE_CANDIDATE so that
3144 // ch1.conn() will sent GOOG_PING_REQUEST directly.
3145 // This only makes test a bit shorter...
3146 ch1.SetIceMode(ICEMODE_LITE);
3147 // Start gathering candidates.
3148 ch1.Start();
3149 port2->PrepareAddress();
3150
3151 ASSERT_EQ_WAIT(1, ch1.complete_count(), kDefaultTimeout);
3152 ASSERT_FALSE(port2->Candidates().empty());
3153
3154 ch1.CreateConnection(GetCandidate(port2.get()));
3155 ASSERT_TRUE(ch1.conn() != NULL);
3156 EXPECT_EQ(Connection::STATE_WRITE_INIT, ch1.conn()->write_state());
3157 ch1.conn()->SetIceFieldTrials(&trials);
3158
3159 // Send ping.
3160 ch1.Ping();
3161
3162 ASSERT_TRUE_WAIT(port1->last_stun_msg() != NULL, kDefaultTimeout);
3163 const IceMessage* request1 = port1->last_stun_msg();
3164
3165 ASSERT_TRUE(GetSupportedGoogPingVersion(request1) &&
3166 GetSupportedGoogPingVersion(request1) >= kGoogPingVersion);
3167
3168 auto* con = port2->CreateConnection(port1->Candidates()[0],
3169 cricket::Port::ORIGIN_MESSAGE);
3170 con->SetIceFieldTrials(&trials);
3171
3172 con->SendStunBindingResponse(request1);
3173
3174 // Then check the response matches the settings.
3175 const auto* response = port2->last_stun_msg();
3176 EXPECT_EQ(response->type(), STUN_BINDING_RESPONSE);
3177 EXPECT_TRUE(GetSupportedGoogPingVersion(response));
3178
3179 // Modify the STUN message response to contain GetSupportedGoogPingVersion ==
3180 // 0
3181 auto modified_response = response->Clone();
3182 ASSERT_TRUE(modified_response->RemoveAttribute(STUN_ATTR_GOOG_MISC_INFO) !=
3183 nullptr);
3184 ASSERT_TRUE(modified_response->RemoveAttribute(STUN_ATTR_MESSAGE_INTEGRITY) !=
3185 nullptr);
3186 ASSERT_TRUE(modified_response->RemoveAttribute(STUN_ATTR_FINGERPRINT) !=
3187 nullptr);
3188 {
3189 auto list =
3190 StunAttribute::CreateUInt16ListAttribute(STUN_ATTR_GOOG_MISC_INFO);
3191 list->AddTypeAtIndex(
3192 static_cast<uint16_t>(
3193 cricket::IceGoogMiscInfoBindingResponseAttributeIndex::
3194 SUPPORT_GOOG_PING_VERSION),
3195 /* version */ 0);
3196 modified_response->AddAttribute(std::move(list));
3197 modified_response->AddMessageIntegrity("rpass");
3198 modified_response->AddFingerprint();
3199 }
3200
3201 rtc::ByteBufferWriter buf;
3202 modified_response->Write(&buf);
3203
3204 // Feeding the modified respone message back.
3205 ch1.conn()->OnReadPacket(buf.Data(), buf.Length(), /* packet_time_us */ -1);
3206
3207 port1->Reset();
3208 port2->Reset();
3209
3210 ch1.Ping();
3211 ASSERT_TRUE_WAIT(port1->last_stun_msg() != NULL, kDefaultTimeout);
3212
3213 // This should now be a STUN_BINDING...without a kGoogPingVersion
3214 const IceMessage* request2 = port1->last_stun_msg();
3215 EXPECT_EQ(request2->type(), STUN_BINDING_REQUEST);
3216 EXPECT_FALSE(GetSupportedGoogPingVersion(request2));
3217
3218 ch1.Stop();
3219}
3220
Jonas Oreland9a52bd72019-12-11 11:35:48 +01003221INSTANTIATE_TEST_SUITE_P(GoogPingTest,
3222 GoogPingTest,
3223 // test all combinations of <announce, enable> pairs.
3224 ::testing::Values(std::make_pair(false, false),
3225 std::make_pair(true, false),
3226 std::make_pair(false, true),
3227 std::make_pair(true, true)));
3228
3229// This test checks that a change in attributes falls back to STUN_BINDING
3230TEST_F(PortTest, TestChangeInAttributeMakesGoogPingFallsbackToStunBinding) {
3231 IceFieldTrials trials;
3232 trials.announce_goog_ping = true;
3233 trials.enable_goog_ping = true;
3234
3235 auto port1_unique =
3236 CreateTestPort(kLocalAddr1, "lfrag", "lpass",
3237 cricket::ICEROLE_CONTROLLING, kTiebreaker1);
3238 auto* port1 = port1_unique.get();
3239 auto port2 = CreateTestPort(kLocalAddr2, "rfrag", "rpass",
3240 cricket::ICEROLE_CONTROLLED, kTiebreaker2);
3241
3242 TestChannel ch1(std::move(port1_unique));
3243 // Block usage of STUN_ATTR_USE_CANDIDATE so that
3244 // ch1.conn() will sent GOOG_PING_REQUEST directly.
3245 // This only makes test a bit shorter...
3246 ch1.SetIceMode(ICEMODE_LITE);
3247 // Start gathering candidates.
3248 ch1.Start();
3249 port2->PrepareAddress();
3250
3251 ASSERT_EQ_WAIT(1, ch1.complete_count(), kDefaultTimeout);
3252 ASSERT_FALSE(port2->Candidates().empty());
3253
3254 ch1.CreateConnection(GetCandidate(port2.get()));
3255 ASSERT_TRUE(ch1.conn() != nullptr);
3256 EXPECT_EQ(Connection::STATE_WRITE_INIT, ch1.conn()->write_state());
3257 ch1.conn()->SetIceFieldTrials(&trials);
3258
3259 // Send ping.
3260 ch1.Ping();
3261
3262 ASSERT_TRUE_WAIT(port1->last_stun_msg() != NULL, kDefaultTimeout);
3263 const IceMessage* msg = port1->last_stun_msg();
3264 auto* con = port2->CreateConnection(port1->Candidates()[0],
3265 cricket::Port::ORIGIN_MESSAGE);
3266 con->SetIceFieldTrials(&trials);
3267
3268 // Feed the message into the connection.
3269 con->SendStunBindingResponse(msg);
3270
3271 // The check reply wrt to settings.
3272 const auto* response = port2->last_stun_msg();
3273 ASSERT_EQ(response->type(), STUN_BINDING_RESPONSE);
3274 ASSERT_TRUE(GetSupportedGoogPingVersion(response) >= kGoogPingVersion);
3275
3276 // Feeding the respone message back.
3277 ch1.conn()->OnReadPacket(port2->last_stun_buf()->data<char>(),
3278 port2->last_stun_buf()->size(),
3279 /* packet_time_us */ -1);
3280
3281 port1->Reset();
3282 port2->Reset();
3283
3284 ch1.Ping();
3285 ASSERT_TRUE_WAIT(port1->last_stun_msg() != NULL, kDefaultTimeout);
3286 const IceMessage* msg2 = port1->last_stun_msg();
3287
3288 // It should be a GOOG_PING if both of these are TRUE
3289 ASSERT_EQ(msg2->type(), GOOG_PING_REQUEST);
3290 con->SendGoogPingResponse(msg2);
3291
3292 const auto* response2 = port2->last_stun_msg();
3293 ASSERT_TRUE(response2 != nullptr);
3294
3295 // It should be a GOOG_PING_RESPONSE.
3296 ASSERT_EQ(response2->type(), GOOG_PING_RESPONSE);
3297
3298 // And now the third ping.
3299 port1->Reset();
3300 port2->Reset();
3301
3302 // Modify the message to be sent.
3303 ch1.conn()->set_use_candidate_attr(!ch1.conn()->use_candidate_attr());
3304
3305 ch1.Ping();
3306 ASSERT_TRUE_WAIT(port1->last_stun_msg() != NULL, kDefaultTimeout);
3307 const IceMessage* msg3 = port1->last_stun_msg();
3308
3309 // It should be a STUN_BINDING_REQUEST
3310 ASSERT_EQ(msg3->type(), STUN_BINDING_REQUEST);
3311
3312 ch1.Stop();
3313}
3314
3315// This test that an error response fall back to STUN_BINDING.
3316TEST_F(PortTest, TestErrorResponseMakesGoogPingFallBackToStunBinding) {
3317 IceFieldTrials trials;
3318 trials.announce_goog_ping = true;
3319 trials.enable_goog_ping = true;
3320
3321 auto port1_unique =
3322 CreateTestPort(kLocalAddr1, "lfrag", "lpass",
3323 cricket::ICEROLE_CONTROLLING, kTiebreaker1);
3324 auto* port1 = port1_unique.get();
3325 auto port2 = CreateTestPort(kLocalAddr2, "rfrag", "rpass",
3326 cricket::ICEROLE_CONTROLLED, kTiebreaker2);
3327
3328 TestChannel ch1(std::move(port1_unique));
3329 // Block usage of STUN_ATTR_USE_CANDIDATE so that
3330 // ch1.conn() will sent GOOG_PING_REQUEST directly.
3331 // This only makes test a bit shorter...
3332 ch1.SetIceMode(ICEMODE_LITE);
3333 // Start gathering candidates.
3334 ch1.Start();
3335 port2->PrepareAddress();
3336
3337 ASSERT_EQ_WAIT(1, ch1.complete_count(), kDefaultTimeout);
3338 ASSERT_FALSE(port2->Candidates().empty());
3339
3340 ch1.CreateConnection(GetCandidate(port2.get()));
3341 ASSERT_TRUE(ch1.conn() != NULL);
3342 EXPECT_EQ(Connection::STATE_WRITE_INIT, ch1.conn()->write_state());
3343 ch1.conn()->SetIceFieldTrials(&trials);
3344
3345 // Send ping.
3346 ch1.Ping();
3347
3348 ASSERT_TRUE_WAIT(port1->last_stun_msg() != NULL, kDefaultTimeout);
3349 const IceMessage* msg = port1->last_stun_msg();
3350 auto* con = port2->CreateConnection(port1->Candidates()[0],
3351 cricket::Port::ORIGIN_MESSAGE);
3352 con->SetIceFieldTrials(&trials);
3353
3354 // Feed the message into the connection.
3355 con->SendStunBindingResponse(msg);
3356
3357 // The check reply wrt to settings.
3358 const auto* response = port2->last_stun_msg();
3359 ASSERT_EQ(response->type(), STUN_BINDING_RESPONSE);
3360 ASSERT_TRUE(GetSupportedGoogPingVersion(response) >= kGoogPingVersion);
3361
3362 // Feeding the respone message back.
3363 ch1.conn()->OnReadPacket(port2->last_stun_buf()->data<char>(),
3364 port2->last_stun_buf()->size(),
3365 /* packet_time_us */ -1);
3366
3367 port1->Reset();
3368 port2->Reset();
3369
3370 ch1.Ping();
3371 ASSERT_TRUE_WAIT(port1->last_stun_msg() != NULL, kDefaultTimeout);
3372 const IceMessage* msg2 = port1->last_stun_msg();
3373
3374 // It should be a GOOG_PING.
3375 ASSERT_EQ(msg2->type(), GOOG_PING_REQUEST);
3376 con->SendGoogPingResponse(msg2);
3377
3378 const auto* response2 = port2->last_stun_msg();
3379 ASSERT_TRUE(response2 != nullptr);
3380
3381 // It should be a GOOG_PING_RESPONSE.
3382 ASSERT_EQ(response2->type(), GOOG_PING_RESPONSE);
3383
3384 // But rather than the RESPONSE...feedback an error.
3385 StunMessage error_response;
3386 error_response.SetType(GOOG_PING_ERROR_RESPONSE);
3387 error_response.SetTransactionID(response2->transaction_id());
3388 error_response.AddMessageIntegrity32("rpass");
3389 rtc::ByteBufferWriter buf;
3390 error_response.Write(&buf);
3391
3392 ch1.conn()->OnReadPacket(buf.Data(), buf.Length(),
3393 /* packet_time_us */ -1);
3394
3395 // And now the third ping...this should be a binding.
3396 port1->Reset();
3397 port2->Reset();
3398
3399 ch1.Ping();
3400 ASSERT_TRUE_WAIT(port1->last_stun_msg() != NULL, kDefaultTimeout);
3401 const IceMessage* msg3 = port1->last_stun_msg();
3402
3403 // It should be a STUN_BINDING_REQUEST
3404 ASSERT_EQ(msg3->type(), STUN_BINDING_REQUEST);
3405
3406 ch1.Stop();
3407}
3408
Honghai Zhanga74363c2016-07-28 18:06:15 -07003409// This test case verifies that both the controlling port and the controlled
3410// port will time out after connectivity is lost, if they are not marked as
3411// "keep alive until pruned."
3412TEST_F(PortTest, TestPortTimeoutIfNotKeptAlive) {
3413 rtc::ScopedFakeClock clock;
3414 int timeout_delay = 100;
Steve Anton11358fe2018-10-09 15:39:19 -07003415 auto port1 = CreateUdpPort(kLocalAddr1);
3416 ConnectToSignalDestroyed(port1.get());
Honghai Zhanga74363c2016-07-28 18:06:15 -07003417 port1->set_timeout_delay(timeout_delay); // milliseconds
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00003418 port1->SetIceRole(cricket::ICEROLE_CONTROLLING);
3419 port1->SetIceTiebreaker(kTiebreaker1);
3420
Steve Anton11358fe2018-10-09 15:39:19 -07003421 auto port2 = CreateUdpPort(kLocalAddr2);
3422 ConnectToSignalDestroyed(port2.get());
Honghai Zhanga74363c2016-07-28 18:06:15 -07003423 port2->set_timeout_delay(timeout_delay); // milliseconds
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00003424 port2->SetIceRole(cricket::ICEROLE_CONTROLLED);
3425 port2->SetIceTiebreaker(kTiebreaker2);
3426
3427 // Set up channels and ensure both ports will be deleted.
Steve Anton11358fe2018-10-09 15:39:19 -07003428 TestChannel ch1(std::move(port1));
3429 TestChannel ch2(std::move(port2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00003430
3431 // Simulate a connection that succeeds, and then is destroyed.
Guo-wei Shiehbe508a12015-04-06 12:48:47 -07003432 StartConnectAndStopChannels(&ch1, &ch2);
Honghai Zhanga74363c2016-07-28 18:06:15 -07003433 // After the connection is destroyed, the port will be destroyed because
3434 // none of them is marked as "keep alive until pruned.
3435 EXPECT_EQ_SIMULATED_WAIT(2, ports_destroyed(), 110, clock);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00003436}
3437
Honghai Zhanga74363c2016-07-28 18:06:15 -07003438// Test that if after all connection are destroyed, new connections are created
3439// and destroyed again, ports won't be destroyed until a timeout period passes
3440// after the last set of connections are all destroyed.
3441TEST_F(PortTest, TestPortTimeoutAfterNewConnectionCreatedAndDestroyed) {
Honghai Zhangb5db1ec2016-07-28 13:23:05 -07003442 rtc::ScopedFakeClock clock;
Honghai Zhanga74363c2016-07-28 18:06:15 -07003443 int timeout_delay = 100;
Steve Anton11358fe2018-10-09 15:39:19 -07003444 auto port1 = CreateUdpPort(kLocalAddr1);
3445 ConnectToSignalDestroyed(port1.get());
Honghai Zhanga74363c2016-07-28 18:06:15 -07003446 port1->set_timeout_delay(timeout_delay); // milliseconds
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00003447 port1->SetIceRole(cricket::ICEROLE_CONTROLLING);
3448 port1->SetIceTiebreaker(kTiebreaker1);
3449
Steve Anton11358fe2018-10-09 15:39:19 -07003450 auto port2 = CreateUdpPort(kLocalAddr2);
3451 ConnectToSignalDestroyed(port2.get());
Honghai Zhanga74363c2016-07-28 18:06:15 -07003452 port2->set_timeout_delay(timeout_delay); // milliseconds
3453
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00003454 port2->SetIceRole(cricket::ICEROLE_CONTROLLED);
3455 port2->SetIceTiebreaker(kTiebreaker2);
3456
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00003457 // Set up channels and ensure both ports will be deleted.
Steve Anton11358fe2018-10-09 15:39:19 -07003458 TestChannel ch1(std::move(port1));
3459 TestChannel ch2(std::move(port2));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00003460
3461 // Simulate a connection that succeeds, and then is destroyed.
Guo-wei Shiehbe508a12015-04-06 12:48:47 -07003462 StartConnectAndStopChannels(&ch1, &ch2);
Honghai Zhanga74363c2016-07-28 18:06:15 -07003463 SIMULATED_WAIT(ports_destroyed() > 0, 80, clock);
3464 EXPECT_EQ(0, ports_destroyed());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00003465
Honghai Zhanga74363c2016-07-28 18:06:15 -07003466 // Start the second set of connection and destroy them.
3467 ch1.CreateConnection(GetCandidate(ch2.port()));
Honghai Zhangb5db1ec2016-07-28 13:23:05 -07003468 ch2.CreateConnection(GetCandidate(ch1.port()));
Honghai Zhanga74363c2016-07-28 18:06:15 -07003469 ch1.Stop();
Honghai Zhangb5db1ec2016-07-28 13:23:05 -07003470 ch2.Stop();
Honghai Zhangb5db1ec2016-07-28 13:23:05 -07003471
Honghai Zhanga74363c2016-07-28 18:06:15 -07003472 SIMULATED_WAIT(ports_destroyed() > 0, 80, clock);
3473 EXPECT_EQ(0, ports_destroyed());
3474
3475 // The ports on both sides should be destroyed after timeout.
3476 EXPECT_TRUE_SIMULATED_WAIT(ports_destroyed() == 2, 30, clock);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00003477}
honghaizd0b31432015-09-30 12:42:17 -07003478
Honghai Zhanga74363c2016-07-28 18:06:15 -07003479// This test case verifies that neither the controlling port nor the controlled
3480// port will time out after connectivity is lost if they are marked as "keep
3481// alive until pruned". They will time out after they are pruned.
3482TEST_F(PortTest, TestPortNotTimeoutUntilPruned) {
3483 rtc::ScopedFakeClock clock;
3484 int timeout_delay = 100;
Steve Anton11358fe2018-10-09 15:39:19 -07003485 auto port1 = CreateUdpPort(kLocalAddr1);
3486 ConnectToSignalDestroyed(port1.get());
Honghai Zhanga74363c2016-07-28 18:06:15 -07003487 port1->set_timeout_delay(timeout_delay); // milliseconds
honghaizd0b31432015-09-30 12:42:17 -07003488 port1->SetIceRole(cricket::ICEROLE_CONTROLLING);
3489 port1->SetIceTiebreaker(kTiebreaker1);
3490
Steve Anton11358fe2018-10-09 15:39:19 -07003491 auto port2 = CreateUdpPort(kLocalAddr2);
3492 ConnectToSignalDestroyed(port2.get());
Honghai Zhanga74363c2016-07-28 18:06:15 -07003493 port2->set_timeout_delay(timeout_delay); // milliseconds
honghaizd0b31432015-09-30 12:42:17 -07003494 port2->SetIceRole(cricket::ICEROLE_CONTROLLED);
3495 port2->SetIceTiebreaker(kTiebreaker2);
honghaizd0b31432015-09-30 12:42:17 -07003496 // The connection must not be destroyed before a connection is attempted.
Honghai Zhanga74363c2016-07-28 18:06:15 -07003497 EXPECT_EQ(0, ports_destroyed());
honghaizd0b31432015-09-30 12:42:17 -07003498
3499 port1->set_component(cricket::ICE_CANDIDATE_COMPONENT_DEFAULT);
3500 port2->set_component(cricket::ICE_CANDIDATE_COMPONENT_DEFAULT);
3501
Honghai Zhanga74363c2016-07-28 18:06:15 -07003502 // Set up channels and keep the port alive.
Steve Anton11358fe2018-10-09 15:39:19 -07003503 TestChannel ch1(std::move(port1));
3504 TestChannel ch2(std::move(port2));
Honghai Zhanga74363c2016-07-28 18:06:15 -07003505 // Simulate a connection that succeeds, and then is destroyed. But ports
3506 // are kept alive. Ports won't be destroyed.
honghaizd0b31432015-09-30 12:42:17 -07003507 StartConnectAndStopChannels(&ch1, &ch2);
Steve Anton11358fe2018-10-09 15:39:19 -07003508 ch1.port()->KeepAliveUntilPruned();
3509 ch2.port()->KeepAliveUntilPruned();
Honghai Zhanga74363c2016-07-28 18:06:15 -07003510 SIMULATED_WAIT(ports_destroyed() > 0, 150, clock);
3511 EXPECT_EQ(0, ports_destroyed());
honghaizd0b31432015-09-30 12:42:17 -07003512
Honghai Zhanga74363c2016-07-28 18:06:15 -07003513 // If they are pruned now, they will be destroyed right away.
Steve Anton11358fe2018-10-09 15:39:19 -07003514 ch1.port()->Prune();
3515 ch2.port()->Prune();
Honghai Zhanga74363c2016-07-28 18:06:15 -07003516 // The ports on both sides should be destroyed after timeout.
3517 EXPECT_TRUE_SIMULATED_WAIT(ports_destroyed() == 2, 1, clock);
honghaizd0b31432015-09-30 12:42:17 -07003518}
Honghai Zhangf9945b22015-12-15 12:20:13 -08003519
3520TEST_F(PortTest, TestSupportsProtocol) {
Steve Anton11358fe2018-10-09 15:39:19 -07003521 auto udp_port = CreateUdpPort(kLocalAddr1);
Honghai Zhangf9945b22015-12-15 12:20:13 -08003522 EXPECT_TRUE(udp_port->SupportsProtocol(UDP_PROTOCOL_NAME));
3523 EXPECT_FALSE(udp_port->SupportsProtocol(TCP_PROTOCOL_NAME));
3524
Steve Anton11358fe2018-10-09 15:39:19 -07003525 auto stun_port = CreateStunPort(kLocalAddr1, nat_socket_factory1());
Honghai Zhangf9945b22015-12-15 12:20:13 -08003526 EXPECT_TRUE(stun_port->SupportsProtocol(UDP_PROTOCOL_NAME));
3527 EXPECT_FALSE(stun_port->SupportsProtocol(TCP_PROTOCOL_NAME));
3528
Steve Anton11358fe2018-10-09 15:39:19 -07003529 auto tcp_port = CreateTcpPort(kLocalAddr1);
Honghai Zhangf9945b22015-12-15 12:20:13 -08003530 EXPECT_TRUE(tcp_port->SupportsProtocol(TCP_PROTOCOL_NAME));
3531 EXPECT_TRUE(tcp_port->SupportsProtocol(SSLTCP_PROTOCOL_NAME));
3532 EXPECT_FALSE(tcp_port->SupportsProtocol(UDP_PROTOCOL_NAME));
3533
Steve Anton11358fe2018-10-09 15:39:19 -07003534 auto turn_port =
3535 CreateTurnPort(kLocalAddr1, nat_socket_factory1(), PROTO_UDP, PROTO_UDP);
Honghai Zhangf9945b22015-12-15 12:20:13 -08003536 EXPECT_TRUE(turn_port->SupportsProtocol(UDP_PROTOCOL_NAME));
3537 EXPECT_FALSE(turn_port->SupportsProtocol(TCP_PROTOCOL_NAME));
3538}
Taylor Brandstettera1c30352016-05-13 08:15:11 -07003539
3540// Test that SetIceParameters updates the component, ufrag and password
3541// on both the port itself and its candidates.
3542TEST_F(PortTest, TestSetIceParameters) {
Steve Anton11358fe2018-10-09 15:39:19 -07003543 auto port = CreateTestPort(kLocalAddr1, "ufrag1", "password1");
Taylor Brandstettera1c30352016-05-13 08:15:11 -07003544 port->PrepareAddress();
3545 EXPECT_EQ(1UL, port->Candidates().size());
3546 port->SetIceParameters(1, "ufrag2", "password2");
3547 EXPECT_EQ(1, port->component());
3548 EXPECT_EQ("ufrag2", port->username_fragment());
3549 EXPECT_EQ("password2", port->password());
3550 const Candidate& candidate = port->Candidates()[0];
3551 EXPECT_EQ(1, candidate.component());
3552 EXPECT_EQ("ufrag2", candidate.username());
3553 EXPECT_EQ("password2", candidate.password());
3554}
honghaiz36f50e82016-06-01 15:57:03 -07003555
3556TEST_F(PortTest, TestAddConnectionWithSameAddress) {
Steve Anton11358fe2018-10-09 15:39:19 -07003557 auto port = CreateTestPort(kLocalAddr1, "ufrag1", "password1");
honghaiz36f50e82016-06-01 15:57:03 -07003558 port->PrepareAddress();
3559 EXPECT_EQ(1u, port->Candidates().size());
3560 rtc::SocketAddress address("1.1.1.1", 5000);
3561 cricket::Candidate candidate(1, "udp", address, 0, "", "", "relay", 0, "");
3562 cricket::Connection* conn1 =
3563 port->CreateConnection(candidate, Port::ORIGIN_MESSAGE);
3564 cricket::Connection* conn_in_use = port->GetConnection(address);
3565 EXPECT_EQ(conn1, conn_in_use);
3566 EXPECT_EQ(0u, conn_in_use->remote_candidate().generation());
3567
3568 // Creating with a candidate with the same address again will get us a
3569 // different connection with the new candidate.
3570 candidate.set_generation(2);
3571 cricket::Connection* conn2 =
3572 port->CreateConnection(candidate, Port::ORIGIN_MESSAGE);
3573 EXPECT_NE(conn1, conn2);
3574 conn_in_use = port->GetConnection(address);
3575 EXPECT_EQ(conn2, conn_in_use);
3576 EXPECT_EQ(2u, conn_in_use->remote_candidate().generation());
3577
3578 // Make sure the new connection was not deleted.
3579 rtc::Thread::Current()->ProcessMessages(300);
3580 EXPECT_TRUE(port->GetConnection(address) != nullptr);
3581}
Steve Antonbabf9172017-11-29 10:19:02 -08003582
Jonas Orelandef60c2b2020-03-26 15:10:39 +01003583// TODO(webrtc:11463) : Move Connection tests into separate unit test
3584// splitting out shared test code as needed.
3585
3586class ConnectionTest : public PortTest {
3587 public:
3588 ConnectionTest() {
3589 lport_ = CreateTestPort(kLocalAddr1, "lfrag", "lpass");
3590 rport_ = CreateTestPort(kLocalAddr2, "rfrag", "rpass");
3591 lport_->SetIceRole(cricket::ICEROLE_CONTROLLING);
3592 lport_->SetIceTiebreaker(kTiebreaker1);
3593 rport_->SetIceRole(cricket::ICEROLE_CONTROLLED);
3594 rport_->SetIceTiebreaker(kTiebreaker2);
3595
3596 lport_->PrepareAddress();
3597 rport_->PrepareAddress();
3598 }
3599
3600 rtc::ScopedFakeClock clock_;
3601 int num_state_changes_ = 0;
3602
3603 Connection* CreateConnection(IceRole role) {
3604 Connection* conn;
3605 if (role == cricket::ICEROLE_CONTROLLING) {
3606 conn = lport_->CreateConnection(rport_->Candidates()[0],
3607 Port::ORIGIN_MESSAGE);
3608 } else {
3609 conn = rport_->CreateConnection(lport_->Candidates()[0],
3610 Port::ORIGIN_MESSAGE);
3611 }
3612 conn->SignalStateChange.connect(this,
3613 &ConnectionTest::OnConnectionStateChange);
3614 return conn;
3615 }
3616
3617 void SendPingAndCaptureReply(Connection* lconn,
3618 Connection* rconn,
3619 int64_t ms,
3620 rtc::BufferT<uint8_t>* reply) {
3621 TestPort* lport =
3622 lconn->PortForTest() == lport_.get() ? lport_.get() : rport_.get();
3623 TestPort* rport =
3624 rconn->PortForTest() == rport_.get() ? rport_.get() : lport_.get();
3625 lconn->Ping(rtc::TimeMillis());
3626 ASSERT_TRUE_WAIT(lport->last_stun_msg(), kDefaultTimeout);
3627 ASSERT_TRUE(lport->last_stun_buf());
3628 rconn->OnReadPacket(lport->last_stun_buf()->data<char>(),
3629 lport->last_stun_buf()->size(),
3630 /* packet_time_us */ -1);
3631 clock_.AdvanceTime(webrtc::TimeDelta::Millis(ms));
3632 ASSERT_TRUE_WAIT(rport->last_stun_msg(), kDefaultTimeout);
3633 ASSERT_TRUE(rport->last_stun_buf());
3634 *reply = std::move(*rport->last_stun_buf());
3635 }
3636
3637 void SendPingAndReceiveResponse(Connection* lconn,
3638 Connection* rconn,
3639 int64_t ms) {
3640 rtc::BufferT<uint8_t> reply;
3641 SendPingAndCaptureReply(lconn, rconn, ms, &reply);
3642 lconn->OnReadPacket(reply.data<char>(), reply.size(),
3643 /* packet_time_us */ -1);
3644 }
3645
3646 void OnConnectionStateChange(Connection* connection) { num_state_changes_++; }
3647
3648 private:
3649 std::unique_ptr<TestPort> lport_;
3650 std::unique_ptr<TestPort> rport_;
3651};
3652
3653TEST_F(ConnectionTest, ConnectionForgetLearnedState) {
3654 Connection* lconn = CreateConnection(ICEROLE_CONTROLLING);
3655 Connection* rconn = CreateConnection(ICEROLE_CONTROLLED);
3656
3657 EXPECT_FALSE(lconn->writable());
3658 EXPECT_FALSE(lconn->receiving());
3659 EXPECT_TRUE(std::isnan(lconn->GetRttEstimate().GetAverage()));
3660 EXPECT_EQ(lconn->GetRttEstimate().GetVariance(),
3661 std::numeric_limits<double>::infinity());
3662
3663 SendPingAndReceiveResponse(lconn, rconn, 10);
3664
3665 EXPECT_TRUE(lconn->writable());
3666 EXPECT_TRUE(lconn->receiving());
3667 EXPECT_EQ(lconn->GetRttEstimate().GetAverage(), 10);
3668 EXPECT_EQ(lconn->GetRttEstimate().GetVariance(),
3669 std::numeric_limits<double>::infinity());
3670
3671 SendPingAndReceiveResponse(lconn, rconn, 11);
3672
3673 EXPECT_TRUE(lconn->writable());
3674 EXPECT_TRUE(lconn->receiving());
3675 EXPECT_NEAR(lconn->GetRttEstimate().GetAverage(), 10, 0.5);
3676 EXPECT_LT(lconn->GetRttEstimate().GetVariance(),
3677 std::numeric_limits<double>::infinity());
3678
3679 lconn->ForgetLearnedState();
3680
3681 EXPECT_FALSE(lconn->writable());
3682 EXPECT_FALSE(lconn->receiving());
3683 EXPECT_TRUE(std::isnan(lconn->GetRttEstimate().GetAverage()));
3684 EXPECT_EQ(lconn->GetRttEstimate().GetVariance(),
3685 std::numeric_limits<double>::infinity());
3686}
3687
3688TEST_F(ConnectionTest, ConnectionForgetLearnedStateDiscardsPendingPings) {
3689 Connection* lconn = CreateConnection(ICEROLE_CONTROLLING);
3690 Connection* rconn = CreateConnection(ICEROLE_CONTROLLED);
3691
3692 SendPingAndReceiveResponse(lconn, rconn, 10);
3693
3694 EXPECT_TRUE(lconn->writable());
3695 EXPECT_TRUE(lconn->receiving());
3696
3697 rtc::BufferT<uint8_t> reply;
3698 SendPingAndCaptureReply(lconn, rconn, 10, &reply);
3699
3700 lconn->ForgetLearnedState();
3701
3702 EXPECT_FALSE(lconn->writable());
3703 EXPECT_FALSE(lconn->receiving());
3704
3705 lconn->OnReadPacket(reply.data<char>(), reply.size(),
3706 /* packet_time_us */ -1);
3707
3708 // That reply was discarded due to the ForgetLearnedState() while it was
3709 // outstanding.
3710 EXPECT_FALSE(lconn->writable());
3711 EXPECT_FALSE(lconn->receiving());
3712
3713 // But sending a new ping and getting a reply works.
3714 SendPingAndReceiveResponse(lconn, rconn, 11);
3715 EXPECT_TRUE(lconn->writable());
3716 EXPECT_TRUE(lconn->receiving());
3717}
3718
3719TEST_F(ConnectionTest, ConnectionForgetLearnedStateDoesNotTriggerStateChange) {
3720 Connection* lconn = CreateConnection(ICEROLE_CONTROLLING);
3721 Connection* rconn = CreateConnection(ICEROLE_CONTROLLED);
3722
3723 EXPECT_EQ(num_state_changes_, 0);
3724 SendPingAndReceiveResponse(lconn, rconn, 10);
3725
3726 EXPECT_TRUE(lconn->writable());
3727 EXPECT_TRUE(lconn->receiving());
3728 EXPECT_EQ(num_state_changes_, 2);
3729
3730 lconn->ForgetLearnedState();
3731
3732 EXPECT_FALSE(lconn->writable());
3733 EXPECT_FALSE(lconn->receiving());
3734 EXPECT_EQ(num_state_changes_, 2);
3735}
3736
Steve Antonbabf9172017-11-29 10:19:02 -08003737} // namespace cricket