Пример #1
0
TASK_DLLEXPORT int
Task_wait_read(int fd, long msec)
{
   Task *tp;

   struct timeval tv;

   fd_set set;

   int r;

   if (!canSwitch)
   {

      FD_ZERO(&set);
      FD_SET(fd, &set);
      calcTv(&tv, msec);
      r = t_select(FD_SETSIZE, &set, 0, 0, &tv);
      if (r > 0)
	 return 0;
      else if (r == 0)
	 return 1;
      else
	 return r;
   }

   tp = currTask;

   FD_ZERO(&set);
   FD_SET(fd, &set);
   tv.tv_sec = tv.tv_usec = 0;
   r = t_select(FD_SETSIZE, &set, 0, 0, &tv);

   if (r != 0)
   {
      Task_yield();
      if (r > 0)
	 return 0;
      else
	 return r;
   }

   FD_ZERO(&tp->rfileset);
   FD_SET(fd, &tp->rfileset);

   tp->wakeUp = calcWakeup(msec);
   removeFromList(tp);
   tp->isRead = 1;
   addToWait(tp);
   tp->isTimed = 0;

   Task_yield();

   tp->isRead = 0;
   return tp->isTimed;
}
Пример #2
0
/* FUNCTION: bsd_select()
 *
 * Synchronous I/O multiplexing (for sockets)
 *
 * PARAM1: nfds; IN - the number of fds to be checked in each set (readfds,
 *               writefds, exceptfds): not used in this release
 * PARAM2: readfds; IN/OUT - fd set containing descriptors to be examined
 *                  for readiness to read (i.e. received data is present
 *                  and can be retreived by recv() or recvfrom() without
 *                  blocking); on successful return, will contain 
 *                  only those descriptors that are ready to read
 * PARAM3: writefds; IN/OUT - fd set containing descriptors to be examined
 *                   for readiness to write (e.g. send() or sendto() could
 *                   succeed without blocking, or socket has connect()ed);
 *                   on successful return, will contain only those 
 *                   descriptors that are ready to write
 * PARAM4: exceptfds; IN/OUT - fd set containing descriptors to be examined
 *                    for exceptional conditions (i.e. out-of-band data
 *                    pending on socket); on successful return
 * PARAM5: timeout; IN - ptr to a struct timeval, which should be set to
 *                  indicate the maximum interval to wait for any 
 *                  descriptor(s) to become ready; may be NULL, indicating 
 *                  that select() can wait indefinitely for any descriptor(s) 
 *                  to become ready
 * RETURNS: if successful, the number of ready file descriptors in all
 *          the fd sets (may be 0 if the timeout expired), or -1 if an
 *          error occured.  The error would be available via bsd_errno(s).
 */
int 
bsd_select(int nfds,
           fd_set * readfds,
           fd_set * writefds,
           fd_set * exceptfds,
           BSD_TIMEVAL_T * timeout)
{
   long ltv;    /* timeout expressed in ticks */
   long tps;    /* local copy of TPS */

   USE_ARG(nfds);

   if (timeout != NULL)
   {
      /* This turning of a struct timeval into a tick-count timeout
       * assumes that TPS (ticks-per-second) is a reasonably small
       * integer, and that tv_usec may be anywhere from 0 to one
       * million (i.e. any number of microseconds up to one second).
       * So we scale tv_usec from microseconds to something reasonable
       * based on TPS, multiply it by TPS, then scale it the rest of
       * the way to ticks-per-second.
       */
      tps = TPS;
      if (tps >= 1000)
      {
         ltv = (((timeout->tv_usec + 50) / 100) * tps) / 10000;
      }
      else if (tps >= 100)
      {
         ltv = (((timeout->tv_usec + 500) / 1000) * tps) / 1000;
      }
      else if (tps >= 10)
      {
         ltv = (((timeout->tv_usec + 5000) / 10000) * tps) / 100;
      }
      else
      {
         ltv = (((timeout->tv_usec + 50000) / 100000) * tps) / 10;
      }
      ltv += (timeout->tv_sec * TPS);
   }
   else {
      /*
       * NULL timeout: wait indefinitely in t_select()
       */
      ltv = -1;
   }

   return (t_select(readfds, writefds, exceptfds, ltv));
}
    kii_socket_code_t
