buffered_stun_socket_unittest.cpp (7228B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 // Original author: ekr@rtfm.com 8 9 extern "C" { 10 #include "nr_api.h" 11 #include "nr_socket.h" 12 #include "nr_socket_buffered_stun.h" 13 #include "transport_addr.h" 14 } 15 16 #include "dummysocket.h" 17 #include "nr_socket_prsock.h" 18 #include "stun_msg.h" 19 20 #define GTEST_HAS_RTTI 0 21 #include "gtest/gtest.h" 22 #include "gtest_utils.h" 23 24 using namespace mozilla; 25 26 static uint8_t kStunMessage[] = {0x00, 0x01, 0x00, 0x08, 0x21, 0x12, 0xa4, 27 0x42, 0x9b, 0x90, 0xbe, 0x2c, 0xae, 0x1a, 28 0x0c, 0xa8, 0xa0, 0xd6, 0x8b, 0x08, 0x80, 29 0x28, 0x00, 0x04, 0xdb, 0x35, 0x5f, 0xaa}; 30 static size_t kStunMessageLen = sizeof(kStunMessage); 31 32 class BufferedStunSocketTest : public MtransportTest { 33 public: 34 BufferedStunSocketTest() : dummy_(nullptr), test_socket_(nullptr) {} 35 36 ~BufferedStunSocketTest() { nr_socket_destroy(&test_socket_); } 37 38 void SetUp() override { 39 MtransportTest::SetUp(); 40 41 RefPtr<DummySocket> dummy(new DummySocket()); 42 43 int r = 44 nr_socket_buffered_stun_create(dummy->get_nr_socket(), kStunMessageLen, 45 TURN_TCP_FRAMING, &test_socket_); 46 ASSERT_EQ(0, r); 47 dummy_ = std::move(dummy); // Now owned by test_socket_. 48 49 r = nr_str_port_to_transport_addr((char*)"192.0.2.133", 3333, IPPROTO_TCP, 50 &remote_addr_); 51 ASSERT_EQ(0, r); 52 53 r = nr_socket_connect(test_socket_, &remote_addr_); 54 ASSERT_EQ(0, r); 55 } 56 57 nr_socket* socket() { return test_socket_; } 58 59 protected: 60 RefPtr<DummySocket> dummy_; 61 nr_socket* test_socket_; 62 nr_transport_addr remote_addr_; 63 }; 64 65 TEST_F(BufferedStunSocketTest, TestCreate) {} 66 67 TEST_F(BufferedStunSocketTest, TestSendTo) { 68 int r = nr_socket_sendto(test_socket_, kStunMessage, kStunMessageLen, 0, 69 &remote_addr_); 70 ASSERT_EQ(0, r); 71 72 dummy_->CheckWriteBuffer(kStunMessage, kStunMessageLen); 73 } 74 75 TEST_F(BufferedStunSocketTest, TestSendToBuffered) { 76 dummy_->SetWritable(0); 77 78 int r = nr_socket_sendto(test_socket_, kStunMessage, kStunMessageLen, 0, 79 &remote_addr_); 80 ASSERT_EQ(0, r); 81 82 dummy_->CheckWriteBuffer(nullptr, 0); 83 84 dummy_->SetWritable(kStunMessageLen); 85 dummy_->FireWritableCb(); 86 dummy_->CheckWriteBuffer(kStunMessage, kStunMessageLen); 87 } 88 89 TEST_F(BufferedStunSocketTest, TestSendFullThenDrain) { 90 dummy_->SetWritable(0); 91 92 for (;;) { 93 int r = nr_socket_sendto(test_socket_, kStunMessage, kStunMessageLen, 0, 94 &remote_addr_); 95 if (r == R_WOULDBLOCK) break; 96 97 ASSERT_EQ(0, r); 98 } 99 100 // Nothing was written. 101 dummy_->CheckWriteBuffer(nullptr, 0); 102 103 // Now flush. 104 dummy_->SetWritable(kStunMessageLen); 105 dummy_->FireWritableCb(); 106 dummy_->ClearWriteBuffer(); 107 108 // Verify we can write something. 109 int r = nr_socket_sendto(test_socket_, kStunMessage, kStunMessageLen, 0, 110 &remote_addr_); 111 ASSERT_EQ(0, r); 112 113 // And that it appears. 114 dummy_->CheckWriteBuffer(kStunMessage, kStunMessageLen); 115 } 116 117 TEST_F(BufferedStunSocketTest, TestSendToPartialBuffered) { 118 dummy_->SetWritable(10); 119 120 int r = nr_socket_sendto(test_socket_, kStunMessage, kStunMessageLen, 0, 121 &remote_addr_); 122 ASSERT_EQ(0, r); 123 124 dummy_->CheckWriteBuffer(kStunMessage, 10); 125 dummy_->ClearWriteBuffer(); 126 127 dummy_->SetWritable(kStunMessageLen); 128 dummy_->FireWritableCb(); 129 dummy_->CheckWriteBuffer(kStunMessage + 10, kStunMessageLen - 10); 130 } 131 132 TEST_F(BufferedStunSocketTest, TestSendToReject) { 133 dummy_->SetWritable(0); 134 135 int r = nr_socket_sendto(test_socket_, kStunMessage, kStunMessageLen, 0, 136 &remote_addr_); 137 ASSERT_EQ(0, r); 138 139 dummy_->CheckWriteBuffer(nullptr, 0); 140 141 r = nr_socket_sendto(test_socket_, kStunMessage, kStunMessageLen, 0, 142 &remote_addr_); 143 ASSERT_EQ(R_WOULDBLOCK, r); 144 145 dummy_->CheckWriteBuffer(nullptr, 0); 146 } 147 148 TEST_F(BufferedStunSocketTest, TestSendToWrongAddr) { 149 nr_transport_addr addr; 150 151 int r = nr_str_port_to_transport_addr((char*)"192.0.2.134", 3333, IPPROTO_TCP, 152 &addr); 153 ASSERT_EQ(0, r); 154 155 r = nr_socket_sendto(test_socket_, kStunMessage, kStunMessageLen, 0, &addr); 156 ASSERT_EQ(R_BAD_DATA, r); 157 } 158 159 TEST_F(BufferedStunSocketTest, TestReceiveRecvFrom) { 160 dummy_->SetReadBuffer(kStunMessage, kStunMessageLen); 161 162 unsigned char tmp[2048]; 163 size_t len; 164 nr_transport_addr addr; 165 166 int r = nr_socket_recvfrom(test_socket_, tmp, sizeof(tmp), &len, 0, &addr); 167 ASSERT_EQ(0, r); 168 ASSERT_EQ(kStunMessageLen, len); 169 ASSERT_EQ(0, memcmp(kStunMessage, tmp, kStunMessageLen)); 170 ASSERT_EQ(0, nr_transport_addr_cmp(&addr, &remote_addr_, 171 NR_TRANSPORT_ADDR_CMP_MODE_ALL)); 172 } 173 174 TEST_F(BufferedStunSocketTest, TestReceiveRecvFromPartial) { 175 dummy_->SetReadBuffer(kStunMessage, 15); 176 177 unsigned char tmp[2048]; 178 size_t len; 179 nr_transport_addr addr; 180 181 int r = nr_socket_recvfrom(test_socket_, tmp, sizeof(tmp), &len, 0, &addr); 182 ASSERT_EQ(R_WOULDBLOCK, r); 183 184 dummy_->SetReadBuffer(kStunMessage + 15, kStunMessageLen - 15); 185 186 r = nr_socket_recvfrom(test_socket_, tmp, sizeof(tmp), &len, 0, &addr); 187 ASSERT_EQ(0, r); 188 ASSERT_EQ(kStunMessageLen, len); 189 ASSERT_EQ(0, memcmp(kStunMessage, tmp, kStunMessageLen)); 190 ASSERT_EQ(0, nr_transport_addr_cmp(&addr, &remote_addr_, 191 NR_TRANSPORT_ADDR_CMP_MODE_ALL)); 192 193 r = nr_socket_recvfrom(test_socket_, tmp, sizeof(tmp), &len, 0, &addr); 194 ASSERT_EQ(R_WOULDBLOCK, r); 195 } 196 197 TEST_F(BufferedStunSocketTest, TestReceiveRecvFromGarbage) { 198 uint8_t garbage[50]; 199 memset(garbage, 0xff, sizeof(garbage)); 200 201 dummy_->SetReadBuffer(garbage, sizeof(garbage)); 202 203 unsigned char tmp[2048]; 204 size_t len; 205 nr_transport_addr addr; 206 int r = nr_socket_recvfrom(test_socket_, tmp, sizeof(tmp), &len, 0, &addr); 207 ASSERT_EQ(R_BAD_DATA, r); 208 209 r = nr_socket_recvfrom(test_socket_, tmp, sizeof(tmp), &len, 0, &addr); 210 ASSERT_EQ(R_FAILED, r); 211 } 212 213 TEST_F(BufferedStunSocketTest, TestReceiveRecvFromTooShort) { 214 dummy_->SetReadBuffer(kStunMessage, kStunMessageLen); 215 216 unsigned char tmp[2048]; 217 size_t len; 218 nr_transport_addr addr; 219 220 int r = nr_socket_recvfrom(test_socket_, tmp, kStunMessageLen - 1, &len, 0, 221 &addr); 222 ASSERT_EQ(R_BAD_ARGS, r); 223 } 224 225 TEST_F(BufferedStunSocketTest, TestReceiveRecvFromReallyLong) { 226 uint8_t garbage[4096]; 227 memset(garbage, 0xff, sizeof(garbage)); 228 memcpy(garbage, kStunMessage, kStunMessageLen); 229 nr_stun_message_header* hdr = 230 reinterpret_cast<nr_stun_message_header*>(garbage); 231 hdr->length = htons(3000); 232 233 dummy_->SetReadBuffer(garbage, sizeof(garbage)); 234 235 unsigned char tmp[4096]; 236 size_t len; 237 nr_transport_addr addr; 238 239 int r = nr_socket_recvfrom(test_socket_, tmp, kStunMessageLen - 1, &len, 0, 240 &addr); 241 ASSERT_EQ(R_BAD_DATA, r); 242 }