123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878 |
- /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
- // Original author: bcampen@mozilla.com
- extern "C" {
- #include "stun_msg.h" // for NR_STUN_MAX_MESSAGE_SIZE
- #include "stun_util.h"
- #include "nr_api.h"
- #include "async_wait.h"
- #include "nr_socket.h"
- #include "nr_socket_local.h"
- #include "stun_hint.h"
- #include "local_addr.h"
- #include "registry.h"
- }
- #include "test_nr_socket.h"
- #include "nsCOMPtr.h"
- #include "nsNetCID.h"
- #include "nsServiceManagerUtils.h"
- #include "nsAutoPtr.h"
- #include "runnable_utils.h"
- #include <vector>
- #define GTEST_HAS_RTTI 0
- #include "gtest/gtest.h"
- #include "gtest_utils.h"
- #define DATA_BUF_SIZE 1024
- namespace mozilla {
- class TestNrSocketTest : public MtransportTest {
- public:
- TestNrSocketTest() :
- MtransportTest(),
- wait_done_for_main_(false),
- sts_(),
- public_addrs_(),
- private_addrs_(),
- nats_() {
- }
- void SetUp() override {
- MtransportTest::SetUp();
- // Get the transport service as a dispatch target
- nsresult rv;
- sts_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
- EXPECT_TRUE(NS_SUCCEEDED(rv)) << "Failed to get STS: " << (int)rv;
- }
- void TearDown() override {
- sts_->Dispatch(WrapRunnable(this, &TestNrSocketTest::TearDown_s),
- NS_DISPATCH_SYNC);
- MtransportTest::TearDown();
- }
- void TearDown_s() {
- public_addrs_.clear();
- private_addrs_.clear();
- nats_.clear();
- sts_ = nullptr;
- }
- RefPtr<TestNrSocket> CreateTestNrSocket_s(const char *ip_str,
- int proto,
- TestNat *nat) {
- // If no nat is supplied, we create a default NAT which is disabled. This
- // is how we simulate a non-natted socket.
- RefPtr<TestNrSocket> sock(new TestNrSocket(nat ? nat : new TestNat));
- nr_transport_addr address;
- nr_str_port_to_transport_addr(ip_str, 0, proto, &address);
- int r = sock->create(&address);
- if (r) {
- return nullptr;
- }
- return sock;
- }
- void CreatePublicAddrs(size_t count,
- const char *ip_str = "127.0.0.1",
- int proto = IPPROTO_UDP) {
- sts_->Dispatch(
- WrapRunnable(this,
- &TestNrSocketTest::CreatePublicAddrs_s,
- count,
- ip_str,
- proto),
- NS_DISPATCH_SYNC);
- }
- void CreatePublicAddrs_s(size_t count, const char* ip_str, int proto) {
- while (count--) {
- auto sock = CreateTestNrSocket_s(ip_str, proto, nullptr);
- ASSERT_TRUE(sock) << "Failed to create socket";
- public_addrs_.push_back(sock);
- }
- }
- RefPtr<TestNat> CreatePrivateAddrs(size_t size,
- const char* ip_str = "127.0.0.1",
- int proto = IPPROTO_UDP) {
- RefPtr<TestNat> result;
- sts_->Dispatch(
- WrapRunnableRet(&result,
- this,
- &TestNrSocketTest::CreatePrivateAddrs_s,
- size,
- ip_str,
- proto),
- NS_DISPATCH_SYNC);
- return result;
- }
- RefPtr<TestNat> CreatePrivateAddrs_s(size_t count,
- const char* ip_str,
- int proto) {
- RefPtr<TestNat> nat(new TestNat);
- while (count--) {
- auto sock = CreateTestNrSocket_s(ip_str, proto, nat);
- if (!sock) {
- EXPECT_TRUE(false) << "Failed to create socket";
- break;
- }
- private_addrs_.push_back(sock);
- }
- nat->enabled_ = true;
- nats_.push_back(nat);
- return nat;
- }
- bool CheckConnectivityVia(
- TestNrSocket *from,
- TestNrSocket *to,
- const nr_transport_addr &via,
- nr_transport_addr *sender_external_address = nullptr) {
- MOZ_ASSERT(from);
- if (!WaitForWriteable(from)) {
- return false;
- }
- int result = 0;
- sts_->Dispatch(WrapRunnableRet(&result,
- this,
- &TestNrSocketTest::SendData_s,
- from,
- via),
- NS_DISPATCH_SYNC);
- if (result) {
- return false;
- }
- if (!WaitForReadable(to)) {
- return false;
- }
- nr_transport_addr dummy_outparam;
- if (!sender_external_address) {
- sender_external_address = &dummy_outparam;
- }
- MOZ_ASSERT(to);
- sts_->Dispatch(WrapRunnableRet(&result,
- this,
- &TestNrSocketTest::RecvData_s,
- to,
- sender_external_address),
- NS_DISPATCH_SYNC);
- return !result;
- }
- bool CheckConnectivity(
- TestNrSocket *from,
- TestNrSocket *to,
- nr_transport_addr *sender_external_address = nullptr) {
- nr_transport_addr destination_address;
- int r = GetAddress(to, &destination_address);
- if (r) {
- return false;
- }
- return CheckConnectivityVia(from,
- to,
- destination_address,
- sender_external_address);
- }
- bool CheckTcpConnectivity(TestNrSocket *from, TestNrSocket *to) {
- NrSocketBase *accepted_sock;
- if (!Connect(from, to, &accepted_sock)) {
- std::cerr << "Connect failed" << std::endl;
- return false;
- }
- // write on |from|, recv on |accepted_sock|
- if (!WaitForWriteable(from)) {
- std::cerr << __LINE__ << "WaitForWriteable (1) failed" << std::endl;
- return false;
- }
- int r;
- sts_->Dispatch(WrapRunnableRet(&r,
- this,
- &TestNrSocketTest::SendDataTcp_s,
- from),
- NS_DISPATCH_SYNC);
- if (r) {
- std::cerr << "SendDataTcp_s (1) failed" << std::endl;
- return false;
- }
- if (!WaitForReadable(accepted_sock)) {
- std::cerr << __LINE__ << "WaitForReadable (1) failed" << std::endl;
- return false;
- }
- sts_->Dispatch(WrapRunnableRet(&r,
- this,
- &TestNrSocketTest::RecvDataTcp_s,
- accepted_sock),
- NS_DISPATCH_SYNC);
- if (r) {
- std::cerr << "RecvDataTcp_s (1) failed" << std::endl;
- return false;
- }
- if (!WaitForWriteable(accepted_sock)) {
- std::cerr << __LINE__ << "WaitForWriteable (2) failed" << std::endl;
- return false;
- }
- sts_->Dispatch(WrapRunnableRet(&r,
- this,
- &TestNrSocketTest::SendDataTcp_s,
- accepted_sock),
- NS_DISPATCH_SYNC);
- if (r) {
- std::cerr << "SendDataTcp_s (2) failed" << std::endl;
- return false;
- }
- if (!WaitForReadable(from)) {
- std::cerr << __LINE__ << "WaitForReadable (2) failed" << std::endl;
- return false;
- }
- sts_->Dispatch(WrapRunnableRet(&r,
- this,
- &TestNrSocketTest::RecvDataTcp_s,
- from),
- NS_DISPATCH_SYNC);
- if (r) {
- std::cerr << "RecvDataTcp_s (2) failed" << std::endl;
- return false;
- }
- return true;
- }
- int GetAddress(TestNrSocket *sock, nr_transport_addr_ *address) {
- MOZ_ASSERT(sock);
- MOZ_ASSERT(address);
- int r;
- sts_->Dispatch(WrapRunnableRet(&r,
- this,
- &TestNrSocketTest::GetAddress_s,
- sock,
- address),
- NS_DISPATCH_SYNC);
- return r;
- }
- int GetAddress_s(TestNrSocket *sock, nr_transport_addr *address) {
- return sock->getaddr(address);
- }
- int SendData_s(TestNrSocket *from, const nr_transport_addr &to) {
- // It is up to caller to ensure that |from| is writeable.
- const char buf[] = "foobajooba";
- return from->sendto(buf, sizeof(buf), 0,
- // TODO(bug 1170299): Remove const_cast when no longer necessary
- const_cast<nr_transport_addr*>(&to));
- }
- int SendDataTcp_s(NrSocketBase *from) {
- // It is up to caller to ensure that |from| is writeable.
- const char buf[] = "foobajooba";
- size_t written;
- return from->write(buf, sizeof(buf), &written);
- }
- int RecvData_s(TestNrSocket *to, nr_transport_addr *from) {
- // It is up to caller to ensure that |to| is readable
- char buf[DATA_BUF_SIZE];
- size_t len;
- // Maybe check that data matches?
- int r = to->recvfrom(buf, sizeof(buf), &len, 0, from);
- if (!r && (len == 0)) {
- r = R_INTERNAL;
- }
- return r;
- }
- int RecvDataTcp_s(NrSocketBase *to) {
- // It is up to caller to ensure that |to| is readable
- char buf[DATA_BUF_SIZE];
- size_t len;
- // Maybe check that data matches?
- int r = to->read(buf, sizeof(buf), &len);
- if (!r && (len == 0)) {
- r = R_INTERNAL;
- }
- return r;
- }
- int Listen_s(TestNrSocket *to) {
- // listen on |to|
- int r = to->listen(1);
- if (r) {
- return r;
- }
- return 0;
- }
- int Connect_s(TestNrSocket *from, TestNrSocket *to) {
- // connect on |from|
- nr_transport_addr destination_address;
- int r = to->getaddr(&destination_address);
- if (r) {
- return r;
- }
- r = from->connect(&destination_address);
- if (r) {
- return r;
- }
- return 0;
- }
- int Accept_s(TestNrSocket *to, NrSocketBase **accepted_sock) {
- nr_socket *sock;
- nr_transport_addr source_address;
- int r = to->accept(&source_address, &sock);
- if (r) {
- return r;
- }
- *accepted_sock = reinterpret_cast<NrSocketBase*>(sock->obj);
- return 0;
- }
- bool Connect(TestNrSocket *from,
- TestNrSocket *to,
- NrSocketBase **accepted_sock) {
- int r;
- sts_->Dispatch(WrapRunnableRet(&r,
- this,
- &TestNrSocketTest::Listen_s,
- to),
- NS_DISPATCH_SYNC);
- if (r) {
- std::cerr << "Listen_s failed: " << r << std::endl;
- return false;
- }
- sts_->Dispatch(WrapRunnableRet(&r,
- this,
- &TestNrSocketTest::Connect_s,
- from,
- to),
- NS_DISPATCH_SYNC);
- if (r && r != R_WOULDBLOCK) {
- std::cerr << "Connect_s failed: " << r << std::endl;
- return false;
- }
- if (!WaitForReadable(to)) {
- std::cerr << "WaitForReadable failed" << std::endl;
- return false;
- }
- sts_->Dispatch(WrapRunnableRet(&r,
- this,
- &TestNrSocketTest::Accept_s,
- to,
- accepted_sock),
- NS_DISPATCH_SYNC);
- if (r) {
- std::cerr << "Accept_s failed: " << r << std::endl;
- return false;
- }
- return true;
- }
- bool WaitForSocketState(NrSocketBase *sock, int state) {
- MOZ_ASSERT(sock);
- sts_->Dispatch(WrapRunnable(this,
- &TestNrSocketTest::WaitForSocketState_s,
- sock,
- state),
- NS_DISPATCH_SYNC);
- bool res;
- WAIT_(wait_done_for_main_, 500, res);
- wait_done_for_main_ = false;
- if (!res) {
- sts_->Dispatch(WrapRunnable(this,
- &TestNrSocketTest::CancelWait_s,
- sock,
- state),
- NS_DISPATCH_SYNC);
- }
- return res;
- }
- void WaitForSocketState_s(NrSocketBase *sock, int state) {
- NR_ASYNC_WAIT(sock, state, &WaitDone, this);
- }
- void CancelWait_s(NrSocketBase *sock, int state) {
- sock->cancel(state);
- }
- bool WaitForReadable(NrSocketBase *sock) {
- return WaitForSocketState(sock, NR_ASYNC_WAIT_READ);
- }
- bool WaitForWriteable(NrSocketBase *sock) {
- return WaitForSocketState(sock, NR_ASYNC_WAIT_WRITE);
- }
- static void WaitDone(void *sock, int how, void *test_fixture) {
- TestNrSocketTest *test = static_cast<TestNrSocketTest*>(test_fixture);
- test->wait_done_for_main_ = true;
- }
- // Simple busywait boolean for the test cases to spin on.
- Atomic<bool> wait_done_for_main_;
- nsCOMPtr<nsIEventTarget> sts_;
- std::vector<RefPtr<TestNrSocket>> public_addrs_;
- std::vector<RefPtr<TestNrSocket>> private_addrs_;
- std::vector<RefPtr<TestNat>> nats_;
- };
- } // namespace mozilla
- using mozilla::TestNrSocketTest;
- using mozilla::TestNat;
- TEST_F(TestNrSocketTest, PublicConnectivity) {
- CreatePublicAddrs(2);
- ASSERT_TRUE(CheckConnectivity(public_addrs_[0], public_addrs_[1]));
- ASSERT_TRUE(CheckConnectivity(public_addrs_[1], public_addrs_[0]));
- ASSERT_TRUE(CheckConnectivity(public_addrs_[0], public_addrs_[0]));
- ASSERT_TRUE(CheckConnectivity(public_addrs_[1], public_addrs_[1]));
- }
- TEST_F(TestNrSocketTest, PrivateConnectivity) {
- RefPtr<TestNat> nat(CreatePrivateAddrs(2));
- nat->filtering_type_ = TestNat::ENDPOINT_INDEPENDENT;
- nat->mapping_type_ = TestNat::ENDPOINT_INDEPENDENT;
- ASSERT_TRUE(CheckConnectivity(private_addrs_[0], private_addrs_[1]));
- ASSERT_TRUE(CheckConnectivity(private_addrs_[1], private_addrs_[0]));
- ASSERT_TRUE(CheckConnectivity(private_addrs_[0], private_addrs_[0]));
- ASSERT_TRUE(CheckConnectivity(private_addrs_[1], private_addrs_[1]));
- }
- TEST_F(TestNrSocketTest, NoConnectivityWithoutPinhole) {
- RefPtr<TestNat> nat(CreatePrivateAddrs(1));
- nat->filtering_type_ = TestNat::ENDPOINT_INDEPENDENT;
- nat->mapping_type_ = TestNat::ENDPOINT_INDEPENDENT;
- CreatePublicAddrs(1);
- ASSERT_FALSE(CheckConnectivity(public_addrs_[0], private_addrs_[0]));
- }
- TEST_F(TestNrSocketTest, NoConnectivityBetweenSubnets) {
- RefPtr<TestNat> nat1(CreatePrivateAddrs(1));
- nat1->filtering_type_ = TestNat::ENDPOINT_INDEPENDENT;
- nat1->mapping_type_ = TestNat::ENDPOINT_INDEPENDENT;
- RefPtr<TestNat> nat2(CreatePrivateAddrs(1));
- nat2->filtering_type_ = TestNat::ENDPOINT_INDEPENDENT;
- nat2->mapping_type_ = TestNat::ENDPOINT_INDEPENDENT;
- ASSERT_FALSE(CheckConnectivity(private_addrs_[0], private_addrs_[1]));
- ASSERT_FALSE(CheckConnectivity(private_addrs_[1], private_addrs_[0]));
- ASSERT_TRUE(CheckConnectivity(private_addrs_[0], private_addrs_[0]));
- ASSERT_TRUE(CheckConnectivity(private_addrs_[1], private_addrs_[1]));
- }
- TEST_F(TestNrSocketTest, FullConeAcceptIngress) {
- RefPtr<TestNat> nat(CreatePrivateAddrs(1));
- nat->filtering_type_ = TestNat::ENDPOINT_INDEPENDENT;
- nat->mapping_type_ = TestNat::ENDPOINT_INDEPENDENT;
- CreatePublicAddrs(2);
- nr_transport_addr sender_external_address;
- // Open pinhole to public IP 0
- ASSERT_TRUE(CheckConnectivity(private_addrs_[0],
- public_addrs_[0],
- &sender_external_address));
- // Verify that return traffic works
- ASSERT_TRUE(CheckConnectivityVia(public_addrs_[0],
- private_addrs_[0],
- sender_external_address));
- // Verify that other public IP can use the pinhole
- ASSERT_TRUE(CheckConnectivityVia(public_addrs_[1],
- private_addrs_[0],
- sender_external_address));
- }
- TEST_F(TestNrSocketTest, FullConeOnePinhole) {
- RefPtr<TestNat> nat(CreatePrivateAddrs(1));
- nat->filtering_type_ = TestNat::ENDPOINT_INDEPENDENT;
- nat->mapping_type_ = TestNat::ENDPOINT_INDEPENDENT;
- CreatePublicAddrs(2);
- nr_transport_addr sender_external_address;
- // Open pinhole to public IP 0
- ASSERT_TRUE(CheckConnectivity(private_addrs_[0],
- public_addrs_[0],
- &sender_external_address));
- // Verify that return traffic works
- ASSERT_TRUE(CheckConnectivityVia(public_addrs_[0],
- private_addrs_[0],
- sender_external_address));
- // Send traffic to other public IP, verify that it uses the same pinhole
- nr_transport_addr sender_external_address2;
- ASSERT_TRUE(CheckConnectivity(private_addrs_[0],
- public_addrs_[1],
- &sender_external_address2));
- ASSERT_FALSE(nr_transport_addr_cmp(&sender_external_address,
- &sender_external_address2,
- NR_TRANSPORT_ADDR_CMP_MODE_ALL))
- << "addr1: " << sender_external_address.as_string << " addr2: "
- << sender_external_address2.as_string;
- }
- // OS 10.6 doesn't seem to allow us to open ports on 127.0.0.2, and while linux
- // does allow this, it has other behavior (see below) that prevents this test
- // from working.
- TEST_F(TestNrSocketTest, DISABLED_AddressRestrictedCone) {
- RefPtr<TestNat> nat(CreatePrivateAddrs(1));
- nat->filtering_type_ = TestNat::ADDRESS_DEPENDENT;
- nat->mapping_type_ = TestNat::ENDPOINT_INDEPENDENT;
- CreatePublicAddrs(2, "127.0.0.1");
- CreatePublicAddrs(1, "127.0.0.2");
- nr_transport_addr sender_external_address;
- // Open pinhole to public IP 0
- ASSERT_TRUE(CheckConnectivity(private_addrs_[0],
- public_addrs_[0],
- &sender_external_address));
- // Verify that return traffic works
- ASSERT_TRUE(CheckConnectivityVia(public_addrs_[0],
- private_addrs_[0],
- sender_external_address));
- // Verify that another address on the same host can use the pinhole
- ASSERT_TRUE(CheckConnectivityVia(public_addrs_[1],
- private_addrs_[0],
- sender_external_address));
- // Linux has a tendency to monkey around with source addresses, doing
- // stuff like substituting 127.0.0.1 for packets sent by 127.0.0.2, and even
- // going as far as substituting localhost for a packet sent from a real IP
- // address when the destination is localhost. The only way to make this test
- // work on linux is to have two real IP addresses.
- #ifndef __linux__
- // Verify that an address on a different host can't use the pinhole
- ASSERT_FALSE(CheckConnectivityVia(public_addrs_[2],
- private_addrs_[0],
- sender_external_address));
- #endif
- // Send traffic to other public IP, verify that it uses the same pinhole
- nr_transport_addr sender_external_address2;
- ASSERT_TRUE(CheckConnectivity(private_addrs_[0],
- public_addrs_[1],
- &sender_external_address2));
- ASSERT_FALSE(nr_transport_addr_cmp(&sender_external_address,
- &sender_external_address2,
- NR_TRANSPORT_ADDR_CMP_MODE_ALL))
- << "addr1: " << sender_external_address.as_string << " addr2: "
- << sender_external_address2.as_string;
- // Verify that the other public IP can now use the pinhole
- ASSERT_TRUE(CheckConnectivityVia(public_addrs_[1],
- private_addrs_[0],
- sender_external_address2));
- // Send traffic to other public IP, verify that it uses the same pinhole
- nr_transport_addr sender_external_address3;
- ASSERT_TRUE(CheckConnectivity(private_addrs_[0],
- public_addrs_[2],
- &sender_external_address3));
- ASSERT_FALSE(nr_transport_addr_cmp(&sender_external_address,
- &sender_external_address3,
- NR_TRANSPORT_ADDR_CMP_MODE_ALL))
- << "addr1: " << sender_external_address.as_string << " addr2: "
- << sender_external_address3.as_string;
- // Verify that the other public IP can now use the pinhole
- ASSERT_TRUE(CheckConnectivityVia(public_addrs_[2],
- private_addrs_[0],
- sender_external_address3));
- }
- TEST_F(TestNrSocketTest, RestrictedCone) {
- RefPtr<TestNat> nat(CreatePrivateAddrs(1));
- nat->filtering_type_ = TestNat::PORT_DEPENDENT;
- nat->mapping_type_ = TestNat::ENDPOINT_INDEPENDENT;
- CreatePublicAddrs(2);
- nr_transport_addr sender_external_address;
- // Open pinhole to public IP 0
- ASSERT_TRUE(CheckConnectivity(private_addrs_[0],
- public_addrs_[0],
- &sender_external_address));
- // Verify that return traffic works
- ASSERT_TRUE(CheckConnectivityVia(public_addrs_[0],
- private_addrs_[0],
- sender_external_address));
- // Verify that other public IP cannot use the pinhole
- ASSERT_FALSE(CheckConnectivityVia(public_addrs_[1],
- private_addrs_[0],
- sender_external_address));
- // Send traffic to other public IP, verify that it uses the same pinhole
- nr_transport_addr sender_external_address2;
- ASSERT_TRUE(CheckConnectivity(private_addrs_[0],
- public_addrs_[1],
- &sender_external_address2));
- ASSERT_FALSE(nr_transport_addr_cmp(&sender_external_address,
- &sender_external_address2,
- NR_TRANSPORT_ADDR_CMP_MODE_ALL))
- << "addr1: " << sender_external_address.as_string << " addr2: "
- << sender_external_address2.as_string;
- // Verify that the other public IP can now use the pinhole
- ASSERT_TRUE(CheckConnectivityVia(public_addrs_[1],
- private_addrs_[0],
- sender_external_address2));
- }
- TEST_F(TestNrSocketTest, PortDependentMappingFullCone) {
- RefPtr<TestNat> nat(CreatePrivateAddrs(1));
- nat->filtering_type_ = TestNat::ENDPOINT_INDEPENDENT;
- nat->mapping_type_ = TestNat::PORT_DEPENDENT;
- CreatePublicAddrs(2);
- nr_transport_addr sender_external_address0;
- // Open pinhole to public IP 0
- ASSERT_TRUE(CheckConnectivity(private_addrs_[0],
- public_addrs_[0],
- &sender_external_address0));
- // Verify that return traffic works
- ASSERT_TRUE(CheckConnectivityVia(public_addrs_[0],
- private_addrs_[0],
- sender_external_address0));
- // Verify that other public IP can use the pinhole
- ASSERT_TRUE(CheckConnectivityVia(public_addrs_[1],
- private_addrs_[0],
- sender_external_address0));
- // Send traffic to other public IP, verify that it uses a different pinhole
- nr_transport_addr sender_external_address1;
- ASSERT_TRUE(CheckConnectivity(private_addrs_[0],
- public_addrs_[1],
- &sender_external_address1));
- ASSERT_TRUE(nr_transport_addr_cmp(&sender_external_address0,
- &sender_external_address1,
- NR_TRANSPORT_ADDR_CMP_MODE_ALL))
- << "addr1: " << sender_external_address0.as_string << " addr2: "
- << sender_external_address1.as_string;
- // Verify that return traffic works
- ASSERT_TRUE(CheckConnectivityVia(public_addrs_[1],
- private_addrs_[0],
- sender_external_address1));
- // Verify that other public IP can use the original pinhole
- ASSERT_TRUE(CheckConnectivityVia(public_addrs_[0],
- private_addrs_[0],
- sender_external_address1));
- }
- TEST_F(TestNrSocketTest, Symmetric) {
- RefPtr<TestNat> nat(CreatePrivateAddrs(1));
- nat->filtering_type_ = TestNat::PORT_DEPENDENT;
- nat->mapping_type_ = TestNat::PORT_DEPENDENT;
- CreatePublicAddrs(2);
- nr_transport_addr sender_external_address;
- // Open pinhole to public IP 0
- ASSERT_TRUE(CheckConnectivity(private_addrs_[0],
- public_addrs_[0],
- &sender_external_address));
- // Verify that return traffic works
- ASSERT_TRUE(CheckConnectivityVia(public_addrs_[0],
- private_addrs_[0],
- sender_external_address));
- // Verify that other public IP cannot use the pinhole
- ASSERT_FALSE(CheckConnectivityVia(public_addrs_[1],
- private_addrs_[0],
- sender_external_address));
- // Send traffic to other public IP, verify that it uses a new pinhole
- nr_transport_addr sender_external_address2;
- ASSERT_TRUE(CheckConnectivity(private_addrs_[0],
- public_addrs_[1],
- &sender_external_address2));
- ASSERT_TRUE(nr_transport_addr_cmp(&sender_external_address,
- &sender_external_address2,
- NR_TRANSPORT_ADDR_CMP_MODE_ALL));
- // Verify that the other public IP can use the new pinhole
- ASSERT_TRUE(CheckConnectivityVia(public_addrs_[1],
- private_addrs_[0],
- sender_external_address2));
- }
- TEST_F(TestNrSocketTest, BlockUdp) {
- RefPtr<TestNat> nat(CreatePrivateAddrs(2));
- nat->block_udp_ = true;
- CreatePublicAddrs(1);
- nr_transport_addr sender_external_address;
- ASSERT_FALSE(CheckConnectivity(private_addrs_[0],
- public_addrs_[0],
- &sender_external_address));
- // Make sure UDP behind the NAT still works
- ASSERT_TRUE(CheckConnectivity(private_addrs_[0],
- private_addrs_[1]));
- ASSERT_TRUE(CheckConnectivity(private_addrs_[1],
- private_addrs_[0]));
- }
- TEST_F(TestNrSocketTest, DenyHairpinning) {
- RefPtr<TestNat> nat(CreatePrivateAddrs(2));
- nat->filtering_type_ = TestNat::ENDPOINT_INDEPENDENT;
- nat->mapping_type_ = TestNat::ENDPOINT_INDEPENDENT;
- CreatePublicAddrs(1);
- nr_transport_addr sender_external_address;
- // Open pinhole to public IP 0
- ASSERT_TRUE(CheckConnectivity(private_addrs_[0],
- public_addrs_[0],
- &sender_external_address));
- // Verify that hairpinning is disallowed
- ASSERT_FALSE(CheckConnectivityVia(private_addrs_[1],
- private_addrs_[0],
- sender_external_address));
- }
- TEST_F(TestNrSocketTest, AllowHairpinning) {
- RefPtr<TestNat> nat(CreatePrivateAddrs(2));
- nat->filtering_type_ = TestNat::ENDPOINT_INDEPENDENT;
- nat->mapping_type_ = TestNat::ENDPOINT_INDEPENDENT;
- nat->mapping_timeout_ = 30000;
- nat->allow_hairpinning_ = true;
- CreatePublicAddrs(1);
- nr_transport_addr sender_external_address;
- // Open pinhole to public IP 0, obtain external address
- ASSERT_TRUE(CheckConnectivity(private_addrs_[0],
- public_addrs_[0],
- &sender_external_address));
- // Verify that hairpinning is allowed
- ASSERT_TRUE(CheckConnectivityVia(private_addrs_[1],
- private_addrs_[0],
- sender_external_address));
- }
- TEST_F(TestNrSocketTest, FullConeTimeout) {
- RefPtr<TestNat> nat(CreatePrivateAddrs(1));
- nat->filtering_type_ = TestNat::ENDPOINT_INDEPENDENT;
- nat->mapping_type_ = TestNat::ENDPOINT_INDEPENDENT;
- nat->mapping_timeout_ = 200;
- CreatePublicAddrs(2);
- nr_transport_addr sender_external_address;
- // Open pinhole to public IP 0
- ASSERT_TRUE(CheckConnectivity(private_addrs_[0],
- public_addrs_[0],
- &sender_external_address));
- // Verify that return traffic works
- ASSERT_TRUE(CheckConnectivityVia(public_addrs_[0],
- private_addrs_[0],
- sender_external_address));
- PR_Sleep(201);
- // Verify that return traffic does not work
- ASSERT_FALSE(CheckConnectivityVia(public_addrs_[0],
- private_addrs_[0],
- sender_external_address));
- }
- TEST_F(TestNrSocketTest, PublicConnectivityTcp)
- {
- CreatePublicAddrs(2, "127.0.0.1", IPPROTO_TCP);
- ASSERT_TRUE(CheckTcpConnectivity(public_addrs_[0], public_addrs_[1]));
- }
- TEST_F(TestNrSocketTest, PrivateConnectivityTcp) {
- RefPtr<TestNat> nat(CreatePrivateAddrs(2, "127.0.0.1", IPPROTO_TCP));
- nat->filtering_type_ = TestNat::ENDPOINT_INDEPENDENT;
- nat->mapping_type_ = TestNat::ENDPOINT_INDEPENDENT;
- ASSERT_TRUE(CheckTcpConnectivity(private_addrs_[0], private_addrs_[1]));
- }
- TEST_F(TestNrSocketTest, PrivateToPublicConnectivityTcp)
- {
- RefPtr<TestNat> nat(CreatePrivateAddrs(1, "127.0.0.1", IPPROTO_TCP));
- nat->filtering_type_ = TestNat::ENDPOINT_INDEPENDENT;
- nat->mapping_type_ = TestNat::ENDPOINT_INDEPENDENT;
- CreatePublicAddrs(1, "127.0.0.1", IPPROTO_TCP);
- ASSERT_TRUE(CheckTcpConnectivity(private_addrs_[0], public_addrs_[0]));
- }
- TEST_F(TestNrSocketTest, NoConnectivityBetweenSubnetsTcp)
- {
- RefPtr<TestNat> nat1(CreatePrivateAddrs(1, "127.0.0.1", IPPROTO_TCP));
- nat1->filtering_type_ = TestNat::ENDPOINT_INDEPENDENT;
- nat1->mapping_type_ = TestNat::ENDPOINT_INDEPENDENT;
- RefPtr<TestNat> nat2(CreatePrivateAddrs(1, "127.0.0.1", IPPROTO_TCP));
- nat2->filtering_type_ = TestNat::ENDPOINT_INDEPENDENT;
- nat2->mapping_type_ = TestNat::ENDPOINT_INDEPENDENT;
- ASSERT_FALSE(CheckTcpConnectivity(private_addrs_[0], private_addrs_[1]));
- }
- TEST_F(TestNrSocketTest, NoConnectivityPublicToPrivateTcp)
- {
- RefPtr<TestNat> nat(CreatePrivateAddrs(1, "127.0.0.1", IPPROTO_TCP));
- nat->filtering_type_ = TestNat::ENDPOINT_INDEPENDENT;
- nat->mapping_type_ = TestNat::ENDPOINT_INDEPENDENT;
- CreatePublicAddrs(1, "127.0.0.1", IPPROTO_TCP);
- ASSERT_FALSE(CheckTcpConnectivity(public_addrs_[0], private_addrs_[0]));
- }
|