socket_recv_cb(
        kii_socket_context_t* socket_context,
        char* buffer,
        size_t length_to_read,
        size_t* out_actual_length)
{
    int res;
    int received;
    int total = 0;
    char *pBuf = NULL;
    context_t* ctx = (context_t*)socket_context->app_context;
    do
    {
        res = t_select((void *)handle, ctx->sock, 1000);
        if (res == A_OK)
        {
#if CONNECT_SSL
            received = SSL_read(ssl, buffer, length_to_read);
#else
            received = t_recv(handle, ctx->sock, buffer, length_to_read, 0);
#endif
            if(received > 0)
            {
                total = received;
                break;
            }
        }
    } while (res == A_OK);

    if (total >  0) {
        *out_actual_length = total;
        return KII_SOCKETC_OK;
    } else {
        printf("failed to receive:\n");
        // TOOD: could be 0 on success?
        *out_actual_length = 0;
        socket_close_cb(socket_context);
        return KII_SOCKETC_FAIL;
    }
}
Пример #4
0
void
tcp_echo_recv(void)
{
   int   len;        /* length of recv data */
   int   e;          /* error holder */
   unsigned i;       /* generic index */
   int   count;      /* select return */
   fd_set fd_recv;   /* fd for recv */
   fd_set fd_accept; /* fd for accept */
   TCPCLIENT tmpclient = tcpq;
   struct sockaddr_in client;
   SOCKTYPE tmpsock; /* scratch socket */

   if (elisten_sock == INVALID_SOCKET && tcpq == NULL)
      return;  /* Echo not set up, don't bother */

#ifdef USE_FDS
   FD_ZERO(&fd_recv);
   FD_ZERO(&fd_accept);
#endif

   /* select on all open data sockets */
   i = 0;
   count = 0;
#ifdef USE_FDS
   while (tmpclient)
   {
      if (tmpclient->sock != INVALID_SOCKET)
      {
         FD_SET(tmpclient->sock, &fd_recv);
         i++;
      }
      tmpclient=tmpclient->next;
   }
#else
   while (tmpclient)
   {
      if (tmpclient->sock != INVALID_SOCKET)
         fd_recv.fd_array[i++] = tmpclient->sock ;
      tmpclient=tmpclient->next;
   }
#endif  /* USE_FDS */

#ifndef TCP_ZEROCOPY
   /* if we need to listen for server receives too */
#ifdef USE_FDS
   if (tcpecho_server && (esvr_sock != INVALID_SOCKET))
   {
      FD_SET(esvr_sock, &fd_recv);
   }
#else
   if (tcpecho_server)
   {
      if (esvr_sock != INVALID_SOCKET)
         fd_recv.fd_array[i++] = esvr_sock;
   }
#endif  /* USE_FDS */
#else
   /* if we need to close the server's active socket */
   if (esvr_sock_close != FALSE)
   {
      if (esvr_sock != INVALID_SOCKET)
      {
         socketclose(esvr_sock);
         esvr_sock = INVALID_SOCKET;
      }
      esvr_sock_close = FALSE;
   }
#endif   /* TCP_ZEROCOPY */

#ifndef USE_FDS
   fd_recv.fd_count = i;
#endif

   /* make this a short timeout since elisten may create soon */
   if (elisten_sock != INVALID_SOCKET)
   {
#ifdef USE_FDS
      FD_SET(elisten_sock, &fd_accept);
#else
      fd_accept.fd_array[0] = elisten_sock;
      fd_accept.fd_count = 1;
#endif  /* USE_FDS */
      count = t_select(&fd_recv, NULL, &fd_accept, 1);
   }
   else 
   {
      if (i)   /* if no fd_set sockets filled in, don't bother */
         count = t_select(&fd_recv, NULL, NULL, 1);
   }

   /* While the t_select() was executing, commands can be 
    * executed from cmd-prompt and sockets can be cleaned up. 
    * Check for that. 
    */
   if (elisten_sock == INVALID_SOCKET && tcpq == NULL)
      return;  /* Echo not set up, don't bother */

   for (i = 0; i < fd_recv.fd_count; i++)
   {
#ifdef USE_FDS
      tmpsock = FD_GET(i, &fd_recv);
      if (tmpsock == INVALID_SOCKET)
         continue;
#else
      tmpsock = fd_recv.fd_array[i];
#endif  /* USE_FDS */

      /* Find out the client connection corresponding to this socket */
      tmpclient = tcp_client_from_sock(tmpsock);

      /* try a receive. Pick buffer according to client or server */
      if (tmpclient)    /* found a client for this one */
         len = recv(tmpsock, tmpclient->inbuf, ECHOBUFSIZE, 0);
#ifndef TCP_ZEROCOPY
      else if (tmpsock == esvr_sock)
         len = recv(tmpsock, srv_inbuf, ECHOBUFSIZE, 0);
#endif   /* TCP_ZEROCOPY */
      else
      {
         continue;
      }

      if (len < 0)
      {
         e = t_errno(tmpsock);
         if (e != EWOULDBLOCK)
         {
            if (tmpsock != esvr_sock)
               ns_printf(tmpclient->pio,"TCP echo recv error %d\n", e);
            else
               ns_printf(NULL,"TCP echo recv error %d\n", e);
         }
      }
      else if (len == 0)
      {
         ns_printf(NULL,"TCPECHO:socket closed by other side\n");
         if (tmpsock == esvr_sock)
         {
            socketclose (tmpsock);
            esvr_sock = INVALID_SOCKET;
         }
         else
         {
            if (tmpclient == NULL)
            {
               dtrap();
            }          
            else
            {
               tmpclient->sock = INVALID_SOCKET ;
               tcp_client_del(tmpclient);
            }
         }
      }
      else  /* if (len > 0) - got some echo data */
      {
#ifndef TCP_ZEROCOPY
         if (tmpsock == esvr_sock)
         {
            /* we must be server, send echo reply */
            if (tcpecho_server)
            {
               e = send(esvr_sock, srv_inbuf, len, 0);
               if (e < 0)
               {
                  /* Print the error to console */
                  e = t_errno(esvr_sock);
                  ns_printf(NULL,
                   "TCP echo server, error %d sending reply\n", e);
               }
            }
         }
         else     /* not the server socket, must be client */
#endif   /* TCP_ZEROCOPY */
         {
            /* If not a bulk test, print info */
            if (tmpclient->len <= ECHOBUFSIZE)
            {
               ns_printf(tmpclient->pio,"TCP echo reply from:%s, len:%d, reply:%lu", 
                print_ipad(tmpclient->rhost), len, tmpclient->replies);
               ns_printf(tmpclient->pio,"\n%s",prompt);
            }
            else
            {
               u_long   dataval;
               u_long * rxbuf =  (u_long*)(tmpclient->inbuf);
               u_long * rxend =  (u_long*)(tmpclient->inbuf +  (len  &  ~3));

               dataval = tmpclient->tot_rcvd/4;

               /* adjust for odd sized previous receives */
               if (tmpclient->tot_rcvd & 3)
               {
                  MEMMOVE(rxbuf, tmpclient->inbuf + (len & 3), len);
                  rxend--;
                  dataval++;     /* ignore sliced word */
               }

               while (rxbuf < rxend)
               {
                  if (*rxbuf != dataval)
                  {
                     ns_printf(tmpclient->pio,
                      "tcp_echo data error; got %lu, expected %lu\n",
                      *rxbuf, dataval);
                  }
                  rxbuf++;
                  dataval++;
               }
            }
            tmpclient->replies++;
            tmpclient->tot_rcvd += len;
         }
      }
   }

   /* if no server listen to poll, return now */
   if (elisten_sock == INVALID_SOCKET)
      return;

#ifdef NOTDEF
   MEMSET(&client, 0, sizeof(client));
   client.sin_family = AF_INET;
   client.sin_addr.s_addr = INADDR_ANY;
   client.sin_port = htons(ECHO_PORT);
#endif

   /* check for received echo connection on server */
   len = sizeof(client);
   tmpsock = accept(elisten_sock, (struct sockaddr*)&client, &len);
   if (tmpsock != INVALID_SOCKET)
   {
      if (esvr_sock == INVALID_SOCKET)
      {
         esvr_sock = tmpsock;
#ifdef TCP_ZEROCOPY
         t_setsockopt(esvr_sock, SOL_SOCKET, SO_CALLBACK, (void*)echo_svr_upcall, 0);
#endif   /* TCP_ZEROCOPY */
      }
      else  /* we already have a connection */
      {
         dprintf("tcpecho: rejected extra connection\n");
         socketclose(tmpsock);   /* refuse to serve another */
      }
   }
}