peek.c (10079B)
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/. */ 5 6 /* 7 * A test case for the PR_MSG_PEEK flag of PR_Recv(). 8 * 9 * Test both blocking and non-blocking sockets. 10 */ 11 12 #include "nspr.h" 13 14 #include <stdio.h> 15 #include <stdlib.h> 16 #include <string.h> 17 18 #define BUFFER_SIZE 1024 19 20 static int iterations = 10; 21 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] = {16, 128, 256, 1024, 512, 33 512, 128, 256, 32, 32}; 34 static PRInt32 send_amount[10] = {16, 64, 128, 1024, 512, 256, 128, 64, 16, 32}; 35 36 /* Blocking I/O */ 37 static void ServerB(void* arg) { 38 PRFileDesc* listenSock = (PRFileDesc*)arg; 39 PRFileDesc* sock; 40 char buf[BUFFER_SIZE]; 41 PRInt32 nbytes; 42 int i; 43 int j; 44 45 sock = PR_Accept(listenSock, NULL, PR_INTERVAL_NO_TIMEOUT); 46 if (NULL == sock) { 47 fprintf(stderr, "PR_Accept failed\n"); 48 exit(1); 49 } 50 51 for (i = 0; i < iterations; i++) { 52 memset(buf, 0, sizeof(buf)); 53 nbytes = 54 PR_Recv(sock, buf, recv_amount[i], PR_MSG_PEEK, PR_INTERVAL_NO_TIMEOUT); 55 if (-1 == nbytes) { 56 fprintf(stderr, "PR_Recv failed\n"); 57 exit(1); 58 } 59 if (send_amount[i] != nbytes) { 60 fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes); 61 exit(1); 62 } 63 for (j = 0; j < nbytes; j++) { 64 if (buf[j] != 2 * i) { 65 fprintf(stderr, "byte %d should be %d but is %d\n", j, 2 * i, buf[j]); 66 exit(1); 67 } 68 } 69 fprintf(stderr, "server: peeked expected data\n"); 70 71 memset(buf, 0, sizeof(buf)); 72 nbytes = 73 PR_Recv(sock, buf, recv_amount[i], PR_MSG_PEEK, PR_INTERVAL_NO_TIMEOUT); 74 if (-1 == nbytes) { 75 fprintf(stderr, "PR_Recv failed\n"); 76 exit(1); 77 } 78 if (send_amount[i] != nbytes) { 79 fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes); 80 exit(1); 81 } 82 for (j = 0; j < nbytes; j++) { 83 if (buf[j] != 2 * i) { 84 fprintf(stderr, "byte %d should be %d but is %d\n", j, 2 * i, buf[j]); 85 exit(1); 86 } 87 } 88 fprintf(stderr, "server: peeked expected data\n"); 89 90 memset(buf, 0, sizeof(buf)); 91 nbytes = PR_Recv(sock, buf, recv_amount[i], 0, PR_INTERVAL_NO_TIMEOUT); 92 if (-1 == nbytes) { 93 fprintf(stderr, "PR_Recv failed\n"); 94 exit(1); 95 } 96 if (send_amount[i] != nbytes) { 97 fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes); 98 exit(1); 99 } 100 for (j = 0; j < nbytes; j++) { 101 if (buf[j] != 2 * i) { 102 fprintf(stderr, "byte %d should be %d but is %d\n", j, 2 * i, buf[j]); 103 exit(1); 104 } 105 } 106 fprintf(stderr, "server: received expected data\n"); 107 108 PR_Sleep(PR_SecondsToInterval(1)); 109 memset(buf, 2 * i + 1, send_amount[i]); 110 nbytes = PR_Send(sock, buf, send_amount[i], 0, PR_INTERVAL_NO_TIMEOUT); 111 if (-1 == nbytes) { 112 fprintf(stderr, "PR_Send failed\n"); 113 exit(1); 114 } 115 if (send_amount[i] != nbytes) { 116 fprintf(stderr, "PR_Send returned %d, absurd!\n", nbytes); 117 exit(1); 118 } 119 } 120 if (PR_Close(sock) == PR_FAILURE) { 121 fprintf(stderr, "PR_Close failed\n"); 122 exit(1); 123 } 124 } 125 126 /* Non-blocking I/O */ 127 static void ClientNB(void* arg) { 128 PRFileDesc* sock; 129 PRSocketOptionData opt; 130 PRUint16 port = (PRUint16)arg; 131 PRNetAddr addr; 132 char buf[BUFFER_SIZE]; 133 PRPollDesc pd; 134 PRInt32 npds; 135 PRInt32 nbytes; 136 int i; 137 int j; 138 139 sock = PR_OpenTCPSocket(PR_AF_INET6); 140 if (NULL == sock) { 141 fprintf(stderr, "PR_OpenTCPSocket failed\n"); 142 exit(1); 143 } 144 opt.option = PR_SockOpt_Nonblocking; 145 opt.value.non_blocking = PR_TRUE; 146 if (PR_SetSocketOption(sock, &opt) == PR_FAILURE) { 147 fprintf(stderr, "PR_SetSocketOption failed\n"); 148 exit(1); 149 } 150 memset(&addr, 0, sizeof(addr)); 151 if (PR_SetNetAddr(PR_IpAddrLoopback, PR_AF_INET6, port, &addr) == 152 PR_FAILURE) { 153 fprintf(stderr, "PR_SetNetAddr failed\n"); 154 exit(1); 155 } 156 if (PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) { 157 if (PR_GetError() != PR_IN_PROGRESS_ERROR) { 158 fprintf(stderr, "PR_Connect failed\n"); 159 exit(1); 160 } 161 pd.fd = sock; 162 pd.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT; 163 npds = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT); 164 if (-1 == npds) { 165 fprintf(stderr, "PR_Poll failed\n"); 166 exit(1); 167 } 168 if (1 != npds) { 169 fprintf(stderr, "PR_Poll returned %d, absurd!\n", npds); 170 exit(1); 171 } 172 if (PR_GetConnectStatus(&pd) == PR_FAILURE) { 173 fprintf(stderr, "PR_GetConnectStatus failed\n"); 174 exit(1); 175 } 176 } 177 178 for (i = 0; i < iterations; i++) { 179 PR_Sleep(PR_SecondsToInterval(1)); 180 memset(buf, 2 * i, send_amount[i]); 181 while ((nbytes = PR_Send(sock, buf, send_amount[i], 0, 182 PR_INTERVAL_NO_TIMEOUT)) == -1) { 183 if (PR_GetError() != PR_WOULD_BLOCK_ERROR) { 184 fprintf(stderr, "PR_Send failed\n"); 185 exit(1); 186 } 187 pd.fd = sock; 188 pd.in_flags = PR_POLL_WRITE; 189 npds = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT); 190 if (-1 == npds) { 191 fprintf(stderr, "PR_Poll failed\n"); 192 exit(1); 193 } 194 if (1 != npds) { 195 fprintf(stderr, "PR_Poll returned %d, absurd!\n", npds); 196 exit(1); 197 } 198 } 199 if (send_amount[i] != nbytes) { 200 fprintf(stderr, "PR_Send returned %d, absurd!\n", nbytes); 201 exit(1); 202 } 203 204 memset(buf, 0, sizeof(buf)); 205 while ((nbytes = PR_Recv(sock, buf, recv_amount[i], PR_MSG_PEEK, 206 PR_INTERVAL_NO_TIMEOUT)) == -1) { 207 if (PR_GetError() != PR_WOULD_BLOCK_ERROR) { 208 fprintf(stderr, "PR_Recv failed\n"); 209 exit(1); 210 } 211 pd.fd = sock; 212 pd.in_flags = PR_POLL_READ; 213 npds = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT); 214 if (-1 == npds) { 215 fprintf(stderr, "PR_Poll failed\n"); 216 exit(1); 217 } 218 if (1 != npds) { 219 fprintf(stderr, "PR_Poll returned %d, absurd!\n", npds); 220 exit(1); 221 } 222 } 223 if (send_amount[i] != nbytes) { 224 fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes); 225 exit(1); 226 } 227 for (j = 0; j < nbytes; j++) { 228 if (buf[j] != 2 * i + 1) { 229 fprintf(stderr, "byte %d should be %d but is %d\n", j, 2 * i + 1, 230 buf[j]); 231 exit(1); 232 } 233 } 234 fprintf(stderr, "client: peeked expected data\n"); 235 236 memset(buf, 0, sizeof(buf)); 237 nbytes = 238 PR_Recv(sock, buf, recv_amount[i], PR_MSG_PEEK, PR_INTERVAL_NO_TIMEOUT); 239 if (-1 == nbytes) { 240 fprintf(stderr, "PR_Recv failed\n"); 241 exit(1); 242 } 243 if (send_amount[i] != nbytes) { 244 fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes); 245 exit(1); 246 } 247 for (j = 0; j < nbytes; j++) { 248 if (buf[j] != 2 * i + 1) { 249 fprintf(stderr, "byte %d should be %d but is %d\n", j, 2 * i + 1, 250 buf[j]); 251 exit(1); 252 } 253 } 254 fprintf(stderr, "client: peeked expected data\n"); 255 256 memset(buf, 0, sizeof(buf)); 257 nbytes = PR_Recv(sock, buf, recv_amount[i], 0, PR_INTERVAL_NO_TIMEOUT); 258 if (-1 == nbytes) { 259 fprintf(stderr, "PR_Recv failed\n"); 260 exit(1); 261 } 262 if (send_amount[i] != nbytes) { 263 fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes); 264 exit(1); 265 } 266 for (j = 0; j < nbytes; j++) { 267 if (buf[j] != 2 * i + 1) { 268 fprintf(stderr, "byte %d should be %d but is %d\n", j, 2 * i + 1, 269 buf[j]); 270 exit(1); 271 } 272 } 273 fprintf(stderr, "client: received expected data\n"); 274 } 275 if (PR_Close(sock) == PR_FAILURE) { 276 fprintf(stderr, "PR_Close failed\n"); 277 exit(1); 278 } 279 } 280 281 static void RunTest(PRThreadScope scope, PRFileDesc* listenSock, 282 PRUint16 port) { 283 PRThread *server, *client; 284 285 server = PR_CreateThread(PR_USER_THREAD, ServerB, listenSock, 286 PR_PRIORITY_NORMAL, scope, PR_JOINABLE_THREAD, 0); 287 if (NULL == server) { 288 fprintf(stderr, "PR_CreateThread failed\n"); 289 exit(1); 290 } 291 client = PR_CreateThread(PR_USER_THREAD, ClientNB, (void*)port, 292 PR_PRIORITY_NORMAL, scope, PR_JOINABLE_THREAD, 0); 293 if (NULL == client) { 294 fprintf(stderr, "PR_CreateThread failed\n"); 295 exit(1); 296 } 297 298 if (PR_JoinThread(server) == PR_FAILURE) { 299 fprintf(stderr, "PR_JoinThread failed\n"); 300 exit(1); 301 } 302 if (PR_JoinThread(client) == PR_FAILURE) { 303 fprintf(stderr, "PR_JoinThread failed\n"); 304 exit(1); 305 } 306 } 307 308 int main(int argc, char** argv) { 309 PRFileDesc* listenSock; 310 PRNetAddr addr; 311 PRUint16 port; 312 313 listenSock = PR_OpenTCPSocket(PR_AF_INET6); 314 if (NULL == listenSock) { 315 fprintf(stderr, "PR_OpenTCPSocket failed\n"); 316 exit(1); 317 } 318 memset(&addr, 0, sizeof(addr)); 319 if (PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET6, 0, &addr) == PR_FAILURE) { 320 fprintf(stderr, "PR_SetNetAddr failed\n"); 321 exit(1); 322 } 323 if (PR_Bind(listenSock, &addr) == PR_FAILURE) { 324 fprintf(stderr, "PR_Bind failed\n"); 325 exit(1); 326 } 327 if (PR_GetSockName(listenSock, &addr) == PR_FAILURE) { 328 fprintf(stderr, "PR_GetSockName failed\n"); 329 exit(1); 330 } 331 port = PR_ntohs(addr.ipv6.port); 332 if (PR_Listen(listenSock, 5) == PR_FAILURE) { 333 fprintf(stderr, "PR_Listen failed\n"); 334 exit(1); 335 } 336 337 fprintf(stderr, "Running the test with local threads\n"); 338 RunTest(PR_LOCAL_THREAD, listenSock, port); 339 fprintf(stderr, "Running the test with global threads\n"); 340 RunTest(PR_GLOBAL_THREAD, listenSock, port); 341 342 if (PR_Close(listenSock) == PR_FAILURE) { 343 fprintf(stderr, "PR_Close failed\n"); 344 exit(1); 345 } 346 printf("PASS\n"); 347 return 0; 348 }