X-Git-Url: http://git.jankratochvil.net/?a=blobdiff_plain;f=src%2Fnetwork.c;h=4e702453ca329d9ba4d7739a211f795aceb8b6b1;hb=3434c87d156593144eca1ef4c9fabf8947bd15eb;hp=2e755fed29c7d0de0cafa58aa80195532276db74;hpb=398fc84beb6a68762bf1a77f6344e551eb79aacd;p=udpgate.git diff --git a/src/network.c b/src/network.c index 2e755fe..4e70245 100644 --- a/src/network.c +++ b/src/network.c @@ -45,14 +45,13 @@ #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); @@ -70,6 +69,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); @@ -142,14 +144,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 +161,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 +178,17 @@ static gboolean client_touch_timeout(struct client *client) client->timeout_id=0; if (client==probe) { + if (probe_timeout_sec_nowgpollfd.fd, /* s */ - packet, /* buf */ - sizeof(packet), /* len */ - 0, /* flags */ - (struct sockaddr *)&sockaddr_in_from, /* from */ - &sockaddr_in_from_length))) { /* fromlen */ GList *clientl; + sockaddr_in_from_length=sizeof(sockaddr_in_from); + if (-1==(gotlen=recvfrom( + master->gpollfd.fd, /* s */ + packet, /* buf */ + sizeof(packet), /* len */ + 0, /* flags */ + (struct sockaddr *)&sockaddr_in_from, /* from */ + &sockaddr_in_from_length))) /* fromlen */ + break; + if (sockaddr_in_from_length!=sizeof(sockaddr_in_from)) /* FIXME: errors reporting */ continue; @@ -258,6 +275,13 @@ GList *clientl; handle_master_probe(packet,gotlen,&sockaddr_in_from); continue; } + /* Not yet initialized by 'probe' reply - drop it. */ + if (probe) { + if (optarg_verbose) + g_message(_("Data packet received from %s but no probe reply yet; dropping packet."), + SOCKADDR_IN_TO_STRING(&sockaddr_in_from)); + continue; + } /* FIXME: Performance: Ugly search... */ for (clientl=sock_client_list;clientl;clientl=clientl->next) { @@ -274,7 +298,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); @@ -292,21 +316,23 @@ GList *clientl; static void handle_probe(struct client *probe) { + g_return_if_fail(probe!=NULL); + + for (;;) { ssize_t gotlen; struct sockaddr_in sockaddr_in_from; char packet[0x10000]; socklen_t sockaddr_in_from_length; - g_return_if_fail(probe!=NULL); - - sockaddr_in_from_length=sizeof(sockaddr_in_from); - while (-1!=(gotlen=recvfrom( - master->gpollfd.fd, /* s */ - packet, /* buf */ - sizeof(packet), /* len */ - 0, /* flags */ - (struct sockaddr *)&sockaddr_in_from, /* from */ - &sockaddr_in_from_length))) { /* fromlen */ + sockaddr_in_from_length=sizeof(sockaddr_in_from); + if (-1==(gotlen=recvfrom( + master->gpollfd.fd, /* s */ + packet, /* buf */ + sizeof(packet), /* len */ + 0, /* flags */ + (struct sockaddr *)&sockaddr_in_from, /* from */ + &sockaddr_in_from_length))) /* fromlen */ + break; if (sockaddr_in_from_length!=sizeof(sockaddr_in_from)) /* FIXME: errors reporting */ continue; @@ -316,24 +342,27 @@ socklen_t sockaddr_in_from_length; static void handle_client(struct client *client) { + g_return_if_fail(client!=NULL); + g_return_if_fail(master!=NULL); + + for (;;) { ssize_t gotlen; struct sockaddr_in sockaddr_in_from; char packet [0x10000]; socklen_t sockaddr_in_from_length; - g_return_if_fail(client!=NULL); - g_return_if_fail(master!=NULL); - - while (-1!=(gotlen=recvfrom( - client->gpollfd.fd, /* s */ - packet, /* buf */ - sizeof(packet), /* len */ - 0, /* flags */ - (struct sockaddr *)&sockaddr_in_from, /* from */ - &sockaddr_in_from_length))) { /* fromlen */ + sockaddr_in_from_length=sizeof(sockaddr_in_from); + if (-1==(gotlen=recvfrom( + client->gpollfd.fd, /* s */ + packet, /* buf */ + sizeof(packet), /* len */ + 0, /* flags */ + (struct sockaddr *)&sockaddr_in_from, /* from */ + &sockaddr_in_from_length))) /* fromlen */ + 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 */ @@ -404,6 +433,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); @@ -451,8 +481,8 @@ int sock; if (!sock_gsource_new()) return FALSE; - if (-1==(sock=socket(AF_INET,SOCK_DGRAM,0))) { - g_warning("socket(AF_INET,SOCK_DGRAM): %m"); + if (-1==(sock=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP))) { + g_warning("socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP): %m"); return NULL; } if (ioctl(sock,FIONBIO,&oneul)) { /* non-blocking mode */ @@ -542,20 +572,14 @@ size_t packet_length; return TRUE; } -gboolean network_start(gint port) +static gboolean master_start(gint port) { -pid_t daemon_pid; struct sockaddr_in sockaddr_in; g_return_val_if_fail(port>=0,FALSE); - - if ((pid_t)-1!=(daemon_pid=is_daemon_running())) { - g_warning(_("Cannot start network daemon: Daemon is already running on PID %d"),(int)daemon_pid); - return FALSE; - } + g_return_val_if_fail(master==NULL,FALSE); /* Setup 'master': */ - g_assert(master==NULL); if (!(master=client_new())) return FALSE; UDPGATE_MEMZERO(&sockaddr_in); @@ -564,17 +588,47 @@ struct sockaddr_in sockaddr_in; 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); -err_sock_gsource_destroy: - sock_gsource_destroy(); return FALSE; } + return TRUE; +} + +static gboolean probe_start(gint port) +{ + g_return_val_if_fail(port>=0,FALSE); + g_return_val_if_fail(probe==NULL,FALSE); /* Setup 'probe': */ if (!(probe=client_new())) - goto err_sock_gsource_destroy; - probe_send(probe,port); - client_touch(probe); /* timeout */ + return FALSE; + 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; +} +gboolean network_start(gint port) +{ +pid_t daemon_pid; + + g_return_val_if_fail(port>=0,FALSE); + + if ((pid_t)-1!=(daemon_pid=is_daemon_running())) { + g_warning(_("Cannot start network daemon: Daemon is already running on PID %d"),(int)daemon_pid); + return FALSE; + } + if (!master_start(port)) { + sock_gsource_destroy(); + return FALSE; + } + if (!probe_start(port)) { + sock_gsource_destroy(); + return FALSE; + } write_daemon_running(getpid()); /* errors ignored */ if (network_notify_hostip) (*network_notify_hostip)(0); @@ -617,6 +671,7 @@ int errno_save; errno=0; kill(daemon_pid,SIGKILL); errno_save=errno; + write_daemon_running((pid_t)-1); /* unlink; errors ignored */ if (errno_save) { g_warning(udpgate_printf_alloca(_("Unable to stop the daemon at PID %d: %s"), (int)daemon_pid,strerror(errno_save)));