net-snmp 5.7
fd_event_manager.c
00001 /* UNIT: File Descriptor (FD) Event Manager                              */
00002 #include <net-snmp/net-snmp-config.h>
00003 #ifdef HAVE_SYS_SELECT
00004 #include <sys/select.h>
00005 #endif
00006 #include <net-snmp/net-snmp-includes.h>
00007 #include <net-snmp/net-snmp-features.h>
00008 #include <net-snmp/library/snmp_api.h>
00009 #include <net-snmp/library/fd_event_manager.h>
00010 #include <net-snmp/library/snmp_logging.h>
00011 #include <net-snmp/library/large_fd_set.h>
00012 
00013 netsnmp_feature_child_of(fd_event_manager, libnetsnmp)
00014 
00015 #ifndef NETSNMP_FEATURE_REMOVE_FD_EVENT_MANAGER
00016 int     external_readfd[NUM_EXTERNAL_FDS],   external_readfdlen   = 0;
00017 int     external_writefd[NUM_EXTERNAL_FDS],  external_writefdlen  = 0;
00018 int     external_exceptfd[NUM_EXTERNAL_FDS], external_exceptfdlen = 0;
00019 void  (*external_readfdfunc[NUM_EXTERNAL_FDS]) (int, void *);
00020 void  (*external_writefdfunc[NUM_EXTERNAL_FDS]) (int, void *);
00021 void  (*external_exceptfdfunc[NUM_EXTERNAL_FDS]) (int, void *);
00022 void   *external_readfd_data[NUM_EXTERNAL_FDS];
00023 void   *external_writefd_data[NUM_EXTERNAL_FDS];
00024 void   *external_exceptfd_data[NUM_EXTERNAL_FDS];
00025 
00026 static int external_fd_unregistered;
00027 
00028 /*
00029  * Register a given fd for read events.  Call callback when events
00030  * are received.
00031  */
00032 int
00033 register_readfd(int fd, void (*func) (int, void *), void *data)
00034 {
00035     if (external_readfdlen < NUM_EXTERNAL_FDS) {
00036         external_readfd[external_readfdlen] = fd;
00037         external_readfdfunc[external_readfdlen] = func;
00038         external_readfd_data[external_readfdlen] = data;
00039         external_readfdlen++;
00040         DEBUGMSGTL(("fd_event_manager:register_readfd", "registered fd %d\n", fd));
00041         return FD_REGISTERED_OK;
00042     } else {
00043         snmp_log(LOG_CRIT, "register_readfd: too many file descriptors\n");
00044         return FD_REGISTRATION_FAILED;
00045     }
00046 }
00047 
00048 /*
00049  * Register a given fd for write events.  Call callback when events
00050  * are received.
00051  */
00052 int
00053 register_writefd(int fd, void (*func) (int, void *), void *data)
00054 {
00055     if (external_writefdlen < NUM_EXTERNAL_FDS) {
00056         external_writefd[external_writefdlen] = fd;
00057         external_writefdfunc[external_writefdlen] = func;
00058         external_writefd_data[external_writefdlen] = data;
00059         external_writefdlen++;
00060         DEBUGMSGTL(("fd_event_manager:register_writefd", "registered fd %d\n", fd));
00061         return FD_REGISTERED_OK;
00062     } else {
00063         snmp_log(LOG_CRIT,
00064                  "register_writefd: too many file descriptors\n");
00065         return FD_REGISTRATION_FAILED;
00066     }
00067 }
00068 
00069 /*
00070  * Register a given fd for exception events.  Call callback when events
00071  * are received.
00072  */
00073 int
00074 register_exceptfd(int fd, void (*func) (int, void *), void *data)
00075 {
00076     if (external_exceptfdlen < NUM_EXTERNAL_FDS) {
00077         external_exceptfd[external_exceptfdlen] = fd;
00078         external_exceptfdfunc[external_exceptfdlen] = func;
00079         external_exceptfd_data[external_exceptfdlen] = data;
00080         external_exceptfdlen++;
00081         DEBUGMSGTL(("fd_event_manager:register_exceptfd", "registered fd %d\n", fd));
00082         return FD_REGISTERED_OK;
00083     } else {
00084         snmp_log(LOG_CRIT,
00085                  "register_exceptfd: too many file descriptors\n");
00086         return FD_REGISTRATION_FAILED;
00087     }
00088 }
00089 
00090 /*
00091  * Unregister a given fd for read events.
00092  */ 
00093 int
00094 unregister_readfd(int fd)
00095 {
00096     int             i, j;
00097 
00098     for (i = 0; i < external_readfdlen; i++) {
00099         if (external_readfd[i] == fd) {
00100             external_readfdlen--;
00101             for (j = i; j < external_readfdlen; j++) {
00102                 external_readfd[j] = external_readfd[j + 1];
00103                 external_readfdfunc[j] = external_readfdfunc[j + 1];
00104                 external_readfd_data[j] = external_readfd_data[j + 1];
00105             }
00106             DEBUGMSGTL(("fd_event_manager:unregister_readfd", "unregistered fd %d\n", fd));
00107             external_fd_unregistered = 1;
00108             return FD_UNREGISTERED_OK;
00109         }
00110     }
00111     return FD_NO_SUCH_REGISTRATION;
00112 }
00113 
00114 /*
00115  * Unregister a given fd for read events.
00116  */ 
00117 int
00118 unregister_writefd(int fd)
00119 {
00120     int             i, j;
00121 
00122     for (i = 0; i < external_writefdlen; i++) {
00123         if (external_writefd[i] == fd) {
00124             external_writefdlen--;
00125             for (j = i; j < external_writefdlen; j++) {
00126                 external_writefd[j] = external_writefd[j + 1];
00127                 external_writefdfunc[j] = external_writefdfunc[j + 1];
00128                 external_writefd_data[j] = external_writefd_data[j + 1];
00129             }
00130             DEBUGMSGTL(("fd_event_manager:unregister_writefd", "unregistered fd %d\n", fd));
00131             external_fd_unregistered = 1;
00132             return FD_UNREGISTERED_OK;
00133         }
00134     }
00135     return FD_NO_SUCH_REGISTRATION;
00136 }
00137 
00138 /*
00139  * Unregister a given fd for exception events.
00140  */
00141 int
00142 unregister_exceptfd(int fd)
00143 {
00144     int             i, j;
00145 
00146     for (i = 0; i < external_exceptfdlen; i++) {
00147         if (external_exceptfd[i] == fd) {
00148             external_exceptfdlen--;
00149             for (j = i; j < external_exceptfdlen; j++) {
00150                 external_exceptfd[j] = external_exceptfd[j + 1];
00151                 external_exceptfdfunc[j] = external_exceptfdfunc[j + 1];
00152                 external_exceptfd_data[j] = external_exceptfd_data[j + 1];
00153             }
00154             DEBUGMSGTL(("fd_event_manager:unregister_exceptfd", "unregistered fd %d\n",
00155                         fd));
00156             external_fd_unregistered = 1;
00157             return FD_UNREGISTERED_OK;
00158         }
00159     }
00160     return FD_NO_SUCH_REGISTRATION;
00161 }
00162 
00163 /* 
00164  * NET-SNMP External Event Info 
00165  */
00166 void netsnmp_external_event_info(int *numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds)
00167 {
00168   netsnmp_large_fd_set lreadfds;
00169   netsnmp_large_fd_set lwritefds;
00170   netsnmp_large_fd_set lexceptfds;
00171 
00172   netsnmp_large_fd_set_init(&lreadfds, FD_SETSIZE);
00173   netsnmp_large_fd_set_init(&lwritefds, FD_SETSIZE);
00174   netsnmp_large_fd_set_init(&lexceptfds, FD_SETSIZE);
00175 
00176   netsnmp_copy_fd_set_to_large_fd_set(&lreadfds, readfds);
00177   netsnmp_copy_fd_set_to_large_fd_set(&lwritefds, writefds);
00178   netsnmp_copy_fd_set_to_large_fd_set(&lexceptfds, exceptfds);
00179 
00180   netsnmp_external_event_info2(numfds, &lreadfds, &lwritefds, &lexceptfds);
00181 
00182   if (netsnmp_copy_large_fd_set_to_fd_set(readfds, &lreadfds) < 0
00183       || netsnmp_copy_large_fd_set_to_fd_set(writefds, &lwritefds) < 0
00184       || netsnmp_copy_large_fd_set_to_fd_set(exceptfds, &lexceptfds) < 0)
00185   {
00186     snmp_log(LOG_ERR,
00187              "Use netsnmp_external_event_info2() for processing"
00188              " large file descriptors\n");
00189   }
00190 
00191   netsnmp_large_fd_set_cleanup(&lreadfds);
00192   netsnmp_large_fd_set_cleanup(&lwritefds);
00193   netsnmp_large_fd_set_cleanup(&lexceptfds);
00194 }
00195 
00196 void netsnmp_external_event_info2(int *numfds,
00197                                   netsnmp_large_fd_set *readfds,
00198                                   netsnmp_large_fd_set *writefds,
00199                                   netsnmp_large_fd_set *exceptfds)
00200 {
00201   int i;
00202 
00203   external_fd_unregistered = 0;
00204 
00205   for (i = 0; i < external_readfdlen; i++) {
00206     NETSNMP_LARGE_FD_SET(external_readfd[i], readfds);
00207     if (external_readfd[i] >= *numfds)
00208       *numfds = external_readfd[i] + 1;
00209   }
00210   for (i = 0; i < external_writefdlen; i++) {
00211     NETSNMP_LARGE_FD_SET(external_writefd[i], writefds);
00212     if (external_writefd[i] >= *numfds)
00213       *numfds = external_writefd[i] + 1;
00214   }
00215   for (i = 0; i < external_exceptfdlen; i++) {
00216     NETSNMP_LARGE_FD_SET(external_exceptfd[i], exceptfds);
00217     if (external_exceptfd[i] >= *numfds)
00218       *numfds = external_exceptfd[i] + 1;
00219   }
00220 }
00221 
00222 /* 
00223  * NET-SNMP Dispatch External Events 
00224  */
00225 void netsnmp_dispatch_external_events(int *count, fd_set *readfds, fd_set *writefds, fd_set *exceptfds)
00226 {
00227   netsnmp_large_fd_set lreadfds;
00228   netsnmp_large_fd_set lwritefds;
00229   netsnmp_large_fd_set lexceptfds;
00230 
00231   netsnmp_large_fd_set_init(&lreadfds, FD_SETSIZE);
00232   netsnmp_large_fd_set_init(&lwritefds, FD_SETSIZE);
00233   netsnmp_large_fd_set_init(&lexceptfds, FD_SETSIZE);
00234 
00235   netsnmp_copy_fd_set_to_large_fd_set(&lreadfds, readfds);
00236   netsnmp_copy_fd_set_to_large_fd_set(&lwritefds, writefds);
00237   netsnmp_copy_fd_set_to_large_fd_set(&lexceptfds, exceptfds);
00238 
00239   netsnmp_dispatch_external_events2(count, &lreadfds, &lwritefds, &lexceptfds);
00240 
00241   if (netsnmp_copy_large_fd_set_to_fd_set(readfds, &lreadfds) < 0
00242       || netsnmp_copy_large_fd_set_to_fd_set(writefds,  &lwritefds) < 0
00243       || netsnmp_copy_large_fd_set_to_fd_set(exceptfds, &lexceptfds) < 0)
00244   {
00245     snmp_log(LOG_ERR,
00246              "Use netsnmp_dispatch_external_events2() for processing"
00247              " large file descriptors\n");
00248   }
00249 
00250   netsnmp_large_fd_set_cleanup(&lreadfds);
00251   netsnmp_large_fd_set_cleanup(&lwritefds);
00252   netsnmp_large_fd_set_cleanup(&lexceptfds);
00253 }
00254 
00255 void netsnmp_dispatch_external_events2(int *count,
00256                                        netsnmp_large_fd_set *readfds,
00257                                        netsnmp_large_fd_set *writefds,
00258                                        netsnmp_large_fd_set *exceptfds)
00259 {
00260   int i;
00261   for (i = 0;
00262        *count && (i < external_readfdlen) && !external_fd_unregistered; i++) {
00263       if (NETSNMP_LARGE_FD_ISSET(external_readfd[i], readfds)) {
00264           DEBUGMSGTL(("fd_event_manager:netsnmp_dispatch_external_events", 
00265                      "readfd[%d] = %d\n", i, external_readfd[i]));
00266           external_readfdfunc[i] (external_readfd[i],
00267                                   external_readfd_data[i]);
00268           NETSNMP_LARGE_FD_CLR(external_readfd[i], readfds);
00269           (*count)--;
00270       }
00271   }
00272   for (i = 0;
00273        *count && (i < external_writefdlen) && !external_fd_unregistered; i++) {
00274       if (NETSNMP_LARGE_FD_ISSET(external_writefd[i], writefds)) {
00275           DEBUGMSGTL(("fd_event_manager:netsnmp_dispatch_external_events", 
00276                      "writefd[%d] = %d\n", i, external_writefd[i]));
00277           external_writefdfunc[i] (external_writefd[i],
00278                                    external_writefd_data[i]);
00279           NETSNMP_LARGE_FD_CLR(external_writefd[i], writefds);
00280           (*count)--;
00281       }
00282   }
00283   for (i = 0;
00284        *count && (i < external_exceptfdlen) && !external_fd_unregistered; i++) {
00285       if (NETSNMP_LARGE_FD_ISSET(external_exceptfd[i], exceptfds)) {
00286           DEBUGMSGTL(("fd_event_manager:netsnmp_dispatch_external_events", 
00287                      "exceptfd[%d] = %d\n", i, external_exceptfd[i]));
00288           external_exceptfdfunc[i] (external_exceptfd[i],
00289                                     external_exceptfd_data[i]);
00290           NETSNMP_LARGE_FD_CLR(external_exceptfd[i], exceptfds);
00291           (*count)--;
00292       }
00293   }
00294 }
00295 #else  /*  !NETSNMP_FEATURE_REMOVE_FD_EVENT_MANAGER */
00296 netsnmp_feature_unused(fd_event_manager);
00297 #endif /*  !NETSNMP_FEATURE_REMOVE_FD_EVENT_MANAGER */