summaryrefslogtreecommitdiff
path: root/nss/cmd/libpkix/pkix_pl/module/test_socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'nss/cmd/libpkix/pkix_pl/module/test_socket.c')
-rw-r--r--nss/cmd/libpkix/pkix_pl/module/test_socket.c600
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);
+}