Пример #1
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);
	}
}
Пример #2
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 */
/* 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);
    }
}
Пример #4
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;
}