Пример #1
0
Файл: nwio.c Проект: DeadZen/qse
static int wait_for_data (qse_nwio_t* nwio, const qse_ntime_t* tmout, int what)
{
	int xret;

#if defined(USE_SELECT)
	fd_set fds[2];
	struct timeval tv;

	FD_ZERO (&fds[0]);
	FD_ZERO (&fds[1]);

	switch (what)
	{
		case 0:
		case 1:
			FD_SET (nwio->handle, &fds[what]);
			break;

		case 2:
			FD_SET (nwio->handle, &fds[0]);
			FD_SET (nwio->handle, &fds[1]);
			break;

		default:
			nwio->errnum = QSE_NWIO_EINVAL;
			return -1;
	}
	

	tv.tv_sec = tmout->sec;
	tv.tv_usec = QSE_NSEC_TO_USEC (tmout->nsec);

	xret = select (nwio->handle + 1, &fds[0], &fds[1], QSE_NULL, &tv);
	#if defined(_WIN32)
	if (xret == SOCKET_ERROR)
	#else
	if (xret <= -1)
	#endif
	{
	#if defined(_WIN32)
		nwio->errnum = skerr_to_errnum (WSAGetLastError());
	#elif defined(__OS2__)
		nwio->errnum = skerr_to_errnum (sock_errno());
	#else
		nwio->errnum = skerr_to_errnum (errno);
	#endif
		return -1;
	}
	else if (xret == 0)
	{
		nwio->errnum = QSE_NWIO_ETMOUT;
		return -1;
	}
	return 0;

#elif defined(__OS2__)
	int count[2] = { 0, 0 };
	long tmout_msecs; 
	
	count[what]++;

	tmout_msecs = QSE_SECNSEC_TO_MSEC (tmout->sec, tmout->nsec);
	xret = os2_select (&nwio->handle, count[0], count[1], 0, tmout_msecs);
	if (xret <= -1)
	{
		nwio->errnum = skerr_to_errnum (sock_errno());
		return -1;
	}
	else if (xret == 0)
	{
		nwio->errnum = QSE_NWIO_ETMOUT;
		return -1;
	}
	return 0;

#else
	nwio->errnum = QSE_NWIO_ENOIMPL;
	return -1;
#endif

}
Пример #2
0
PRInt32 _PR_MD_PR_POLL(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
{
#ifdef BSD_SELECT
    fd_set rd, wt, ex;
#else
    int rd, wt, ex;
    int* socks;
    unsigned long msecs;
    int i, j;
#endif
    PRFileDesc *bottom;
    PRPollDesc *pd, *epd;
    PRInt32 maxfd = -1, ready, err;
    PRIntervalTime remaining, elapsed, start;

#ifdef BSD_SELECT
    struct timeval tv, *tvp = NULL;

    FD_ZERO(&rd);
    FD_ZERO(&wt);
    FD_ZERO(&ex);
#else
    rd = 0;
    wt = 0;
    ex = 0;
    socks = (int) PR_MALLOC( npds * 3 * sizeof(int) );
    
    if (!socks)
    {
        PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
        return -1;
    }
#endif

    ready = 0;
    for (pd = pds, epd = pd + npds; pd < epd; pd++)
    {
        PRInt16 in_flags_read = 0, in_flags_write = 0;
        PRInt16 out_flags_read = 0, out_flags_write = 0;

        if ((NULL != pd->fd) && (0 != pd->in_flags))
        {
            if (pd->in_flags & PR_POLL_READ)
            {
                in_flags_read = (pd->fd->methods->poll)(
                    pd->fd, pd->in_flags & ~PR_POLL_WRITE, &out_flags_read);
            }
            if (pd->in_flags & PR_POLL_WRITE)
            {
                in_flags_write = (pd->fd->methods->poll)(
                    pd->fd, pd->in_flags & ~PR_POLL_READ, &out_flags_write);
            }
            if ((0 != (in_flags_read & out_flags_read)) ||
                (0 != (in_flags_write & out_flags_write)))
            {
                /* this one's ready right now */
                if (0 == ready)
                {
                    /*
                     * We will have to return without calling the
                     * system poll/select function.  So zero the
                     * out_flags fields of all the poll descriptors
                     * before this one.
                     */
                    PRPollDesc *prev;
                    for (prev = pds; prev < pd; prev++)
                    {
                        prev->out_flags = 0;
                    }
                }
                ready += 1;
                pd->out_flags = out_flags_read | out_flags_write;
            }
            else
            {
                pd->out_flags = 0;  /* pre-condition */

                /* make sure this is an NSPR supported stack */
                bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
                PR_ASSERT(NULL != bottom);  /* what to do about that? */
                if ((NULL != bottom) &&
                    (_PR_FILEDESC_OPEN == bottom->secret->state))
                {
                    if (0 == ready)
                    {
                        PRInt32 osfd = bottom->secret->md.osfd;
                        if (osfd > maxfd) 
                            maxfd = osfd;
                        if (in_flags_read & PR_POLL_READ)
                        {
                            pd->out_flags |= _PR_POLL_READ_SYS_READ;
#ifdef BSD_SELECT
                            FD_SET(osfd, &rd);
#else
                            socks[rd] = osfd;
                            rd++;              
#endif
                        }
                        if (in_flags_read & PR_POLL_WRITE)
                        {
                            pd->out_flags |= _PR_POLL_READ_SYS_WRITE;
#ifdef BSD_SELECT
                            FD_SET(osfd, &wt);
#else
                            socks[npds+wt] = osfd;
                            wt++;              
#endif
                        }
                        if (in_flags_write & PR_POLL_READ)
                        {
                            pd->out_flags |= _PR_POLL_WRITE_SYS_READ;
#ifdef BSD_SELECT
                            FD_SET(osfd, &rd);
#else
                            socks[rd] = osfd;
                            rd++;              
#endif
                        }
                        if (in_flags_write & PR_POLL_WRITE)
                        {
                            pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE;
#ifdef BSD_SELECT
                            FD_SET(osfd, &wt);
#else
                            socks[npds+wt] = osfd;
                            wt++;              
#endif
                        }
                        if (pd->in_flags & PR_POLL_EXCEPT)
                        {
#ifdef BSD_SELECT
                            FD_SET(osfd, &ex);
#else
                            socks[npds*2+ex] = osfd;
                            ex++;
#endif
                        }
                    }
                }
                else
                {
                    if (0 == ready)
                    {
                        PRPollDesc *prev;
                        for (prev = pds; prev < pd; prev++)
                        {
                            prev->out_flags = 0;
                        }
                    }
                    ready += 1;  /* this will cause an abrupt return */
                    pd->out_flags = PR_POLL_NVAL;  /* bogii */
                }
            }
        }
        else
        {
            pd->out_flags = 0;
        }
    }

    if (0 != ready)
    {
#ifndef BSD_SELECT
        PR_Free(socks);
#endif
        return ready;  /* no need to block */
    }

    remaining = timeout;
    start = PR_IntervalNow();

retry:
#ifdef BSD_SELECT
    if (timeout != PR_INTERVAL_NO_TIMEOUT)
    {
        PRInt32 ticksPerSecond = PR_TicksPerSecond();
        tv.tv_sec = remaining / ticksPerSecond;
        tv.tv_usec = PR_IntervalToMicroseconds( remaining % ticksPerSecond );
        tvp = &tv;
    }

    ready = bsdselect(maxfd + 1, &rd, &wt, &ex, tvp);
#else
    switch (timeout)
    {
        case PR_INTERVAL_NO_WAIT:
            msecs = 0;
            break;
        case PR_INTERVAL_NO_TIMEOUT:
            msecs = -1;
            break;
        default:
            msecs = PR_IntervalToMilliseconds(remaining);
    }

     /* compact array */
    for( i = rd, j = npds; j < npds+wt; i++,j++ )
        socks[i] = socks[j];
    for( i = rd+wt, j = npds*2; j < npds*2+ex; i++,j++ )
        socks[i] = socks[j];
    
    ready = os2_select(socks, rd, wt, ex, msecs);
#endif

    if (ready == -1 && errno == EINTR)
    {
        if (timeout == PR_INTERVAL_NO_TIMEOUT)
            goto retry;
        else
        {
            elapsed = (PRIntervalTime) (PR_IntervalNow() - start);
            if (elapsed > timeout)
                ready = 0;  /* timed out */
            else
            {
                remaining = timeout - elapsed;
                goto retry;
            }
        }
    }

    /*
    ** Now to unravel the select sets back into the client's poll
    ** descriptor list. Is this possibly an area for pissing away
    ** a few cycles or what?
    */
    if (ready > 0)
    {
        ready = 0;
        for (pd = pds, epd = pd + npds; pd < epd; pd++)
        {
            PRInt16 out_flags = 0;
            if ((NULL != pd->fd) && (0 != pd->in_flags))
            {
                PRInt32 osfd;
                bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
                PR_ASSERT(NULL != bottom);

                osfd = bottom->secret->md.osfd;

#ifdef BSD_SELECT
                if (FD_ISSET(osfd, &rd))
#else
                if( IsSocketSet(osfd, socks, 0, rd) )        
#endif
                {
                    if (pd->out_flags & _PR_POLL_READ_SYS_READ)
                        out_flags |= PR_POLL_READ;
                    if (pd->out_flags & _PR_POLL_WRITE_SYS_READ)
                        out_flags |= PR_POLL_WRITE;
                } 

#ifdef BSD_SELECT
                if (FD_ISSET(osfd, &wt))
#else
                if( IsSocketSet(osfd, socks, rd, wt) )        
#endif
                {
                    if (pd->out_flags & _PR_POLL_READ_SYS_WRITE)
                        out_flags |= PR_POLL_READ;
                    if (pd->out_flags & _PR_POLL_WRITE_SYS_WRITE)
                        out_flags |= PR_POLL_WRITE;
                } 

#ifdef BSD_SELECT
                if (FD_ISSET(osfd, &ex))
#else
                if( IsSocketSet(osfd, socks, rd+wt, ex) )        
#endif
                {
                    out_flags |= PR_POLL_EXCEPT;
                }
            }
            pd->out_flags = out_flags;
            if (out_flags) ready++;
        }
        PR_ASSERT(ready > 0);
    }
    else if (ready < 0)
    {
        err = _MD_ERRNO();
        if (err == EBADF)
        {
            /* Find the bad fds */
            int optval;
            int optlen = sizeof(optval);
            ready = 0;
            for (pd = pds, epd = pd + npds; pd < epd; pd++)
            {
                pd->out_flags = 0;
                if ((NULL != pd->fd) && (0 != pd->in_flags))
                {
                    bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
                    if (getsockopt(bottom->secret->md.osfd, SOL_SOCKET,
                        SO_TYPE, (char *) &optval, &optlen) == -1)
                    {
                        PR_ASSERT(sock_errno() == ENOTSOCK);
                        if (sock_errno() == ENOTSOCK)
                        {
                            pd->out_flags = PR_POLL_NVAL;
                            ready++;
                        }
                    }
                }
            }
            PR_ASSERT(ready > 0);
        }
        else
            _PR_MD_MAP_SELECT_ERROR(err);
    }

#ifndef BSD_SELECT
    PR_Free(socks);
#endif
    return ready;
}
void main(int argc, char **argv) {
   int listen_sock, udp_sock, socks[2], newsock;
   struct servent *echoprot;
   struct sockaddr_in server, client;
   int rc;
   int asize;

   // Initialize TCP/IP
   if (sock_init() != 0) {
      printf("INET.SYS probably is not running");
      exit(1);
   }

//------ Create the TCP server socket

   // Create a TCP socket to accept incoming connections
   listen_sock = socket(AF_INET, SOCK_STREAM, 0);
   if (listen_sock == -1) {
       psock_errno("tcp socket()");
       exit(1);
   }

   printf("TCP socket assigned is %d\n", listen_sock);

   // Get the port for the echo protocol out of the etc\services file
   echoprot = getservbyname("echo", "tcp");
   if (echoprot == NULL) {
      printf("The echo/tcp protocol is not listed in the etc/services file\n");
      exit(1);
   }

   // Bind the TCP socket to the echo port
   server.sin_family = AF_INET;
   server.sin_port = echoprot->s_port;
   server.sin_addr.s_addr = INADDR_ANY;

   rc = bind(listen_sock, (struct sockaddr *)&server, sizeof(server));
   if (rc == -1) {
       psock_errno("tcp bind()");
       exit(1);
   }

   // Put the socket into listen mode

   rc = listen(listen_sock, SOMAXCONN);
   if (rc == -1) {
       psock_errno("listen()");
       exit(1);
   }

//------ Create the UDP server socket

   // Create a UDP socket to accept incoming data
   udp_sock = socket(AF_INET, SOCK_DGRAM, 0);
   if (udp_sock == -1) {
       psock_errno("udp socket()");
       exit(1);
   }

   printf("UDP socket assigned is %d\n", udp_sock);

   // Get the port for the echo protocol out of the etc\services file
   echoprot = getservbyname("echo", "udp");
   if (echoprot == NULL) {
      printf("The echo/udp protocol is not listed in the etc/services file\n");
      exit(1);
   }

   // Bind the UDP socket to the echo port
   server.sin_family = AF_INET;
   server.sin_port = echoprot->s_port;
   server.sin_addr.s_addr = INADDR_ANY;

   rc = bind(udp_sock, (struct sockaddr *)&server, sizeof(server));
   if (rc == -1) {
       psock_errno("udp bind()");
       exit(1);
   }

//------ Wait for a connection on the TCP socket or a packet on the UDP socket

   while (1) {
      // Setup the socket array for select()
      socks[0] = listen_sock;
      socks[1] = udp_sock;

      // Wait indefinitely
      rc = os2_select(socks, 2, 0, 0, -1);
      if (rc == -1) {
         // If the select was interrupted, just continue
         if (sock_errno() == SOCEINTR)
            continue;
         psock_errno("main() select()");
         exit(1);
      }

      if (socks[0] != -1) {
         // The TCP listen socket has a connection request ready-- accept() it

         asize = sizeof(client);
         newsock = accept(socks[0], (struct sockaddr *)&client, &asize);
         if (newsock == -1) {
            psock_errno("accept()");
            exit(1);
         }

         printf("Received a TCP connection on socket %d from %s port %d\n",
                newsock, inet_ntoa(client.sin_addr), ntohs(client.sin_port));

         // Start a new thread and pass it the socket it should service

         rc = _beginthread(ServiceTCP, 0, STACK_SIZE, (void *)newsock);
         if (rc == -1) {
            printf("_beginthread() failed\n");
            exit(1);
         }
      }

      // If the UDP socket has a packet waiting, service it

      if (socks[1] != -1)
         ServiceUDP(socks[1]);
   }
}