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