---
gdhcp/client.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
gdhcp/gdhcp.h | 3 +++
src/dhcp.c | 20 +++++++++++++++++
3 files changed, 86 insertions(+), 4 deletions(-)
diff --git a/gdhcp/client.c b/gdhcp/client.c
index 7d103ce..c6d3fa4 100644
--- a/gdhcp/client.c
+++ b/gdhcp/client.c
@@ -138,6 +138,8 @@ struct _GDHCPClient {
gpointer confirm_data;
GDHCPClientEventFunc decline_cb;
gpointer decline_data;
+ GDHCPClientEventFunc wake_event_cb;
+ gpointer wake_event_data;
char *last_address;
unsigned char *duid;
int duid_len;
@@ -146,6 +148,8 @@ struct _GDHCPClient {
uint16_t status_code;
uint32_t iaid;
uint32_t T1, T2;
+ uint32_t next_event;
+ bool can_sleep;
struct in6_addr ia_na;
struct in6_addr ia_ta;
time_t last_request;
@@ -271,6 +275,31 @@ static int32_t get_time_diff(struct timeval *tv)
return hsec;
}
+static void set_wake(GDHCPClient *dhcp_client, uint32_t timeout)
+{
+ dhcp_client->next_event = timeout + time(NULL);
+ dhcp_client->can_sleep = false;
+ if (dhcp_client->wake_event_cb)
+ dhcp_client->wake_event_cb(dhcp_client,
+ dhcp_client->wake_event_data);
+}
+
+static void release_wake(GDHCPClient *dhcp_client, uint32_t timeout)
+{
+ dhcp_client->next_event = timeout + time(NULL);
+ dhcp_client->can_sleep = true;
+ if (dhcp_client->wake_event_cb)
+ dhcp_client->wake_event_cb(dhcp_client,
+ dhcp_client->wake_event_data);
+}
+
+bool g_dhcp_get_next_event(GDHCPClient *dhcp_client, time_t *next_event)
+{
+ *next_event = dhcp_client->next_event;
+
+ return dhcp_client->can_sleep;
+}
+
static void add_dhcpv6_request_options(GDHCPClient *dhcp_client,
struct dhcpv6_packet *packet,
unsigned char *buf, int max_buf,
@@ -585,6 +614,7 @@ static gboolean send_announce_packet(gpointer dhcp_data)
ipv4ll_defend_timeout,
dhcp_client,
NULL);
+ set_wake(dhcp_client, DEFEND_INTERVAL);
return TRUE;
} else
dhcp_client->timeout =
@@ -593,6 +623,7 @@ static gboolean send_announce_packet(gpointer dhcp_data)
ipv4ll_announce_timeout,
dhcp_client,
NULL);
+ set_wake(dhcp_client, ANNOUNCE_INTERVAL);
return TRUE;
}
@@ -1179,6 +1210,7 @@ GDHCPClient *g_dhcp_client_new(GDHCPType type,
dhcp_client->lease_lost_cb = NULL;
dhcp_client->ipv4ll_lost_cb = NULL;
dhcp_client->address_conflict_cb = NULL;
+ dhcp_client->wake_event_cb = NULL;
dhcp_client->listener_watch = 0;
dhcp_client->retry_times = 0;
dhcp_client->ack_retry_times = 0;
@@ -1657,6 +1689,10 @@ static gboolean start_rebound_timeout(gpointer user_data)
dhcp_client->expire >>= 1;
+ if (dhcp_client->timeout > 0){
+ g_source_remove(dhcp_client->timeout);
+ }
+
/* We need to have enough time to receive ACK package*/
if (dhcp_client->expire <= 60) {
@@ -1673,6 +1709,7 @@ static gboolean start_rebound_timeout(gpointer user_data)
start_rebound,
dhcp_client,
NULL);
+ release_wake(dhcp_client, dhcp_client->expire);
}
return false;
@@ -1696,7 +1733,7 @@ static gboolean start_rebound(gpointer user_data)
start_rebound_timeout,
dhcp_client,
NULL);
-
+ set_wake(dhcp_client, REQUEST_TIMEOUT);
return FALSE;
}
@@ -1708,6 +1745,10 @@ static gboolean start_renew_request_timeout(gpointer
user_data)
dhcp_client->T2>>=1;
+ if (dhcp_client->timeout > 0){
+ g_source_remove(dhcp_client->timeout);
+ }
+
if (dhcp_client->T2 <= 60)
{
debug(dhcp_client, "renew request timeout");
@@ -1724,6 +1765,7 @@ static gboolean start_renew_request_timeout(gpointer
user_data)
start_renew,
dhcp_client,
NULL);
+ release_wake(dhcp_client, dhcp_client->T2);
}
return false;
@@ -1739,8 +1781,10 @@ static gboolean start_renew(gpointer user_data)
switch_listening_mode(dhcp_client, L3);
- if (dhcp_client->timeout > 0)
+ if (dhcp_client->timeout > 0){
g_source_remove(dhcp_client->timeout);
+ dhcp_client->timeout = 0;
+ }
send_renew(dhcp_client);
@@ -1751,6 +1795,7 @@ static gboolean start_renew(gpointer user_data)
start_renew_request_timeout,
dhcp_client,
NULL);
+ set_wake(dhcp_client, REQUEST_TIMEOUT);
return FALSE;
}
@@ -1761,8 +1806,9 @@ static void start_bound(GDHCPClient *dhcp_client)
dhcp_client->state = BOUND;
- if (dhcp_client->timeout > 0)
+ if (dhcp_client->timeout > 0){
g_source_remove(dhcp_client->timeout);
+ }
/* TODO: T1 and T2 should be set through options instead of
* defaults as they are here, also note that the actual value
@@ -1777,6 +1823,7 @@ static void start_bound(GDHCPClient *dhcp_client)
dhcp_client->T1,
start_renew, dhcp_client,
NULL);
+ release_wake(dhcp_client, dhcp_client->T1);
}
static gboolean restart_dhcp_timeout(gpointer user_data)
@@ -2349,6 +2396,10 @@ static gboolean listener_event(GIOChannel *channel,
GIOCondition condition,
g_source_remove(dhcp_client->timeout);
dhcp_client->timeout = 0;
dhcp_client->retry_times = 0;
+ dhcp_client->T1 = 0;
+ dhcp_client->T2 = 0;
+ dhcp_client->expire = 0;
+ dhcp_client->next_event= 0;
option = dhcp_get_option(&packet, DHCP_SERVER_ID);
dhcp_client->server_ip = get_be32(option);
@@ -2365,8 +2416,9 @@ static gboolean listener_event(GIOChannel *channel,
GIOCondition condition,
if (*message_type == DHCPACK) {
dhcp_client->retry_times = 0;
- if (dhcp_client->timeout > 0)
+ if (dhcp_client->timeout > 0){
g_source_remove(dhcp_client->timeout);
+ }
dhcp_client->timeout = 0;
dhcp_client->lease_seconds = get_lease(&packet);
@@ -2395,6 +2447,7 @@ static gboolean listener_event(GIOChannel *channel,
GIOCondition condition,
restart_dhcp_timeout,
dhcp_client,
NULL);
+ set_wake(dhcp_client,3);
}
break;
@@ -2789,6 +2842,7 @@ int g_dhcp_client_start(GDHCPClient *dhcp_client, const
char *last_address)
discover_timeout,
dhcp_client,
NULL);
+ set_wake(dhcp_client, DISCOVER_TIMEOUT);
return 0;
}
@@ -2803,6 +2857,7 @@ void g_dhcp_client_stop(GDHCPClient *dhcp_client)
dhcp_client->requested_ip);
if (dhcp_client->timeout > 0) {
+ set_wake(dhcp_client, 1);
g_source_remove(dhcp_client->timeout);
dhcp_client->timeout = 0;
}
@@ -2917,6 +2972,10 @@ void g_dhcp_client_register_event(GDHCPClient
*dhcp_client,
dhcp_client->decline_cb = func;
dhcp_client->decline_data = data;
return;
+ case G_DHCP_CLIENT_EVENT_WAKE_EVENT:
+ dhcp_client->wake_event_cb = func;
+ dhcp_client->wake_event_data= data;
+ return;
}
}
diff --git a/gdhcp/gdhcp.h b/gdhcp/gdhcp.h
index 0d79361..26b1287 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_WAKE_EVENT,
} GDHCPClientEvent;
typedef enum {
@@ -169,6 +170,8 @@ gboolean g_dhcpv6_client_clear_send(GDHCPClient
*dhcp_client, uint16_t code);
void g_dhcpv6_client_set_send(GDHCPClient *dhcp_client, uint16_t option_code,
uint8_t *option_value, uint16_t option_len);
uint16_t g_dhcpv6_client_get_status(GDHCPClient *dhcp_client);
+bool g_dhcp_get_next_event(GDHCPClient *dhcp_client, time_t *next_event);
+
int g_dhcpv6_client_set_oro(GDHCPClient *dhcp_client, int args, ...);
void g_dhcpv6_client_create_iaid(GDHCPClient *dhcp_client, int index,
unsigned char *iaid);
diff --git a/src/dhcp.c b/src/dhcp.c
index 2193e4d..680eae4 100644
--- a/src/dhcp.c
+++ b/src/dhcp.c
@@ -163,6 +163,7 @@ static void ipv4ll_stop_client(struct connman_dhcp *dhcp)
static void ipv4ll_lost_cb(GDHCPClient *dhcp_client, gpointer user_data);
static void ipv4ll_available_cb(GDHCPClient *ipv4ll_client, gpointer
user_data);
+static void wake_event_cb(GDHCPClient *dhcp_client, gpointer user_data);
static int ipv4ll_start_client(struct connman_dhcp *dhcp)
{
@@ -199,6 +200,10 @@ static int ipv4ll_start_client(struct connman_dhcp *dhcp)
G_DHCP_CLIENT_EVENT_IPV4LL_LOST, ipv4ll_lost_cb, dhcp);
g_dhcp_client_register_event(ipv4ll_client,
+ G_DHCP_CLIENT_EVENT_WAKE_EVENT,
+ wake_event_cb, dhcp);
+
+ g_dhcp_client_register_event(ipv4ll_client,
G_DHCP_CLIENT_EVENT_IPV4LL_AVAILABLE,
ipv4ll_available_cb, dhcp);
@@ -278,6 +283,17 @@ static void ipv4ll_lost_cb(GDHCPClient *dhcp_client,
gpointer user_data)
dhcp_invalidate(dhcp, true);
}
+static void wake_event_cb(GDHCPClient *dhcp_client, gpointer user_data)
+{
+ struct connman_dhcp *dhcp = user_data;
+ time_t valid_until;
+ bool can_sleep;
+
+ can_sleep = g_dhcp_get_next_event(dhcp_client, &valid_until);
+ DBG("can_sleep: %d until: %lld", can_sleep, (long long)valid_until);
+
+ __connman_notifier_sleep_event(dhcp,can_sleep, valid_until);
+}
static bool compare_string_arrays(char **array_a, char **array_b)
{
int i;
@@ -543,6 +559,10 @@ static int dhcp_request(struct connman_dhcp *dhcp)
lease_available_cb, dhcp);
g_dhcp_client_register_event(dhcp_client,
+ G_DHCP_CLIENT_EVENT_WAKE_EVENT,
+ wake_event_cb, dhcp);
+
+ g_dhcp_client_register_event(dhcp_client,
G_DHCP_CLIENT_EVENT_LEASE_LOST, lease_lost_cb, dhcp);
g_dhcp_client_register_event(dhcp_client,
--
1.7.9.5
_______________________________________________
connman mailing list
[email protected]
https://lists.connman.net/mailman/listinfo/connman