| Index: nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_socket.c
|
| diff --git a/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_socket.c b/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_socket.c
|
| deleted file mode 100644
|
| index e8698376b5bec71531ec486a1cb78d276f3be049..0000000000000000000000000000000000000000
|
| --- a/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_socket.c
|
| +++ /dev/null
|
| @@ -1,1695 +0,0 @@
|
| -/* This Source Code Form is subject to the terms of the Mozilla Public
|
| - * License, v. 2.0. If a copy of the MPL was not distributed with this
|
| - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
| -/*
|
| - * pkix_pl_socket.c
|
| - *
|
| - * Socket Function Definitions
|
| - *
|
| - */
|
| -
|
| -/*
|
| - * If Socket Tracing is active, messages sent and received will be
|
| - * timestamped and dumped (to stdout) in standard hex-dump format. E.g.,
|
| - *
|
| - * 1116612359156140:
|
| - * 28F0: 48 65 6C 6C 6F 2C 20 77 6F 72 6C 64 21 00 Hello, world!.
|
| - *
|
| - * The timestamp is not formatted to be meaningful except as an increasing
|
| - * value of seconds.microseconds, which is good enough to correlate two
|
| - * sides of a message exchange and to figure durations.
|
| - *
|
| - * Code to perform Socket tracing will be compiled in if PKIX_SOCKETTRACE
|
| - * is defined, but that doesn't mean socket tracing is active. Tracing also
|
| - * requires that the Boolean socketTraceFlag is set to PKIX_TRUE. That is
|
| - * the default value, but it can be overridden by using the debugger to
|
| - * change its value -- allowing tracing to be turned on and off at various
|
| - * breakpoints -- or by setting the environment variable SOCKETTRACE. A
|
| - * value of 1 sets socketTraceFlag to PKIX_TRUE (tracing on), and any other
|
| - * value sets socketTraceFlag to PKIX_FALSE (tracing off). The environment
|
| - * value is checked during system initialization.
|
| - */
|
| -#ifndef BUILD_OPT
|
| -#define PKIX_SOCKETTRACE 1
|
| -#endif
|
| -
|
| -#ifdef PKIX_SOCKETDEBUG
|
| -#define PKIX_SOCKETTRACE 1
|
| -#endif
|
| -
|
| -#include "pkix_pl_socket.h"
|
| -
|
| -/* --Private-Socket-Functions---------------------------------- */
|
| -
|
| -#ifdef PKIX_SOCKETTRACE
|
| -static PKIX_Boolean socketTraceFlag = PKIX_FALSE;
|
| -
|
| -/*
|
| - * FUNCTION: pkix_pl_socket_timestamp
|
| - * DESCRIPTION:
|
| - *
|
| - * This functions prints to stdout the time of day, as obtained from the
|
| - * system function gettimeofday, as seconds.microseconds. Its resolution
|
| - * is whatever the system call provides.
|
| - *
|
| - * PARAMETERS:
|
| - * none
|
| - * THREAD SAFETY:
|
| - * Thread Safe (see Thread Safety definitions in Programmer's Guide)
|
| - * RETURNS:
|
| - * none
|
| - */
|
| -static void pkix_pl_socket_timestamp() {
|
| - PRInt64 prTime;
|
| - prTime = PR_Now();
|
| -/* We shouldn't use PR_ALTERNATE_INT64_TYPEDEF, but nor can we use PRId64 */
|
| -#if PR_BYTES_PER_LONG == 8 && !defined(PR_ALTERNATE_INT64_TYPEDEF)
|
| - printf("%ld:\n", prTime);
|
| -#else
|
| - printf("%lld:\n", prTime);
|
| -#endif
|
| -}
|
| -
|
| -/*
|
| - * FUNCTION: pkix_pl_socket_hexDigit
|
| - * DESCRIPTION:
|
| - *
|
| - * This functions prints to stdout the byte "byteVal" as two hex digits.
|
| - *
|
| - * PARAMETERS:
|
| - * "byteVal"
|
| - * The value to be printed.
|
| - * THREAD SAFETY:
|
| - * Thread Safe (see Thread Safety definitions in Programmer's Guide)
|
| - * RETURNS:
|
| - * none
|
| - */
|
| -static void pkix_pl_socket_hexDigit(char byteVal) {
|
| - int n = 0;
|
| - char cHi = '\0';
|
| - char cLow = '\0';
|
| - n = ((byteVal >> 4) & 0xf);
|
| - if (n > 9) {
|
| - cHi = (char) ((n - 10) + 'A');
|
| - } else {
|
| - cHi = (char) (n + '0');
|
| - }
|
| - n = byteVal & 0xf;
|
| - if (n > 9) {
|
| - cLow = (char) ((n - 10) + 'A');
|
| - } else {
|
| - cLow = (char) (n + '0');
|
| - }
|
| - (void) printf("%c%c", cHi, cLow);
|
| -}
|
| -
|
| -/*
|
| - * FUNCTION: pkix_pl_socket_linePrefix
|
| - * DESCRIPTION:
|
| - *
|
| - * This functions prints to stdout the address provided by "addr" as four
|
| - * hexadecimal digits followed by a colon and a space.
|
| - *
|
| - * PARAMETERS:
|
| - * "addr"
|
| - * The address to be printed
|
| - * none
|
| - * THREAD SAFETY:
|
| - * Thread Safe (see Thread Safety definitions in Programmer's Guide)
|
| - * RETURNS:
|
| - * none
|
| - */
|
| -static void pkix_pl_socket_linePrefix(PKIX_UInt32 addr) {
|
| - pkix_pl_socket_hexDigit((char)((addr >> 8) & 0xff));
|
| - pkix_pl_socket_hexDigit((char)(addr & 0xff));
|
| - (void) printf(": ");
|
| -}
|
| -
|
| -/*
|
| - * FUNCTION: pkix_pl_socket_traceLine
|
| - * DESCRIPTION:
|
| - *
|
| - * This functions prints to stdout the sixteen bytes beginning at the
|
| - * address pointed to by "ptr". The bytes are printed as sixteen pairs
|
| - * of hexadecimal characters followed by an ascii interpretation, in which
|
| - * characters from 0x20 to 0x7d are shown as their ascii equivalents, and
|
| - * other values are represented as periods.
|
| - *
|
| - * PARAMETERS:
|
| - * "ptr"
|
| - * The address of the first of the bytes to be printed
|
| - * THREAD SAFETY:
|
| - * Thread Safe (see Thread Safety definitions in Programmer's Guide)
|
| - * RETURNS:
|
| - * none
|
| - */
|
| -static void pkix_pl_socket_traceLine(char *ptr) {
|
| - PKIX_UInt32 i = 0;
|
| - pkix_pl_socket_linePrefix((PKIX_UInt32)((char *)ptr - (char *)NULL));
|
| - for (i = 0; i < 16; i++) {
|
| - printf(" ");
|
| - pkix_pl_socket_hexDigit(ptr[i]);
|
| - if (i == 7) {
|
| - printf(" ");
|
| - }
|
| - }
|
| - printf(" ");
|
| - for (i = 0; i < 16; i++) {
|
| - if ((ptr[i] < ' ') || (ptr[i] > '}')) {
|
| - printf(".");
|
| - } else {
|
| - printf("%c", ptr[i]);
|
| - }
|
| - }
|
| - printf("\n");
|
| -}
|
| -
|
| -/*
|
| - * FUNCTION: pkix_pl_socket_tracePartialLine
|
| - * DESCRIPTION:
|
| - *
|
| - * This functions prints to stdout the number of bytes given by "nBytes",
|
| - * beginning at the address pointed to by "ptr". The bytes are printed as
|
| - * pairs of hexadecimal characters followed by an ascii interpretation, in
|
| - * which characters from 0x20 to 0x7d are shown as their ascii equivalents,
|
| - * and other values are represented as periods.
|
| - *
|
| - * PARAMETERS:
|
| - * "ptr"
|
| - * The address of the first of the bytes to be printed
|
| - * "nBytes"
|
| - * The Int32 value giving the number of bytes to be printed. If "nBytes"
|
| - * is greater than sixteen, the results will be unattractive.
|
| - * none
|
| - * THREAD SAFETY:
|
| - * Thread Safe (see Thread Safety definitions in Programmer's Guide)
|
| - * RETURNS:
|
| - * none
|
| - */
|
| -static void pkix_pl_socket_tracePartialLine(char *ptr, PKIX_UInt32 nBytes) {
|
| - PKIX_UInt32 i = 0;
|
| - if (nBytes > 0) {
|
| - pkix_pl_socket_linePrefix((PKIX_UInt32)((char *)ptr - (char *)NULL));
|
| - }
|
| - for (i = 0; i < nBytes; i++) {
|
| - printf(" ");
|
| - pkix_pl_socket_hexDigit(ptr[i]);
|
| - if (i == 7) {
|
| - printf(" ");
|
| - }
|
| - }
|
| - for (i = nBytes; i < 16; i++) {
|
| - printf(" ");
|
| - if (i == 7) {
|
| - printf(" ");
|
| - }
|
| - }
|
| - printf(" ");
|
| - for (i = 0; i < nBytes; i++) {
|
| - if ((ptr[i] < ' ') || (ptr[i] > '}')) {
|
| - printf(".");
|
| - } else {
|
| - printf("%c", ptr[i]);
|
| - }
|
| - }
|
| - printf("\n");
|
| -}
|
| -
|
| -/*
|
| - * FUNCTION: pkix_pl_socket_tracebuff
|
| - * DESCRIPTION:
|
| - *
|
| - * This functions prints to stdout the number of bytes given by "nBytes",
|
| - * beginning with the byte pointed to by "buf". The output is preceded by
|
| - * a timestamp, and each group of sixteen (and a remainder, if any) is
|
| - * preceded by its address. The contents are shown in hexadecimal and as
|
| - * ascii characters. If "nBytes" is zero, the timestamp and starting
|
| - * address are displayed.
|
| - *
|
| - * PARAMETERS:
|
| - * "buf"
|
| - * The starting address of the bytes to be printed
|
| - * "nBytes"
|
| - * The number of bytes to be printed
|
| - * THREAD SAFETY:
|
| - * Thread Safe (see Thread Safety definitions in Programmer's Guide)
|
| - * RETURNS:
|
| - * none
|
| - */
|
| -void pkix_pl_socket_tracebuff(void *buf, PKIX_UInt32 nBytes) {
|
| - PKIX_UInt32 bytesRemaining = nBytes;
|
| - PKIX_UInt32 offset = 0;
|
| - char *bufptr = (char *)buf;
|
| -
|
| - if (socketTraceFlag == PKIX_FALSE) return;
|
| -
|
| - pkix_pl_socket_timestamp();
|
| - /*
|
| - * Special case: if called with length of zero, just do address
|
| - */
|
| - if (nBytes == 0) {
|
| - pkix_pl_socket_linePrefix((PKIX_UInt32)((char *)buf - (char *)NULL));
|
| - printf("\n");
|
| - } else {
|
| - while (bytesRemaining >= 16) {
|
| - pkix_pl_socket_traceLine(&bufptr[offset]);
|
| - bytesRemaining -= 16;
|
| - offset += 16;
|
| - }
|
| - pkix_pl_socket_tracePartialLine
|
| - (&bufptr[offset], bytesRemaining);
|
| - }
|
| -}
|
| -
|
| -#endif
|
| -
|
| -/*
|
| - * FUNCTION: pkix_pl_Socket_SetNonBlocking
|
| - * DESCRIPTION:
|
| - *
|
| - * This functions sets the socket represented by the PRFileDesc "fileDesc"
|
| - * to nonblocking mode.
|
| - *
|
| - * PARAMETERS:
|
| - * "fileDesc"
|
| - * The address of the PRFileDesc whose I/O mode is to be set
|
| - * non-blocking. Must be non-NULL.
|
| - * "plContext"
|
| - * Platform-specific context pointer
|
| - * THREAD SAFETY:
|
| - * Thread Safe (see Thread Safety definitions in Programmer's Guide)
|
| - * RETURNS:
|
| - * none
|
| - */
|
| -static PKIX_Error *
|
| -pkix_pl_Socket_SetNonBlocking(
|
| - PRFileDesc *fileDesc,
|
| - void *plContext)
|
| -{
|
| - PRStatus rv = PR_FAILURE;
|
| - PRSocketOptionData sockOptionData;
|
| -
|
| - PKIX_ENTER(SOCKET, "pkix_pl_Socket_SetNonBlocking");
|
| - PKIX_NULLCHECK_ONE(fileDesc);
|
| -
|
| - sockOptionData.option = PR_SockOpt_Nonblocking;
|
| - sockOptionData.value.non_blocking = PR_TRUE;
|
| -
|
| - PKIX_PL_NSSCALLRV(SOCKET, rv, fileDesc->methods->setsocketoption,
|
| - (fileDesc, &sockOptionData));
|
| -
|
| - if (rv != PR_SUCCESS) {
|
| - PKIX_ERROR(PKIX_UNABLETOSETSOCKETTONONBLOCKING);
|
| - }
|
| -cleanup:
|
| -
|
| - PKIX_RETURN(SOCKET);
|
| -}
|
| -
|
| -/*
|
| - * FUNCTION: pkix_pl_Socket_CreateClient
|
| - * DESCRIPTION:
|
| - *
|
| - * This functions creates a client socket for the PKIX_PL_Socket pointed to
|
| - * by "socket". If "socket" was created with a timeout value of zero, the
|
| - * client socket is set to use nonblocking I/O.
|
| - *
|
| - * PARAMETERS:
|
| - * "socket"
|
| - * The address of the Socket for which a client socket is to be
|
| - * created. Must be non-NULL.
|
| - * "plContext"
|
| - * Platform-specific context pointer
|
| - * THREAD SAFETY:
|
| - * Thread Safe (see Thread Safety definitions in Programmer's Guide)
|
| - * RETURNS:
|
| - * none
|
| - */
|
| -
|
| -static PKIX_Error *
|
| -pkix_pl_Socket_CreateClient(
|
| - PKIX_PL_Socket *socket,
|
| - void *plContext)
|
| -{
|
| -#ifdef PKIX_SOCKETDEBUG
|
| - PRErrorCode errorcode = 0;
|
| -#endif
|
| - PRFileDesc *mySock = NULL;
|
| -
|
| - PKIX_ENTER(SOCKET, "pkix_pl_Socket_CreateClient");
|
| - PKIX_NULLCHECK_ONE(socket);
|
| -
|
| - PKIX_PL_NSSCALLRV(SOCKET, mySock, PR_NewTCPSocket, ());
|
| - if (!mySock) {
|
| -#ifdef PKIX_SOCKETDEBUG
|
| - errorcode = PR_GetError();
|
| - printf
|
| - ("pkix_pl_Socket_CreateClient: %s\n",
|
| - PR_ErrorToString(errorcode, PR_LANGUAGE_EN));
|
| -#endif
|
| - PKIX_ERROR(PKIX_PRNEWTCPSOCKETFAILED);
|
| - }
|
| -
|
| -#ifdef PKIX_SOCKETDEBUG
|
| - printf("Created socket, PRFileDesc @ %#X\n", mySock);
|
| -#endif
|
| -
|
| - socket->clientSock = mySock;
|
| - socket->status = SOCKET_UNCONNECTED;
|
| - if (socket->timeout == 0) {
|
| - PKIX_CHECK(pkix_pl_Socket_SetNonBlocking(mySock, plContext),
|
| - PKIX_SOCKETSETNONBLOCKINGFAILED);
|
| - }
|
| -
|
| -cleanup:
|
| -
|
| - PKIX_RETURN(SOCKET);
|
| -}
|
| -
|
| -/*
|
| - * FUNCTION: pkix_pl_Socket_CreateServer
|
| - * DESCRIPTION:
|
| - *
|
| - * This functions creates a server socket for the PKIX_PL_Socket pointed to
|
| - * by "socket". If "socket" was created with a timeout value of zero, the
|
| - * server socket is set to use nonblocking I/O.
|
| - *
|
| - * Warning: there seems to be a problem with operating a server socket in
|
| - * non-blocking mode. If the server calls Recv prior to a corresponding
|
| - * Send, the message may be lost.
|
| - *
|
| - * PARAMETERS:
|
| - * "socket"
|
| - * The address of the Socket for which a server socket is to be
|
| - * created. Must be non-NULL.
|
| - * "plContext"
|
| - * Platform-specific context pointer
|
| - * THREAD SAFETY:
|
| - * Thread Safe (see Thread Safety definitions in Programmer's Guide)
|
| - * RETURNS:
|
| - * none
|
| - */
|
| -static PKIX_Error *
|
| -pkix_pl_Socket_CreateServer(
|
| - PKIX_PL_Socket *socket,
|
| - void *plContext)
|
| -{
|
| -/* #ifdef PKIX_SOCKETDEBUG */
|
| - PRErrorCode errorcode = 0;
|
| -/* #endif */
|
| - PRStatus rv = PR_FAILURE;
|
| - PRFileDesc *serverSock = NULL;
|
| - PRSocketOptionData sockOptionData;
|
| -
|
| - PKIX_ENTER(SOCKET, "pkix_pl_Socket_CreateServer");
|
| - PKIX_NULLCHECK_ONE(socket);
|
| -
|
| - PKIX_PL_NSSCALLRV(SOCKET, serverSock, PR_NewTCPSocket, ());
|
| - if (!serverSock) {
|
| -#ifdef PKIX_SOCKETDEBUG
|
| - errorcode = PR_GetError();
|
| - printf
|
| - ("pkix_pl_Socket_CreateServer: %s\n",
|
| - PR_ErrorToString(errorcode, PR_LANGUAGE_EN));
|
| -#endif
|
| - PKIX_ERROR(PKIX_PRNEWTCPSOCKETFAILED);
|
| - }
|
| -
|
| - socket->serverSock = serverSock;
|
| -
|
| -#ifdef PKIX_SOCKETDEBUG
|
| - printf("Created socket, PRFileDesc @ %#X\n", serverSock);
|
| -#endif
|
| -
|
| - if (socket->timeout == 0) {
|
| - PKIX_CHECK(pkix_pl_Socket_SetNonBlocking(serverSock, plContext),
|
| - PKIX_SOCKETSETNONBLOCKINGFAILED);
|
| - }
|
| -
|
| - sockOptionData.option = PR_SockOpt_Reuseaddr;
|
| - sockOptionData.value.reuse_addr = PR_TRUE;
|
| -
|
| - PKIX_PL_NSSCALLRV(SOCKET, rv, serverSock->methods->setsocketoption,
|
| - (serverSock, &sockOptionData));
|
| -
|
| - if (rv != PR_SUCCESS) {
|
| - PKIX_ERROR(PKIX_UNABLETOSETSOCKETTONONBLOCKING);
|
| - }
|
| -
|
| - PKIX_PL_NSSCALLRV(SOCKET, rv, PR_Bind, (serverSock, socket->netAddr));
|
| -
|
| - if (rv == PR_FAILURE) {
|
| -/* #ifdef PKIX_SOCKETDEBUG */
|
| - errorcode = PR_GetError();
|
| - printf
|
| - ("pkix_pl_Socket_CreateServer: %s\n",
|
| - PR_ErrorToString(errorcode, PR_LANGUAGE_EN));
|
| -/* #endif */
|
| - PKIX_ERROR(PKIX_PRBINDFAILED);
|
| - }
|
| -
|
| -#ifdef PKIX_SOCKETDEBUG
|
| - printf("Successful bind!\n");
|
| -#endif
|
| -
|
| - socket->status = SOCKET_BOUND;
|
| -
|
| -cleanup:
|
| -
|
| - PKIX_RETURN(SOCKET);
|
| -}
|
| -
|
| -/*
|
| - * FUNCTION: pkix_pl_Socket_Connect
|
| - * DESCRIPTION:
|
| - *
|
| - * This functions performs the connect function for the client socket
|
| - * specified in "socket", storing the status at "pStatus".
|
| - *
|
| - * PARAMETERS:
|
| - * "socket"
|
| - * The address of the Socket for which a connect is to be performed.
|
| - * Must be non-NULL.
|
| - * "pStatus"
|
| - * The address at which the connection status is stored. Must be non-NULL.
|
| - * "plContext"
|
| - * Platform-specific context pointer
|
| - * THREAD SAFETY:
|
| - * Thread Safe (see Thread Safety definitions in Programmer's Guide)
|
| - * RETURNS:
|
| - * none
|
| - */
|
| -static PKIX_Error *
|
| -pkix_pl_Socket_Connect(
|
| - PKIX_PL_Socket *socket,
|
| - PRErrorCode *pStatus,
|
| - void *plContext)
|
| -{
|
| - PRStatus rv = PR_FAILURE;
|
| - PRErrorCode errorcode = 0;
|
| -
|
| - PKIX_ENTER(SOCKET, "pkix_pl_Socket_Connect");
|
| - PKIX_NULLCHECK_TWO(socket, socket->clientSock);
|
| -
|
| - PKIX_PL_NSSCALLRV(SOCKET, rv, PR_Connect,
|
| - (socket->clientSock, socket->netAddr, socket->timeout));
|
| -
|
| - if (rv == PR_FAILURE) {
|
| - errorcode = PR_GetError();
|
| - *pStatus = errorcode;
|
| - if (errorcode == PR_IN_PROGRESS_ERROR) {
|
| - socket->status = SOCKET_CONNECTPENDING;
|
| - goto cleanup;
|
| - } else {
|
| -#ifdef PKIX_SOCKETDEBUG
|
| - printf
|
| - ("pkix_pl_Socket_Connect: %s\n",
|
| - PR_ErrorToString(errorcode, PR_LANGUAGE_EN));
|
| -#endif
|
| - PKIX_ERROR(PKIX_PRCONNECTFAILED);
|
| - }
|
| - }
|
| -
|
| -#ifdef PKIX_SOCKETDEBUG
|
| - printf("Successful connect!\n");
|
| -#endif
|
| -
|
| - *pStatus = 0;
|
| - socket->status = SOCKET_CONNECTED;
|
| -
|
| -cleanup:
|
| -
|
| - PKIX_RETURN(SOCKET);
|
| -}
|
| -
|
| -/*
|
| - * FUNCTION: pkix_pl_Socket_ConnectContinue
|
| - * DESCRIPTION:
|
| - *
|
| - * This functions continues the connect function for the client socket
|
| - * specified in "socket", storing the status at "pStatus". It is expected that
|
| - * the non-blocking connect has returned PR_IN_PROGRESS_ERROR.
|
| - *
|
| - * PARAMETERS:
|
| - * "socket"
|
| - * The address of the Socket for which a connect is to be continued.
|
| - * Must be non-NULL.
|
| - * "pStatus"
|
| - * The address at which the connection status is stored. Must be non-NULL.
|
| - * "plContext"
|
| - * Platform-specific context pointer
|
| - * THREAD SAFETY:
|
| - * Thread Safe (see Thread Safety definitions in Programmer's Guide)
|
| - * RETURNS:
|
| - * none
|
| - */
|
| -static PKIX_Error *
|
| -pkix_pl_Socket_ConnectContinue(
|
| - PKIX_PL_Socket *socket,
|
| - PRErrorCode *pStatus,
|
| - void *plContext)
|
| -{
|
| - PRStatus rv = PR_FAILURE;
|
| - PRErrorCode errorcode = 0;
|
| - PRPollDesc pollDesc;
|
| - PRInt32 numEvents = 0;
|
| -
|
| - PKIX_ENTER(SOCKET, "pkix_pl_Socket_ConnectContinue");
|
| - PKIX_NULLCHECK_TWO(socket, socket->clientSock);
|
| -
|
| - pollDesc.fd = socket->clientSock;
|
| - pollDesc.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
|
| - pollDesc.out_flags = 0;
|
| - PKIX_PL_NSSCALLRV(SOCKET, numEvents, PR_Poll, (&pollDesc, 1, 0));
|
| - if (numEvents < 0) {
|
| - PKIX_ERROR(PKIX_PRPOLLFAILED);
|
| - }
|
| -
|
| - if (numEvents == 0) {
|
| - *pStatus = PR_IN_PROGRESS_ERROR;
|
| - goto cleanup;
|
| - }
|
| -
|
| - PKIX_PL_NSSCALLRV(SOCKET, rv, PR_ConnectContinue,
|
| - (socket->clientSock, pollDesc.out_flags));
|
| -
|
| - /*
|
| - * PR_ConnectContinue sometimes lies. It returns PR_SUCCESS
|
| - * even though the connection is not yet ready. But its deceit
|
| - * is betrayed by the contents of out_flags!
|
| - */
|
| - if ((rv == PR_SUCCESS) && (pollDesc.out_flags == PR_POLL_ERR)) {
|
| - *pStatus = PR_IN_PROGRESS_ERROR;
|
| - goto cleanup;
|
| - }
|
| -
|
| - if (rv == PR_FAILURE) {
|
| - errorcode = PR_GetError();
|
| - *pStatus = errorcode;
|
| - if (errorcode == PR_IN_PROGRESS_ERROR) {
|
| - goto cleanup;
|
| - } else {
|
| -#ifdef PKIX_SOCKETDEBUG
|
| - printf
|
| - ("pkix_pl_Socket_ConnectContinue: %s\n",
|
| - PR_ErrorToString(errorcode, PR_LANGUAGE_EN));
|
| -#endif
|
| - PKIX_ERROR(PKIX_PRCONNECTCONTINUEFAILED);
|
| - }
|
| - }
|
| -
|
| -#ifdef PKIX_SOCKETDEBUG
|
| - printf("Successful connect!\n");
|
| -#endif
|
| -
|
| - *pStatus = 0;
|
| - socket->status = SOCKET_CONNECTED;
|
| -
|
| -cleanup:
|
| -
|
| - PKIX_RETURN(SOCKET);
|
| -}
|
| -
|
| -/*
|
| - * FUNCTION: pkix_pl_Socket_Destroy
|
| - * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
|
| - */
|
| -static PKIX_Error *
|
| -pkix_pl_Socket_Destroy(
|
| - PKIX_PL_Object *object,
|
| - void *plContext)
|
| -{
|
| - PKIX_PL_Socket *socket = NULL;
|
| -
|
| - PKIX_ENTER(SOCKET, "pkix_pl_Socket_Destroy");
|
| - PKIX_NULLCHECK_ONE(object);
|
| -
|
| - PKIX_CHECK(pkix_CheckType
|
| - (object, PKIX_SOCKET_TYPE, plContext),
|
| - PKIX_OBJECTNOTANSOCKET);
|
| -
|
| - socket = (PKIX_PL_Socket *)object;
|
| -
|
| - if (socket->isServer) {
|
| - if (socket->serverSock) {
|
| - PR_Close(socket->serverSock);
|
| - }
|
| - } else {
|
| - if (socket->clientSock) {
|
| - PR_Close(socket->clientSock);
|
| - }
|
| - }
|
| -
|
| -cleanup:
|
| -
|
| - PKIX_RETURN(SOCKET);
|
| -}
|
| -
|
| -/*
|
| - * FUNCTION: pkix_pl_Socket_Hashcode
|
| - * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
|
| - */
|
| -static PKIX_Error *
|
| -pkix_pl_Socket_Hashcode(
|
| - PKIX_PL_Object *object,
|
| - PKIX_UInt32 *pHashcode,
|
| - void *plContext)
|
| -{
|
| - PKIX_PL_Socket *socket = NULL;
|
| -
|
| - PKIX_ENTER(SOCKET, "pkix_pl_Socket_Hashcode");
|
| - PKIX_NULLCHECK_TWO(object, pHashcode);
|
| -
|
| - PKIX_CHECK(pkix_CheckType(object, PKIX_SOCKET_TYPE, plContext),
|
| - PKIX_OBJECTNOTSOCKET);
|
| -
|
| - socket = (PKIX_PL_Socket *)object;
|
| -
|
| - *pHashcode = (((socket->timeout << 3) +
|
| - (socket->netAddr->inet.family << 3)) +
|
| - (*((PKIX_UInt32 *)&(socket->netAddr->inet.ip)))) +
|
| - socket->netAddr->inet.port;
|
| -
|
| -cleanup:
|
| -
|
| - PKIX_RETURN(SOCKET);
|
| -}
|
| -
|
| -/*
|
| - * FUNCTION: pkix_pl_Socket_Equals
|
| - * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
|
| - */
|
| -static PKIX_Error *
|
| -pkix_pl_Socket_Equals(
|
| - PKIX_PL_Object *firstObject,
|
| - PKIX_PL_Object *secondObject,
|
| - PKIX_Int32 *pResult,
|
| - void *plContext)
|
| -{
|
| - PKIX_PL_Socket *firstSocket = NULL;
|
| - PKIX_PL_Socket *secondSocket = NULL;
|
| -
|
| - PKIX_ENTER(SOCKET, "pkix_pl_Socket_Equals");
|
| - PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
|
| -
|
| - *pResult = PKIX_FALSE;
|
| -
|
| - PKIX_CHECK(pkix_CheckTypes
|
| - (firstObject, secondObject, PKIX_SOCKET_TYPE, plContext),
|
| - PKIX_OBJECTNOTSOCKET);
|
| -
|
| - firstSocket = (PKIX_PL_Socket *)firstObject;
|
| - secondSocket = (PKIX_PL_Socket *)secondObject;
|
| -
|
| - if (firstSocket->timeout != secondSocket->timeout) {
|
| - goto cleanup;
|
| - }
|
| -
|
| - if (firstSocket->netAddr == secondSocket->netAddr) {
|
| - *pResult = PKIX_TRUE;
|
| - goto cleanup;
|
| - }
|
| -
|
| - if ((firstSocket->netAddr->inet.family !=
|
| - secondSocket->netAddr->inet.family) ||
|
| - (*((PKIX_UInt32 *)&(firstSocket->netAddr->inet.ip)) !=
|
| - *((PKIX_UInt32 *)&(secondSocket->netAddr->inet.ip))) ||
|
| - (firstSocket->netAddr->inet.port !=
|
| - secondSocket->netAddr->inet.port)) {
|
| -
|
| - goto cleanup;
|
| -
|
| - }
|
| -
|
| - *pResult = PKIX_TRUE;
|
| -
|
| -cleanup:
|
| -
|
| - PKIX_RETURN(SOCKET);
|
| -}
|
| -
|
| -/*
|
| - * FUNCTION: pkix_pl_Socket_RegisterSelf
|
| - *
|
| - * DESCRIPTION:
|
| - * Registers PKIX_PL_SOCKET_TYPE and its related
|
| - * functions with systemClasses[]
|
| - *
|
| - * THREAD SAFETY:
|
| - * Not Thread Safe - for performance and complexity reasons
|
| - *
|
| - * Since this function is only called by PKIX_PL_Initialize, which should
|
| - * only be called once, it is acceptable that this function is not
|
| - * thread-safe.
|
| - */
|
| -PKIX_Error *
|
| -pkix_pl_Socket_RegisterSelf(void *plContext)
|
| -{
|
| - extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
|
| - pkix_ClassTable_Entry entry;
|
| -
|
| - PKIX_ENTER(SOCKET, "pkix_pl_Socket_RegisterSelf");
|
| -
|
| - entry.description = "Socket";
|
| - entry.objCounter = 0;
|
| - entry.typeObjectSize = sizeof(PKIX_PL_Socket);
|
| - entry.destructor = pkix_pl_Socket_Destroy;
|
| - entry.equalsFunction = pkix_pl_Socket_Equals;
|
| - entry.hashcodeFunction = pkix_pl_Socket_Hashcode;
|
| - entry.toStringFunction = NULL;
|
| - entry.comparator = NULL;
|
| - entry.duplicateFunction = NULL;
|
| -
|
| - systemClasses[PKIX_SOCKET_TYPE] = entry;
|
| -
|
| -#ifdef PKIX_SOCKETTRACE
|
| - {
|
| - char *val = NULL;
|
| - val = PR_GetEnvSecure("SOCKETTRACE");
|
| - /* Is SOCKETTRACE set in the environment? */
|
| - if ((val != NULL) && (*val != '\0')) {
|
| - socketTraceFlag =
|
| - ((*val == '1')?PKIX_TRUE:PKIX_FALSE);
|
| - }
|
| - }
|
| -#endif
|
| -
|
| - PKIX_RETURN(SOCKET);
|
| -}
|
| -
|
| -/* --Public-Socket-Functions----------------------------------- */
|
| -
|
| -/*
|
| - * FUNCTION: pkix_pl_Socket_Listen
|
| - * DESCRIPTION:
|
| - *
|
| - * This functions establishes a listening queue for the server Socket
|
| - * pointed to by "socket".
|
| - *
|
| - * PARAMETERS:
|
| - * "socket"
|
| - * The address of the server socket for which the queue is to be
|
| - * established. Must be non-NULL.
|
| - * "backlog"
|
| - * The UInt32 value of the length of the queue to be established.
|
| - * "plContext"
|
| - * Platform-specific context pointer
|
| - * THREAD SAFETY:
|
| - * Thread Safe (see Thread Safety definitions in Programmer's Guide)
|
| - * RETURNS:
|
| - * none
|
| - */
|
| -static PKIX_Error *
|
| -pkix_pl_Socket_Listen(
|
| - PKIX_PL_Socket *socket,
|
| - PKIX_UInt32 backlog,
|
| - void *plContext)
|
| -{
|
| -#ifdef PKIX_SOCKETDEBUG
|
| - PRErrorCode errorcode = 0;
|
| -#endif
|
| - PRStatus rv = PR_FAILURE;
|
| -
|
| - PKIX_ENTER(SOCKET, "pkix_pl_Socket_Listen");
|
| - PKIX_NULLCHECK_TWO(socket, socket->serverSock);
|
| -
|
| - PKIX_PL_NSSCALLRV(SOCKET, rv, PR_Listen,
|
| - (socket->serverSock, (PRIntn)backlog));
|
| -
|
| - if (rv == PR_FAILURE) {
|
| -#ifdef PKIX_SOCKETDEBUG
|
| - errorcode = PR_GetError();
|
| - printf
|
| - ("pkix_pl_Socket_Listen: %s\n",
|
| - PR_ErrorToString(errorcode, PR_LANGUAGE_EN));
|
| -#endif
|
| - PKIX_ERROR(PKIX_PRLISTENFAILED);
|
| - }
|
| -
|
| -#ifdef PKIX_SOCKETDEBUG
|
| - printf("Successful listen!\n");
|
| -#endif
|
| -
|
| - socket->status = SOCKET_LISTENING;
|
| -cleanup:
|
| -
|
| - PKIX_RETURN(SOCKET);
|
| -}
|
| -
|
| -/*
|
| - * FUNCTION: pkix_pl_Socket_Shutdown
|
| - * DESCRIPTION:
|
| - *
|
| - * This functions performs the shutdown of any connections controlled by the
|
| - * socket pointed to by "socket".
|
| - *
|
| - * PARAMETERS:
|
| - * "socket"
|
| - * The address of the socket to be shut down. Must be non-NULL.
|
| - * "plContext"
|
| - * Platform-specific context pointer
|
| - * THREAD SAFETY:
|
| - * Thread Safe (see Thread Safety definitions in Programmer's Guide)
|
| - * RETURNS:
|
| - * none
|
| - */
|
| -static PKIX_Error *
|
| -pkix_pl_Socket_Shutdown(
|
| - PKIX_PL_Socket *socket,
|
| - void *plContext)
|
| -{
|
| -#ifdef PKIX_SOCKETDEBUG
|
| - PRErrorCode errorcode = 0;
|
| -#endif
|
| - PRStatus rv = PR_FAILURE;
|
| - PRFileDesc *fileDesc = NULL;
|
| -
|
| - PKIX_ENTER(SOCKET, "pkix_pl_Socket_Shutdown");
|
| - PKIX_NULLCHECK_ONE(socket);
|
| -
|
| - fileDesc =
|
| - (socket->isServer)?(socket->serverSock):(socket->clientSock);
|
| -
|
| - PKIX_PL_NSSCALLRV(SOCKET, rv, PR_Shutdown,
|
| - (fileDesc, PR_SHUTDOWN_BOTH));
|
| -
|
| - if (rv == PR_FAILURE) {
|
| -#ifdef PKIX_SOCKETDEBUG
|
| - errorcode = PR_GetError();
|
| - printf
|
| - ("pkix_pl_Socket_Shutdown: %s\n",
|
| - PR_ErrorToString(errorcode, PR_LANGUAGE_EN));
|
| -#endif
|
| - PKIX_ERROR(PKIX_PRSHUTDOWNFAILED);
|
| - }
|
| - socket->status = SOCKET_SHUTDOWN;
|
| -
|
| -cleanup:
|
| -
|
| - PKIX_RETURN(SOCKET);
|
| -}
|
| -
|
| -/*
|
| - * FUNCTION: pkix_pl_Socket_Send
|
| - * DESCRIPTION:
|
| - *
|
| - * This functions sends a message using the socket pointed to by "sendSock",
|
| - * from the buffer pointed to by "buf", of the number of bytes given by
|
| - * "bytesToWrite", storing the number of bytes actually written at
|
| - * "pBytesWritten". If "socket" is in non-blocking mode, the send operation
|
| - * may store -1 at "pBytesWritten" and the write is not complete until a
|
| - * corresponding pkix_pl_Poll call has indicated its completion by returning
|
| - * a non-negative value for bytes written.
|
| - *
|
| - * PARAMETERS:
|
| - * "sendSock"
|
| - * The address of the Socket on which the message is to be sent. Must
|
| - * be non-NULL.
|
| - * "buf"
|
| - * The address of the data to be sent. Must be non-NULL.
|
| - * "bytesToWrite""
|
| - * The UInt32 value indicating the number of bytes to write.
|
| - * "pBytesWritten"
|
| - * The address at which the Int32 value indicating the number of bytes
|
| - * actually written is to be stored. Must be non-NULL.
|
| - * "plContext"
|
| - * Platform-specific context pointer
|
| - * THREAD SAFETY:
|
| - * Thread Safe (see Thread Safety definitions in Programmer's Guide)
|
| - * RETURNS:
|
| - * none
|
| - */
|
| -static PKIX_Error *
|
| -pkix_pl_Socket_Send(
|
| - PKIX_PL_Socket *sendSock,
|
| - void *buf,
|
| - PKIX_UInt32 bytesToWrite,
|
| - PKIX_Int32 *pBytesWritten,
|
| - void *plContext)
|
| -{
|
| - PRInt32 bytesWritten = 0;
|
| - PRErrorCode errorcode = 0;
|
| - PRFileDesc *fd = NULL;
|
| -
|
| - PKIX_ENTER(SOCKET, "pkix_pl_Socket_Send");
|
| - PKIX_NULLCHECK_TWO(buf, pBytesWritten);
|
| -
|
| - fd = sendSock->clientSock;
|
| -
|
| - PKIX_PL_NSSCALLRV(SOCKET, bytesWritten, PR_Send,
|
| - (fd, buf, (PRInt32)bytesToWrite, 0, sendSock->timeout));
|
| -
|
| - if (bytesWritten >= 0) {
|
| - if (sendSock->status == SOCKET_SENDRCVPENDING) {
|
| - sendSock->status = SOCKET_RCVPENDING;
|
| - } else {
|
| - sendSock->status = SOCKET_CONNECTED;
|
| - }
|
| -#ifdef PKIX_SOCKETTRACE
|
| - pkix_pl_socket_tracebuff(buf, bytesWritten);
|
| -#endif
|
| - } else {
|
| - errorcode = PR_GetError();
|
| - if (errorcode != PR_WOULD_BLOCK_ERROR) {
|
| -#ifdef PKIX_SOCKETDEBUG
|
| - printf
|
| - ("pkix_pl_Socket_Send: %s\n",
|
| - PR_ErrorToString(errorcode, PR_LANGUAGE_EN));
|
| -#endif
|
| - PKIX_ERROR(PKIX_PRSENDFAILED);
|
| - }
|
| -
|
| - sendSock->writeBuf = buf;
|
| - sendSock->writeBufSize = bytesToWrite;
|
| - if (sendSock->status == SOCKET_RCVPENDING) {
|
| - sendSock->status = SOCKET_SENDRCVPENDING;
|
| - } else {
|
| - sendSock->status = SOCKET_SENDPENDING;
|
| - }
|
| - }
|
| -
|
| - *pBytesWritten = (PKIX_Int32)bytesWritten;
|
| -
|
| -cleanup:
|
| -
|
| - PKIX_RETURN(SOCKET);
|
| -}
|
| -
|
| -/*
|
| - * FUNCTION: pkix_pl_Socket_Recv
|
| - * DESCRIPTION:
|
| - *
|
| - * This functions receives a message on the socket pointed to by "rcvSock",
|
| - * into the buffer pointed to by "buf", of capacity given by "capacity",
|
| - * storing the number of bytes actually received at "pBytesRead". If "socket"
|
| - * is in non-blocking mode, the receive operation may store -1 at
|
| - * "pBytesWritten". In that case the write is not complete until a
|
| - * corresponding pkix_pl_Poll call has indicated its completion by returning
|
| - * a non-negative value for bytes read.
|
| - *
|
| - * PARAMETERS:
|
| - * "rcvSock"
|
| - * The address of the Socket on which the message is to be received.
|
| - * Must be non-NULL.
|
| - * "buf"
|
| - * The address of the buffer into which the message is to be received.
|
| - * Must be non-NULL.
|
| - * "capacity"
|
| - * The UInt32 value of the size of the buffer; that is, the maximum
|
| - * number of bytes that can be received.
|
| - * "pBytesRead"
|
| - * The address at which is stored the Int32 value of the number of bytes
|
| - * actually received.
|
| - * "plContext"
|
| - * Platform-specific context pointer
|
| - * THREAD SAFETY:
|
| - * Thread Safe (see Thread Safety definitions in Programmer's Guide)
|
| - * RETURNS:
|
| - * none
|
| - */
|
| -static PKIX_Error *
|
| -pkix_pl_Socket_Recv(
|
| - PKIX_PL_Socket *rcvSock,
|
| - void *buf,
|
| - PKIX_UInt32 capacity,
|
| - PKIX_Int32 *pBytesRead,
|
| - void *plContext)
|
| -{
|
| - PRErrorCode errorcode = 0;
|
| - PRInt32 bytesRead = 0;
|
| - PRFileDesc *fd = NULL;
|
| -
|
| - PKIX_ENTER(SOCKET, "pkix_pl_Socket_Recv");
|
| - PKIX_NULLCHECK_THREE(rcvSock, buf, pBytesRead);
|
| -
|
| - fd = rcvSock->clientSock;
|
| -
|
| - PKIX_PL_NSSCALLRV(SOCKET, bytesRead, PR_Recv,
|
| - (fd, buf, (PRInt32)capacity, 0, rcvSock->timeout));
|
| -
|
| - if (bytesRead > 0) {
|
| - if (rcvSock->status == SOCKET_SENDRCVPENDING) {
|
| - rcvSock->status = SOCKET_SENDPENDING;
|
| - } else {
|
| - rcvSock->status = SOCKET_CONNECTED;
|
| - }
|
| -#ifdef PKIX_SOCKETTRACE
|
| - pkix_pl_socket_tracebuff(buf, bytesRead);
|
| -#endif
|
| - } else if (bytesRead == 0) {
|
| - PKIX_ERROR(PKIX_PRRECVREPORTSNETWORKCONNECTIONCLOSED);
|
| - } else {
|
| - errorcode = PR_GetError();
|
| - if (errorcode != PR_WOULD_BLOCK_ERROR) {
|
| -#ifdef PKIX_SOCKETDEBUG
|
| - printf
|
| - ("pkix_pl_Socket_Recv: %s\n",
|
| - PR_ErrorToString(errorcode, PR_LANGUAGE_EN));
|
| -#endif
|
| - PKIX_ERROR(PKIX_PRRECVFAILED);
|
| - }
|
| - rcvSock->readBuf = buf;
|
| - rcvSock->readBufSize = capacity;
|
| - if (rcvSock->status == SOCKET_SENDPENDING) {
|
| - rcvSock->status = SOCKET_SENDRCVPENDING;
|
| - } else {
|
| - rcvSock->status = SOCKET_RCVPENDING;
|
| - }
|
| -
|
| - }
|
| -
|
| - *pBytesRead = (PKIX_Int32)bytesRead;
|
| -
|
| -cleanup:
|
| -
|
| - PKIX_RETURN(SOCKET);
|
| -}
|
| -
|
| -/*
|
| - * FUNCTION: pkix_pl_Socket_Poll
|
| - * DESCRIPTION:
|
| - *
|
| - * This functions checks for completion of an earlier Send or Recv on the
|
| - * socket pointed to by "sock", storing in "pBytesWritten" the number of bytes
|
| - * written by a completed Send and in "pBytesRead" the number of bytes
|
| - * received in a completed Recv. A value of -1 returned indicates the
|
| - * operation has still not completed. A NULL pointer may be supplied for
|
| - * "pBytesWritten" to avoid checking for completion of a Send. A NULL pointer
|
| - * may be supplied for "pBytesRead" to avoid checking for completion of a Recv.
|
| - *
|
| - * PARAMETERS:
|
| - * "sock"
|
| - * The address of the socket for which completions are to be checked.
|
| - * "pBytesWritten"
|
| - * The address at which the number of bytes written is to be stored, if
|
| - * a pending Send has completed. If NULL, Sends are not checked.
|
| - * "pBytesRead"
|
| - * The address at which the number of bytes read is to be stored, if
|
| - * a pending Recv has completed. If NULL, Recvs are not checked.
|
| - * "plContext"
|
| - * Platform-specific context pointer
|
| - * THREAD SAFETY:
|
| - * Thread Safe (see Thread Safety definitions in Programmer's Guide)
|
| - * RETURNS:
|
| - * none
|
| - */
|
| -static PKIX_Error *
|
| -pkix_pl_Socket_Poll(
|
| - PKIX_PL_Socket *sock,
|
| - PKIX_Int32 *pBytesWritten,
|
| - PKIX_Int32 *pBytesRead,
|
| - void *plContext)
|
| -{
|
| - PRPollDesc pollDesc;
|
| - PRInt32 numEvents = 0;
|
| - PKIX_Int32 bytesRead = 0;
|
| - PKIX_Int32 bytesWritten = 0;
|
| - PRErrorCode errorcode = 0;
|
| -
|
| - PKIX_ENTER(SOCKET, "pkix_pl_Socket_Poll");
|
| - PKIX_NULLCHECK_ONE(sock);
|
| -
|
| - pollDesc.fd = sock->clientSock;
|
| - pollDesc.in_flags = 0;
|
| - pollDesc.out_flags = 0;
|
| -
|
| - if ((pBytesWritten) &&
|
| - ((sock->status == SOCKET_SENDPENDING) ||
|
| - (sock->status == SOCKET_SENDRCVPENDING))) {
|
| - pollDesc.in_flags = PR_POLL_WRITE;
|
| - }
|
| -
|
| - if ((pBytesRead) &&
|
| - ((sock->status == SOCKET_RCVPENDING) ||
|
| - (sock->status == SOCKET_SENDRCVPENDING))) {
|
| - pollDesc.in_flags |= PR_POLL_READ;
|
| - }
|
| -
|
| - PKIX_PL_NSSCALLRV(SOCKET, numEvents, PR_Poll, (&pollDesc, 1, 0));
|
| -
|
| - if (numEvents < 0) {
|
| - PKIX_ERROR(PKIX_PRPOLLFAILED);
|
| - } else if (numEvents > 0) {
|
| - if (pollDesc.out_flags & PR_POLL_WRITE) {
|
| - PKIX_CHECK(pkix_pl_Socket_Send
|
| - (sock,
|
| - sock->writeBuf,
|
| - sock->writeBufSize,
|
| - &bytesWritten,
|
| - plContext),
|
| - PKIX_SOCKETSENDFAILED);
|
| - *pBytesWritten = (PKIX_Int32)bytesWritten;
|
| - if (bytesWritten >= 0) {
|
| - sock->writeBuf = NULL;
|
| - sock->writeBufSize = 0;
|
| - }
|
| - }
|
| -
|
| - if (pollDesc.out_flags & PR_POLL_READ) {
|
| - PKIX_CHECK(pkix_pl_Socket_Recv
|
| - (sock,
|
| - sock->readBuf,
|
| - sock->readBufSize,
|
| - &bytesRead,
|
| - plContext),
|
| - PKIX_SOCKETRECVFAILED);
|
| - *pBytesRead = (PKIX_Int32)bytesRead;
|
| - if (bytesRead >= 0) {
|
| - sock->readBuf = NULL;
|
| - sock->readBufSize = 0;
|
| - }
|
| - }
|
| - } else if (numEvents == 0) {
|
| - errorcode = PR_GetError();
|
| - if (errorcode != PR_WOULD_BLOCK_ERROR) {
|
| -#ifdef PKIX_SOCKETDEBUG
|
| - printf
|
| - ("pkix_pl_Socket_Poll: %s\n",
|
| - PR_ErrorToString(errorcode, PR_LANGUAGE_EN));
|
| -#endif
|
| - PKIX_ERROR(PKIX_PRPOLLFAILED);
|
| - }
|
| - if (pBytesWritten) {
|
| - *pBytesWritten = 0;
|
| - }
|
| - if (pBytesRead) {
|
| - *pBytesRead = 0;
|
| - }
|
| - }
|
| -
|
| -cleanup:
|
| -
|
| - PKIX_RETURN(SOCKET);
|
| -}
|
| -
|
| -/*
|
| - * FUNCTION: pkix_pl_Socket_Accept
|
| - * DESCRIPTION:
|
| - *
|
| - * This functions accepts a client connection for the server Socket pointed
|
| - * to by "serverSocket", creating a new Socket and storing the result at
|
| - * "pRendezvousSocket". If "serverSocket" is in non-blocking mode, this
|
| - * function will return NULL if there is no client connection to accept.
|
| - * Otherwise this function will block until a connection is available.
|
| - * When a client connection is available the new Socket will have the same
|
| - * blocking/non-blocking property as "serverSocket".
|
| - *
|
| - * PARAMETERS:
|
| - * "serverSocket"
|
| - * The address of the Socket for which a client connection is to be
|
| - * accepted. Must be non-NULL.
|
| - * "pRendezvousSocket"
|
| - * The address at which the created Socket is stored, when a client
|
| - * connection is available, or at which NULL is stored, if no connection
|
| - * is available for a non-blocking "serverSocket". Must be non-NULL.
|
| - * "plContext"
|
| - * Platform-specific context pointer
|
| - * THREAD SAFETY:
|
| - * Thread Safe (see Thread Safety definitions in Programmer's Guide)
|
| - * RETURNS:
|
| - * none
|
| - */
|
| -static PKIX_Error *
|
| -pkix_pl_Socket_Accept(
|
| - PKIX_PL_Socket *serverSocket,
|
| - PKIX_PL_Socket **pRendezvousSocket,
|
| - void *plContext)
|
| -{
|
| - PRErrorCode errorcode = 0;
|
| - PRFileDesc *rendezvousSock = NULL;
|
| - PRNetAddr *clientAddr = NULL;
|
| - PKIX_PL_Socket *newSocket = NULL;
|
| -
|
| - PKIX_ENTER(SOCKET, "pkix_pl_Socket_Accept");
|
| - PKIX_NULLCHECK_TWO(serverSocket, pRendezvousSocket);
|
| -
|
| - PKIX_PL_NSSCALLRV(SOCKET, rendezvousSock, PR_Accept,
|
| - (serverSocket->serverSock, clientAddr, serverSocket->timeout));
|
| -
|
| - if (!rendezvousSock) {
|
| - errorcode = PR_GetError();
|
| - if (errorcode != PR_WOULD_BLOCK_ERROR) {
|
| -#ifdef PKIX_SOCKETDEBUG
|
| - printf
|
| - ("pkix_pl_Socket_Accept: %s\n",
|
| - PR_ErrorToString(errorcode, PR_LANGUAGE_EN));
|
| -#endif
|
| - PKIX_ERROR(PKIX_PRACCEPTFAILED);
|
| - }
|
| - serverSocket->status = SOCKET_ACCEPTPENDING;
|
| - *pRendezvousSocket = NULL;
|
| - goto cleanup;
|
| -
|
| - }
|
| -
|
| -#ifdef PKIX_SOCKETDEBUG
|
| - printf("Successful accept!\n");
|
| -#endif
|
| -
|
| - PKIX_CHECK(PKIX_PL_Object_Alloc
|
| - (PKIX_SOCKET_TYPE,
|
| - sizeof (PKIX_PL_Socket),
|
| - (PKIX_PL_Object **)&newSocket,
|
| - plContext),
|
| - PKIX_COULDNOTCREATESOCKETOBJECT);
|
| -
|
| - newSocket->isServer = PKIX_FALSE;
|
| - newSocket->timeout = serverSocket->timeout;
|
| - newSocket->clientSock = rendezvousSock;
|
| - newSocket->serverSock = NULL;
|
| - newSocket->netAddr = NULL;
|
| - newSocket->status = SOCKET_CONNECTED;
|
| - newSocket->callbackList.shutdownCallback = pkix_pl_Socket_Shutdown;
|
| - newSocket->callbackList.listenCallback = pkix_pl_Socket_Listen;
|
| - newSocket->callbackList.acceptCallback = pkix_pl_Socket_Accept;
|
| - newSocket->callbackList.connectcontinueCallback =
|
| - pkix_pl_Socket_ConnectContinue;
|
| - newSocket->callbackList.sendCallback = pkix_pl_Socket_Send;
|
| - newSocket->callbackList.recvCallback = pkix_pl_Socket_Recv;
|
| - newSocket->callbackList.pollCallback = pkix_pl_Socket_Poll;
|
| -
|
| - if (serverSocket->timeout == 0) {
|
| - PKIX_CHECK(pkix_pl_Socket_SetNonBlocking
|
| - (rendezvousSock, plContext),
|
| - PKIX_SOCKETSETNONBLOCKINGFAILED);
|
| - }
|
| -
|
| - *pRendezvousSocket = newSocket;
|
| -
|
| -cleanup:
|
| -
|
| - PKIX_RETURN(SOCKET);
|
| -}
|
| -
|
| -/*
|
| - * FUNCTION: pkix_pl_Socket_Create
|
| - * DESCRIPTION:
|
| - *
|
| - * This function creates a new Socket, setting it to be a server or a client
|
| - * according to the value of "isServer", setting its timeout value from
|
| - * "timeout" and server address from "netAddr", and stores the created Socket
|
| - * at "pSocket".
|
| - *
|
| - * PARAMETERS:
|
| - * "isServer"
|
| - * The Boolean value indicating if PKIX_TRUE, that a server socket (using
|
| - * Bind, Listen, and Accept) is to be created, or if PKIX_FALSE, that a
|
| - * client socket (using Connect) is to be created.
|
| - * "timeout"
|
| - * A PRTimeInterval value to be used for I/O waits for this socket. If
|
| - * zero, non-blocking I/O is to be used.
|
| - * "netAddr"
|
| - * The PRNetAddr to be used for the Bind function, if this is a server
|
| - * socket, or for the Connect, if this is a client socket.
|
| - * "pSocket"
|
| - * The address at which the Socket is to be stored. Must be non-NULL.
|
| - * "plContext"
|
| - * Platform-specific context pointer.
|
| - * THREAD SAFETY:
|
| - * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
|
| - * RETURNS:
|
| - * Returns NULL if the function succeeds.
|
| - * Returns a Socket Error if the function fails in
|
| - * a non-fatal way.
|
| - * Returns a Fatal Error if the function fails in an unrecoverable way.
|
| - */
|
| -PKIX_Error *
|
| -pkix_pl_Socket_Create(
|
| - PKIX_Boolean isServer,
|
| - PRIntervalTime timeout,
|
| - PRNetAddr *netAddr,
|
| - PRErrorCode *status,
|
| - PKIX_PL_Socket **pSocket,
|
| - void *plContext)
|
| -{
|
| - PKIX_PL_Socket *socket = NULL;
|
| -
|
| - PKIX_ENTER(SOCKET, "pkix_pl_Socket_Create");
|
| - PKIX_NULLCHECK_ONE(pSocket);
|
| -
|
| - PKIX_CHECK(PKIX_PL_Object_Alloc
|
| - (PKIX_SOCKET_TYPE,
|
| - sizeof (PKIX_PL_Socket),
|
| - (PKIX_PL_Object **)&socket,
|
| - plContext),
|
| - PKIX_COULDNOTCREATESOCKETOBJECT);
|
| -
|
| - socket->isServer = isServer;
|
| - socket->timeout = timeout;
|
| - socket->clientSock = NULL;
|
| - socket->serverSock = NULL;
|
| - socket->netAddr = netAddr;
|
| -
|
| - socket->callbackList.listenCallback = pkix_pl_Socket_Listen;
|
| - socket->callbackList.acceptCallback = pkix_pl_Socket_Accept;
|
| - socket->callbackList.connectcontinueCallback =
|
| - pkix_pl_Socket_ConnectContinue;
|
| - socket->callbackList.sendCallback = pkix_pl_Socket_Send;
|
| - socket->callbackList.recvCallback = pkix_pl_Socket_Recv;
|
| - socket->callbackList.pollCallback = pkix_pl_Socket_Poll;
|
| - socket->callbackList.shutdownCallback = pkix_pl_Socket_Shutdown;
|
| -
|
| - if (isServer) {
|
| - PKIX_CHECK(pkix_pl_Socket_CreateServer(socket, plContext),
|
| - PKIX_SOCKETCREATESERVERFAILED);
|
| - *status = 0;
|
| - } else {
|
| - socket->timeout = timeout;
|
| - PKIX_CHECK(pkix_pl_Socket_CreateClient(socket, plContext),
|
| - PKIX_SOCKETCREATECLIENTFAILED);
|
| - PKIX_CHECK(pkix_pl_Socket_Connect(socket, status, plContext),
|
| - PKIX_SOCKETCONNECTFAILED);
|
| - }
|
| -
|
| - *pSocket = socket;
|
| -
|
| -cleanup:
|
| - if (PKIX_ERROR_RECEIVED) {
|
| - PKIX_DECREF(socket);
|
| - }
|
| -
|
| - PKIX_RETURN(SOCKET);
|
| -}
|
| -
|
| -/*
|
| - * FUNCTION: pkix_pl_Socket_CreateByName
|
| - * DESCRIPTION:
|
| - *
|
| - * This function creates a new Socket, setting it to be a server or a client
|
| - * according to the value of "isServer", setting its timeout value from
|
| - * "timeout" and server address and port number from "serverName", and stores
|
| - * the status at "pStatus" and the created Socket at "pSocket".
|
| - *
|
| - * If isServer is PKIX_TRUE, it is attempted to create the socket with an ip
|
| - * address of PR_INADDR_ANY.
|
| - *
|
| - * PARAMETERS:
|
| - * "isServer"
|
| - * The Boolean value indicating if PKIX_TRUE, that a server socket (using
|
| - * Bind, Listen, and Accept) is to be created, or if PKIX_FALSE, that a
|
| - * client socket (using Connect) is to be created.
|
| - * "timeout"
|
| - * A PRTimeInterval value to be used for I/O waits for this socket. If
|
| - * zero, non-blocking I/O is to be used.
|
| - * "serverName"
|
| - * Address of a character string consisting of the server's domain name
|
| - * followed by a colon and a port number for the desired socket.
|
| - * "pStatus"
|
| - * Address at which the PRErrorCode resulting from the create is
|
| - * stored. Must be non-NULL.
|
| - * "pSocket"
|
| - * The address at which the Socket is to be stored. Must be non-NULL.
|
| - * "plContext"
|
| - * Platform-specific context pointer.
|
| - * THREAD SAFETY:
|
| - * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
|
| - * RETURNS:
|
| - * Returns NULL if the function succeeds.
|
| - * Returns a Socket Error if the function fails in
|
| - * a non-fatal way.
|
| - * Returns a Fatal Error if the function fails in an unrecoverable way.
|
| - */
|
| -PKIX_Error *
|
| -pkix_pl_Socket_CreateByName(
|
| - PKIX_Boolean isServer,
|
| - PRIntervalTime timeout,
|
| - char *serverName,
|
| - PRErrorCode *pStatus,
|
| - PKIX_PL_Socket **pSocket,
|
| - void *plContext)
|
| -{
|
| - PRNetAddr netAddr;
|
| - PKIX_PL_Socket *socket = NULL;
|
| - char *sepPtr = NULL;
|
| - PRHostEnt hostent;
|
| - PRIntn hostenum;
|
| - PRStatus prstatus = PR_FAILURE;
|
| - char buf[PR_NETDB_BUF_SIZE];
|
| - PRUint16 portNum = 0;
|
| - char *localCopyName = NULL;
|
| -
|
| - PKIX_ENTER(SOCKET, "pkix_pl_Socket_CreateByName");
|
| - PKIX_NULLCHECK_TWO(serverName, pSocket);
|
| -
|
| - localCopyName = PL_strdup(serverName);
|
| -
|
| - sepPtr = strchr(localCopyName, ':');
|
| - /* First strip off the portnum, if present, from the end of the name */
|
| - if (sepPtr) {
|
| - *sepPtr++ = '\0';
|
| - portNum = (PRUint16)atoi(sepPtr);
|
| - } else {
|
| - portNum = (PRUint16)LDAP_PORT;
|
| - }
|
| -
|
| - prstatus = PR_GetHostByName(localCopyName, buf, sizeof(buf), &hostent);
|
| -
|
| - if ((prstatus != PR_SUCCESS) || (hostent.h_length != 4)) {
|
| - /*
|
| - * The hostname may be a fully-qualified name. Try using just
|
| - * the leftmost component in our lookup.
|
| - */
|
| - sepPtr = strchr(localCopyName, '.');
|
| - if (sepPtr) {
|
| - *sepPtr++ = '\0';
|
| - }
|
| - prstatus = PR_GetHostByName
|
| - (localCopyName, buf, sizeof(buf), &hostent);
|
| -
|
| - if ((prstatus != PR_SUCCESS) || (hostent.h_length != 4)) {
|
| - PKIX_ERROR
|
| - (PKIX_PRGETHOSTBYNAMEREJECTSHOSTNAMEARGUMENT);
|
| - }
|
| - }
|
| -
|
| - netAddr.inet.family = PR_AF_INET;
|
| - netAddr.inet.port = PR_htons(portNum);
|
| -
|
| - if (isServer) {
|
| -
|
| - netAddr.inet.ip = PR_INADDR_ANY;
|
| -
|
| - } else {
|
| -
|
| - hostenum = PR_EnumerateHostEnt(0, &hostent, portNum, &netAddr);
|
| - if (hostenum == -1) {
|
| - PKIX_ERROR(PKIX_PRENUMERATEHOSTENTFAILED);
|
| - }
|
| - }
|
| -
|
| - PKIX_CHECK(PKIX_PL_Object_Alloc
|
| - (PKIX_SOCKET_TYPE,
|
| - sizeof (PKIX_PL_Socket),
|
| - (PKIX_PL_Object **)&socket,
|
| - plContext),
|
| - PKIX_COULDNOTCREATESOCKETOBJECT);
|
| -
|
| - socket->isServer = isServer;
|
| - socket->timeout = timeout;
|
| - socket->clientSock = NULL;
|
| - socket->serverSock = NULL;
|
| - socket->netAddr = &netAddr;
|
| -
|
| - socket->callbackList.listenCallback = pkix_pl_Socket_Listen;
|
| - socket->callbackList.acceptCallback = pkix_pl_Socket_Accept;
|
| - socket->callbackList.connectcontinueCallback =
|
| - pkix_pl_Socket_ConnectContinue;
|
| - socket->callbackList.sendCallback = pkix_pl_Socket_Send;
|
| - socket->callbackList.recvCallback = pkix_pl_Socket_Recv;
|
| - socket->callbackList.pollCallback = pkix_pl_Socket_Poll;
|
| - socket->callbackList.shutdownCallback = pkix_pl_Socket_Shutdown;
|
| -
|
| - if (isServer) {
|
| - PKIX_CHECK(pkix_pl_Socket_CreateServer(socket, plContext),
|
| - PKIX_SOCKETCREATESERVERFAILED);
|
| - *pStatus = 0;
|
| - } else {
|
| - PKIX_CHECK(pkix_pl_Socket_CreateClient(socket, plContext),
|
| - PKIX_SOCKETCREATECLIENTFAILED);
|
| - PKIX_CHECK(pkix_pl_Socket_Connect(socket, pStatus, plContext),
|
| - PKIX_SOCKETCONNECTFAILED);
|
| - }
|
| -
|
| - *pSocket = socket;
|
| -
|
| -cleanup:
|
| - PL_strfree(localCopyName);
|
| -
|
| - if (PKIX_ERROR_RECEIVED) {
|
| - PKIX_DECREF(socket);
|
| - }
|
| -
|
| - PKIX_RETURN(SOCKET);
|
| -}
|
| -
|
| -/*
|
| - * FUNCTION: pkix_pl_Socket_CreateByHostAndPort
|
| - * DESCRIPTION:
|
| - *
|
| - * This function creates a new Socket, setting it to be a server or a client
|
| - * according to the value of "isServer", setting its timeout value from
|
| - * "timeout", host from "hostname", and port number from "portNum", and stores
|
| - * the status at "pStatus" and the created Socket at "pSocket".
|
| - *
|
| - * If isServer is PKIX_TRUE, it is attempted to create the socket with an ip
|
| - * address of PR_INADDR_ANY.
|
| - *
|
| - * PARAMETERS:
|
| - * "isServer"
|
| - * The Boolean value indicating if PKIX_TRUE, that a server socket (using
|
| - * Bind, Listen, and Accept) is to be created, or if PKIX_FALSE, that a
|
| - * client socket (using Connect) is to be created.
|
| - * "timeout"
|
| - * A PRTimeInterval value to be used for I/O waits for this socket. If
|
| - * zero, non-blocking I/O is to be used.
|
| - * "hostname"
|
| - * Address of a character string consisting of the server's domain name.
|
| - * "portNum"
|
| - * UInt16 value of the port number for the desired socket.
|
| - * "pStatus"
|
| - * Address at which the PRErrorCode resulting from the create is
|
| - * stored. Must be non-NULL.
|
| - * "pSocket"
|
| - * The address at which the Socket is to be stored. Must be non-NULL.
|
| - * "plContext"
|
| - * Platform-specific context pointer.
|
| - * THREAD SAFETY:
|
| - * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
|
| - * RETURNS:
|
| - * Returns NULL if the function succeeds.
|
| - * Returns a Socket Error if the function fails in
|
| - * a non-fatal way.
|
| - * Returns a Fatal Error if the function fails in an unrecoverable way.
|
| - */
|
| -PKIX_Error *
|
| -pkix_pl_Socket_CreateByHostAndPort(
|
| - PKIX_Boolean isServer,
|
| - PRIntervalTime timeout,
|
| - char *hostname,
|
| - PRUint16 portnum,
|
| - PRErrorCode *pStatus,
|
| - PKIX_PL_Socket **pSocket,
|
| - void *plContext)
|
| -{
|
| - PRNetAddr netAddr;
|
| - PKIX_PL_Socket *socket = NULL;
|
| - char *sepPtr = NULL;
|
| - PRHostEnt hostent;
|
| - PRIntn hostenum;
|
| - PRStatus prstatus = PR_FAILURE;
|
| - char buf[PR_NETDB_BUF_SIZE];
|
| -
|
| - PKIX_ENTER(SOCKET, "pkix_pl_Socket_CreateByHostAndPort");
|
| - PKIX_NULLCHECK_THREE(hostname, pStatus, pSocket);
|
| -
|
| -
|
| - prstatus = PR_GetHostByName(hostname, buf, sizeof(buf), &hostent);
|
| -
|
| - if ((prstatus != PR_SUCCESS) || (hostent.h_length != 4)) {
|
| - /*
|
| - * The hostname may be a fully-qualified name. Try using just
|
| - * the leftmost component in our lookup.
|
| - */
|
| - sepPtr = strchr(hostname, '.');
|
| - if (sepPtr) {
|
| - *sepPtr++ = '\0';
|
| - }
|
| - prstatus = PR_GetHostByName(hostname, buf, sizeof(buf), &hostent);
|
| -
|
| - if ((prstatus != PR_SUCCESS) || (hostent.h_length != 4)) {
|
| - PKIX_ERROR
|
| - (PKIX_PRGETHOSTBYNAMEREJECTSHOSTNAMEARGUMENT);
|
| - }
|
| - }
|
| -
|
| - netAddr.inet.family = PR_AF_INET;
|
| - netAddr.inet.port = PR_htons(portnum);
|
| -
|
| - if (isServer) {
|
| -
|
| - netAddr.inet.ip = PR_INADDR_ANY;
|
| -
|
| - } else {
|
| -
|
| - hostenum = PR_EnumerateHostEnt(0, &hostent, portnum, &netAddr);
|
| - if (hostenum == -1) {
|
| - PKIX_ERROR(PKIX_PRENUMERATEHOSTENTFAILED);
|
| - }
|
| - }
|
| -
|
| - PKIX_CHECK(PKIX_PL_Object_Alloc
|
| - (PKIX_SOCKET_TYPE,
|
| - sizeof (PKIX_PL_Socket),
|
| - (PKIX_PL_Object **)&socket,
|
| - plContext),
|
| - PKIX_COULDNOTCREATESOCKETOBJECT);
|
| -
|
| - socket->isServer = isServer;
|
| - socket->timeout = timeout;
|
| - socket->clientSock = NULL;
|
| - socket->serverSock = NULL;
|
| - socket->netAddr = &netAddr;
|
| -
|
| - socket->callbackList.listenCallback = pkix_pl_Socket_Listen;
|
| - socket->callbackList.acceptCallback = pkix_pl_Socket_Accept;
|
| - socket->callbackList.connectcontinueCallback =
|
| - pkix_pl_Socket_ConnectContinue;
|
| - socket->callbackList.sendCallback = pkix_pl_Socket_Send;
|
| - socket->callbackList.recvCallback = pkix_pl_Socket_Recv;
|
| - socket->callbackList.pollCallback = pkix_pl_Socket_Poll;
|
| - socket->callbackList.shutdownCallback = pkix_pl_Socket_Shutdown;
|
| -
|
| - if (isServer) {
|
| - PKIX_CHECK(pkix_pl_Socket_CreateServer(socket, plContext),
|
| - PKIX_SOCKETCREATESERVERFAILED);
|
| - *pStatus = 0;
|
| - } else {
|
| - PKIX_CHECK(pkix_pl_Socket_CreateClient(socket, plContext),
|
| - PKIX_SOCKETCREATECLIENTFAILED);
|
| - PKIX_CHECK(pkix_pl_Socket_Connect(socket, pStatus, plContext),
|
| - PKIX_SOCKETCONNECTFAILED);
|
| - }
|
| -
|
| - *pSocket = socket;
|
| -
|
| -cleanup:
|
| - if (PKIX_ERROR_RECEIVED) {
|
| - PKIX_DECREF(socket);
|
| - }
|
| -
|
| - PKIX_RETURN(SOCKET);
|
| -}
|
| -
|
| -/*
|
| - * FUNCTION: pkix_pl_Socket_GetCallbackList
|
| - */
|
| -PKIX_Error *
|
| -pkix_pl_Socket_GetCallbackList(
|
| - PKIX_PL_Socket *socket,
|
| - PKIX_PL_Socket_Callback **pCallbackList,
|
| - void *plContext)
|
| -{
|
| - PKIX_ENTER(SOCKET, "pkix_pl_Socket_GetCallbackList");
|
| - PKIX_NULLCHECK_TWO(socket, pCallbackList);
|
| -
|
| - *pCallbackList = &(socket->callbackList);
|
| -
|
| - PKIX_RETURN(SOCKET);
|
| -}
|
| -
|
| -/*
|
| - * FUNCTION: pkix_pl_Socket_GetPRFileDesc
|
| - */
|
| -PKIX_Error *
|
| -pkix_pl_Socket_GetPRFileDesc(
|
| - PKIX_PL_Socket *socket,
|
| - PRFileDesc **pDesc,
|
| - void *plContext)
|
| -{
|
| - PKIX_ENTER(SOCKET, "pkix_pl_Socket_GetPRFileDesc");
|
| - PKIX_NULLCHECK_TWO(socket, pDesc);
|
| -
|
| - *pDesc = socket->clientSock;
|
| -
|
| - PKIX_RETURN(SOCKET);
|
| -}
|
|
|