X-Git-Url: http://git.jankratochvil.net/?a=blobdiff_plain;f=src%2Fnetwork.c;h=00592eb5497d810918ba0b56c5e310c9c1025db4;hb=a17d9bed38a3774b6aa56992426da0dee434340c;hp=74208be8f0d4f3e9ded2e187894d429d6208b992;hpb=8d4823fa8a4db82fff3aad2c8507872ed2b0d907;p=udpgate.git diff --git a/src/network.c b/src/network.c index 74208be..00592eb 100644 --- a/src/network.c +++ b/src/network.c @@ -38,6 +38,7 @@ #include "network.h" #include "packet.h" +#include "main.h" /* for optarg_verbose */ /* Config: */ @@ -54,7 +55,7 @@ #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 { @@ -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,17 +164,69 @@ 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,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) @@ -195,6 +252,12 @@ GList *clientl; 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; @@ -243,38 +306,10 @@ socklen_t sockaddr_in_from_length; 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,HOSTIP_GUINT32_TO_STRING(hostip_guint32)); + /* Probe socket should have no response; maybe some ICMP errors - ignored. */ } } @@ -433,6 +468,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; } @@ -443,6 +481,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); @@ -456,6 +497,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); } @@ -515,7 +560,7 @@ struct sockaddr_in sockaddr_in; 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: @@ -530,6 +575,8 @@ err_sock_gsource_destroy: client_touch(probe); /* timeout */ write_daemon_running(getpid()); + if (network_notify_hostip) + (*network_notify_hostip)(0); return TRUE; } @@ -544,7 +591,7 @@ int errno_save; } if (daemon_pid==getpid()) { sock_gsource_destroy(); - return TRUE; + goto ok; } errno=0; kill(daemon_pid,SIGKILL); @@ -554,5 +601,8 @@ int errno_save; (int)daemon_pid,strerror(errno_save))); return FALSE; } +ok: + if (network_notify_hostip) + (*network_notify_hostip)(0); return TRUE; }