really kill the helper if something went wrong
[oweals/gnunet.git] / src / vpn / gnunet-daemon-vpn.c
index 658a3fd7cabef081ad4fec8df4f133343f7732b7..ddd540cb0744874f409ff00b6c6c340252665dca 100644 (file)
@@ -1,10 +1,10 @@
 /*
      This file is part of GNUnet.
 /*
      This file is part of GNUnet.
-     (C) 2010 Christian Grothoff (and other contributing authors)
+     (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
 
      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 2, or (at your
+     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
      option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
 /**
  * @file vpn/gnunet-daemon-vpn.c
  * @brief 
 /**
  * @file vpn/gnunet-daemon-vpn.c
  * @brief 
- * @author Christian Grothoff
+ * @author Philipp Tölke
  */
 #include "platform.h"
 #include "gnunet_getopt_lib.h"
 #include "gnunet_program_lib.h"
  */
 #include "platform.h"
 #include "gnunet_getopt_lib.h"
 #include "gnunet_program_lib.h"
+#include "gnunet_os_lib.h"
+#include "gnunet-vpn-helper-p.h"
+#include "gnunet-vpn-packet.h"
+#include "gnunet-vpn-pretty-print.h"
+#include "gnunet_common.h"
+#include "gnunet_protocols.h"
+#include "gnunet_server_lib.h"
 /* #include "gnunet_template_service.h" */
 
 /**
 /* #include "gnunet_template_service.h" */
 
 /**
  */
 static int ret;
 
  */
 static int ret;
 
