Home | History | Annotate | Download | only in base
      1 /*
      2  * libjingle
      3  * Copyright 2004 Google Inc.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions are met:
      7  *
      8  *  1. Redistributions of source code must retain the above copyright notice,
      9  *     this list of conditions and the following disclaimer.
     10  *  2. Redistributions in binary form must reproduce the above copyright notice,
     11  *     this list of conditions and the following disclaimer in the documentation
     12  *     and/or other materials provided with the distribution.
     13  *  3. The name of the author may not be used to endorse or promote products
     14  *     derived from this software without specific prior written permission.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
     17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
     19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26  */
     27 
     28 #include <string>
     29 
     30 #include "talk/p2p/base/relayserver.h"
     31 #include "webrtc/base/gunit.h"
     32 #include "webrtc/base/helpers.h"
     33 #include "webrtc/base/logging.h"
     34 #include "webrtc/base/physicalsocketserver.h"
     35 #include "webrtc/base/socketaddress.h"
     36 #include "webrtc/base/ssladapter.h"
     37 #include "webrtc/base/testclient.h"
     38 #include "webrtc/base/thread.h"
     39 
     40 using rtc::SocketAddress;
     41 using namespace cricket;
     42 
     43 static const uint32 LIFETIME = 4;  // seconds
     44 static const SocketAddress server_int_addr("127.0.0.1", 5000);
     45 static const SocketAddress server_ext_addr("127.0.0.1", 5001);
     46 static const SocketAddress client1_addr("127.0.0.1", 6000 + (rand() % 1000));
     47 static const SocketAddress client2_addr("127.0.0.1", 7000 + (rand() % 1000));
     48 static const char* bad = "this is a completely nonsensical message whose only "
     49                          "purpose is to make the parser go 'ack'.  it doesn't "
     50                          "look anything like a normal stun message";
     51 static const char* msg1 = "spamspamspamspamspamspamspambakedbeansspam";
     52 static const char* msg2 = "Lobster Thermidor a Crevette with a mornay sauce...";
     53 
     54 class RelayServerTest : public testing::Test {
     55  public:
     56   static void SetUpTestCase() {
     57     rtc::InitializeSSL();
     58   }
     59 
     60   static void TearDownTestCase() {
     61     rtc::CleanupSSL();
     62   }
     63 
     64   RelayServerTest()
     65       : main_(rtc::Thread::Current()), ss_(main_->socketserver()),
     66         username_(rtc::CreateRandomString(12)),
     67         password_(rtc::CreateRandomString(12)) {
     68   }
     69  protected:
     70   virtual void SetUp() {
     71     server_.reset(new RelayServer(main_));
     72 
     73     server_->AddInternalSocket(
     74         rtc::AsyncUDPSocket::Create(ss_, server_int_addr));
     75     server_->AddExternalSocket(
     76         rtc::AsyncUDPSocket::Create(ss_, server_ext_addr));
     77 
     78     client1_.reset(new rtc::TestClient(
     79         rtc::AsyncUDPSocket::Create(ss_, client1_addr)));
     80     client2_.reset(new rtc::TestClient(
     81         rtc::AsyncUDPSocket::Create(ss_, client2_addr)));
     82   }
     83 
     84   void Allocate() {
     85     rtc::scoped_ptr<StunMessage> req(
     86         CreateStunMessage(STUN_ALLOCATE_REQUEST));
     87     AddUsernameAttr(req.get(), username_);
     88     AddLifetimeAttr(req.get(), LIFETIME);
     89     Send1(req.get());
     90     delete Receive1();
     91   }
     92   void Bind() {
     93     rtc::scoped_ptr<StunMessage> req(
     94         CreateStunMessage(STUN_BINDING_REQUEST));
     95     AddUsernameAttr(req.get(), username_);
     96     Send2(req.get());
     97     delete Receive1();
     98   }
     99 
    100   void Send1(const StunMessage* msg) {
    101     rtc::ByteBuffer buf;
    102     msg->Write(&buf);
    103     SendRaw1(buf.Data(), static_cast<int>(buf.Length()));
    104   }
    105   void Send2(const StunMessage* msg) {
    106     rtc::ByteBuffer buf;
    107     msg->Write(&buf);
    108     SendRaw2(buf.Data(), static_cast<int>(buf.Length()));
    109   }
    110   void SendRaw1(const char* data, int len) {
    111     return Send(client1_.get(), data, len, server_int_addr);
    112   }
    113   void SendRaw2(const char* data, int len) {
    114     return Send(client2_.get(), data, len, server_ext_addr);
    115   }
    116   void Send(rtc::TestClient* client, const char* data,
    117             int len, const SocketAddress& addr) {
    118     client->SendTo(data, len, addr);
    119   }
    120 
    121   StunMessage* Receive1() {
    122     return Receive(client1_.get());
    123   }
    124   StunMessage* Receive2() {
    125     return Receive(client2_.get());
    126   }
    127   std::string ReceiveRaw1() {
    128     return ReceiveRaw(client1_.get());
    129   }
    130   std::string ReceiveRaw2() {
    131     return ReceiveRaw(client2_.get());
    132   }
    133   StunMessage* Receive(rtc::TestClient* client) {
    134     StunMessage* msg = NULL;
    135     rtc::TestClient::Packet* packet = client->NextPacket();
    136     if (packet) {
    137       rtc::ByteBuffer buf(packet->buf, packet->size);
    138       msg = new RelayMessage();
    139       msg->Read(&buf);
    140       delete packet;
    141     }
    142     return msg;
    143   }
    144   std::string ReceiveRaw(rtc::TestClient* client) {
    145     std::string raw;
    146     rtc::TestClient::Packet* packet = client->NextPacket();
    147     if (packet) {
    148       raw = std::string(packet->buf, packet->size);
    149       delete packet;
    150     }
    151     return raw;
    152   }
    153 
    154   static StunMessage* CreateStunMessage(int type) {
    155     StunMessage* msg = new RelayMessage();
    156     msg->SetType(type);
    157     msg->SetTransactionID(
    158         rtc::CreateRandomString(kStunTransactionIdLength));
    159     return msg;
    160   }
    161   static void AddMagicCookieAttr(StunMessage* msg) {
    162     StunByteStringAttribute* attr =
    163         StunAttribute::CreateByteString(STUN_ATTR_MAGIC_COOKIE);
    164     attr->CopyBytes(TURN_MAGIC_COOKIE_VALUE, sizeof(TURN_MAGIC_COOKIE_VALUE));
    165     msg->AddAttribute(attr);
    166   }
    167   static void AddUsernameAttr(StunMessage* msg, const std::string& val) {
    168     StunByteStringAttribute* attr =
    169         StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
    170     attr->CopyBytes(val.c_str(), val.size());
    171     msg->AddAttribute(attr);
    172   }
    173   static void AddLifetimeAttr(StunMessage* msg, int val) {
    174     StunUInt32Attribute* attr =
    175         StunAttribute::CreateUInt32(STUN_ATTR_LIFETIME);
    176     attr->SetValue(val);
    177     msg->AddAttribute(attr);
    178   }
    179   static void AddDestinationAttr(StunMessage* msg, const SocketAddress& addr) {
    180     StunAddressAttribute* attr =
    181         StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS);
    182     attr->SetIP(addr.ipaddr());
    183     attr->SetPort(addr.port());
    184     msg->AddAttribute(attr);
    185   }
    186 
    187   rtc::Thread* main_;
    188   rtc::SocketServer* ss_;
    189   rtc::scoped_ptr<RelayServer> server_;
    190   rtc::scoped_ptr<rtc::TestClient> client1_;
    191   rtc::scoped_ptr<rtc::TestClient> client2_;
    192   std::string username_;
    193   std::string password_;
    194 };
    195 
    196 // Send a complete nonsense message and verify that it is eaten.
    197 TEST_F(RelayServerTest, TestBadRequest) {
    198   rtc::scoped_ptr<StunMessage> res;
    199 
    200   SendRaw1(bad, static_cast<int>(strlen(bad)));
    201   res.reset(Receive1());
    202 
    203   ASSERT_TRUE(!res);
    204 }
    205 
    206 // Send an allocate request without a username and verify it is rejected.
    207 TEST_F(RelayServerTest, TestAllocateNoUsername) {
    208   rtc::scoped_ptr<StunMessage> req(
    209       CreateStunMessage(STUN_ALLOCATE_REQUEST)), res;
    210 
    211   Send1(req.get());
    212   res.reset(Receive1());
    213 
    214   ASSERT_TRUE(res);
    215   EXPECT_EQ(STUN_ALLOCATE_ERROR_RESPONSE, res->type());
    216   EXPECT_EQ(req->transaction_id(), res->transaction_id());
    217 
    218   const StunErrorCodeAttribute* err = res->GetErrorCode();
    219   ASSERT_TRUE(err != NULL);
    220   EXPECT_EQ(4, err->eclass());
    221   EXPECT_EQ(32, err->number());
    222   EXPECT_EQ("Missing Username", err->reason());
    223 }
    224 
    225 // Send a binding request and verify that it is rejected.
    226 TEST_F(RelayServerTest, TestBindingRequest) {
    227   rtc::scoped_ptr<StunMessage> req(
    228       CreateStunMessage(STUN_BINDING_REQUEST)), res;
    229   AddUsernameAttr(req.get(), username_);
    230 
    231   Send1(req.get());
    232   res.reset(Receive1());
    233 
    234   ASSERT_TRUE(res);
    235   EXPECT_EQ(STUN_BINDING_ERROR_RESPONSE, res->type());
    236   EXPECT_EQ(req->transaction_id(), res->transaction_id());
    237 
    238   const StunErrorCodeAttribute* err = res->GetErrorCode();
    239   ASSERT_TRUE(err != NULL);
    240   EXPECT_EQ(6, err->eclass());
    241   EXPECT_EQ(0, err->number());
    242   EXPECT_EQ("Operation Not Supported", err->reason());
    243 }
    244 
    245 // Send an allocate request and verify that it is accepted.
    246 TEST_F(RelayServerTest, TestAllocate) {
    247   rtc::scoped_ptr<StunMessage> req(
    248       CreateStunMessage(STUN_ALLOCATE_REQUEST)), res;
    249   AddUsernameAttr(req.get(), username_);
    250   AddLifetimeAttr(req.get(), LIFETIME);
    251 
    252   Send1(req.get());
    253   res.reset(Receive1());
    254 
    255   ASSERT_TRUE(res);
    256   EXPECT_EQ(STUN_ALLOCATE_RESPONSE, res->type());
    257   EXPECT_EQ(req->transaction_id(), res->transaction_id());
    258 
    259   const StunAddressAttribute* mapped_addr =
    260       res->GetAddress(STUN_ATTR_MAPPED_ADDRESS);
    261   ASSERT_TRUE(mapped_addr != NULL);
    262   EXPECT_EQ(1, mapped_addr->family());
    263   EXPECT_EQ(server_ext_addr.port(), mapped_addr->port());
    264   EXPECT_EQ(server_ext_addr.ipaddr(), mapped_addr->ipaddr());
    265 
    266   const StunUInt32Attribute* res_lifetime_attr =
    267       res->GetUInt32(STUN_ATTR_LIFETIME);
    268   ASSERT_TRUE(res_lifetime_attr != NULL);
    269   EXPECT_EQ(LIFETIME, res_lifetime_attr->value());
    270 }
    271 
    272 // Send a second allocate request and verify that it is also accepted, though
    273 // the lifetime should be ignored.
    274 TEST_F(RelayServerTest, TestReallocate) {
    275   Allocate();
    276 
    277   rtc::scoped_ptr<StunMessage> req(
    278       CreateStunMessage(STUN_ALLOCATE_REQUEST)), res;
    279   AddMagicCookieAttr(req.get());
    280   AddUsernameAttr(req.get(), username_);
    281 
    282   Send1(req.get());
    283   res.reset(Receive1());
    284 
    285   ASSERT_TRUE(res);
    286   EXPECT_EQ(STUN_ALLOCATE_RESPONSE, res->type());
    287   EXPECT_EQ(req->transaction_id(), res->transaction_id());
    288 
    289   const StunAddressAttribute* mapped_addr =
    290       res->GetAddress(STUN_ATTR_MAPPED_ADDRESS);
    291   ASSERT_TRUE(mapped_addr != NULL);
    292   EXPECT_EQ(1, mapped_addr->family());
    293   EXPECT_EQ(server_ext_addr.port(), mapped_addr->port());
    294   EXPECT_EQ(server_ext_addr.ipaddr(), mapped_addr->ipaddr());
    295 
    296   const StunUInt32Attribute* lifetime_attr =
    297       res->GetUInt32(STUN_ATTR_LIFETIME);
    298   ASSERT_TRUE(lifetime_attr != NULL);
    299   EXPECT_EQ(LIFETIME, lifetime_attr->value());
    300 }
    301 
    302 // Send a request from another client and see that it arrives at the first
    303 // client in the binding.
    304 TEST_F(RelayServerTest, TestRemoteBind) {
    305   Allocate();
    306 
    307   rtc::scoped_ptr<StunMessage> req(
    308       CreateStunMessage(STUN_BINDING_REQUEST)), res;
    309   AddUsernameAttr(req.get(), username_);
    310 
    311   Send2(req.get());
    312   res.reset(Receive1());
    313 
    314   ASSERT_TRUE(res);
    315   EXPECT_EQ(STUN_DATA_INDICATION, res->type());
    316 
    317   const StunByteStringAttribute* recv_data =
    318       res->GetByteString(STUN_ATTR_DATA);
    319   ASSERT_TRUE(recv_data != NULL);
    320 
    321   rtc::ByteBuffer buf(recv_data->bytes(), recv_data->length());
    322   rtc::scoped_ptr<StunMessage> res2(new StunMessage());
    323   EXPECT_TRUE(res2->Read(&buf));
    324   EXPECT_EQ(STUN_BINDING_REQUEST, res2->type());
    325   EXPECT_EQ(req->transaction_id(), res2->transaction_id());
    326 
    327   const StunAddressAttribute* src_addr =
    328       res->GetAddress(STUN_ATTR_SOURCE_ADDRESS2);
    329   ASSERT_TRUE(src_addr != NULL);
    330   EXPECT_EQ(1, src_addr->family());
    331   EXPECT_EQ(client2_addr.ipaddr(), src_addr->ipaddr());
    332   EXPECT_EQ(client2_addr.port(), src_addr->port());
    333 
    334   EXPECT_TRUE(Receive2() == NULL);
    335 }
    336 
    337 // Send a complete nonsense message to the established connection and verify
    338 // that it is dropped by the server.
    339 TEST_F(RelayServerTest, TestRemoteBadRequest) {
    340   Allocate();
    341   Bind();
    342 
    343   SendRaw1(bad, static_cast<int>(strlen(bad)));
    344   EXPECT_TRUE(Receive1() == NULL);
    345   EXPECT_TRUE(Receive2() == NULL);
    346 }
    347 
    348 // Send a send request without a username and verify it is rejected.
    349 TEST_F(RelayServerTest, TestSendRequestMissingUsername) {
    350   Allocate();
    351   Bind();
    352 
    353   rtc::scoped_ptr<StunMessage> req(
    354       CreateStunMessage(STUN_SEND_REQUEST)), res;
    355   AddMagicCookieAttr(req.get());
    356 
    357   Send1(req.get());
    358   res.reset(Receive1());
    359 
    360   ASSERT_TRUE(res);
    361   EXPECT_EQ(STUN_SEND_ERROR_RESPONSE, res->type());
    362   EXPECT_EQ(req->transaction_id(), res->transaction_id());
    363 
    364   const StunErrorCodeAttribute* err = res->GetErrorCode();
    365   ASSERT_TRUE(err != NULL);
    366   EXPECT_EQ(4, err->eclass());
    367   EXPECT_EQ(32, err->number());
    368   EXPECT_EQ("Missing Username", err->reason());
    369 }
    370 
    371 // Send a send request with the wrong username and verify it is rejected.
    372 TEST_F(RelayServerTest, TestSendRequestBadUsername) {
    373   Allocate();
    374   Bind();
    375 
    376   rtc::scoped_ptr<StunMessage> req(
    377       CreateStunMessage(STUN_SEND_REQUEST)), res;
    378   AddMagicCookieAttr(req.get());
    379   AddUsernameAttr(req.get(), "foobarbizbaz");
    380 
    381   Send1(req.get());
    382   res.reset(Receive1());
    383 
    384   ASSERT_TRUE(res);
    385   EXPECT_EQ(STUN_SEND_ERROR_RESPONSE, res->type());
    386   EXPECT_EQ(req->transaction_id(), res->transaction_id());
    387 
    388   const StunErrorCodeAttribute* err = res->GetErrorCode();
    389   ASSERT_TRUE(err != NULL);
    390   EXPECT_EQ(4, err->eclass());
    391   EXPECT_EQ(30, err->number());
    392   EXPECT_EQ("Stale Credentials", err->reason());
    393 }
    394 
    395 // Send a send request without a destination address and verify that it is
    396 // rejected.
    397 TEST_F(RelayServerTest, TestSendRequestNoDestinationAddress) {
    398   Allocate();
    399   Bind();
    400 
    401   rtc::scoped_ptr<StunMessage> req(
    402       CreateStunMessage(STUN_SEND_REQUEST)), res;
    403   AddMagicCookieAttr(req.get());
    404   AddUsernameAttr(req.get(), username_);
    405 
    406   Send1(req.get());
    407   res.reset(Receive1());
    408 
    409   ASSERT_TRUE(res);
    410   EXPECT_EQ(STUN_SEND_ERROR_RESPONSE, res->type());
    411   EXPECT_EQ(req->transaction_id(), res->transaction_id());
    412 
    413   const StunErrorCodeAttribute* err = res->GetErrorCode();
    414   ASSERT_TRUE(err != NULL);
    415   EXPECT_EQ(4, err->eclass());
    416   EXPECT_EQ(0, err->number());
    417   EXPECT_EQ("Bad Request", err->reason());
    418 }
    419 
    420 // Send a send request without data and verify that it is rejected.
    421 TEST_F(RelayServerTest, TestSendRequestNoData) {
    422   Allocate();
    423   Bind();
    424 
    425   rtc::scoped_ptr<StunMessage> req(
    426       CreateStunMessage(STUN_SEND_REQUEST)), res;
    427   AddMagicCookieAttr(req.get());
    428   AddUsernameAttr(req.get(), username_);
    429   AddDestinationAttr(req.get(), client2_addr);
    430 
    431   Send1(req.get());
    432   res.reset(Receive1());
    433 
    434   ASSERT_TRUE(res);
    435   EXPECT_EQ(STUN_SEND_ERROR_RESPONSE, res->type());
    436   EXPECT_EQ(req->transaction_id(), res->transaction_id());
    437 
    438   const StunErrorCodeAttribute* err = res->GetErrorCode();
    439   ASSERT_TRUE(err != NULL);
    440   EXPECT_EQ(4, err->eclass());
    441   EXPECT_EQ(00, err->number());
    442   EXPECT_EQ("Bad Request", err->reason());
    443 }
    444 
    445 // Send a binding request after an allocate and verify that it is rejected.
    446 TEST_F(RelayServerTest, TestSendRequestWrongType) {
    447   Allocate();
    448   Bind();
    449 
    450   rtc::scoped_ptr<StunMessage> req(
    451       CreateStunMessage(STUN_BINDING_REQUEST)), res;
    452   AddMagicCookieAttr(req.get());
    453   AddUsernameAttr(req.get(), username_);
    454 
    455   Send1(req.get());
    456   res.reset(Receive1());
    457 
    458   ASSERT_TRUE(res);
    459   EXPECT_EQ(STUN_BINDING_ERROR_RESPONSE, res->type());
    460   EXPECT_EQ(req->transaction_id(), res->transaction_id());
    461 
    462   const StunErrorCodeAttribute* err = res->GetErrorCode();
    463   ASSERT_TRUE(err != NULL);
    464   EXPECT_EQ(6, err->eclass());
    465   EXPECT_EQ(0, err->number());
    466   EXPECT_EQ("Operation Not Supported", err->reason());
    467 }
    468 
    469 // Verify that we can send traffic back and forth between the clients after a
    470 // successful allocate and bind.
    471 TEST_F(RelayServerTest, TestSendRaw) {
    472   Allocate();
    473   Bind();
    474 
    475   for (int i = 0; i < 10; i++) {
    476     rtc::scoped_ptr<StunMessage> req(
    477         CreateStunMessage(STUN_SEND_REQUEST)), res;
    478     AddMagicCookieAttr(req.get());
    479     AddUsernameAttr(req.get(), username_);
    480     AddDestinationAttr(req.get(), client2_addr);
    481 
    482     StunByteStringAttribute* send_data =
    483         StunAttribute::CreateByteString(STUN_ATTR_DATA);
    484     send_data->CopyBytes(msg1);
    485     req->AddAttribute(send_data);
    486 
    487     Send1(req.get());
    488     EXPECT_EQ(msg1, ReceiveRaw2());
    489     SendRaw2(msg2, static_cast<int>(strlen(msg2)));
    490     res.reset(Receive1());
    491 
    492     ASSERT_TRUE(res);
    493     EXPECT_EQ(STUN_DATA_INDICATION, res->type());
    494 
    495     const StunAddressAttribute* src_addr =
    496         res->GetAddress(STUN_ATTR_SOURCE_ADDRESS2);
    497     ASSERT_TRUE(src_addr != NULL);
    498     EXPECT_EQ(1, src_addr->family());
    499     EXPECT_EQ(client2_addr.ipaddr(), src_addr->ipaddr());
    500     EXPECT_EQ(client2_addr.port(), src_addr->port());
    501 
    502     const StunByteStringAttribute* recv_data =
    503         res->GetByteString(STUN_ATTR_DATA);
    504     ASSERT_TRUE(recv_data != NULL);
    505     EXPECT_EQ(strlen(msg2), recv_data->length());
    506     EXPECT_EQ(0, memcmp(msg2, recv_data->bytes(), recv_data->length()));
    507   }
    508 }
    509 
    510 // Verify that a binding expires properly, and rejects send requests.
    511 TEST_F(RelayServerTest, TestExpiration) {
    512   Allocate();
    513   Bind();
    514 
    515   // Wait twice the lifetime to make sure the server has expired the binding.
    516   rtc::Thread::Current()->ProcessMessages((LIFETIME * 2) * 1000);
    517 
    518   rtc::scoped_ptr<StunMessage> req(
    519       CreateStunMessage(STUN_SEND_REQUEST)), res;
    520   AddMagicCookieAttr(req.get());
    521   AddUsernameAttr(req.get(), username_);
    522   AddDestinationAttr(req.get(), client2_addr);
    523 
    524   StunByteStringAttribute* data_attr =
    525       StunAttribute::CreateByteString(STUN_ATTR_DATA);
    526   data_attr->CopyBytes(msg1);
    527   req->AddAttribute(data_attr);
    528 
    529   Send1(req.get());
    530   res.reset(Receive1());
    531 
    532   ASSERT_TRUE(res.get() != NULL);
    533   EXPECT_EQ(STUN_SEND_ERROR_RESPONSE, res->type());
    534 
    535   const StunErrorCodeAttribute* err = res->GetErrorCode();
    536   ASSERT_TRUE(err != NULL);
    537   EXPECT_EQ(6, err->eclass());
    538   EXPECT_EQ(0, err->number());
    539   EXPECT_EQ("Operation Not Supported", err->reason());
    540 
    541   // Also verify that traffic from the external client is ignored.
    542   SendRaw2(msg2, static_cast<int>(strlen(msg2)));
    543   EXPECT_TRUE(ReceiveRaw1().empty());
    544 }
    545