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