Back to index

opendkim  2.6.4
ar-socket.c
Go to the documentation of this file.
00001 /*
00002 **  Copyright (c) 2011, The OpenDKIM Project.  All rights reserved.
00003 */
00004 
00005 /* OS stuff */
00006 #if HPUX11
00007 # define _XOPEN_SOURCE_EXTENDED
00008 #endif /* HPUX11 */
00009 
00010 #include "build-config.h"
00011 
00012 /* system includes */
00013 #include <sys/param.h>
00014 #include <sys/types.h>
00015 #ifdef POLL
00016 # include <poll.h>
00017 #else /* POLL */
00018 # include <sys/select.h>
00019 #endif /* POLL */
00020 #include <sys/time.h>
00021 #include <time.h>
00022 #include <errno.h>
00023 #include <assert.h>
00024 #include <stdlib.h>
00025 
00026 /* libar includes */
00027 #include "ar-socket.h"
00028 
00029 /* useful stuff */
00030 #ifndef NULL
00031 # define NULL 0
00032 #endif /* ! NULL */
00033 #ifndef FALSE
00034 # define FALSE       0
00035 #endif /* ! FALSE */
00036 #ifndef TRUE
00037 # define TRUE 1
00038 #endif /* ! TRUE */
00039 
00040 #define       MINSETSIZE    16
00041 
00042 /* data types */
00043 struct ar_socket_set
00044 {
00045 #ifdef POLL
00046        unsigned int  arss_alloc;
00047        unsigned int  arss_num;
00048        struct pollfd *      arss_poll;
00049 #else /* POLL */
00050        int           arss_maxfd;
00051        fd_set        arss_rfds;
00052        fd_set        arss_wfds;
00053        fd_set        arss_xfds;
00054 #endif /* POLL */
00055 };
00056 
00057 /*
00058 **  AR_SOCKET_INIT -- create a socket set
00059 **
00060 **  Parameters:
00061 **     initsz -- initial set size
00062 **
00063 **  Return value:
00064 **     A newly-allocated socket set handle, or NULL on error.
00065 */
00066 
00067 AR_SOCKET_SET
00068 ar_socket_init(unsigned int initsz)
00069 {
00070        struct ar_socket_set *new;
00071 
00072        new = (AR_SOCKET_SET) malloc(sizeof *new);
00073        if (new == NULL)
00074               return NULL;
00075 
00076        if (initsz < MINSETSIZE)
00077               initsz = MINSETSIZE;
00078 
00079 #ifdef POLL
00080        new->arss_poll = (struct pollfd *) malloc(sizeof(struct pollfd) * initsz);
00081        if (new->arss_poll == NULL)
00082        {
00083               free(new);
00084               return NULL;
00085        }
00086 
00087        new->arss_num = 0;
00088        new->arss_alloc = initsz;
00089 #else /* POLL */
00090        new->arss_maxfd = -1;
00091        FD_ZERO(&new->arss_rfds);
00092        FD_ZERO(&new->arss_wfds);
00093        FD_ZERO(&new->arss_xfds);
00094 #endif /* POLL */
00095 
00096        return new;
00097 }
00098 
00099 /*
00100 **  AR_SOCKET_FREE -- release a socket set
00101 **
00102 **  Parameters:
00103 **     ss -- AR_SOCKET_SET to be released
00104 **
00105 **  Return value:
00106 **     None.
00107 */
00108 
00109 void
00110 ar_socket_free(AR_SOCKET_SET ss)
00111 {
00112        assert(ss != NULL);
00113 
00114 #ifdef POLL
00115        if (ss->arss_poll != NULL)
00116               free(ss->arss_poll);
00117 #endif /* POLL */
00118 
00119        free(ss);
00120 }
00121 
00122 /*
00123 **  AR_SOCKET_RESET -- reset a socket set
00124 **
00125 **  Parameters:
00126 **     ss -- AR_SOCKET_SET to be reset
00127 **
00128 **  Return value:
00129 **     None.
00130 */
00131 
00132 void
00133 ar_socket_reset(AR_SOCKET_SET ss)
00134 {
00135        assert(ss != NULL);
00136 
00137 #ifdef POLL
00138        ss->arss_num = 0;
00139 #else /* POLL */
00140        ss->arss_maxfd = -1;
00141        FD_ZERO(&ss->arss_rfds);
00142        FD_ZERO(&ss->arss_wfds);
00143        FD_ZERO(&ss->arss_xfds);
00144 #endif /* POLL */
00145 }
00146 
00147 /*
00148 **  AR_SOCKET_ADD -- add a socket of interest to the socket set
00149 **
00150 **  Parameters:
00151 **     ss -- socket set
00152 **     fd -- descriptor
00153 **     events -- bitmask of events of interest
00154 **
00155 **  Return value:
00156 **     -1 -- error (check errno)
00157 **     0 -- success
00158 */
00159 
00160 int
00161 ar_socket_add(AR_SOCKET_SET ss, int fd, unsigned int events)
00162 {
00163 #ifdef POLL
00164        int c;
00165 #endif /* POLL */
00166 
00167        assert(ss != NULL);
00168        assert(fd >= 0);
00169 
00170 #ifdef POLL
00171        /* if this one is alerady in the set, update the events bitmask */
00172        for (c = 0; c < ss->arss_num; c++)
00173        {
00174               if (ss->arss_poll[c].fd == fd)
00175               {
00176                      if ((events & AR_SOCKET_EVENT_READ) != 0)
00177                             ss->arss_poll[c].events |= POLLIN;
00178                      if ((events & AR_SOCKET_EVENT_WRITE) != 0)
00179                             ss->arss_poll[c].events |= POLLOUT;
00180                      if ((events & AR_SOCKET_EVENT_EXCEPTION) != 0)
00181                             ss->arss_poll[c].events |= (POLLERR|POLLHUP|POLLNVAL);
00182 
00183                      return 0;
00184               }
00185        }
00186 
00187        /* adding; resize poll array if needed */
00188        if (ss->arss_alloc == ss->arss_num)
00189        {
00190               unsigned int new;
00191               struct pollfd *newp;
00192 
00193               new = ss->arss_alloc * 2;
00194               newp = (struct pollfd *) realloc(ss->arss_poll,
00195                                                new * sizeof(struct pollfd));
00196               if (newp == NULL)
00197                      return -1;
00198 
00199               ss->arss_alloc = new;
00200               ss->arss_poll = newp;
00201        }
00202 
00203        ss->arss_poll[ss->arss_num].fd = fd;
00204        ss->arss_poll[ss->arss_num].events = 0;
00205        ss->arss_poll[ss->arss_num].revents = 0;
00206        if ((events & AR_SOCKET_EVENT_READ) != 0)
00207               ss->arss_poll[ss->arss_num].events |= POLLIN;
00208        if ((events & AR_SOCKET_EVENT_WRITE) != 0)
00209               ss->arss_poll[ss->arss_num].events |= POLLOUT;
00210        if ((events & AR_SOCKET_EVENT_EXCEPTION) != 0)
00211               ss->arss_poll[ss->arss_num].events |= (POLLERR|POLLHUP|POLLNVAL);
00212        ss->arss_num++;
00213 
00214        return 0;
00215 #else /* POLL */
00216        if (fd >= FD_SETSIZE)
00217        {
00218               errno = EINVAL;
00219               return -1;
00220        }
00221 
00222        if ((events & AR_SOCKET_EVENT_READ) != 0)
00223               FD_SET(fd, &ss->arss_rfds);
00224        if ((events & AR_SOCKET_EVENT_WRITE) != 0)
00225               FD_SET(fd, &ss->arss_wfds);
00226        if ((events & AR_SOCKET_EVENT_EXCEPTION) != 0)
00227               FD_SET(fd, &ss->arss_xfds);
00228 
00229        if (fd > ss->arss_maxfd)
00230               ss->arss_maxfd = fd;
00231 
00232        return 0;
00233 #endif /* POLL */
00234 }
00235 
00236 /*
00237 **  AR_SOCKET_CHECK -- see if a socket has particular events set after waiting
00238 **
00239 **  Parameters:
00240 **     ss -- socket set
00241 **     fd -- descriptor of interest
00242 **     events -- events of interest
00243 **
00244 **  Return value:
00245 **     1 -- one or more of the requested socket events occurred
00246 **     0 -- none of the requested socket events occurred
00247 **     -1 -- an error occurred
00248 */
00249 
00250 int
00251 ar_socket_check(AR_SOCKET_SET ss, int fd, unsigned int events)
00252 {
00253 #ifdef POLL
00254        unsigned int c;
00255 #else /* POLL */
00256        int ret;
00257 #endif /* POLL */
00258 
00259        assert(ss != NULL);
00260        assert(fd >= 0);
00261 
00262 #ifdef POLL
00263        for (c = 0; c < ss->arss_num; c++)
00264        {
00265               if (ss->arss_poll[c].fd == fd)
00266               {
00267                      /* read */
00268                      if ((events & AR_SOCKET_EVENT_READ) != 0 &&
00269                          (ss->arss_poll[c].revents & POLLIN) != 0)
00270                             return 1;
00271 
00272                      /* write */
00273                      if ((events & AR_SOCKET_EVENT_WRITE) != 0 &&
00274                          (ss->arss_poll[c].revents & POLLOUT) != 0)
00275                             return 1;
00276 
00277                      /* exception */
00278                      if ((events & AR_SOCKET_EVENT_EXCEPTION) != 0 &&
00279                          (ss->arss_poll[c].revents & (POLLERR|POLLHUP|POLLNVAL)) != 0)
00280                             return 1;
00281 
00282                      return 0;
00283               }
00284        }
00285 
00286        return 0;
00287 #else /* POLL */
00288        if (fd >= FD_SETSIZE)
00289        {
00290               errno = EINVAL;
00291               return -1;
00292        }
00293 
00294        ret = 0;
00295        if ((events & AR_SOCKET_EVENT_READ) != 0 &&
00296            FD_ISSET(fd, &ss->arss_rfds))
00297               ret = 1;
00298        if ((events & AR_SOCKET_EVENT_WRITE) != 0 &&
00299            FD_ISSET(fd, &ss->arss_wfds))
00300               ret = 1;
00301        if ((events & AR_SOCKET_EVENT_EXCEPTION) != 0 &&
00302            FD_ISSET(fd, &ss->arss_xfds))
00303               ret = 1;
00304 
00305        return ret;
00306 #endif /* POLL */
00307 }
00308 
00309 /*
00310 **  AR_SOCKET_WAIT -- wait for a socket in a set to become ready
00311 **
00312 **  Parameters:
00313 **     ss -- socket set
00314 **     timeout -- time (in milliseconds) to wait; -1 = forever
00315 **
00316 **  Return value:
00317 **     Number of descriptors that are ready; 0 = timeout, -1 = error
00318 */
00319 
00320 int
00321 ar_socket_wait(AR_SOCKET_SET ss, int timeout)
00322 {
00323 #ifndef POLL
00324        struct timeval to;
00325 #endif /* POLL */
00326 
00327        assert(ss != NULL);
00328 
00329 #ifdef POLL
00330        return poll(ss->arss_poll, ss->arss_num, timeout);
00331 #else /* POLL */
00332        if (timeout != -1)
00333        {
00334               to.tv_sec = timeout / 1000;
00335               to.tv_usec = (timeout % 1000) * 1000;
00336        }
00337 
00338        return select(ss->arss_maxfd + 1,
00339                      &ss->arss_rfds,
00340                      &ss->arss_wfds,
00341                      &ss->arss_xfds,
00342                      timeout == -1 ? NULL : &to);
00343 #endif /* POLL */
00344 }