#include "services/modstack.h"
#include "util/module.h"
#include "util/random.h"
+#include "util/tube.h"
#include <signal.h>
/** How many quit requests happened. */
int i;
for(i=0; i<daemon->num; i++)
if(i!=thr) {
- if(daemon->workers[i]->cmd_send_fd != -1) {
- close(daemon->workers[i]->cmd_send_fd);
- daemon->workers[i]->cmd_send_fd = -1;
- }
- if(daemon->workers[i]->cmd_recv_fd != -1) {
- close(daemon->workers[i]->cmd_recv_fd);
- daemon->workers[i]->cmd_recv_fd = -1;
- }
+ tube_delete(daemon->workers[i]->cmd);
+ daemon->workers[i]->cmd = NULL;
}
}
#include "util/data/msgencode.h"
#include "util/data/dname.h"
#include "util/fptr_wlist.h"
+#include "util/tube.h"
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
ldns_buffer_write_u16(buffer, sizeof(uint32_t));
ldns_buffer_write_u32(buffer, (uint32_t)cmd);
ldns_buffer_flip(buffer);
- if(!write_socket(worker->cmd_send_fd, ldns_buffer_begin(buffer),
- ldns_buffer_limit(buffer)))
- log_err("write socket: %s", strerror(errno));
+ if(!tube_send_cmd(worker->cmd, buffer)) {
+ log_err("worker send cmd %d failed", (int)cmd);
+ }
}
int
return 0;
}
-int
-worker_handle_control_cmd(struct comm_point* c, void* arg, int error,
- struct comm_reply* ATTR_UNUSED(reply_info))
+void
+worker_handle_control_cmd(struct tube* ATTR_UNUSED(tube), ldns_buffer* buffer,
+ int error, void* arg)
{
struct worker* worker = (struct worker*)arg;
enum worker_commands cmd;
if(error == NETEVENT_CLOSED)
comm_base_exit(worker->base);
else log_info("control event: %d", error);
- return 0;
+ return;
}
- if(ldns_buffer_limit(c->buffer) != sizeof(uint32_t)) {
+ if(ldns_buffer_limit(buffer) != sizeof(uint32_t)) {
fatal_exit("bad control msg length %d",
- (int)ldns_buffer_limit(c->buffer));
+ (int)ldns_buffer_limit(buffer));
}
- cmd = ldns_buffer_read_u32(c->buffer);
+ cmd = ldns_buffer_read_u32(buffer);
switch(cmd) {
case worker_cmd_quit:
verbose(VERB_ALGO, "got control cmd quit");
log_err("bad command %d", (int)cmd);
break;
}
- return 0;
}
/** check if a delegation is secure */
}
worker->daemon = daemon;
worker->thread_num = id;
- worker->cmd_send_fd = -1;
- worker->cmd_recv_fd = -1;
if(id != 0) {
- int sv[2];
- /* create socketpair to communicate with worker */
- if(socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == -1) {
- free(worker);
- log_err("socketpair: %s", strerror(errno));
- return NULL;
- }
- if(!fd_set_nonblock(sv[0]) || !fd_set_nonblock(sv[1])) {
- close(sv[0]);
- close(sv[1]);
+ if(!(worker->cmd = tube_create())) {
+ free(worker->ports);
free(worker);
return NULL;
}
- worker->cmd_send_fd = sv[0];
- worker->cmd_recv_fd = sv[1];
}
return worker;
}
}
if(worker->thread_num != 0) {
/* start listening to commands */
- if(!(worker->cmd_com=comm_point_create_local(worker->base,
- worker->cmd_recv_fd, cfg->msg_buffer_size,
- worker_handle_control_cmd, worker))) {
+ if(!tube_listen_cmd(worker->cmd, worker->base,
+ cfg->msg_buffer_size, worker_handle_control_cmd,
+ worker)) {
log_err("could not create control compt.");
worker_delete(worker);
return 0;
listen_delete(worker->front);
outside_network_delete(worker->back);
comm_signal_delete(worker->comsig);
- comm_point_delete(worker->cmd_com);
+ tube_delete(worker->cmd);
comm_timer_delete(worker->stat_timer);
free(worker->ports);
if(worker->thread_num == 0)
log_set_time(NULL);
comm_base_delete(worker->base);
ub_randfree(worker->rndstate);
- /* close fds after deleting commpoints, to be sure.
- Also epoll does not like closing fd before event_del */
- if(worker->cmd_send_fd != -1)
- close(worker->cmd_send_fd);
- worker->cmd_send_fd = -1;
- if(worker->cmd_recv_fd != -1)
- close(worker->cmd_recv_fd);
- worker->cmd_recv_fd = -1;
alloc_clear(&worker->alloc);
regional_destroy(worker->scratchpad);
free(worker);
struct listen_port;
struct ub_randstate;
struct regional;
+struct tube;
/** worker commands */
enum worker_commands {
struct daemon* daemon;
/** thread id */
ub_thread_t thr_id;
- /** fd 0 of socketpair, write commands for worker to this one */
- int cmd_send_fd;
- /** fd 1 of socketpair, worker listens on this one */
- int cmd_recv_fd;
+ /** pipe, for commands for this worker */
+ struct tube* cmd;
/** the event base this worker works with */
struct comm_base* base;
/** the frontside listening interface where request events come in */
/**
* process control messages from the main thread.
- * @param c: comm point to read from.
- * @param arg: worker.
- * @param error: error status of comm point.
- * @param reply_info: not used.
+ * @param tube: tube control message came on.
+ * @param buf: buffer with message in it.
+ * @param error: if error (NETEVENT_*) happened.
+ * @param arg: user argument
*/
-int worker_handle_control_cmd(struct comm_point* c, void* arg, int error,
- struct comm_reply* reply_info);
+void worker_handle_control_cmd(struct tube* tube, ldns_buffer* buffer,
+ int error, void* arg);
/** handles callbacks from listening event interface */
int worker_handle_request(struct comm_point* c, void* arg, int error,
18 July 2008: Wouter
- branch for 1.0 support.
+ - trunk work on tube.c.
17 July 2008: Wouter
- fix bug #196, compile outside source tree.
#include "daemon/acl_list.h"
#include "libunbound/libworker.h"
#include "libunbound/context.h"
+#include "util/tube.h"
int
fptr_whitelist_comm_point(comm_point_callback_t *fptr)
if(fptr == &worker_handle_request) return 1;
else if(fptr == &outnet_udp_cb) return 1;
else if(fptr == &outnet_tcp_cb) return 1;
- else if(fptr == &worker_handle_control_cmd) return 1;
+ else if(fptr == &tube_handle_listen) return 1;
return 0;
}
if(fptr == &worker_alloc_cleanup) return 1;
return 0;
}
+
+int fptr_whitelist_tube_listen(tube_callback_t* fptr)
+{
+ if(fptr == &worker_handle_control_cmd) return 1;
+ return 0;
+}
#include "util/netevent.h"
#include "util/storage/lruhash.h"
#include "util/module.h"
+#include "util/tube.h"
/**
* Macro to perform an assertion check for fptr wlist checks.
*/
int fptr_whitelist_alloc_cleanup(void (*fptr)(void*));
+/**
+ * Check function pointer whitelist for tube listen handler values.
+ *
+ * @param fptr: function pointer to check.
+ * @return false if not in whitelist.
+ */
+int fptr_whitelist_tube_listen(tube_callback_t* fptr);
+
/** Due to module breakage by fptr wlist, these test app declarations
* are presented here */
/**
--- /dev/null
+/*
+ * util/tube.c - pipe service
+ *
+ * Copyright (c) 2008, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file
+ *
+ * This file contains pipe service functions.
+ */
+#include "config.h"
+#include "util/tube.h"
+#include "util/log.h"
+#include "util/net_help.h"
+#include "util/netevent.h"
+#include "util/fptr_wlist.h"
+
+struct tube* tube_create(void)
+{
+ struct tube* tube = (struct tube*)calloc(1, sizeof(*tube));
+ int sv[2];
+ if(!tube) return 0;
+ tube->sr = -1;
+ tube->sw = -1;
+ if(socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == -1) {
+ log_err("socketpair: %s", strerror(errno));
+ free(tube);
+ return NULL;
+ }
+ tube->sr = sv[0];
+ tube->sw = sv[1];
+ if(!fd_set_nonblock(tube->sr) || !fd_set_nonblock(tube->sw)) {
+ log_err("tube: cannot set nonblocking");
+ tube_delete(tube);
+ return NULL;
+ }
+ return tube;
+}
+
+void tube_delete(struct tube* tube)
+{
+ if(!tube) return;
+ if(tube->listen_com) {
+ comm_point_delete(tube->listen_com);
+ }
+ /* close fds after deleting commpoints, to be sure.
+ * Also epoll does not like closing fd before event_del */
+ if(tube->sr != -1) close(tube->sr);
+ if(tube->sw != -1) close(tube->sw);
+ tube->sr = -1;
+ tube->sw = -1;
+ free(tube);
+}
+
+int
+tube_handle_listen(struct comm_point* c, void* arg, int error,
+ struct comm_reply* ATTR_UNUSED(reply_info))
+{
+ struct tube* tube = (struct tube*)arg;
+ if(error != NETEVENT_NOERROR) {
+ fptr_ok(fptr_whitelist_tube_listen(tube->listen_cb));
+ (*tube->listen_cb)(tube, NULL, error, tube->listen_arg);
+ return 0;
+ }
+ fptr_ok(fptr_whitelist_tube_listen(tube->listen_cb));
+ (*tube->listen_cb)(tube, c->buffer, error, tube->listen_arg);
+ return 0;
+}
+
+int tube_listen_cmd(struct tube* tube, struct comm_base* base,
+ size_t msg_buffer_sz, tube_callback_t* cb, void* arg)
+{
+ tube->listen_cb = cb;
+ tube->listen_arg = arg;
+ if(!(tube->listen_com = comm_point_create_local(base, tube->sr,
+ msg_buffer_sz, tube_handle_listen, tube))) {
+ log_err("tube_listen_cmd: commpoint creation failed");
+ return 0;
+ }
+ return 1;
+}
+
+int tube_send_cmd(struct tube* tube, ldns_buffer* buffer)
+{
+ if(!write_socket(tube->sw, ldns_buffer_begin(buffer),
+ ldns_buffer_limit(buffer))) {
+ log_err("write socket: %s", strerror(errno));
+ return 0;
+ }
+ return 1;
+}
--- /dev/null
+/*
+ * util/tube.h - pipe service
+ *
+ * Copyright (c) 2008, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file
+ *
+ * This file contains pipe service functions.
+ */
+
+#ifndef UTIL_TUBE_H
+#define UTIL_TUBE_H
+struct comm_reply;
+struct comm_base;
+struct tube;
+
+/**
+ * Callback from pipe listen function
+ * void mycallback(tube, buffer, error, argument);
+ * if error is true (NETEVENT_*), buffer is probably NULL.
+ */
+typedef void (tube_callback_t)(struct tube* tube, ldns_buffer* buffer,
+ int error, void* arg);
+
+/**
+ * A pipe
+ */
+struct tube {
+ /** pipe end to read from */
+ int sr;
+ /** pipe end to write on */
+ int sw;
+
+ /** listen commpoint */
+ struct comm_point* listen_com;
+ /** listen callback */
+ tube_callback_t* listen_cb;
+ /** listen callback user arg */
+ void* listen_arg;
+};
+
+/**
+ * Create a pipe
+ * @return: new tube struct or NULL on error.
+ */
+struct tube* tube_create(void);
+
+/**
+ * Delete and destroy a pipe
+ * @param tube: to delete
+ */
+void tube_delete(struct tube* tube);
+
+/**
+ * Start listening for information over the pipe
+ * @param tube: tube to listen on
+ * @param base: what base to register event callback.
+ * @param msg_buffer_sz: what message buffer size to use.
+ * @param cb: callback routine.
+ * @param arg: user argument for callback routine.
+ * @return true if successful, false on error.
+ */
+int tube_listen_cmd(struct tube* tube, struct comm_base* base,
+ size_t msg_buffer_sz, tube_callback_t* cb, void* arg);
+
+/**
+ * Send a command over a pipe, blocking operation.
+ * @param tube: tube to send the info on.
+ * @param buffer: buffer to send. starts with network order uint16 with
+ * length of remainder of buffer.
+ * The receiver does not receive the length uint16 in the buffer
+ * (the buffer is sized appropriately).
+ * @return 0 on error, true on success.
+ */
+int tube_send_cmd(struct tube* tube, ldns_buffer* buffer);
+
+/** decl for fptr_wlist of tube pipe listen handler */
+int tube_handle_listen(struct comm_point* c, void* arg, int error,
+ struct comm_reply* reply_info);
+
+#endif /* UTIL_TUBE_H */