summaryrefslogtreecommitdiffstats
path: root/src/dispatch.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dispatch.c')
-rw-r--r--src/dispatch.c109
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;
+}