dummysocket.h (5384B)
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 authors: ekr@rtfm.com; ryan@tokbox.com 8 9 #ifndef MTRANSPORT_DUMMY_SOCKET_H_ 10 #define MTRANSPORT_DUMMY_SOCKET_H_ 11 12 #include "nr_socket_prsock.h" 13 14 extern "C" { 15 #include "transport_addr.h" 16 } 17 18 #include "mediapacket.h" 19 #include "mozilla/UniquePtr.h" 20 21 #define GTEST_HAS_RTTI 0 22 #include "gtest/gtest.h" 23 #include "gtest_utils.h" 24 25 namespace mozilla { 26 27 static UniquePtr<MediaPacket> merge(UniquePtr<MediaPacket> a, 28 UniquePtr<MediaPacket> b) { 29 if (a && a->len() && b && b->len()) { 30 UniquePtr<uint8_t[]> data(new uint8_t[a->len() + b->len()]); 31 memcpy(data.get(), a->data(), a->len()); 32 memcpy(data.get() + a->len(), b->data(), b->len()); 33 34 UniquePtr<MediaPacket> merged(new MediaPacket); 35 merged->Take(std::move(data), a->len() + b->len()); 36 return merged; 37 } 38 39 if (a && a->len()) { 40 return a; 41 } 42 43 if (b && b->len()) { 44 return b; 45 } 46 47 return nullptr; 48 } 49 50 class DummySocket : public NrSocketBase { 51 public: 52 DummySocket() 53 : writable_(UINT_MAX), 54 write_buffer_(nullptr), 55 readable_(UINT_MAX), 56 read_buffer_(nullptr), 57 cb_(nullptr), 58 cb_arg_(nullptr), 59 self_(nullptr) {} 60 61 // the nr_socket APIs 62 virtual int create(nr_transport_addr* addr) override { return 0; } 63 64 virtual int sendto(const void* msg, size_t len, int flags, 65 const nr_transport_addr* to) override { 66 MOZ_CRASH(); 67 return 0; 68 } 69 70 virtual int recvfrom(void* buf, size_t maxlen, size_t* len, int flags, 71 nr_transport_addr* from) override { 72 MOZ_CRASH(); 73 return 0; 74 } 75 76 virtual int getaddr(nr_transport_addr* addrp) override { 77 MOZ_CRASH(); 78 return 0; 79 } 80 81 virtual void close() override {} 82 83 virtual int connect(const nr_transport_addr* addr) override { 84 nr_transport_addr_copy(&connect_addr_, addr); 85 return 0; 86 } 87 88 virtual int listen(int backlog) override { return 0; } 89 90 virtual int accept(nr_transport_addr* addrp, nr_socket** sockp) override { 91 return 0; 92 } 93 94 virtual int write(const void* msg, size_t len, size_t* written) override { 95 size_t to_write = std::min(len, writable_); 96 97 if (to_write) { 98 UniquePtr<MediaPacket> msgbuf(new MediaPacket); 99 msgbuf->Copy(static_cast<const uint8_t*>(msg), to_write); 100 write_buffer_ = merge(std::move(write_buffer_), std::move(msgbuf)); 101 } 102 103 *written = to_write; 104 105 return 0; 106 } 107 108 virtual int read(void* buf, size_t maxlen, size_t* len) override { 109 if (!read_buffer_.get()) { 110 return R_WOULDBLOCK; 111 } 112 113 size_t to_read = std::min(read_buffer_->len(), std::min(maxlen, readable_)); 114 115 memcpy(buf, read_buffer_->data(), to_read); 116 *len = to_read; 117 118 if (to_read < read_buffer_->len()) { 119 MediaPacket* newPacket = new MediaPacket; 120 newPacket->Copy(read_buffer_->data() + to_read, 121 read_buffer_->len() - to_read); 122 read_buffer_.reset(newPacket); 123 } else { 124 read_buffer_.reset(); 125 } 126 127 return 0; 128 } 129 130 // Implementations of the async_event APIs. 131 // These are no-ops because we handle scheduling manually 132 // for test purposes. 133 virtual int async_wait(int how, NR_async_cb cb, void* cb_arg, char* function, 134 int line) override { 135 EXPECT_EQ(nullptr, cb_); 136 cb_ = cb; 137 cb_arg_ = cb_arg; 138 139 return 0; 140 } 141 142 virtual int cancel(int how) override { 143 cb_ = nullptr; 144 cb_arg_ = nullptr; 145 146 return 0; 147 } 148 149 // Read/Manipulate the current state. 150 void CheckWriteBuffer(const uint8_t* data, size_t len) { 151 if (!len) { 152 EXPECT_EQ(nullptr, write_buffer_.get()); 153 } else { 154 EXPECT_NE(nullptr, write_buffer_.get()); 155 ASSERT_EQ(len, write_buffer_->len()); 156 ASSERT_EQ(0, memcmp(data, write_buffer_->data(), len)); 157 } 158 } 159 160 void ClearWriteBuffer() { write_buffer_.reset(); } 161 162 void SetWritable(size_t val) { writable_ = val; } 163 164 void FireWritableCb() { 165 NR_async_cb cb = cb_; 166 void* cb_arg = cb_arg_; 167 168 cb_ = nullptr; 169 cb_arg_ = nullptr; 170 171 cb(this, NR_ASYNC_WAIT_WRITE, cb_arg); 172 } 173 174 void SetReadBuffer(const uint8_t* data, size_t len) { 175 EXPECT_EQ(nullptr, write_buffer_.get()); 176 read_buffer_.reset(new MediaPacket); 177 read_buffer_->Copy(data, len); 178 } 179 180 void ClearReadBuffer() { read_buffer_.reset(); } 181 182 void SetReadable(size_t val) { readable_ = val; } 183 184 nr_socket* get_nr_socket() { 185 if (!self_) { 186 int r = nr_socket_create_int(this, vtbl(), &self_); 187 AddRef(); 188 if (r) return nullptr; 189 } 190 191 return self_; 192 } 193 194 nr_transport_addr* get_connect_addr() { return &connect_addr_; } 195 196 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DummySocket, override); 197 198 private: 199 ~DummySocket() = default; 200 201 DISALLOW_COPY_ASSIGN(DummySocket); 202 203 size_t writable_; // Amount we allow someone to write. 204 UniquePtr<MediaPacket> write_buffer_; 205 size_t readable_; // Amount we allow someone to read. 206 UniquePtr<MediaPacket> read_buffer_; 207 208 NR_async_cb cb_; 209 void* cb_arg_; 210 nr_socket* self_; 211 212 nr_transport_addr connect_addr_; 213 }; 214 215 } // namespace mozilla 216 217 #endif