test_socket.c (20171B)
1 /* 2 * test_socket.c 3 * 4 * Test Socket Type 5 * 6 * Copyright 2004-2005 Sun Microsystems, Inc. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions are met: 10 * 11 * 1. Redistribution of source code must retain the above copyright notice, 12 * this list of conditions and the following disclaimer. 13 * 14 * 2. Redistribution in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * Neither the name of Sun Microsystems, Inc. or the names of contributors may 19 * be used to endorse or promote products derived from this software without 20 * specific prior written permission. 21 * 22 * This software is provided "AS IS," without a warranty of any kind. ALL 23 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING 24 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE 25 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") 26 * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE 27 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS 28 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST 29 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, 30 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY 31 * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, 32 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 33 * 34 * You acknowledge that this software is not designed or intended for use in 35 * the design, construction, operation or maintenance of any nuclear facility. 36 */ 37 38 #include "testutil.h" 39 #include "testutil_nss.h" 40 #include "pkix_pl_common.h" 41 42 #define LDAP_PORT 389 43 44 static void *plContext = NULL; 45 46 typedef enum { 47 SERVER_LISTENING, 48 SERVER_RECV1, 49 SERVER_POLL1, 50 SERVER_SEND2, 51 SERVER_POLL2, 52 SERVER_RECV3, 53 SERVER_POLL3, 54 SERVER_SEND4, 55 SERVER_POLL4, 56 SERVER_DONE, 57 SERVER_FAILED 58 } SERVER_STATE; 59 60 typedef enum { 61 CLIENT_WAITFORCONNECT, 62 CLIENT_SEND1, 63 CLIENT_POLL1, 64 CLIENT_RECV2, 65 CLIENT_POLL2, 66 CLIENT_SEND3, 67 CLIENT_POLL3, 68 CLIENT_RECV4, 69 CLIENT_POLL4, 70 CLIENT_DONE, 71 CLIENT_FAILED 72 } CLIENT_STATE; 73 74 SERVER_STATE serverState; 75 CLIENT_STATE clientState; 76 PKIX_PL_Socket *sSock = NULL; 77 PKIX_PL_Socket *cSock = NULL; 78 PKIX_PL_Socket *rendezvousSock = NULL; 79 PKIX_PL_Socket_Callback *sCallbackList; 80 PKIX_PL_Socket_Callback *cCallbackList; 81 PKIX_PL_Socket_Callback *rvCallbackList; 82 PRNetAddr serverNetAddr; 83 PRNetAddr clientNetAddr; 84 PRIntn backlog = 0; 85 PRIntervalTime timeout = 0; 86 char *sendBuf1 = "Hello, world!"; 87 char *sendBuf2 = "Ack"; 88 char *sendBuf3 = "What do you mean, \"Ack\"?"; 89 char *sendBuf4 = "What do you mean, \"What do you mean, \'Ack\'?\"?"; 90 char rcvBuf1[100]; 91 char rcvBuf2[100]; 92 93 static void 94 printUsage(char *testname) 95 { 96 char *fmt = "USAGE: %s [-arenas] server:port\n"; 97 printf(fmt, testname); 98 } 99 100 /* Functional tests for Socket public functions */ 101 static void 102 do_other_work(void) 103 { /* while waiting for nonblocking I/O to complete */ 104 (void)PR_Sleep(2 * 60); 105 } 106 107 static PKIX_Boolean 108 server() 109 { 110 PKIX_Int32 bytesRead = 0; 111 PKIX_Int32 bytesWritten = 0; 112 PKIX_Boolean keepGoing = PKIX_FALSE; 113 114 PKIX_TEST_STD_VARS(); 115 116 switch (serverState) { 117 case SERVER_LISTENING: 118 subTest("SERVER_LISTENING"); 119 PKIX_TEST_EXPECT_NO_ERROR(sCallbackList->acceptCallback(sSock, &rendezvousSock, plContext)); 120 if (rendezvousSock) { 121 PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_GetCallbackList(rendezvousSock, &rvCallbackList, plContext)); 122 123 serverState = SERVER_RECV1; 124 } 125 break; 126 case SERVER_RECV1: 127 subTest("SERVER_RECV1"); 128 PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->recvCallback(rendezvousSock, 129 rcvBuf1, 130 sizeof(rcvBuf1), 131 &bytesRead, 132 plContext)); 133 134 if (bytesRead > 0) { 135 /* confirm that rcvBuf1 = sendBuf1 */ 136 if ((bytesRead != (PRInt32)PL_strlen(sendBuf1) + 1) || 137 (strncmp(sendBuf1, rcvBuf1, bytesRead) != 0)) { 138 testError("Receive buffer mismatch\n"); 139 } 140 141 serverState = SERVER_SEND2; 142 keepGoing = PKIX_TRUE; 143 } else { 144 serverState = SERVER_POLL1; 145 } 146 break; 147 case SERVER_POLL1: 148 subTest("SERVER_POLL1"); 149 PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->pollCallback(rendezvousSock, NULL, &bytesRead, plContext)); 150 151 if (bytesRead > 0) { 152 /* confirm that rcvBuf1 = sendBuf1 */ 153 if ((bytesRead != (PRInt32)PL_strlen(sendBuf1) + 1) || 154 (strncmp(sendBuf1, rcvBuf1, bytesRead) != 0)) { 155 testError("Receive buffer mismatch\n"); 156 } 157 158 serverState = SERVER_SEND2; 159 keepGoing = PKIX_TRUE; 160 } 161 break; 162 case SERVER_SEND2: 163 subTest("SERVER_SEND2"); 164 PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->sendCallback(rendezvousSock, 165 sendBuf2, 166 strlen(sendBuf2) + 167 1, 168 &bytesWritten, 169 plContext)); 170 if (bytesWritten > 0) { 171 serverState = SERVER_RECV3; 172 } else { 173 serverState = SERVER_POLL2; 174 } 175 break; 176 case SERVER_POLL2: 177 subTest("SERVER_POLL2"); 178 PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->pollCallback(rendezvousSock, &bytesWritten, NULL, plContext)); 179 if (bytesWritten > 0) { 180 serverState = SERVER_RECV3; 181 } 182 break; 183 case SERVER_RECV3: 184 subTest("SERVER_RECV3"); 185 PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->recvCallback(rendezvousSock, 186 rcvBuf1, 187 sizeof(rcvBuf1), 188 &bytesRead, 189 plContext)); 190 191 if (bytesRead > 0) { 192 serverState = SERVER_SEND4; 193 keepGoing = PKIX_TRUE; 194 } else { 195 serverState = SERVER_POLL3; 196 } 197 break; 198 case SERVER_POLL3: 199 subTest("SERVER_POLL3"); 200 PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->pollCallback(rendezvousSock, NULL, &bytesRead, plContext)); 201 if (bytesRead > 0) { 202 serverState = SERVER_SEND4; 203 keepGoing = PKIX_TRUE; 204 } 205 break; 206 case SERVER_SEND4: 207 subTest("SERVER_SEND4"); 208 PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->sendCallback(rendezvousSock, 209 sendBuf4, 210 strlen(sendBuf4) + 211 1, 212 &bytesWritten, 213 plContext)); 214 215 if (bytesWritten > 0) { 216 PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->shutdownCallback(rendezvousSock, plContext)); 217 PKIX_TEST_DECREF_BC(sSock); 218 PKIX_TEST_DECREF_BC(rendezvousSock); 219 serverState = SERVER_DONE; 220 } else { 221 serverState = SERVER_POLL4; 222 } 223 break; 224 case SERVER_POLL4: 225 subTest("SERVER_POLL4"); 226 PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->pollCallback(rendezvousSock, &bytesWritten, NULL, plContext)); 227 if (bytesWritten > 0) { 228 PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->shutdownCallback(rendezvousSock, plContext)); 229 PKIX_TEST_DECREF_BC(sSock); 230 PKIX_TEST_DECREF_BC(rendezvousSock); 231 serverState = SERVER_DONE; 232 } 233 break; 234 case SERVER_DONE: 235 default: 236 subTest("SERVER_DONE"); 237 break; 238 } 239 240 cleanup: 241 242 PKIX_TEST_RETURN(); 243 244 return (keepGoing); 245 } 246 247 static PKIX_Boolean 248 client() 249 { 250 PKIX_Boolean keepGoing = PKIX_FALSE; 251 PKIX_Int32 bytesRead = 0; 252 PKIX_Int32 bytesWritten = 0; 253 PRErrorCode cStat = 0; 254 255 /* At 2 seconds each cycle, this should suffice! */ 256 PKIX_UInt32 giveUpCount = 10; 257 258 PKIX_TEST_STD_VARS(); 259 260 switch (clientState) { 261 case CLIENT_WAITFORCONNECT: 262 subTest("CLIENT_WAITFORCONNECT"); 263 clientState = CLIENT_FAILED; 264 PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->connectcontinueCallback(cSock, &cStat, plContext)); 265 if (cStat == 0) { 266 clientState = CLIENT_SEND1; 267 keepGoing = PKIX_TRUE; 268 } else { 269 clientState = CLIENT_WAITFORCONNECT; 270 if (--giveUpCount == 0) { 271 testError("Client unable to connect"); 272 } 273 } 274 break; 275 case CLIENT_SEND1: 276 subTest("CLIENT_SEND1"); 277 clientState = CLIENT_FAILED; 278 PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->sendCallback(cSock, 279 sendBuf1, 280 strlen(sendBuf1) + 281 1, 282 &bytesWritten, 283 plContext)); 284 if (bytesWritten > 0) { 285 clientState = CLIENT_RECV2; 286 } else { 287 clientState = CLIENT_POLL1; 288 } 289 break; 290 case CLIENT_POLL1: 291 subTest("CLIENT_POLL1"); 292 clientState = CLIENT_FAILED; 293 PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->pollCallback(cSock, &bytesWritten, NULL, plContext)); 294 if (bytesWritten > 0) { 295 clientState = CLIENT_RECV2; 296 } else { 297 clientState = CLIENT_POLL1; 298 } 299 break; 300 case CLIENT_RECV2: 301 subTest("CLIENT_RECV2"); 302 clientState = CLIENT_FAILED; 303 PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->recvCallback(cSock, 304 rcvBuf2, 305 sizeof(rcvBuf2), 306 &bytesRead, 307 plContext)); 308 309 if (bytesRead > 0) { 310 /* confirm that rcvBuf2 = sendBuf2 */ 311 if ((bytesRead != (PRInt32)PL_strlen(sendBuf2) + 1) || 312 (strncmp(sendBuf2, rcvBuf2, bytesRead) != 0)) { 313 testError("Receive buffer mismatch\n"); 314 } 315 clientState = CLIENT_SEND3; 316 keepGoing = PKIX_TRUE; 317 } else { 318 clientState = CLIENT_POLL2; 319 } 320 break; 321 case CLIENT_POLL2: 322 subTest("CLIENT_POLL2"); 323 clientState = CLIENT_FAILED; 324 PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->pollCallback(cSock, NULL, &bytesRead, plContext)); 325 if (bytesRead > 0) { 326 /* confirm that rcvBuf2 = sendBuf2 */ 327 if ((bytesRead != (PRInt32)PL_strlen(sendBuf2) + 1) || 328 (strncmp(sendBuf2, rcvBuf2, bytesRead) != 0)) { 329 testError("Receive buffer mismatch\n"); 330 } 331 clientState = CLIENT_SEND3; 332 } else { 333 clientState = CLIENT_POLL2; 334 } 335 break; 336 case CLIENT_SEND3: 337 subTest("CLIENT_SEND3"); 338 clientState = CLIENT_FAILED; 339 PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->sendCallback(cSock, 340 sendBuf3, 341 strlen(sendBuf3) + 342 1, 343 &bytesWritten, 344 plContext)); 345 346 if (bytesWritten > 0) { 347 clientState = CLIENT_RECV4; 348 } else { 349 clientState = CLIENT_POLL3; 350 } 351 break; 352 case CLIENT_POLL3: 353 subTest("CLIENT_POLL3"); 354 clientState = CLIENT_FAILED; 355 PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->pollCallback(cSock, &bytesWritten, NULL, plContext)); 356 if (bytesWritten > 0) { 357 clientState = CLIENT_RECV4; 358 } else { 359 clientState = CLIENT_POLL3; 360 } 361 break; 362 case CLIENT_RECV4: 363 subTest("CLIENT_RECV4"); 364 clientState = CLIENT_FAILED; 365 PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->recvCallback(cSock, 366 rcvBuf2, 367 sizeof(rcvBuf2), 368 &bytesRead, 369 plContext)); 370 371 if (bytesRead > 0) { 372 PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->shutdownCallback(cSock, plContext)); 373 PKIX_TEST_DECREF_BC(cSock); 374 clientState = CLIENT_DONE; 375 } else { 376 clientState = CLIENT_POLL4; 377 } 378 break; 379 case CLIENT_POLL4: 380 subTest("CLIENT_POLL4"); 381 clientState = CLIENT_FAILED; 382 PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->pollCallback(cSock, NULL, &bytesRead, plContext)); 383 if (bytesRead > 0) { 384 PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->shutdownCallback(cSock, plContext)); 385 PKIX_TEST_DECREF_BC(cSock); 386 clientState = CLIENT_DONE; 387 } else { 388 clientState = CLIENT_POLL4; 389 } 390 break; 391 case CLIENT_DONE: 392 default: 393 subTest("CLIENT_DONE"); 394 break; 395 } 396 397 cleanup: 398 399 PKIX_TEST_RETURN(); 400 401 return (keepGoing); 402 } 403 404 static void 405 dispatcher() 406 { 407 PKIX_Boolean keepGoing = PKIX_FALSE; 408 409 PKIX_TEST_STD_VARS(); 410 411 do { 412 if (serverState < SERVER_DONE) { 413 do { 414 keepGoing = server(); 415 } while (keepGoing == PKIX_TRUE); 416 } 417 if (clientState < CLIENT_DONE) { 418 do { 419 keepGoing = client(); 420 } while (keepGoing == PKIX_TRUE); 421 } 422 do_other_work(); 423 424 } while ((serverState < SERVER_DONE) || (clientState < CLIENT_DONE)); 425 426 PKIX_TEST_RETURN(); 427 } 428 429 int 430 test_socket(int argc, char *argv[]) 431 { 432 433 int j = 0; 434 PKIX_UInt32 actualMinorVersion; 435 char buf[PR_NETDB_BUF_SIZE]; 436 char *serverName = NULL; 437 char *sepPtr = NULL; 438 PRHostEnt hostent; 439 PRUint16 portNum = 0; 440 PRStatus prstatus = PR_FAILURE; 441 PRErrorCode cStat = 0; 442 void *ipaddr = NULL; 443 PKIX_Error *bindError = NULL; 444 PRIntn hostenum; 445 446 PKIX_TEST_STD_VARS(); 447 448 startTests("Socket"); 449 450 PKIX_TEST_EXPECT_NO_ERROR( 451 PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext)); 452 453 if (argc != (j + 2)) { 454 printUsage(argv[0]); 455 pkixTestErrorMsg = "Missing command line argument."; 456 goto cleanup; 457 } 458 459 serverName = argv[j + 1]; 460 461 subTest("Using pkix_pl_Socket_CreateByName"); 462 463 PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_CreateByName(PKIX_TRUE, timeout, serverName, &cStat, &sSock, plContext)); 464 465 PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_GetCallbackList(sSock, &sCallbackList, plContext)); 466 467 PKIX_TEST_EXPECT_NO_ERROR(sCallbackList->listenCallback(sSock, backlog, plContext)); 468 469 serverState = SERVER_LISTENING; 470 471 PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_CreateByName(PKIX_FALSE, timeout, serverName, &cStat, &cSock, plContext)); 472 473 PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_GetCallbackList(cSock, &cCallbackList, plContext)); 474 475 if ((timeout == 0) && (cStat == PR_IN_PROGRESS_ERROR)) { 476 clientState = CLIENT_WAITFORCONNECT; 477 } else { 478 clientState = CLIENT_SEND1; 479 } 480 481 dispatcher(); 482 483 subTest("Using pkix_pl_Socket_Create"); 484 485 sepPtr = strchr(serverName, ':'); 486 /* First strip off the portnum, if present, from the end of the name */ 487 if (sepPtr) { 488 *sepPtr++ = '\0'; 489 portNum = (PRUint16)atoi(sepPtr); 490 } else { 491 portNum = (PRUint16)LDAP_PORT; 492 } 493 /* 494 * The hostname may be a fully-qualified name. Just 495 * use the leftmost component in our lookup. 496 */ 497 sepPtr = strchr(serverName, '.'); 498 if (sepPtr) { 499 *sepPtr++ = '\0'; 500 } 501 prstatus = PR_GetHostByName(serverName, buf, sizeof(buf), &hostent); 502 503 if ((prstatus != PR_SUCCESS) || (hostent.h_length != 4)) { 504 printUsage(argv[0]); 505 pkixTestErrorMsg = 506 "PR_GetHostByName rejects command line argument."; 507 goto cleanup; 508 } 509 510 serverNetAddr.inet.family = PR_AF_INET; 511 serverNetAddr.inet.port = PR_htons(portNum); 512 serverNetAddr.inet.ip = PR_htonl(PR_INADDR_ANY); 513 514 hostenum = PR_EnumerateHostEnt(0, &hostent, portNum, &clientNetAddr); 515 if (hostenum == -1) { 516 pkixTestErrorMsg = 517 "PR_EnumerateHostEnt failed."; 518 goto cleanup; 519 } 520 521 backlog = 5; 522 523 /* timeout = PR_INTERVAL_NO_TIMEOUT; */ 524 /* timeout = 0; nonblocking */ 525 timeout = 0; 526 527 bindError = pkix_pl_Socket_Create(PKIX_TRUE, timeout, &serverNetAddr, &cStat, &sSock, plContext); 528 529 /* If PR_Bind can't handle INADDR_ANY, try it with the real name */ 530 if (bindError) { 531 PKIX_TEST_DECREF_BC(bindError); 532 serverNetAddr.inet.ip = PR_htonl(*(PRUint32 *)ipaddr); 533 534 PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_Create(PKIX_TRUE, 535 timeout, 536 &serverNetAddr, 537 &cStat, 538 &sSock, 539 plContext)); 540 } 541 542 PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_GetCallbackList(sSock, &sCallbackList, plContext)); 543 544 PKIX_TEST_EXPECT_NO_ERROR(sCallbackList->listenCallback(sSock, backlog, plContext)); 545 546 serverState = SERVER_LISTENING; 547 548 PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_Create(PKIX_FALSE, timeout, &clientNetAddr, &cStat, &cSock, plContext)); 549 550 PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_GetCallbackList(cSock, &cCallbackList, plContext)); 551 552 if ((timeout == 0) && (cStat == PR_IN_PROGRESS_ERROR)) { 553 clientState = CLIENT_WAITFORCONNECT; 554 } else { 555 clientState = CLIENT_SEND1; 556 } 557 558 dispatcher(); 559 560 cleanup: 561 562 PKIX_TEST_DECREF_AC(sSock); 563 PKIX_TEST_DECREF_AC(cSock); 564 PKIX_TEST_DECREF_AC(rendezvousSock); 565 566 PKIX_TEST_RETURN(); 567 568 endTests("Socket"); 569 570 return (0); 571 }