#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 */
#define SERVER_PORT 9201 /* host order */
#define PROBE_INADDR SERVER_INADDR /* host order */
#define PROBE_TIMEOUT_SEC (5)
-void (*network_notify_hostip)(guint32 hostip_guint32,const gchar *hostip_string);
+void (*network_notify_hostip)(guint32 hostip_guint32);
struct 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;
(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);
}
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,NULL);
+ /* Never destroy 'client' now - it has been destroyed by network_stop()! */
+ }
+ else {
+ client_destroy(client);
}
- client_destroy(client);
+ if (optarg_verbose)
+ g_message(_("Client timeout occurance finish"));
return FALSE; /* GSource should be removed */
}
+static void handle_master_probe(const void *packet,size_t gotlen,const struct sockaddr_in *sockaddr_in_from)
+{
+GHashTable *got_hash;
+gpointer got_unique_gpointer;
+gpointer hostip_gpointer;
+guint32 hostip_guint32;
+
+ g_return_if_fail(packet!=NULL);
+ g_return_if_fail(sockaddr_in_from!=NULL);
+
+ if (!probe)
+ return;
+
+ if (!(got_hash=packet_disassembly(packet,gotlen)))
+ return;
+ if (!(g_hash_table_lookup_extended(
+ got_hash, /* hash_table */
+ GUINT_TO_POINTER(PACKET_ELEM_TYPE_DATA_GUINT32), /* lookup_key */
+ NULL, /* orig_key */
+ &got_unique_gpointer))) {
+err_packet_disassembly_destroy_got_hash:
+ packet_disassembly_destroy(got_hash);
+ return;
+ }
+ if (GPOINTER_TO_UINT(got_unique_gpointer)!=probe_unique)
+ goto err_packet_disassembly_destroy_got_hash;
+ if (!(g_hash_table_lookup_extended(
+ got_hash, /* hash_table */
+ GUINT_TO_POINTER(PACKET_ELEM_TYPE_CLIENT_INADDR), /* lookup_key */
+ NULL, /* orig_key */
+ &hostip_gpointer)))
+ goto err_packet_disassembly_destroy_got_hash;
+ hostip_guint32=GPOINTER_TO_UINT(hostip_gpointer);
+ packet_disassembly_destroy(got_hash);
+
+ client_destroy(probe);
+ if (network_notify_hostip)
+ (*network_notify_hostip)(hostip_guint32);
+}
+
static struct client *client_new(void);
static void handle_master(struct client *master)
if (sockaddr_in_from_length!=sizeof(sockaddr_in_from)) /* FIXME: errors reporting */
continue;
+
+ if (packet_recognized(packet,gotlen)) {
+ handle_master_probe(packet,gotlen,&sockaddr_in_from);
+ continue;
+ }
+
/* FIXME: Performance: Ugly search... */
for (clientl=sock_client_list;clientl;clientl=clientl->next) {
client=clientl->data;
0, /* flags */
(struct sockaddr *)&sockaddr_in_from, /* from */
&sockaddr_in_from_length))) { /* fromlen */
-static GHashTable *got_hash;
-static gpointer got_unique_gpointer;
-static gpointer hostip_gpointer;
-static guint32 hostip_guint32;
-
if (sockaddr_in_from_length!=sizeof(sockaddr_in_from)) /* FIXME: errors reporting */
continue;
- if (!(got_hash=packet_disassembly(packet,gotlen)))
- continue;
- if (!(g_hash_table_lookup_extended(
- got_hash, /* hash_table */
- GUINT_TO_POINTER(PACKET_ELEM_TYPE_DATA_GUINT32), /* lookup_key */
- NULL, /* orig_key */
- &got_unique_gpointer))) {
-err_packet_disassembly_destroy_got_hash:
- packet_disassembly_destroy(got_hash);
- continue;
- }
- if (GPOINTER_TO_UINT(got_unique_gpointer)!=probe_unique)
- goto err_packet_disassembly_destroy_got_hash;
- if (!(g_hash_table_lookup_extended(
- got_hash, /* hash_table */
- GUINT_TO_POINTER(PACKET_ELEM_TYPE_CLIENT_INADDR), /* lookup_key */
- NULL, /* orig_key */
- &hostip_gpointer)))
- goto err_packet_disassembly_destroy_got_hash;
- hostip_guint32=GPOINTER_TO_UINT(hostip_gpointer);
- packet_disassembly_destroy(got_hash);
- client_destroy(probe);
- if (network_notify_hostip)
- (*network_notify_hostip)(hostip_guint32,
- udpgate_printf_alloca("%d.%d.%d.%d",
- (hostip_guint32>>24U)&0xFFU,
- (hostip_guint32>>16U)&0xFFU,
- (hostip_guint32>> 8U)&0xFFU,
- (hostip_guint32>> 0U)&0xFFU));
+ /* Probe socket should have no response; maybe some ICMP errors - ignored. */
}
}
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;
}
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);
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);
}
UDPGATE_MEMZERO(&sockaddr_in);
sockaddr_in.sin_family=AF_INET;
sockaddr_in.sin_port=htons(port);
- sockaddr_in.sin_addr.s_addr=INADDR_ANY;
+ 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:
client_touch(probe); /* timeout */
write_daemon_running(getpid());
+ if (network_notify_hostip)
+ (*network_notify_hostip)(0);
return TRUE;
}
}
if (daemon_pid==getpid()) {
sock_gsource_destroy();
- return TRUE;
+ goto ok;
}
errno=0;
kill(daemon_pid,SIGKILL);
(int)daemon_pid,strerror(errno_save)));
return FALSE;
}
+ok:
+ if (network_notify_hostip)
+ (*network_notify_hostip)(0);
return TRUE;
}