---
 gdhcp/client.c |  123 ++++++++++++++++++++++++++++++++++++++++++--------------
 gdhcp/gdhcp.h  |    3 ++
 2 files changed, 95 insertions(+), 31 deletions(-)

diff --git a/gdhcp/client.c b/gdhcp/client.c
index e6106d1..ddcbeb3 100644
--- a/gdhcp/client.c
+++ b/gdhcp/client.c
@@ -118,6 +118,8 @@ struct _GDHCPClient {
        gpointer ipv4ll_lost_data;
        GDHCPClientEventFunc address_conflict_cb;
        gpointer address_conflict_data;
+       GDHCPClientEventFunc changed_cb;
+       gpointer changed_data;
        GDHCPDebugFunc debug_func;
        gpointer debug_data;
        GDHCPClientEventFunc information_req_cb;
@@ -170,6 +172,19 @@ static inline void debug(GDHCPClient *client, const char 
*format, ...)
        va_end(ap);
 }
 
+static void set_state(GDHCPClient *dhcp_client, ClientState state)
+{
+    if (state != dhcp_client->state)
+    {
+        dhcp_client->state = state;
+        debug(dhcp_client, "setting state");
+
+        if (dhcp_client->changed_cb!= NULL)
+            dhcp_client->changed_cb(dhcp_client,
+                    dhcp_client->changed_data);
+    }
+}
+
 /* Initialize the packet with the proper defaults */
 static void init_packet(GDHCPClient *dhcp_client, gpointer pkt, char type)
 {
@@ -537,7 +552,7 @@ static gboolean send_probe_packet(gpointer dhcp_data)
        debug(dhcp_client, "sending IPV4LL probe request");
 
        if (dhcp_client->retry_times == 1) {
-               dhcp_client->state = IPV4LL_PROBE;
+               set_state(dhcp_client,IPV4LL_PROBE);
                switch_listening_mode(dhcp_client, L_ARP);
        }
        ipv4ll_send_arp_packet(dhcp_client->mac_address, 0,
@@ -1388,7 +1403,7 @@ static void ipv4ll_stop(GDHCPClient *dhcp_client)
                dhcp_client->listener_watch = 0;
        }
 
-       dhcp_client->state = IPV4LL_PROBE;
+       set_state(dhcp_client,IPV4LL_PROBE);
        dhcp_client->retry_times = 0;
        dhcp_client->requested_ip = 0;
 
@@ -1430,7 +1445,7 @@ static int ipv4ll_recv_arp_packet(GDHCPClient 
*dhcp_client)
        if (dhcp_client->state == IPV4LL_MONITOR) {
                if (!source_conflict)
                        return 0;
-               dhcp_client->state = IPV4LL_DEFEND;
+               set_state(dhcp_client,IPV4LL_DEFEND);
                debug(dhcp_client, "DEFEND mode conflicts : %d",
                        dhcp_client->conflicts);
                /*Try to defend with a single announce*/
@@ -1597,7 +1612,7 @@ static void start_request(GDHCPClient *dhcp_client)
        }
 
        if (dhcp_client->retry_times == 0) {
-               dhcp_client->state = REQUESTING;
+               set_state(dhcp_client,REQUESTING);
                switch_listening_mode(dhcp_client, L2);
        }
 
@@ -1639,7 +1654,7 @@ static void restart_dhcp(GDHCPClient *dhcp_client, int 
retry_times)
 
        dhcp_client->retry_times = retry_times;
        dhcp_client->requested_ip = 0;
-       dhcp_client->state = INIT_SELECTING;
+       set_state(dhcp_client,INIT_SELECTING);
        switch_listening_mode(dhcp_client, L2);
 
        g_dhcp_client_start(dhcp_client, dhcp_client->last_address);
@@ -1682,7 +1697,7 @@ static void start_rebound(GDHCPClient *dhcp_client)
 {
        debug(dhcp_client, "start rebound");
 
-       dhcp_client->state = REBINDING;
+       set_state(dhcp_client,REBINDING);
 
        dhcp_client->timeout = g_timeout_add_seconds_full(G_PRIORITY_HIGH,
                                                dhcp_client->lease_seconds >> 1,
@@ -1710,7 +1725,7 @@ static gboolean start_renew_timeout(gpointer user_data)
 
        debug(dhcp_client, "start renew timeout");
 
-       dhcp_client->state = RENEWING;
+       set_state(dhcp_client,RENEWING);
 
        dhcp_client->lease_seconds >>= 1;
 
@@ -1738,7 +1753,8 @@ static void start_bound(GDHCPClient *dhcp_client)
 {
        debug(dhcp_client, "start bound");
 
-       dhcp_client->state = BOUND;
+       set_state(dhcp_client,BOUND);
+
 
        if (dhcp_client->timeout > 0)
                g_source_remove(dhcp_client->timeout);
@@ -2324,7 +2340,7 @@ static gboolean listener_event(GIOChannel *channel, 
GIOCondition condition,
                dhcp_client->server_ip = get_be32(option);
                dhcp_client->requested_ip = ntohl(packet.yiaddr);
 
-               dhcp_client->state = REQUESTING;
+               set_state(dhcp_client,REQUESTING);
 
                start_request(dhcp_client);
 
@@ -2341,6 +2357,8 @@ static gboolean listener_event(GIOChannel *channel, 
GIOCondition condition,
 
                        dhcp_client->lease_seconds = get_lease(&packet);
 
+                       dhcp_client->expire = time(NULL) + 
dhcp_client->lease_seconds;
+
                        get_request(dhcp_client, &packet);
 
                        switch_listening_mode(dhcp_client, L_NONE);
@@ -2571,7 +2589,7 @@ static gboolean ipv4ll_defend_timeout(gpointer dhcp_data)
        debug(dhcp_client, "back to MONITOR mode");
 
        dhcp_client->conflicts = 0;
-       dhcp_client->state = IPV4LL_MONITOR;
+       set_state(dhcp_client,IPV4LL_MONITOR);
 
        return FALSE;
 }
@@ -2592,7 +2610,7 @@ static gboolean ipv4ll_announce_timeout(gpointer 
dhcp_data)
 
        ip = htonl(dhcp_client->requested_ip);
        debug(dhcp_client, "switching to monitor mode");
-       dhcp_client->state = IPV4LL_MONITOR;
+       set_state(dhcp_client,IPV4LL_MONITOR);
        dhcp_client->assigned_ip = get_ip(ip);
 
        if (dhcp_client->ipv4ll_available_cb)
@@ -2612,7 +2630,7 @@ static gboolean ipv4ll_probe_timeout(gpointer dhcp_data)
               dhcp_client->retry_times);
 
        if (dhcp_client->retry_times == PROBE_NUM) {
-               dhcp_client->state = IPV4LL_ANNOUNCE;
+               set_state(dhcp_client,IPV4LL_ANNOUNCE);
                dhcp_client->retry_times = 0;
 
                dhcp_client->retry_times++;
@@ -2632,80 +2650,80 @@ int g_dhcp_client_start(GDHCPClient *dhcp_client, const 
char *last_address)
 
        if (dhcp_client->type == G_DHCP_IPV6) {
                if (dhcp_client->information_req_cb) {
-                       dhcp_client->state = INFORMATION_REQ;
+                       set_state(dhcp_client, INFORMATION_REQ);
                        re = switch_listening_mode(dhcp_client, L3);
                        if (re != 0) {
                                switch_listening_mode(dhcp_client, L_NONE);
-                               dhcp_client->state = 0;
+                               set_state(dhcp_client, 0);
                                return re;
                        }
                        send_information_req(dhcp_client);
 
                } else if (dhcp_client->solicitation_cb) {
-                       dhcp_client->state = SOLICITATION;
+                       set_state(dhcp_client, SOLICITATION);
                        re = switch_listening_mode(dhcp_client, L3);
                        if (re != 0) {
                                switch_listening_mode(dhcp_client, L_NONE);
-                               dhcp_client->state = 0;
+                               set_state(dhcp_client, 0);
                                return re;
                        }
                        send_solicitation(dhcp_client);
 
                } else if (dhcp_client->request_cb) {
-                       dhcp_client->state = REQUEST;
+                       set_state(dhcp_client, REQUEST);
                        re = switch_listening_mode(dhcp_client, L3);
                        if (re != 0) {
                                switch_listening_mode(dhcp_client, L_NONE);
-                               dhcp_client->state = 0;
+                               set_state(dhcp_client, 0);
                                return re;
                        }
                        send_dhcpv6_request(dhcp_client);
 
                } else if (dhcp_client->confirm_cb) {
-                       dhcp_client->state = CONFIRM;
+                       set_state(dhcp_client, CONFIRM);
                        re = switch_listening_mode(dhcp_client, L3);
                        if (re != 0) {
                                switch_listening_mode(dhcp_client, L_NONE);
-                               dhcp_client->state = 0;
+                               set_state(dhcp_client, 0);
                                return re;
                        }
                        send_dhcpv6_confirm(dhcp_client);
 
                } else if (dhcp_client->renew_cb) {
-                       dhcp_client->state = RENEW;
+                       set_state(dhcp_client, RENEW);
                        re = switch_listening_mode(dhcp_client, L3);
                        if (re != 0) {
                                switch_listening_mode(dhcp_client, L_NONE);
-                               dhcp_client->state = 0;
+                               set_state(dhcp_client, 0);
                                return re;
                        }
                        send_dhcpv6_renew(dhcp_client);
 
                } else if (dhcp_client->rebind_cb) {
-                       dhcp_client->state = REBIND;
+                       set_state(dhcp_client, REBIND);
                        re = switch_listening_mode(dhcp_client, L3);
                        if (re != 0) {
                                switch_listening_mode(dhcp_client, L_NONE);
-                               dhcp_client->state = 0;
+                               set_state(dhcp_client, 0);
                                return re;
                        }
                        send_dhcpv6_rebind(dhcp_client);
 
                } else if (dhcp_client->release_cb) {
-                       dhcp_client->state = RENEW;
+                       set_state(dhcp_client, RENEW);
                        re = switch_listening_mode(dhcp_client, L3);
                        if (re != 0) {
                                switch_listening_mode(dhcp_client, L_NONE);
-                               dhcp_client->state = 0;
+                               set_state(dhcp_client, 0);
                                return re;
                        }
                        send_dhcpv6_release(dhcp_client);
                } else if (dhcp_client->decline_cb) {
-                       dhcp_client->state = DECLINE;
+                       set_state(dhcp_client, DECLINE);
                        re = switch_listening_mode(dhcp_client, L3);
                        if (re != 0) {
                                switch_listening_mode(dhcp_client, L_NONE);
-                               dhcp_client->state = 0;
+                               set_state(dhcp_client, 0);
                                return re;
                        }
                        send_dhcpv6_decline(dhcp_client);
@@ -2715,7 +2733,7 @@ int g_dhcp_client_start(GDHCPClient *dhcp_client, const 
char *last_address)
        }
 
        if (dhcp_client->type == G_DHCP_IPV4LL) {
-               dhcp_client->state = INIT_SELECTING;
+               set_state(dhcp_client, INIT_SELECTING);
                ipv4ll_start(dhcp_client);
                return 0;
        }
@@ -2732,7 +2750,7 @@ int g_dhcp_client_start(GDHCPClient *dhcp_client, const 
char *last_address)
                g_free(dhcp_client->assigned_ip);
                dhcp_client->assigned_ip = NULL;
 
-               dhcp_client->state = INIT_SELECTING;
+               set_state(dhcp_client,INIT_SELECTING);
                re = switch_listening_mode(dhcp_client, L2);
                if (re != 0)
                        return re;
@@ -2788,7 +2806,7 @@ void g_dhcp_client_stop(GDHCPClient *dhcp_client)
        dhcp_client->ack_retry_times = 0;
 
        dhcp_client->requested_ip = 0;
-       dhcp_client->state = RELEASED;
+       set_state(dhcp_client,RELEASED);
        dhcp_client->lease_seconds = 0;
 }
 
@@ -2833,6 +2851,10 @@ void g_dhcp_client_register_event(GDHCPClient 
*dhcp_client,
                dhcp_client->address_conflict_cb = func;
                dhcp_client->address_conflict_data = data;
                return;
+       case G_DHCP_CLIENT_EVENT_CHANGED:
+               dhcp_client->changed_cb = func;
+               dhcp_client->changed_data = data;
+               return;
        case G_DHCP_CLIENT_EVENT_INFORMATION_REQ:
                if (dhcp_client->type != G_DHCP_IPV6)
                        return;
@@ -2935,6 +2957,45 @@ char *g_dhcp_client_get_netmask(GDHCPClient *dhcp_client)
        return NULL;
 }
 
+const char* g_dhcp_client_get_state(GDHCPClient *dhcp_client)
+{
+       switch (dhcp_client->state) {
+               case INIT_SELECTING:
+                       return "INIT_SELECTING";
+               case REQUESTING:
+                       return "REQUESTING";
+               case BOUND:
+                       return "BOUND";
+               case RENEWING:
+                       return "RENEWING";
+               case REBINDING:
+                       return "REBINDING";
+               case RELEASED:
+                       return "RELEASED";
+               case IPV4LL_PROBE:
+                       return "IPV4LL_PROBE";
+               case IPV4LL_ANNOUNCE:
+                       return "IPV4LL_ANNOUNCE";
+               case IPV4LL_MONITOR:
+                       return "IPV4LL_MONITOR";
+               case IPV4LL_DEFEND:
+                       return "IPV4LL_DEFEND";
+               case INFORMATION_REQ:
+                       return "INFORMATION_REQ";
+               case SOLICITATION:
+                       return "SOLICITATION";
+               case REQUEST:
+                       return "REQUEST";
+               case RENEW:
+                       return "RENEW";
+               case REBIND:
+                       return "REBIND";
+               case RELEASE:
+                       return "RELEASE";
+               default:
+                       return NULL;
+       }
+}
 GDHCPClientError g_dhcp_client_set_request(GDHCPClient *dhcp_client,
                                                unsigned int option_code)
 {
diff --git a/gdhcp/gdhcp.h b/gdhcp/gdhcp.h
index 0d79361..4a3e6d2 100644
--- a/gdhcp/gdhcp.h
+++ b/gdhcp/gdhcp.h
@@ -63,6 +63,7 @@ typedef enum {
        G_DHCP_CLIENT_EVENT_RELEASE,
        G_DHCP_CLIENT_EVENT_CONFIRM,
        G_DHCP_CLIENT_EVENT_DECLINE,
+       G_DHCP_CLIENT_EVENT_CHANGED,
 } GDHCPClientEvent;
 
 typedef enum {
@@ -156,6 +157,8 @@ GList *g_dhcp_client_get_option(GDHCPClient *client,
                                                unsigned char option_code);
 int g_dhcp_client_get_index(GDHCPClient *client);
 
+const char* g_dhcp_client_get_state(GDHCPClient *state);
+
 void g_dhcp_client_set_debug(GDHCPClient *client,
                                GDHCPDebugFunc func, gpointer user_data);
 int g_dhcpv6_create_duid(GDHCPDuidType duid_type, int index, int type,
-- 
1.7.9.5

_______________________________________________
connman mailing list
[email protected]
https://lists.connman.net/mailman/listinfo/connman

Reply via email to