+struct vpn_cls {
+       struct GNUNET_DISK_PipeHandle* helper_in; // From the helper
+       struct GNUNET_DISK_PipeHandle* helper_out; // To the helper
+       const struct GNUNET_DISK_FileHandle* fh_from_helper;
+
+       struct GNUNET_SERVER_MessageStreamTokenizer* mst;
+
+       struct GNUNET_SCHEDULER_Handle *sched;
+
+       pid_t helper_pid;
+};
+
+static void cleanup(void* cls, const struct GNUNET_SCHEDULER_TaskContext* tskctx) {
+       struct vpn_cls* mycls = (struct vpn_cls*) cls;
+       if (tskctx->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) {
+               PLIBC_KILL(mycls->helper_pid, SIGTERM);
+               GNUNET_OS_process_wait(mycls->helper_pid);
+       }
+}
+
+static void helper_read(void* cls, const struct GNUNET_SCHEDULER_TaskContext* tsdkctx);
+
+static void start_helper_and_schedule(struct vpn_cls* mycls) {
+       mycls->helper_in = GNUNET_DISK_pipe(1);
+       mycls->helper_out = GNUNET_DISK_pipe(1);
+
+       mycls->helper_pid = GNUNET_OS_start_process(mycls->helper_in, mycls->helper_out, "gnunet-vpn-helper", "gnunet-vpn-helper", NULL);
+
+       mycls->fh_from_helper = GNUNET_DISK_pipe_handle (mycls->helper_out, GNUNET_DISK_PIPE_END_READ);
+
+       GNUNET_DISK_pipe_close_end(mycls->helper_out, GNUNET_DISK_PIPE_END_WRITE);
+       GNUNET_DISK_pipe_close_end(mycls->helper_in, GNUNET_DISK_PIPE_END_READ);
+
+       GNUNET_SCHEDULER_add_read_file (mycls->sched, GNUNET_TIME_UNIT_FOREVER_REL, mycls->fh_from_helper, &helper_read, mycls);
+}
+
+
+static void restart_helper(void* cls, const struct GNUNET_SCHEDULER_TaskContext* tskctx) {
+       struct vpn_cls* mycls = (struct vpn_cls*) cls;
+
+       // Kill the helper
+       PLIBC_KILL(mycls->helper_pid, SIGKILL);
+       GNUNET_OS_process_wait(mycls->helper_pid);
+
+       // Restart the helper
+       start_helper_and_schedule(mycls);
+
+}
+
+static void helper_read(void* cls, const struct GNUNET_SCHEDULER_TaskContext* tsdkctx) {
+       struct vpn_cls* mycls = (struct vpn_cls*) cls;
+       char buf[65535];
+
+       if (tsdkctx->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)
+               return;
+
+       int t = GNUNET_DISK_file_read(mycls->fh_from_helper, &buf, 65535);
+       if (t<=0) {
+               fprintf(stderr, "Read error for header: %m\n");
+               GNUNET_SCHEDULER_add_now(mycls->sched, restart_helper, cls);
+               return;
+       }
+
+       /* FIXME */ GNUNET_SERVER_mst_receive(mycls->mst, NULL, buf, t, 0, 0);
+
+       GNUNET_SCHEDULER_add_read_file (mycls->sched, GNUNET_TIME_UNIT_FOREVER_REL, mycls->fh_from_helper, &helper_read, mycls);
+}
+
+static void message_token(void *cls, void *client, const struct GNUNET_MessageHeader *message) {
+       if (ntohs(message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) return;
+
+       struct ip6_pkt *pkt6 = (struct ip6_pkt*) message;
+       struct ip6_tcp *pkt6_tcp;
+       struct ip6_udp *pkt6_udp;
+
+       pkt_printf(pkt6);
+       switch(pkt6->ip6_hdr.nxthdr) {
+               case 0x06:
+                       pkt6_tcp = (struct ip6_tcp*)pkt6;
+                       pkt_printf_ip6tcp(pkt6_tcp);
+                       break;
+               case 0x11:
+                       pkt6_udp = (struct ip6_udp*)pkt6;
+                       pkt_printf_ip6udp(pkt6_udp);
+                       if (ntohs(pkt6_udp->udp_hdr.dpt) == 53) {
+                               pkt_printf_ip6dns((struct ip6_udp_dns*)pkt6_udp);
+                       }
+                       break;
+       }
+
+}
+
 /**
  * Main function that will be run by the scheduler.
  *
 /**
  * Main function that will be run by the scheduler.
  *
@@ -44,12 +143,20 @@ static int ret;
  */
 static void
 run (void *cls,
  */
 static void
 run (void *cls,
-     struct GNUNET_SCHEDULER_Handle *sched,
-     char *const *args,
-     const char *cfgfile,
-     const struct GNUNET_CONFIGURATION_Handle *cfg)
-{
-  /* main code here */
+               struct GNUNET_SCHEDULER_Handle *sched,
+               char *const *args,
+               const char *cfgfile,
+               const struct GNUNET_CONFIGURATION_Handle *cfg) {
+
+       struct vpn_cls* mycls = (struct vpn_cls*) cls;
+
+       mycls->sched = sched;
+
+       mycls->mst = GNUNET_SERVER_mst_create(&message_token, mycls);
+
+       GNUNET_SCHEDULER_add_delayed(sched, GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls);
+
+       start_helper_and_schedule(mycls);
 }
 
 
 }
 
 
@@ -66,12 +173,17 @@ main (int argc, char *const *argv)
   static const struct GNUNET_GETOPT_CommandLineOption options[] = {
     GNUNET_GETOPT_OPTION_END
   };
   static const struct GNUNET_GETOPT_CommandLineOption options[] = {
     GNUNET_GETOPT_OPTION_END
   };
+
+  struct vpn_cls* cls = (struct vpn_cls*)malloc(sizeof(struct vpn_cls));
+
   return (GNUNET_OK ==
           GNUNET_PROGRAM_run (argc,
                               argv,
                               "gnunet-daemon-vpn",
                               gettext_noop ("help text"),
   return (GNUNET_OK ==
           GNUNET_PROGRAM_run (argc,
                               argv,
                               "gnunet-daemon-vpn",
                               gettext_noop ("help text"),
-                              options, &run, NULL)) ? ret : 1;
+                              options, &run, cls)) ? ret : 1;
+
+  free(cls); // Make clang happy
 }
 
 /* end of gnunet-daemon-vpn.c */
 }
 
 /* end of gnunet-daemon-vpn.c */