/************************************************************************
 *   IRC - Internet Relay Chat, src/socketengine_poll.c
 *   Copyright (C) 2003 Lucas Madar
 *
 * engine functions for the poll() socket engine
 *
 */

/* $Id: socketengine_poll.c,v 1.1.1.1 2005/06/27 03:02:37 sheik Exp $ */

#include "struct.h"
#include "common.h"
#include "sys.h"
#include "h.h"
#include "fds.h"

#include <sys/poll.h>

struct pollfd poll_fds[MAXCONNECTIONS];
int last_pfd = -1;

void engine_init()
{
}

void engine_add_fd(int fd)
{
   struct pollfd *pfd = &poll_fds[++last_pfd];

   /* sanity check */
   if(last_pfd >= MAXCONNECTIONS)
      abort();

   set_fd_internal(fd, (void *) last_pfd);

   pfd->fd = fd;
   pfd->events = 0;
   pfd->revents = 0;
}

void engine_del_fd(int fd)
{
   int arrayidx = (int) get_fd_internal(fd);

   /* If it's at the end of the array, just chop it off */
   if(arrayidx == last_pfd)
   {
      fdfprintf(stderr, "Removing %d[%d] from end of pollfds\n", last_pfd, fd);
      last_pfd--;
      return;
   }

   /* Otherwise, move the last array member to where the old one was */
   fdfprintf(stderr, "Moving pfd %d[%d] to vacated spot %d[%d] -- now %d[%d]\n", 
             last_pfd, poll_fds[last_pfd].fd, arrayidx, fd, last_pfd, fd);
   memcpy(&poll_fds[arrayidx], &poll_fds[last_pfd], sizeof(struct pollfd));
   last_pfd--;
   set_fd_internal(poll_fds[arrayidx].fd, (void *) arrayidx);
}

void engine_change_fd_state(int fd, unsigned int stateplus)
{
   int arrayidx = (int) get_fd_internal(fd);
   struct pollfd *pfd = &poll_fds[arrayidx];

   pfd->events = 0;
   if(stateplus & FDF_WANTREAD)
      pfd->events |= POLLIN|POLLHUP|POLLERR;
   if(stateplus & FDF_WANTWRITE)
      pfd->events |= POLLOUT;
}

void engine_get_pollfds(struct pollfd **pfds, int *numpfds)
{
   *pfds = poll_fds;
   *numpfds = (last_pfd + 1);
}

int engine_read_message(time_t delay)
{
   static struct pollfd poll_fdarray[MAXCONNECTIONS];

   struct pollfd *pfd;
   int nfds, nbr_pfds, length, i;
   unsigned int fdflags;
   int fdtype;
   void *fdvalue;
   aClient *cptr;
   aListener *lptr;

   engine_get_pollfds(&pfd, &nbr_pfds);
   memcpy(poll_fdarray, pfd, sizeof(struct pollfd) * nbr_pfds);

   nfds = poll(poll_fdarray, nbr_pfds, delay * 1000);
   if (nfds == -1)
   {
      if(((errno == EINTR) || (errno == EAGAIN)))
         return -1;
      report_error("poll %s:%s", &me);
      sleep(5);
      return -1;
   }

   if(delay)
      NOW = timeofday = time(NULL);

   for (pfd = poll_fdarray, i = 0; nfds && (i < nbr_pfds); i++, pfd++) 
   {
      get_fd_info(pfd->fd, &fdtype, &fdflags, &fdvalue);

      cptr = NULL;
      length = -1;

      if (nfds && pfd->revents)
      {
         int rr = pfd->revents & (POLLIN|POLLHUP|POLLERR);
         int rw = pfd->revents & (POLLOUT);

         fdfprintf(stderr, "fd %d: %s%s\n", pfd->fd, rr ? "read " : "", rw ? "write" : "");

         nfds--;

         switch(fdtype)
         {
            case FDT_NONE:
               break;

            case FDT_AUTH:
               cptr = (aClient *) fdvalue;
               if (rr)
                  read_authports(cptr);
               if (rw && cptr->authfd >= 0)
                  send_authports(cptr);
               check_client_fd(cptr);
               break;

            case FDT_LISTENER:
               lptr = (aListener *) fdvalue;
               if(rr)
                  accept_connection(lptr);
               break;

            case FDT_RESOLVER:
               do_dns_async();
               break;

            case FDT_CLIENT:
               cptr = (aClient *) fdvalue;
               readwrite_client(cptr, rr, rw);
               break;

            case FDT_CALLBACKP:
               {
                  struct fd_callbackp *fdcb = (struct fd_callbackp *) fdvalue;

                  fdcb->rdf = rr;
                  fdcb->wrf = rw;
                  (*fdcb->callback)(fdcb);
               }
               break;

            default:
               abort(); /* unknown client type? bail! */
         }
      }
   } /* end of for() loop for testing polled sockets */

   return 0;
}


syntax highlighted by Code2HTML, v. 0.9.1