1269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org/*
2269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
3269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org *
4269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org *  Use of this source code is governed by a BSD-style license
5269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org *  that can be found in the LICENSE file in the root of the source
6269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org *  tree. An additional intellectual property rights grant can be found
7269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org *  in the file PATENTS.  All contributing project authors may
8269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org */
10269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
11269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/p2p/base/basicpacketsocketfactory.h"
12269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/p2p/base/relayport.h"
13269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/p2p/base/stunport.h"
14269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/p2p/base/tcpport.h"
15269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/p2p/base/testrelayserver.h"
16269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/p2p/base/teststunserver.h"
17269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/p2p/base/testturnserver.h"
18269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/p2p/base/transport.h"
19269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/p2p/base/turnport.h"
205237aaf243d29732f59557361b7a993c0a18cf0etfarina#include "webrtc/base/arraysize.h"
21269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/crc32.h"
22269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/gunit.h"
23269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/helpers.h"
24269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/logging.h"
25269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/natserver.h"
26269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/natsocketfactory.h"
27269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/physicalsocketserver.h"
28269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/scoped_ptr.h"
29269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/socketaddress.h"
30269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/ssladapter.h"
31269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/stringutils.h"
32269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/thread.h"
33269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/virtualsocketserver.h"
34269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
35269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgusing rtc::AsyncPacketSocket;
36269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgusing rtc::ByteBuffer;
37269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgusing rtc::NATType;
38269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgusing rtc::NAT_OPEN_CONE;
39269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgusing rtc::NAT_ADDR_RESTRICTED;
40269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgusing rtc::NAT_PORT_RESTRICTED;
41269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgusing rtc::NAT_SYMMETRIC;
42269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgusing rtc::PacketSocketFactory;
43269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgusing rtc::scoped_ptr;
44269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgusing rtc::Socket;
45269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgusing rtc::SocketAddress;
46269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgusing namespace cricket;
47269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
48269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgstatic const int kTimeout = 1000;
49269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgstatic const SocketAddress kLocalAddr1("192.168.1.2", 0);
50269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgstatic const SocketAddress kLocalAddr2("192.168.1.3", 0);
51c5d0d95fd8957a7a6645b1196e5f1e9cee33525cdeadbeefstatic const SocketAddress kNatAddr1("77.77.77.77", rtc::NAT_SERVER_UDP_PORT);
52c5d0d95fd8957a7a6645b1196e5f1e9cee33525cdeadbeefstatic const SocketAddress kNatAddr2("88.88.88.88", rtc::NAT_SERVER_UDP_PORT);
53269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgstatic const SocketAddress kStunAddr("99.99.99.1", STUN_SERVER_PORT);
54269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgstatic const SocketAddress kRelayUdpIntAddr("99.99.99.2", 5000);
55269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgstatic const SocketAddress kRelayUdpExtAddr("99.99.99.3", 5001);
56269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgstatic const SocketAddress kRelayTcpIntAddr("99.99.99.2", 5002);
57269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgstatic const SocketAddress kRelayTcpExtAddr("99.99.99.3", 5003);
58269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgstatic const SocketAddress kRelaySslTcpIntAddr("99.99.99.2", 5004);
59269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgstatic const SocketAddress kRelaySslTcpExtAddr("99.99.99.3", 5005);
60269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgstatic const SocketAddress kTurnUdpIntAddr("99.99.99.4", STUN_SERVER_PORT);
61269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgstatic const SocketAddress kTurnUdpExtAddr("99.99.99.5", 0);
62269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgstatic const RelayCredentials kRelayCredentials("test", "test");
63269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
64269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// TODO: Update these when RFC5245 is completely supported.
65269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Magic value of 30 is from RFC3484, for IPv4 addresses.
660c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströmstatic const uint32_t kDefaultPrflxPriority =
670c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    ICE_TYPE_PREFERENCE_PRFLX << 24 | 30 << 8 |
680c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    (256 - ICE_CANDIDATE_COMPONENT_DEFAULT);
69269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
70269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgstatic const int kTiebreaker1 = 11111;
71269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgstatic const int kTiebreaker2 = 22222;
72269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
73be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shiehstatic const char* data = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
74be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh
75269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgstatic Candidate GetCandidate(Port* port) {
767cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher  assert(port->Candidates().size() >= 1);
77269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  return port->Candidates()[0];
78269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
79269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
80269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgstatic SocketAddress GetAddress(Port* port) {
81269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  return GetCandidate(port).address();
82269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
83269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
84269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgstatic IceMessage* CopyStunMessage(const IceMessage* src) {
85269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  IceMessage* dst = new IceMessage();
86269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ByteBuffer buf;
87269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  src->Write(&buf);
88269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  dst->Read(&buf);
89269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  return dst;
90269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
91269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
92269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgstatic bool WriteStunMessage(const StunMessage* msg, ByteBuffer* buf) {
93269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  buf->Resize(0);  // clear out any existing buffer contents
94269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  return msg->Write(buf);
95269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
96269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
97269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Stub port class for testing STUN generation and processing.
98269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgclass TestPort : public Port {
99269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org public:
100332331fb01f8a316ac6d61cf4572478610fb3472pkasting@chromium.org  TestPort(rtc::Thread* thread,
101332331fb01f8a316ac6d61cf4572478610fb3472pkasting@chromium.org           const std::string& type,
102332331fb01f8a316ac6d61cf4572478610fb3472pkasting@chromium.org           rtc::PacketSocketFactory* factory,
103332331fb01f8a316ac6d61cf4572478610fb3472pkasting@chromium.org           rtc::Network* network,
104332331fb01f8a316ac6d61cf4572478610fb3472pkasting@chromium.org           const rtc::IPAddress& ip,
1050c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström           uint16_t min_port,
1060c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström           uint16_t max_port,
107332331fb01f8a316ac6d61cf4572478610fb3472pkasting@chromium.org           const std::string& username_fragment,
108332331fb01f8a316ac6d61cf4572478610fb3472pkasting@chromium.org           const std::string& password)
1090c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      : Port(thread,
1100c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström             type,
1110c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström             factory,
1120c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström             network,
1130c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström             ip,
1140c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström             min_port,
1150c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström             max_port,
1160c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström             username_fragment,
1170c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström             password) {}
118269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ~TestPort() {}
119269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
120269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Expose GetStunMessage so that we can test it.
121269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  using cricket::Port::GetStunMessage;
122269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
123269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // The last StunMessage that was sent on this Port.
124269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // TODO: Make these const; requires changes to SendXXXXResponse.
125269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ByteBuffer* last_stun_buf() { return last_stun_buf_.get(); }
126269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  IceMessage* last_stun_msg() { return last_stun_msg_.get(); }
127269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  int last_stun_error_code() {
128269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    int code = 0;
129269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    if (last_stun_msg_) {
130269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      const StunErrorCodeAttribute* error_attr = last_stun_msg_->GetErrorCode();
131269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      if (error_attr) {
132269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        code = error_attr->code();
133269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      }
134269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    }
135269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return code;
136269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
137269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
138269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  virtual void PrepareAddress() {
139269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    rtc::SocketAddress addr(ip(), min_port());
1403d564c10157d7de1d2d4236f4e2a13ff1363d52bGuo-wei Shieh    AddAddress(addr, addr, rtc::SocketAddress(), "udp", "", "", Type(),
141269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org               ICE_TYPE_PREFERENCE_HOST, 0, true);
142269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
143269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
144f9945b2d1aa2d78b19987219ea872605167d7b5fHonghai Zhang  virtual bool SupportsProtocol(const std::string& protocol) const {
145f9945b2d1aa2d78b19987219ea872605167d7b5fHonghai Zhang    return true;
146f9945b2d1aa2d78b19987219ea872605167d7b5fHonghai Zhang  }
147f9945b2d1aa2d78b19987219ea872605167d7b5fHonghai Zhang
148269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Exposed for testing candidate building.
149269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  void AddCandidateAddress(const rtc::SocketAddress& addr) {
1503d564c10157d7de1d2d4236f4e2a13ff1363d52bGuo-wei Shieh    AddAddress(addr, addr, rtc::SocketAddress(), "udp", "", "", Type(),
151269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org               type_preference_, 0, false);
152269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
153269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  void AddCandidateAddress(const rtc::SocketAddress& addr,
154269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                           const rtc::SocketAddress& base_address,
155269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                           const std::string& type,
156269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                           int type_preference,
157269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                           bool final) {
1583d564c10157d7de1d2d4236f4e2a13ff1363d52bGuo-wei Shieh    AddAddress(addr, base_address, rtc::SocketAddress(), "udp", "", "", type,
159269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org               type_preference, 0, final);
160269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
161269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
162269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  virtual Connection* CreateConnection(const Candidate& remote_candidate,
163269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                       CandidateOrigin origin) {
164269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    Connection* conn = new ProxyConnection(this, 0, remote_candidate);
165269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    AddConnection(conn);
166269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    // Set use-candidate attribute flag as this will add USE-CANDIDATE attribute
167269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    // in STUN binding requests.
168269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    conn->set_use_candidate_attr(true);
169269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return conn;
170269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
171269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  virtual int SendTo(
172269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      const void* data, size_t size, const rtc::SocketAddress& addr,
173269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      const rtc::PacketOptions& options, bool payload) {
174269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    if (!payload) {
175269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      IceMessage* msg = new IceMessage;
176269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      ByteBuffer* buf = new ByteBuffer(static_cast<const char*>(data), size);
177269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      ByteBuffer::ReadPosition pos(buf->GetReadPosition());
178269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      if (!msg->Read(buf)) {
179269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        delete msg;
180269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        delete buf;
181269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        return -1;
182269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      }
183269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      buf->SetReadPosition(pos);
184269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      last_stun_buf_.reset(buf);
185269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      last_stun_msg_.reset(msg);
186269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    }
187269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return static_cast<int>(size);
188269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
189269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  virtual int SetOption(rtc::Socket::Option opt, int value) {
190269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return 0;
191269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
192269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  virtual int GetOption(rtc::Socket::Option opt, int* value) {
193269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return -1;
194269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
195269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  virtual int GetError() {
196269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return 0;
197269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
198269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  void Reset() {
199269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    last_stun_buf_.reset();
200269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    last_stun_msg_.reset();
201269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
202269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  void set_type_preference(int type_preference) {
203269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    type_preference_ = type_preference;
204269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
205269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
206269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org private:
20755674ffb32307c6f3efaab442340d3c5c075073bStefan Holmer  void OnSentPacket(rtc::AsyncPacketSocket* socket,
20855674ffb32307c6f3efaab442340d3c5c075073bStefan Holmer                    const rtc::SentPacket& sent_packet) {
20955674ffb32307c6f3efaab442340d3c5c075073bStefan Holmer    PortInterface::SignalSentPacket(sent_packet);
21055674ffb32307c6f3efaab442340d3c5c075073bStefan Holmer  }
211269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<ByteBuffer> last_stun_buf_;
212269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<IceMessage> last_stun_msg_;
2137640ffabd74a79bf4b40688a4b664950a846e989pbos  int type_preference_ = 0;
214269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org};
215269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
216269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgclass TestChannel : public sigslot::has_slots<> {
217269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org public:
218269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Takes ownership of |p1| (but not |p2|).
2191eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh  TestChannel(Port* p1)
2201eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh      : ice_mode_(ICEMODE_FULL),
2211eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh        port_(p1),
2221eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh        complete_count_(0),
2231eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh        conn_(NULL),
2241eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh        remote_request_(),
2251eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh        nominated_(false) {
2261eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh    port_->SignalPortComplete.connect(this, &TestChannel::OnPortComplete);
2271eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh    port_->SignalUnknownAddress.connect(this, &TestChannel::OnUnknownAddress);
2281eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh    port_->SignalDestroyed.connect(this, &TestChannel::OnSrcPortDestroyed);
229269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
230269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
231269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  int complete_count() { return complete_count_; }
232269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  Connection* conn() { return conn_; }
233269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  const SocketAddress& remote_address() { return remote_address_; }
234269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  const std::string remote_fragment() { return remote_frag_; }
235269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2361eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh  void Start() { port_->PrepareAddress(); }
2371eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh  void CreateConnection(const Candidate& remote_candidate) {
2381eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh    conn_ = port_->CreateConnection(remote_candidate, Port::ORIGIN_MESSAGE);
239269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    IceMode remote_ice_mode =
240269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        (ice_mode_ == ICEMODE_FULL) ? ICEMODE_LITE : ICEMODE_FULL;
241269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    conn_->set_remote_ice_mode(remote_ice_mode);
242269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    conn_->set_use_candidate_attr(remote_ice_mode == ICEMODE_FULL);
243269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    conn_->SignalStateChange.connect(
244269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        this, &TestChannel::OnConnectionStateChange);
245be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    conn_->SignalDestroyed.connect(this, &TestChannel::OnDestroyed);
246b594041ec8a3ae9f501260e2456d9d5ce6482819Guo-wei Shieh    conn_->SignalReadyToSend.connect(this,
247b594041ec8a3ae9f501260e2456d9d5ce6482819Guo-wei Shieh                                     &TestChannel::OnConnectionReadyToSend);
248b594041ec8a3ae9f501260e2456d9d5ce6482819Guo-wei Shieh    connection_ready_to_send_ = false;
249269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
250269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  void OnConnectionStateChange(Connection* conn) {
251269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    if (conn->write_state() == Connection::STATE_WRITABLE) {
252269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      conn->set_use_candidate_attr(true);
253269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      nominated_ = true;
254269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    }
255269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
2561eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh  void AcceptConnection(const Candidate& remote_candidate) {
257269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    ASSERT_TRUE(remote_request_.get() != NULL);
2581eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh    Candidate c = remote_candidate;
259269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    c.set_address(remote_address_);
2601eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh    conn_ = port_->CreateConnection(c, Port::ORIGIN_MESSAGE);
261be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    conn_->SignalDestroyed.connect(this, &TestChannel::OnDestroyed);
2621eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh    port_->SendBindingResponse(remote_request_.get(), remote_address_);
263269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    remote_request_.reset();
264269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
265269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  void Ping() {
266269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    Ping(0);
267269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
2680c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  void Ping(uint32_t now) { conn_->Ping(now); }
269269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  void Stop() {
270be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    if (conn_) {
271be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh      conn_->Destroy();
272be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    }
273269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
274269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
275269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  void OnPortComplete(Port* port) {
276269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    complete_count_++;
277269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
278269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  void SetIceMode(IceMode ice_mode) {
279269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    ice_mode_ = ice_mode;
280269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
281269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
282be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  int SendData(const char* data, size_t len) {
283be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    rtc::PacketOptions options;
284be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    return conn_->Send(data, len, options);
285be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  }
286be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh
287269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  void OnUnknownAddress(PortInterface* port, const SocketAddress& addr,
288269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                        ProtocolType proto,
289269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                        IceMessage* msg, const std::string& rf,
290269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                        bool /*port_muxed*/) {
2911eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh    ASSERT_EQ(port_.get(), port);
292269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    if (!remote_address_.IsNil()) {
293269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      ASSERT_EQ(remote_address_, addr);
294269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    }
295269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    const cricket::StunUInt32Attribute* priority_attr =
296269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        msg->GetUInt32(STUN_ATTR_PRIORITY);
297269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    const cricket::StunByteStringAttribute* mi_attr =
298269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        msg->GetByteString(STUN_ATTR_MESSAGE_INTEGRITY);
299269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    const cricket::StunUInt32Attribute* fingerprint_attr =
300269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        msg->GetUInt32(STUN_ATTR_FINGERPRINT);
3017cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    EXPECT_TRUE(priority_attr != NULL);
3027cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    EXPECT_TRUE(mi_attr != NULL);
3037cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    EXPECT_TRUE(fingerprint_attr != NULL);
304269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    remote_address_ = addr;
305269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    remote_request_.reset(CopyStunMessage(msg));
306269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    remote_frag_ = rf;
307269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
308269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
309269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  void OnDestroyed(Connection* conn) {
310269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    ASSERT_EQ(conn_, conn);
311be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    LOG(INFO) << "OnDestroy connection " << conn << " deleted";
312269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    conn_ = NULL;
313be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    // When the connection is destroyed, also clear these fields so future
314be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    // connections are possible.
315be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    remote_request_.reset();
316be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    remote_address_.Clear();
317269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
318269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
319269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  void OnSrcPortDestroyed(PortInterface* port) {
3201eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh    Port* destroyed_src = port_.release();
321269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    ASSERT_EQ(destroyed_src, port);
322269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
323269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
3241eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh  Port* port() { return port_.get(); }
325be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh
326269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  bool nominated() const { return nominated_; }
327269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
328b594041ec8a3ae9f501260e2456d9d5ce6482819Guo-wei Shieh  void set_connection_ready_to_send(bool ready) {
329b594041ec8a3ae9f501260e2456d9d5ce6482819Guo-wei Shieh    connection_ready_to_send_ = ready;
330b594041ec8a3ae9f501260e2456d9d5ce6482819Guo-wei Shieh  }
331b594041ec8a3ae9f501260e2456d9d5ce6482819Guo-wei Shieh  bool connection_ready_to_send() const {
332b594041ec8a3ae9f501260e2456d9d5ce6482819Guo-wei Shieh    return connection_ready_to_send_;
333b594041ec8a3ae9f501260e2456d9d5ce6482819Guo-wei Shieh  }
334b594041ec8a3ae9f501260e2456d9d5ce6482819Guo-wei Shieh
335269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org private:
336b594041ec8a3ae9f501260e2456d9d5ce6482819Guo-wei Shieh  // ReadyToSend will only issue after a Connection recovers from EWOULDBLOCK.
337b594041ec8a3ae9f501260e2456d9d5ce6482819Guo-wei Shieh  void OnConnectionReadyToSend(Connection* conn) {
338b594041ec8a3ae9f501260e2456d9d5ce6482819Guo-wei Shieh    ASSERT_EQ(conn, conn_);
339b594041ec8a3ae9f501260e2456d9d5ce6482819Guo-wei Shieh    connection_ready_to_send_ = true;
340b594041ec8a3ae9f501260e2456d9d5ce6482819Guo-wei Shieh  }
341b594041ec8a3ae9f501260e2456d9d5ce6482819Guo-wei Shieh
342269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  IceMode ice_mode_;
3431eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh  rtc::scoped_ptr<Port> port_;
344269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
345269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  int complete_count_;
346269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  Connection* conn_;
347269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  SocketAddress remote_address_;
348269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<StunMessage> remote_request_;
349269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  std::string remote_frag_;
350269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  bool nominated_;
351b594041ec8a3ae9f501260e2456d9d5ce6482819Guo-wei Shieh  bool connection_ready_to_send_ = false;
352269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org};
353269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
354269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgclass PortTest : public testing::Test, public sigslot::has_slots<> {
355269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org public:
356269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  PortTest()
357269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      : main_(rtc::Thread::Current()),
358269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        pss_(new rtc::PhysicalSocketServer),
359269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        ss_(new rtc::VirtualSocketServer(pss_.get())),
360269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        ss_scope_(ss_.get()),
361269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        network_("unittest", "unittest", rtc::IPAddress(INADDR_ANY), 32),
362269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        socket_factory_(rtc::Thread::Current()),
363c5d0d95fd8957a7a6645b1196e5f1e9cee33525cdeadbeef        nat_factory1_(ss_.get(), kNatAddr1, SocketAddress()),
364c5d0d95fd8957a7a6645b1196e5f1e9cee33525cdeadbeef        nat_factory2_(ss_.get(), kNatAddr2, SocketAddress()),
365269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        nat_socket_factory1_(&nat_factory1_),
366269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        nat_socket_factory2_(&nat_factory2_),
367269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        stun_server_(TestStunServer::Create(main_, kStunAddr)),
368269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        turn_server_(main_, kTurnUdpIntAddr, kTurnUdpExtAddr),
369be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh        relay_server_(main_,
370be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh                      kRelayUdpIntAddr,
371be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh                      kRelayUdpExtAddr,
372be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh                      kRelayTcpIntAddr,
373be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh                      kRelayTcpExtAddr,
374be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh                      kRelaySslTcpIntAddr,
375be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh                      kRelaySslTcpExtAddr),
376269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        username_(rtc::CreateRandomString(ICE_UFRAG_LENGTH)),
377269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        password_(rtc::CreateRandomString(ICE_PWD_LENGTH)),
378269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        role_conflict_(false),
379269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        destroyed_(false) {
380269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    network_.AddIP(rtc::IPAddress(INADDR_ANY));
381269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
382269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
383269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org protected:
384269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  void TestLocalToLocal() {
385269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    Port* port1 = CreateUdpPort(kLocalAddr1);
3867cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    port1->SetIceRole(cricket::ICEROLE_CONTROLLING);
387269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    Port* port2 = CreateUdpPort(kLocalAddr2);
3887cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    port2->SetIceRole(cricket::ICEROLE_CONTROLLED);
389269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    TestConnectivity("udp", port1, "udp", port2, true, true, true, true);
390269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
391269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  void TestLocalToStun(NATType ntype) {
392269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    Port* port1 = CreateUdpPort(kLocalAddr1);
3937cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    port1->SetIceRole(cricket::ICEROLE_CONTROLLING);
394269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    nat_server2_.reset(CreateNatServer(kNatAddr2, ntype));
395269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    Port* port2 = CreateStunPort(kLocalAddr2, &nat_socket_factory2_);
3967cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    port2->SetIceRole(cricket::ICEROLE_CONTROLLED);
397269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    TestConnectivity("udp", port1, StunName(ntype), port2,
398269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                     ntype == NAT_OPEN_CONE, true,
399269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                     ntype != NAT_SYMMETRIC, true);
400269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
401269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  void TestLocalToRelay(RelayType rtype, ProtocolType proto) {
402269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    Port* port1 = CreateUdpPort(kLocalAddr1);
4037cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    port1->SetIceRole(cricket::ICEROLE_CONTROLLING);
404269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    Port* port2 = CreateRelayPort(kLocalAddr2, rtype, proto, PROTO_UDP);
4057cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    port2->SetIceRole(cricket::ICEROLE_CONTROLLED);
406269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    TestConnectivity("udp", port1, RelayName(rtype, proto), port2,
407269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                     rtype == RELAY_GTURN, true, true, true);
408269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
409269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  void TestStunToLocal(NATType ntype) {
410269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    nat_server1_.reset(CreateNatServer(kNatAddr1, ntype));
411269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    Port* port1 = CreateStunPort(kLocalAddr1, &nat_socket_factory1_);
4127cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    port1->SetIceRole(cricket::ICEROLE_CONTROLLING);
413269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    Port* port2 = CreateUdpPort(kLocalAddr2);
4147cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    port2->SetIceRole(cricket::ICEROLE_CONTROLLED);
415269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    TestConnectivity(StunName(ntype), port1, "udp", port2,
416269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                     true, ntype != NAT_SYMMETRIC, true, true);
417269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
418269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  void TestStunToStun(NATType ntype1, NATType ntype2) {
419269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    nat_server1_.reset(CreateNatServer(kNatAddr1, ntype1));
420269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    Port* port1 = CreateStunPort(kLocalAddr1, &nat_socket_factory1_);
4217cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    port1->SetIceRole(cricket::ICEROLE_CONTROLLING);
422269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    nat_server2_.reset(CreateNatServer(kNatAddr2, ntype2));
423269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    Port* port2 = CreateStunPort(kLocalAddr2, &nat_socket_factory2_);
4247cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    port2->SetIceRole(cricket::ICEROLE_CONTROLLED);
425269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    TestConnectivity(StunName(ntype1), port1, StunName(ntype2), port2,
426269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                     ntype2 == NAT_OPEN_CONE,
427269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                     ntype1 != NAT_SYMMETRIC, ntype2 != NAT_SYMMETRIC,
428269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                     ntype1 + ntype2 < (NAT_PORT_RESTRICTED + NAT_SYMMETRIC));
429269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
430269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  void TestStunToRelay(NATType ntype, RelayType rtype, ProtocolType proto) {
431269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    nat_server1_.reset(CreateNatServer(kNatAddr1, ntype));
432269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    Port* port1 = CreateStunPort(kLocalAddr1, &nat_socket_factory1_);
4337cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    port1->SetIceRole(cricket::ICEROLE_CONTROLLING);
434269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    Port* port2 = CreateRelayPort(kLocalAddr2, rtype, proto, PROTO_UDP);
4357cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    port2->SetIceRole(cricket::ICEROLE_CONTROLLED);
436269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    TestConnectivity(StunName(ntype), port1, RelayName(rtype, proto), port2,
437269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                     rtype == RELAY_GTURN, ntype != NAT_SYMMETRIC, true, true);
438269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
439269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  void TestTcpToTcp() {
440269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    Port* port1 = CreateTcpPort(kLocalAddr1);
4417cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    port1->SetIceRole(cricket::ICEROLE_CONTROLLING);
442269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    Port* port2 = CreateTcpPort(kLocalAddr2);
4437cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    port2->SetIceRole(cricket::ICEROLE_CONTROLLED);
444269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    TestConnectivity("tcp", port1, "tcp", port2, true, false, true, true);
445269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
446269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  void TestTcpToRelay(RelayType rtype, ProtocolType proto) {
447269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    Port* port1 = CreateTcpPort(kLocalAddr1);
4487cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    port1->SetIceRole(cricket::ICEROLE_CONTROLLING);
449269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    Port* port2 = CreateRelayPort(kLocalAddr2, rtype, proto, PROTO_TCP);
4507cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    port2->SetIceRole(cricket::ICEROLE_CONTROLLED);
451269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    TestConnectivity("tcp", port1, RelayName(rtype, proto), port2,
452269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                     rtype == RELAY_GTURN, false, true, true);
453269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
454269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  void TestSslTcpToRelay(RelayType rtype, ProtocolType proto) {
455269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    Port* port1 = CreateTcpPort(kLocalAddr1);
4567cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    port1->SetIceRole(cricket::ICEROLE_CONTROLLING);
457269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    Port* port2 = CreateRelayPort(kLocalAddr2, rtype, proto, PROTO_SSLTCP);
4587cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    port2->SetIceRole(cricket::ICEROLE_CONTROLLED);
459269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    TestConnectivity("ssltcp", port1, RelayName(rtype, proto), port2,
460269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                     rtype == RELAY_GTURN, false, true, true);
461269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
462269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // helpers for above functions
463269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  UDPPort* CreateUdpPort(const SocketAddress& addr) {
464269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return CreateUdpPort(addr, &socket_factory_);
465269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
466269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  UDPPort* CreateUdpPort(const SocketAddress& addr,
467269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                         PacketSocketFactory* socket_factory) {
4689af97f89103d8f1f77b52a6ae77b8b7bcdc23f71Guo-wei Shieh    return UDPPort::Create(main_, socket_factory, &network_, addr.ipaddr(), 0,
4699af97f89103d8f1f77b52a6ae77b8b7bcdc23f71Guo-wei Shieh                           0, username_, password_, std::string(), true);
470269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
471269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TCPPort* CreateTcpPort(const SocketAddress& addr) {
4727cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    return CreateTcpPort(addr, &socket_factory_);
473269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
474269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TCPPort* CreateTcpPort(const SocketAddress& addr,
475269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                        PacketSocketFactory* socket_factory) {
4767cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    return TCPPort::Create(main_, socket_factory, &network_,
4777cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher                           addr.ipaddr(), 0, 0, username_, password_,
4787cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher                           true);
479269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
480269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  StunPort* CreateStunPort(const SocketAddress& addr,
481269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                           rtc::PacketSocketFactory* factory) {
482269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    ServerAddresses stun_servers;
483269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    stun_servers.insert(kStunAddr);
4847cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    return StunPort::Create(main_, factory, &network_,
4857cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher                            addr.ipaddr(), 0, 0,
4867cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher                            username_, password_, stun_servers,
4877cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher                            std::string());
488269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
489269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  Port* CreateRelayPort(const SocketAddress& addr, RelayType rtype,
490269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                        ProtocolType int_proto, ProtocolType ext_proto) {
491269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    if (rtype == RELAY_TURN) {
492269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      return CreateTurnPort(addr, &socket_factory_, int_proto, ext_proto);
493269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    } else {
494269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      return CreateGturnPort(addr, int_proto, ext_proto);
495269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    }
496269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
497269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TurnPort* CreateTurnPort(const SocketAddress& addr,
498269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                           PacketSocketFactory* socket_factory,
499269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                           ProtocolType int_proto, ProtocolType ext_proto) {
500269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return CreateTurnPort(addr, socket_factory,
501269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                          int_proto, ext_proto, kTurnUdpIntAddr);
502269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
503269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TurnPort* CreateTurnPort(const SocketAddress& addr,
504269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                           PacketSocketFactory* socket_factory,
505269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                           ProtocolType int_proto, ProtocolType ext_proto,
506269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                           const rtc::SocketAddress& server_addr) {
5077cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    return TurnPort::Create(main_, socket_factory, &network_,
5087cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher                            addr.ipaddr(), 0, 0,
5097cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher                            username_, password_, ProtocolAddress(
5107cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher                                server_addr, PROTO_UDP),
5117cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher                            kRelayCredentials, 0,
5127cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher                            std::string());
513269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
514269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  RelayPort* CreateGturnPort(const SocketAddress& addr,
515269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                             ProtocolType int_proto, ProtocolType ext_proto) {
516269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    RelayPort* port = CreateGturnPort(addr);
517269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    SocketAddress addrs[] =
518269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        { kRelayUdpIntAddr, kRelayTcpIntAddr, kRelaySslTcpIntAddr };
519269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    port->AddServerAddress(ProtocolAddress(addrs[int_proto], int_proto));
520269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return port;
521269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
522269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  RelayPort* CreateGturnPort(const SocketAddress& addr) {
5237cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    // TODO(pthatcher):  Remove GTURN.
5247cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    return RelayPort::Create(main_, &socket_factory_, &network_,
5257cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher                             addr.ipaddr(), 0, 0,
5267cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher                             username_, password_);
527269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    // TODO: Add an external address for ext_proto, so that the
528269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    // other side can connect to this port using a non-UDP protocol.
529269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
530269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::NATServer* CreateNatServer(const SocketAddress& addr,
531269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                        rtc::NATType type) {
532c5d0d95fd8957a7a6645b1196e5f1e9cee33525cdeadbeef    return new rtc::NATServer(type, ss_.get(), addr, addr, ss_.get(), addr);
533269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
534269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  static const char* StunName(NATType type) {
535269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    switch (type) {
536269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      case NAT_OPEN_CONE:       return "stun(open cone)";
537269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      case NAT_ADDR_RESTRICTED: return "stun(addr restricted)";
538269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      case NAT_PORT_RESTRICTED: return "stun(port restricted)";
539269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      case NAT_SYMMETRIC:       return "stun(symmetric)";
540269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      default:                  return "stun(?)";
541269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    }
542269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
543269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  static const char* RelayName(RelayType type, ProtocolType proto) {
544269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    if (type == RELAY_TURN) {
545269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      switch (proto) {
546269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        case PROTO_UDP:           return "turn(udp)";
547269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        case PROTO_TCP:           return "turn(tcp)";
548269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        case PROTO_SSLTCP:        return "turn(ssltcp)";
549269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        default:                  return "turn(?)";
550269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      }
551269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    } else {
552269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      switch (proto) {
553269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        case PROTO_UDP:           return "gturn(udp)";
554269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        case PROTO_TCP:           return "gturn(tcp)";
555269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        case PROTO_SSLTCP:        return "gturn(ssltcp)";
556269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        default:                  return "gturn(?)";
557269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      }
558269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    }
559269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
560269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
561269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  void TestCrossFamilyPorts(int type);
562269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
563b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher  void ExpectPortsCanConnect(bool can_connect, Port* p1, Port* p2);
564b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher
565269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // This does all the work and then deletes |port1| and |port2|.
566269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  void TestConnectivity(const char* name1, Port* port1,
567269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                        const char* name2, Port* port2,
568269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                        bool accept, bool same_addr1,
569269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                        bool same_addr2, bool possible);
570269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
571be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  // This connects the provided channels which have already started.  |ch1|
572be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  // should have its Connection created (either through CreateConnection() or
573be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  // TCP reconnecting mechanism before entering this function.
574be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  void ConnectStartedChannels(TestChannel* ch1, TestChannel* ch2) {
575be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    ASSERT_TRUE(ch1->conn());
576be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    EXPECT_TRUE_WAIT(ch1->conn()->connected(), kTimeout);  // for TCP connect
577be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    ch1->Ping();
578be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    WAIT(!ch2->remote_address().IsNil(), kTimeout);
579be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh
580be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    // Send a ping from dst to src.
5811eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh    ch2->AcceptConnection(GetCandidate(ch1->port()));
582be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    ch2->Ping();
583be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    EXPECT_EQ_WAIT(Connection::STATE_WRITABLE, ch2->conn()->write_state(),
584be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh                   kTimeout);
585be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  }
586be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh
587269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // This connects and disconnects the provided channels in the same sequence as
588269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // TestConnectivity with all options set to |true|.  It does not delete either
589269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // channel.
590be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  void StartConnectAndStopChannels(TestChannel* ch1, TestChannel* ch2) {
591be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    // Acquire addresses.
592be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    ch1->Start();
593be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    ch2->Start();
594be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh
5951eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh    ch1->CreateConnection(GetCandidate(ch2->port()));
596be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    ConnectStartedChannels(ch1, ch2);
597be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh
598be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    // Destroy the connections.
599be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    ch1->Stop();
600be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    ch2->Stop();
601be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  }
602be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh
603be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  // This disconnects both end's Connection and make sure ch2 ready for new
604be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  // connection.
605be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  void DisconnectTcpTestChannels(TestChannel* ch1, TestChannel* ch2) {
6061eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh    TCPConnection* tcp_conn1 = static_cast<TCPConnection*>(ch1->conn());
6071eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh    TCPConnection* tcp_conn2 = static_cast<TCPConnection*>(ch2->conn());
6081eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh    ASSERT_TRUE(
6091eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh        ss_->CloseTcpConnections(tcp_conn1->socket()->GetLocalAddress(),
6101eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh                                 tcp_conn2->socket()->GetLocalAddress()));
611be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh
612be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    // Wait for both OnClose are delivered.
613be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    EXPECT_TRUE_WAIT(!ch1->conn()->connected(), kTimeout);
614be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    EXPECT_TRUE_WAIT(!ch2->conn()->connected(), kTimeout);
615be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh
6161eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh    // Ensure redundant SignalClose events on TcpConnection won't break tcp
6171eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh    // reconnection. Chromium will fire SignalClose for all outstanding IPC
6181eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh    // packets during reconnection.
6191eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh    tcp_conn1->socket()->SignalClose(tcp_conn1->socket(), 0);
6201eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh    tcp_conn2->socket()->SignalClose(tcp_conn2->socket(), 0);
6211eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh
6221eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh    // Speed up destroying ch2's connection such that the test is ready to
6231eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh    // accept a new connection from ch1 before ch1's connection destroys itself.
624be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    ch2->conn()->Destroy();
625be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    EXPECT_TRUE_WAIT(ch2->conn() == NULL, kTimeout);
626be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  }
627be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh
628be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  void TestTcpReconnect(bool ping_after_disconnected,
629be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh                        bool send_after_disconnected) {
630be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    Port* port1 = CreateTcpPort(kLocalAddr1);
6317cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    port1->SetIceRole(cricket::ICEROLE_CONTROLLING);
632be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    Port* port2 = CreateTcpPort(kLocalAddr2);
6337cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher    port2->SetIceRole(cricket::ICEROLE_CONTROLLED);
634be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh
635be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    port1->set_component(cricket::ICE_CANDIDATE_COMPONENT_DEFAULT);
636be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    port2->set_component(cricket::ICE_CANDIDATE_COMPONENT_DEFAULT);
637be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh
638be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    // Set up channels and ensure both ports will be deleted.
6391eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh    TestChannel ch1(port1);
6401eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh    TestChannel ch2(port2);
641be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    EXPECT_EQ(0, ch1.complete_count());
642be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    EXPECT_EQ(0, ch2.complete_count());
643be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh
644be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    ch1.Start();
645be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    ch2.Start();
646be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    ASSERT_EQ_WAIT(1, ch1.complete_count(), kTimeout);
647be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    ASSERT_EQ_WAIT(1, ch2.complete_count(), kTimeout);
648be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh
649be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    // Initial connecting the channel, create connection on channel1.
6501eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh    ch1.CreateConnection(GetCandidate(port2));
651be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    ConnectStartedChannels(&ch1, &ch2);
652be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh
653be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    // Shorten the timeout period.
654be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    const int kTcpReconnectTimeout = kTimeout;
655be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    static_cast<TCPConnection*>(ch1.conn())
656be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh        ->set_reconnection_timeout(kTcpReconnectTimeout);
657be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    static_cast<TCPConnection*>(ch2.conn())
658be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh        ->set_reconnection_timeout(kTcpReconnectTimeout);
659be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh
660b594041ec8a3ae9f501260e2456d9d5ce6482819Guo-wei Shieh    EXPECT_FALSE(ch1.connection_ready_to_send());
661b594041ec8a3ae9f501260e2456d9d5ce6482819Guo-wei Shieh    EXPECT_FALSE(ch2.connection_ready_to_send());
662b594041ec8a3ae9f501260e2456d9d5ce6482819Guo-wei Shieh
663be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    // Once connected, disconnect them.
664be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    DisconnectTcpTestChannels(&ch1, &ch2);
665be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh
666be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    if (send_after_disconnected || ping_after_disconnected) {
667be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh      if (send_after_disconnected) {
668be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh        // First SendData after disconnect should fail but will trigger
669be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh        // reconnect.
670be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh        EXPECT_EQ(-1, ch1.SendData(data, static_cast<int>(strlen(data))));
671be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh      }
672be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh
673be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh      if (ping_after_disconnected) {
674be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh        // Ping should trigger reconnect.
675be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh        ch1.Ping();
676be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh      }
677be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh
678be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh      // Wait for channel's outgoing TCPConnection connected.
679be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh      EXPECT_TRUE_WAIT(ch1.conn()->connected(), kTimeout);
680be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh
681be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh      // Verify that we could still connect channels.
682be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh      ConnectStartedChannels(&ch1, &ch2);
683b594041ec8a3ae9f501260e2456d9d5ce6482819Guo-wei Shieh      EXPECT_TRUE_WAIT(ch1.connection_ready_to_send(),
684b594041ec8a3ae9f501260e2456d9d5ce6482819Guo-wei Shieh                       kTcpReconnectTimeout);
685b594041ec8a3ae9f501260e2456d9d5ce6482819Guo-wei Shieh      // Channel2 is the passive one so a new connection is created during
686b594041ec8a3ae9f501260e2456d9d5ce6482819Guo-wei Shieh      // reconnect. This new connection should never have issued EWOULDBLOCK
687b594041ec8a3ae9f501260e2456d9d5ce6482819Guo-wei Shieh      // hence the connection_ready_to_send() should be false.
688b594041ec8a3ae9f501260e2456d9d5ce6482819Guo-wei Shieh      EXPECT_FALSE(ch2.connection_ready_to_send());
689be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    } else {
690be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh      EXPECT_EQ(ch1.conn()->write_state(), Connection::STATE_WRITABLE);
6911eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh      // Since the reconnection never happens, the connections should have been
6921eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh      // destroyed after the timeout.
6931eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh      EXPECT_TRUE_WAIT(!ch1.conn(), kTcpReconnectTimeout + kTimeout);
6941eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh      EXPECT_TRUE(!ch2.conn());
695be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    }
696be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh
697be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    // Tear down and ensure that goes smoothly.
698be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    ch1.Stop();
699be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    ch2.Stop();
700be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    EXPECT_TRUE_WAIT(ch1.conn() == NULL, kTimeout);
701be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh    EXPECT_TRUE_WAIT(ch2.conn() == NULL, kTimeout);
702be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  }
703269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
704269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  IceMessage* CreateStunMessage(int type) {
705269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    IceMessage* msg = new IceMessage();
706269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    msg->SetType(type);
707269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    msg->SetTransactionID("TESTTESTTEST");
708269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return msg;
709269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
710269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  IceMessage* CreateStunMessageWithUsername(int type,
711269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                            const std::string& username) {
712269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    IceMessage* msg = CreateStunMessage(type);
713269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    msg->AddAttribute(
714269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        new StunByteStringAttribute(STUN_ATTR_USERNAME, username));
715269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return msg;
716269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
717269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestPort* CreateTestPort(const rtc::SocketAddress& addr,
718269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                           const std::string& username,
719269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                           const std::string& password) {
720269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    TestPort* port =  new TestPort(main_, "test", &socket_factory_, &network_,
721269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                   addr.ipaddr(), 0, 0, username, password);
722269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    port->SignalRoleConflict.connect(this, &PortTest::OnRoleConflict);
723269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return port;
724269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
725269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestPort* CreateTestPort(const rtc::SocketAddress& addr,
726269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                           const std::string& username,
727269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                           const std::string& password,
728269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                           cricket::IceRole role,
729269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                           int tiebreaker) {
730269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    TestPort* port = CreateTestPort(addr, username, password);
731269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    port->SetIceRole(role);
732269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    port->SetIceTiebreaker(tiebreaker);
733269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return port;
734269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
735269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
736269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  void OnRoleConflict(PortInterface* port) {
737269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    role_conflict_ = true;
738269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
739269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  bool role_conflict() const { return role_conflict_; }
740269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
741269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  void ConnectToSignalDestroyed(PortInterface* port) {
742269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    port->SignalDestroyed.connect(this, &PortTest::OnDestroyed);
743269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
744269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
745269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  void OnDestroyed(PortInterface* port) {
746269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    destroyed_ = true;
747269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
748269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  bool destroyed() const { return destroyed_; }
749269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
750269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::BasicPacketSocketFactory* nat_socket_factory1() {
751269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return &nat_socket_factory1_;
752269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
753269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
7541eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh protected:
7551eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh  rtc::VirtualSocketServer* vss() { return ss_.get(); }
7561eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh
757269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org private:
758269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::Thread* main_;
759269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<rtc::PhysicalSocketServer> pss_;
760269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<rtc::VirtualSocketServer> ss_;
761269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::SocketServerScope ss_scope_;
762269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::Network network_;
763269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::BasicPacketSocketFactory socket_factory_;
764269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<rtc::NATServer> nat_server1_;
765269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<rtc::NATServer> nat_server2_;
766269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::NATSocketFactory nat_factory1_;
767269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::NATSocketFactory nat_factory2_;
768269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::BasicPacketSocketFactory nat_socket_factory1_;
769269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::BasicPacketSocketFactory nat_socket_factory2_;
770269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  scoped_ptr<TestStunServer> stun_server_;
771269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestTurnServer turn_server_;
772269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestRelayServer relay_server_;
773269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  std::string username_;
774269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  std::string password_;
775269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  bool role_conflict_;
776269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  bool destroyed_;
777269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org};
778269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
779269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid PortTest::TestConnectivity(const char* name1, Port* port1,
780269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                const char* name2, Port* port2,
781269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                bool accept, bool same_addr1,
782269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                bool same_addr2, bool possible) {
783269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  LOG(LS_INFO) << "Test: " << name1 << " to " << name2 << ": ";
784269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  port1->set_component(cricket::ICE_CANDIDATE_COMPONENT_DEFAULT);
785269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  port2->set_component(cricket::ICE_CANDIDATE_COMPONENT_DEFAULT);
786269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
787269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Set up channels and ensure both ports will be deleted.
7881eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh  TestChannel ch1(port1);
7891eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh  TestChannel ch2(port2);
790269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(0, ch1.complete_count());
791269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(0, ch2.complete_count());
792269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
793269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Acquire addresses.
794269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ch1.Start();
795269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ch2.Start();
796269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_EQ_WAIT(1, ch1.complete_count(), kTimeout);
797269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_EQ_WAIT(1, ch2.complete_count(), kTimeout);
798269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
799269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Send a ping from src to dst. This may or may not make it.
8001eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh  ch1.CreateConnection(GetCandidate(port2));
801269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_TRUE(ch1.conn() != NULL);
802269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE_WAIT(ch1.conn()->connected(), kTimeout);  // for TCP connect
803269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ch1.Ping();
804269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  WAIT(!ch2.remote_address().IsNil(), kTimeout);
805269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
806269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (accept) {
807269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    // We are able to send a ping from src to dst. This is the case when
808269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    // sending to UDP ports and cone NATs.
809269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    EXPECT_TRUE(ch1.remote_address().IsNil());
810269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    EXPECT_EQ(ch2.remote_fragment(), port1->username_fragment());
811269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
812269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    // Ensure the ping came from the same address used for src.
813269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    // This is the case unless the source NAT was symmetric.
814269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    if (same_addr1) EXPECT_EQ(ch2.remote_address(), GetAddress(port1));
815269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    EXPECT_TRUE(same_addr2);
816269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
817269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    // Send a ping from dst to src.
8181eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh    ch2.AcceptConnection(GetCandidate(port1));
819269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    ASSERT_TRUE(ch2.conn() != NULL);
820269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    ch2.Ping();
821269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    EXPECT_EQ_WAIT(Connection::STATE_WRITABLE, ch2.conn()->write_state(),
822269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                   kTimeout);
823269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  } else {
824269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    // We can't send a ping from src to dst, so flip it around. This will happen
825269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    // when the destination NAT is addr/port restricted or symmetric.
826269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    EXPECT_TRUE(ch1.remote_address().IsNil());
827269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    EXPECT_TRUE(ch2.remote_address().IsNil());
828269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
829269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    // Send a ping from dst to src. Again, this may or may not make it.
8301eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh    ch2.CreateConnection(GetCandidate(port1));
831269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    ASSERT_TRUE(ch2.conn() != NULL);
832269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    ch2.Ping();
833269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    WAIT(ch2.conn()->write_state() == Connection::STATE_WRITABLE, kTimeout);
834269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
835269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    if (same_addr1 && same_addr2) {
836269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      // The new ping got back to the source.
83704ac81f2fd8ef6680522438fac1894db5415a0ecPeter Thatcher      EXPECT_TRUE(ch1.conn()->receiving());
838269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      EXPECT_EQ(Connection::STATE_WRITABLE, ch2.conn()->write_state());
839269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
840269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      // First connection may not be writable if the first ping did not get
841269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      // through.  So we will have to do another.
842269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      if (ch1.conn()->write_state() == Connection::STATE_WRITE_INIT) {
843269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        ch1.Ping();
844269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        EXPECT_EQ_WAIT(Connection::STATE_WRITABLE, ch1.conn()->write_state(),
845269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                       kTimeout);
846269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      }
847269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    } else if (!same_addr1 && possible) {
848269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      // The new ping went to the candidate address, but that address was bad.
849269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      // This will happen when the source NAT is symmetric.
850269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      EXPECT_TRUE(ch1.remote_address().IsNil());
851269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      EXPECT_TRUE(ch2.remote_address().IsNil());
852269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
853269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      // However, since we have now sent a ping to the source IP, we should be
854269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      // able to get a ping from it. This gives us the real source address.
855269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      ch1.Ping();
856269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      EXPECT_TRUE_WAIT(!ch2.remote_address().IsNil(), kTimeout);
85704ac81f2fd8ef6680522438fac1894db5415a0ecPeter Thatcher      EXPECT_FALSE(ch2.conn()->receiving());
858269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      EXPECT_TRUE(ch1.remote_address().IsNil());
859269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
860269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      // Pick up the actual address and establish the connection.
8611eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh      ch2.AcceptConnection(GetCandidate(port1));
862269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      ASSERT_TRUE(ch2.conn() != NULL);
863269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      ch2.Ping();
864269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      EXPECT_EQ_WAIT(Connection::STATE_WRITABLE, ch2.conn()->write_state(),
865269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                     kTimeout);
866269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    } else if (!same_addr2 && possible) {
867269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      // The new ping came in, but from an unexpected address. This will happen
868269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      // when the destination NAT is symmetric.
869269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      EXPECT_FALSE(ch1.remote_address().IsNil());
87004ac81f2fd8ef6680522438fac1894db5415a0ecPeter Thatcher      EXPECT_FALSE(ch1.conn()->receiving());
871269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
872269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      // Update our address and complete the connection.
8731eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh      ch1.AcceptConnection(GetCandidate(port2));
874269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      ch1.Ping();
875269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      EXPECT_EQ_WAIT(Connection::STATE_WRITABLE, ch1.conn()->write_state(),
876269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                     kTimeout);
877269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    } else {  // (!possible)
878269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      // There should be s no way for the pings to reach each other. Check it.
879269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      EXPECT_TRUE(ch1.remote_address().IsNil());
880269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      EXPECT_TRUE(ch2.remote_address().IsNil());
881269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      ch1.Ping();
882269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      WAIT(!ch2.remote_address().IsNil(), kTimeout);
883269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      EXPECT_TRUE(ch1.remote_address().IsNil());
884269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      EXPECT_TRUE(ch2.remote_address().IsNil());
885269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    }
886269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
887269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
888269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Everything should be good, unless we know the situation is impossible.
889269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_TRUE(ch1.conn() != NULL);
890269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_TRUE(ch2.conn() != NULL);
891269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (possible) {
89204ac81f2fd8ef6680522438fac1894db5415a0ecPeter Thatcher    EXPECT_TRUE(ch1.conn()->receiving());
893269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    EXPECT_EQ(Connection::STATE_WRITABLE, ch1.conn()->write_state());
89404ac81f2fd8ef6680522438fac1894db5415a0ecPeter Thatcher    EXPECT_TRUE(ch2.conn()->receiving());
895269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    EXPECT_EQ(Connection::STATE_WRITABLE, ch2.conn()->write_state());
896269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  } else {
89704ac81f2fd8ef6680522438fac1894db5415a0ecPeter Thatcher    EXPECT_FALSE(ch1.conn()->receiving());
898269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    EXPECT_NE(Connection::STATE_WRITABLE, ch1.conn()->write_state());
89904ac81f2fd8ef6680522438fac1894db5415a0ecPeter Thatcher    EXPECT_FALSE(ch2.conn()->receiving());
900269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    EXPECT_NE(Connection::STATE_WRITABLE, ch2.conn()->write_state());
901269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
902269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
903269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Tear down and ensure that goes smoothly.
904269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ch1.Stop();
905269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ch2.Stop();
906269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE_WAIT(ch1.conn() == NULL, kTimeout);
907269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE_WAIT(ch2.conn() == NULL, kTimeout);
908269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
909269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
910269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgclass FakePacketSocketFactory : public rtc::PacketSocketFactory {
911269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org public:
912269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  FakePacketSocketFactory()
913269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      : next_udp_socket_(NULL),
914269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        next_server_tcp_socket_(NULL),
915269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        next_client_tcp_socket_(NULL) {
916269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
917332331fb01f8a316ac6d61cf4572478610fb3472pkasting@chromium.org  ~FakePacketSocketFactory() override { }
918269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
919332331fb01f8a316ac6d61cf4572478610fb3472pkasting@chromium.org  AsyncPacketSocket* CreateUdpSocket(const SocketAddress& address,
9200c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                                     uint16_t min_port,
9210c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                                     uint16_t max_port) override {
922269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    EXPECT_TRUE(next_udp_socket_ != NULL);
923269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    AsyncPacketSocket* result = next_udp_socket_;
924269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    next_udp_socket_ = NULL;
925269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return result;
926269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
927269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
928332331fb01f8a316ac6d61cf4572478610fb3472pkasting@chromium.org  AsyncPacketSocket* CreateServerTcpSocket(const SocketAddress& local_address,
9290c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                                           uint16_t min_port,
9300c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                                           uint16_t max_port,
931332331fb01f8a316ac6d61cf4572478610fb3472pkasting@chromium.org                                           int opts) override {
932269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    EXPECT_TRUE(next_server_tcp_socket_ != NULL);
933269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    AsyncPacketSocket* result = next_server_tcp_socket_;
934269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    next_server_tcp_socket_ = NULL;
935269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return result;
936269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
937269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
938269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // TODO: |proxy_info| and |user_agent| should be set
939269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // per-factory and not when socket is created.
940332331fb01f8a316ac6d61cf4572478610fb3472pkasting@chromium.org  AsyncPacketSocket* CreateClientTcpSocket(const SocketAddress& local_address,
941332331fb01f8a316ac6d61cf4572478610fb3472pkasting@chromium.org                                           const SocketAddress& remote_address,
942332331fb01f8a316ac6d61cf4572478610fb3472pkasting@chromium.org                                           const rtc::ProxyInfo& proxy_info,
943332331fb01f8a316ac6d61cf4572478610fb3472pkasting@chromium.org                                           const std::string& user_agent,
944332331fb01f8a316ac6d61cf4572478610fb3472pkasting@chromium.org                                           int opts) override {
945269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    EXPECT_TRUE(next_client_tcp_socket_ != NULL);
946269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    AsyncPacketSocket* result = next_client_tcp_socket_;
947269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    next_client_tcp_socket_ = NULL;
948269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return result;
949269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
950269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
951269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  void set_next_udp_socket(AsyncPacketSocket* next_udp_socket) {
952269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    next_udp_socket_ = next_udp_socket;
953269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
954269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  void set_next_server_tcp_socket(AsyncPacketSocket* next_server_tcp_socket) {
955269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    next_server_tcp_socket_ = next_server_tcp_socket;
956269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
957269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  void set_next_client_tcp_socket(AsyncPacketSocket* next_client_tcp_socket) {
958269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    next_client_tcp_socket_ = next_client_tcp_socket;
959269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
960269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::AsyncResolverInterface* CreateAsyncResolver() {
961269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return NULL;
962269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
963269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
964269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org private:
965269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  AsyncPacketSocket* next_udp_socket_;
966269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  AsyncPacketSocket* next_server_tcp_socket_;
967269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  AsyncPacketSocket* next_client_tcp_socket_;
968269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org};
969269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
970269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgclass FakeAsyncPacketSocket : public AsyncPacketSocket {
971269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org public:
972269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Returns current local address. Address may be set to NULL if the
973269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // socket is not bound yet (GetState() returns STATE_BINDING).
974269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  virtual SocketAddress GetLocalAddress() const {
975269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return SocketAddress();
976269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
977269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
978269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Returns remote address. Returns zeroes if this is not a client TCP socket.
979269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  virtual SocketAddress GetRemoteAddress() const {
980269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return SocketAddress();
981269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
982269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
983269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Send a packet.
984269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  virtual int Send(const void *pv, size_t cb,
985269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                   const rtc::PacketOptions& options) {
986269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return static_cast<int>(cb);
987269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
988269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  virtual int SendTo(const void *pv, size_t cb, const SocketAddress& addr,
989269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                     const rtc::PacketOptions& options) {
990269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return static_cast<int>(cb);
991269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
992269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  virtual int Close() {
993269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return 0;
994269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
995269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
996269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  virtual State GetState() const { return state_; }
997269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  virtual int GetOption(Socket::Option opt, int* value) { return 0; }
998269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  virtual int SetOption(Socket::Option opt, int value) { return 0; }
999269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  virtual int GetError() const { return 0; }
1000269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  virtual void SetError(int error) { }
1001269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1002269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  void set_state(State state) { state_ = state; }
1003269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1004269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org private:
1005269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  State state_;
1006269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org};
1007269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1008269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Local -> XXXX
1009269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestLocalToLocal) {
1010269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestLocalToLocal();
1011269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1012269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1013269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestLocalToConeNat) {
1014269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestLocalToStun(NAT_OPEN_CONE);
1015269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1016269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1017269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestLocalToARNat) {
1018269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestLocalToStun(NAT_ADDR_RESTRICTED);
1019269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1020269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1021269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestLocalToPRNat) {
1022269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestLocalToStun(NAT_PORT_RESTRICTED);
1023269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1024269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1025269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestLocalToSymNat) {
1026269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestLocalToStun(NAT_SYMMETRIC);
1027269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1028269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1029269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Flaky: https://code.google.com/p/webrtc/issues/detail?id=3316.
1030269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, DISABLED_TestLocalToTurn) {
1031269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestLocalToRelay(RELAY_TURN, PROTO_UDP);
1032269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1033269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1034269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestLocalToGturn) {
1035269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestLocalToRelay(RELAY_GTURN, PROTO_UDP);
1036269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1037269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1038269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestLocalToTcpGturn) {
1039269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestLocalToRelay(RELAY_GTURN, PROTO_TCP);
1040269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1041269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1042269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestLocalToSslTcpGturn) {
1043269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestLocalToRelay(RELAY_GTURN, PROTO_SSLTCP);
1044269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1045269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1046269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Cone NAT -> XXXX
1047269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestConeNatToLocal) {
1048269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestStunToLocal(NAT_OPEN_CONE);
1049269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1050269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1051269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestConeNatToConeNat) {
1052269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestStunToStun(NAT_OPEN_CONE, NAT_OPEN_CONE);
1053269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1054269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1055269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestConeNatToARNat) {
1056269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestStunToStun(NAT_OPEN_CONE, NAT_ADDR_RESTRICTED);
1057269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1058269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1059269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestConeNatToPRNat) {
1060269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestStunToStun(NAT_OPEN_CONE, NAT_PORT_RESTRICTED);
1061269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1062269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1063269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestConeNatToSymNat) {
1064269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestStunToStun(NAT_OPEN_CONE, NAT_SYMMETRIC);
1065269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1066269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1067269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestConeNatToTurn) {
1068269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestStunToRelay(NAT_OPEN_CONE, RELAY_TURN, PROTO_UDP);
1069269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1070269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1071269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestConeNatToGturn) {
1072269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestStunToRelay(NAT_OPEN_CONE, RELAY_GTURN, PROTO_UDP);
1073269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1074269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1075269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestConeNatToTcpGturn) {
1076269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestStunToRelay(NAT_OPEN_CONE, RELAY_GTURN, PROTO_TCP);
1077269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1078269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1079269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Address-restricted NAT -> XXXX
1080269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestARNatToLocal) {
1081269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestStunToLocal(NAT_ADDR_RESTRICTED);
1082269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1083269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1084269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestARNatToConeNat) {
1085269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestStunToStun(NAT_ADDR_RESTRICTED, NAT_OPEN_CONE);
1086269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1087269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1088269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestARNatToARNat) {
1089269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestStunToStun(NAT_ADDR_RESTRICTED, NAT_ADDR_RESTRICTED);
1090269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1091269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1092269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestARNatToPRNat) {
1093269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestStunToStun(NAT_ADDR_RESTRICTED, NAT_PORT_RESTRICTED);
1094269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1095269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1096269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestARNatToSymNat) {
1097269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestStunToStun(NAT_ADDR_RESTRICTED, NAT_SYMMETRIC);
1098269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1099269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1100269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestARNatToTurn) {
1101269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestStunToRelay(NAT_ADDR_RESTRICTED, RELAY_TURN, PROTO_UDP);
1102269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1103269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1104269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestARNatToGturn) {
1105269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestStunToRelay(NAT_ADDR_RESTRICTED, RELAY_GTURN, PROTO_UDP);
1106269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1107269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1108269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestARNATNatToTcpGturn) {
1109269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestStunToRelay(NAT_ADDR_RESTRICTED, RELAY_GTURN, PROTO_TCP);
1110269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1111269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1112269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Port-restricted NAT -> XXXX
1113269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestPRNatToLocal) {
1114269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestStunToLocal(NAT_PORT_RESTRICTED);
1115269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1116269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1117269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestPRNatToConeNat) {
1118269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestStunToStun(NAT_PORT_RESTRICTED, NAT_OPEN_CONE);
1119269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1120269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1121269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestPRNatToARNat) {
1122269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestStunToStun(NAT_PORT_RESTRICTED, NAT_ADDR_RESTRICTED);
1123269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1124269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1125269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestPRNatToPRNat) {
1126269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestStunToStun(NAT_PORT_RESTRICTED, NAT_PORT_RESTRICTED);
1127269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1128269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1129269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestPRNatToSymNat) {
1130269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Will "fail"
1131269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestStunToStun(NAT_PORT_RESTRICTED, NAT_SYMMETRIC);
1132269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1133269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1134269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestPRNatToTurn) {
1135269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestStunToRelay(NAT_PORT_RESTRICTED, RELAY_TURN, PROTO_UDP);
1136269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1137269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1138269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestPRNatToGturn) {
1139269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestStunToRelay(NAT_PORT_RESTRICTED, RELAY_GTURN, PROTO_UDP);
1140269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1141269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1142269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestPRNatToTcpGturn) {
1143269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestStunToRelay(NAT_PORT_RESTRICTED, RELAY_GTURN, PROTO_TCP);
1144269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1145269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1146269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Symmetric NAT -> XXXX
1147269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestSymNatToLocal) {
1148269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestStunToLocal(NAT_SYMMETRIC);
1149269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1150269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1151269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestSymNatToConeNat) {
1152269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestStunToStun(NAT_SYMMETRIC, NAT_OPEN_CONE);
1153269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1154269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1155269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestSymNatToARNat) {
1156269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestStunToStun(NAT_SYMMETRIC, NAT_ADDR_RESTRICTED);
1157269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1158269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1159269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestSymNatToPRNat) {
1160269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Will "fail"
1161269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestStunToStun(NAT_SYMMETRIC, NAT_PORT_RESTRICTED);
1162269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1163269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1164269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestSymNatToSymNat) {
1165269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Will "fail"
1166269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestStunToStun(NAT_SYMMETRIC, NAT_SYMMETRIC);
1167269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1168269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1169269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestSymNatToTurn) {
1170269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestStunToRelay(NAT_SYMMETRIC, RELAY_TURN, PROTO_UDP);
1171269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1172269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1173269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestSymNatToGturn) {
1174269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestStunToRelay(NAT_SYMMETRIC, RELAY_GTURN, PROTO_UDP);
1175269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1176269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1177269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestSymNatToTcpGturn) {
1178269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestStunToRelay(NAT_SYMMETRIC, RELAY_GTURN, PROTO_TCP);
1179269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1180269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1181269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Outbound TCP -> XXXX
1182269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestTcpToTcp) {
1183269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestTcpToTcp();
1184269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1185269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1186be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei ShiehTEST_F(PortTest, TestTcpReconnectOnSendPacket) {
1187be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  TestTcpReconnect(false /* ping */, true /* send */);
1188be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh}
1189be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh
1190be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei ShiehTEST_F(PortTest, TestTcpReconnectOnPing) {
1191be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  TestTcpReconnect(true /* ping */, false /* send */);
1192be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh}
1193be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh
1194be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei ShiehTEST_F(PortTest, TestTcpReconnectTimeout) {
1195be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  TestTcpReconnect(false /* ping */, false /* send */);
1196be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh}
1197be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh
11981eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh// Test when TcpConnection never connects, the OnClose() will be called to
11991eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh// destroy the connection.
12001eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei ShiehTEST_F(PortTest, TestTcpNeverConnect) {
12011eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh  Port* port1 = CreateTcpPort(kLocalAddr1);
12021eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh  port1->SetIceRole(cricket::ICEROLE_CONTROLLING);
12031eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh  port1->set_component(cricket::ICE_CANDIDATE_COMPONENT_DEFAULT);
12041eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh
12051eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh  // Set up a channel and ensure the port will be deleted.
12061eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh  TestChannel ch1(port1);
12071eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh  EXPECT_EQ(0, ch1.complete_count());
12081eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh
12091eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh  ch1.Start();
12101eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh  ASSERT_EQ_WAIT(1, ch1.complete_count(), kTimeout);
12111eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh
12121eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh  rtc::scoped_ptr<rtc::AsyncSocket> server(
12131eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh      vss()->CreateAsyncSocket(kLocalAddr2.family(), SOCK_STREAM));
12141eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh  // Bind but not listen.
12151eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh  EXPECT_EQ(0, server->Bind(kLocalAddr2));
12161eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh
12171eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh  Candidate c = GetCandidate(port1);
12181eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh  c.set_address(server->GetLocalAddress());
12191eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh
12201eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh  ch1.CreateConnection(c);
12211eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh  EXPECT_TRUE(ch1.conn());
12221eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh  EXPECT_TRUE_WAIT(!ch1.conn(), kTimeout);  // for TCP connect
12231eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh}
12241eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh
1225269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org/* TODO: Enable these once testrelayserver can accept external TCP.
1226269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestTcpToTcpRelay) {
1227269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestTcpToRelay(PROTO_TCP);
1228269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1229269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1230269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestTcpToSslTcpRelay) {
1231269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestTcpToRelay(PROTO_SSLTCP);
1232269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1233269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org*/
1234269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1235269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Outbound SSLTCP -> XXXX
1236269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org/* TODO: Enable these once testrelayserver can accept external SSL.
1237269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestSslTcpToTcpRelay) {
1238269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestSslTcpToRelay(PROTO_TCP);
1239269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1240269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1241269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestSslTcpToSslTcpRelay) {
1242269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestSslTcpToRelay(PROTO_SSLTCP);
1243269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1244269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org*/
1245269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
12462cd7afe7e2dc011ab00bdbc131039b16aa8fbdebHonghai Zhang// Test that a connection will be dead and deleted if
12472cd7afe7e2dc011ab00bdbc131039b16aa8fbdebHonghai Zhang// i) it has never received anything for MIN_CONNECTION_LIFETIME milliseconds
12482cd7afe7e2dc011ab00bdbc131039b16aa8fbdebHonghai Zhang//    since it was created, or
12492cd7afe7e2dc011ab00bdbc131039b16aa8fbdebHonghai Zhang// ii) it has not received anything for DEAD_CONNECTION_RECEIVE_TIMEOUT
12502cd7afe7e2dc011ab00bdbc131039b16aa8fbdebHonghai Zhang//     milliseconds since last receiving.
12512cd7afe7e2dc011ab00bdbc131039b16aa8fbdebHonghai ZhangTEST_F(PortTest, TestConnectionDead) {
12522cd7afe7e2dc011ab00bdbc131039b16aa8fbdebHonghai Zhang  UDPPort* port1 = CreateUdpPort(kLocalAddr1);
12532cd7afe7e2dc011ab00bdbc131039b16aa8fbdebHonghai Zhang  UDPPort* port2 = CreateUdpPort(kLocalAddr2);
12542cd7afe7e2dc011ab00bdbc131039b16aa8fbdebHonghai Zhang  TestChannel ch1(port1);
12552cd7afe7e2dc011ab00bdbc131039b16aa8fbdebHonghai Zhang  TestChannel ch2(port2);
12562cd7afe7e2dc011ab00bdbc131039b16aa8fbdebHonghai Zhang  // Acquire address.
12572cd7afe7e2dc011ab00bdbc131039b16aa8fbdebHonghai Zhang  ch1.Start();
12582cd7afe7e2dc011ab00bdbc131039b16aa8fbdebHonghai Zhang  ch2.Start();
12592cd7afe7e2dc011ab00bdbc131039b16aa8fbdebHonghai Zhang  ASSERT_EQ_WAIT(1, ch1.complete_count(), kTimeout);
12602cd7afe7e2dc011ab00bdbc131039b16aa8fbdebHonghai Zhang  ASSERT_EQ_WAIT(1, ch2.complete_count(), kTimeout);
12612cd7afe7e2dc011ab00bdbc131039b16aa8fbdebHonghai Zhang
126237389b42b4f42c49583b5fa187611cdb6dcd67b4honghaiz  // Test case that the connection has never received anything.
12632cd7afe7e2dc011ab00bdbc131039b16aa8fbdebHonghai Zhang  uint32_t before_created = rtc::Time();
12642cd7afe7e2dc011ab00bdbc131039b16aa8fbdebHonghai Zhang  ch1.CreateConnection(GetCandidate(port2));
12652cd7afe7e2dc011ab00bdbc131039b16aa8fbdebHonghai Zhang  uint32_t after_created = rtc::Time();
12662cd7afe7e2dc011ab00bdbc131039b16aa8fbdebHonghai Zhang  Connection* conn = ch1.conn();
12672cd7afe7e2dc011ab00bdbc131039b16aa8fbdebHonghai Zhang  ASSERT(conn != nullptr);
126837389b42b4f42c49583b5fa187611cdb6dcd67b4honghaiz  // It is not dead if it is after MIN_CONNECTION_LIFETIME but not pruned.
126937389b42b4f42c49583b5fa187611cdb6dcd67b4honghaiz  conn->UpdateState(after_created + MIN_CONNECTION_LIFETIME + 1);
127037389b42b4f42c49583b5fa187611cdb6dcd67b4honghaiz  rtc::Thread::Current()->ProcessMessages(0);
127137389b42b4f42c49583b5fa187611cdb6dcd67b4honghaiz  EXPECT_TRUE(ch1.conn() != nullptr);
127237389b42b4f42c49583b5fa187611cdb6dcd67b4honghaiz  // It is not dead if it is before MIN_CONNECTION_LIFETIME and pruned.
12732cd7afe7e2dc011ab00bdbc131039b16aa8fbdebHonghai Zhang  conn->UpdateState(before_created + MIN_CONNECTION_LIFETIME - 1);
127437389b42b4f42c49583b5fa187611cdb6dcd67b4honghaiz  conn->Prune();
127537389b42b4f42c49583b5fa187611cdb6dcd67b4honghaiz  rtc::Thread::Current()->ProcessMessages(0);
12762cd7afe7e2dc011ab00bdbc131039b16aa8fbdebHonghai Zhang  EXPECT_TRUE(ch1.conn() != nullptr);
127737389b42b4f42c49583b5fa187611cdb6dcd67b4honghaiz  // It will be dead after MIN_CONNECTION_LIFETIME and pruned.
12782cd7afe7e2dc011ab00bdbc131039b16aa8fbdebHonghai Zhang  conn->UpdateState(after_created + MIN_CONNECTION_LIFETIME + 1);
12792cd7afe7e2dc011ab00bdbc131039b16aa8fbdebHonghai Zhang  EXPECT_TRUE_WAIT(ch1.conn() == nullptr, kTimeout);
12802cd7afe7e2dc011ab00bdbc131039b16aa8fbdebHonghai Zhang
128137389b42b4f42c49583b5fa187611cdb6dcd67b4honghaiz  // Test case that the connection has received something.
12822cd7afe7e2dc011ab00bdbc131039b16aa8fbdebHonghai Zhang  // Create a connection again and receive a ping.
12832cd7afe7e2dc011ab00bdbc131039b16aa8fbdebHonghai Zhang  ch1.CreateConnection(GetCandidate(port2));
12842cd7afe7e2dc011ab00bdbc131039b16aa8fbdebHonghai Zhang  conn = ch1.conn();
12852cd7afe7e2dc011ab00bdbc131039b16aa8fbdebHonghai Zhang  ASSERT(conn != nullptr);
12862cd7afe7e2dc011ab00bdbc131039b16aa8fbdebHonghai Zhang  uint32_t before_last_receiving = rtc::Time();
12872cd7afe7e2dc011ab00bdbc131039b16aa8fbdebHonghai Zhang  conn->ReceivedPing();
12882cd7afe7e2dc011ab00bdbc131039b16aa8fbdebHonghai Zhang  uint32_t after_last_receiving = rtc::Time();
12892cd7afe7e2dc011ab00bdbc131039b16aa8fbdebHonghai Zhang  // The connection will be dead after DEAD_CONNECTION_RECEIVE_TIMEOUT
12902cd7afe7e2dc011ab00bdbc131039b16aa8fbdebHonghai Zhang  conn->UpdateState(
12912cd7afe7e2dc011ab00bdbc131039b16aa8fbdebHonghai Zhang      before_last_receiving + DEAD_CONNECTION_RECEIVE_TIMEOUT - 1);
12922cd7afe7e2dc011ab00bdbc131039b16aa8fbdebHonghai Zhang  rtc::Thread::Current()->ProcessMessages(100);
12932cd7afe7e2dc011ab00bdbc131039b16aa8fbdebHonghai Zhang  EXPECT_TRUE(ch1.conn() != nullptr);
12942cd7afe7e2dc011ab00bdbc131039b16aa8fbdebHonghai Zhang  conn->UpdateState(after_last_receiving + DEAD_CONNECTION_RECEIVE_TIMEOUT + 1);
12952cd7afe7e2dc011ab00bdbc131039b16aa8fbdebHonghai Zhang  EXPECT_TRUE_WAIT(ch1.conn() == nullptr, kTimeout);
12962cd7afe7e2dc011ab00bdbc131039b16aa8fbdebHonghai Zhang}
12972cd7afe7e2dc011ab00bdbc131039b16aa8fbdebHonghai Zhang
1298269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// This test case verifies standard ICE features in STUN messages. Currently it
1299269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// verifies Message Integrity attribute in STUN messages and username in STUN
1300269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// binding request will have colon (":") between remote and local username.
13017cbd188c5ed7df80bb737bd4ada94422730e2d89Peter ThatcherTEST_F(PortTest, TestLocalToLocalStandard) {
1302269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  UDPPort* port1 = CreateUdpPort(kLocalAddr1);
1303269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  port1->SetIceRole(cricket::ICEROLE_CONTROLLING);
1304269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  port1->SetIceTiebreaker(kTiebreaker1);
1305269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  UDPPort* port2 = CreateUdpPort(kLocalAddr2);
1306269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  port2->SetIceRole(cricket::ICEROLE_CONTROLLED);
1307269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  port2->SetIceTiebreaker(kTiebreaker2);
1308269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Same parameters as TestLocalToLocal above.
1309269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestConnectivity("udp", port1, "udp", port2, true, true, true, true);
1310269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1311269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1312269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// This test is trying to validate a successful and failure scenario in a
1313269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// loopback test when protocol is RFC5245. For success IceTiebreaker, username
1314269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// should remain equal to the request generated by the port and role of port
1315269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// must be in controlling.
13167cbd188c5ed7df80bb737bd4ada94422730e2d89Peter ThatcherTEST_F(PortTest, TestLoopbackCal) {
1317269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<TestPort> lport(
1318269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      CreateTestPort(kLocalAddr1, "lfrag", "lpass"));
1319269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  lport->SetIceRole(cricket::ICEROLE_CONTROLLING);
1320269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  lport->SetIceTiebreaker(kTiebreaker1);
1321269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  lport->PrepareAddress();
1322269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_FALSE(lport->Candidates().empty());
1323269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  Connection* conn = lport->CreateConnection(lport->Candidates()[0],
1324269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                             Port::ORIGIN_MESSAGE);
1325269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  conn->Ping(0);
1326269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1327269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_TRUE_WAIT(lport->last_stun_msg() != NULL, 1000);
1328269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  IceMessage* msg = lport->last_stun_msg();
1329269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(STUN_BINDING_REQUEST, msg->type());
1330269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  conn->OnReadPacket(lport->last_stun_buf()->Data(),
1331269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                     lport->last_stun_buf()->Length(),
1332269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                     rtc::PacketTime());
1333269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_TRUE_WAIT(lport->last_stun_msg() != NULL, 1000);
1334269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  msg = lport->last_stun_msg();
1335269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(STUN_BINDING_RESPONSE, msg->type());
1336269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1337269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // If the tiebreaker value is different from port, we expect a error
1338269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // response.
1339269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  lport->Reset();
1340269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  lport->AddCandidateAddress(kLocalAddr2);
134104ac81f2fd8ef6680522438fac1894db5415a0ecPeter Thatcher  // Creating a different connection as |conn| is receiving.
1342269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  Connection* conn1 = lport->CreateConnection(lport->Candidates()[1],
1343269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                              Port::ORIGIN_MESSAGE);
1344269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  conn1->Ping(0);
1345269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1346269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_TRUE_WAIT(lport->last_stun_msg() != NULL, 1000);
1347269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  msg = lport->last_stun_msg();
1348269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(STUN_BINDING_REQUEST, msg->type());
1349269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<IceMessage> modified_req(
1350269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      CreateStunMessage(STUN_BINDING_REQUEST));
1351269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  const StunByteStringAttribute* username_attr = msg->GetByteString(
1352269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      STUN_ATTR_USERNAME);
1353269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  modified_req->AddAttribute(new StunByteStringAttribute(
1354269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      STUN_ATTR_USERNAME, username_attr->GetString()));
1355269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // To make sure we receive error response, adding tiebreaker less than
1356269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // what's present in request.
1357269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  modified_req->AddAttribute(new StunUInt64Attribute(
1358269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      STUN_ATTR_ICE_CONTROLLING, kTiebreaker1 - 1));
1359269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  modified_req->AddMessageIntegrity("lpass");
1360269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  modified_req->AddFingerprint();
1361269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1362269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  lport->Reset();
1363269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<ByteBuffer> buf(new ByteBuffer());
1364269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  WriteStunMessage(modified_req.get(), buf.get());
1365269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  conn1->OnReadPacket(buf->Data(), buf->Length(), rtc::PacketTime());
1366269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_TRUE_WAIT(lport->last_stun_msg() != NULL, 1000);
1367269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  msg = lport->last_stun_msg();
1368269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(STUN_BINDING_ERROR_RESPONSE, msg->type());
1369269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1370269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1371269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// This test verifies role conflict signal is received when there is
1372269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// conflict in the role. In this case both ports are in controlling and
1373269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// |rport| has higher tiebreaker value than |lport|. Since |lport| has lower
1374269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// value of tiebreaker, when it receives ping request from |rport| it will
1375269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// send role conflict signal.
1376269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestIceRoleConflict) {
1377269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<TestPort> lport(
1378269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      CreateTestPort(kLocalAddr1, "lfrag", "lpass"));
1379269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  lport->SetIceRole(cricket::ICEROLE_CONTROLLING);
1380269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  lport->SetIceTiebreaker(kTiebreaker1);
1381269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<TestPort> rport(
1382269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      CreateTestPort(kLocalAddr2, "rfrag", "rpass"));
1383269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rport->SetIceRole(cricket::ICEROLE_CONTROLLING);
1384269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rport->SetIceTiebreaker(kTiebreaker2);
1385269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1386269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  lport->PrepareAddress();
1387269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rport->PrepareAddress();
1388269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_FALSE(lport->Candidates().empty());
1389269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_FALSE(rport->Candidates().empty());
1390269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  Connection* lconn = lport->CreateConnection(rport->Candidates()[0],
1391269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                              Port::ORIGIN_MESSAGE);
1392269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  Connection* rconn = rport->CreateConnection(lport->Candidates()[0],
1393269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                              Port::ORIGIN_MESSAGE);
1394269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rconn->Ping(0);
1395269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1396269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_TRUE_WAIT(rport->last_stun_msg() != NULL, 1000);
1397269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  IceMessage* msg = rport->last_stun_msg();
1398269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(STUN_BINDING_REQUEST, msg->type());
1399269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Send rport binding request to lport.
1400269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  lconn->OnReadPacket(rport->last_stun_buf()->Data(),
1401269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                      rport->last_stun_buf()->Length(),
1402269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                      rtc::PacketTime());
1403269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1404269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_TRUE_WAIT(lport->last_stun_msg() != NULL, 1000);
1405269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(STUN_BINDING_RESPONSE, lport->last_stun_msg()->type());
1406269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(role_conflict());
1407269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1408269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1409269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestTcpNoDelay) {
1410269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TCPPort* port1 = CreateTcpPort(kLocalAddr1);
14117cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher  port1->SetIceRole(cricket::ICEROLE_CONTROLLING);
1412269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  int option_value = -1;
1413269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  int success = port1->GetOption(rtc::Socket::OPT_NODELAY,
1414269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                 &option_value);
1415269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_EQ(0, success);  // GetOption() should complete successfully w/ 0
1416269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_EQ(1, option_value);
1417269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  delete port1;
1418269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1419269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1420269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestDelayedBindingUdp) {
1421269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  FakeAsyncPacketSocket *socket = new FakeAsyncPacketSocket();
1422269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  FakePacketSocketFactory socket_factory;
1423269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1424269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  socket_factory.set_next_udp_socket(socket);
1425269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  scoped_ptr<UDPPort> port(
1426269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      CreateUdpPort(kLocalAddr1, &socket_factory));
1427269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1428269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  socket->set_state(AsyncPacketSocket::STATE_BINDING);
1429269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  port->PrepareAddress();
1430269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1431269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(0U, port->Candidates().size());
1432269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  socket->SignalAddressReady(socket, kLocalAddr2);
1433269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1434269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(1U, port->Candidates().size());
1435269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1436269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1437269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestDelayedBindingTcp) {
1438269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  FakeAsyncPacketSocket *socket = new FakeAsyncPacketSocket();
1439269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  FakePacketSocketFactory socket_factory;
1440269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1441269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  socket_factory.set_next_server_tcp_socket(socket);
1442269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  scoped_ptr<TCPPort> port(
1443269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      CreateTcpPort(kLocalAddr1, &socket_factory));
1444269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1445269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  socket->set_state(AsyncPacketSocket::STATE_BINDING);
1446269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  port->PrepareAddress();
1447269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1448269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(0U, port->Candidates().size());
1449269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  socket->SignalAddressReady(socket, kLocalAddr2);
1450269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1451269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(1U, port->Candidates().size());
1452269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1453269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1454269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid PortTest::TestCrossFamilyPorts(int type) {
1455269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  FakePacketSocketFactory factory;
1456269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  scoped_ptr<Port> ports[4];
1457269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  SocketAddress addresses[4] = {SocketAddress("192.168.1.3", 0),
1458269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                SocketAddress("192.168.1.4", 0),
1459269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                SocketAddress("2001:db8::1", 0),
1460269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                SocketAddress("2001:db8::2", 0)};
1461269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  for (int i = 0; i < 4; i++) {
1462269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    FakeAsyncPacketSocket *socket = new FakeAsyncPacketSocket();
1463269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    if (type == SOCK_DGRAM) {
1464269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      factory.set_next_udp_socket(socket);
1465269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      ports[i].reset(CreateUdpPort(addresses[i], &factory));
1466269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    } else if (type == SOCK_STREAM) {
1467269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      factory.set_next_server_tcp_socket(socket);
1468269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      ports[i].reset(CreateTcpPort(addresses[i], &factory));
1469269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    }
1470269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    socket->set_state(AsyncPacketSocket::STATE_BINDING);
1471269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    socket->SignalAddressReady(socket, addresses[i]);
1472269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    ports[i]->PrepareAddress();
1473269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
1474269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1475269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // IPv4 Port, connects to IPv6 candidate and then to IPv4 candidate.
1476269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (type == SOCK_STREAM) {
1477269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    FakeAsyncPacketSocket* clientsocket = new FakeAsyncPacketSocket();
1478269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    factory.set_next_client_tcp_socket(clientsocket);
1479269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
1480269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  Connection* c = ports[0]->CreateConnection(GetCandidate(ports[2].get()),
1481269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                             Port::ORIGIN_MESSAGE);
1482269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(NULL == c);
1483269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(0U, ports[0]->connections().size());
1484269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  c = ports[0]->CreateConnection(GetCandidate(ports[1].get()),
1485269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                 Port::ORIGIN_MESSAGE);
1486269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_FALSE(NULL == c);
1487269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(1U, ports[0]->connections().size());
1488269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1489269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // IPv6 Port, connects to IPv4 candidate and to IPv6 candidate.
1490269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (type == SOCK_STREAM) {
1491269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    FakeAsyncPacketSocket* clientsocket = new FakeAsyncPacketSocket();
1492269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    factory.set_next_client_tcp_socket(clientsocket);
1493269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
1494269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  c = ports[2]->CreateConnection(GetCandidate(ports[0].get()),
1495269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                 Port::ORIGIN_MESSAGE);
1496269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(NULL == c);
1497269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(0U, ports[2]->connections().size());
1498269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  c = ports[2]->CreateConnection(GetCandidate(ports[3].get()),
1499269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                 Port::ORIGIN_MESSAGE);
1500269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_FALSE(NULL == c);
1501269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(1U, ports[2]->connections().size());
1502269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1503269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1504269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestSkipCrossFamilyTcp) {
1505269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestCrossFamilyPorts(SOCK_STREAM);
1506269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1507269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1508269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestSkipCrossFamilyUdp) {
1509269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestCrossFamilyPorts(SOCK_DGRAM);
1510269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1511269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1512b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatchervoid PortTest::ExpectPortsCanConnect(bool can_connect, Port* p1, Port* p2) {
1513b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher  Connection* c = p1->CreateConnection(GetCandidate(p2),
1514b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher                                       Port::ORIGIN_MESSAGE);
1515b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher  if (can_connect) {
1516b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher    EXPECT_FALSE(NULL == c);
1517b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher    EXPECT_EQ(1U, p1->connections().size());
1518b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher  } else {
1519b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher    EXPECT_TRUE(NULL == c);
1520b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher    EXPECT_EQ(0U, p1->connections().size());
1521b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher  }
1522b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher}
1523b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher
1524b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter ThatcherTEST_F(PortTest, TestUdpV6CrossTypePorts) {
1525b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher  FakePacketSocketFactory factory;
1526b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher  scoped_ptr<Port> ports[4];
1527b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher  SocketAddress addresses[4] = {SocketAddress("2001:db8::1", 0),
1528b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher                                SocketAddress("fe80::1", 0),
1529b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher                                SocketAddress("fe80::2", 0),
1530b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher                                SocketAddress("::1", 0)};
1531b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher  for (int i = 0; i < 4; i++) {
1532b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher    FakeAsyncPacketSocket *socket = new FakeAsyncPacketSocket();
1533b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher    factory.set_next_udp_socket(socket);
1534b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher    ports[i].reset(CreateUdpPort(addresses[i], &factory));
1535b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher    socket->set_state(AsyncPacketSocket::STATE_BINDING);
1536b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher    socket->SignalAddressReady(socket, addresses[i]);
1537b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher    ports[i]->PrepareAddress();
1538b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher  }
1539b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher
1540b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher  Port* standard = ports[0].get();
1541b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher  Port* link_local1 = ports[1].get();
1542b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher  Port* link_local2 = ports[2].get();
1543b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher  Port* localhost = ports[3].get();
1544b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher
1545b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher  ExpectPortsCanConnect(false, link_local1, standard);
1546b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher  ExpectPortsCanConnect(false, standard, link_local1);
1547b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher  ExpectPortsCanConnect(false, link_local1, localhost);
1548b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher  ExpectPortsCanConnect(false, localhost, link_local1);
1549b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher
1550b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher  ExpectPortsCanConnect(true, link_local1, link_local2);
1551b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher  ExpectPortsCanConnect(true, localhost, standard);
1552b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher  ExpectPortsCanConnect(true, standard, localhost);
1553b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher}
1554b8b0143a11afd495b8e9c1a1cc388cdbd4340b99Peter Thatcher
1555269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// This test verifies DSCP value set through SetOption interface can be
1556269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// get through DefaultDscpValue.
1557269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestDefaultDscpValue) {
1558269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  int dscp;
1559269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<UDPPort> udpport(CreateUdpPort(kLocalAddr1));
1560269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(0, udpport->SetOption(rtc::Socket::OPT_DSCP,
1561269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                  rtc::DSCP_CS6));
1562269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(0, udpport->GetOption(rtc::Socket::OPT_DSCP, &dscp));
1563269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<TCPPort> tcpport(CreateTcpPort(kLocalAddr1));
1564269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(0, tcpport->SetOption(rtc::Socket::OPT_DSCP,
1565269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                 rtc::DSCP_AF31));
1566269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(0, tcpport->GetOption(rtc::Socket::OPT_DSCP, &dscp));
1567269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(rtc::DSCP_AF31, dscp);
1568269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<StunPort> stunport(
1569269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      CreateStunPort(kLocalAddr1, nat_socket_factory1()));
1570269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(0, stunport->SetOption(rtc::Socket::OPT_DSCP,
1571269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                  rtc::DSCP_AF41));
1572269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(0, stunport->GetOption(rtc::Socket::OPT_DSCP, &dscp));
1573269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(rtc::DSCP_AF41, dscp);
1574269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<TurnPort> turnport1(CreateTurnPort(
1575269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      kLocalAddr1, nat_socket_factory1(), PROTO_UDP, PROTO_UDP));
1576269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Socket is created in PrepareAddress.
1577269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  turnport1->PrepareAddress();
1578269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(0, turnport1->SetOption(rtc::Socket::OPT_DSCP,
1579269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                  rtc::DSCP_CS7));
1580269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(0, turnport1->GetOption(rtc::Socket::OPT_DSCP, &dscp));
1581269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(rtc::DSCP_CS7, dscp);
1582269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // This will verify correct value returned without the socket.
1583269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<TurnPort> turnport2(CreateTurnPort(
1584269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      kLocalAddr1, nat_socket_factory1(), PROTO_UDP, PROTO_UDP));
1585269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(0, turnport2->SetOption(rtc::Socket::OPT_DSCP,
1586269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                  rtc::DSCP_CS6));
1587269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(0, turnport2->GetOption(rtc::Socket::OPT_DSCP, &dscp));
1588269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(rtc::DSCP_CS6, dscp);
1589269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1590269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
15917cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher// Test sending STUN messages.
15927cbd188c5ed7df80bb737bd4ada94422730e2d89Peter ThatcherTEST_F(PortTest, TestSendStunMessage) {
1593269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<TestPort> lport(
1594269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      CreateTestPort(kLocalAddr1, "lfrag", "lpass"));
1595269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<TestPort> rport(
1596269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      CreateTestPort(kLocalAddr2, "rfrag", "rpass"));
1597269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  lport->SetIceRole(cricket::ICEROLE_CONTROLLING);
1598269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  lport->SetIceTiebreaker(kTiebreaker1);
1599269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rport->SetIceRole(cricket::ICEROLE_CONTROLLED);
1600269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rport->SetIceTiebreaker(kTiebreaker2);
1601269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1602269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Send a fake ping from lport to rport.
1603269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  lport->PrepareAddress();
1604269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rport->PrepareAddress();
1605269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_FALSE(rport->Candidates().empty());
1606269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  Connection* lconn = lport->CreateConnection(
1607269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      rport->Candidates()[0], Port::ORIGIN_MESSAGE);
1608269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  Connection* rconn = rport->CreateConnection(
1609269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      lport->Candidates()[0], Port::ORIGIN_MESSAGE);
1610269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  lconn->Ping(0);
1611269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1612269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Check that it's a proper BINDING-REQUEST.
1613269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_TRUE_WAIT(lport->last_stun_msg() != NULL, 1000);
1614269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  IceMessage* msg = lport->last_stun_msg();
1615269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(STUN_BINDING_REQUEST, msg->type());
1616269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_FALSE(msg->IsLegacy());
1617269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  const StunByteStringAttribute* username_attr =
1618269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      msg->GetByteString(STUN_ATTR_USERNAME);
1619269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_TRUE(username_attr != NULL);
1620269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  const StunUInt32Attribute* priority_attr = msg->GetUInt32(STUN_ATTR_PRIORITY);
1621269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_TRUE(priority_attr != NULL);
1622269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(kDefaultPrflxPriority, priority_attr->value());
1623269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ("rfrag:lfrag", username_attr->GetString());
1624269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(msg->GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
1625269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(StunMessage::ValidateMessageIntegrity(
1626269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      lport->last_stun_buf()->Data(), lport->last_stun_buf()->Length(),
1627269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      "rpass"));
1628269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  const StunUInt64Attribute* ice_controlling_attr =
1629269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      msg->GetUInt64(STUN_ATTR_ICE_CONTROLLING);
1630269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_TRUE(ice_controlling_attr != NULL);
1631269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(lport->IceTiebreaker(), ice_controlling_attr->value());
1632269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(msg->GetByteString(STUN_ATTR_ICE_CONTROLLED) == NULL);
1633269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(msg->GetByteString(STUN_ATTR_USE_CANDIDATE) != NULL);
1634269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(msg->GetUInt32(STUN_ATTR_FINGERPRINT) != NULL);
1635269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(StunMessage::ValidateFingerprint(
1636269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      lport->last_stun_buf()->Data(), lport->last_stun_buf()->Length()));
1637269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1638269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Request should not include ping count.
1639269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_TRUE(msg->GetUInt32(STUN_ATTR_RETRANSMIT_COUNT) == NULL);
1640269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1641269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Save a copy of the BINDING-REQUEST for use below.
1642269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<IceMessage> request(CopyStunMessage(msg));
1643269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1644269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Respond with a BINDING-RESPONSE.
1645269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rport->SendBindingResponse(request.get(), lport->Candidates()[0].address());
1646269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  msg = rport->last_stun_msg();
1647269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_TRUE(msg != NULL);
1648269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(STUN_BINDING_RESPONSE, msg->type());
1649269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1650269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1651269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_FALSE(msg->IsLegacy());
1652269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  const StunAddressAttribute* addr_attr = msg->GetAddress(
1653269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      STUN_ATTR_XOR_MAPPED_ADDRESS);
1654269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_TRUE(addr_attr != NULL);
1655269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(lport->Candidates()[0].address(), addr_attr->GetAddress());
1656269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(msg->GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
1657269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(StunMessage::ValidateMessageIntegrity(
1658269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      rport->last_stun_buf()->Data(), rport->last_stun_buf()->Length(),
1659269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      "rpass"));
1660269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(msg->GetUInt32(STUN_ATTR_FINGERPRINT) != NULL);
1661269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(StunMessage::ValidateFingerprint(
1662269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      lport->last_stun_buf()->Data(), lport->last_stun_buf()->Length()));
1663269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // No USERNAME or PRIORITY in ICE responses.
1664269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(msg->GetByteString(STUN_ATTR_USERNAME) == NULL);
1665269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(msg->GetByteString(STUN_ATTR_PRIORITY) == NULL);
1666269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(msg->GetByteString(STUN_ATTR_MAPPED_ADDRESS) == NULL);
1667269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(msg->GetByteString(STUN_ATTR_ICE_CONTROLLING) == NULL);
1668269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(msg->GetByteString(STUN_ATTR_ICE_CONTROLLED) == NULL);
1669269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(msg->GetByteString(STUN_ATTR_USE_CANDIDATE) == NULL);
1670269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1671269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Response should not include ping count.
1672269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_TRUE(msg->GetUInt32(STUN_ATTR_RETRANSMIT_COUNT) == NULL);
1673269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1674269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Respond with a BINDING-ERROR-RESPONSE. This wouldn't happen in real life,
1675269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // but we can do it here.
1676269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rport->SendBindingErrorResponse(request.get(),
1677269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                  lport->Candidates()[0].address(),
1678269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                  STUN_ERROR_SERVER_ERROR,
1679269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                  STUN_ERROR_REASON_SERVER_ERROR);
1680269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  msg = rport->last_stun_msg();
1681269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_TRUE(msg != NULL);
1682269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(STUN_BINDING_ERROR_RESPONSE, msg->type());
1683269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_FALSE(msg->IsLegacy());
1684269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  const StunErrorCodeAttribute* error_attr = msg->GetErrorCode();
1685269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_TRUE(error_attr != NULL);
1686269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(STUN_ERROR_SERVER_ERROR, error_attr->code());
1687269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(std::string(STUN_ERROR_REASON_SERVER_ERROR), error_attr->reason());
1688269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(msg->GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL);
1689269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(StunMessage::ValidateMessageIntegrity(
1690269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      rport->last_stun_buf()->Data(), rport->last_stun_buf()->Length(),
1691269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      "rpass"));
1692269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(msg->GetUInt32(STUN_ATTR_FINGERPRINT) != NULL);
1693269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(StunMessage::ValidateFingerprint(
1694269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      lport->last_stun_buf()->Data(), lport->last_stun_buf()->Length()));
1695269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // No USERNAME with ICE.
1696269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(msg->GetByteString(STUN_ATTR_USERNAME) == NULL);
1697269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(msg->GetByteString(STUN_ATTR_PRIORITY) == NULL);
1698269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1699269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Testing STUN binding requests from rport --> lport, having ICE_CONTROLLED
1700269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // and (incremented) RETRANSMIT_COUNT attributes.
1701269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rport->Reset();
1702269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rport->set_send_retransmit_count_attribute(true);
1703269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rconn->Ping(0);
1704269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rconn->Ping(0);
1705269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rconn->Ping(0);
1706269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_TRUE_WAIT(rport->last_stun_msg() != NULL, 1000);
1707269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  msg = rport->last_stun_msg();
1708269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(STUN_BINDING_REQUEST, msg->type());
1709269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  const StunUInt64Attribute* ice_controlled_attr =
1710269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      msg->GetUInt64(STUN_ATTR_ICE_CONTROLLED);
1711269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_TRUE(ice_controlled_attr != NULL);
1712269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(rport->IceTiebreaker(), ice_controlled_attr->value());
1713269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(msg->GetByteString(STUN_ATTR_USE_CANDIDATE) == NULL);
1714269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1715269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Request should include ping count.
1716269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  const StunUInt32Attribute* retransmit_attr =
1717269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      msg->GetUInt32(STUN_ATTR_RETRANSMIT_COUNT);
1718269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_TRUE(retransmit_attr != NULL);
1719269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(2U, retransmit_attr->value());
1720269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1721269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Respond with a BINDING-RESPONSE.
1722269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  request.reset(CopyStunMessage(msg));
1723269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  lport->SendBindingResponse(request.get(), rport->Candidates()[0].address());
1724269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  msg = lport->last_stun_msg();
1725269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1726269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Response should include same ping count.
1727269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  retransmit_attr = msg->GetUInt32(STUN_ATTR_RETRANSMIT_COUNT);
1728269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_TRUE(retransmit_attr != NULL);
1729269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(2U, retransmit_attr->value());
1730269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1731269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1732269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestUseCandidateAttribute) {
1733269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<TestPort> lport(
1734269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      CreateTestPort(kLocalAddr1, "lfrag", "lpass"));
1735269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<TestPort> rport(
1736269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      CreateTestPort(kLocalAddr2, "rfrag", "rpass"));
1737269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  lport->SetIceRole(cricket::ICEROLE_CONTROLLING);
1738269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  lport->SetIceTiebreaker(kTiebreaker1);
1739269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rport->SetIceRole(cricket::ICEROLE_CONTROLLED);
1740269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rport->SetIceTiebreaker(kTiebreaker2);
1741269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1742269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Send a fake ping from lport to rport.
1743269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  lport->PrepareAddress();
1744269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rport->PrepareAddress();
1745269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_FALSE(rport->Candidates().empty());
1746269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  Connection* lconn = lport->CreateConnection(
1747269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      rport->Candidates()[0], Port::ORIGIN_MESSAGE);
1748269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  lconn->Ping(0);
1749269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_TRUE_WAIT(lport->last_stun_msg() != NULL, 1000);
1750269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  IceMessage* msg = lport->last_stun_msg();
1751269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  const StunUInt64Attribute* ice_controlling_attr =
1752269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      msg->GetUInt64(STUN_ATTR_ICE_CONTROLLING);
1753269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_TRUE(ice_controlling_attr != NULL);
1754269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  const StunByteStringAttribute* use_candidate_attr = msg->GetByteString(
1755269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      STUN_ATTR_USE_CANDIDATE);
1756269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_TRUE(use_candidate_attr != NULL);
1757269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1758269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
17597cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher// Test handling STUN messages.
17607cbd188c5ed7df80bb737bd4ada94422730e2d89Peter ThatcherTEST_F(PortTest, TestHandleStunMessage) {
1761269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Our port will act as the "remote" port.
1762269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<TestPort> port(
1763269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      CreateTestPort(kLocalAddr2, "rfrag", "rpass"));
1764269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1765269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<IceMessage> in_msg, out_msg;
1766269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<ByteBuffer> buf(new ByteBuffer());
1767269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::SocketAddress addr(kLocalAddr1);
1768269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  std::string username;
1769269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1770269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // BINDING-REQUEST from local to remote with valid ICE username,
1771269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // MESSAGE-INTEGRITY, and FINGERPRINT.
1772269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg.reset(CreateStunMessageWithUsername(STUN_BINDING_REQUEST,
1773269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                             "rfrag:lfrag"));
1774269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg->AddMessageIntegrity("rpass");
1775269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg->AddFingerprint();
1776269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  WriteStunMessage(in_msg.get(), buf.get());
1777269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(port->GetStunMessage(buf->Data(), buf->Length(), addr,
1778269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                   out_msg.accept(), &username));
1779269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(out_msg.get() != NULL);
1780269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ("lfrag", username);
1781269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1782269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // BINDING-RESPONSE without username, with MESSAGE-INTEGRITY and FINGERPRINT.
1783269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg.reset(CreateStunMessage(STUN_BINDING_RESPONSE));
1784269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg->AddAttribute(
1785269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      new StunXorAddressAttribute(STUN_ATTR_XOR_MAPPED_ADDRESS, kLocalAddr2));
1786269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg->AddMessageIntegrity("rpass");
1787269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg->AddFingerprint();
1788269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  WriteStunMessage(in_msg.get(), buf.get());
1789269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(port->GetStunMessage(buf->Data(), buf->Length(), addr,
1790269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                   out_msg.accept(), &username));
1791269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(out_msg.get() != NULL);
1792269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ("", username);
1793269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1794269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // BINDING-ERROR-RESPONSE without username, with error, M-I, and FINGERPRINT.
1795269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg.reset(CreateStunMessage(STUN_BINDING_ERROR_RESPONSE));
1796269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg->AddAttribute(new StunErrorCodeAttribute(STUN_ATTR_ERROR_CODE,
1797269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      STUN_ERROR_SERVER_ERROR, STUN_ERROR_REASON_SERVER_ERROR));
1798269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg->AddFingerprint();
1799269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  WriteStunMessage(in_msg.get(), buf.get());
1800269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(port->GetStunMessage(buf->Data(), buf->Length(), addr,
1801269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                   out_msg.accept(), &username));
1802269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(out_msg.get() != NULL);
1803269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ("", username);
1804269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_TRUE(out_msg->GetErrorCode() != NULL);
1805269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(STUN_ERROR_SERVER_ERROR, out_msg->GetErrorCode()->code());
1806269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(std::string(STUN_ERROR_REASON_SERVER_ERROR),
1807269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      out_msg->GetErrorCode()->reason());
1808269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1809269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1810269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Tests handling of ICE binding requests with missing or incorrect usernames.
18117cbd188c5ed7df80bb737bd4ada94422730e2d89Peter ThatcherTEST_F(PortTest, TestHandleStunMessageBadUsername) {
1812269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<TestPort> port(
1813269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      CreateTestPort(kLocalAddr2, "rfrag", "rpass"));
1814269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1815269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<IceMessage> in_msg, out_msg;
1816269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<ByteBuffer> buf(new ByteBuffer());
1817269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::SocketAddress addr(kLocalAddr1);
1818269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  std::string username;
1819269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1820269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // BINDING-REQUEST with no username.
1821269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg.reset(CreateStunMessage(STUN_BINDING_REQUEST));
1822269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg->AddMessageIntegrity("rpass");
1823269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg->AddFingerprint();
1824269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  WriteStunMessage(in_msg.get(), buf.get());
1825269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(port->GetStunMessage(buf->Data(), buf->Length(), addr,
1826269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                   out_msg.accept(), &username));
1827269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(out_msg.get() == NULL);
1828269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ("", username);
1829269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(STUN_ERROR_BAD_REQUEST, port->last_stun_error_code());
1830269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1831269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // BINDING-REQUEST with empty username.
1832269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg.reset(CreateStunMessageWithUsername(STUN_BINDING_REQUEST, ""));
1833269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg->AddMessageIntegrity("rpass");
1834269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg->AddFingerprint();
1835269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  WriteStunMessage(in_msg.get(), buf.get());
1836269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(port->GetStunMessage(buf->Data(), buf->Length(), addr,
1837269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                   out_msg.accept(), &username));
1838269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(out_msg.get() == NULL);
1839269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ("", username);
1840269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(STUN_ERROR_UNAUTHORIZED, port->last_stun_error_code());
1841269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1842269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // BINDING-REQUEST with too-short username.
1843269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg.reset(CreateStunMessageWithUsername(STUN_BINDING_REQUEST, "rfra"));
1844269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg->AddMessageIntegrity("rpass");
1845269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg->AddFingerprint();
1846269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  WriteStunMessage(in_msg.get(), buf.get());
1847269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(port->GetStunMessage(buf->Data(), buf->Length(), addr,
1848269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                   out_msg.accept(), &username));
1849269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(out_msg.get() == NULL);
1850269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ("", username);
1851269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(STUN_ERROR_UNAUTHORIZED, port->last_stun_error_code());
1852269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1853269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // BINDING-REQUEST with reversed username.
1854269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg.reset(CreateStunMessageWithUsername(STUN_BINDING_REQUEST,
1855269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                            "lfrag:rfrag"));
1856269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg->AddMessageIntegrity("rpass");
1857269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg->AddFingerprint();
1858269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  WriteStunMessage(in_msg.get(), buf.get());
1859269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(port->GetStunMessage(buf->Data(), buf->Length(), addr,
1860269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                   out_msg.accept(), &username));
1861269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(out_msg.get() == NULL);
1862269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ("", username);
1863269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(STUN_ERROR_UNAUTHORIZED, port->last_stun_error_code());
1864269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1865269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // BINDING-REQUEST with garbage username.
1866269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg.reset(CreateStunMessageWithUsername(STUN_BINDING_REQUEST,
1867269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                             "abcd:efgh"));
1868269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg->AddMessageIntegrity("rpass");
1869269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg->AddFingerprint();
1870269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  WriteStunMessage(in_msg.get(), buf.get());
1871269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(port->GetStunMessage(buf->Data(), buf->Length(), addr,
1872269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                   out_msg.accept(), &username));
1873269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(out_msg.get() == NULL);
1874269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ("", username);
1875269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(STUN_ERROR_UNAUTHORIZED, port->last_stun_error_code());
1876269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1877269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
18787cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher// Test handling STUN messages with missing or malformed M-I.
18797cbd188c5ed7df80bb737bd4ada94422730e2d89Peter ThatcherTEST_F(PortTest, TestHandleStunMessageBadMessageIntegrity) {
1880269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Our port will act as the "remote" port.
1881269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<TestPort> port(
1882269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      CreateTestPort(kLocalAddr2, "rfrag", "rpass"));
1883269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1884269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<IceMessage> in_msg, out_msg;
1885269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<ByteBuffer> buf(new ByteBuffer());
1886269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::SocketAddress addr(kLocalAddr1);
1887269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  std::string username;
1888269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1889269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // BINDING-REQUEST from local to remote with valid ICE username and
1890269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // FINGERPRINT, but no MESSAGE-INTEGRITY.
1891269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg.reset(CreateStunMessageWithUsername(STUN_BINDING_REQUEST,
1892269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                             "rfrag:lfrag"));
1893269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg->AddFingerprint();
1894269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  WriteStunMessage(in_msg.get(), buf.get());
1895269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(port->GetStunMessage(buf->Data(), buf->Length(), addr,
1896269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                   out_msg.accept(), &username));
1897269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(out_msg.get() == NULL);
1898269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ("", username);
1899269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(STUN_ERROR_BAD_REQUEST, port->last_stun_error_code());
1900269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1901269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // BINDING-REQUEST from local to remote with valid ICE username and
1902269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // FINGERPRINT, but invalid MESSAGE-INTEGRITY.
1903269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg.reset(CreateStunMessageWithUsername(STUN_BINDING_REQUEST,
1904269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                             "rfrag:lfrag"));
1905269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg->AddMessageIntegrity("invalid");
1906269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg->AddFingerprint();
1907269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  WriteStunMessage(in_msg.get(), buf.get());
1908269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(port->GetStunMessage(buf->Data(), buf->Length(), addr,
1909269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                   out_msg.accept(), &username));
1910269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(out_msg.get() == NULL);
1911269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ("", username);
1912269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(STUN_ERROR_UNAUTHORIZED, port->last_stun_error_code());
1913269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1914269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // TODO: BINDING-RESPONSES and BINDING-ERROR-RESPONSES are checked
1915269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // by the Connection, not the Port, since they require the remote username.
1916269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Change this test to pass in data via Connection::OnReadPacket instead.
1917269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1918269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
19197cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher// Test handling STUN messages with missing or malformed FINGERPRINT.
19207cbd188c5ed7df80bb737bd4ada94422730e2d89Peter ThatcherTEST_F(PortTest, TestHandleStunMessageBadFingerprint) {
1921269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Our port will act as the "remote" port.
1922269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<TestPort> port(
1923269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      CreateTestPort(kLocalAddr2, "rfrag", "rpass"));
1924269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1925269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<IceMessage> in_msg, out_msg;
1926269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<ByteBuffer> buf(new ByteBuffer());
1927269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::SocketAddress addr(kLocalAddr1);
1928269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  std::string username;
1929269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1930269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // BINDING-REQUEST from local to remote with valid ICE username and
1931269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // MESSAGE-INTEGRITY, but no FINGERPRINT; GetStunMessage should fail.
1932269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg.reset(CreateStunMessageWithUsername(STUN_BINDING_REQUEST,
1933269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                             "rfrag:lfrag"));
1934269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg->AddMessageIntegrity("rpass");
1935269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  WriteStunMessage(in_msg.get(), buf.get());
1936269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_FALSE(port->GetStunMessage(buf->Data(), buf->Length(), addr,
1937269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                    out_msg.accept(), &username));
1938269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(0, port->last_stun_error_code());
1939269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1940269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Now, add a fingerprint, but munge the message so it's not valid.
1941269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg->AddFingerprint();
1942269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg->SetTransactionID("TESTTESTBADD");
1943269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  WriteStunMessage(in_msg.get(), buf.get());
1944269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_FALSE(port->GetStunMessage(buf->Data(), buf->Length(), addr,
1945269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                    out_msg.accept(), &username));
1946269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(0, port->last_stun_error_code());
1947269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1948269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Valid BINDING-RESPONSE, except no FINGERPRINT.
1949269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg.reset(CreateStunMessage(STUN_BINDING_RESPONSE));
1950269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg->AddAttribute(
1951269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      new StunXorAddressAttribute(STUN_ATTR_XOR_MAPPED_ADDRESS, kLocalAddr2));
1952269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg->AddMessageIntegrity("rpass");
1953269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  WriteStunMessage(in_msg.get(), buf.get());
1954269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_FALSE(port->GetStunMessage(buf->Data(), buf->Length(), addr,
1955269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                    out_msg.accept(), &username));
1956269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(0, port->last_stun_error_code());
1957269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1958269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Now, add a fingerprint, but munge the message so it's not valid.
1959269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg->AddFingerprint();
1960269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg->SetTransactionID("TESTTESTBADD");
1961269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  WriteStunMessage(in_msg.get(), buf.get());
1962269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_FALSE(port->GetStunMessage(buf->Data(), buf->Length(), addr,
1963269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                    out_msg.accept(), &username));
1964269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(0, port->last_stun_error_code());
1965269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1966269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Valid BINDING-ERROR-RESPONSE, except no FINGERPRINT.
1967269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg.reset(CreateStunMessage(STUN_BINDING_ERROR_RESPONSE));
1968269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg->AddAttribute(new StunErrorCodeAttribute(STUN_ATTR_ERROR_CODE,
1969269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      STUN_ERROR_SERVER_ERROR, STUN_ERROR_REASON_SERVER_ERROR));
1970269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg->AddMessageIntegrity("rpass");
1971269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  WriteStunMessage(in_msg.get(), buf.get());
1972269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_FALSE(port->GetStunMessage(buf->Data(), buf->Length(), addr,
1973269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                    out_msg.accept(), &username));
1974269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(0, port->last_stun_error_code());
1975269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1976269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Now, add a fingerprint, but munge the message so it's not valid.
1977269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg->AddFingerprint();
1978269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg->SetTransactionID("TESTTESTBADD");
1979269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  WriteStunMessage(in_msg.get(), buf.get());
1980269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_FALSE(port->GetStunMessage(buf->Data(), buf->Length(), addr,
1981269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                    out_msg.accept(), &username));
1982269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(0, port->last_stun_error_code());
1983269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
1984269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
19857cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher// Test handling of STUN binding indication messages . STUN binding
1986269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// indications are allowed only to the connection which is in read mode.
1987269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestHandleStunBindingIndication) {
1988269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<TestPort> lport(
1989269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      CreateTestPort(kLocalAddr2, "lfrag", "lpass"));
1990269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  lport->SetIceRole(cricket::ICEROLE_CONTROLLING);
1991269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  lport->SetIceTiebreaker(kTiebreaker1);
1992269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1993269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Verifying encoding and decoding STUN indication message.
1994269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<IceMessage> in_msg, out_msg;
1995269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<ByteBuffer> buf(new ByteBuffer());
1996269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::SocketAddress addr(kLocalAddr1);
1997269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  std::string username;
1998269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1999269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg.reset(CreateStunMessage(STUN_BINDING_INDICATION));
2000269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  in_msg->AddFingerprint();
2001269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  WriteStunMessage(in_msg.get(), buf.get());
2002269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(lport->GetStunMessage(buf->Data(), buf->Length(), addr,
2003269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                    out_msg.accept(), &username));
2004269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(out_msg.get() != NULL);
2005269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(out_msg->type(), STUN_BINDING_INDICATION);
2006269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ("", username);
2007269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2008269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Verify connection can handle STUN indication and updates
2009269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // last_ping_received.
2010269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<TestPort> rport(
2011269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      CreateTestPort(kLocalAddr2, "rfrag", "rpass"));
2012269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rport->SetIceRole(cricket::ICEROLE_CONTROLLED);
2013269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rport->SetIceTiebreaker(kTiebreaker2);
2014269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2015269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  lport->PrepareAddress();
2016269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rport->PrepareAddress();
2017269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_FALSE(lport->Candidates().empty());
2018269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_FALSE(rport->Candidates().empty());
2019269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2020269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  Connection* lconn = lport->CreateConnection(rport->Candidates()[0],
2021269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                              Port::ORIGIN_MESSAGE);
2022269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  Connection* rconn = rport->CreateConnection(lport->Candidates()[0],
2023269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                              Port::ORIGIN_MESSAGE);
2024269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rconn->Ping(0);
2025269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2026269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_TRUE_WAIT(rport->last_stun_msg() != NULL, 1000);
2027269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  IceMessage* msg = rport->last_stun_msg();
2028269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(STUN_BINDING_REQUEST, msg->type());
2029269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Send rport binding request to lport.
2030269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  lconn->OnReadPacket(rport->last_stun_buf()->Data(),
2031269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                      rport->last_stun_buf()->Length(),
2032269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                      rtc::PacketTime());
2033269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_TRUE_WAIT(lport->last_stun_msg() != NULL, 1000);
2034269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(STUN_BINDING_RESPONSE, lport->last_stun_msg()->type());
20350c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint32_t last_ping_received1 = lconn->last_ping_received();
2036269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2037269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Adding a delay of 100ms.
2038269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::Thread::Current()->ProcessMessages(100);
2039269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Pinging lconn using stun indication message.
2040269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  lconn->OnReadPacket(buf->Data(), buf->Length(), rtc::PacketTime());
20410c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint32_t last_ping_received2 = lconn->last_ping_received();
2042269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_GT(last_ping_received2, last_ping_received1);
2043269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
2044269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2045269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestComputeCandidatePriority) {
2046269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<TestPort> port(
2047269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      CreateTestPort(kLocalAddr1, "name", "pass"));
2048269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  port->set_type_preference(90);
2049269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  port->set_component(177);
2050269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  port->AddCandidateAddress(SocketAddress("192.168.1.4", 1234));
2051269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  port->AddCandidateAddress(SocketAddress("2001:db8::1234", 1234));
2052269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  port->AddCandidateAddress(SocketAddress("fc12:3456::1234", 1234));
2053269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  port->AddCandidateAddress(SocketAddress("::ffff:192.168.1.4", 1234));
2054269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  port->AddCandidateAddress(SocketAddress("::192.168.1.4", 1234));
2055269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  port->AddCandidateAddress(SocketAddress("2002::1234:5678", 1234));
2056269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  port->AddCandidateAddress(SocketAddress("2001::1234:5678", 1234));
2057269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  port->AddCandidateAddress(SocketAddress("fecf::1234:5678", 1234));
2058269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  port->AddCandidateAddress(SocketAddress("3ffe::1234:5678", 1234));
2059269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // These should all be:
2060269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // (90 << 24) | ([rfc3484 pref value] << 8) | (256 - 177)
20610c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint32_t expected_priority_v4 = 1509957199U;
20620c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint32_t expected_priority_v6 = 1509959759U;
20630c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint32_t expected_priority_ula = 1509962319U;
20640c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint32_t expected_priority_v4mapped = expected_priority_v4;
20650c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint32_t expected_priority_v4compat = 1509949775U;
20660c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint32_t expected_priority_6to4 = 1509954639U;
20670c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint32_t expected_priority_teredo = 1509952079U;
20680c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint32_t expected_priority_sitelocal = 1509949775U;
20690c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint32_t expected_priority_6bone = 1509949775U;
2070269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_EQ(expected_priority_v4, port->Candidates()[0].priority());
2071269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_EQ(expected_priority_v6, port->Candidates()[1].priority());
2072269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_EQ(expected_priority_ula, port->Candidates()[2].priority());
2073269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_EQ(expected_priority_v4mapped, port->Candidates()[3].priority());
2074269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_EQ(expected_priority_v4compat, port->Candidates()[4].priority());
2075269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_EQ(expected_priority_6to4, port->Candidates()[5].priority());
2076269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_EQ(expected_priority_teredo, port->Candidates()[6].priority());
2077269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_EQ(expected_priority_sitelocal, port->Candidates()[7].priority());
2078269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_EQ(expected_priority_6bone, port->Candidates()[8].priority());
2079269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
2080269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2081269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// In the case of shared socket, one port may be shared by local and stun.
2082269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Test that candidates with different types will have different foundation.
2083269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestFoundation) {
2084269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<TestPort> testport(
2085269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      CreateTestPort(kLocalAddr1, "name", "pass"));
2086269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  testport->AddCandidateAddress(kLocalAddr1, kLocalAddr1,
2087269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                LOCAL_PORT_TYPE,
2088269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                cricket::ICE_TYPE_PREFERENCE_HOST, false);
2089269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  testport->AddCandidateAddress(kLocalAddr2, kLocalAddr1,
2090269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                STUN_PORT_TYPE,
2091269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                cricket::ICE_TYPE_PREFERENCE_SRFLX, true);
2092269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_NE(testport->Candidates()[0].foundation(),
2093269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org            testport->Candidates()[1].foundation());
2094269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
2095269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2096269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// This test verifies the foundation of different types of ICE candidates.
2097269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestCandidateFoundation) {
2098269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<rtc::NATServer> nat_server(
2099269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      CreateNatServer(kNatAddr1, NAT_OPEN_CONE));
2100269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<UDPPort> udpport1(CreateUdpPort(kLocalAddr1));
2101269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  udpport1->PrepareAddress();
2102269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<UDPPort> udpport2(CreateUdpPort(kLocalAddr1));
2103269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  udpport2->PrepareAddress();
2104269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(udpport1->Candidates()[0].foundation(),
2105269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org            udpport2->Candidates()[0].foundation());
2106269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<TCPPort> tcpport1(CreateTcpPort(kLocalAddr1));
2107269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  tcpport1->PrepareAddress();
2108269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<TCPPort> tcpport2(CreateTcpPort(kLocalAddr1));
2109269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  tcpport2->PrepareAddress();
2110269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(tcpport1->Candidates()[0].foundation(),
2111269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org            tcpport2->Candidates()[0].foundation());
2112269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<Port> stunport(
2113269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      CreateStunPort(kLocalAddr1, nat_socket_factory1()));
2114269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  stunport->PrepareAddress();
2115269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_EQ_WAIT(1U, stunport->Candidates().size(), kTimeout);
2116269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_NE(tcpport1->Candidates()[0].foundation(),
2117269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org            stunport->Candidates()[0].foundation());
2118269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_NE(tcpport2->Candidates()[0].foundation(),
2119269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org            stunport->Candidates()[0].foundation());
2120269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_NE(udpport1->Candidates()[0].foundation(),
2121269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org            stunport->Candidates()[0].foundation());
2122269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_NE(udpport2->Candidates()[0].foundation(),
2123269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org            stunport->Candidates()[0].foundation());
2124269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Verify GTURN candidate foundation.
2125269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<RelayPort> relayport(
2126269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      CreateGturnPort(kLocalAddr1));
2127269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  relayport->AddServerAddress(
2128269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      cricket::ProtocolAddress(kRelayUdpIntAddr, cricket::PROTO_UDP));
2129269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  relayport->PrepareAddress();
2130269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_EQ_WAIT(1U, relayport->Candidates().size(), kTimeout);
2131269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_NE(udpport1->Candidates()[0].foundation(),
2132269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org            relayport->Candidates()[0].foundation());
2133269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_NE(udpport2->Candidates()[0].foundation(),
2134269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org            relayport->Candidates()[0].foundation());
2135269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Verifying TURN candidate foundation.
2136269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<Port> turnport1(CreateTurnPort(
2137269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      kLocalAddr1, nat_socket_factory1(), PROTO_UDP, PROTO_UDP));
2138269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  turnport1->PrepareAddress();
2139269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_EQ_WAIT(1U, turnport1->Candidates().size(), kTimeout);
2140269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_NE(udpport1->Candidates()[0].foundation(),
2141269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org            turnport1->Candidates()[0].foundation());
2142269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_NE(udpport2->Candidates()[0].foundation(),
2143269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org            turnport1->Candidates()[0].foundation());
2144269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_NE(stunport->Candidates()[0].foundation(),
2145269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org            turnport1->Candidates()[0].foundation());
2146269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<Port> turnport2(CreateTurnPort(
2147269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      kLocalAddr1, nat_socket_factory1(), PROTO_UDP, PROTO_UDP));
2148269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  turnport2->PrepareAddress();
2149269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_EQ_WAIT(1U, turnport2->Candidates().size(), kTimeout);
2150269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(turnport1->Candidates()[0].foundation(),
2151269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org            turnport2->Candidates()[0].foundation());
2152269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2153269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Running a second turn server, to get different base IP address.
2154269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  SocketAddress kTurnUdpIntAddr2("99.99.98.4", STUN_SERVER_PORT);
2155269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  SocketAddress kTurnUdpExtAddr2("99.99.98.5", 0);
2156269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestTurnServer turn_server2(
2157269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      rtc::Thread::Current(), kTurnUdpIntAddr2, kTurnUdpExtAddr2);
2158269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<Port> turnport3(CreateTurnPort(
2159269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      kLocalAddr1, nat_socket_factory1(), PROTO_UDP, PROTO_UDP,
2160269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      kTurnUdpIntAddr2));
2161269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  turnport3->PrepareAddress();
2162269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_EQ_WAIT(1U, turnport3->Candidates().size(), kTimeout);
2163269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_NE(turnport3->Candidates()[0].foundation(),
2164269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org            turnport2->Candidates()[0].foundation());
2165269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
2166269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2167269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// This test verifies the related addresses of different types of
2168269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// ICE candiates.
2169269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestCandidateRelatedAddress) {
2170269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<rtc::NATServer> nat_server(
2171269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      CreateNatServer(kNatAddr1, NAT_OPEN_CONE));
2172269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<UDPPort> udpport(CreateUdpPort(kLocalAddr1));
2173269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  udpport->PrepareAddress();
2174269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // For UDPPort, related address will be empty.
2175269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(udpport->Candidates()[0].related_address().IsNil());
2176269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Testing related address for stun candidates.
2177269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // For stun candidate related address must be equal to the base
2178269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // socket address.
2179269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<StunPort> stunport(
2180269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      CreateStunPort(kLocalAddr1, nat_socket_factory1()));
2181269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  stunport->PrepareAddress();
2182269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_EQ_WAIT(1U, stunport->Candidates().size(), kTimeout);
2183269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Check STUN candidate address.
2184269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(stunport->Candidates()[0].address().ipaddr(),
2185269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org            kNatAddr1.ipaddr());
2186269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Check STUN candidate related address.
2187269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(stunport->Candidates()[0].related_address(),
2188269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org            stunport->GetLocalAddress());
2189269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Verifying the related address for the GTURN candidates.
2190269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // NOTE: In case of GTURN related address will be equal to the mapped
2191269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // address, but address(mapped) will not be XOR.
2192269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<RelayPort> relayport(
2193269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      CreateGturnPort(kLocalAddr1));
2194269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  relayport->AddServerAddress(
2195269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      cricket::ProtocolAddress(kRelayUdpIntAddr, cricket::PROTO_UDP));
2196269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  relayport->PrepareAddress();
2197269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_EQ_WAIT(1U, relayport->Candidates().size(), kTimeout);
2198269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // For Gturn related address is set to "0.0.0.0:0"
2199269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(rtc::SocketAddress(),
2200269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org            relayport->Candidates()[0].related_address());
2201269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Verifying the related address for TURN candidate.
2202269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // For TURN related address must be equal to the mapped address.
2203269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<Port> turnport(CreateTurnPort(
2204269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      kLocalAddr1, nat_socket_factory1(), PROTO_UDP, PROTO_UDP));
2205269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  turnport->PrepareAddress();
2206269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_EQ_WAIT(1U, turnport->Candidates().size(), kTimeout);
2207269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(kTurnUdpExtAddr.ipaddr(),
2208269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org            turnport->Candidates()[0].address().ipaddr());
2209269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(kNatAddr1.ipaddr(),
2210269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org            turnport->Candidates()[0].related_address().ipaddr());
2211269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
2212269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2213269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Test priority value overflow handling when preference is set to 3.
22147cbd188c5ed7df80bb737bd4ada94422730e2d89Peter ThatcherTEST_F(PortTest, TestCandidatePriority) {
2215269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  cricket::Candidate cand1;
22167cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher  cand1.set_priority(3);
2217269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  cricket::Candidate cand2;
22187cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher  cand2.set_priority(1);
22197cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher  EXPECT_TRUE(cand1.priority() > cand2.priority());
2220269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
2221269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2222269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Test the Connection priority is calculated correctly.
2223269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestConnectionPriority) {
2224269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<TestPort> lport(
2225269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      CreateTestPort(kLocalAddr1, "lfrag", "lpass"));
2226269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  lport->set_type_preference(cricket::ICE_TYPE_PREFERENCE_HOST);
2227269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<TestPort> rport(
2228269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      CreateTestPort(kLocalAddr2, "rfrag", "rpass"));
2229269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rport->set_type_preference(cricket::ICE_TYPE_PREFERENCE_RELAY);
2230269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  lport->set_component(123);
2231269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  lport->AddCandidateAddress(SocketAddress("192.168.1.4", 1234));
2232269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rport->set_component(23);
2233269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rport->AddCandidateAddress(SocketAddress("10.1.1.100", 1234));
2234269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2235269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(0x7E001E85U, lport->Candidates()[0].priority());
2236269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(0x2001EE9U, rport->Candidates()[0].priority());
2237269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2238269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // RFC 5245
2239269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // pair priority = 2^32*MIN(G,D) + 2*MAX(G,D) + (G>D?1:0)
2240269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  lport->SetIceRole(cricket::ICEROLE_CONTROLLING);
2241269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rport->SetIceRole(cricket::ICEROLE_CONTROLLED);
2242269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  Connection* lconn = lport->CreateConnection(
2243269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      rport->Candidates()[0], Port::ORIGIN_MESSAGE);
2244269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#if defined(WEBRTC_WIN)
2245269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(0x2001EE9FC003D0BU, lconn->priority());
2246269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#else
2247269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(0x2001EE9FC003D0BLLU, lconn->priority());
2248269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#endif
2249269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2250269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  lport->SetIceRole(cricket::ICEROLE_CONTROLLED);
2251269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rport->SetIceRole(cricket::ICEROLE_CONTROLLING);
2252269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  Connection* rconn = rport->CreateConnection(
2253269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      lport->Candidates()[0], Port::ORIGIN_MESSAGE);
2254269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#if defined(WEBRTC_WIN)
2255269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(0x2001EE9FC003D0AU, rconn->priority());
2256269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#else
2257269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(0x2001EE9FC003D0ALLU, rconn->priority());
2258269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#endif
2259269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
2260269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2261269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestWritableState) {
2262269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  UDPPort* port1 = CreateUdpPort(kLocalAddr1);
22637cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher  port1->SetIceRole(cricket::ICEROLE_CONTROLLING);
2264269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  UDPPort* port2 = CreateUdpPort(kLocalAddr2);
22657cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher  port2->SetIceRole(cricket::ICEROLE_CONTROLLED);
2266269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2267269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Set up channels.
22681eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh  TestChannel ch1(port1);
22691eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh  TestChannel ch2(port2);
2270269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2271269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Acquire addresses.
2272269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ch1.Start();
2273269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ch2.Start();
2274269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_EQ_WAIT(1, ch1.complete_count(), kTimeout);
2275269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_EQ_WAIT(1, ch2.complete_count(), kTimeout);
2276269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2277269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Send a ping from src to dst.
22781eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh  ch1.CreateConnection(GetCandidate(port2));
2279269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_TRUE(ch1.conn() != NULL);
2280269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(Connection::STATE_WRITE_INIT, ch1.conn()->write_state());
2281269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE_WAIT(ch1.conn()->connected(), kTimeout);  // for TCP connect
2282269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ch1.Ping();
2283269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  WAIT(!ch2.remote_address().IsNil(), kTimeout);
2284269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2285269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Data should be unsendable until the connection is accepted.
2286269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  char data[] = "abcd";
22875237aaf243d29732f59557361b7a993c0a18cf0etfarina  int data_size = arraysize(data);
2288269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::PacketOptions options;
2289269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(SOCKET_ERROR, ch1.conn()->Send(data, data_size, options));
2290269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2291269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Accept the connection to return the binding response, transition to
2292269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // writable, and allow data to be sent.
22931eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh  ch2.AcceptConnection(GetCandidate(port1));
2294269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ_WAIT(Connection::STATE_WRITABLE, ch1.conn()->write_state(),
2295269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                 kTimeout);
2296269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(data_size, ch1.conn()->Send(data, data_size, options));
2297269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2298269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Ask the connection to update state as if enough time has passed to lose
2299269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // full writability and 5 pings went unresponded to. We'll accomplish the
2300269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // latter by sending pings but not pumping messages.
23010c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  for (uint32_t i = 1; i <= CONNECTION_WRITE_CONNECT_FAILURES; ++i) {
2302269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    ch1.Ping(i);
2303269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
23040c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint32_t unreliable_timeout_delay = CONNECTION_WRITE_CONNECT_TIMEOUT + 500u;
2305269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ch1.conn()->UpdateState(unreliable_timeout_delay);
2306269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(Connection::STATE_WRITE_UNRELIABLE, ch1.conn()->write_state());
2307269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2308269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Data should be able to be sent in this state.
2309269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(data_size, ch1.conn()->Send(data, data_size, options));
2310269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2311269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // And now allow the other side to process the pings and send binding
2312269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // responses.
2313269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ_WAIT(Connection::STATE_WRITABLE, ch1.conn()->write_state(),
2314269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                 kTimeout);
2315269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2316269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Wait long enough for a full timeout (past however long we've already
2317269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // waited).
23180c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  for (uint32_t i = 1; i <= CONNECTION_WRITE_CONNECT_FAILURES; ++i) {
2319269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    ch1.Ping(unreliable_timeout_delay + i);
2320269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
2321269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ch1.conn()->UpdateState(unreliable_timeout_delay + CONNECTION_WRITE_TIMEOUT +
2322269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                          500u);
2323269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(Connection::STATE_WRITE_TIMEOUT, ch1.conn()->write_state());
2324269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2325269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Now that the connection has completely timed out, data send should fail.
2326269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(SOCKET_ERROR, ch1.conn()->Send(data, data_size, options));
2327269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2328269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ch1.Stop();
2329269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ch2.Stop();
2330269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
2331269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2332269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestTimeoutForNeverWritable) {
2333269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  UDPPort* port1 = CreateUdpPort(kLocalAddr1);
23347cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher  port1->SetIceRole(cricket::ICEROLE_CONTROLLING);
2335269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  UDPPort* port2 = CreateUdpPort(kLocalAddr2);
23367cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher  port2->SetIceRole(cricket::ICEROLE_CONTROLLED);
2337269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2338269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Set up channels.
23391eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh  TestChannel ch1(port1);
23401eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh  TestChannel ch2(port2);
2341269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2342269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Acquire addresses.
2343269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ch1.Start();
2344269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ch2.Start();
2345269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
23461eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh  ch1.CreateConnection(GetCandidate(port2));
2347269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_TRUE(ch1.conn() != NULL);
2348269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(Connection::STATE_WRITE_INIT, ch1.conn()->write_state());
2349269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2350269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Attempt to go directly to write timeout.
23510c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  for (uint32_t i = 1; i <= CONNECTION_WRITE_CONNECT_FAILURES; ++i) {
2352269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    ch1.Ping(i);
2353269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
2354269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ch1.conn()->UpdateState(CONNECTION_WRITE_TIMEOUT + 500u);
2355269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(Connection::STATE_WRITE_TIMEOUT, ch1.conn()->write_state());
2356269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
2357269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2358269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// This test verifies the connection setup between ICEMODE_FULL
2359269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// and ICEMODE_LITE.
2360269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// In this test |ch1| behaves like FULL mode client and we have created
2361269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// port which responds to the ping message just like LITE client.
2362269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestIceLiteConnectivity) {
2363269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TestPort* ice_full_port = CreateTestPort(
23647cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher      kLocalAddr1, "lfrag", "lpass",
2365269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      cricket::ICEROLE_CONTROLLING, kTiebreaker1);
2366269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2367269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<TestPort> ice_lite_port(CreateTestPort(
23687cbd188c5ed7df80bb737bd4ada94422730e2d89Peter Thatcher      kLocalAddr2, "rfrag", "rpass",
2369269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      cricket::ICEROLE_CONTROLLED, kTiebreaker2));
2370269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Setup TestChannel. This behaves like FULL mode client.
23711eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh  TestChannel ch1(ice_full_port);
2372269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ch1.SetIceMode(ICEMODE_FULL);
2373269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2374269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Start gathering candidates.
2375269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ch1.Start();
2376269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ice_lite_port->PrepareAddress();
2377269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2378269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_EQ_WAIT(1, ch1.complete_count(), kTimeout);
2379269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_FALSE(ice_lite_port->Candidates().empty());
2380269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
23811eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh  ch1.CreateConnection(GetCandidate(ice_lite_port.get()));
2382269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_TRUE(ch1.conn() != NULL);
2383269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ(Connection::STATE_WRITE_INIT, ch1.conn()->write_state());
2384269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2385269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Send ping from full mode client.
2386269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // This ping must not have USE_CANDIDATE_ATTR.
2387269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ch1.Ping();
2388269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2389269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Verify stun ping is without USE_CANDIDATE_ATTR. Getting message directly
2390269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // from port.
2391269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_TRUE_WAIT(ice_full_port->last_stun_msg() != NULL, 1000);
2392269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  IceMessage* msg = ice_full_port->last_stun_msg();
2393269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(msg->GetByteString(STUN_ATTR_USE_CANDIDATE) == NULL);
2394269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2395269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Respond with a BINDING-RESPONSE from litemode client.
2396269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // NOTE: Ideally we should't create connection at this stage from lite
2397269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // port, as it should be done only after receiving ping with USE_CANDIDATE.
2398269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // But we need a connection to send a response message.
2399269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ice_lite_port->CreateConnection(
2400269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      ice_full_port->Candidates()[0], cricket::Port::ORIGIN_MESSAGE);
2401269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::scoped_ptr<IceMessage> request(CopyStunMessage(msg));
2402269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ice_lite_port->SendBindingResponse(
2403269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      request.get(), ice_full_port->Candidates()[0].address());
2404269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2405269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Feeding the respone message from litemode to the full mode connection.
2406269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ch1.conn()->OnReadPacket(ice_lite_port->last_stun_buf()->Data(),
2407269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                           ice_lite_port->last_stun_buf()->Length(),
2408269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                           rtc::PacketTime());
2409269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Verifying full mode connection becomes writable from the response.
2410269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_EQ_WAIT(Connection::STATE_WRITABLE, ch1.conn()->write_state(),
2411269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                 kTimeout);
2412269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE_WAIT(ch1.nominated(), kTimeout);
2413269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2414269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Clear existing stun messsages. Otherwise we will process old stun
2415269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // message right after we send ping.
2416269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ice_full_port->Reset();
2417269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Send ping. This must have USE_CANDIDATE_ATTR.
2418269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ch1.Ping();
2419269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT_TRUE_WAIT(ice_full_port->last_stun_msg() != NULL, 1000);
2420269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  msg = ice_full_port->last_stun_msg();
2421269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE(msg->GetByteString(STUN_ATTR_USE_CANDIDATE) != NULL);
2422269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ch1.Stop();
2423269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
2424269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2425269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// This test case verifies that the CONTROLLING port does not time out.
2426269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestControllingNoTimeout) {
2427269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  UDPPort* port1 = CreateUdpPort(kLocalAddr1);
2428269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ConnectToSignalDestroyed(port1);
2429269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  port1->set_timeout_delay(10);  // milliseconds
2430269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  port1->SetIceRole(cricket::ICEROLE_CONTROLLING);
2431269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  port1->SetIceTiebreaker(kTiebreaker1);
2432269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2433269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  UDPPort* port2 = CreateUdpPort(kLocalAddr2);
2434269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  port2->SetIceRole(cricket::ICEROLE_CONTROLLED);
2435269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  port2->SetIceTiebreaker(kTiebreaker2);
2436269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2437269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Set up channels and ensure both ports will be deleted.
24381eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh  TestChannel ch1(port1);
24391eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh  TestChannel ch2(port2);
2440269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2441269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Simulate a connection that succeeds, and then is destroyed.
2442be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  StartConnectAndStopChannels(&ch1, &ch2);
2443269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2444269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // After the connection is destroyed, the port should not be destroyed.
2445269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::Thread::Current()->ProcessMessages(kTimeout);
2446269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_FALSE(destroyed());
2447269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
2448269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2449269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// This test case verifies that the CONTROLLED port does time out, but only
2450269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// after connectivity is lost.
2451269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTEST_F(PortTest, TestControlledTimeout) {
2452269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  UDPPort* port1 = CreateUdpPort(kLocalAddr1);
2453269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  port1->SetIceRole(cricket::ICEROLE_CONTROLLING);
2454269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  port1->SetIceTiebreaker(kTiebreaker1);
2455269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2456269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  UDPPort* port2 = CreateUdpPort(kLocalAddr2);
2457269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ConnectToSignalDestroyed(port2);
2458269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  port2->set_timeout_delay(10);  // milliseconds
2459269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  port2->SetIceRole(cricket::ICEROLE_CONTROLLED);
2460269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  port2->SetIceTiebreaker(kTiebreaker2);
2461269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2462269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // The connection must not be destroyed before a connection is attempted.
2463269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_FALSE(destroyed());
2464269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2465269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  port1->set_component(cricket::ICE_CANDIDATE_COMPONENT_DEFAULT);
2466269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  port2->set_component(cricket::ICE_CANDIDATE_COMPONENT_DEFAULT);
2467269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2468269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Set up channels and ensure both ports will be deleted.
24691eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh  TestChannel ch1(port1);
24701eb87c7d94916a6e5641bfbbc8df37527712e4caGuo-wei Shieh  TestChannel ch2(port2);
2471269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2472269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Simulate a connection that succeeds, and then is destroyed.
2473be508a1d3634ce63b64cd740c44600453e3c3a6bGuo-wei Shieh  StartConnectAndStopChannels(&ch1, &ch2);
2474269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
2475269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // The controlled port should be destroyed after 10 milliseconds.
2476269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  EXPECT_TRUE_WAIT(destroyed(), kTimeout);
2477269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
2478d0b3143f0e37f5f5e0578e88cf740dd839b50c24honghaiz
2479d0b3143f0e37f5f5e0578e88cf740dd839b50c24honghaiz// This test case verifies that if the role of a port changes from controlled
2480d0b3143f0e37f5f5e0578e88cf740dd839b50c24honghaiz// to controlling after all connections fail, the port will not be destroyed.
2481d0b3143f0e37f5f5e0578e88cf740dd839b50c24honghaizTEST_F(PortTest, TestControlledToControllingNotDestroyed) {
2482d0b3143f0e37f5f5e0578e88cf740dd839b50c24honghaiz  UDPPort* port1 = CreateUdpPort(kLocalAddr1);
2483d0b3143f0e37f5f5e0578e88cf740dd839b50c24honghaiz  port1->SetIceRole(cricket::ICEROLE_CONTROLLING);
2484d0b3143f0e37f5f5e0578e88cf740dd839b50c24honghaiz  port1->SetIceTiebreaker(kTiebreaker1);
2485d0b3143f0e37f5f5e0578e88cf740dd839b50c24honghaiz
2486d0b3143f0e37f5f5e0578e88cf740dd839b50c24honghaiz  UDPPort* port2 = CreateUdpPort(kLocalAddr2);
2487d0b3143f0e37f5f5e0578e88cf740dd839b50c24honghaiz  ConnectToSignalDestroyed(port2);
2488d0b3143f0e37f5f5e0578e88cf740dd839b50c24honghaiz  port2->set_timeout_delay(10);  // milliseconds
2489d0b3143f0e37f5f5e0578e88cf740dd839b50c24honghaiz  port2->SetIceRole(cricket::ICEROLE_CONTROLLED);
2490d0b3143f0e37f5f5e0578e88cf740dd839b50c24honghaiz  port2->SetIceTiebreaker(kTiebreaker2);
2491d0b3143f0e37f5f5e0578e88cf740dd839b50c24honghaiz
2492d0b3143f0e37f5f5e0578e88cf740dd839b50c24honghaiz  // The connection must not be destroyed before a connection is attempted.
2493d0b3143f0e37f5f5e0578e88cf740dd839b50c24honghaiz  EXPECT_FALSE(destroyed());
2494d0b3143f0e37f5f5e0578e88cf740dd839b50c24honghaiz
2495d0b3143f0e37f5f5e0578e88cf740dd839b50c24honghaiz  port1->set_component(cricket::ICE_CANDIDATE_COMPONENT_DEFAULT);
2496d0b3143f0e37f5f5e0578e88cf740dd839b50c24honghaiz  port2->set_component(cricket::ICE_CANDIDATE_COMPONENT_DEFAULT);
2497d0b3143f0e37f5f5e0578e88cf740dd839b50c24honghaiz
2498d0b3143f0e37f5f5e0578e88cf740dd839b50c24honghaiz  // Set up channels and ensure both ports will be deleted.
2499d0b3143f0e37f5f5e0578e88cf740dd839b50c24honghaiz  TestChannel ch1(port1);
2500d0b3143f0e37f5f5e0578e88cf740dd839b50c24honghaiz  TestChannel ch2(port2);
2501d0b3143f0e37f5f5e0578e88cf740dd839b50c24honghaiz
2502d0b3143f0e37f5f5e0578e88cf740dd839b50c24honghaiz  // Simulate a connection that succeeds, and then is destroyed.
2503d0b3143f0e37f5f5e0578e88cf740dd839b50c24honghaiz  StartConnectAndStopChannels(&ch1, &ch2);
2504d0b3143f0e37f5f5e0578e88cf740dd839b50c24honghaiz  // Switch the role after all connections are destroyed.
2505d0b3143f0e37f5f5e0578e88cf740dd839b50c24honghaiz  EXPECT_TRUE_WAIT(ch2.conn() == nullptr, kTimeout);
2506d0b3143f0e37f5f5e0578e88cf740dd839b50c24honghaiz  port1->SetIceRole(cricket::ICEROLE_CONTROLLED);
2507d0b3143f0e37f5f5e0578e88cf740dd839b50c24honghaiz  port2->SetIceRole(cricket::ICEROLE_CONTROLLING);
2508d0b3143f0e37f5f5e0578e88cf740dd839b50c24honghaiz
2509d0b3143f0e37f5f5e0578e88cf740dd839b50c24honghaiz  // After the connection is destroyed, the port should not be destroyed.
2510d0b3143f0e37f5f5e0578e88cf740dd839b50c24honghaiz  rtc::Thread::Current()->ProcessMessages(kTimeout);
2511d0b3143f0e37f5f5e0578e88cf740dd839b50c24honghaiz  EXPECT_FALSE(destroyed());
2512d0b3143f0e37f5f5e0578e88cf740dd839b50c24honghaiz}
2513f9945b2d1aa2d78b19987219ea872605167d7b5fHonghai Zhang
2514f9945b2d1aa2d78b19987219ea872605167d7b5fHonghai ZhangTEST_F(PortTest, TestSupportsProtocol) {
2515f9945b2d1aa2d78b19987219ea872605167d7b5fHonghai Zhang  rtc::scoped_ptr<Port> udp_port(CreateUdpPort(kLocalAddr1));
2516f9945b2d1aa2d78b19987219ea872605167d7b5fHonghai Zhang  EXPECT_TRUE(udp_port->SupportsProtocol(UDP_PROTOCOL_NAME));
2517f9945b2d1aa2d78b19987219ea872605167d7b5fHonghai Zhang  EXPECT_FALSE(udp_port->SupportsProtocol(TCP_PROTOCOL_NAME));
2518f9945b2d1aa2d78b19987219ea872605167d7b5fHonghai Zhang
2519f9945b2d1aa2d78b19987219ea872605167d7b5fHonghai Zhang  rtc::scoped_ptr<Port> stun_port(
2520f9945b2d1aa2d78b19987219ea872605167d7b5fHonghai Zhang      CreateStunPort(kLocalAddr1, nat_socket_factory1()));
2521f9945b2d1aa2d78b19987219ea872605167d7b5fHonghai Zhang  EXPECT_TRUE(stun_port->SupportsProtocol(UDP_PROTOCOL_NAME));
2522f9945b2d1aa2d78b19987219ea872605167d7b5fHonghai Zhang  EXPECT_FALSE(stun_port->SupportsProtocol(TCP_PROTOCOL_NAME));
2523f9945b2d1aa2d78b19987219ea872605167d7b5fHonghai Zhang
2524f9945b2d1aa2d78b19987219ea872605167d7b5fHonghai Zhang  rtc::scoped_ptr<Port> tcp_port(CreateTcpPort(kLocalAddr1));
2525f9945b2d1aa2d78b19987219ea872605167d7b5fHonghai Zhang  EXPECT_TRUE(tcp_port->SupportsProtocol(TCP_PROTOCOL_NAME));
2526f9945b2d1aa2d78b19987219ea872605167d7b5fHonghai Zhang  EXPECT_TRUE(tcp_port->SupportsProtocol(SSLTCP_PROTOCOL_NAME));
2527f9945b2d1aa2d78b19987219ea872605167d7b5fHonghai Zhang  EXPECT_FALSE(tcp_port->SupportsProtocol(UDP_PROTOCOL_NAME));
2528f9945b2d1aa2d78b19987219ea872605167d7b5fHonghai Zhang
2529f9945b2d1aa2d78b19987219ea872605167d7b5fHonghai Zhang  rtc::scoped_ptr<Port> turn_port(
2530f9945b2d1aa2d78b19987219ea872605167d7b5fHonghai Zhang      CreateTurnPort(kLocalAddr1, nat_socket_factory1(), PROTO_UDP, PROTO_UDP));
2531f9945b2d1aa2d78b19987219ea872605167d7b5fHonghai Zhang  EXPECT_TRUE(turn_port->SupportsProtocol(UDP_PROTOCOL_NAME));
2532f9945b2d1aa2d78b19987219ea872605167d7b5fHonghai Zhang  EXPECT_FALSE(turn_port->SupportsProtocol(TCP_PROTOCOL_NAME));
2533f9945b2d1aa2d78b19987219ea872605167d7b5fHonghai Zhang}
2534