pkix_pl_socket.c (54293B)
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/. */ 4 /* 5 * pkix_pl_socket.c 6 * 7 * Socket Function Definitions 8 * 9 */ 10 11 /* 12 * If Socket Tracing is active, messages sent and received will be 13 * timestamped and dumped (to stdout) in standard hex-dump format. E.g., 14 * 15 * 1116612359156140: 16 * 28F0: 48 65 6C 6C 6F 2C 20 77 6F 72 6C 64 21 00 Hello, world!. 17 * 18 * The timestamp is not formatted to be meaningful except as an increasing 19 * value of seconds.microseconds, which is good enough to correlate two 20 * sides of a message exchange and to figure durations. 21 * 22 * Code to perform Socket tracing will be compiled in if PKIX_SOCKETTRACE 23 * is defined, but that doesn't mean socket tracing is active. Tracing also 24 * requires that the Boolean socketTraceFlag is set to PKIX_TRUE. That is 25 * the default value, but it can be overridden by using the debugger to 26 * change its value -- allowing tracing to be turned on and off at various 27 * breakpoints -- or by setting the environment variable SOCKETTRACE. A 28 * value of 1 sets socketTraceFlag to PKIX_TRUE (tracing on), and any other 29 * value sets socketTraceFlag to PKIX_FALSE (tracing off). The environment 30 * value is checked during system initialization. 31 */ 32 #ifndef BUILD_OPT 33 #define PKIX_SOCKETTRACE 1 34 #endif 35 36 #ifdef PKIX_SOCKETDEBUG 37 #define PKIX_SOCKETTRACE 1 38 #endif 39 40 #include "pkix_pl_socket.h" 41 42 /* --Private-Socket-Functions---------------------------------- */ 43 44 #ifdef PKIX_SOCKETTRACE 45 static PKIX_Boolean socketTraceFlag = PKIX_FALSE; 46 47 /* 48 * FUNCTION: pkix_pl_socket_timestamp 49 * DESCRIPTION: 50 * 51 * This functions prints to stdout the time of day, as obtained from the 52 * system function gettimeofday, as seconds.microseconds. Its resolution 53 * is whatever the system call provides. 54 * 55 * PARAMETERS: 56 * none 57 * THREAD SAFETY: 58 * Thread Safe (see Thread Safety definitions in Programmer's Guide) 59 * RETURNS: 60 * none 61 */ 62 static void pkix_pl_socket_timestamp() { 63 PRInt64 prTime; 64 prTime = PR_Now(); 65 /* We shouldn't use PR_ALTERNATE_INT64_TYPEDEF, but nor can we use PRId64 */ 66 #if PR_BYTES_PER_LONG == 8 && !defined(PR_ALTERNATE_INT64_TYPEDEF) 67 printf("%ld:\n", prTime); 68 #else 69 printf("%lld:\n", prTime); 70 #endif 71 } 72 73 /* 74 * FUNCTION: pkix_pl_socket_hexDigit 75 * DESCRIPTION: 76 * 77 * This functions prints to stdout the byte "byteVal" as two hex digits. 78 * 79 * PARAMETERS: 80 * "byteVal" 81 * The value to be printed. 82 * THREAD SAFETY: 83 * Thread Safe (see Thread Safety definitions in Programmer's Guide) 84 * RETURNS: 85 * none 86 */ 87 static void pkix_pl_socket_hexDigit(char byteVal) { 88 int n = 0; 89 char cHi = '\0'; 90 char cLow = '\0'; 91 n = ((byteVal >> 4) & 0xf); 92 if (n > 9) { 93 cHi = (char) ((n - 10) + 'A'); 94 } else { 95 cHi = (char) (n + '0'); 96 } 97 n = byteVal & 0xf; 98 if (n > 9) { 99 cLow = (char) ((n - 10) + 'A'); 100 } else { 101 cLow = (char) (n + '0'); 102 } 103 (void) printf("%c%c", cHi, cLow); 104 } 105 106 /* 107 * FUNCTION: pkix_pl_socket_linePrefix 108 * DESCRIPTION: 109 * 110 * This functions prints to stdout the address provided by "addr" as four 111 * hexadecimal digits followed by a colon and a space. 112 * 113 * PARAMETERS: 114 * "addr" 115 * The address to be printed 116 * none 117 * THREAD SAFETY: 118 * Thread Safe (see Thread Safety definitions in Programmer's Guide) 119 * RETURNS: 120 * none 121 */ 122 static void pkix_pl_socket_linePrefix(PKIX_UInt32 addr) { 123 pkix_pl_socket_hexDigit((char)((addr >> 8) & 0xff)); 124 pkix_pl_socket_hexDigit((char)(addr & 0xff)); 125 (void) printf(": "); 126 } 127 128 /* 129 * FUNCTION: pkix_pl_socket_traceLine 130 * DESCRIPTION: 131 * 132 * This functions prints to stdout the sixteen bytes beginning at the 133 * address pointed to by "ptr". The bytes are printed as sixteen pairs 134 * of hexadecimal characters followed by an ascii interpretation, in which 135 * characters from 0x20 to 0x7d are shown as their ascii equivalents, and 136 * other values are represented as periods. 137 * 138 * PARAMETERS: 139 * "ptr" 140 * The address of the first of the bytes to be printed 141 * THREAD SAFETY: 142 * Thread Safe (see Thread Safety definitions in Programmer's Guide) 143 * RETURNS: 144 * none 145 */ 146 static void pkix_pl_socket_traceLine(char *ptr) { 147 PKIX_UInt32 i = 0; 148 pkix_pl_socket_linePrefix((PKIX_UInt32)((char *)ptr - (char *)NULL)); 149 for (i = 0; i < 16; i++) { 150 printf(" "); 151 pkix_pl_socket_hexDigit(ptr[i]); 152 if (i == 7) { 153 printf(" "); 154 } 155 } 156 printf(" "); 157 for (i = 0; i < 16; i++) { 158 if ((ptr[i] < ' ') || (ptr[i] > '}')) { 159 printf("."); 160 } else { 161 printf("%c", ptr[i]); 162 } 163 } 164 printf("\n"); 165 } 166 167 /* 168 * FUNCTION: pkix_pl_socket_tracePartialLine 169 * DESCRIPTION: 170 * 171 * This functions prints to stdout the number of bytes given by "nBytes", 172 * beginning at the address pointed to by "ptr". The bytes are printed as 173 * pairs of hexadecimal characters followed by an ascii interpretation, in 174 * which characters from 0x20 to 0x7d are shown as their ascii equivalents, 175 * and other values are represented as periods. 176 * 177 * PARAMETERS: 178 * "ptr" 179 * The address of the first of the bytes to be printed 180 * "nBytes" 181 * The Int32 value giving the number of bytes to be printed. If "nBytes" 182 * is greater than sixteen, the results will be unattractive. 183 * none 184 * THREAD SAFETY: 185 * Thread Safe (see Thread Safety definitions in Programmer's Guide) 186 * RETURNS: 187 * none 188 */ 189 static void pkix_pl_socket_tracePartialLine(char *ptr, PKIX_UInt32 nBytes) { 190 PKIX_UInt32 i = 0; 191 if (nBytes > 0) { 192 pkix_pl_socket_linePrefix((PKIX_UInt32)((char *)ptr - (char *)NULL)); 193 } 194 for (i = 0; i < nBytes; i++) { 195 printf(" "); 196 pkix_pl_socket_hexDigit(ptr[i]); 197 if (i == 7) { 198 printf(" "); 199 } 200 } 201 for (i = nBytes; i < 16; i++) { 202 printf(" "); 203 if (i == 7) { 204 printf(" "); 205 } 206 } 207 printf(" "); 208 for (i = 0; i < nBytes; i++) { 209 if ((ptr[i] < ' ') || (ptr[i] > '}')) { 210 printf("."); 211 } else { 212 printf("%c", ptr[i]); 213 } 214 } 215 printf("\n"); 216 } 217 218 /* 219 * FUNCTION: pkix_pl_socket_tracebuff 220 * DESCRIPTION: 221 * 222 * This functions prints to stdout the number of bytes given by "nBytes", 223 * beginning with the byte pointed to by "buf". The output is preceded by 224 * a timestamp, and each group of sixteen (and a remainder, if any) is 225 * preceded by its address. The contents are shown in hexadecimal and as 226 * ascii characters. If "nBytes" is zero, the timestamp and starting 227 * address are displayed. 228 * 229 * PARAMETERS: 230 * "buf" 231 * The starting address of the bytes to be printed 232 * "nBytes" 233 * The number of bytes to be printed 234 * THREAD SAFETY: 235 * Thread Safe (see Thread Safety definitions in Programmer's Guide) 236 * RETURNS: 237 * none 238 */ 239 void pkix_pl_socket_tracebuff(void *buf, PKIX_UInt32 nBytes) { 240 PKIX_UInt32 bytesRemaining = nBytes; 241 PKIX_UInt32 offset = 0; 242 char *bufptr = (char *)buf; 243 244 if (socketTraceFlag == PKIX_FALSE) return; 245 246 pkix_pl_socket_timestamp(); 247 /* 248 * Special case: if called with length of zero, just do address 249 */ 250 if (nBytes == 0) { 251 pkix_pl_socket_linePrefix((PKIX_UInt32)((char *)buf - (char *)NULL)); 252 printf("\n"); 253 } else { 254 while (bytesRemaining >= 16) { 255 pkix_pl_socket_traceLine(&bufptr[offset]); 256 bytesRemaining -= 16; 257 offset += 16; 258 } 259 pkix_pl_socket_tracePartialLine 260 (&bufptr[offset], bytesRemaining); 261 } 262 } 263 264 #endif 265 266 /* 267 * FUNCTION: pkix_pl_Socket_SetNonBlocking 268 * DESCRIPTION: 269 * 270 * This functions sets the socket represented by the PRFileDesc "fileDesc" 271 * to nonblocking mode. 272 * 273 * PARAMETERS: 274 * "fileDesc" 275 * The address of the PRFileDesc whose I/O mode is to be set 276 * non-blocking. Must be non-NULL. 277 * "plContext" 278 * Platform-specific context pointer 279 * THREAD SAFETY: 280 * Thread Safe (see Thread Safety definitions in Programmer's Guide) 281 * RETURNS: 282 * none 283 */ 284 static PKIX_Error * 285 pkix_pl_Socket_SetNonBlocking( 286 PRFileDesc *fileDesc, 287 void *plContext) 288 { 289 PRStatus rv = PR_FAILURE; 290 PRSocketOptionData sockOptionData; 291 292 PKIX_ENTER(SOCKET, "pkix_pl_Socket_SetNonBlocking"); 293 PKIX_NULLCHECK_ONE(fileDesc); 294 295 sockOptionData.option = PR_SockOpt_Nonblocking; 296 sockOptionData.value.non_blocking = PR_TRUE; 297 298 PKIX_PL_NSSCALLRV(SOCKET, rv, fileDesc->methods->setsocketoption, 299 (fileDesc, &sockOptionData)); 300 301 if (rv != PR_SUCCESS) { 302 PKIX_ERROR(PKIX_UNABLETOSETSOCKETTONONBLOCKING); 303 } 304 cleanup: 305 306 PKIX_RETURN(SOCKET); 307 } 308 309 /* 310 * FUNCTION: pkix_pl_Socket_CreateClient 311 * DESCRIPTION: 312 * 313 * This functions creates a client socket for the PKIX_PL_Socket pointed to 314 * by "socket". If "socket" was created with a timeout value of zero, the 315 * client socket is set to use nonblocking I/O. 316 * 317 * PARAMETERS: 318 * "socket" 319 * The address of the Socket for which a client socket is to be 320 * created. Must be non-NULL. 321 * "plContext" 322 * Platform-specific context pointer 323 * THREAD SAFETY: 324 * Thread Safe (see Thread Safety definitions in Programmer's Guide) 325 * RETURNS: 326 * none 327 */ 328 329 static PKIX_Error * 330 pkix_pl_Socket_CreateClient( 331 PKIX_PL_Socket *socket, 332 void *plContext) 333 { 334 #ifdef PKIX_SOCKETDEBUG 335 PRErrorCode errorcode = 0; 336 #endif 337 PRFileDesc *mySock = NULL; 338 339 PKIX_ENTER(SOCKET, "pkix_pl_Socket_CreateClient"); 340 PKIX_NULLCHECK_ONE(socket); 341 342 PKIX_PL_NSSCALLRV(SOCKET, mySock, PR_NewTCPSocket, ()); 343 if (!mySock) { 344 #ifdef PKIX_SOCKETDEBUG 345 errorcode = PR_GetError(); 346 printf 347 ("pkix_pl_Socket_CreateClient: %s\n", 348 PR_ErrorToString(errorcode, PR_LANGUAGE_EN)); 349 #endif 350 PKIX_ERROR(PKIX_PRNEWTCPSOCKETFAILED); 351 } 352 353 #ifdef PKIX_SOCKETDEBUG 354 printf("Created socket, PRFileDesc @ %#X\n", mySock); 355 #endif 356 357 socket->clientSock = mySock; 358 socket->status = SOCKET_UNCONNECTED; 359 if (socket->timeout == 0) { 360 PKIX_CHECK(pkix_pl_Socket_SetNonBlocking(mySock, plContext), 361 PKIX_SOCKETSETNONBLOCKINGFAILED); 362 } 363 364 cleanup: 365 366 PKIX_RETURN(SOCKET); 367 } 368 369 /* 370 * FUNCTION: pkix_pl_Socket_CreateServer 371 * DESCRIPTION: 372 * 373 * This functions creates a server socket for the PKIX_PL_Socket pointed to 374 * by "socket". If "socket" was created with a timeout value of zero, the 375 * server socket is set to use nonblocking I/O. 376 * 377 * Warning: there seems to be a problem with operating a server socket in 378 * non-blocking mode. If the server calls Recv prior to a corresponding 379 * Send, the message may be lost. 380 * 381 * PARAMETERS: 382 * "socket" 383 * The address of the Socket for which a server socket is to be 384 * created. Must be non-NULL. 385 * "plContext" 386 * Platform-specific context pointer 387 * THREAD SAFETY: 388 * Thread Safe (see Thread Safety definitions in Programmer's Guide) 389 * RETURNS: 390 * none 391 */ 392 static PKIX_Error * 393 pkix_pl_Socket_CreateServer( 394 PKIX_PL_Socket *socket, 395 void *plContext) 396 { 397 /* #ifdef PKIX_SOCKETDEBUG */ 398 PRErrorCode errorcode = 0; 399 /* #endif */ 400 PRStatus rv = PR_FAILURE; 401 PRFileDesc *serverSock = NULL; 402 PRSocketOptionData sockOptionData; 403 404 PKIX_ENTER(SOCKET, "pkix_pl_Socket_CreateServer"); 405 PKIX_NULLCHECK_ONE(socket); 406 407 PKIX_PL_NSSCALLRV(SOCKET, serverSock, PR_NewTCPSocket, ()); 408 if (!serverSock) { 409 #ifdef PKIX_SOCKETDEBUG 410 errorcode = PR_GetError(); 411 printf 412 ("pkix_pl_Socket_CreateServer: %s\n", 413 PR_ErrorToString(errorcode, PR_LANGUAGE_EN)); 414 #endif 415 PKIX_ERROR(PKIX_PRNEWTCPSOCKETFAILED); 416 } 417 418 socket->serverSock = serverSock; 419 420 #ifdef PKIX_SOCKETDEBUG 421 printf("Created socket, PRFileDesc @ %#X\n", serverSock); 422 #endif 423 424 if (socket->timeout == 0) { 425 PKIX_CHECK(pkix_pl_Socket_SetNonBlocking(serverSock, plContext), 426 PKIX_SOCKETSETNONBLOCKINGFAILED); 427 } 428 429 sockOptionData.option = PR_SockOpt_Reuseaddr; 430 sockOptionData.value.reuse_addr = PR_TRUE; 431 432 PKIX_PL_NSSCALLRV(SOCKET, rv, serverSock->methods->setsocketoption, 433 (serverSock, &sockOptionData)); 434 435 if (rv != PR_SUCCESS) { 436 PKIX_ERROR(PKIX_UNABLETOSETSOCKETTONONBLOCKING); 437 } 438 439 PKIX_PL_NSSCALLRV(SOCKET, rv, PR_Bind, (serverSock, socket->netAddr)); 440 441 if (rv == PR_FAILURE) { 442 /* #ifdef PKIX_SOCKETDEBUG */ 443 errorcode = PR_GetError(); 444 printf 445 ("pkix_pl_Socket_CreateServer: %s\n", 446 PR_ErrorToString(errorcode, PR_LANGUAGE_EN)); 447 /* #endif */ 448 PKIX_ERROR(PKIX_PRBINDFAILED); 449 } 450 451 #ifdef PKIX_SOCKETDEBUG 452 printf("Successful bind!\n"); 453 #endif 454 455 socket->status = SOCKET_BOUND; 456 457 cleanup: 458 459 PKIX_RETURN(SOCKET); 460 } 461 462 /* 463 * FUNCTION: pkix_pl_Socket_Connect 464 * DESCRIPTION: 465 * 466 * This functions performs the connect function for the client socket 467 * specified in "socket", storing the status at "pStatus". 468 * 469 * PARAMETERS: 470 * "socket" 471 * The address of the Socket for which a connect is to be performed. 472 * Must be non-NULL. 473 * "pStatus" 474 * The address at which the connection status is stored. Must be non-NULL. 475 * "plContext" 476 * Platform-specific context pointer 477 * THREAD SAFETY: 478 * Thread Safe (see Thread Safety definitions in Programmer's Guide) 479 * RETURNS: 480 * none 481 */ 482 static PKIX_Error * 483 pkix_pl_Socket_Connect( 484 PKIX_PL_Socket *socket, 485 PRErrorCode *pStatus, 486 void *plContext) 487 { 488 PRStatus rv = PR_FAILURE; 489 PRErrorCode errorcode = 0; 490 491 PKIX_ENTER(SOCKET, "pkix_pl_Socket_Connect"); 492 PKIX_NULLCHECK_TWO(socket, socket->clientSock); 493 494 PKIX_PL_NSSCALLRV(SOCKET, rv, PR_Connect, 495 (socket->clientSock, socket->netAddr, socket->timeout)); 496 497 if (rv == PR_FAILURE) { 498 errorcode = PR_GetError(); 499 *pStatus = errorcode; 500 if (errorcode == PR_IN_PROGRESS_ERROR) { 501 socket->status = SOCKET_CONNECTPENDING; 502 goto cleanup; 503 } else { 504 #ifdef PKIX_SOCKETDEBUG 505 printf 506 ("pkix_pl_Socket_Connect: %s\n", 507 PR_ErrorToString(errorcode, PR_LANGUAGE_EN)); 508 #endif 509 PKIX_ERROR(PKIX_PRCONNECTFAILED); 510 } 511 } 512 513 #ifdef PKIX_SOCKETDEBUG 514 printf("Successful connect!\n"); 515 #endif 516 517 *pStatus = 0; 518 socket->status = SOCKET_CONNECTED; 519 520 cleanup: 521 522 PKIX_RETURN(SOCKET); 523 } 524 525 /* 526 * FUNCTION: pkix_pl_Socket_ConnectContinue 527 * DESCRIPTION: 528 * 529 * This functions continues the connect function for the client socket 530 * specified in "socket", storing the status at "pStatus". It is expected that 531 * the non-blocking connect has returned PR_IN_PROGRESS_ERROR. 532 * 533 * PARAMETERS: 534 * "socket" 535 * The address of the Socket for which a connect is to be continued. 536 * Must be non-NULL. 537 * "pStatus" 538 * The address at which the connection status is stored. Must be non-NULL. 539 * "plContext" 540 * Platform-specific context pointer 541 * THREAD SAFETY: 542 * Thread Safe (see Thread Safety definitions in Programmer's Guide) 543 * RETURNS: 544 * none 545 */ 546 static PKIX_Error * 547 pkix_pl_Socket_ConnectContinue( 548 PKIX_PL_Socket *socket, 549 PRErrorCode *pStatus, 550 void *plContext) 551 { 552 PRStatus rv = PR_FAILURE; 553 PRErrorCode errorcode = 0; 554 PRPollDesc pollDesc; 555 PRInt32 numEvents = 0; 556 557 PKIX_ENTER(SOCKET, "pkix_pl_Socket_ConnectContinue"); 558 PKIX_NULLCHECK_TWO(socket, socket->clientSock); 559 560 pollDesc.fd = socket->clientSock; 561 pollDesc.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT; 562 pollDesc.out_flags = 0; 563 PKIX_PL_NSSCALLRV(SOCKET, numEvents, PR_Poll, (&pollDesc, 1, 0)); 564 if (numEvents < 0) { 565 PKIX_ERROR(PKIX_PRPOLLFAILED); 566 } 567 568 if (numEvents == 0) { 569 *pStatus = PR_IN_PROGRESS_ERROR; 570 goto cleanup; 571 } 572 573 PKIX_PL_NSSCALLRV(SOCKET, rv, PR_ConnectContinue, 574 (socket->clientSock, pollDesc.out_flags)); 575 576 /* 577 * PR_ConnectContinue sometimes lies. It returns PR_SUCCESS 578 * even though the connection is not yet ready. But its deceit 579 * is betrayed by the contents of out_flags! 580 */ 581 if ((rv == PR_SUCCESS) && (pollDesc.out_flags == PR_POLL_ERR)) { 582 *pStatus = PR_IN_PROGRESS_ERROR; 583 goto cleanup; 584 } 585 586 if (rv == PR_FAILURE) { 587 errorcode = PR_GetError(); 588 *pStatus = errorcode; 589 if (errorcode == PR_IN_PROGRESS_ERROR) { 590 goto cleanup; 591 } else { 592 #ifdef PKIX_SOCKETDEBUG 593 printf 594 ("pkix_pl_Socket_ConnectContinue: %s\n", 595 PR_ErrorToString(errorcode, PR_LANGUAGE_EN)); 596 #endif 597 PKIX_ERROR(PKIX_PRCONNECTCONTINUEFAILED); 598 } 599 } 600 601 #ifdef PKIX_SOCKETDEBUG 602 printf("Successful connect!\n"); 603 #endif 604 605 *pStatus = 0; 606 socket->status = SOCKET_CONNECTED; 607 608 cleanup: 609 610 PKIX_RETURN(SOCKET); 611 } 612 613 /* 614 * FUNCTION: pkix_pl_Socket_Destroy 615 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) 616 */ 617 static PKIX_Error * 618 pkix_pl_Socket_Destroy( 619 PKIX_PL_Object *object, 620 void *plContext) 621 { 622 PKIX_PL_Socket *socket = NULL; 623 624 PKIX_ENTER(SOCKET, "pkix_pl_Socket_Destroy"); 625 PKIX_NULLCHECK_ONE(object); 626 627 PKIX_CHECK(pkix_CheckType 628 (object, PKIX_SOCKET_TYPE, plContext), 629 PKIX_OBJECTNOTANSOCKET); 630 631 socket = (PKIX_PL_Socket *)object; 632 633 if (socket->isServer) { 634 if (socket->serverSock) { 635 PR_Close(socket->serverSock); 636 } 637 } else { 638 if (socket->clientSock) { 639 PR_Close(socket->clientSock); 640 } 641 } 642 643 cleanup: 644 645 PKIX_RETURN(SOCKET); 646 } 647 648 /* 649 * FUNCTION: pkix_pl_Socket_Hashcode 650 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) 651 */ 652 static PKIX_Error * 653 pkix_pl_Socket_Hashcode( 654 PKIX_PL_Object *object, 655 PKIX_UInt32 *pHashcode, 656 void *plContext) 657 { 658 PKIX_PL_Socket *socket = NULL; 659 660 PKIX_ENTER(SOCKET, "pkix_pl_Socket_Hashcode"); 661 PKIX_NULLCHECK_TWO(object, pHashcode); 662 663 PKIX_CHECK(pkix_CheckType(object, PKIX_SOCKET_TYPE, plContext), 664 PKIX_OBJECTNOTSOCKET); 665 666 socket = (PKIX_PL_Socket *)object; 667 668 *pHashcode = (((socket->timeout << 3) + 669 (socket->netAddr->inet.family << 3)) + 670 (*((PKIX_UInt32 *)&(socket->netAddr->inet.ip)))) + 671 socket->netAddr->inet.port; 672 673 cleanup: 674 675 PKIX_RETURN(SOCKET); 676 } 677 678 /* 679 * FUNCTION: pkix_pl_Socket_Equals 680 * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h) 681 */ 682 static PKIX_Error * 683 pkix_pl_Socket_Equals( 684 PKIX_PL_Object *firstObject, 685 PKIX_PL_Object *secondObject, 686 PKIX_Int32 *pResult, 687 void *plContext) 688 { 689 PKIX_PL_Socket *firstSocket = NULL; 690 PKIX_PL_Socket *secondSocket = NULL; 691 692 PKIX_ENTER(SOCKET, "pkix_pl_Socket_Equals"); 693 PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); 694 695 *pResult = PKIX_FALSE; 696 697 PKIX_CHECK(pkix_CheckTypes 698 (firstObject, secondObject, PKIX_SOCKET_TYPE, plContext), 699 PKIX_OBJECTNOTSOCKET); 700 701 firstSocket = (PKIX_PL_Socket *)firstObject; 702 secondSocket = (PKIX_PL_Socket *)secondObject; 703 704 if (firstSocket->timeout != secondSocket->timeout) { 705 goto cleanup; 706 } 707 708 if (firstSocket->netAddr == secondSocket->netAddr) { 709 *pResult = PKIX_TRUE; 710 goto cleanup; 711 } 712 713 if ((firstSocket->netAddr->inet.family != 714 secondSocket->netAddr->inet.family) || 715 (*((PKIX_UInt32 *)&(firstSocket->netAddr->inet.ip)) != 716 *((PKIX_UInt32 *)&(secondSocket->netAddr->inet.ip))) || 717 (firstSocket->netAddr->inet.port != 718 secondSocket->netAddr->inet.port)) { 719 720 goto cleanup; 721 722 } 723 724 *pResult = PKIX_TRUE; 725 726 cleanup: 727 728 PKIX_RETURN(SOCKET); 729 } 730 731 /* 732 * FUNCTION: pkix_pl_Socket_RegisterSelf 733 * 734 * DESCRIPTION: 735 * Registers PKIX_PL_SOCKET_TYPE and its related 736 * functions with systemClasses[] 737 * 738 * THREAD SAFETY: 739 * Not Thread Safe - for performance and complexity reasons 740 * 741 * Since this function is only called by PKIX_PL_Initialize, which should 742 * only be called once, it is acceptable that this function is not 743 * thread-safe. 744 */ 745 PKIX_Error * 746 pkix_pl_Socket_RegisterSelf(void *plContext) 747 { 748 extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; 749 pkix_ClassTable_Entry entry; 750 751 PKIX_ENTER(SOCKET, "pkix_pl_Socket_RegisterSelf"); 752 753 entry.description = "Socket"; 754 entry.objCounter = 0; 755 entry.typeObjectSize = sizeof(PKIX_PL_Socket); 756 entry.destructor = pkix_pl_Socket_Destroy; 757 entry.equalsFunction = pkix_pl_Socket_Equals; 758 entry.hashcodeFunction = pkix_pl_Socket_Hashcode; 759 entry.toStringFunction = NULL; 760 entry.comparator = NULL; 761 entry.duplicateFunction = NULL; 762 763 systemClasses[PKIX_SOCKET_TYPE] = entry; 764 765 #ifdef PKIX_SOCKETTRACE 766 { 767 char *val = NULL; 768 val = PR_GetEnvSecure("SOCKETTRACE"); 769 /* Is SOCKETTRACE set in the environment? */ 770 if ((val != NULL) && (*val != '\0')) { 771 socketTraceFlag = 772 ((*val == '1')?PKIX_TRUE:PKIX_FALSE); 773 } 774 } 775 #endif 776 777 PKIX_RETURN(SOCKET); 778 } 779 780 /* --Public-Socket-Functions----------------------------------- */ 781 782 /* 783 * FUNCTION: pkix_pl_Socket_Listen 784 * DESCRIPTION: 785 * 786 * This functions establishes a listening queue for the server Socket 787 * pointed to by "socket". 788 * 789 * PARAMETERS: 790 * "socket" 791 * The address of the server socket for which the queue is to be 792 * established. Must be non-NULL. 793 * "backlog" 794 * The UInt32 value of the length of the queue to be established. 795 * "plContext" 796 * Platform-specific context pointer 797 * THREAD SAFETY: 798 * Thread Safe (see Thread Safety definitions in Programmer's Guide) 799 * RETURNS: 800 * none 801 */ 802 static PKIX_Error * 803 pkix_pl_Socket_Listen( 804 PKIX_PL_Socket *socket, 805 PKIX_UInt32 backlog, 806 void *plContext) 807 { 808 #ifdef PKIX_SOCKETDEBUG 809 PRErrorCode errorcode = 0; 810 #endif 811 PRStatus rv = PR_FAILURE; 812 813 PKIX_ENTER(SOCKET, "pkix_pl_Socket_Listen"); 814 PKIX_NULLCHECK_TWO(socket, socket->serverSock); 815 816 PKIX_PL_NSSCALLRV(SOCKET, rv, PR_Listen, 817 (socket->serverSock, (PRIntn)backlog)); 818 819 if (rv == PR_FAILURE) { 820 #ifdef PKIX_SOCKETDEBUG 821 errorcode = PR_GetError(); 822 printf 823 ("pkix_pl_Socket_Listen: %s\n", 824 PR_ErrorToString(errorcode, PR_LANGUAGE_EN)); 825 #endif 826 PKIX_ERROR(PKIX_PRLISTENFAILED); 827 } 828 829 #ifdef PKIX_SOCKETDEBUG 830 printf("Successful listen!\n"); 831 #endif 832 833 socket->status = SOCKET_LISTENING; 834 cleanup: 835 836 PKIX_RETURN(SOCKET); 837 } 838 839 /* 840 * FUNCTION: pkix_pl_Socket_Shutdown 841 * DESCRIPTION: 842 * 843 * This functions performs the shutdown of any connections controlled by the 844 * socket pointed to by "socket". 845 * 846 * PARAMETERS: 847 * "socket" 848 * The address of the socket to be shut down. Must be non-NULL. 849 * "plContext" 850 * Platform-specific context pointer 851 * THREAD SAFETY: 852 * Thread Safe (see Thread Safety definitions in Programmer's Guide) 853 * RETURNS: 854 * none 855 */ 856 static PKIX_Error * 857 pkix_pl_Socket_Shutdown( 858 PKIX_PL_Socket *socket, 859 void *plContext) 860 { 861 #ifdef PKIX_SOCKETDEBUG 862 PRErrorCode errorcode = 0; 863 #endif 864 PRStatus rv = PR_FAILURE; 865 PRFileDesc *fileDesc = NULL; 866 867 PKIX_ENTER(SOCKET, "pkix_pl_Socket_Shutdown"); 868 PKIX_NULLCHECK_ONE(socket); 869 870 fileDesc = 871 (socket->isServer)?(socket->serverSock):(socket->clientSock); 872 873 PKIX_PL_NSSCALLRV(SOCKET, rv, PR_Shutdown, 874 (fileDesc, PR_SHUTDOWN_BOTH)); 875 876 if (rv == PR_FAILURE) { 877 #ifdef PKIX_SOCKETDEBUG 878 errorcode = PR_GetError(); 879 printf 880 ("pkix_pl_Socket_Shutdown: %s\n", 881 PR_ErrorToString(errorcode, PR_LANGUAGE_EN)); 882 #endif 883 PKIX_ERROR(PKIX_PRSHUTDOWNFAILED); 884 } 885 socket->status = SOCKET_SHUTDOWN; 886 887 cleanup: 888 889 PKIX_RETURN(SOCKET); 890 } 891 892 /* 893 * FUNCTION: pkix_pl_Socket_Send 894 * DESCRIPTION: 895 * 896 * This functions sends a message using the socket pointed to by "sendSock", 897 * from the buffer pointed to by "buf", of the number of bytes given by 898 * "bytesToWrite", storing the number of bytes actually written at 899 * "pBytesWritten". If "socket" is in non-blocking mode, the send operation 900 * may store -1 at "pBytesWritten" and the write is not complete until a 901 * corresponding pkix_pl_Poll call has indicated its completion by returning 902 * a non-negative value for bytes written. 903 * 904 * PARAMETERS: 905 * "sendSock" 906 * The address of the Socket on which the message is to be sent. Must 907 * be non-NULL. 908 * "buf" 909 * The address of the data to be sent. Must be non-NULL. 910 * "bytesToWrite"" 911 * The UInt32 value indicating the number of bytes to write. 912 * "pBytesWritten" 913 * The address at which the Int32 value indicating the number of bytes 914 * actually written is to be stored. Must be non-NULL. 915 * "plContext" 916 * Platform-specific context pointer 917 * THREAD SAFETY: 918 * Thread Safe (see Thread Safety definitions in Programmer's Guide) 919 * RETURNS: 920 * none 921 */ 922 static PKIX_Error * 923 pkix_pl_Socket_Send( 924 PKIX_PL_Socket *sendSock, 925 void *buf, 926 PKIX_UInt32 bytesToWrite, 927 PKIX_Int32 *pBytesWritten, 928 void *plContext) 929 { 930 PRInt32 bytesWritten = 0; 931 PRErrorCode errorcode = 0; 932 PRFileDesc *fd = NULL; 933 934 PKIX_ENTER(SOCKET, "pkix_pl_Socket_Send"); 935 PKIX_NULLCHECK_TWO(buf, pBytesWritten); 936 937 fd = sendSock->clientSock; 938 939 PKIX_PL_NSSCALLRV(SOCKET, bytesWritten, PR_Send, 940 (fd, buf, (PRInt32)bytesToWrite, 0, sendSock->timeout)); 941 942 if (bytesWritten >= 0) { 943 if (sendSock->status == SOCKET_SENDRCVPENDING) { 944 sendSock->status = SOCKET_RCVPENDING; 945 } else { 946 sendSock->status = SOCKET_CONNECTED; 947 } 948 #ifdef PKIX_SOCKETTRACE 949 pkix_pl_socket_tracebuff(buf, bytesWritten); 950 #endif 951 } else { 952 errorcode = PR_GetError(); 953 if (errorcode != PR_WOULD_BLOCK_ERROR) { 954 #ifdef PKIX_SOCKETDEBUG 955 printf 956 ("pkix_pl_Socket_Send: %s\n", 957 PR_ErrorToString(errorcode, PR_LANGUAGE_EN)); 958 #endif 959 PKIX_ERROR(PKIX_PRSENDFAILED); 960 } 961 962 sendSock->writeBuf = buf; 963 sendSock->writeBufSize = bytesToWrite; 964 if (sendSock->status == SOCKET_RCVPENDING) { 965 sendSock->status = SOCKET_SENDRCVPENDING; 966 } else { 967 sendSock->status = SOCKET_SENDPENDING; 968 } 969 } 970 971 *pBytesWritten = (PKIX_Int32)bytesWritten; 972 973 cleanup: 974 975 PKIX_RETURN(SOCKET); 976 } 977 978 /* 979 * FUNCTION: pkix_pl_Socket_Recv 980 * DESCRIPTION: 981 * 982 * This functions receives a message on the socket pointed to by "rcvSock", 983 * into the buffer pointed to by "buf", of capacity given by "capacity", 984 * storing the number of bytes actually received at "pBytesRead". If "socket" 985 * is in non-blocking mode, the receive operation may store -1 at 986 * "pBytesWritten". In that case the write is not complete until a 987 * corresponding pkix_pl_Poll call has indicated its completion by returning 988 * a non-negative value for bytes read. 989 * 990 * PARAMETERS: 991 * "rcvSock" 992 * The address of the Socket on which the message is to be received. 993 * Must be non-NULL. 994 * "buf" 995 * The address of the buffer into which the message is to be received. 996 * Must be non-NULL. 997 * "capacity" 998 * The UInt32 value of the size of the buffer; that is, the maximum 999 * number of bytes that can be received. 1000 * "pBytesRead" 1001 * The address at which is stored the Int32 value of the number of bytes 1002 * actually received. 1003 * "plContext" 1004 * Platform-specific context pointer 1005 * THREAD SAFETY: 1006 * Thread Safe (see Thread Safety definitions in Programmer's Guide) 1007 * RETURNS: 1008 * none 1009 */ 1010 static PKIX_Error * 1011 pkix_pl_Socket_Recv( 1012 PKIX_PL_Socket *rcvSock, 1013 void *buf, 1014 PKIX_UInt32 capacity, 1015 PKIX_Int32 *pBytesRead, 1016 void *plContext) 1017 { 1018 PRErrorCode errorcode = 0; 1019 PRInt32 bytesRead = 0; 1020 PRFileDesc *fd = NULL; 1021 1022 PKIX_ENTER(SOCKET, "pkix_pl_Socket_Recv"); 1023 PKIX_NULLCHECK_THREE(rcvSock, buf, pBytesRead); 1024 1025 fd = rcvSock->clientSock; 1026 1027 PKIX_PL_NSSCALLRV(SOCKET, bytesRead, PR_Recv, 1028 (fd, buf, (PRInt32)capacity, 0, rcvSock->timeout)); 1029 1030 if (bytesRead > 0) { 1031 if (rcvSock->status == SOCKET_SENDRCVPENDING) { 1032 rcvSock->status = SOCKET_SENDPENDING; 1033 } else { 1034 rcvSock->status = SOCKET_CONNECTED; 1035 } 1036 #ifdef PKIX_SOCKETTRACE 1037 pkix_pl_socket_tracebuff(buf, bytesRead); 1038 #endif 1039 } else if (bytesRead == 0) { 1040 PKIX_ERROR(PKIX_PRRECVREPORTSNETWORKCONNECTIONCLOSED); 1041 } else { 1042 errorcode = PR_GetError(); 1043 if (errorcode != PR_WOULD_BLOCK_ERROR) { 1044 #ifdef PKIX_SOCKETDEBUG 1045 printf 1046 ("pkix_pl_Socket_Recv: %s\n", 1047 PR_ErrorToString(errorcode, PR_LANGUAGE_EN)); 1048 #endif 1049 PKIX_ERROR(PKIX_PRRECVFAILED); 1050 } 1051 rcvSock->readBuf = buf; 1052 rcvSock->readBufSize = capacity; 1053 if (rcvSock->status == SOCKET_SENDPENDING) { 1054 rcvSock->status = SOCKET_SENDRCVPENDING; 1055 } else { 1056 rcvSock->status = SOCKET_RCVPENDING; 1057 } 1058 1059 } 1060 1061 *pBytesRead = (PKIX_Int32)bytesRead; 1062 1063 cleanup: 1064 1065 PKIX_RETURN(SOCKET); 1066 } 1067 1068 /* 1069 * FUNCTION: pkix_pl_Socket_Poll 1070 * DESCRIPTION: 1071 * 1072 * This functions checks for completion of an earlier Send or Recv on the 1073 * socket pointed to by "sock", storing in "pBytesWritten" the number of bytes 1074 * written by a completed Send and in "pBytesRead" the number of bytes 1075 * received in a completed Recv. A value of -1 returned indicates the 1076 * operation has still not completed. A NULL pointer may be supplied for 1077 * "pBytesWritten" to avoid checking for completion of a Send. A NULL pointer 1078 * may be supplied for "pBytesRead" to avoid checking for completion of a Recv. 1079 * 1080 * PARAMETERS: 1081 * "sock" 1082 * The address of the socket for which completions are to be checked. 1083 * "pBytesWritten" 1084 * The address at which the number of bytes written is to be stored, if 1085 * a pending Send has completed. If NULL, Sends are not checked. 1086 * "pBytesRead" 1087 * The address at which the number of bytes read is to be stored, if 1088 * a pending Recv has completed. If NULL, Recvs are not checked. 1089 * "plContext" 1090 * Platform-specific context pointer 1091 * THREAD SAFETY: 1092 * Thread Safe (see Thread Safety definitions in Programmer's Guide) 1093 * RETURNS: 1094 * none 1095 */ 1096 static PKIX_Error * 1097 pkix_pl_Socket_Poll( 1098 PKIX_PL_Socket *sock, 1099 PKIX_Int32 *pBytesWritten, 1100 PKIX_Int32 *pBytesRead, 1101 void *plContext) 1102 { 1103 PRPollDesc pollDesc; 1104 PRInt32 numEvents = 0; 1105 PKIX_Int32 bytesRead = 0; 1106 PKIX_Int32 bytesWritten = 0; 1107 PRErrorCode errorcode = 0; 1108 1109 PKIX_ENTER(SOCKET, "pkix_pl_Socket_Poll"); 1110 PKIX_NULLCHECK_ONE(sock); 1111 1112 pollDesc.fd = sock->clientSock; 1113 pollDesc.in_flags = 0; 1114 pollDesc.out_flags = 0; 1115 1116 if ((pBytesWritten) && 1117 ((sock->status == SOCKET_SENDPENDING) || 1118 (sock->status == SOCKET_SENDRCVPENDING))) { 1119 pollDesc.in_flags = PR_POLL_WRITE; 1120 } 1121 1122 if ((pBytesRead) && 1123 ((sock->status == SOCKET_RCVPENDING) || 1124 (sock->status == SOCKET_SENDRCVPENDING))) { 1125 pollDesc.in_flags |= PR_POLL_READ; 1126 } 1127 1128 PKIX_PL_NSSCALLRV(SOCKET, numEvents, PR_Poll, (&pollDesc, 1, 0)); 1129 1130 if (numEvents < 0) { 1131 PKIX_ERROR(PKIX_PRPOLLFAILED); 1132 } else if (numEvents > 0) { 1133 if (pollDesc.out_flags & PR_POLL_WRITE) { 1134 PKIX_CHECK(pkix_pl_Socket_Send 1135 (sock, 1136 sock->writeBuf, 1137 sock->writeBufSize, 1138 &bytesWritten, 1139 plContext), 1140 PKIX_SOCKETSENDFAILED); 1141 *pBytesWritten = (PKIX_Int32)bytesWritten; 1142 if (bytesWritten >= 0) { 1143 sock->writeBuf = NULL; 1144 sock->writeBufSize = 0; 1145 } 1146 } 1147 1148 if (pollDesc.out_flags & PR_POLL_READ) { 1149 PKIX_CHECK(pkix_pl_Socket_Recv 1150 (sock, 1151 sock->readBuf, 1152 sock->readBufSize, 1153 &bytesRead, 1154 plContext), 1155 PKIX_SOCKETRECVFAILED); 1156 *pBytesRead = (PKIX_Int32)bytesRead; 1157 if (bytesRead >= 0) { 1158 sock->readBuf = NULL; 1159 sock->readBufSize = 0; 1160 } 1161 } 1162 } else if (numEvents == 0) { 1163 errorcode = PR_GetError(); 1164 if (errorcode != PR_WOULD_BLOCK_ERROR) { 1165 #ifdef PKIX_SOCKETDEBUG 1166 printf 1167 ("pkix_pl_Socket_Poll: %s\n", 1168 PR_ErrorToString(errorcode, PR_LANGUAGE_EN)); 1169 #endif 1170 PKIX_ERROR(PKIX_PRPOLLFAILED); 1171 } 1172 if (pBytesWritten) { 1173 *pBytesWritten = 0; 1174 } 1175 if (pBytesRead) { 1176 *pBytesRead = 0; 1177 } 1178 } 1179 1180 cleanup: 1181 1182 PKIX_RETURN(SOCKET); 1183 } 1184 1185 /* 1186 * FUNCTION: pkix_pl_Socket_Accept 1187 * DESCRIPTION: 1188 * 1189 * This functions accepts a client connection for the server Socket pointed 1190 * to by "serverSocket", creating a new Socket and storing the result at 1191 * "pRendezvousSocket". If "serverSocket" is in non-blocking mode, this 1192 * function will return NULL if there is no client connection to accept. 1193 * Otherwise this function will block until a connection is available. 1194 * When a client connection is available the new Socket will have the same 1195 * blocking/non-blocking property as "serverSocket". 1196 * 1197 * PARAMETERS: 1198 * "serverSocket" 1199 * The address of the Socket for which a client connection is to be 1200 * accepted. Must be non-NULL. 1201 * "pRendezvousSocket" 1202 * The address at which the created Socket is stored, when a client 1203 * connection is available, or at which NULL is stored, if no connection 1204 * is available for a non-blocking "serverSocket". Must be non-NULL. 1205 * "plContext" 1206 * Platform-specific context pointer 1207 * THREAD SAFETY: 1208 * Thread Safe (see Thread Safety definitions in Programmer's Guide) 1209 * RETURNS: 1210 * none 1211 */ 1212 static PKIX_Error * 1213 pkix_pl_Socket_Accept( 1214 PKIX_PL_Socket *serverSocket, 1215 PKIX_PL_Socket **pRendezvousSocket, 1216 void *plContext) 1217 { 1218 PRErrorCode errorcode = 0; 1219 PRFileDesc *rendezvousSock = NULL; 1220 PRNetAddr *clientAddr = NULL; 1221 PKIX_PL_Socket *newSocket = NULL; 1222 1223 PKIX_ENTER(SOCKET, "pkix_pl_Socket_Accept"); 1224 PKIX_NULLCHECK_TWO(serverSocket, pRendezvousSocket); 1225 1226 PKIX_PL_NSSCALLRV(SOCKET, rendezvousSock, PR_Accept, 1227 (serverSocket->serverSock, clientAddr, serverSocket->timeout)); 1228 1229 if (!rendezvousSock) { 1230 errorcode = PR_GetError(); 1231 if (errorcode != PR_WOULD_BLOCK_ERROR) { 1232 #ifdef PKIX_SOCKETDEBUG 1233 printf 1234 ("pkix_pl_Socket_Accept: %s\n", 1235 PR_ErrorToString(errorcode, PR_LANGUAGE_EN)); 1236 #endif 1237 PKIX_ERROR(PKIX_PRACCEPTFAILED); 1238 } 1239 serverSocket->status = SOCKET_ACCEPTPENDING; 1240 *pRendezvousSocket = NULL; 1241 goto cleanup; 1242 1243 } 1244 1245 #ifdef PKIX_SOCKETDEBUG 1246 printf("Successful accept!\n"); 1247 #endif 1248 1249 PKIX_CHECK(PKIX_PL_Object_Alloc 1250 (PKIX_SOCKET_TYPE, 1251 sizeof (PKIX_PL_Socket), 1252 (PKIX_PL_Object **)&newSocket, 1253 plContext), 1254 PKIX_COULDNOTCREATESOCKETOBJECT); 1255 1256 newSocket->isServer = PKIX_FALSE; 1257 newSocket->timeout = serverSocket->timeout; 1258 newSocket->clientSock = rendezvousSock; 1259 newSocket->serverSock = NULL; 1260 newSocket->netAddr = NULL; 1261 newSocket->status = SOCKET_CONNECTED; 1262 newSocket->callbackList.shutdownCallback = pkix_pl_Socket_Shutdown; 1263 newSocket->callbackList.listenCallback = pkix_pl_Socket_Listen; 1264 newSocket->callbackList.acceptCallback = pkix_pl_Socket_Accept; 1265 newSocket->callbackList.connectcontinueCallback = 1266 pkix_pl_Socket_ConnectContinue; 1267 newSocket->callbackList.sendCallback = pkix_pl_Socket_Send; 1268 newSocket->callbackList.recvCallback = pkix_pl_Socket_Recv; 1269 newSocket->callbackList.pollCallback = pkix_pl_Socket_Poll; 1270 1271 if (serverSocket->timeout == 0) { 1272 PKIX_CHECK(pkix_pl_Socket_SetNonBlocking 1273 (rendezvousSock, plContext), 1274 PKIX_SOCKETSETNONBLOCKINGFAILED); 1275 } 1276 1277 *pRendezvousSocket = newSocket; 1278 1279 cleanup: 1280 1281 PKIX_RETURN(SOCKET); 1282 } 1283 1284 /* 1285 * FUNCTION: pkix_pl_Socket_Create 1286 * DESCRIPTION: 1287 * 1288 * This function creates a new Socket, setting it to be a server or a client 1289 * according to the value of "isServer", setting its timeout value from 1290 * "timeout" and server address from "netAddr", and stores the created Socket 1291 * at "pSocket". 1292 * 1293 * PARAMETERS: 1294 * "isServer" 1295 * The Boolean value indicating if PKIX_TRUE, that a server socket (using 1296 * Bind, Listen, and Accept) is to be created, or if PKIX_FALSE, that a 1297 * client socket (using Connect) is to be created. 1298 * "timeout" 1299 * A PRTimeInterval value to be used for I/O waits for this socket. If 1300 * zero, non-blocking I/O is to be used. 1301 * "netAddr" 1302 * The PRNetAddr to be used for the Bind function, if this is a server 1303 * socket, or for the Connect, if this is a client socket. 1304 * "pSocket" 1305 * The address at which the Socket is to be stored. Must be non-NULL. 1306 * "plContext" 1307 * Platform-specific context pointer. 1308 * THREAD SAFETY: 1309 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 1310 * RETURNS: 1311 * Returns NULL if the function succeeds. 1312 * Returns a Socket Error if the function fails in 1313 * a non-fatal way. 1314 * Returns a Fatal Error if the function fails in an unrecoverable way. 1315 */ 1316 PKIX_Error * 1317 pkix_pl_Socket_Create( 1318 PKIX_Boolean isServer, 1319 PRIntervalTime timeout, 1320 PRNetAddr *netAddr, 1321 PRErrorCode *status, 1322 PKIX_PL_Socket **pSocket, 1323 void *plContext) 1324 { 1325 #ifdef MOZ_PROXY_BYPASS_PROTECTION 1326 PKIX_ERROR(PKIX_PRNEWTCPSOCKETFAILED); 1327 #else 1328 PKIX_PL_Socket *socket = NULL; 1329 1330 PKIX_ENTER(SOCKET, "pkix_pl_Socket_Create"); 1331 PKIX_NULLCHECK_ONE(pSocket); 1332 1333 PKIX_CHECK(PKIX_PL_Object_Alloc 1334 (PKIX_SOCKET_TYPE, 1335 sizeof (PKIX_PL_Socket), 1336 (PKIX_PL_Object **)&socket, 1337 plContext), 1338 PKIX_COULDNOTCREATESOCKETOBJECT); 1339 1340 socket->isServer = isServer; 1341 socket->timeout = timeout; 1342 socket->clientSock = NULL; 1343 socket->serverSock = NULL; 1344 socket->netAddr = netAddr; 1345 1346 socket->callbackList.listenCallback = pkix_pl_Socket_Listen; 1347 socket->callbackList.acceptCallback = pkix_pl_Socket_Accept; 1348 socket->callbackList.connectcontinueCallback = 1349 pkix_pl_Socket_ConnectContinue; 1350 socket->callbackList.sendCallback = pkix_pl_Socket_Send; 1351 socket->callbackList.recvCallback = pkix_pl_Socket_Recv; 1352 socket->callbackList.pollCallback = pkix_pl_Socket_Poll; 1353 socket->callbackList.shutdownCallback = pkix_pl_Socket_Shutdown; 1354 1355 if (isServer) { 1356 PKIX_CHECK(pkix_pl_Socket_CreateServer(socket, plContext), 1357 PKIX_SOCKETCREATESERVERFAILED); 1358 *status = 0; 1359 } else { 1360 socket->timeout = timeout; 1361 PKIX_CHECK(pkix_pl_Socket_CreateClient(socket, plContext), 1362 PKIX_SOCKETCREATECLIENTFAILED); 1363 PKIX_CHECK(pkix_pl_Socket_Connect(socket, status, plContext), 1364 PKIX_SOCKETCONNECTFAILED); 1365 } 1366 1367 *pSocket = socket; 1368 1369 cleanup: 1370 if (PKIX_ERROR_RECEIVED) { 1371 PKIX_DECREF(socket); 1372 } 1373 1374 PKIX_RETURN(SOCKET); 1375 #endif 1376 } 1377 1378 /* 1379 * FUNCTION: pkix_pl_Socket_CreateByName 1380 * DESCRIPTION: 1381 * 1382 * This function creates a new Socket, setting it to be a server or a client 1383 * according to the value of "isServer", setting its timeout value from 1384 * "timeout" and server address and port number from "serverName", and stores 1385 * the status at "pStatus" and the created Socket at "pSocket". 1386 * 1387 * If isServer is PKIX_TRUE, it is attempted to create the socket with an ip 1388 * address of PR_INADDR_ANY. 1389 * 1390 * PARAMETERS: 1391 * "isServer" 1392 * The Boolean value indicating if PKIX_TRUE, that a server socket (using 1393 * Bind, Listen, and Accept) is to be created, or if PKIX_FALSE, that a 1394 * client socket (using Connect) is to be created. 1395 * "timeout" 1396 * A PRTimeInterval value to be used for I/O waits for this socket. If 1397 * zero, non-blocking I/O is to be used. 1398 * "serverName" 1399 * Address of a character string consisting of the server's domain name 1400 * followed by a colon and a port number for the desired socket. 1401 * "pStatus" 1402 * Address at which the PRErrorCode resulting from the create is 1403 * stored. Must be non-NULL. 1404 * "pSocket" 1405 * The address at which the Socket is to be stored. Must be non-NULL. 1406 * "plContext" 1407 * Platform-specific context pointer. 1408 * THREAD SAFETY: 1409 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 1410 * RETURNS: 1411 * Returns NULL if the function succeeds. 1412 * Returns a Socket Error if the function fails in 1413 * a non-fatal way. 1414 * Returns a Fatal Error if the function fails in an unrecoverable way. 1415 */ 1416 PKIX_Error * 1417 pkix_pl_Socket_CreateByName( 1418 PKIX_Boolean isServer, 1419 PRIntervalTime timeout, 1420 char *serverName, 1421 PRErrorCode *pStatus, 1422 PKIX_PL_Socket **pSocket, 1423 void *plContext) 1424 { 1425 #ifdef MOZ_PROXY_BYPASS_PROTECTION 1426 PKIX_ERROR(PKIX_PRNEWTCPSOCKETFAILED); 1427 #else 1428 PRNetAddr netAddr; 1429 PKIX_PL_Socket *socket = NULL; 1430 char *sepPtr = NULL; 1431 PRHostEnt hostent; 1432 PRIntn hostenum; 1433 PRStatus prstatus = PR_FAILURE; 1434 char buf[PR_NETDB_BUF_SIZE]; 1435 PRUint16 portNum = 0; 1436 char *localCopyName = NULL; 1437 1438 PKIX_ENTER(SOCKET, "pkix_pl_Socket_CreateByName"); 1439 PKIX_NULLCHECK_TWO(serverName, pSocket); 1440 1441 localCopyName = PL_strdup(serverName); 1442 1443 sepPtr = strchr(localCopyName, ':'); 1444 /* First strip off the portnum, if present, from the end of the name */ 1445 if (sepPtr) { 1446 *sepPtr++ = '\0'; 1447 portNum = (PRUint16)atoi(sepPtr); 1448 } else { 1449 portNum = (PRUint16)LDAP_PORT; 1450 } 1451 1452 prstatus = PR_GetHostByName(localCopyName, buf, sizeof(buf), &hostent); 1453 1454 if ((prstatus != PR_SUCCESS) || (hostent.h_length != 4)) { 1455 /* 1456 * The hostname may be a fully-qualified name. Try using just 1457 * the leftmost component in our lookup. 1458 */ 1459 sepPtr = strchr(localCopyName, '.'); 1460 if (sepPtr) { 1461 *sepPtr++ = '\0'; 1462 } 1463 prstatus = PR_GetHostByName 1464 (localCopyName, buf, sizeof(buf), &hostent); 1465 1466 if ((prstatus != PR_SUCCESS) || (hostent.h_length != 4)) { 1467 PKIX_ERROR 1468 (PKIX_PRGETHOSTBYNAMEREJECTSHOSTNAMEARGUMENT); 1469 } 1470 } 1471 1472 netAddr.inet.family = PR_AF_INET; 1473 netAddr.inet.port = PR_htons(portNum); 1474 1475 if (isServer) { 1476 1477 netAddr.inet.ip = PR_htonl(PR_INADDR_ANY); 1478 1479 } else { 1480 1481 hostenum = PR_EnumerateHostEnt(0, &hostent, portNum, &netAddr); 1482 if (hostenum == -1) { 1483 PKIX_ERROR(PKIX_PRENUMERATEHOSTENTFAILED); 1484 } 1485 } 1486 1487 PKIX_CHECK(PKIX_PL_Object_Alloc 1488 (PKIX_SOCKET_TYPE, 1489 sizeof (PKIX_PL_Socket), 1490 (PKIX_PL_Object **)&socket, 1491 plContext), 1492 PKIX_COULDNOTCREATESOCKETOBJECT); 1493 1494 socket->isServer = isServer; 1495 socket->timeout = timeout; 1496 socket->clientSock = NULL; 1497 socket->serverSock = NULL; 1498 socket->netAddr = &netAddr; 1499 1500 socket->callbackList.listenCallback = pkix_pl_Socket_Listen; 1501 socket->callbackList.acceptCallback = pkix_pl_Socket_Accept; 1502 socket->callbackList.connectcontinueCallback = 1503 pkix_pl_Socket_ConnectContinue; 1504 socket->callbackList.sendCallback = pkix_pl_Socket_Send; 1505 socket->callbackList.recvCallback = pkix_pl_Socket_Recv; 1506 socket->callbackList.pollCallback = pkix_pl_Socket_Poll; 1507 socket->callbackList.shutdownCallback = pkix_pl_Socket_Shutdown; 1508 1509 if (isServer) { 1510 PKIX_CHECK(pkix_pl_Socket_CreateServer(socket, plContext), 1511 PKIX_SOCKETCREATESERVERFAILED); 1512 *pStatus = 0; 1513 } else { 1514 PKIX_CHECK(pkix_pl_Socket_CreateClient(socket, plContext), 1515 PKIX_SOCKETCREATECLIENTFAILED); 1516 PKIX_CHECK(pkix_pl_Socket_Connect(socket, pStatus, plContext), 1517 PKIX_SOCKETCONNECTFAILED); 1518 } 1519 1520 *pSocket = socket; 1521 1522 cleanup: 1523 PL_strfree(localCopyName); 1524 1525 if (PKIX_ERROR_RECEIVED) { 1526 PKIX_DECREF(socket); 1527 } 1528 1529 PKIX_RETURN(SOCKET); 1530 #endif 1531 } 1532 1533 /* 1534 * FUNCTION: pkix_pl_Socket_CreateByHostAndPort 1535 * DESCRIPTION: 1536 * 1537 * This function creates a new Socket, setting it to be a server or a client 1538 * according to the value of "isServer", setting its timeout value from 1539 * "timeout", host from "hostname", and port number from "portNum", and stores 1540 * the status at "pStatus" and the created Socket at "pSocket". 1541 * 1542 * If isServer is PKIX_TRUE, it is attempted to create the socket with an ip 1543 * address of PR_INADDR_ANY. 1544 * 1545 * PARAMETERS: 1546 * "isServer" 1547 * The Boolean value indicating if PKIX_TRUE, that a server socket (using 1548 * Bind, Listen, and Accept) is to be created, or if PKIX_FALSE, that a 1549 * client socket (using Connect) is to be created. 1550 * "timeout" 1551 * A PRTimeInterval value to be used for I/O waits for this socket. If 1552 * zero, non-blocking I/O is to be used. 1553 * "hostname" 1554 * Address of a character string consisting of the server's domain name. 1555 * "portNum" 1556 * UInt16 value of the port number for the desired socket. 1557 * "pStatus" 1558 * Address at which the PRErrorCode resulting from the create is 1559 * stored. Must be non-NULL. 1560 * "pSocket" 1561 * The address at which the Socket is to be stored. Must be non-NULL. 1562 * "plContext" 1563 * Platform-specific context pointer. 1564 * THREAD SAFETY: 1565 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 1566 * RETURNS: 1567 * Returns NULL if the function succeeds. 1568 * Returns a Socket Error if the function fails in 1569 * a non-fatal way. 1570 * Returns a Fatal Error if the function fails in an unrecoverable way. 1571 */ 1572 PKIX_Error * 1573 pkix_pl_Socket_CreateByHostAndPort( 1574 PKIX_Boolean isServer, 1575 PRIntervalTime timeout, 1576 char *hostname, 1577 PRUint16 portnum, 1578 PRErrorCode *pStatus, 1579 PKIX_PL_Socket **pSocket, 1580 void *plContext) 1581 { 1582 #ifdef MOZ_PROXY_BYPASS_PROTECTION 1583 PKIX_ERROR(PKIX_PRNEWTCPSOCKETFAILED); 1584 #else 1585 PRNetAddr netAddr; 1586 PKIX_PL_Socket *socket = NULL; 1587 char *sepPtr = NULL; 1588 PRHostEnt hostent; 1589 PRIntn hostenum; 1590 PRStatus prstatus = PR_FAILURE; 1591 char buf[PR_NETDB_BUF_SIZE]; 1592 1593 PKIX_ENTER(SOCKET, "pkix_pl_Socket_CreateByHostAndPort"); 1594 PKIX_NULLCHECK_THREE(hostname, pStatus, pSocket); 1595 1596 1597 prstatus = PR_GetHostByName(hostname, buf, sizeof(buf), &hostent); 1598 1599 if ((prstatus != PR_SUCCESS) || (hostent.h_length != 4)) { 1600 /* 1601 * The hostname may be a fully-qualified name. Try using just 1602 * the leftmost component in our lookup. 1603 */ 1604 sepPtr = strchr(hostname, '.'); 1605 if (sepPtr) { 1606 *sepPtr++ = '\0'; 1607 } 1608 prstatus = PR_GetHostByName(hostname, buf, sizeof(buf), &hostent); 1609 1610 if ((prstatus != PR_SUCCESS) || (hostent.h_length != 4)) { 1611 PKIX_ERROR 1612 (PKIX_PRGETHOSTBYNAMEREJECTSHOSTNAMEARGUMENT); 1613 } 1614 } 1615 1616 netAddr.inet.family = PR_AF_INET; 1617 netAddr.inet.port = PR_htons(portnum); 1618 1619 if (isServer) { 1620 1621 netAddr.inet.ip = PR_htonl(PR_INADDR_ANY); 1622 1623 } else { 1624 1625 hostenum = PR_EnumerateHostEnt(0, &hostent, portnum, &netAddr); 1626 if (hostenum == -1) { 1627 PKIX_ERROR(PKIX_PRENUMERATEHOSTENTFAILED); 1628 } 1629 } 1630 1631 PKIX_CHECK(PKIX_PL_Object_Alloc 1632 (PKIX_SOCKET_TYPE, 1633 sizeof (PKIX_PL_Socket), 1634 (PKIX_PL_Object **)&socket, 1635 plContext), 1636 PKIX_COULDNOTCREATESOCKETOBJECT); 1637 1638 socket->isServer = isServer; 1639 socket->timeout = timeout; 1640 socket->clientSock = NULL; 1641 socket->serverSock = NULL; 1642 socket->netAddr = &netAddr; 1643 1644 socket->callbackList.listenCallback = pkix_pl_Socket_Listen; 1645 socket->callbackList.acceptCallback = pkix_pl_Socket_Accept; 1646 socket->callbackList.connectcontinueCallback = 1647 pkix_pl_Socket_ConnectContinue; 1648 socket->callbackList.sendCallback = pkix_pl_Socket_Send; 1649 socket->callbackList.recvCallback = pkix_pl_Socket_Recv; 1650 socket->callbackList.pollCallback = pkix_pl_Socket_Poll; 1651 socket->callbackList.shutdownCallback = pkix_pl_Socket_Shutdown; 1652 1653 if (isServer) { 1654 PKIX_CHECK(pkix_pl_Socket_CreateServer(socket, plContext), 1655 PKIX_SOCKETCREATESERVERFAILED); 1656 *pStatus = 0; 1657 } else { 1658 PKIX_CHECK(pkix_pl_Socket_CreateClient(socket, plContext), 1659 PKIX_SOCKETCREATECLIENTFAILED); 1660 PKIX_CHECK(pkix_pl_Socket_Connect(socket, pStatus, plContext), 1661 PKIX_SOCKETCONNECTFAILED); 1662 } 1663 1664 *pSocket = socket; 1665 1666 cleanup: 1667 if (PKIX_ERROR_RECEIVED) { 1668 PKIX_DECREF(socket); 1669 } 1670 1671 PKIX_RETURN(SOCKET); 1672 #endif 1673 } 1674 1675 /* 1676 * FUNCTION: pkix_pl_Socket_GetCallbackList 1677 */ 1678 PKIX_Error * 1679 pkix_pl_Socket_GetCallbackList( 1680 PKIX_PL_Socket *socket, 1681 PKIX_PL_Socket_Callback **pCallbackList, 1682 void *plContext) 1683 { 1684 PKIX_ENTER(SOCKET, "pkix_pl_Socket_GetCallbackList"); 1685 PKIX_NULLCHECK_TWO(socket, pCallbackList); 1686 1687 *pCallbackList = &(socket->callbackList); 1688 1689 PKIX_RETURN(SOCKET); 1690 } 1691 1692 /* 1693 * FUNCTION: pkix_pl_Socket_GetPRFileDesc 1694 */ 1695 PKIX_Error * 1696 pkix_pl_Socket_GetPRFileDesc( 1697 PKIX_PL_Socket *socket, 1698 PRFileDesc **pDesc, 1699 void *plContext) 1700 { 1701 PKIX_ENTER(SOCKET, "pkix_pl_Socket_GetPRFileDesc"); 1702 PKIX_NULLCHECK_TWO(socket, pDesc); 1703 1704 *pDesc = socket->clientSock; 1705 1706 PKIX_RETURN(SOCKET); 1707 }