From ac0d240e011c27b1d660b6db05d067bf8766db73 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Philipp=20T=C3=B6lke?= Date: Wed, 2 Feb 2011 23:02:52 +0000 Subject: [PATCH] refactor the interface to the helper a bit to make it easier to use from -exit --- src/vpn/Makefile.am | 3 +- src/vpn/gnunet-daemon-vpn-helper.c | 118 +++++++------------------ src/vpn/gnunet-daemon-vpn-helper.h | 11 +-- src/vpn/gnunet-daemon-vpn.c | 11 +-- src/vpn/gnunet-helper-vpn-api.c | 136 +++++++++++++++++++++++++++++ src/vpn/gnunet-helper-vpn-api.h | 116 ++++++++++++++++++++++++ 6 files changed, 290 insertions(+), 105 deletions(-) create mode 100644 src/vpn/gnunet-helper-vpn-api.c create mode 100644 src/vpn/gnunet-helper-vpn-api.h diff --git a/src/vpn/Makefile.am b/src/vpn/Makefile.am index f1b0e1df7..a36f56833 100644 --- a/src/vpn/Makefile.am +++ b/src/vpn/Makefile.am @@ -36,7 +36,8 @@ gnunet_daemon_vpn_SOURCES = \ gnunet-vpn-pretty-print.c gnunet-vpn-pretty-print.h \ gnunet-dns-parser.c gnunet-dns-parser.h \ gnunet-daemon-vpn-helper.c gnunet-daemon-vpn-helper.h \ - gnunet-daemon-vpn-dns.c gnunet-daemon-vpn-dns.h + gnunet-daemon-vpn-dns.c gnunet-daemon-vpn-dns.h \ + gnunet-helper-vpn-api.c gnunet-helper-vpn-api.h gnunet_daemon_vpn_LDADD = \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ diff --git a/src/vpn/gnunet-daemon-vpn-helper.c b/src/vpn/gnunet-daemon-vpn-helper.c index d2815d4e5..ae6d18fd9 100644 --- a/src/vpn/gnunet-daemon-vpn-helper.c +++ b/src/vpn/gnunet-daemon-vpn-helper.c @@ -40,28 +40,11 @@ #include "gnunet-service-dns-p.h" #include "gnunet-vpn-packet.h" -/** - * PipeHandle to receive data from the helper - */ -static struct GNUNET_DISK_PipeHandle* helper_in; - -/** - * PipeHandle to send data to the helper - */ -static struct GNUNET_DISK_PipeHandle* helper_out; - -/** - * FileHandle to receive data from the helper - */ -static const struct GNUNET_DISK_FileHandle* fh_from_helper; - -/** - * FileHandle to send data to the helper - */ -static const struct GNUNET_DISK_FileHandle* fh_to_helper; - /** * Start the helper-process + * + * If cls != NULL it is assumed that this function is called as a result of a dying + * helper. cls is then taken as handle to the old helper and is cleaned up. * {{{ */ void @@ -70,16 +53,22 @@ start_helper_and_schedule(void *cls, if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; - helper_in = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO); - helper_out = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_NO, GNUNET_YES); - - if (helper_in == NULL || helper_out == NULL) return; + if (cls != NULL) + cleanup_helper(cls); + cls = NULL; + char* ifname; char* ipv6addr; char* ipv6prefix; char* ipv4addr; char* ipv4mask; + if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, "vpn", "IFNAME", &ifname)) + { + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "No entry 'IFNAME' in configuration!\n"); + exit(1); + } + if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, "vpn", "IPV6ADDR", &ipv6addr)) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "No entry 'IPV6ADDR' in configuration!\n"); @@ -104,75 +93,32 @@ start_helper_and_schedule(void *cls, exit(1); } - helper_proc = - GNUNET_OS_start_process (helper_in, helper_out, "gnunet-helper-vpn", - "gnunet-helper-vpn", ipv6addr, ipv6prefix, - ipv4addr, ipv4mask, NULL); + /* Start the helper + * Messages get passed to the function message_token + * When the helper dies, this function will be called again with the + * helper_handle as cls. + */ + helper_handle = start_helper(ifname, + ipv6addr, + ipv6prefix, + ipv4addr, + ipv4mask, + "vpn-gnunet", + start_helper_and_schedule, + message_token, + NULL, + NULL); GNUNET_free(ipv6addr); GNUNET_free(ipv6prefix); GNUNET_free(ipv4addr); GNUNET_free(ipv4mask); - fh_from_helper = GNUNET_DISK_pipe_handle (helper_out, GNUNET_DISK_PIPE_END_READ); - fh_to_helper = GNUNET_DISK_pipe_handle (helper_in, GNUNET_DISK_PIPE_END_WRITE); - - GNUNET_DISK_pipe_close_end(helper_out, GNUNET_DISK_PIPE_END_WRITE); - GNUNET_DISK_pipe_close_end(helper_in, GNUNET_DISK_PIPE_END_READ); - /* Tell the dns-service to rehijack the dns-port * The routing-table gets flushed if an interface disappears. */ restart_hijack = 1; GNUNET_CLIENT_notify_transmit_ready(dns_connection, sizeof(struct GNUNET_MessageHeader), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, &send_query, NULL); - - GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, fh_from_helper, &helper_read, NULL); -} -/*}}}*/ -/** - * Restart the helper-process - * {{{ - */ -void -restart_helper(void* cls, const struct GNUNET_SCHEDULER_TaskContext* tskctx) { - // Kill the helper - GNUNET_OS_process_kill (helper_proc, SIGKILL); - GNUNET_OS_process_wait (helper_proc); - GNUNET_OS_process_close (helper_proc); - helper_proc = NULL; - - GNUNET_DISK_pipe_close(helper_in); - GNUNET_DISK_pipe_close(helper_out); - - /* Restart the helper */ - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, start_helper_and_schedule, NULL); -} -/*}}}*/ - -/** - * Read from the helper-process - * {{{ - */ -void -helper_read(void* cls, const struct GNUNET_SCHEDULER_TaskContext* tsdkctx) { - /* no message can be bigger then 64k */ - char buf[65535]; - - if (tsdkctx->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) - return; - - int t = GNUNET_DISK_file_read(fh_from_helper, &buf, 65535); - - /* On read-error, restart the helper */ - if (t<=0) { - GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Read error for header from vpn-helper: %m\n"); - GNUNET_SCHEDULER_add_now(restart_helper, cls); - return; - } - - /* FIXME */ GNUNET_SERVER_mst_receive(mst, NULL, buf, t, 0, 0); - - GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, fh_from_helper, &helper_read, NULL); } /*}}}*/ @@ -234,12 +180,12 @@ helper_write(void* cls, const struct GNUNET_SCHEDULER_TaskContext* tsdkctx) { GNUNET_CONTAINER_DLL_remove (answer_proc_head, answer_proc_tail, ans); GNUNET_free(ans); - /* FIXME */ GNUNET_DISK_file_write(fh_to_helper, pkt, pkt_len); + /* FIXME */ GNUNET_DISK_file_write(helper_handle->fh_to_helper, pkt, pkt_len); /* if more packets are available, reschedule */ if (answer_proc_head != NULL) GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL, - fh_to_helper, + helper_handle->fh_to_helper, &helper_write, NULL); } @@ -361,10 +307,10 @@ message_token(void *cls, void write_to_helper(void* buf, size_t len) { - (void)GNUNET_DISK_file_write(fh_to_helper, buf, len); + (void)GNUNET_DISK_file_write(helper_handle->fh_to_helper, buf, len); } void schedule_helper_write(struct GNUNET_TIME_Relative time, void* cls) { - GNUNET_SCHEDULER_add_write_file (time, fh_to_helper, &helper_write, cls); + GNUNET_SCHEDULER_add_write_file (time, helper_handle->fh_to_helper, &helper_write, cls); } diff --git a/src/vpn/gnunet-daemon-vpn-helper.h b/src/vpn/gnunet-daemon-vpn-helper.h index c7234c092..17d775b86 100644 --- a/src/vpn/gnunet-daemon-vpn-helper.h +++ b/src/vpn/gnunet-daemon-vpn-helper.h @@ -26,15 +26,12 @@ #ifndef GNUNET_DAEMON_VPN_HELPER_H #define GNUNET_DAEMON_VPN_HELPER_H -/** - * The process id of the helper - */ -struct GNUNET_OS_Process *helper_proc; +#include "gnunet-helper-vpn-api.h" /** - * The Message-Tokenizer that tokenizes the messages comming from the helper + * Handle to the helper. contains filedescriptors and such */ -struct GNUNET_SERVER_MessageStreamTokenizer* mst; +struct GNUNET_VPN_HELPER_Handle *helper_handle; /** * Start the helper-process @@ -65,9 +62,7 @@ void message_token(void *cls, const struct GNUNET_MessageHeader *message); void write_to_helper(void* buf, size_t len); -// GNUNET_DISK_file_write(fh_to_helper, response, ntohs(response->shdr.size)); void schedule_helper_write(struct GNUNET_TIME_Relative, void* cls); -// GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL, fh_to_helper, &helper_write, NULL); #endif /* end of include guard: GNUNET-DAEMON-VPN-HELPER_H */ diff --git a/src/vpn/gnunet-daemon-vpn.c b/src/vpn/gnunet-daemon-vpn.c index 1e0afea35..8424e9887 100644 --- a/src/vpn/gnunet-daemon-vpn.c +++ b/src/vpn/gnunet-daemon-vpn.c @@ -29,7 +29,6 @@ #include "gnunet-vpn-packet.h" #include "gnunet-vpn-pretty-print.h" #include "gnunet_common.h" -#include #include "gnunet_protocols.h" #include #include "gnunet_client_lib.h" @@ -61,14 +60,7 @@ cleanup(void* cls, const struct GNUNET_SCHEDULER_TaskContext* tskctx) { GNUNET_assert (0 != (tskctx->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)); /* stop the helper */ - if (helper_proc != NULL) - { - if (0 != GNUNET_OS_process_kill (helper_proc, SIGTERM)) - GNUNET_log_strerror(GNUNET_ERROR_TYPE_WARNING, "kill"); - GNUNET_OS_process_wait (helper_proc); - GNUNET_OS_process_close (helper_proc); - helper_proc = NULL; - } + cleanup_helper(helper_handle); /* close the connection to the service-dns */ if (dns_connection != NULL) @@ -478,7 +470,6 @@ run (void *cls, NULL, NULL, handlers); - mst = GNUNET_SERVER_mst_create(&message_token, NULL); cfg = cfg_; restart_hijack = 0; hashmap = GNUNET_CONTAINER_multihashmap_create(65536); diff --git a/src/vpn/gnunet-helper-vpn-api.c b/src/vpn/gnunet-helper-vpn-api.c new file mode 100644 index 000000000..c2ab6081d --- /dev/null +++ b/src/vpn/gnunet-helper-vpn-api.c @@ -0,0 +1,136 @@ +/* + This file is part of GNUnet. + (C) 2010 Christian Grothoff + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/** + * @file vpn/gnunet-helper-vpn-api.c + * @brief exposes the API (the convenience-functions) of dealing with the + * helper-vpn + * @author Philipp Toelke + */ + +#include +#include +#include +#include + +#include "gnunet-helper-vpn-api.h" + +static void +stop_helper (struct GNUNET_VPN_HELPER_Handle *handle) +{ + if (NULL == handle->helper_proc) + return; + GNUNET_OS_process_kill (handle->helper_proc, SIGKILL); + GNUNET_OS_process_wait (handle->helper_proc); + GNUNET_OS_process_close (handle->helper_proc); + handle->helper_proc = NULL; + + GNUNET_DISK_pipe_close (handle->helper_in); + GNUNET_DISK_pipe_close (handle->helper_out); +} + +/** + * Read from the helper-process + */ +static void +helper_read (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tsdkctx) +{ + struct GNUNET_VPN_HELPER_Handle *handle = cls; + /* no message can be bigger then 64k */ + char buf[65535]; + + if (tsdkctx->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) + return; + + int t = GNUNET_DISK_file_read (handle->fh_from_helper, &buf, 65535); + + /* On read-error, restart the helper */ + if (t <= 0) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Read error for header from vpn-helper: %m\n"); + stop_helper (handle); + + /* Restart the helper */ + GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, + handle->restart_task, handle); + return; + } + + /* FIXME */ GNUNET_SERVER_mst_receive (handle->mst, handle->client, buf, t, + 0, 0); + + GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, + handle->fh_from_helper, &helper_read, + handle); +} + +void +cleanup_helper (struct GNUNET_VPN_HELPER_Handle *handle) +{ + stop_helper (handle); + GNUNET_free (handle); +} + +struct GNUNET_VPN_HELPER_Handle * +start_helper (const char *ifname, + const char *ipv6addr, + const char *ipv6prefix, + const char *ipv4addr, + const char *ipv4mask, const char *process_name, + GNUNET_SCHEDULER_Task restart_task, + GNUNET_SERVER_MessageTokenizerCallback cb, void *cb_cls, + void *client) +{ + struct GNUNET_VPN_HELPER_Handle *handle = + GNUNET_malloc (sizeof (struct GNUNET_VPN_HELPER_Handle)); + + handle->helper_in = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO); + handle->helper_out = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_NO, GNUNET_YES); + + handle->restart_task = restart_task; + + if (handle->helper_in == NULL || handle->helper_out == NULL) + { + GNUNET_free (handle); + return NULL; + } + + handle->helper_proc = + GNUNET_OS_start_process (handle->helper_in, handle->helper_out, + "gnunet-helper-vpn", process_name, ifname, + ipv6addr, ipv6prefix, ipv4addr, ipv4mask, NULL); + + handle->fh_from_helper = + GNUNET_DISK_pipe_handle (handle->helper_out, GNUNET_DISK_PIPE_END_READ); + handle->fh_to_helper = + GNUNET_DISK_pipe_handle (handle->helper_in, GNUNET_DISK_PIPE_END_WRITE); + + GNUNET_DISK_pipe_close_end (handle->helper_out, GNUNET_DISK_PIPE_END_WRITE); + GNUNET_DISK_pipe_close_end (handle->helper_in, GNUNET_DISK_PIPE_END_READ); + + handle->mst = GNUNET_SERVER_mst_create (cb, cb_cls); + + GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, + handle->fh_from_helper, &helper_read, + handle); + + return handle; +} diff --git a/src/vpn/gnunet-helper-vpn-api.h b/src/vpn/gnunet-helper-vpn-api.h new file mode 100644 index 000000000..00eb7db62 --- /dev/null +++ b/src/vpn/gnunet-helper-vpn-api.h @@ -0,0 +1,116 @@ +/* + This file is part of GNUnet. + (C) 2010 Christian Grothoff + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/** + * @file vpn/gnunet-helper-vpn-api.h + * @brief exposes the API (the convenience-functions) of dealing with the + * helper-vpn + * @author Philipp Toelke + */ +#ifndef GNUNET_HELPER_VPN_API_H +#define GNUNET_HELPER_VPN_API_H + +/** + * The handle to a helper. + * sometimes a few entries may be made opaque. + */ +struct GNUNET_VPN_HELPER_Handle +{ +/** + * PipeHandle to receive data from the helper + */ + struct GNUNET_DISK_PipeHandle *helper_in; + +/** + * PipeHandle to send data to the helper + */ + struct GNUNET_DISK_PipeHandle *helper_out; + +/** + * FileHandle to receive data from the helper + */ + const struct GNUNET_DISK_FileHandle *fh_from_helper; + +/** + * FileHandle to send data to the helper + */ + const struct GNUNET_DISK_FileHandle *fh_to_helper; + + /** + * The process id of the helper + */ + struct GNUNET_OS_Process *helper_proc; + + /** + * The Message-Tokenizer that tokenizes the messages comming from the helper + */ + struct GNUNET_SERVER_MessageStreamTokenizer *mst; + + /** + * The client-identifier passed to the mst-callback + */ + void *client; + + /** + * The name of the interface + */ + char *ifname; + + /** + * The task called when the helper dies. + * Will be called with the handle as cls + */ + GNUNET_SCHEDULER_Task restart_task; +}; + +/** + * @brief Starts a helper and begins reading from it + * + * @param ifname The name of the new interface + * @param ipv6addr The IPv6 address of the new interface + * @param ipv6prefix The IPv6 prefix length of the new IP + * @param ipv4addr The IPv4 address of the new interface + * @param ipv4mask The associated netmask + * @param process_name How the helper should appear in process-listings + * @param restart_task The task called when the helper dies. Will be called with the handle as cls + * @param cb A callback for messages from the helper + * @param cb_cls Closure for the callback + * @param client client_name for the callback + * + * @return A pointer to the new Handle, NULL on error + */ +struct GNUNET_VPN_HELPER_Handle *start_helper (const char *ifname, + const char *ipv6addr, + const char *ipv6prefix, + const char *ipv4addr, + const char *ipv4mask, + const char *process_name, + GNUNET_SCHEDULER_Task + restart_task, + GNUNET_SERVER_MessageTokenizerCallback + cb, void *cb_cls, + void *client); + +/** + * @brief Kills the helper, closes the pipe and free()s the handle + */ +void cleanup_helper (struct GNUNET_VPN_HELPER_Handle *); + +#endif /* end of include guard: GNUNET_HELPER_VPN_API_H */ -- 2.25.1