Wed, 31 Dec 2014 06:55:46 +0100
Added tag TORBROWSER_REPLICA for changeset 6474c204b198
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include "TestCommon.h"
6 #include "TestHarness.h"
7 #include "nsIUDPSocket.h"
8 #include "nsISocketTransportService.h"
9 #include "nsISocketTransport.h"
10 #include "nsIOutputStream.h"
11 #include "nsIInputStream.h"
12 #include "nsINetAddr.h"
13 #include "mozilla/net/DNS.h"
14 #include "prerror.h"
16 #define REQUEST 0x68656c6f
17 #define RESPONSE 0x6f6c6568
19 #define EXPECT_SUCCESS(rv, ...) \
20 PR_BEGIN_MACRO \
21 if (NS_FAILED(rv)) { \
22 fail(__VA_ARGS__); \
23 return false; \
24 } \
25 PR_END_MACRO
28 #define EXPECT_FAILURE(rv, ...) \
29 PR_BEGIN_MACRO \
30 if (NS_SUCCEEDED(rv)) { \
31 fail(__VA_ARGS__); \
32 return false; \
33 } \
34 PR_END_MACRO
36 #define REQUIRE_EQUAL(a, b, ...) \
37 PR_BEGIN_MACRO \
38 if (a != b) { \
39 fail(__VA_ARGS__); \
40 return false; \
41 } \
42 PR_END_MACRO
44 enum TestPhase {
45 TEST_OUTPUT_STREAM,
46 TEST_SEND_API,
47 TEST_NONE
48 };
50 static TestPhase phase = TEST_NONE;
52 static bool CheckMessageContent(nsIUDPMessage *aMessage, uint32_t aExpectedContent)
53 {
54 nsCString data;
55 aMessage->GetData(data);
57 const char* buffer = data.get();
58 uint32_t len = data.Length();
60 FallibleTArray<uint8_t>& rawData = aMessage->GetDataAsTArray();
61 uint32_t rawLen = rawData.Length();
63 if (len != rawLen) {
64 fail("Raw data length(%d) do not matches String data length(%d).", rawLen, len);
65 return false;
66 }
68 for (uint32_t i = 0; i < len; i++) {
69 if (buffer[i] != rawData[i]) {
70 fail("Raw data(%s) do not matches String data(%s)", rawData.Elements() ,buffer);
71 return false;
72 }
73 }
75 uint32_t input = 0;
76 for (uint32_t i = 0; i < len; i++) {
77 input += buffer[i] << (8 * i);
78 }
80 if (len != sizeof(uint32_t) || input != aExpectedContent)
81 {
82 fail("Request 0x%x received, expected 0x%x", input, aExpectedContent);
83 return false;
84 } else {
85 passed("Request 0x%x received as expected", input);
86 return true;
87 }
88 }
90 /*
91 * UDPClientListener: listens for incomming UDP packets
92 */
93 class UDPClientListener : public nsIUDPSocketListener
94 {
95 public:
96 NS_DECL_THREADSAFE_ISUPPORTS
97 NS_DECL_NSIUDPSOCKETLISTENER
98 virtual ~UDPClientListener();
99 nsresult mResult;
100 };
102 NS_IMPL_ISUPPORTS(UDPClientListener, nsIUDPSocketListener)
104 UDPClientListener::~UDPClientListener()
105 {
106 }
108 NS_IMETHODIMP
109 UDPClientListener::OnPacketReceived(nsIUDPSocket* socket, nsIUDPMessage* message)
110 {
111 mResult = NS_OK;
113 uint16_t port;
114 nsCString ip;
115 nsCOMPtr<nsINetAddr> fromAddr;
116 message->GetFromAddr(getter_AddRefs(fromAddr));
117 fromAddr->GetPort(&port);
118 fromAddr->GetAddress(ip);
119 passed("Packet received on client from %s:%d", ip.get(), port);
121 if (TEST_SEND_API == phase && CheckMessageContent(message, REQUEST)) {
122 uint32_t count;
123 const uint32_t data = RESPONSE;
124 printf("*** Attempting to write response 0x%x to server by SendWithAddr...\n", RESPONSE);
125 mResult = socket->SendWithAddr(fromAddr, (const uint8_t*)&data,
126 sizeof(uint32_t), &count);
127 if (mResult == NS_OK && count == sizeof(uint32_t)) {
128 passed("Response written");
129 } else {
130 fail("Response written");
131 }
132 return NS_OK;
133 } else if (TEST_OUTPUT_STREAM != phase || !CheckMessageContent(message, RESPONSE)) {
134 mResult = NS_ERROR_FAILURE;
135 }
137 // Notify thread
138 QuitPumpingEvents();
139 return NS_OK;
140 }
142 NS_IMETHODIMP
143 UDPClientListener::OnStopListening(nsIUDPSocket*, nsresult)
144 {
145 QuitPumpingEvents();
146 return NS_OK;
147 }
149 /*
150 * UDPServerListener: listens for incomming UDP packets
151 */
152 class UDPServerListener : public nsIUDPSocketListener
153 {
154 public:
155 NS_DECL_THREADSAFE_ISUPPORTS
156 NS_DECL_NSIUDPSOCKETLISTENER
158 virtual ~UDPServerListener();
160 nsresult mResult;
161 };
163 NS_IMPL_ISUPPORTS(UDPServerListener, nsIUDPSocketListener)
165 UDPServerListener::~UDPServerListener()
166 {
167 }
169 NS_IMETHODIMP
170 UDPServerListener::OnPacketReceived(nsIUDPSocket* socket, nsIUDPMessage* message)
171 {
172 mResult = NS_OK;
174 uint16_t port;
175 nsCString ip;
176 nsCOMPtr<nsINetAddr> fromAddr;
177 message->GetFromAddr(getter_AddRefs(fromAddr));
178 fromAddr->GetPort(&port);
179 fromAddr->GetAddress(ip);
180 passed("Packet received on server from %s:%d", ip.get(), port);
182 if (TEST_OUTPUT_STREAM == phase && CheckMessageContent(message, REQUEST))
183 {
184 nsCOMPtr<nsIOutputStream> outstream;
185 message->GetOutputStream(getter_AddRefs(outstream));
187 uint32_t count;
188 const uint32_t data = RESPONSE;
189 printf("*** Attempting to write response 0x%x to client by OutputStream...\n", RESPONSE);
190 mResult = outstream->Write((const char*)&data, sizeof(uint32_t), &count);
192 if (mResult == NS_OK && count == sizeof(uint32_t)) {
193 passed("Response written");
194 } else {
195 fail("Response written");
196 }
197 return NS_OK;
198 } else if (TEST_SEND_API != phase || !CheckMessageContent(message, RESPONSE)) {
199 mResult = NS_ERROR_FAILURE;
200 }
202 // Notify thread
203 QuitPumpingEvents();
204 return NS_OK;
205 }
207 NS_IMETHODIMP
208 UDPServerListener::OnStopListening(nsIUDPSocket*, nsresult)
209 {
210 QuitPumpingEvents();
211 return NS_OK;
212 }
214 /**** Main ****/
215 int
216 main(int32_t argc, char *argv[])
217 {
218 nsresult rv;
219 ScopedXPCOM xpcom("UDP ServerSocket");
220 if (xpcom.failed())
221 return -1;
223 // Create UDPSocket
224 nsCOMPtr<nsIUDPSocket> server, client;
225 server = do_CreateInstance("@mozilla.org/network/udp-socket;1", &rv);
226 NS_ENSURE_SUCCESS(rv, -1);
227 client = do_CreateInstance("@mozilla.org/network/udp-socket;1", &rv);
228 NS_ENSURE_SUCCESS(rv, -1);
230 // Create UDPServerListener to process UDP packets
231 nsRefPtr<UDPServerListener> serverListener = new UDPServerListener();
233 // Bind server socket to 127.0.0.1
234 rv = server->Init(0, true);
235 NS_ENSURE_SUCCESS(rv, -1);
236 int32_t serverPort;
237 server->GetPort(&serverPort);
238 server->AsyncListen(serverListener);
240 // Bind clinet on arbitrary port
241 nsRefPtr<UDPClientListener> clientListener = new UDPClientListener();
242 client->Init(0, true);
243 client->AsyncListen(clientListener);
245 // Write data to server
246 uint32_t count;
247 const uint32_t data = REQUEST;
249 phase = TEST_OUTPUT_STREAM;
250 rv = client->Send(NS_LITERAL_CSTRING("127.0.0.1"), serverPort, (uint8_t*)&data, sizeof(uint32_t), &count);
251 NS_ENSURE_SUCCESS(rv, -1);
252 REQUIRE_EQUAL(count, sizeof(uint32_t), "Error");
253 passed("Request written by Send");
255 // Wait for server
256 PumpEvents();
257 NS_ENSURE_SUCCESS(serverListener->mResult, -1);
259 // Read response from server
260 NS_ENSURE_SUCCESS(clientListener->mResult, -1);
262 mozilla::net::NetAddr clientAddr;
263 rv = client->GetAddress(&clientAddr);
264 NS_ENSURE_SUCCESS(rv, -1);
266 phase = TEST_SEND_API;
267 rv = server->SendWithAddress(&clientAddr, (uint8_t*)&data, sizeof(uint32_t), &count);
268 NS_ENSURE_SUCCESS(rv, -1);
269 REQUIRE_EQUAL(count, sizeof(uint32_t), "Error");
270 passed("Request written by SendWithAddress");
272 // Wait for server
273 PumpEvents();
274 NS_ENSURE_SUCCESS(serverListener->mResult, -1);
276 // Read response from server
277 NS_ENSURE_SUCCESS(clientListener->mResult, -1);
279 // Close server
280 printf("*** Attempting to close server ...\n");
281 server->Close();
282 client->Close();
283 PumpEvents();
284 passed("Server closed");
286 return 0; // failure is a non-zero return
287 }