1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is the Netscape Portable Runtime (NSPR).
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1999-2000
20 * the Initial Developer. All Rights Reserved.
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
39 * A test case for the PR_MSG_PEEK flag of PR_Recv().
41 * Test both blocking and non-blocking sockets.
50 #define BUFFER_SIZE 1024
52 static int iterations
= 10;
55 * In iteration i, recv_amount[i] is the number of bytes we
56 * wish to receive, and send_amount[i] is the number of bytes
57 * we actually send. Therefore, the number of elements in the
58 * recv_amount or send_amount array should equal to 'iterations'.
59 * For this test to pass we need to ensure that
60 * recv_amount[i] <= BUFFER_SIZE,
61 * send_amount[i] <= BUFFER_SIZE,
62 * send_amount[i] <= recv_amount[i].
64 static PRInt32 recv_amount
[10] = {
65 16, 128, 256, 1024, 512, 512, 128, 256, 32, 32};
66 static PRInt32 send_amount
[10] = {
67 16, 64, 128, 1024, 512, 256, 128, 64, 16, 32};
70 static void ServerB(void *arg
)
72 PRFileDesc
*listenSock
= (PRFileDesc
*) arg
;
74 char buf
[BUFFER_SIZE
];
79 sock
= PR_Accept(listenSock
, NULL
, PR_INTERVAL_NO_TIMEOUT
);
81 fprintf(stderr
, "PR_Accept failed\n");
85 for (i
= 0; i
< iterations
; i
++) {
86 memset(buf
, 0, sizeof(buf
));
87 nbytes
= PR_Recv(sock
, buf
, recv_amount
[i
],
88 PR_MSG_PEEK
, PR_INTERVAL_NO_TIMEOUT
);
90 fprintf(stderr
, "PR_Recv failed\n");
93 if (send_amount
[i
] != nbytes
) {
94 fprintf(stderr
, "PR_Recv returned %d, absurd!\n", nbytes
);
97 for (j
= 0; j
< nbytes
; j
++) {
99 fprintf(stderr
, "byte %d should be %d but is %d\n",
104 fprintf(stderr
, "server: peeked expected data\n");
106 memset(buf
, 0, sizeof(buf
));
107 nbytes
= PR_Recv(sock
, buf
, recv_amount
[i
],
108 PR_MSG_PEEK
, PR_INTERVAL_NO_TIMEOUT
);
110 fprintf(stderr
, "PR_Recv failed\n");
113 if (send_amount
[i
] != nbytes
) {
114 fprintf(stderr
, "PR_Recv returned %d, absurd!\n", nbytes
);
117 for (j
= 0; j
< nbytes
; j
++) {
119 fprintf(stderr
, "byte %d should be %d but is %d\n",
124 fprintf(stderr
, "server: peeked expected data\n");
126 memset(buf
, 0, sizeof(buf
));
127 nbytes
= PR_Recv(sock
, buf
, recv_amount
[i
],
128 0, PR_INTERVAL_NO_TIMEOUT
);
130 fprintf(stderr
, "PR_Recv failed\n");
133 if (send_amount
[i
] != nbytes
) {
134 fprintf(stderr
, "PR_Recv returned %d, absurd!\n", nbytes
);
137 for (j
= 0; j
< nbytes
; j
++) {
139 fprintf(stderr
, "byte %d should be %d but is %d\n",
144 fprintf(stderr
, "server: received expected data\n");
146 PR_Sleep(PR_SecondsToInterval(1));
147 memset(buf
, 2*i
+1, send_amount
[i
]);
148 nbytes
= PR_Send(sock
, buf
, send_amount
[i
],
149 0, PR_INTERVAL_NO_TIMEOUT
);
151 fprintf(stderr
, "PR_Send failed\n");
154 if (send_amount
[i
] != nbytes
) {
155 fprintf(stderr
, "PR_Send returned %d, absurd!\n", nbytes
);
159 if (PR_Close(sock
) == PR_FAILURE
) {
160 fprintf(stderr
, "PR_Close failed\n");
165 /* Non-blocking I/O */
166 static void ClientNB(void *arg
)
169 PRSocketOptionData opt
;
170 PRUint16 port
= (PRUint16
) arg
;
172 char buf
[BUFFER_SIZE
];
179 sock
= PR_OpenTCPSocket(PR_AF_INET6
);
181 fprintf(stderr
, "PR_OpenTCPSocket failed\n");
184 opt
.option
= PR_SockOpt_Nonblocking
;
185 opt
.value
.non_blocking
= PR_TRUE
;
186 if (PR_SetSocketOption(sock
, &opt
) == PR_FAILURE
) {
187 fprintf(stderr
, "PR_SetSocketOption failed\n");
190 memset(&addr
, 0, sizeof(addr
));
191 if (PR_SetNetAddr(PR_IpAddrLoopback
, PR_AF_INET6
, port
, &addr
)
193 fprintf(stderr
, "PR_SetNetAddr failed\n");
196 if (PR_Connect(sock
, &addr
, PR_INTERVAL_NO_TIMEOUT
) == PR_FAILURE
) {
197 if (PR_GetError() != PR_IN_PROGRESS_ERROR
) {
198 fprintf(stderr
, "PR_Connect failed\n");
202 pd
.in_flags
= PR_POLL_WRITE
| PR_POLL_EXCEPT
;
203 npds
= PR_Poll(&pd
, 1, PR_INTERVAL_NO_TIMEOUT
);
205 fprintf(stderr
, "PR_Poll failed\n");
209 fprintf(stderr
, "PR_Poll returned %d, absurd!\n", npds
);
212 if (PR_GetConnectStatus(&pd
) == PR_FAILURE
) {
213 fprintf(stderr
, "PR_GetConnectStatus failed\n");
218 for (i
= 0; i
< iterations
; i
++) {
219 PR_Sleep(PR_SecondsToInterval(1));
220 memset(buf
, 2*i
, send_amount
[i
]);
221 while ((nbytes
= PR_Send(sock
, buf
, send_amount
[i
],
222 0, PR_INTERVAL_NO_TIMEOUT
)) == -1) {
223 if (PR_GetError() != PR_WOULD_BLOCK_ERROR
) {
224 fprintf(stderr
, "PR_Send failed\n");
228 pd
.in_flags
= PR_POLL_WRITE
;
229 npds
= PR_Poll(&pd
, 1, PR_INTERVAL_NO_TIMEOUT
);
231 fprintf(stderr
, "PR_Poll failed\n");
235 fprintf(stderr
, "PR_Poll returned %d, absurd!\n", npds
);
239 if (send_amount
[i
] != nbytes
) {
240 fprintf(stderr
, "PR_Send returned %d, absurd!\n", nbytes
);
244 memset(buf
, 0, sizeof(buf
));
245 while ((nbytes
= PR_Recv(sock
, buf
, recv_amount
[i
],
246 PR_MSG_PEEK
, PR_INTERVAL_NO_TIMEOUT
)) == -1) {
247 if (PR_GetError() != PR_WOULD_BLOCK_ERROR
) {
248 fprintf(stderr
, "PR_Recv failed\n");
252 pd
.in_flags
= PR_POLL_READ
;
253 npds
= PR_Poll(&pd
, 1, PR_INTERVAL_NO_TIMEOUT
);
255 fprintf(stderr
, "PR_Poll failed\n");
259 fprintf(stderr
, "PR_Poll returned %d, absurd!\n", npds
);
263 if (send_amount
[i
] != nbytes
) {
264 fprintf(stderr
, "PR_Recv returned %d, absurd!\n", nbytes
);
267 for (j
= 0; j
< nbytes
; j
++) {
268 if (buf
[j
] != 2*i
+1) {
269 fprintf(stderr
, "byte %d should be %d but is %d\n",
274 fprintf(stderr
, "client: peeked expected data\n");
276 memset(buf
, 0, sizeof(buf
));
277 nbytes
= PR_Recv(sock
, buf
, recv_amount
[i
],
278 PR_MSG_PEEK
, PR_INTERVAL_NO_TIMEOUT
);
280 fprintf(stderr
, "PR_Recv failed\n");
283 if (send_amount
[i
] != nbytes
) {
284 fprintf(stderr
, "PR_Recv returned %d, absurd!\n", nbytes
);
287 for (j
= 0; j
< nbytes
; j
++) {
288 if (buf
[j
] != 2*i
+1) {
289 fprintf(stderr
, "byte %d should be %d but is %d\n",
294 fprintf(stderr
, "client: peeked expected data\n");
296 memset(buf
, 0, sizeof(buf
));
297 nbytes
= PR_Recv(sock
, buf
, recv_amount
[i
],
298 0, PR_INTERVAL_NO_TIMEOUT
);
300 fprintf(stderr
, "PR_Recv failed\n");
303 if (send_amount
[i
] != nbytes
) {
304 fprintf(stderr
, "PR_Recv returned %d, absurd!\n", nbytes
);
307 for (j
= 0; j
< nbytes
; j
++) {
308 if (buf
[j
] != 2*i
+1) {
309 fprintf(stderr
, "byte %d should be %d but is %d\n",
314 fprintf(stderr
, "client: received expected data\n");
316 if (PR_Close(sock
) == PR_FAILURE
) {
317 fprintf(stderr
, "PR_Close failed\n");
323 RunTest(PRThreadScope scope
, PRFileDesc
*listenSock
, PRUint16 port
)
325 PRThread
*server
, *client
;
327 server
= PR_CreateThread(PR_USER_THREAD
, ServerB
, listenSock
,
328 PR_PRIORITY_NORMAL
, scope
, PR_JOINABLE_THREAD
, 0);
329 if (NULL
== server
) {
330 fprintf(stderr
, "PR_CreateThread failed\n");
333 client
= PR_CreateThread(
334 PR_USER_THREAD
, ClientNB
, (void *) port
,
335 PR_PRIORITY_NORMAL
, scope
, PR_JOINABLE_THREAD
, 0);
336 if (NULL
== client
) {
337 fprintf(stderr
, "PR_CreateThread failed\n");
341 if (PR_JoinThread(server
) == PR_FAILURE
) {
342 fprintf(stderr
, "PR_JoinThread failed\n");
345 if (PR_JoinThread(client
) == PR_FAILURE
) {
346 fprintf(stderr
, "PR_JoinThread failed\n");
351 int main(int argc
, char **argv
)
353 PRFileDesc
*listenSock
;
357 listenSock
= PR_OpenTCPSocket(PR_AF_INET6
);
358 if (NULL
== listenSock
) {
359 fprintf(stderr
, "PR_OpenTCPSocket failed\n");
362 memset(&addr
, 0, sizeof(addr
));
363 if (PR_SetNetAddr(PR_IpAddrAny
, PR_AF_INET6
, 0, &addr
) == PR_FAILURE
) {
364 fprintf(stderr
, "PR_SetNetAddr failed\n");
367 if (PR_Bind(listenSock
, &addr
) == PR_FAILURE
) {
368 fprintf(stderr
, "PR_Bind failed\n");
371 if (PR_GetSockName(listenSock
, &addr
) == PR_FAILURE
) {
372 fprintf(stderr
, "PR_GetSockName failed\n");
375 port
= PR_ntohs(addr
.ipv6
.port
);
376 if (PR_Listen(listenSock
, 5) == PR_FAILURE
) {
377 fprintf(stderr
, "PR_Listen failed\n");
381 fprintf(stderr
, "Running the test with local threads\n");
382 RunTest(PR_LOCAL_THREAD
, listenSock
, port
);
383 fprintf(stderr
, "Running the test with global threads\n");
384 RunTest(PR_GLOBAL_THREAD
, listenSock
, port
);
386 if (PR_Close(listenSock
) == PR_FAILURE
) {
387 fprintf(stderr
, "PR_Close failed\n");