+User notification of the probe timeout.
[udpgate.git] / src / network.c
index e3740a6..dfe306e 100644 (file)
 
 #include "network.h"
 #include "packet.h"
+#include "main.h"      /* for optarg_verbose */
 
 
 /* Config: */
 #define NETWORK_PATHNAME_PID "/var/run/udpgate.pid"
 #define SOCK_SOURCE_CHECK_EVENTS (G_IO_IN)     /* |G_IO_PRI */
 #define SOCK_SOURCE_CHECK_REVENTS (SOCK_SOURCE_CHECK_EVENTS)   /* |G_IO_ERR|G_IO_HUP|G_IO_NVAL */
-#define SERVER_INADDR 0x7F000001
-#undef  SERVER_INADDR
 #define SERVER_INADDR 0x511F02EA       /* paulina.vellum.cz = 81.31.2.234; host order */
+#undef  SERVER_INADDR
+#define SERVER_INADDR 0x7F000001
 #define SERVER_PORT   9201     /* host order */
 #define PROBE_INADDR  SERVER_INADDR    /* host order */
 #define PROBE_PORT    8201     /* host order */
@@ -131,6 +132,8 @@ static void client_timeout_remove(struct client *client)
        if (client->timeout_id) {
 gboolean errgboolean;
 
+               if (optarg_verbose)
+                       g_message(_("Client fd %d removed timeout id %d"),client->gpollfd.fd,client->timeout_id);
                errgboolean=g_source_remove(client->timeout_id);
                g_assert(errgboolean==TRUE);
                client->timeout_id=0;
@@ -149,6 +152,8 @@ static void client_touch(struct client *client)
                        (client==probe ? PROBE_TIMEOUT_SEC*1000 : CLIENT_TIMEOUT_SEC*1000),     /* interval; msec */
                        (GSourceFunc)client_touch_timeout,      /* function */
                        client);        /* data */
+       if (optarg_verbose)
+               g_message(_("Client fd %d new timeout id %d"),client->gpollfd.fd,client->timeout_id);
        g_assert(client->timeout_id!=0);
 }
 
@@ -159,13 +164,26 @@ static gboolean client_touch_timeout(struct client *client)
        g_return_val_if_fail(client!=NULL,FALSE);       /* FALSE=>should be removed */
        g_return_val_if_fail(client!=master,FALSE);     /* FALSE=>should be removed */
 
+       if (optarg_verbose)
+               g_message(_("Client fd %d timeout id %d occured/entered"),client->gpollfd.fd,client->timeout_id);
+
+       /* Do not destroy the timeout in client_destroy().
+        * It would crash GLib - we remove it be returning FALSE from here.
+        */
+       g_assert(client->timeout_id!=0);
+       client->timeout_id=0;
+
        if (client==probe) {
                network_stop();
-               if (network_notify_hostip)
-                       (*network_notify_hostip)(0);
+               /* Never destroy 'client' now - it has been destroyed by network_stop()! */
+               g_warning(_("No probe response from the server, stopping the daemon. Please check your public Internet connectivity."));
+               }
+       else {
+               client_destroy(client);
                }
 
-       client_destroy(client);
+       if (optarg_verbose)
+               g_message(_("Client timeout occurance finish"));
 
        return FALSE;   /* GSource should be removed */
 }
@@ -392,7 +410,7 @@ static void sock_gsource_destroy(void)
                sock_gsource=NULL;
                }
 
-       write_daemon_running((pid_t)-1);        /* unlink */
+       write_daemon_running((pid_t)-1);        /* unlink; errors ignored */
 }
 
 static gboolean sock_gsource_new(void)
@@ -451,6 +469,9 @@ int sock;
        sock_client_list=g_list_prepend(sock_client_list,client);
        g_source_add_poll(sock_gsource,&client->gpollfd);
 
+       if (optarg_verbose)
+               g_message(_("Client fd %d created"),client->gpollfd.fd);
+
        return client;
 }
 
@@ -461,6 +482,9 @@ static void client_destroy(struct client *client)
        if (!sock_gsource_new())
                return;
 
+       if (optarg_verbose)
+               g_message(_("Client fd %d timeout id %d destroy enter"),client->gpollfd.fd,client->timeout_id);
+
        if (client==master) {
                master=NULL;
                g_assert(client->timeout_id==0);
@@ -474,6 +498,10 @@ static void client_destroy(struct client *client)
        g_source_remove_poll(sock_gsource,&client->gpollfd);
        sock_client_list=g_list_remove(sock_client_list,client);
        close(client->gpollfd.fd);      /* errors ignored */
+
+       if (optarg_verbose)
+               g_message(_("Client fd %d timeout id %d destroy finish"),client->gpollfd.fd,client->timeout_id);
+
        g_free(client);
 }
 
@@ -547,7 +575,29 @@ err_sock_gsource_destroy:
        probe_send(probe,port);
        client_touch(probe);    /* timeout */
 
-       write_daemon_running(getpid());
+       write_daemon_running(getpid()); /* errors ignored */
+       if (network_notify_hostip)
+               (*network_notify_hostip)(0);
+       return TRUE;
+}
+
+gboolean optarg_port_set_string(const gchar *port_string)
+{
+char *endp;
+long port_long;
+
+       g_return_val_if_fail(port_string!=NULL,FALSE);
+
+       port_long=strtol(port_string,&endp,0);
+       if (endp && *endp) {
+               g_warning(_("Invalid port specification, offending string: %s"),endp);
+               return FALSE;
+               }
+       if (port_long<1 || port_long>=G_MAXINT || (endp && *endp)) {
+               g_warning(_("Invalid port integer number specification (%ld)"),port_long);
+               return FALSE;
+               }
+       optarg_port=port_long;
        return TRUE;
 }
 
@@ -562,7 +612,7 @@ int errno_save;
                }
        if (daemon_pid==getpid()) {
                sock_gsource_destroy();
-               return TRUE;
+               goto ok;
                }
        errno=0;
        kill(daemon_pid,SIGKILL);
@@ -572,5 +622,50 @@ int errno_save;
                                (int)daemon_pid,strerror(errno_save)));
                return FALSE;
                }
+ok:
+       if (network_notify_hostip)
+               (*network_notify_hostip)(0);
        return TRUE;
 }
+
+static GMainLoop *gmainloop;
+static void network_detach_network_notify_hostip(guint32 hostip_guint32)
+{
+       if (!hostip_guint32)
+               g_main_loop_quit(gmainloop);
+}
+
+gboolean network_detach(void)
+{
+pid_t daemon_pid,forked_pid;
+
+       if ((pid_t)-1==(daemon_pid=is_daemon_running()))
+               return TRUE;
+       if (getpid()!=daemon_pid)
+               return TRUE;
+       if (!optarg_no_fork) {
+               if ((pid_t)-1==(forked_pid=fork())) {
+                       g_warning("fork(2): %m");
+                       return FALSE;
+                       }
+               if (forked_pid) {
+                       /* parent */
+                       return TRUE;
+                       }
+               write_daemon_running(getpid()); /* errors ignored */
+               optarg_verbose=0;
+               close(STDIN_FILENO);
+               close(STDOUT_FILENO);
+               close(STDERR_FILENO);
+               setpgrp();
+               setsid();
+               }
+
+       network_notify_hostip=network_detach_network_notify_hostip;
+       gmainloop=g_main_loop_new(
+                       NULL,   /* context */
+                       TRUE);  /* is_running; ignored */
+       g_main_loop_run(gmainloop);     /* loop */
+       /* Unable to contact the server, aborting. */
+       return FALSE;
+}