int main(int argc, char **argv) { PRFileDesc *listenSock1 = NULL, *listenSock2 = NULL; PRUint16 listenPort1, listenPort2; PRNetAddr addr; char buf[128]; PRPollDesc pds0[10], pds1[10], *pds, *other_pds; PRIntn npds; PRInt32 retVal; /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name -d */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "d:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = 1; break; default: break; } } PL_DestroyOptState(opt); /* main test */ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); if (debug_mode) { printf("This program tests PR_Poll with sockets.\n"); printf("Timeout is tested.\n\n"); } /* Create two listening sockets */ if ((listenSock1 = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a new TCP socket\n"); if (!debug_mode) failed_already=1; goto exit_now; } memset(&addr, 0, sizeof(addr)); addr.inet.family = PR_AF_INET; addr.inet.ip = PR_htonl(PR_INADDR_ANY); addr.inet.port = PR_htons(0); if (PR_Bind(listenSock1, &addr) == PR_FAILURE) { fprintf(stderr, "Can't bind socket\n"); if (!debug_mode) failed_already=1; goto exit_now; } if (PR_GetSockName(listenSock1, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); if (!debug_mode) failed_already=1; goto exit_now; } listenPort1 = PR_ntohs(addr.inet.port); if (PR_Listen(listenSock1, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); if (!debug_mode) failed_already=1; goto exit_now; } if ((listenSock2 = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a new TCP socket\n"); if (!debug_mode) failed_already=1; goto exit_now; } addr.inet.family = PR_AF_INET; addr.inet.ip = PR_htonl(PR_INADDR_ANY); addr.inet.port = PR_htons(0); if (PR_Bind(listenSock2, &addr) == PR_FAILURE) { fprintf(stderr, "Can't bind socket\n"); if (!debug_mode) failed_already=1; goto exit_now; } if (PR_GetSockName(listenSock2, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); if (!debug_mode) failed_already=1; goto exit_now; } listenPort2 = PR_ntohs(addr.inet.port); if (PR_Listen(listenSock2, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); if (!debug_mode) failed_already=1; goto exit_now; } PR_snprintf(buf, sizeof(buf), "The server thread is listening on ports %hu and %hu\n\n", listenPort1, listenPort2); if (debug_mode) printf("%s", buf); /* Set up the poll descriptor array */ pds = pds0; other_pds = pds1; memset(pds, 0, sizeof(pds)); pds[0].fd = listenSock1; pds[0].in_flags = PR_POLL_READ; pds[1].fd = listenSock2; pds[1].in_flags = PR_POLL_READ; npds = 2; /* Testing timeout */ if (debug_mode) printf("PR_Poll should time out in 5 seconds\n"); retVal = PR_Poll(pds, npds, PR_SecondsToInterval(5)); if (retVal != 0) { PR_snprintf(buf, sizeof(buf), "PR_Poll should time out and return 0, but it returns %ld\n", retVal); fprintf(stderr, "%s", buf); if (!debug_mode) failed_already=1; goto exit_now; } if (debug_mode) printf("PR_Poll timed out. Test passed.\n\n"); exit_now: if (listenSock1) { PR_Close(listenSock1); } if (listenSock2) { PR_Close(listenSock2); } PR_Cleanup(); if(failed_already) return 1; else return 0; }
void nsSocketTransportService::ProbeMaxCount() { NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread"); if (mProbedMaxCount) return; mProbedMaxCount = true; // Allocate and test a PR_Poll up to the gMaxCount number of unconnected // sockets. See bug 692260 - windows should be able to handle 1000 sockets // in select() without a problem, but LSPs have been known to balk at lower // numbers. (64 in the bug). // Allocate struct PRPollDesc pfd[SOCKET_LIMIT_TARGET]; uint32_t numAllocated = 0; for (uint32_t index = 0 ; index < gMaxCount; ++index) { pfd[index].in_flags = PR_POLL_READ | PR_POLL_WRITE | PR_POLL_EXCEPT; pfd[index].out_flags = 0; pfd[index].fd = PR_OpenTCPSocket(PR_AF_INET); if (!pfd[index].fd) { SOCKET_LOG(("Socket Limit Test index %d failed\n", index)); if (index < SOCKET_LIMIT_MIN) gMaxCount = SOCKET_LIMIT_MIN; else gMaxCount = index; break; } ++numAllocated; } // Test PR_STATIC_ASSERT(SOCKET_LIMIT_MIN >= 32U); while (gMaxCount <= numAllocated) { int32_t rv = PR_Poll(pfd, gMaxCount, PR_MillisecondsToInterval(0)); SOCKET_LOG(("Socket Limit Test poll() size=%d rv=%d\n", gMaxCount, rv)); if (rv >= 0) break; SOCKET_LOG(("Socket Limit Test poll confirmationSize=%d rv=%d error=%d\n", gMaxCount, rv, PR_GetError())); gMaxCount -= 32; if (gMaxCount <= SOCKET_LIMIT_MIN) { gMaxCount = SOCKET_LIMIT_MIN; break; } } // Free for (uint32_t index = 0 ; index < numAllocated; ++index) if (pfd[index].fd) PR_Close(pfd[index].fd); Telemetry::Accumulate(Telemetry::NETWORK_PROBE_MAXCOUNT, gMaxCount); SOCKET_LOG(("Socket Limit Test max was confirmed at %d\n", gMaxCount)); }
int test_validatechain_NB(int argc, char *argv[]){ PKIX_ValidateParams *valParams = NULL; PKIX_ValidateResult *valResult = NULL; PKIX_UInt32 actualMinorVersion; PKIX_UInt32 j = 0; PKIX_UInt32 k = 0; PKIX_UInt32 chainLength = 0; PKIX_Boolean testValid = PKIX_TRUE; PKIX_List *chainCerts = NULL; PKIX_PL_Cert *dirCert = NULL; char *dirCertName = NULL; char *anchorCertName = NULL; char *dirName = NULL; PKIX_UInt32 certIndex = 0; PKIX_UInt32 anchorIndex = 0; PKIX_UInt32 checkerIndex = 0; PKIX_Boolean revChecking = PKIX_FALSE; PKIX_List *checkers = NULL; PRPollDesc *pollDesc = NULL; PRErrorCode errorCode = 0; PKIX_PL_Socket *socket = NULL; char *ldapName = NULL; PKIX_VerifyNode *verifyTree = NULL; PKIX_PL_String *verifyString = NULL; PKIX_List *loggers = NULL; PKIX_Logger *logger = NULL; char *logging = NULL; PKIX_PL_String *component = NULL; PKIX_TEST_STD_VARS(); if (argc < 5) { printUsage(); return (0); } startTests("ValidateChain_NB"); PKIX_TEST_EXPECT_NO_ERROR( PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext)); /* ENE = expect no error; EE = expect error */ if (PORT_Strcmp(argv[2+j], "ENE") == 0) { testValid = PKIX_TRUE; } else if (PORT_Strcmp(argv[2+j], "EE") == 0) { testValid = PKIX_FALSE; } else { printUsage(); return (0); } subTest(argv[1+j]); dirName = argv[3+j]; chainLength = argc - j - 5; PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&chainCerts, plContext)); for (k = 0; k < chainLength; k++){ dirCert = createCert(dirName, argv[5+k+j], plContext); PKIX_TEST_EXPECT_NO_ERROR (PKIX_List_AppendItem (chainCerts, (PKIX_PL_Object *)dirCert, plContext)); PKIX_TEST_DECREF_BC(dirCert); } valParams = createValidateParams (dirName, argv[4+j], NULL, NULL, NULL, PKIX_FALSE, PKIX_FALSE, PKIX_FALSE, PKIX_FALSE, chainCerts, plContext); ldapName = PR_GetEnv("LDAP"); /* Is LDAP set in the environment? */ if ((ldapName == NULL) || (*ldapName == '\0')) { testError("LDAP not set in environment"); goto cleanup; } pkixTestErrorResult = pkix_pl_Socket_CreateByName (PKIX_FALSE, /* isServer */ PR_SecondsToInterval(30), /* try 30 secs for connect */ ldapName, &errorCode, &socket, plContext); if (pkixTestErrorResult != NULL) { PKIX_PL_Object_DecRef ((PKIX_PL_Object *)pkixTestErrorResult, plContext); pkixTestErrorResult = NULL; testError("Unable to connect to LDAP Server"); goto cleanup; } PKIX_TEST_DECREF_BC(socket); testSetupCertStore(valParams, ldapName); logging = PR_GetEnv("LOGGING"); /* Is LOGGING set in the environment? */ if ((logging != NULL) && (*logging != '\0')) { PKIX_TEST_EXPECT_NO_ERROR (PKIX_List_Create(&loggers, plContext)); testLogErrors (PKIX_VALIDATE_ERROR, 2, loggers, plContext); testLogErrors (PKIX_CERTCHAINCHECKER_ERROR, 2, loggers, plContext); testLogErrors (PKIX_LDAPDEFAULTCLIENT_ERROR, 2, loggers, plContext); testLogErrors (PKIX_CERTSTORE_ERROR, 2, loggers, plContext); PKIX_TEST_EXPECT_NO_ERROR(PKIX_SetLoggers(loggers, plContext)); } pkixTestErrorResult = PKIX_ValidateChain_NB (valParams, &certIndex, &anchorIndex, &checkerIndex, &revChecking, &checkers, (void **)&pollDesc, &valResult, &verifyTree, plContext); while (pollDesc != NULL) { if (PR_Poll(pollDesc, 1, 0) < 0) { testError("PR_Poll failed"); } pkixTestErrorResult = PKIX_ValidateChain_NB (valParams, &certIndex, &anchorIndex, &checkerIndex, &revChecking, &checkers, (void **)&pollDesc, &valResult, &verifyTree, plContext); } if (pkixTestErrorResult) { if (testValid == PKIX_FALSE) { /* EE */ (void) printf("EXPECTED ERROR RECEIVED!\n"); } else { /* ENE */ testError("UNEXPECTED ERROR RECEIVED"); } PKIX_TEST_DECREF_BC(pkixTestErrorResult); } else { if (testValid == PKIX_TRUE) { /* ENE */ (void) printf("EXPECTED NON-ERROR RECEIVED!\n"); } else { /* EE */ (void) printf("UNEXPECTED NON-ERROR RECEIVED!\n"); } } cleanup: if (verifyTree) { PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString ((PKIX_PL_Object*)verifyTree, &verifyString, plContext)); (void) printf("verifyTree is\n%s\n", verifyString->escAsciiString); } PKIX_TEST_DECREF_AC(verifyString); PKIX_TEST_DECREF_AC(verifyTree); PKIX_TEST_DECREF_AC(checkers); PKIX_TEST_DECREF_AC(chainCerts); PKIX_TEST_DECREF_AC(valParams); PKIX_TEST_DECREF_AC(valResult); PKIX_Shutdown(plContext); PKIX_TEST_RETURN(); endTests("ValidateChain_NB"); return (0); }
/** Start polling cycle. @param socket Network connected socket. @param mode Bit-array of MODE_*. This function take care on MODE_RAW. @return 0 on failure, otherwise 1 */ static int poll_cycle(PRFileDesc *localsocket,int mode) { PRPollDesc pool[2]; char buffer[1024],buffer_eol[1024*2]; int readed_bytes; int can_exit; int res; int bytes_to_write; int eol_state; can_exit=0; eol_state=0; /* Fill pool*/ pool[1].fd=localsocket; pool[0].fd=PR_STDIN; pool[0].in_flags=pool[1].in_flags=PR_POLL_READ; pool[0].out_flags=pool[1].out_flags=0; while (!can_exit) { res=(PR_Poll(pool,sizeof(pool)/sizeof(PRPollDesc),PR_INTERVAL_NO_TIMEOUT)); if (res==-1) { print_nspr_error(); return 0; } if (pool[1].out_flags&PR_POLL_READ) { /*We have something in socket*/ if ((readed_bytes=PR_Read(pool[1].fd,buffer,sizeof(buffer)))>0) { if (PR_Write(PR_STDOUT,buffer,readed_bytes)!=readed_bytes) { print_nspr_error(); return 0; } } else { /*End of stream -> quit*/ can_exit=1; } } if (pool[0].out_flags&(PR_POLL_READ|PR_POLL_HUP)) { /*We have something in stdin*/ if ((readed_bytes=PR_Read(pool[0].fd,buffer,sizeof(buffer)))>0) { if (!(mode&MODE_RAW)) { convert_eols(buffer,readed_bytes,buffer_eol,&bytes_to_write,&eol_state); } else bytes_to_write=readed_bytes; if (PR_Write(pool[1].fd,(mode&MODE_RAW?buffer:buffer_eol),bytes_to_write)!=bytes_to_write) { print_nspr_error(); return 0; } } else { /*End of stream -> send EOL (if needed)*/ if (!(mode&MODE_RAW)) { eol_state+=100; convert_eols(NULL,0,buffer_eol,&bytes_to_write,&eol_state); if (PR_Write(pool[1].fd,buffer_eol,bytes_to_write)!=bytes_to_write) { print_nspr_error(); return 0; } } } } pool[0].out_flags=pool[1].out_flags=0; } /*while (!can_exit)*/ return 1; }
int main(int argc, char **argv) { PRFileDesc *listenSock1, *listenSock2; PRFileDesc *badFD; PRUint16 listenPort1, listenPort2; PRNetAddr addr; char buf[BUF_SIZE]; PRThread *clientThread; PRPollDesc pds0[10], pds1[10], *pds, *other_pds; PRIntn npds; PRInt32 retVal; PRInt32 rv; PROsfd sd; struct sockaddr_in saddr; PRIntn saddr_len; PRUint16 listenPort3; PRFileDesc *socket_poll_fd; PRIntn i, j; PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); printf("This program tests PR_Poll with sockets.\n"); printf("Timeout, error reporting, and normal operation are tested.\n\n"); /* Create two listening sockets */ if ((listenSock1 = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a new TCP socket\n"); exit(1); } addr.inet.family = PR_AF_INET; addr.inet.ip = PR_htonl(PR_INADDR_ANY); addr.inet.port = PR_htons(0); if (PR_Bind(listenSock1, &addr) == PR_FAILURE) { fprintf(stderr, "Can't bind socket\n"); exit(1); } if (PR_GetSockName(listenSock1, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); exit(1); } listenPort1 = PR_ntohs(addr.inet.port); if (PR_Listen(listenSock1, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); exit(1); } if ((listenSock2 = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a new TCP socket\n"); exit(1); } addr.inet.family = PR_AF_INET; addr.inet.ip = PR_htonl(PR_INADDR_ANY); addr.inet.port = PR_htons(0); if (PR_Bind(listenSock2, &addr) == PR_FAILURE) { fprintf(stderr, "Can't bind socket\n"); exit(1); } if (PR_GetSockName(listenSock2, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); exit(1); } listenPort2 = PR_ntohs(addr.inet.port); if (PR_Listen(listenSock2, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); exit(1); } /* Set up the poll descriptor array */ pds = pds0; other_pds = pds1; memset(pds, 0, sizeof(pds)); npds = 0; pds[npds].fd = listenSock1; pds[npds].in_flags = PR_POLL_READ; npds++; pds[npds].fd = listenSock2; pds[npds].in_flags = PR_POLL_READ; npds++; sd = socket(AF_INET, SOCK_STREAM, 0); PR_ASSERT(sd >= 0); memset((char *) &saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_addr.s_addr = htonl(INADDR_ANY); saddr.sin_port = htons(0); rv = bind(sd, (struct sockaddr *)&saddr, sizeof(saddr)); PR_ASSERT(rv == 0); saddr_len = sizeof(saddr); rv = getsockname(sd, (struct sockaddr *) &saddr, &saddr_len); PR_ASSERT(rv == 0); listenPort3 = ntohs(saddr.sin_port); rv = listen(sd, 5); PR_ASSERT(rv == 0); pds[npds].fd = socket_poll_fd = PR_CreateSocketPollFd(sd); PR_ASSERT(pds[npds].fd); pds[npds].in_flags = PR_POLL_READ; npds++; PR_snprintf(buf, sizeof(buf), "The server thread is listening on ports %hu, %hu and %hu\n\n", listenPort1, listenPort2, listenPort3); printf("%s", buf); /* Testing timeout */ printf("PR_Poll should time out in 5 seconds\n"); retVal = PR_Poll(pds, npds, PR_SecondsToInterval(5)); if (retVal != 0) { PR_snprintf(buf, sizeof(buf), "PR_Poll should time out and return 0, but it returns %ld\n", retVal); fprintf(stderr, "%s", buf); exit(1); } printf("PR_Poll timed out. Test passed.\n\n"); /* Testing bad fd */ printf("PR_Poll should detect a bad file descriptor\n"); if ((badFD = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a TCP socket\n"); exit(1); } pds[npds].fd = badFD; pds[npds].in_flags = PR_POLL_READ; npds++; PR_Close(badFD); /* make the fd bad */ #if 0 retVal = PR_Poll(pds, npds, PR_INTERVAL_NO_TIMEOUT); if (retVal != 1 || (unsigned short) pds[2].out_flags != PR_POLL_NVAL) { fprintf(stderr, "Failed to detect the bad fd: " "PR_Poll returns %d, out_flags is 0x%hx\n", retVal, pds[npds - 1].out_flags); exit(1); } printf("PR_Poll detected the bad fd. Test passed.\n\n"); #endif npds--; clientThread = PR_CreateThread(PR_USER_THREAD, clientThreadFunc, (void *) listenPort1, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0); if (clientThread == NULL) { fprintf(stderr, "can't create thread\n"); exit(1); } clientThread = PR_CreateThread(PR_USER_THREAD, clientThreadFunc, (void *) listenPort2, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0); if (clientThread == NULL) { fprintf(stderr, "can't create thread\n"); exit(1); } clientThread = PR_CreateThread(PR_USER_THREAD, clientThreadFunc, (void *) listenPort3, PR_PRIORITY_NORMAL, PR_GLOBAL_BOUND_THREAD, PR_UNJOINABLE_THREAD, 0); if (clientThread == NULL) { fprintf(stderr, "can't create thread\n"); exit(1); } printf("Three client threads are created. Each of them will\n"); printf("send data to one of the three ports the server is listening on.\n"); printf("The data they send is the port number. Each of them send\n"); printf("the data five times, so you should see ten lines below,\n"); printf("interleaved in an arbitrary order.\n"); /* 30 events total */ i = 0; while (i < 30) { PRPollDesc *tmp; int nextIndex; int nEvents = 0; retVal = PR_Poll(pds, npds, PR_INTERVAL_NO_TIMEOUT); PR_ASSERT(retVal != 0); /* no timeout */ if (retVal == -1) { fprintf(stderr, "PR_Poll failed\n"); exit(1); } nextIndex = 3; /* the three listening sockets */ for (j = 0; j < 3; j++) { other_pds[j] = pds[j]; PR_ASSERT((pds[j].out_flags & PR_POLL_WRITE) == 0 && (pds[j].out_flags & PR_POLL_EXCEPT) == 0); if (pds[j].out_flags & PR_POLL_READ) { PRFileDesc *sock; nEvents++; if (j == 2) { PROsfd newsd; newsd = accept(PR_FileDesc2NativeHandle(pds[j].fd), NULL, 0); if (newsd == -1) { fprintf(stderr, "accept() failed\n"); exit(1); } other_pds[nextIndex].fd = PR_CreateSocketPollFd(newsd); PR_ASSERT(other_pds[nextIndex].fd); other_pds[nextIndex].in_flags = PR_POLL_READ; } else { sock = PR_Accept(pds[j].fd, NULL, PR_INTERVAL_NO_TIMEOUT); if (sock == NULL) { fprintf(stderr, "PR_Accept() failed\n"); exit(1); } other_pds[nextIndex].fd = sock; other_pds[nextIndex].in_flags = PR_POLL_READ; } nextIndex++; } else if (pds[j].out_flags & PR_POLL_ERR) { fprintf(stderr, "PR_Poll() indicates that an fd has error\n"); exit(1); } else if (pds[j].out_flags & PR_POLL_NVAL) { fprintf(stderr, "PR_Poll() indicates that fd %d is invalid\n", PR_FileDesc2NativeHandle(pds[j].fd)); exit(1); } } for (j = 3; j < npds; j++) { PR_ASSERT((pds[j].out_flags & PR_POLL_WRITE) == 0 && (pds[j].out_flags & PR_POLL_EXCEPT) == 0); if (pds[j].out_flags & PR_POLL_READ) { PRInt32 nBytes; nEvents++; /* XXX: This call is a hack and should be fixed */ if (PR_GetDescType(pds[j].fd) == (PRDescType) 0) { nBytes = recv(PR_FileDesc2NativeHandle(pds[j].fd), buf, sizeof(buf), 0); if (nBytes == -1) { fprintf(stderr, "recv() failed\n"); exit(1); } printf("Server read %d bytes from native fd %d\n",nBytes, PR_FileDesc2NativeHandle(pds[j].fd)); #ifdef WIN32 closesocket((SOCKET)PR_FileDesc2NativeHandle(pds[j].fd)); #else close(PR_FileDesc2NativeHandle(pds[j].fd)); #endif PR_DestroySocketPollFd(pds[j].fd); } else { nBytes = PR_Read(pds[j].fd, buf, sizeof(buf)); if (nBytes == -1) { fprintf(stderr, "PR_Read() failed\n"); exit(1); } PR_Close(pds[j].fd); } /* Just to be safe */ buf[BUF_SIZE - 1] = '\0'; printf("The server received \"%s\" from a client\n", buf); } else if (pds[j].out_flags & PR_POLL_ERR) { fprintf(stderr, "PR_Poll() indicates that an fd has error\n"); exit(1); } else if (pds[j].out_flags & PR_POLL_NVAL) { fprintf(stderr, "PR_Poll() indicates that an fd is invalid\n"); exit(1); } else { other_pds[nextIndex] = pds[j]; nextIndex++; } } PR_ASSERT(retVal == nEvents); /* swap */ tmp = pds; pds = other_pds; other_pds = tmp; npds = nextIndex; i += nEvents; } PR_DestroySocketPollFd(socket_poll_fd); printf("All tests finished\n"); PR_Cleanup(); return 0; }
static void Test_BuildResult( PKIX_ProcessingParams *procParams, PKIX_Boolean testValid, PKIX_List *expectedCerts, void *plContext) { PKIX_PL_Cert *cert = NULL; PKIX_List *certs = NULL; PKIX_PL_String *actualCertsString = NULL; PKIX_PL_String *expectedCertsString = NULL; PKIX_BuildResult *buildResult = NULL; PKIX_Boolean result; PKIX_Boolean supportForward = PKIX_FALSE; PKIX_UInt32 numCerts, i; char *asciiResult = NULL; char *actualCertsAscii = NULL; char *expectedCertsAscii = NULL; void *state = NULL; PRPollDesc *pollDesc = NULL; PKIX_TEST_STD_VARS(); pkixTestErrorResult = PKIX_BuildChain(procParams, (void **)&pollDesc, &state, &buildResult, NULL, plContext); while (pollDesc != NULL) { if (PR_Poll(pollDesc, 1, 0) < 0) { testError("PR_Poll failed"); } pkixTestErrorResult = PKIX_BuildChain(procParams, (void **)&pollDesc, &state, &buildResult, NULL, plContext); } if (pkixTestErrorResult) { if (testValid == PKIX_FALSE) { /* EE */ (void)printf("EXPECTED ERROR RECEIVED!\n"); } else { /* ENE */ testError("UNEXPECTED ERROR RECEIVED!\n"); } PKIX_TEST_DECREF_BC(pkixTestErrorResult); goto cleanup; } if (testValid == PKIX_TRUE) { /* ENE */ (void)printf("EXPECTED NON-ERROR RECEIVED!\n"); } else { /* EE */ testError("UNEXPECTED NON-ERROR RECEIVED!\n"); } if (buildResult) { PKIX_TEST_EXPECT_NO_ERROR(PKIX_BuildResult_GetCertChain(buildResult, &certs, NULL)); PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(certs, &numCerts, plContext)); printf("\n"); for (i = 0; i < numCerts; i++) { PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(certs, i, (PKIX_PL_Object **)&cert, plContext)); asciiResult = PKIX_Cert2ASCII(cert); printf("CERT[%d]:\n%s\n", i, asciiResult); /* PKIX_Cert2ASCII used PKIX_PL_Malloc(...,,NULL) */ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(asciiResult, NULL)); asciiResult = NULL; PKIX_TEST_DECREF_BC(cert); } PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals((PKIX_PL_Object *)certs, (PKIX_PL_Object *)expectedCerts, &result, plContext)); if (!result) { testError("BUILT CERTCHAIN IS " "NOT THE ONE THAT WAS EXPECTED"); PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)certs, &actualCertsString, plContext)); actualCertsAscii = PKIX_String2ASCII(actualCertsString, plContext); if (actualCertsAscii == NULL) { pkixTestErrorMsg = "PKIX_String2ASCII Failed"; goto cleanup; } PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)expectedCerts, &expectedCertsString, plContext)); expectedCertsAscii = PKIX_String2ASCII(expectedCertsString, plContext); if (expectedCertsAscii == NULL) { pkixTestErrorMsg = "PKIX_String2ASCII Failed"; goto cleanup; } (void)printf("Actual value:\t%s\n", actualCertsAscii); (void)printf("Expected value:\t%s\n", expectedCertsAscii); } } cleanup: PKIX_PL_Free(asciiResult, NULL); PKIX_PL_Free(actualCertsAscii, plContext); PKIX_PL_Free(expectedCertsAscii, plContext); PKIX_TEST_DECREF_AC(state); PKIX_TEST_DECREF_AC(buildResult); PKIX_TEST_DECREF_AC(certs); PKIX_TEST_DECREF_AC(cert); PKIX_TEST_DECREF_AC(actualCertsString); PKIX_TEST_DECREF_AC(expectedCertsString); PKIX_TEST_RETURN(); }
ConnThread(void *arg) { PRInt32 num; nsresult rv = NS_OK; ipcConnectionState *s = (ipcConnectionState *) arg; // we monitor two file descriptors in this thread. the first (at index 0) is // the socket connection with the IPC daemon. the second (at index 1) is the // pollable event we monitor in order to know when to send messages to the // IPC daemon. s->fds[SOCK].in_flags = PR_POLL_READ; s->fds[POLL].in_flags = PR_POLL_READ; while (NS_SUCCEEDED(rv)) { s->fds[SOCK].out_flags = 0; s->fds[POLL].out_flags = 0; // // poll on the IPC socket and NSPR pollable event // num = PR_Poll(s->fds, 2, PR_INTERVAL_NO_TIMEOUT); if (num > 0) { ipcCallbackQ cbs_to_run; // check if something has been added to the send queue. if so, then // acknowledge pollable event (wait should not block), and configure // poll flags to find out when we can write. if (s->fds[POLL].out_flags & PR_POLL_READ) { PR_WaitForPollableEvent(s->fds[POLL].fd); PR_Lock(s->lock); if (!s->send_queue.IsEmpty()) s->fds[SOCK].in_flags |= PR_POLL_WRITE; if (!s->callback_queue.IsEmpty()) s->callback_queue.MoveTo(cbs_to_run); PR_Unlock(s->lock); } // check if we can read... if (s->fds[SOCK].out_flags & PR_POLL_READ) rv = ConnRead(s); // check if we can write... if (s->fds[SOCK].out_flags & PR_POLL_WRITE) rv = ConnWrite(s); // check if we have callbacks to run while (!cbs_to_run.IsEmpty()) { ipcCallback *cb = cbs_to_run.First(); (cb->func)(cb->arg); cbs_to_run.DeleteFirst(); } // check if we should exit this thread. delay processing a shutdown // request until after all queued up messages have been sent and until // after all queued up callbacks have been run. PR_Lock(s->lock); if (s->shutdown && s->send_queue.IsEmpty() && s->callback_queue.IsEmpty()) rv = NS_ERROR_ABORT; PR_Unlock(s->lock); } else { LOG(("PR_Poll returned error %d (%s), os error %d\n", PR_GetError(), PR_ErrorToName(PR_GetError()), PR_GetOSError())); rv = NS_ERROR_UNEXPECTED; } } // notify termination of the IPC connection if (rv == NS_ERROR_ABORT) rv = NS_OK; IPC_OnConnectionEnd(rv); LOG(("IPC thread exiting\n")); }
static void PR_CALLBACK Server(void *arg) { PRStatus rv; PRInt32 ready; PRUint8 buffer[100]; PRFileDesc *service; PRUintn empty_flags = 0; struct PRPollDesc polldesc; PRIntn bytes_read, bytes_sent; PRFileDesc *stack = (PRFileDesc*)arg; PRNetAddr client_address; do { if (verbosity > chatty) PR_fprintf(logFile, "Server accepting connection\n"); service = PR_Accept(stack, &client_address, PR_INTERVAL_NO_TIMEOUT); if (verbosity > chatty) PR_fprintf(logFile, "Server accept status [0x%p]\n", service); if ((NULL == service) && (PR_WOULD_BLOCK_ERROR == PR_GetError())) { polldesc.fd = stack; polldesc.out_flags = 0; polldesc.in_flags = PR_POLL_READ | PR_POLL_EXCEPT; ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT); if ((1 != ready) /* if not 1, then we're dead */ || (0 == (polldesc.in_flags & polldesc.out_flags))) { PR_NOT_REACHED("Whoa!"); break; } } } while (NULL == service); PR_ASSERT(NULL != service); if (verbosity > quiet) PR_fprintf(logFile, "Server accepting connection\n"); do { bytes_read = 0; do { if (verbosity > chatty) PR_fprintf( logFile, "Server receiving %d bytes\n", sizeof(buffer) - bytes_read); ready = PR_Recv( service, buffer + bytes_read, sizeof(buffer) - bytes_read, empty_flags, PR_INTERVAL_NO_TIMEOUT); if (verbosity > chatty) PR_fprintf(logFile, "Server receive status [%d]\n", ready); if (0 < ready) bytes_read += ready; else if ((-1 == ready) && (PR_WOULD_BLOCK_ERROR == PR_GetError())) { polldesc.fd = service; polldesc.out_flags = 0; polldesc.in_flags = PR_POLL_READ; ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT); if ((1 != ready) /* if not 1, then we're dead */ || (0 == (polldesc.in_flags & polldesc.out_flags))) { PR_NOT_REACHED("Whoa!"); break; } } else break; } while (bytes_read < sizeof(buffer)); if (0 != bytes_read) { if (verbosity > chatty) PR_fprintf(logFile, "Server received %d bytes\n", bytes_read); PR_ASSERT(bytes_read > 0); bytes_sent = 0; do { ready = PR_Send( service, buffer + bytes_sent, bytes_read - bytes_sent, empty_flags, PR_INTERVAL_NO_TIMEOUT); if (0 < ready) { bytes_sent += ready; } else if ((-1 == ready) && (PR_WOULD_BLOCK_ERROR == PR_GetError())) { polldesc.fd = service; polldesc.out_flags = 0; polldesc.in_flags = PR_POLL_WRITE; ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT); if ((1 != ready) /* if not 1, then we're dead */ || (0 == (polldesc.in_flags & polldesc.out_flags))) { PR_NOT_REACHED("Whoa!"); break; } } else break; } while (bytes_sent < bytes_read); PR_ASSERT(bytes_read == bytes_sent); if (verbosity > chatty) PR_fprintf(logFile, "Server sent %d bytes\n", bytes_sent); } } while (0 != bytes_read); if (verbosity > quiet) PR_fprintf(logFile, "Server shutting down stack\n"); rv = PR_Shutdown(service, PR_SHUTDOWN_BOTH); PR_ASSERT(PR_SUCCESS == rv); rv = PR_Close(service); PR_ASSERT(PR_SUCCESS == rv); } /* Server */
static void PR_CALLBACK Client(void *arg) { PRStatus rv; PRIntn mits; PRInt32 ready; PRUint8 buffer[100]; PRPollDesc polldesc; PRIntn empty_flags = 0; PRIntn bytes_read, bytes_sent; PRFileDesc *stack = (PRFileDesc*)arg; /* Initialize the buffer so that Purify won't complain */ memset(buffer, 0, sizeof(buffer)); rv = PR_Connect(stack, &server_address, PR_INTERVAL_NO_TIMEOUT); if ((PR_FAILURE == rv) && (PR_IN_PROGRESS_ERROR == PR_GetError())) { if (verbosity > quiet) PR_fprintf(logFile, "Client connect 'in progress'\n"); do { polldesc.fd = stack; polldesc.out_flags = 0; polldesc.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT; ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT); if ((1 != ready) /* if not 1, then we're dead */ || (0 == (polldesc.in_flags & polldesc.out_flags))) { PR_NOT_REACHED("Whoa!"); break; } if (verbosity > quiet) PR_fprintf( logFile, "Client connect 'in progress' [0x%x]\n", polldesc.out_flags); rv = PR_GetConnectStatus(&polldesc); if ((PR_FAILURE == rv) && (PR_IN_PROGRESS_ERROR != PR_GetError())) break; } while (PR_FAILURE == rv); } PR_ASSERT(PR_SUCCESS == rv); if (verbosity > chatty) PR_fprintf(logFile, "Client created connection\n"); for (mits = 0; mits < minor_iterations; ++mits) { bytes_sent = 0; if (verbosity > quiet) PR_fprintf(logFile, "Client sending %d bytes\n", sizeof(buffer)); do { if (verbosity > chatty) PR_fprintf( logFile, "Client sending %d bytes\n", sizeof(buffer) - bytes_sent); ready = PR_Send( stack, buffer + bytes_sent, sizeof(buffer) - bytes_sent, empty_flags, PR_INTERVAL_NO_TIMEOUT); if (verbosity > chatty) PR_fprintf(logFile, "Client send status [%d]\n", ready); if (0 < ready) bytes_sent += ready; else if ((-1 == ready) && (PR_WOULD_BLOCK_ERROR == PR_GetError())) { polldesc.fd = stack; polldesc.out_flags = 0; polldesc.in_flags = PR_POLL_WRITE; ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT); if ((1 != ready) /* if not 1, then we're dead */ || (0 == (polldesc.in_flags & polldesc.out_flags))) { PR_NOT_REACHED("Whoa!"); break; } } else break; } while (bytes_sent < sizeof(buffer)); PR_ASSERT(sizeof(buffer) == bytes_sent); bytes_read = 0; do { if (verbosity > chatty) PR_fprintf( logFile, "Client receiving %d bytes\n", bytes_sent - bytes_read); ready = PR_Recv( stack, buffer + bytes_read, bytes_sent - bytes_read, empty_flags, PR_INTERVAL_NO_TIMEOUT); if (verbosity > chatty) PR_fprintf( logFile, "Client receive status [%d]\n", ready); if (0 < ready) bytes_read += ready; else if ((-1 == ready) && (PR_WOULD_BLOCK_ERROR == PR_GetError())) { polldesc.fd = stack; polldesc.out_flags = 0; polldesc.in_flags = PR_POLL_READ; ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT); if ((1 != ready) /* if not 1, then we're dead */ || (0 == (polldesc.in_flags & polldesc.out_flags))) { PR_NOT_REACHED("Whoa!"); break; } } else break; } while (bytes_read < bytes_sent); if (verbosity > chatty) PR_fprintf(logFile, "Client received %d bytes\n", bytes_read); PR_ASSERT(bytes_read == bytes_sent); } if (verbosity > quiet) PR_fprintf(logFile, "Client shutting down stack\n"); rv = PR_Shutdown(stack, PR_SHUTDOWN_BOTH); PR_ASSERT(PR_SUCCESS == rv); } /* Client */
int main(int argc, char **argv) { PRFileDesc *listenSock1, *listenSock2; PRFileDesc *badFD; PRUint16 listenPort1, listenPort2; PRNetAddr addr; char buf[128]; PRPollDesc pds0[10], pds1[10], *pds, *other_pds; PRIntn npds; PRInt32 retVal; /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name -d */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "d:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = 1; break; default: break; } } PL_DestroyOptState(opt); /* main test */ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); if (debug_mode) { printf("This program tests PR_Poll with sockets.\n"); printf("error reporting is tested.\n\n"); } /* Create two listening sockets */ if ((listenSock1 = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a new TCP socket\n"); failed_already=1; goto exit_now; } addr.inet.family = AF_INET; addr.inet.ip = PR_htonl(INADDR_ANY); addr.inet.port = PR_htons(0); if (PR_Bind(listenSock1, &addr) == PR_FAILURE) { fprintf(stderr, "Can't bind socket\n"); failed_already=1; goto exit_now; } if (PR_GetSockName(listenSock1, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); failed_already=1; goto exit_now; } listenPort1 = PR_ntohs(addr.inet.port); if (PR_Listen(listenSock1, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); failed_already=1; goto exit_now; } if ((listenSock2 = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a new TCP socket\n"); failed_already=1; goto exit_now; } addr.inet.family = AF_INET; addr.inet.ip = PR_htonl(INADDR_ANY); addr.inet.port = PR_htons(0); if (PR_Bind(listenSock2, &addr) == PR_FAILURE) { fprintf(stderr, "Can't bind socket\n"); failed_already=1; goto exit_now; } if (PR_GetSockName(listenSock2, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); failed_already=1; goto exit_now; } listenPort2 = PR_ntohs(addr.inet.port); if (PR_Listen(listenSock2, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); failed_already=1; goto exit_now; } PR_snprintf(buf, sizeof(buf), "The server thread is listening on ports %hu and %hu\n\n", listenPort1, listenPort2); if (debug_mode) printf("%s", buf); /* Set up the poll descriptor array */ pds = pds0; other_pds = pds1; memset(pds, 0, sizeof(pds)); pds[0].fd = listenSock1; pds[0].in_flags = PR_POLL_READ; pds[1].fd = listenSock2; pds[1].in_flags = PR_POLL_READ; npds = 2; /* Testing bad fd */ if (debug_mode) printf("PR_Poll should detect a bad file descriptor\n"); if ((badFD = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a TCP socket\n"); goto exit_now; } pds[2].fd = badFD; pds[2].in_flags = PR_POLL_READ; npds = 3; if (PR_CreateThread(PR_USER_THREAD, ClientThreadFunc, badFD, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0) == NULL) { fprintf(stderr, "cannot create thread\n"); exit(1); } retVal = PR_Poll(pds, npds, PR_INTERVAL_NO_TIMEOUT); if (retVal != 1 || (unsigned short) pds[2].out_flags != PR_POLL_NVAL) { fprintf(stderr, "Failed to detect the bad fd: " "PR_Poll returns %d, out_flags is 0x%hx\n", retVal, pds[2].out_flags); failed_already=1; goto exit_now; } if (debug_mode) printf("PR_Poll detected the bad fd. Test passed.\n\n"); PR_Cleanup(); goto exit_now; exit_now: if(failed_already) return 1; else return 0; }
int main(int argc, char **argv) { PRHostEnt he; char buf[1024]; PRNetAddr addr; PRFileDesc *sock; PRPollDesc pd; PRStatus rv; PRSocketOptionData optData; PRIntn n; #ifdef XP_MAC int index; PRIntervalTime timeout; SetupMacPrintfLog("nbconn.log"); for (index=0; index<4; index++) { argv[1] = hosts[index]; timeout = PR_INTERVAL_NO_TIMEOUT; if (index == 3) timeout = PR_SecondsToInterval(10UL); #endif PR_STDIO_INIT(); #ifndef XP_MAC if (argc != 2) { fprintf(stderr, "Usage: nbconn <hostname>\n"); exit(1); } #endif if (PR_GetHostByName(argv[1], buf, sizeof(buf), &he) == PR_FAILURE) { printf( "Unknown host: %s\n", buf); exit(1); } else { printf( "host: %s\n", buf); } PR_EnumerateHostEnt(0, &he, 80, &addr); sock = PR_NewTCPSocket(); optData.option = PR_SockOpt_Nonblocking; optData.value.non_blocking = PR_TRUE; PR_SetSocketOption(sock, &optData); rv = PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT); if (rv == PR_FAILURE && PR_GetError() == PR_IN_PROGRESS_ERROR) { printf( "Connect in progress\n"); } pd.fd = sock; pd.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT; #ifndef XP_MAC n = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT); #else n = PR_Poll(&pd, 1, timeout); #endif if (n == -1) { printf( "PR_Poll failed\n"); exit(1); } printf( "PR_Poll returns %d\n", n); if (pd.out_flags & PR_POLL_READ) { printf( "PR_POLL_READ\n"); } if (pd.out_flags & PR_POLL_WRITE) { printf( "PR_POLL_WRITE\n"); } if (pd.out_flags & PR_POLL_EXCEPT) { printf( "PR_POLL_EXCEPT\n"); } if (pd.out_flags & PR_POLL_ERR) { printf( "PR_POLL_ERR\n"); } if (pd.out_flags & PR_POLL_NVAL) { printf( "PR_POLL_NVAL\n"); } if (PR_GetConnectStatus(&pd) == PR_SUCCESS) { printf("PR_GetConnectStatus: connect succeeded\n"); /* Mac and Win16 have trouble printing to the console. */ #if !defined(XP_MAC) && !defined(WIN16) PR_Write(sock, "GET /\r\n\r\n", 9); PR_Shutdown(sock, PR_SHUTDOWN_SEND); pd.in_flags = PR_POLL_READ; while (1) { n = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT); printf( "poll returns %d\n", n); n = PR_Read(sock, buf, sizeof(buf)); printf( "read returns %d\n", n); if (n <= 0) { break; } PR_Write(PR_STDOUT, buf, n); } #endif } else { if (PR_GetError() == PR_IN_PROGRESS_ERROR) { printf( "PR_GetConnectStatus: connect still in progress\n"); exit(1); } printf( "PR_GetConnectStatus: connect failed: (%ld, %ld)\n", PR_GetError(), PR_GetOSError()); } PR_Close(sock); #ifdef XP_MAC } /* end of for loop */ #endif printf( "PASS\n"); return 0; }
JD_METHOD_(JDint32) CNSAdapter_NSPR::JD_Poll(struct JDPollDesc pds[], int npds, JDUint32 JDIntervalTime) { return PR_Poll((PRPollDesc*)pds, (PRIntn)npds, (PRIntervalTime)JDIntervalTime); }
int main(int argc, char **argv) { PRFileDesc *listenSock1 = NULL, *listenSock2 = NULL; PRUint16 listenPort1, listenPort2; PRNetAddr addr; char buf[128]; PRThread *clientThread; PRPollDesc pds0[20], pds1[20], *pds, *other_pds; PRIntn npds; PRInt32 retVal; PRIntn i, j; PRSocketOptionData optval; /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name -d */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "d:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = 1; break; default: break; } } PL_DestroyOptState(opt); /* main test */ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); if (debug_mode) { printf("This program tests PR_Poll with sockets.\n"); printf("Normal operation are tested.\n\n"); } /* Create two listening sockets */ if ((listenSock1 = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a new TCP socket\n"); failed_already=1; goto exit_now; } memset(&addr, 0, sizeof(addr)); addr.inet.family = PR_AF_INET; addr.inet.ip = PR_htonl(PR_INADDR_ANY); addr.inet.port = PR_htons(0); if (PR_Bind(listenSock1, &addr) == PR_FAILURE) { fprintf(stderr, "Can't bind socket\n"); failed_already=1; goto exit_now; } if (PR_GetSockName(listenSock1, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); failed_already=1; goto exit_now; } listenPort1 = PR_ntohs(addr.inet.port); optval.option = PR_SockOpt_Nonblocking; optval.value.non_blocking = PR_TRUE; PR_SetSocketOption(listenSock1, &optval); if (PR_Listen(listenSock1, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); failed_already=1; goto exit_now; } if ((listenSock2 = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a new TCP socket\n"); failed_already=1; goto exit_now; } addr.inet.family = PR_AF_INET; addr.inet.ip = PR_htonl(PR_INADDR_ANY); addr.inet.port = PR_htons(0); if (PR_Bind(listenSock2, &addr) == PR_FAILURE) { fprintf(stderr, "Can't bind socket\n"); failed_already=1; goto exit_now; } if (PR_GetSockName(listenSock2, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); failed_already=1; goto exit_now; } listenPort2 = PR_ntohs(addr.inet.port); PR_SetSocketOption(listenSock2, &optval); if (PR_Listen(listenSock2, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); failed_already=1; goto exit_now; } PR_snprintf(buf, sizeof(buf), "The server thread is listening on ports %hu and %hu\n\n", listenPort1, listenPort2); if (debug_mode) printf("%s", buf); /* Set up the poll descriptor array */ pds = pds0; other_pds = pds1; memset(pds, 0, sizeof(pds)); pds[0].fd = listenSock1; pds[0].in_flags = PR_POLL_READ; pds[1].fd = listenSock2; pds[1].in_flags = PR_POLL_READ; /* Add some unused entries to test if they are ignored by PR_Poll() */ memset(&pds[2], 0, sizeof(pds[2])); memset(&pds[3], 0, sizeof(pds[3])); memset(&pds[4], 0, sizeof(pds[4])); npds = 5; clientThread = PR_CreateThread(PR_USER_THREAD, clientThreadFunc, (void *) listenPort1, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0); if (clientThread == NULL) { fprintf(stderr, "can't create thread\n"); failed_already=1; goto exit_now; } clientThread = PR_CreateThread(PR_USER_THREAD, clientThreadFunc, (void *) listenPort2, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0); if (clientThread == NULL) { fprintf(stderr, "can't create thread\n"); failed_already=1; goto exit_now; } if (debug_mode) { printf("Two client threads are created. Each of them will\n"); printf("send data to one of the two ports the server is listening on.\n"); printf("The data they send is the port number. Each of them send\n"); printf("the data five times, so you should see ten lines below,\n"); printf("interleaved in an arbitrary order.\n"); } /* two clients, three events per iteration: accept, read, close */ i = 0; while (i < 2 * 3 * NUM_ITERATIONS) { PRPollDesc *tmp; int nextIndex; int nEvents = 0; retVal = PR_Poll(pds, npds, PR_INTERVAL_NO_TIMEOUT); PR_ASSERT(retVal != 0); /* no timeout */ if (retVal == -1) { fprintf(stderr, "PR_Poll failed\n"); failed_already=1; goto exit_now; } nextIndex = 2; /* the two listening sockets */ for (j = 0; j < 2; j++) { other_pds[j] = pds[j]; PR_ASSERT((pds[j].out_flags & PR_POLL_WRITE) == 0 && (pds[j].out_flags & PR_POLL_EXCEPT) == 0); if (pds[j].out_flags & PR_POLL_READ) { PRFileDesc *sock; nEvents++; sock = PR_Accept(pds[j].fd, NULL, PR_INTERVAL_NO_TIMEOUT); if (sock == NULL) { fprintf(stderr, "PR_Accept() failed\n"); failed_already=1; goto exit_now; } other_pds[nextIndex].fd = sock; other_pds[nextIndex].in_flags = PR_POLL_READ; nextIndex++; } else if (pds[j].out_flags & PR_POLL_ERR) { fprintf(stderr, "PR_Poll() indicates that an fd has error\n"); failed_already=1; goto exit_now; } else if (pds[j].out_flags & PR_POLL_NVAL) { fprintf(stderr, "PR_Poll() indicates that fd %d is invalid\n", PR_FileDesc2NativeHandle(pds[j].fd)); failed_already=1; goto exit_now; } } for (j = 2; j < npds; j++) { if (NULL == pds[j].fd) { /* * Keep the unused entries in the poll descriptor array * for testing purposes. */ other_pds[nextIndex] = pds[j]; nextIndex++; continue; } PR_ASSERT((pds[j].out_flags & PR_POLL_WRITE) == 0 && (pds[j].out_flags & PR_POLL_EXCEPT) == 0); if (pds[j].out_flags & PR_POLL_READ) { PRInt32 nAvail; PRInt32 nRead; nEvents++; nAvail = PR_Available(pds[j].fd); nRead = PR_Read(pds[j].fd, buf, sizeof(buf)); PR_ASSERT(nAvail == nRead); if (nRead == -1) { fprintf(stderr, "PR_Read() failed\n"); failed_already=1; goto exit_now; } else if (nRead == 0) { PR_Close(pds[j].fd); continue; } else { /* Just to be safe */ buf[127] = '\0'; if (debug_mode) printf("The server received \"%s\" from a client\n", buf); } } else if (pds[j].out_flags & PR_POLL_ERR) { fprintf(stderr, "PR_Poll() indicates that an fd has error\n"); failed_already=1; goto exit_now; } else if (pds[j].out_flags & PR_POLL_NVAL) { fprintf(stderr, "PR_Poll() indicates that an fd is invalid\n"); failed_already=1; goto exit_now; } other_pds[nextIndex] = pds[j]; nextIndex++; } PR_ASSERT(retVal == nEvents); /* swap */ tmp = pds; pds = other_pds; other_pds = tmp; npds = nextIndex; i += nEvents; } if (debug_mode) printf("Tests passed\n"); exit_now: if (listenSock1) { PR_Close(listenSock1); } if (listenSock2) { PR_Close(listenSock2); } PR_Cleanup(); if(failed_already) return 1; else return 0; }
static void PR_CALLBACK clientThreadFunc(void *arg) { PRUintn port = (PRUintn)arg; PRFileDesc *sock; PRNetAddr addr; char buf[CHUNK_SIZE]; int i; PRIntervalTime unitTime = PR_MillisecondsToInterval(UNIT_TIME); PRSocketOptionData optval; PRStatus retVal; PRInt32 nBytes; /* Initialize the buffer so that Purify won't complain */ memset(buf, 0, sizeof(buf)); addr.inet.family = PR_AF_INET; addr.inet.port = PR_htons((PRUint16)port); addr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK); PR_snprintf(buf, sizeof(buf), "%hu", addr.inet.ip); /* time 1 */ PR_Sleep(unitTime); sock = PR_NewTCPSocket(); optval.option = PR_SockOpt_Nonblocking; optval.value.non_blocking = PR_TRUE; PR_SetSocketOption(sock, &optval); retVal = PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT); if (retVal == PR_FAILURE && PR_GetError() == PR_IN_PROGRESS_ERROR) { #if !defined(USE_PR_SELECT) PRPollDesc pd; PRInt32 n; fprintf(stderr, "connect: EWOULDBLOCK, good\n"); pd.fd = sock; pd.in_flags = PR_POLL_WRITE; n = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT); PR_ASSERT(n == 1); PR_ASSERT(pd.out_flags == PR_POLL_WRITE); #else PR_fd_set writeSet; PRInt32 n; fprintf(stderr, "connect: EWOULDBLOCK, good\n"); PR_FD_ZERO(&writeSet); PR_FD_SET(sock, &writeSet); n = PR_Select(0, NULL, &writeSet, NULL, PR_INTERVAL_NO_TIMEOUT); PR_ASSERT(n == 1); PR_ASSERT(PR_FD_ISSET(sock, &writeSet)); #endif } printf("client connected\n"); fflush(stdout); /* time 4, 7, 11, etc. */ for (i = 0; i < NUMBER_ROUNDS; i++) { PR_Sleep(3 * unitTime); nBytes = PR_Write(sock, buf, sizeof(buf)); if (nBytes == -1) { if (PR_GetError() == PR_WOULD_BLOCK_ERROR) { fprintf(stderr, "write: EWOULDBLOCK\n"); exit(1); } else { fprintf(stderr, "write: failed\n"); } } printf("client sent %d bytes\n", nBytes); fflush(stdout); } PR_Close(sock); }
static PRStatus _MW_PollInternal(PRWaitGroup *group) { PRRecvWait **waiter; PRStatus rv = PR_FAILURE; PRUintn count, count_ready; PRIntervalTime polling_interval; group->poller = PR_GetCurrentThread(); PR_Unlock(group->ml); while (PR_TRUE) { PRIntervalTime now, since_last_poll; PRPollDesc *poll_list = group->polling_list; /* ** There's something to do. See if our existing polling list ** is large enough for what we have to do? */ while (group->polling_count < group->waiter->count) { PRUint32 old_count = group->waiter->count; PRUint32 new_count = PR_ROUNDUP(old_count, _PR_POLL_COUNT_FUDGE); PRSize new_size = sizeof(PRPollDesc) * new_count; poll_list = (PRPollDesc*)PR_CALLOC(new_size); if (NULL == poll_list) goto failed_alloc; if (NULL != group->polling_list) PR_DELETE(group->polling_list); group->polling_list = poll_list; group->polling_count = new_count; } now = PR_IntervalNow(); polling_interval = max_polling_interval; since_last_poll = now - group->last_poll; PR_Lock(group->ml); waiter = &group->waiter->recv_wait; for (count = 0; count < group->waiter->count; ++waiter) { if (NULL != *waiter) /* a live one! */ { if (since_last_poll >= (*waiter)->timeout) _MW_DoneInternal(group, waiter, PR_MW_TIMEOUT); else { if (PR_INTERVAL_NO_TIMEOUT != (*waiter)->timeout) { (*waiter)->timeout -= since_last_poll; if ((*waiter)->timeout < polling_interval) polling_interval = (*waiter)->timeout; } poll_list->fd = (*waiter)->fd; poll_list->in_flags = PR_POLL_READ; poll_list->out_flags = 0; #if 0 printf( "Polling 0x%x[%d]: [fd: 0x%x, tmo: %u]\n", poll_list, count, poll_list->fd, (*waiter)->timeout); #endif poll_list += 1; count += 1; } } } PR_ASSERT(count == group->waiter->count); if (0 == count) break; group->last_poll = now; PR_Unlock(group->ml); count_ready = PR_Poll(group->polling_list, count, polling_interval); PR_Lock(group->ml); if (-1 == count_ready) goto failed_poll; /* that's a shame */ for (poll_list = group->polling_list; count > 0; poll_list++, count--) { if (poll_list->out_flags != 0) { waiter = _MW_LookupInternal(group, poll_list->fd); if (NULL != waiter) _MW_DoneInternal(group, waiter, PR_MW_SUCCESS); } } /* ** If there are no more threads waiting for completion, ** we need to return. ** This thread was "borrowed" to do the polling, but it really ** belongs to the client. */ if ((_prmw_running != group->state) || (0 == group->waiting_threads)) break; PR_Unlock(group->ml); } rv = PR_SUCCESS; failed_poll: failed_alloc: group->poller = NULL; /* we were that, not we ain't */ return rv; /* we return with the lock held */ } /* _MW_PollInternal */
static int qnetd_poll(struct qnetd_instance *instance) { struct qnetd_client *client; PRPollDesc *pfds; PRInt32 poll_res; ssize_t i; int client_disconnect; struct qnetd_poll_array_user_data *user_data; struct unix_socket_client *ipc_client; client = NULL; client_disconnect = 0; pfds = qnetd_pr_poll_array_create(instance); if (pfds == NULL) { return (-1); } if ((poll_res = PR_Poll(pfds, pr_poll_array_size(&instance->poll_array), timer_list_time_to_expire(&instance->main_timer_list))) >= 0) { timer_list_expire(&instance->main_timer_list); /* * Walk thru pfds array and process events */ for (i = 0; i < pr_poll_array_size(&instance->poll_array); i++) { user_data = pr_poll_array_get_user_data(&instance->poll_array, i); client = NULL; ipc_client = NULL; client_disconnect = 0; switch (user_data->type) { case QNETD_POLL_ARRAY_USER_DATA_TYPE_SOCKET: break; case QNETD_POLL_ARRAY_USER_DATA_TYPE_CLIENT: client = user_data->client; client_disconnect = client->schedule_disconnect; break; case QNETD_POLL_ARRAY_USER_DATA_TYPE_IPC_SOCKET: break; case QNETD_POLL_ARRAY_USER_DATA_TYPE_IPC_CLIENT: ipc_client = user_data->ipc_client; client_disconnect = ipc_client->schedule_disconnect; } if (!client_disconnect && poll_res > 0 && pfds[i].out_flags & PR_POLL_READ) { switch (user_data->type) { case QNETD_POLL_ARRAY_USER_DATA_TYPE_SOCKET: qnetd_client_net_accept(instance); break; case QNETD_POLL_ARRAY_USER_DATA_TYPE_CLIENT: if (qnetd_client_net_read(instance, client) == -1) { client_disconnect = 1; } break; case QNETD_POLL_ARRAY_USER_DATA_TYPE_IPC_SOCKET: qnetd_ipc_accept(instance, &ipc_client); break; case QNETD_POLL_ARRAY_USER_DATA_TYPE_IPC_CLIENT: qnetd_ipc_io_read(instance, ipc_client); break; } } if (!client_disconnect && poll_res > 0 && pfds[i].out_flags & PR_POLL_WRITE) { switch (user_data->type) { case QNETD_POLL_ARRAY_USER_DATA_TYPE_SOCKET: /* * Poll write on listen socket -> fatal error */ qnetd_log(LOG_CRIT, "POLL_WRITE on listening socket"); return (-1); break; case QNETD_POLL_ARRAY_USER_DATA_TYPE_CLIENT: if (qnetd_client_net_write(instance, client) == -1) { client_disconnect = 1; } break; case QNETD_POLL_ARRAY_USER_DATA_TYPE_IPC_SOCKET: qnetd_log(LOG_CRIT, "POLL_WRITE on listening IPC socket"); return (-1); break; case QNETD_POLL_ARRAY_USER_DATA_TYPE_IPC_CLIENT: qnetd_ipc_io_write(instance, ipc_client); break; } } if (!client_disconnect && poll_res > 0 && (pfds[i].out_flags & (PR_POLL_ERR|PR_POLL_NVAL|PR_POLL_HUP|PR_POLL_EXCEPT)) && !(pfds[i].out_flags & (PR_POLL_READ|PR_POLL_WRITE))) { switch (user_data->type) { case QNETD_POLL_ARRAY_USER_DATA_TYPE_SOCKET: case QNETD_POLL_ARRAY_USER_DATA_TYPE_IPC_SOCKET: if (pfds[i].out_flags != PR_POLL_NVAL) { /* * Poll ERR on listening socket is fatal error. * POLL_NVAL is used as a signal to quit poll loop. */ qnetd_log(LOG_CRIT, "POLL_ERR (%u) on listening " "socket", pfds[i].out_flags); } else { qnetd_log(LOG_DEBUG, "Listening socket is closed"); } return (-1); break; case QNETD_POLL_ARRAY_USER_DATA_TYPE_CLIENT: qnetd_log(LOG_DEBUG, "POLL_ERR (%u) on client socket. " "Disconnecting.", pfds[i].out_flags); client_disconnect = 1; break; case QNETD_POLL_ARRAY_USER_DATA_TYPE_IPC_CLIENT: qnetd_log(LOG_DEBUG, "POLL_ERR (%u) on ipc client socket." " Disconnecting.", pfds[i].out_flags); client_disconnect = 1; break; } } /* * If client is scheduled for disconnect, disconnect it */ if (user_data->type == QNETD_POLL_ARRAY_USER_DATA_TYPE_CLIENT && client_disconnect) { qnetd_instance_client_disconnect(instance, client, 0); } else if (user_data->type == QNETD_POLL_ARRAY_USER_DATA_TYPE_IPC_CLIENT && (client_disconnect || ipc_client->schedule_disconnect)) { qnetd_ipc_client_disconnect(instance, ipc_client); } } } return (0); }
static void PollThread(void *arg) { PRIntervalTime timeout = (PRIntervalTime) arg; PRIntervalTime elapsed; #if defined(XP_UNIX) || defined(WIN32) PRInt32 timeout_msecs = PR_IntervalToMilliseconds(timeout); PRInt32 elapsed_msecs; #endif #if defined(XP_UNIX) struct timeval end_time_tv; #endif #if defined(WIN32) && !defined(WINCE) struct _timeb end_time_tb; #endif PRFileDesc *sock; PRNetAddr addr; PRPollDesc pd; PRIntn rv; sock = PR_NewTCPSocket(); if (sock == NULL) { fprintf(stderr, "PR_NewTCPSocket failed\n"); exit(1); } memset(&addr, 0, sizeof(addr)); addr.inet.family = PR_AF_INET; addr.inet.port = 0; addr.inet.ip = PR_htonl(PR_INADDR_ANY); if (PR_Bind(sock, &addr) == PR_FAILURE) { fprintf(stderr, "PR_Bind failed\n"); exit(1); } if (PR_Listen(sock, 5) == PR_FAILURE) { fprintf(stderr, "PR_Listen failed\n"); exit(1); } pd.fd = sock; pd.in_flags = PR_POLL_READ; rv = PR_Poll(&pd, 1, timeout); if (rv != 0) { fprintf(stderr, "PR_Poll did not time out\n"); exit(1); } elapsed = (PRIntervalTime)(PR_IntervalNow() - start_time); if (elapsed + tolerance < timeout || elapsed > timeout + tolerance) { fprintf(stderr, "timeout wrong\n"); exit(1); } #if defined(XP_UNIX) gettimeofday(&end_time_tv, NULL); elapsed_msecs = 1000*(end_time_tv.tv_sec - start_time_tv.tv_sec) + (end_time_tv.tv_usec - start_time_tv.tv_usec)/1000; #endif #if defined(WIN32) #if defined(WINCE) elapsed_msecs = GetTickCount() - start_time_tick; #else _ftime(&end_time_tb); elapsed_msecs = 1000*(end_time_tb.time - start_time_tb.time) + (end_time_tb.millitm - start_time_tb.millitm); #endif #endif #if defined(XP_UNIX) || defined(WIN32) if (elapsed_msecs + tolerance_msecs < timeout_msecs || elapsed_msecs > timeout_msecs + tolerance_msecs) { fprintf(stderr, "timeout wrong\n"); exit(1); } #endif if (PR_Close(sock) == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } if (debug_mode) { fprintf(stderr, "Poll thread (scope %d) done\n", PR_GetThreadScope(PR_GetCurrentThread())); } }
/* Non-blocking I/O */ static void ClientNB(void *arg) { PRFileDesc *sock; PRSocketOptionData opt; PRUint16 port = (PRUint16) arg; PRNetAddr addr; char buf[BUFFER_SIZE]; PRPollDesc pd; PRInt32 npds; PRInt32 nbytes; int i; int j; sock = PR_OpenTCPSocket(PR_AF_INET6); if (NULL == sock) { fprintf(stderr, "PR_OpenTCPSocket failed\n"); exit(1); } opt.option = PR_SockOpt_Nonblocking; opt.value.non_blocking = PR_TRUE; if (PR_SetSocketOption(sock, &opt) == PR_FAILURE) { fprintf(stderr, "PR_SetSocketOption failed\n"); exit(1); } memset(&addr, 0, sizeof(addr)); if (PR_SetNetAddr(PR_IpAddrLoopback, PR_AF_INET6, port, &addr) == PR_FAILURE) { fprintf(stderr, "PR_SetNetAddr failed\n"); exit(1); } if (PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) { if (PR_GetError() != PR_IN_PROGRESS_ERROR) { fprintf(stderr, "PR_Connect failed\n"); exit(1); } pd.fd = sock; pd.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT; npds = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT); if (-1 == npds) { fprintf(stderr, "PR_Poll failed\n"); exit(1); } if (1 != npds) { fprintf(stderr, "PR_Poll returned %d, absurd!\n", npds); exit(1); } if (PR_GetConnectStatus(&pd) == PR_FAILURE) { fprintf(stderr, "PR_GetConnectStatus failed\n"); exit(1); } } for (i = 0; i < iterations; i++) { PR_Sleep(PR_SecondsToInterval(1)); memset(buf, 2*i, send_amount[i]); while ((nbytes = PR_Send(sock, buf, send_amount[i], 0, PR_INTERVAL_NO_TIMEOUT)) == -1) { if (PR_GetError() != PR_WOULD_BLOCK_ERROR) { fprintf(stderr, "PR_Send failed\n"); exit(1); } pd.fd = sock; pd.in_flags = PR_POLL_WRITE; npds = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT); if (-1 == npds) { fprintf(stderr, "PR_Poll failed\n"); exit(1); } if (1 != npds) { fprintf(stderr, "PR_Poll returned %d, absurd!\n", npds); exit(1); } } if (send_amount[i] != nbytes) { fprintf(stderr, "PR_Send returned %d, absurd!\n", nbytes); exit(1); } memset(buf, 0, sizeof(buf)); while ((nbytes = PR_Recv(sock, buf, recv_amount[i], PR_MSG_PEEK, PR_INTERVAL_NO_TIMEOUT)) == -1) { if (PR_GetError() != PR_WOULD_BLOCK_ERROR) { fprintf(stderr, "PR_Recv failed\n"); exit(1); } pd.fd = sock; pd.in_flags = PR_POLL_READ; npds = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT); if (-1 == npds) { fprintf(stderr, "PR_Poll failed\n"); exit(1); } if (1 != npds) { fprintf(stderr, "PR_Poll returned %d, absurd!\n", npds); exit(1); } } if (send_amount[i] != nbytes) { fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes); exit(1); } for (j = 0; j < nbytes; j++) { if (buf[j] != 2*i+1) { fprintf(stderr, "byte %d should be %d but is %d\n", j, 2*i+1, buf[j]); exit(1); } } fprintf(stderr, "client: peeked expected data\n"); memset(buf, 0, sizeof(buf)); nbytes = PR_Recv(sock, buf, recv_amount[i], PR_MSG_PEEK, PR_INTERVAL_NO_TIMEOUT); if (-1 == nbytes) { fprintf(stderr, "PR_Recv failed\n"); exit(1); } if (send_amount[i] != nbytes) { fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes); exit(1); } for (j = 0; j < nbytes; j++) { if (buf[j] != 2*i+1) { fprintf(stderr, "byte %d should be %d but is %d\n", j, 2*i+1, buf[j]); exit(1); } } fprintf(stderr, "client: peeked expected data\n"); memset(buf, 0, sizeof(buf)); nbytes = PR_Recv(sock, buf, recv_amount[i], 0, PR_INTERVAL_NO_TIMEOUT); if (-1 == nbytes) { fprintf(stderr, "PR_Recv failed\n"); exit(1); } if (send_amount[i] != nbytes) { fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes); exit(1); } for (j = 0; j < nbytes; j++) { if (buf[j] != 2*i+1) { fprintf(stderr, "byte %d should be %d but is %d\n", j, 2*i+1, buf[j]); exit(1); } } fprintf(stderr, "client: received expected data\n"); } if (PR_Close(sock) == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } }
/* * io worker thread function */ static void io_wstart(void *arg) { PRThreadPool *tp = (PRThreadPool *) arg; int pollfd_cnt, pollfds_used; int rv; PRCList *qp, *nextqp; PRPollDesc *pollfds; PRJob **polljobs; int poll_timeout; PRIntervalTime now; /* * scan io_jobq * construct poll list * call PR_Poll * for all fds, for which poll returns true, move the job to * jobq and wakeup worker thread. */ while (!tp->shutdown) { PRJob *jobp; pollfd_cnt = tp->ioq.cnt + 10; if (pollfd_cnt > tp->ioq.npollfds) { /* * re-allocate pollfd array if the current one is not large * enough */ if (NULL != tp->ioq.pollfds) PR_Free(tp->ioq.pollfds); tp->ioq.pollfds = (PRPollDesc *) PR_Malloc(pollfd_cnt * (sizeof(PRPollDesc) + sizeof(PRJob *))); PR_ASSERT(NULL != tp->ioq.pollfds); /* * array of pollfds */ pollfds = tp->ioq.pollfds; tp->ioq.polljobs = (PRJob **) (&tp->ioq.pollfds[pollfd_cnt]); /* * parallel array of jobs */ polljobs = tp->ioq.polljobs; tp->ioq.npollfds = pollfd_cnt; } pollfds_used = 0; /* * add the notify fd; used for unblocking io thread(s) */ pollfds[pollfds_used].fd = tp->ioq.notify_fd; pollfds[pollfds_used].in_flags = PR_POLL_READ; pollfds[pollfds_used].out_flags = 0; polljobs[pollfds_used] = NULL; pollfds_used++; /* * fill in the pollfd array */ PR_Lock(tp->ioq.lock); for (qp = tp->ioq.list.next; qp != &tp->ioq.list; qp = nextqp) { nextqp = qp->next; jobp = JOB_LINKS_PTR(qp); if (jobp->cancel_io) { CANCEL_IO_JOB(jobp); continue; } if (pollfds_used == (pollfd_cnt)) break; pollfds[pollfds_used].fd = jobp->iod->socket; pollfds[pollfds_used].in_flags = jobp->io_poll_flags; pollfds[pollfds_used].out_flags = 0; polljobs[pollfds_used] = jobp; pollfds_used++; } if (!PR_CLIST_IS_EMPTY(&tp->ioq.list)) { qp = tp->ioq.list.next; jobp = JOB_LINKS_PTR(qp); if (PR_INTERVAL_NO_TIMEOUT == jobp->timeout) poll_timeout = PR_INTERVAL_NO_TIMEOUT; else if (PR_INTERVAL_NO_WAIT == jobp->timeout) poll_timeout = PR_INTERVAL_NO_WAIT; else { poll_timeout = jobp->absolute - PR_IntervalNow(); if (poll_timeout <= 0) /* already timed out */ poll_timeout = PR_INTERVAL_NO_WAIT; } } else { poll_timeout = PR_INTERVAL_NO_TIMEOUT; } PR_Unlock(tp->ioq.lock); /* * XXXX * should retry if more jobs have been added to the queue? * */ PR_ASSERT(pollfds_used <= pollfd_cnt); rv = PR_Poll(tp->ioq.pollfds, pollfds_used, poll_timeout); if (tp->shutdown) { break; } if (rv > 0) { /* * at least one io event is set */ PRStatus rval_status; PRInt32 index; PR_ASSERT(pollfds[0].fd == tp->ioq.notify_fd); /* * reset the pollable event, if notified */ if (pollfds[0].out_flags & PR_POLL_READ) { rval_status = PR_WaitForPollableEvent(tp->ioq.notify_fd); PR_ASSERT(PR_SUCCESS == rval_status); } for(index = 1; index < (pollfds_used); index++) { PRInt16 events = pollfds[index].in_flags; PRInt16 revents = pollfds[index].out_flags; jobp = polljobs[index]; if ((revents & PR_POLL_NVAL) || /* busted in all cases */ (revents & PR_POLL_ERR) || ((events & PR_POLL_WRITE) && (revents & PR_POLL_HUP))) { /* write op & hup */ PR_Lock(tp->ioq.lock); if (jobp->cancel_io) { CANCEL_IO_JOB(jobp); PR_Unlock(tp->ioq.lock); continue; } PR_REMOVE_AND_INIT_LINK(&jobp->links); tp->ioq.cnt--; jobp->on_ioq = PR_FALSE; PR_Unlock(tp->ioq.lock); /* set error */ if (PR_POLL_NVAL & revents) jobp->iod->error = PR_BAD_DESCRIPTOR_ERROR; else if (PR_POLL_HUP & revents) jobp->iod->error = PR_CONNECT_RESET_ERROR; else jobp->iod->error = PR_IO_ERROR; /* * add to jobq */ add_to_jobq(tp, jobp); } else if (revents) { /* * add to jobq */ PR_Lock(tp->ioq.lock); if (jobp->cancel_io) { CANCEL_IO_JOB(jobp); PR_Unlock(tp->ioq.lock); continue; } PR_REMOVE_AND_INIT_LINK(&jobp->links); tp->ioq.cnt--; jobp->on_ioq = PR_FALSE; PR_Unlock(tp->ioq.lock); if (jobp->io_op == JOB_IO_CONNECT) { if (PR_GetConnectStatus(&pollfds[index]) == PR_SUCCESS) jobp->iod->error = 0; else jobp->iod->error = PR_GetError(); } else jobp->iod->error = 0; add_to_jobq(tp, jobp); } } } /* * timeout processing */ now = PR_IntervalNow(); PR_Lock(tp->ioq.lock); for (qp = tp->ioq.list.next; qp != &tp->ioq.list; qp = nextqp) { nextqp = qp->next; jobp = JOB_LINKS_PTR(qp); if (jobp->cancel_io) { CANCEL_IO_JOB(jobp); continue; } if (PR_INTERVAL_NO_TIMEOUT == jobp->timeout) break; if ((PR_INTERVAL_NO_WAIT != jobp->timeout) && ((PRInt32)(jobp->absolute - now) > 0)) break; PR_REMOVE_AND_INIT_LINK(&jobp->links); tp->ioq.cnt--; jobp->on_ioq = PR_FALSE; jobp->iod->error = PR_IO_TIMEOUT_ERROR; add_to_jobq(tp, jobp); } PR_Unlock(tp->ioq.lock); } }
int main(int argc, char ** argv) { SECStatus rv; PRFileDesc *in; PRFileDesc *out; PRPollDesc pd; PRIntervalTime timeout = PR_INTERVAL_NO_TIMEOUT; char buf[1024]; PRInt32 nBytes; char * command; char * tokenName; char * tokenpw; int fipsmode = 0; int semid = 0; union semun semarg; if (argc < 4 || argc > 5) { fprintf(stderr, "Usage: nss_pcache <semid> <fips on/off> <directory> [prefix]\n"); exit(1); } signal(SIGHUP, SIG_IGN); semid = strtol(argv[1], NULL, 10); if (!strcasecmp(argv[2], "on")) fipsmode = 1; /* Initialize NSPR */ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 256); /* Set the PKCS #11 strings for the internal token. */ PK11_ConfigurePKCS11(NULL,NULL,NULL, INTERNAL_TOKEN_NAME, NULL, NULL,NULL,NULL,8,1); /* Initialize NSS and open the certificate database read-only. */ rv = NSS_Initialize(argv[3], argc == 5 ? argv[4] : NULL, argc == 5 ? argv[4] : NULL, "secmod.db", NSS_INIT_READONLY); if (rv != SECSuccess) { fprintf(stderr, "Unable to initialize NSS database: %d\n", rv); exit(1); } if (fipsmode) { if (!PK11_IsFIPS()) { char * internal_name = PR_smprintf("%s", SECMOD_GetInternalModule()->commonName); if ((SECMOD_DeleteInternalModule(internal_name) != SECSuccess) || !PK11_IsFIPS()) { NSS_Shutdown(); fprintf(stderr, "Unable to enable FIPS mode"); exit(1); } PR_smprintf_free(internal_name); } } in = PR_GetSpecialFD(PR_StandardInput); out = PR_GetSpecialFD(PR_StandardOutput); if (in == NULL || out == NULL) { fprintf(stderr, "PR_GetInheritedFD failed\n"); exit(1); } pd.fd = in; pd.in_flags = PR_POLL_READ | PR_POLL_EXCEPT; while (1) { rv = PR_Poll(&pd, 1, timeout); if (rv == -1) { /* PR_Poll failed */ break; } if (pd.out_flags & (PR_POLL_HUP | PR_POLL_ERR | PR_POLL_NVAL | PR_POLL_EXCEPT)) { break; } if (pd.out_flags & PR_POLL_READ) { memset(buf, 0, sizeof(buf)); nBytes = PR_Read(in, buf, sizeof(buf)); if (nBytes == -1 || nBytes == 0) { break; } command = getstr(buf, 0); tokenName = getstr(buf, 1); tokenpw = getstr(buf, 2); if (command && !strcmp(command, "QUIT")) { break; } else if (command && !strcmp(command, "STOR")) { PRInt32 err = PIN_SUCCESS; Node *node = NULL; if (tokenName && tokenpw) { node = (Node*)malloc(sizeof (Node)); if (!node) { err = PIN_NOMEMORY; } node->tokenName = strdup(tokenName); node->store = 0; node->next = 0; if (err == PIN_SUCCESS) err = CreatePk11PinStore(&node->store, tokenName, tokenpw); memset(tokenpw, 0, strlen(tokenpw)); } else err = PIN_SYSTEMERROR; sprintf(buf, "%d", err); PR_Write(out, buf, 1); if (err == PIN_SUCCESS) { if (pinList) node->next = pinList; pinList = node; } /* Now clean things up */ if (command) free(command); if (tokenName) free(tokenName); if (tokenpw) free(tokenpw); } else if (command && !strcmp(command, "RETR")) { Node *node; char *pin = 0; PRBool found = PR_FALSE; for (node = pinList; node != NULL; node = node->next) { if (!strcmp(node->tokenName, tokenName)) { if (Pk11StoreGetPin(&pin, node->store) == SECSuccess) { if (strlen(pin) == 0) PR_Write(out, "", 1); else PR_Write(out, pin, strlen(pin)); memset(pin, 0, strlen(pin)); free(pin); found = PR_TRUE; break; } } } if (found != PR_TRUE) PR_Write(out, "", 1); free(command); free(tokenName); } else { ; /* ack, unknown command */ } } } freeList(pinList); PR_Close(in); /* Remove the semaphore used for locking here. This is because this * program only goes away when Apache shuts down so we don't have to * worry about reloads. */ semctl(semid, 0, IPC_RMID, semarg); return 0; }
PR_IMPLEMENT(PRInt32) PR_Select( PRInt32 unused, PR_fd_set *pr_rd, PR_fd_set *pr_wr, PR_fd_set *pr_ex, PRIntervalTime timeout) { #if !defined(NEED_SELECT) PRInt32 npds = 0; /* ** Find out how many fds are represented in the three lists. ** Then allocate a polling descriptor for the logical union ** (there can't be any overlapping) and call PR_Poll(). */ PRPollDesc *copy, *poll; static PRBool warning = PR_TRUE; if (warning) warning = _PR_Obsolete( "PR_Select()", "PR_Poll()"); /* try to get an initial guesss at how much space we need */ npds = 0; if ((NULL != pr_rd) && ((pr_rd->hsize + pr_rd->nsize - npds) > 0)) npds = pr_rd->hsize + pr_rd->nsize; if ((NULL != pr_wr) && ((pr_wr->hsize + pr_wr->nsize - npds) > 0)) npds = pr_wr->hsize + pr_wr->nsize; if ((NULL != pr_ex) && ((pr_ex->hsize + pr_ex->nsize - npds) > 0)) npds = pr_ex->hsize + pr_ex->nsize; if (0 == npds) { PR_Sleep(timeout); return 0; } copy = poll = (PRPollDesc*)PR_Calloc(npds + PD_INCR, sizeof(PRPollDesc)); if (NULL == poll) goto out_of_memory; poll[npds + PD_INCR - 1].fd = (PRFileDesc*)-1; poll = _pr_setfd(pr_rd, PR_POLL_READ, poll); if (NULL == poll) goto out_of_memory; poll = _pr_setfd(pr_wr, PR_POLL_WRITE, poll); if (NULL == poll) goto out_of_memory; poll = _pr_setfd(pr_ex, PR_POLL_EXCEPT, poll); if (NULL == poll) goto out_of_memory; unused = 0; while (NULL != poll[unused].fd && (PRFileDesc*)-1 != poll[unused].fd) { ++unused; } PR_ASSERT(unused > 0); npds = PR_Poll(poll, unused, timeout); if (npds > 0) { /* Copy the results back into the fd sets */ if (NULL != pr_rd) pr_rd->nsize = pr_rd->hsize = 0; if (NULL != pr_wr) pr_wr->nsize = pr_wr->hsize = 0; if (NULL != pr_ex) pr_ex->nsize = pr_ex->hsize = 0; for (copy = &poll[unused - 1]; copy >= poll; --copy) { if (copy->out_flags & PR_POLL_NVAL) { PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0); npds = -1; break; } if (copy->out_flags & PR_POLL_READ) if (NULL != pr_rd) pr_rd->harray[pr_rd->hsize++] = copy->fd; if (copy->out_flags & PR_POLL_WRITE) if (NULL != pr_wr) pr_wr->harray[pr_wr->hsize++] = copy->fd; if (copy->out_flags & PR_POLL_EXCEPT) if (NULL != pr_ex) pr_ex->harray[pr_ex->hsize++] = copy->fd; } } PR_DELETE(poll); return npds; out_of_memory: PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return -1; #endif /* !defined(NEED_SELECT) */ }
static PRStatus _MW_PollInternal(PRWaitGroup *group) { PRRecvWait **waiter; PRStatus rv = PR_FAILURE; PRInt32 count, count_ready; PRIntervalTime polling_interval; group->poller = PR_GetCurrentThread(); while (PR_TRUE) { PRIntervalTime now, since_last_poll; PRPollDesc *poll_list; while (0 == group->waiter->count) { PRStatus st; st = PR_WaitCondVar(group->new_business, PR_INTERVAL_NO_TIMEOUT); if (_prmw_running != group->state) { PR_SetError(PR_INVALID_STATE_ERROR, 0); goto aborted; } if (_MW_ABORTED(st)) goto aborted; } /* ** There's something to do. See if our existing polling list ** is large enough for what we have to do? */ while (group->polling_count < group->waiter->count) { PRUint32 old_count = group->waiter->count; PRUint32 new_count = PR_ROUNDUP(old_count, _PR_POLL_COUNT_FUDGE); PRSize new_size = sizeof(PRPollDesc) * new_count; PRPollDesc *old_polling_list = group->polling_list; PR_Unlock(group->ml); poll_list = (PRPollDesc*)PR_CALLOC(new_size); if (NULL == poll_list) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); PR_Lock(group->ml); goto failed_alloc; } if (NULL != old_polling_list) PR_DELETE(old_polling_list); PR_Lock(group->ml); if (_prmw_running != group->state) { PR_SetError(PR_INVALID_STATE_ERROR, 0); goto aborted; } group->polling_list = poll_list; group->polling_count = new_count; } now = PR_IntervalNow(); polling_interval = max_polling_interval; since_last_poll = now - group->last_poll; waiter = &group->waiter->recv_wait; poll_list = group->polling_list; for (count = 0; count < group->waiter->count; ++waiter) { PR_ASSERT(waiter < &group->waiter->recv_wait + group->waiter->length); if (NULL != *waiter) /* a live one! */ { if ((PR_INTERVAL_NO_TIMEOUT != (*waiter)->timeout) && (since_last_poll >= (*waiter)->timeout)) _MW_DoneInternal(group, waiter, PR_MW_TIMEOUT); else { if (PR_INTERVAL_NO_TIMEOUT != (*waiter)->timeout) { (*waiter)->timeout -= since_last_poll; if ((*waiter)->timeout < polling_interval) polling_interval = (*waiter)->timeout; } PR_ASSERT(poll_list < group->polling_list + group->polling_count); poll_list->fd = (*waiter)->fd; poll_list->in_flags = PR_POLL_READ; poll_list->out_flags = 0; #if 0 printf( "Polling 0x%x[%d]: [fd: 0x%x, tmo: %u]\n", poll_list, count, poll_list->fd, (*waiter)->timeout); #endif poll_list += 1; count += 1; } } } PR_ASSERT(count == group->waiter->count); /* ** If there are no more threads waiting for completion, ** we need to return. */ if ((!PR_CLIST_IS_EMPTY(&group->io_ready)) && (1 == group->waiting_threads)) break; if (0 == count) continue; /* wait for new business */ group->last_poll = now; PR_Unlock(group->ml); count_ready = PR_Poll(group->polling_list, count, polling_interval); PR_Lock(group->ml); if (_prmw_running != group->state) { PR_SetError(PR_INVALID_STATE_ERROR, 0); goto aborted; } if (-1 == count_ready) { goto failed_poll; /* that's a shame */ } else if (0 < count_ready) { for (poll_list = group->polling_list; count > 0; poll_list++, count--) { PR_ASSERT( poll_list < group->polling_list + group->polling_count); if (poll_list->out_flags != 0) { waiter = _MW_LookupInternal(group, poll_list->fd); /* ** If 'waiter' is NULL, that means the wait receive ** descriptor has been canceled. */ if (NULL != waiter) _MW_DoneInternal(group, waiter, PR_MW_SUCCESS); } } } /* ** If there are no more threads waiting for completion, ** we need to return. ** This thread was "borrowed" to do the polling, but it really ** belongs to the client. */ if ((!PR_CLIST_IS_EMPTY(&group->io_ready)) && (1 == group->waiting_threads)) break; } rv = PR_SUCCESS; aborted: failed_poll: failed_alloc: group->poller = NULL; /* we were that, not we ain't */ if ((_prmw_running == group->state) && (group->waiting_threads > 1)) { /* Wake up one thread to become the new poller. */ PR_NotifyCondVar(group->io_complete); } return rv; /* we return with the lock held */ } /* _MW_PollInternal */