diff options
Diffstat (limited to 'nss/cmd/libpkix/pkix_pl/module/test_socket.c')
-rw-r--r-- | nss/cmd/libpkix/pkix_pl/module/test_socket.c | 600 |
1 files changed, 600 insertions, 0 deletions
diff --git a/nss/cmd/libpkix/pkix_pl/module/test_socket.c b/nss/cmd/libpkix/pkix_pl/module/test_socket.c new file mode 100644 index 0000000..8e25c14 --- /dev/null +++ b/nss/cmd/libpkix/pkix_pl/module/test_socket.c @@ -0,0 +1,600 @@ +/* + * test_socket.c + * + * Test Socket Type + * + * Copyright 2004-2005 Sun Microsystems, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") + * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE + * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use in + * the design, construction, operation or maintenance of any nuclear facility. + */ + +#include "testutil.h" +#include "testutil_nss.h" +#include "pkix_pl_common.h" + +#define LDAP_PORT 389 + +static void *plContext = NULL; + +typedef enum { + SERVER_LISTENING, + SERVER_RECV1, + SERVER_POLL1, + SERVER_SEND2, + SERVER_POLL2, + SERVER_RECV3, + SERVER_POLL3, + SERVER_SEND4, + SERVER_POLL4, + SERVER_DONE, + SERVER_FAILED +} SERVER_STATE; + +typedef enum { + CLIENT_WAITFORCONNECT, + CLIENT_SEND1, + CLIENT_POLL1, + CLIENT_RECV2, + CLIENT_POLL2, + CLIENT_SEND3, + CLIENT_POLL3, + CLIENT_RECV4, + CLIENT_POLL4, + CLIENT_DONE, + CLIENT_FAILED +} CLIENT_STATE; + +SERVER_STATE serverState; +CLIENT_STATE clientState; +PKIX_PL_Socket *sSock = NULL; +PKIX_PL_Socket *cSock = NULL; +PKIX_PL_Socket *rendezvousSock = NULL; +PKIX_PL_Socket_Callback *sCallbackList; +PKIX_PL_Socket_Callback *cCallbackList; +PKIX_PL_Socket_Callback *rvCallbackList; +PRNetAddr serverNetAddr; +PRNetAddr clientNetAddr; +PRIntn backlog = 0; +PRIntervalTime timeout = 0; +char *sendBuf1 = "Hello, world!"; +char *sendBuf2 = "Ack"; +char *sendBuf3 = "What do you mean, \"Ack\"?"; +char *sendBuf4 = "What do you mean, \"What do you mean, \'Ack\'?\"?"; +char rcvBuf1[100]; +char rcvBuf2[100]; + +static +void printUsage(char *testname) +{ + char *fmt = "USAGE: %s [-arenas] server:port\n"; + printf(fmt, testname); +} + +/* Functional tests for Socket public functions */ +static +void do_other_work(void) +{ /* while waiting for nonblocking I/O to complete */ + (void) PR_Sleep(2*60); +} + +static +PKIX_Boolean server() +{ + PKIX_Int32 bytesRead = 0; + PKIX_Int32 bytesWritten = 0; + PKIX_Boolean keepGoing = PKIX_FALSE; + + PKIX_TEST_STD_VARS(); + + switch (serverState) { + case SERVER_LISTENING: + subTest("SERVER_LISTENING"); + PKIX_TEST_EXPECT_NO_ERROR(sCallbackList->acceptCallback + (sSock, &rendezvousSock, plContext)); + if (rendezvousSock) { + PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_GetCallbackList + (rendezvousSock, &rvCallbackList, plContext)); + + serverState = SERVER_RECV1; + } + break; + case SERVER_RECV1: + subTest("SERVER_RECV1"); + PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->recvCallback + (rendezvousSock, + rcvBuf1, + sizeof(rcvBuf1), + &bytesRead, + plContext)); + + if (bytesRead > 0) { + /* confirm that rcvBuf1 = sendBuf1 */ + if ((bytesRead != (PRInt32)PL_strlen(sendBuf1) + 1) || + (strncmp(sendBuf1, rcvBuf1, bytesRead) != 0)) { + testError("Receive buffer mismatch\n"); + } + + serverState = SERVER_SEND2; + keepGoing = PKIX_TRUE; + } else { + serverState = SERVER_POLL1; + } + break; + case SERVER_POLL1: + subTest("SERVER_POLL1"); + PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->pollCallback + (rendezvousSock, NULL, &bytesRead, plContext)); + + if (bytesRead > 0) { + /* confirm that rcvBuf1 = sendBuf1 */ + if ((bytesRead != (PRInt32)PL_strlen(sendBuf1) + 1) || + (strncmp(sendBuf1, rcvBuf1, bytesRead) != 0)) { + testError("Receive buffer mismatch\n"); + } + + serverState = SERVER_SEND2; + keepGoing = PKIX_TRUE; + } + break; + case SERVER_SEND2: + subTest("SERVER_SEND2"); + PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->sendCallback + (rendezvousSock, + sendBuf2, + strlen(sendBuf2) + 1, + &bytesWritten, + plContext)); + if (bytesWritten > 0) { + serverState = SERVER_RECV3; + } else { + serverState = SERVER_POLL2; + } + break; + case SERVER_POLL2: + subTest("SERVER_POLL2"); + PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->pollCallback + (rendezvousSock, &bytesWritten, NULL, plContext)); + if (bytesWritten > 0) { + serverState = SERVER_RECV3; + } + break; + case SERVER_RECV3: + subTest("SERVER_RECV3"); + PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->recvCallback + (rendezvousSock, + rcvBuf1, + sizeof(rcvBuf1), + &bytesRead, + plContext)); + + if (bytesRead > 0) { + serverState = SERVER_SEND4; + keepGoing = PKIX_TRUE; + } else { + serverState = SERVER_POLL3; + } + break; + case SERVER_POLL3: + subTest("SERVER_POLL3"); + PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->pollCallback + (rendezvousSock, NULL, &bytesRead, plContext)); + if (bytesRead > 0) { + serverState = SERVER_SEND4; + keepGoing = PKIX_TRUE; + } + break; + case SERVER_SEND4: + subTest("SERVER_SEND4"); + PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->sendCallback + (rendezvousSock, + sendBuf4, + strlen(sendBuf4) + 1, + &bytesWritten, + plContext)); + + if (bytesWritten > 0) { + PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->shutdownCallback + (rendezvousSock, plContext)); + PKIX_TEST_DECREF_BC(sSock); + PKIX_TEST_DECREF_BC(rendezvousSock); + serverState = SERVER_DONE; + } else { + serverState = SERVER_POLL4; + } + break; + case SERVER_POLL4: + subTest("SERVER_POLL4"); + PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->pollCallback + (rendezvousSock, &bytesWritten, NULL, plContext)); + if (bytesWritten > 0) { + PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->shutdownCallback + (rendezvousSock, plContext)); + PKIX_TEST_DECREF_BC(sSock); + PKIX_TEST_DECREF_BC(rendezvousSock); + serverState = SERVER_DONE; + } + break; + case SERVER_DONE: + default: + subTest("SERVER_DONE"); + break; + } + +cleanup: + + PKIX_TEST_RETURN(); + + return (keepGoing); +} + +static +PKIX_Boolean client() +{ + PKIX_Boolean keepGoing = PKIX_FALSE; + PKIX_Int32 bytesRead = 0; + PKIX_Int32 bytesWritten = 0; + PRErrorCode cStat = 0; + + /* At 2 seconds each cycle, this should suffice! */ + PKIX_UInt32 giveUpCount = 10; + + PKIX_TEST_STD_VARS(); + + switch (clientState) { + case CLIENT_WAITFORCONNECT: + subTest("CLIENT_WAITFORCONNECT"); + clientState = CLIENT_FAILED; + PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->connectcontinueCallback + (cSock, &cStat, plContext)); + if (cStat == 0) { + clientState = CLIENT_SEND1; + keepGoing = PKIX_TRUE; + } else { + clientState = CLIENT_WAITFORCONNECT; + if (--giveUpCount == 0) { + testError("Client unable to connect"); + } + } + break; + case CLIENT_SEND1: + subTest("CLIENT_SEND1"); + clientState = CLIENT_FAILED; + PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->sendCallback + (cSock, + sendBuf1, + strlen(sendBuf1) + 1, + &bytesWritten, + plContext)); + if (bytesWritten > 0) { + clientState = CLIENT_RECV2; + } else { + clientState = CLIENT_POLL1; + } + break; + case CLIENT_POLL1: + subTest("CLIENT_POLL1"); + clientState = CLIENT_FAILED; + PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->pollCallback + (cSock, &bytesWritten, NULL, plContext)); + if (bytesWritten > 0) { + clientState = CLIENT_RECV2; + } else { + clientState = CLIENT_POLL1; + } + break; + case CLIENT_RECV2: + subTest("CLIENT_RECV2"); + clientState = CLIENT_FAILED; + PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->recvCallback + (cSock, + rcvBuf2, + sizeof(rcvBuf2), + &bytesRead, + plContext)); + + if (bytesRead > 0) { + /* confirm that rcvBuf2 = sendBuf2 */ + if ((bytesRead != (PRInt32)PL_strlen(sendBuf2) + 1) || + (strncmp(sendBuf2, rcvBuf2, bytesRead) != 0)) { + testError("Receive buffer mismatch\n"); + } + clientState = CLIENT_SEND3; + keepGoing = PKIX_TRUE; + } else { + clientState = CLIENT_POLL2; + } + break; + case CLIENT_POLL2: + subTest("CLIENT_POLL2"); + clientState = CLIENT_FAILED; + PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->pollCallback + (cSock, NULL, &bytesRead, plContext)); + if (bytesRead > 0) { + /* confirm that rcvBuf2 = sendBuf2 */ + if ((bytesRead != (PRInt32)PL_strlen(sendBuf2) + 1) || + (strncmp(sendBuf2, rcvBuf2, bytesRead) != 0)) { + testError("Receive buffer mismatch\n"); + } + clientState = CLIENT_SEND3; + } else { + clientState = CLIENT_POLL2; + } + break; + case CLIENT_SEND3: + subTest("CLIENT_SEND3"); + clientState = CLIENT_FAILED; + PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->sendCallback + (cSock, + sendBuf3, + strlen(sendBuf3) + 1, + &bytesWritten, + plContext)); + + if (bytesWritten > 0) { + clientState = CLIENT_RECV4; + } else { + clientState = CLIENT_POLL3; + } + break; + case CLIENT_POLL3: + subTest("CLIENT_POLL3"); + clientState = CLIENT_FAILED; + PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->pollCallback + (cSock, &bytesWritten, NULL, plContext)); + if (bytesWritten > 0) { + clientState = CLIENT_RECV4; + } else { + clientState = CLIENT_POLL3; + } + break; + case CLIENT_RECV4: + subTest("CLIENT_RECV4"); + clientState = CLIENT_FAILED; + PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->recvCallback + (cSock, + rcvBuf2, + sizeof(rcvBuf2), + &bytesRead, + plContext)); + + if (bytesRead > 0) { + PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->shutdownCallback + (cSock, plContext)); + PKIX_TEST_DECREF_BC(cSock); + clientState = CLIENT_DONE; + } else { + clientState = CLIENT_POLL4; + } + break; + case CLIENT_POLL4: + subTest("CLIENT_POLL4"); + clientState = CLIENT_FAILED; + PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->pollCallback + (cSock, NULL, &bytesRead, plContext)); + if (bytesRead > 0) { + PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->shutdownCallback + (cSock, plContext)); + PKIX_TEST_DECREF_BC(cSock); + clientState = CLIENT_DONE; + } else { + clientState = CLIENT_POLL4; + } + break; + case CLIENT_DONE: + default: + subTest("CLIENT_DONE"); + break; + } + +cleanup: + + PKIX_TEST_RETURN(); + + return (keepGoing); +} + +static +void dispatcher() +{ + PKIX_Boolean keepGoing = PKIX_FALSE; + + PKIX_TEST_STD_VARS(); + + do { + if (serverState < SERVER_DONE) { + do { + keepGoing = server(); + } while (keepGoing == PKIX_TRUE); + } + if (clientState < CLIENT_DONE) { + do { + keepGoing = client(); + } while (keepGoing == PKIX_TRUE); + } + do_other_work(); + + } while ((serverState < SERVER_DONE) || (clientState < CLIENT_DONE)); + + PKIX_TEST_RETURN(); +} + +int test_socket(int argc, char *argv[]) +{ + + int j = 0; + PKIX_UInt32 actualMinorVersion; + char buf[PR_NETDB_BUF_SIZE]; + char *serverName = NULL; + char *sepPtr = NULL; + PRHostEnt hostent; + PRUint16 portNum = 0; + PRStatus prstatus = PR_FAILURE; + PRErrorCode cStat = 0; + void *ipaddr = NULL; + PKIX_Error *bindError = NULL; + PRIntn hostenum; + + PKIX_TEST_STD_VARS(); + + startTests("Socket"); + + PKIX_TEST_EXPECT_NO_ERROR( + PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext)); + + if (argc != (j + 2)) { + printUsage(argv[0]); + pkixTestErrorMsg = "Missing command line argument."; + goto cleanup; + } + + serverName = argv[j + 1]; + + subTest("Using pkix_pl_Socket_CreateByName"); + + PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_CreateByName + (PKIX_TRUE, timeout, serverName, &cStat, &sSock, plContext)); + + PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_GetCallbackList + (sSock, &sCallbackList, plContext)); + + PKIX_TEST_EXPECT_NO_ERROR(sCallbackList->listenCallback + (sSock, backlog, plContext)); + + serverState = SERVER_LISTENING; + + PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_CreateByName + (PKIX_FALSE, timeout, serverName, &cStat, &cSock, plContext)); + + PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_GetCallbackList + (cSock, &cCallbackList, plContext)); + + if ((timeout == 0) && (cStat == PR_IN_PROGRESS_ERROR)) { + clientState = CLIENT_WAITFORCONNECT; + } else { + clientState = CLIENT_SEND1; + } + + dispatcher(); + + subTest("Using pkix_pl_Socket_Create"); + + sepPtr = strchr(serverName, ':'); + /* 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; + } + /* + * The hostname may be a fully-qualified name. Just + * use the leftmost component in our lookup. + */ + sepPtr = strchr(serverName, '.'); + if (sepPtr) { + *sepPtr++ = '\0'; + } + prstatus = PR_GetHostByName(serverName, buf, sizeof(buf), &hostent); + + if ((prstatus != PR_SUCCESS) || (hostent.h_length != 4)) { + printUsage(argv[0]); + pkixTestErrorMsg = + "PR_GetHostByName rejects command line argument."; + goto cleanup; + } + + serverNetAddr.inet.family = PR_AF_INET; + serverNetAddr.inet.port = PR_htons(portNum); + serverNetAddr.inet.ip = PR_INADDR_ANY; + + hostenum = PR_EnumerateHostEnt(0, &hostent, portNum, &clientNetAddr); + if (hostenum == -1) { + pkixTestErrorMsg = + "PR_EnumerateHostEnt failed."; + goto cleanup; + } + + backlog = 5; + + /* timeout = PR_INTERVAL_NO_TIMEOUT; */ + /* timeout = 0; nonblocking */ + timeout = 0; + + bindError = pkix_pl_Socket_Create + (PKIX_TRUE, timeout, &serverNetAddr, &cStat, &sSock, plContext); + + /* If PR_Bind can't handle INADDR_ANY, try it with the real name */ + if (bindError) { + PKIX_TEST_DECREF_BC(bindError); + serverNetAddr.inet.ip = PR_htonl(*(PRUint32 *)ipaddr); + + PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_Create + (PKIX_TRUE, + timeout, + &serverNetAddr, + &cStat, + &sSock, + plContext)); + } + + PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_GetCallbackList + (sSock, &sCallbackList, plContext)); + + PKIX_TEST_EXPECT_NO_ERROR(sCallbackList->listenCallback + (sSock, backlog, plContext)); + + serverState = SERVER_LISTENING; + + PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_Create + (PKIX_FALSE, timeout, &clientNetAddr, &cStat, &cSock, plContext)); + + PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_GetCallbackList + (cSock, &cCallbackList, plContext)); + + if ((timeout == 0) && (cStat == PR_IN_PROGRESS_ERROR)) { + clientState = CLIENT_WAITFORCONNECT; + } else { + clientState = CLIENT_SEND1; + } + + dispatcher(); + +cleanup: + + PKIX_TEST_DECREF_AC(sSock); + PKIX_TEST_DECREF_AC(cSock); + PKIX_TEST_DECREF_AC(rendezvousSock); + + PKIX_TEST_RETURN(); + + endTests("Socket"); + + return (0); +} |