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
merge(UniquePtr<MediaPacket> a,UniquePtr<MediaPacket> b)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:
DummySocket()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
create(nr_transport_addr * addr)62 virtual int create(nr_transport_addr* addr) override { return 0; }
63
sendto(const void * msg,size_t len,int flags,const nr_transport_addr * to)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
recvfrom(void * buf,size_t maxlen,size_t * len,int flags,nr_transport_addr * from)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
getaddr(nr_transport_addr * addrp)76 virtual int getaddr(nr_transport_addr* addrp) override {
77 MOZ_CRASH();
78 return 0;
79 }
80
close()81 virtual void close() override {}
82
connect(const nr_transport_addr * addr)83 virtual int connect(const nr_transport_addr* addr) override {
84 nr_transport_addr_copy(&connect_addr_, addr);
85 return 0;
86 }
87
listen(int backlog)88 virtual int listen(int backlog) override { return 0; }
89
accept(nr_transport_addr * addrp,nr_socket ** sockp)90 virtual int accept(nr_transport_addr* addrp, nr_socket** sockp) override {
91 return 0;
92 }
93
write(const void * msg,size_t len,size_t * written)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
read(void * buf,size_t maxlen,size_t * len)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.
async_wait(int how,NR_async_cb cb,void * cb_arg,char * function,int line)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
cancel(int how)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.
CheckWriteBuffer(const uint8_t * data,size_t len)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
ClearWriteBuffer()160 void ClearWriteBuffer() { write_buffer_.reset(); }
161
SetWritable(size_t val)162 void SetWritable(size_t val) { writable_ = val; }
163
FireWritableCb()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
SetReadBuffer(const uint8_t * data,size_t len)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
ClearReadBuffer()180 void ClearReadBuffer() { read_buffer_.reset(); }
181
SetReadable(size_t val)182 void SetReadable(size_t val) { readable_ = val; }
183
get_nr_socket()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
get_connect_addr()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
218