Ejemplo n.º 1
0
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;

}
Ejemplo n.º 2
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);
}
Ejemplo n.º 4
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();
}
Ejemplo n.º 7
0
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"));
}
Ejemplo n.º 8
0
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 */
Ejemplo n.º 9
0
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 */
Ejemplo n.º 10
0
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;
}
Ejemplo n.º 11
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;
}
Ejemplo n.º 12
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;

}
Ejemplo n.º 14
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);
}
Ejemplo n.º 15
0
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 */
Ejemplo n.º 16
0
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);
    }
}
Ejemplo n.º 19
0
/*
 * 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);
	}
}
Ejemplo n.º 20
0
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;
}
Ejemplo n.º 21
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) */
    
}
Ejemplo n.º 22
0
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 */