Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 /*
7 * A test case for the PR_MSG_PEEK flag of PR_Recv().
8 *
9 * Test both blocking and non-blocking sockets.
10 */
12 #include "nspr.h"
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
18 #define BUFFER_SIZE 1024
20 static int iterations = 10;
22 /*
23 * In iteration i, recv_amount[i] is the number of bytes we
24 * wish to receive, and send_amount[i] is the number of bytes
25 * we actually send. Therefore, the number of elements in the
26 * recv_amount or send_amount array should equal to 'iterations'.
27 * For this test to pass we need to ensure that
28 * recv_amount[i] <= BUFFER_SIZE,
29 * send_amount[i] <= BUFFER_SIZE,
30 * send_amount[i] <= recv_amount[i].
31 */
32 static PRInt32 recv_amount[10] = {
33 16, 128, 256, 1024, 512, 512, 128, 256, 32, 32};
34 static PRInt32 send_amount[10] = {
35 16, 64, 128, 1024, 512, 256, 128, 64, 16, 32};
37 /* Blocking I/O */
38 static void ServerB(void *arg)
39 {
40 PRFileDesc *listenSock = (PRFileDesc *) arg;
41 PRFileDesc *sock;
42 char buf[BUFFER_SIZE];
43 PRInt32 nbytes;
44 int i;
45 int j;
47 sock = PR_Accept(listenSock, NULL, PR_INTERVAL_NO_TIMEOUT);
48 if (NULL == sock) {
49 fprintf(stderr, "PR_Accept failed\n");
50 exit(1);
51 }
53 for (i = 0; i < iterations; i++) {
54 memset(buf, 0, sizeof(buf));
55 nbytes = PR_Recv(sock, buf, recv_amount[i],
56 PR_MSG_PEEK, PR_INTERVAL_NO_TIMEOUT);
57 if (-1 == nbytes) {
58 fprintf(stderr, "PR_Recv failed\n");
59 exit(1);
60 }
61 if (send_amount[i] != nbytes) {
62 fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes);
63 exit(1);
64 }
65 for (j = 0; j < nbytes; j++) {
66 if (buf[j] != 2*i) {
67 fprintf(stderr, "byte %d should be %d but is %d\n",
68 j, 2*i, buf[j]);
69 exit(1);
70 }
71 }
72 fprintf(stderr, "server: peeked expected data\n");
74 memset(buf, 0, sizeof(buf));
75 nbytes = PR_Recv(sock, buf, recv_amount[i],
76 PR_MSG_PEEK, PR_INTERVAL_NO_TIMEOUT);
77 if (-1 == nbytes) {
78 fprintf(stderr, "PR_Recv failed\n");
79 exit(1);
80 }
81 if (send_amount[i] != nbytes) {
82 fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes);
83 exit(1);
84 }
85 for (j = 0; j < nbytes; j++) {
86 if (buf[j] != 2*i) {
87 fprintf(stderr, "byte %d should be %d but is %d\n",
88 j, 2*i, buf[j]);
89 exit(1);
90 }
91 }
92 fprintf(stderr, "server: peeked expected data\n");
94 memset(buf, 0, sizeof(buf));
95 nbytes = PR_Recv(sock, buf, recv_amount[i],
96 0, PR_INTERVAL_NO_TIMEOUT);
97 if (-1 == nbytes) {
98 fprintf(stderr, "PR_Recv failed\n");
99 exit(1);
100 }
101 if (send_amount[i] != nbytes) {
102 fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes);
103 exit(1);
104 }
105 for (j = 0; j < nbytes; j++) {
106 if (buf[j] != 2*i) {
107 fprintf(stderr, "byte %d should be %d but is %d\n",
108 j, 2*i, buf[j]);
109 exit(1);
110 }
111 }
112 fprintf(stderr, "server: received expected data\n");
114 PR_Sleep(PR_SecondsToInterval(1));
115 memset(buf, 2*i+1, send_amount[i]);
116 nbytes = PR_Send(sock, buf, send_amount[i],
117 0, PR_INTERVAL_NO_TIMEOUT);
118 if (-1 == nbytes) {
119 fprintf(stderr, "PR_Send failed\n");
120 exit(1);
121 }
122 if (send_amount[i] != nbytes) {
123 fprintf(stderr, "PR_Send returned %d, absurd!\n", nbytes);
124 exit(1);
125 }
126 }
127 if (PR_Close(sock) == PR_FAILURE) {
128 fprintf(stderr, "PR_Close failed\n");
129 exit(1);
130 }
131 }
133 /* Non-blocking I/O */
134 static void ClientNB(void *arg)
135 {
136 PRFileDesc *sock;
137 PRSocketOptionData opt;
138 PRUint16 port = (PRUint16) arg;
139 PRNetAddr addr;
140 char buf[BUFFER_SIZE];
141 PRPollDesc pd;
142 PRInt32 npds;
143 PRInt32 nbytes;
144 int i;
145 int j;
147 sock = PR_OpenTCPSocket(PR_AF_INET6);
148 if (NULL == sock) {
149 fprintf(stderr, "PR_OpenTCPSocket failed\n");
150 exit(1);
151 }
152 opt.option = PR_SockOpt_Nonblocking;
153 opt.value.non_blocking = PR_TRUE;
154 if (PR_SetSocketOption(sock, &opt) == PR_FAILURE) {
155 fprintf(stderr, "PR_SetSocketOption failed\n");
156 exit(1);
157 }
158 memset(&addr, 0, sizeof(addr));
159 if (PR_SetNetAddr(PR_IpAddrLoopback, PR_AF_INET6, port, &addr)
160 == PR_FAILURE) {
161 fprintf(stderr, "PR_SetNetAddr failed\n");
162 exit(1);
163 }
164 if (PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) {
165 if (PR_GetError() != PR_IN_PROGRESS_ERROR) {
166 fprintf(stderr, "PR_Connect failed\n");
167 exit(1);
168 }
169 pd.fd = sock;
170 pd.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
171 npds = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
172 if (-1 == npds) {
173 fprintf(stderr, "PR_Poll failed\n");
174 exit(1);
175 }
176 if (1 != npds) {
177 fprintf(stderr, "PR_Poll returned %d, absurd!\n", npds);
178 exit(1);
179 }
180 if (PR_GetConnectStatus(&pd) == PR_FAILURE) {
181 fprintf(stderr, "PR_GetConnectStatus failed\n");
182 exit(1);
183 }
184 }
186 for (i = 0; i < iterations; i++) {
187 PR_Sleep(PR_SecondsToInterval(1));
188 memset(buf, 2*i, send_amount[i]);
189 while ((nbytes = PR_Send(sock, buf, send_amount[i],
190 0, PR_INTERVAL_NO_TIMEOUT)) == -1) {
191 if (PR_GetError() != PR_WOULD_BLOCK_ERROR) {
192 fprintf(stderr, "PR_Send failed\n");
193 exit(1);
194 }
195 pd.fd = sock;
196 pd.in_flags = PR_POLL_WRITE;
197 npds = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
198 if (-1 == npds) {
199 fprintf(stderr, "PR_Poll failed\n");
200 exit(1);
201 }
202 if (1 != npds) {
203 fprintf(stderr, "PR_Poll returned %d, absurd!\n", npds);
204 exit(1);
205 }
206 }
207 if (send_amount[i] != nbytes) {
208 fprintf(stderr, "PR_Send returned %d, absurd!\n", nbytes);
209 exit(1);
210 }
212 memset(buf, 0, sizeof(buf));
213 while ((nbytes = PR_Recv(sock, buf, recv_amount[i],
214 PR_MSG_PEEK, PR_INTERVAL_NO_TIMEOUT)) == -1) {
215 if (PR_GetError() != PR_WOULD_BLOCK_ERROR) {
216 fprintf(stderr, "PR_Recv failed\n");
217 exit(1);
218 }
219 pd.fd = sock;
220 pd.in_flags = PR_POLL_READ;
221 npds = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
222 if (-1 == npds) {
223 fprintf(stderr, "PR_Poll failed\n");
224 exit(1);
225 }
226 if (1 != npds) {
227 fprintf(stderr, "PR_Poll returned %d, absurd!\n", npds);
228 exit(1);
229 }
230 }
231 if (send_amount[i] != nbytes) {
232 fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes);
233 exit(1);
234 }
235 for (j = 0; j < nbytes; j++) {
236 if (buf[j] != 2*i+1) {
237 fprintf(stderr, "byte %d should be %d but is %d\n",
238 j, 2*i+1, buf[j]);
239 exit(1);
240 }
241 }
242 fprintf(stderr, "client: peeked expected data\n");
244 memset(buf, 0, sizeof(buf));
245 nbytes = PR_Recv(sock, buf, recv_amount[i],
246 PR_MSG_PEEK, PR_INTERVAL_NO_TIMEOUT);
247 if (-1 == nbytes) {
248 fprintf(stderr, "PR_Recv failed\n");
249 exit(1);
250 }
251 if (send_amount[i] != nbytes) {
252 fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes);
253 exit(1);
254 }
255 for (j = 0; j < nbytes; j++) {
256 if (buf[j] != 2*i+1) {
257 fprintf(stderr, "byte %d should be %d but is %d\n",
258 j, 2*i+1, buf[j]);
259 exit(1);
260 }
261 }
262 fprintf(stderr, "client: peeked expected data\n");
264 memset(buf, 0, sizeof(buf));
265 nbytes = PR_Recv(sock, buf, recv_amount[i],
266 0, PR_INTERVAL_NO_TIMEOUT);
267 if (-1 == nbytes) {
268 fprintf(stderr, "PR_Recv failed\n");
269 exit(1);
270 }
271 if (send_amount[i] != nbytes) {
272 fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes);
273 exit(1);
274 }
275 for (j = 0; j < nbytes; j++) {
276 if (buf[j] != 2*i+1) {
277 fprintf(stderr, "byte %d should be %d but is %d\n",
278 j, 2*i+1, buf[j]);
279 exit(1);
280 }
281 }
282 fprintf(stderr, "client: received expected data\n");
283 }
284 if (PR_Close(sock) == PR_FAILURE) {
285 fprintf(stderr, "PR_Close failed\n");
286 exit(1);
287 }
288 }
290 static void
291 RunTest(PRThreadScope scope, PRFileDesc *listenSock, PRUint16 port)
292 {
293 PRThread *server, *client;
295 server = PR_CreateThread(PR_USER_THREAD, ServerB, listenSock,
296 PR_PRIORITY_NORMAL, scope, PR_JOINABLE_THREAD, 0);
297 if (NULL == server) {
298 fprintf(stderr, "PR_CreateThread failed\n");
299 exit(1);
300 }
301 client = PR_CreateThread(
302 PR_USER_THREAD, ClientNB, (void *) port,
303 PR_PRIORITY_NORMAL, scope, PR_JOINABLE_THREAD, 0);
304 if (NULL == client) {
305 fprintf(stderr, "PR_CreateThread failed\n");
306 exit(1);
307 }
309 if (PR_JoinThread(server) == PR_FAILURE) {
310 fprintf(stderr, "PR_JoinThread failed\n");
311 exit(1);
312 }
313 if (PR_JoinThread(client) == PR_FAILURE) {
314 fprintf(stderr, "PR_JoinThread failed\n");
315 exit(1);
316 }
317 }
319 int main(int argc, char **argv)
320 {
321 PRFileDesc *listenSock;
322 PRNetAddr addr;
323 PRUint16 port;
325 listenSock = PR_OpenTCPSocket(PR_AF_INET6);
326 if (NULL == listenSock) {
327 fprintf(stderr, "PR_OpenTCPSocket failed\n");
328 exit(1);
329 }
330 memset(&addr, 0, sizeof(addr));
331 if (PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET6, 0, &addr) == PR_FAILURE) {
332 fprintf(stderr, "PR_SetNetAddr failed\n");
333 exit(1);
334 }
335 if (PR_Bind(listenSock, &addr) == PR_FAILURE) {
336 fprintf(stderr, "PR_Bind failed\n");
337 exit(1);
338 }
339 if (PR_GetSockName(listenSock, &addr) == PR_FAILURE) {
340 fprintf(stderr, "PR_GetSockName failed\n");
341 exit(1);
342 }
343 port = PR_ntohs(addr.ipv6.port);
344 if (PR_Listen(listenSock, 5) == PR_FAILURE) {
345 fprintf(stderr, "PR_Listen failed\n");
346 exit(1);
347 }
349 fprintf(stderr, "Running the test with local threads\n");
350 RunTest(PR_LOCAL_THREAD, listenSock, port);
351 fprintf(stderr, "Running the test with global threads\n");
352 RunTest(PR_GLOBAL_THREAD, listenSock, port);
354 if (PR_Close(listenSock) == PR_FAILURE) {
355 fprintf(stderr, "PR_Close failed\n");
356 exit(1);
357 }
358 printf("PASS\n");
359 return 0;
360 }