diff options
Diffstat (limited to 'src/dispatch.c')
-rw-r--r-- | src/dispatch.c | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/src/dispatch.c b/src/dispatch.c new file mode 100644 index 0000000..9435193 --- /dev/null +++ b/src/dispatch.c @@ -0,0 +1,109 @@ +#include <sys/types.h> +#include <sys/socket.h> +#include <arpa/inet.h> +#include <assert.h> +#include <errno.h> +#include <poll.h> +#include <pthread.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <unistd.h> + +#include <rpc/rpc.h> +#include <rpc/pmap_clnt.h> +#include <rpcsvc/yp_prot.h> + +#include <nspr.h> +#include <secport.h> +#include <plarenas.h> +#include <dirsrv/slapi-plugin.h> + +#include "dispatch.h" +#include "nis.h" +#include "plugin.h" +#include "portmap.h" +#include "schema.h" +#include "stream.h" + +/* Handle a datagram client -- read the request and handle it immediately. */ +static void +dispatch_dgram(struct plugin_state *state, int fd) +{ + struct sockaddr_storage client_addr; + socklen_t client_addrlen; + char dgram[65536]; + int reqsize; + + /* Read the request. */ + client_addrlen = sizeof(client_addr); + reqsize = recvfrom(fd, dgram, sizeof(dgram), 0, + (struct sockaddr *) &client_addr, &client_addrlen); + slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, + "datagram request\n"); + + /* Handle the request. */ + nis_process_request(state, fd, + (struct sockaddr *) &client_addr, client_addrlen, + dgram, reqsize); +} + +/* Handle a stream client -- answer the connection and spawn a thread to handle + * its requests. */ +static void +dispatch_stream(struct plugin_state *state, int fd) +{ + struct sockaddr_storage client_addr; + socklen_t client_addrlen; + int client; + client = accept(fd, (struct sockaddr *) &client_addr, &client_addrlen); + if (client != -1) { + slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, + "new stream request\n"); + stream_client_start(state, client); + } +} + +void * +dispatch_thread(void *p) +{ + struct plugin_state *state = p; + struct pollfd fds[4]; + int i; + for (;;) { + /* Set up for polling. */ + memset(&fds, 0, sizeof(fds)); + for (i = 0; i < state->n_listeners; i++) { + fds[i].fd = state->listener[i].fd; + fds[i].events = POLLIN; + } + switch (poll(fds, state->n_listeners, -1)) { + case -1: + return NULL; + break; + case 0: + continue; + default: + /* Iterate over listening sockets which have work for + * us to do. */ + for (i = 0; i < state->n_listeners; i++) { + if ((fds[i].revents & POLLIN) == 0) { + continue; + } + switch (state->listener[i].type) { + case SOCK_DGRAM: + dispatch_dgram(state, fds[i].fd); + break; + case SOCK_STREAM: + dispatch_stream(state, fds[i].fd); + break; + default: + /* never reached */ + assert(0); + break; + } + } + } + } + return state; +} |