X-Git-Url: http://git.jankratochvil.net/?a=blobdiff_plain;f=src%2Fnetwork.c;h=07a3061ab6e793a437acdac29c62a5e5b2b44ccd;hb=806d202b9f9bc9ba3276bc764eee6f42e4e7f472;hp=3e2255743dd45eb49da4796be343603625dddc62;hpb=26bc2e65503ce21a8bd140d012d077d679f73996;p=udpgate.git diff --git a/src/network.c b/src/network.c index 3e22557..07a3061 100644 --- a/src/network.c +++ b/src/network.c @@ -35,29 +35,44 @@ #include #include #include +#include #include "network.h" #include "packet.h" #include "main.h" /* for optarg_verbose */ +#include "pathname.h" /* 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 */ +#define SERVER_INADDR 0xC37AD054 /* mms2.org = 195.122.208.84; host order */ #define SERVER_PORT 9201 /* host order */ #define PROBE_INADDR SERVER_INADDR /* host order */ #define PROBE_PORT 8201 /* host order */ #define CLIENT_TIMEOUT_SEC (5*60) -#define PROBE_TIMEOUT_SEC (5) +#define PROBE_TIMEOUT_SEC_BASE 5 +#define PROBE_TIMEOUT_SEC_MAX 3500 void (*network_notify_hostip)(guint32 hostip_guint32); +static G_CONST_RETURN gchar *pid_pathname(void) +{ +static const gchar *static_pathname; +static const char *user_val; + + if (!static_pathname) + user_val=g_get_user_name(); + return pathname_find(&static_pathname, + G_STRINGIFY(LOCALSTATEDIR) "/run",PACKAGE ".pid", + (!user_val ? NULL : g_get_tmp_dir()), + (!user_val ? NULL : udpgate_printf_alloca(".%s-%s.pid",user_val,PACKAGE)), + NULL); +} + + struct client { GPollFD gpollfd; struct sockaddr_in sockaddr_in_from; @@ -70,6 +85,9 @@ static GList *sock_client_list; /* of 'struct client *', incl. 'master' and 'pro static struct client *master; /* no 'timeout' permitted */ static struct client *probe; /* 'timeout' permitted */ static guint32 probe_unique; +static guint probe_timeout_sec_now; +guint probe_timeout_sec_max=G_MAXUINT; +static gint port_local; /* for 'probe' resends */ static gboolean write_daemon_running(pid_t pid); @@ -82,7 +100,7 @@ int pid_int; if (sock_gsource) return getpid(); - if (!(f=fopen(NETWORK_PATHNAME_PID,"r"))) + if (!(f=fopen(pid_pathname(),"r"))) goto err; got=fgets(buf,sizeof(buf),f); fclose(f); /* FIXME: error ignored */ @@ -108,15 +126,20 @@ static gboolean write_daemon_running(pid_t pid) FILE *f; if (pid==(pid_t)-1) { - if (unlink(NETWORK_PATHNAME_PID)) { + if (unlink(pid_pathname())) { if (errno!=ENOENT) - g_warning(_("Error removing PID file \"%s\": %m"),NETWORK_PATHNAME_PID); + g_warning(_("Error removing PID file \"%s\": %m"),pid_pathname()); return FALSE; } return TRUE; } - if (!(f=fopen(NETWORK_PATHNAME_PID,"w"))) { - g_warning(_("Error writing PID %d to \"%s\": %m"),(int)pid,NETWORK_PATHNAME_PID); + if (!(f=fopen(pid_pathname(),"w"))) { +static gboolean once=TRUE; + + if (once) { + once=FALSE; + g_warning(_("Error writing PID %d to \"%s\": %m"),(int)pid,pid_pathname()); + } return FALSE; } fprintf(f,"%d\n",(int)pid); /* errors ignored */ @@ -142,14 +165,15 @@ gboolean errgboolean; static gboolean client_touch_timeout(struct client *client); -static void client_touch(struct client *client) +static void client_touch(struct client *client,guint timeout_sec) { g_return_if_fail(client!=NULL); g_return_if_fail(client!=master); + g_return_if_fail(timeout_sec>0); client_timeout_remove(client); client->timeout_id=g_timeout_add( - (client==probe ? PROBE_TIMEOUT_SEC*1000 : CLIENT_TIMEOUT_SEC*1000), /* interval; msec */ + timeout_sec*1000, /* interval; msec */ (GSourceFunc)client_touch_timeout, /* function */ client); /* data */ if (optarg_verbose) @@ -158,6 +182,7 @@ static void client_touch(struct client *client) } static void client_destroy(struct client *client); +static gboolean probe_send(struct client *probe,gint port_local); static gboolean client_touch_timeout(struct client *client) { @@ -174,6 +199,17 @@ static gboolean client_touch_timeout(struct client *client) client->timeout_id=0; if (client==probe) { + if (probe_timeout_sec_nownext) { @@ -276,7 +319,7 @@ GList *clientl; client=client_new(); client->sockaddr_in_from=sockaddr_in_from; } - client_touch(client); + client_touch(client,CLIENT_TIMEOUT_SEC); UDPGATE_MEMZERO(&sockaddr_in_server); sockaddr_in_server.sin_family=AF_INET; sockaddr_in_server.sin_port=htons(SERVER_PORT); @@ -340,7 +383,7 @@ socklen_t sockaddr_in_from_length; break; if (sockaddr_in_from_length!=sizeof(sockaddr_in_from)) /* FIXME: errors reporting */ continue; - client_touch(client); + client_touch(client,CLIENT_TIMEOUT_SEC); /* FIXME: errors checking */ sendto( master->gpollfd.fd, /* s */ @@ -411,6 +454,7 @@ static void sock_gsource_destroy(void) client_destroy(sock_client_list->data); g_assert(master==NULL); + g_assert(probe==NULL); if (sock_gsource) { g_source_destroy(sock_gsource); @@ -552,19 +596,26 @@ size_t packet_length; static gboolean master_start(gint port) { struct sockaddr_in sockaddr_in; +uint16_t port_use; g_return_val_if_fail(port>=0,FALSE); g_return_val_if_fail(master==NULL,FALSE); + port_use=port; + if (port < 0 || port_use != port) { + g_warning(_("Port value %d is not valid for IPv4!"),(int)port); + return FALSE; + } + /* Setup 'master': */ if (!(master=client_new())) return FALSE; UDPGATE_MEMZERO(&sockaddr_in); sockaddr_in.sin_family=AF_INET; - sockaddr_in.sin_port=htons(port); + sockaddr_in.sin_port=htons(port_use); sockaddr_in.sin_addr.s_addr=htonl(INADDR_ANY); if (bind(master->gpollfd.fd,(struct sockaddr *)&sockaddr_in,sizeof(sockaddr_in))) { - g_warning("bind(sock,{AF_INET,INADDR_ANY:%d}): %m",(int)port); + g_warning("bind(sock,{AF_INET,INADDR_ANY:%u}): %m",(unsigned)port_use); return FALSE; } return TRUE; @@ -578,8 +629,13 @@ static gboolean probe_start(gint port) /* Setup 'probe': */ if (!(probe=client_new())) return FALSE; - probe_send(probe,port); - client_touch(probe); /* timeout */ + port_local=port; + if (!probe_send(probe,port)) { + client_destroy(probe); + return FALSE; + } + probe_timeout_sec_now=PROBE_TIMEOUT_SEC_BASE; + client_touch(probe,probe_timeout_sec_now); /* timeout */ return TRUE; }