From: Jaehyun Kim Date: Fri, 8 Sep 2017 07:43:53 +0000 (+0900) Subject: Add support for metered network X-Git-Tag: accepted/tizen/unified/20170914.065446^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=629f099ee1df80fb9255b8d3515d1a0832ee5222;p=platform%2Fcore%2Fconnectivity%2Fnet-config.git Add support for metered network Change-Id: Icd31d6f21f6d7cfb8c09b046e7fbb973e828b599 Signed-off-by: Jaehyun Kim --- diff --git a/include/network-state.h b/include/network-state.h index cb892ee..a1bdd0d 100755 --- a/include/network-state.h +++ b/include/network-state.h @@ -33,6 +33,7 @@ const char *netconfig_get_default_ipaddress6(void); const char *netconfig_get_default_proxy(void); unsigned int netconfig_get_default_frequency(void); const char *netconfig_wifi_get_connected_essid(const char *default_profile); +gboolean netconfig_get_default_is_metered(void); void netconfig_update_default(void); void netconfig_update_default_profile(const char *profile); diff --git a/interfaces/netconfig-iface-network-state.xml b/interfaces/netconfig-iface-network-state.xml index 7d0a32c..e0fa110 100755 --- a/interfaces/netconfig-iface-network-state.xml +++ b/interfaces/netconfig-iface-network-state.xml @@ -38,5 +38,8 @@ + + + diff --git a/src/network-state.c b/src/network-state.c index 2c66a1e..0fb0280 100755 --- a/src/network-state.c +++ b/src/network-state.c @@ -76,6 +76,17 @@ #define ROUTE_EXEC_PATH "/sbin/route" +#define TELEPHONY_SERVICE "com.tcore.ps" +#define TELEPHONY_MASTER_INTERFACE TELEPHONY_SERVICE ".master" +#define TELEPHONY_MODEM_INTERFACE TELEPHONY_SERVICE ".modem" +#define TELEPHONY_PROFILE_INTERFACE TELEPHONY_SERVICE ".context" +#define TELEPHONY_MASTER_PATH "/" +#define NET_PROFILE_NAME_LEN_MAX 512 + +typedef struct { + char profile_name[NET_PROFILE_NAME_LEN_MAX]; +} net_profile_name_t; + static Network *netconfigstate = NULL; struct netconfig_default_connection { @@ -86,6 +97,7 @@ struct netconfig_default_connection { char *proxy; char *essid; unsigned int freq; + gboolean is_metered; }; static struct netconfig_default_connection @@ -155,6 +167,192 @@ static char *__netconfig_get_default_profile(void) return default_profile; } +static int __netconfig_telephony_get_modem_object_path(GSList **modem_path_list) +{ + GVariant *result; + GVariantIter *iter_modem = NULL; + GVariantIter *modem_properties = NULL; + const char *modem_path; + + result = netconfig_invoke_dbus_method(TELEPHONY_SERVICE, TELEPHONY_MASTER_PATH, + TELEPHONY_MASTER_INTERFACE, "GetModems", NULL); + if (result == NULL) { + ERR("Failed to get modem path list"); + return -1; + } + + g_variant_get(result, "(a{sa{ss}})", &iter_modem); + while (g_variant_iter_loop(iter_modem, "{sa{ss}}", &modem_path, &modem_properties)) { + *modem_path_list = g_slist_append(*modem_path_list, g_strdup(modem_path)); + DBG("modem object path: %s", modem_path); + } + + g_variant_iter_free(iter_modem); + g_variant_unref(result); + + return 0; +} + +static int __netconfig_telephony_get_profile_list(net_profile_name_t **profile_list, + int *profile_count) +{ + int ret = 0; + int count = 0, i = 0; + const char *str = NULL; + GVariant *result; + GVariantIter *iter = NULL; + GSList *profiles = NULL, *list = NULL; + net_profile_name_t *plist = NULL; + + GSList *modem_path_list = NULL; + const char *path = NULL; + + ret = __netconfig_telephony_get_modem_object_path(&modem_path_list); + if (ret < 0) { + ERR("Failed to get modems path list"); + + g_slist_free_full(modem_path_list, g_free); + return ret; + } + + for (list = modem_path_list; list != NULL; list = list->next) { + path = (const char *)list->data; + + DBG("path: %s", path); + result = netconfig_invoke_dbus_method(TELEPHONY_SERVICE, path, + TELEPHONY_MODEM_INTERFACE, "GetProfileList", NULL); + if (result == NULL) { + DBG("Failed to get profiles: %s", path); + continue; + } + + g_variant_get(result, "(as)", &iter); + while (g_variant_iter_loop(iter, "s", &str)) + profiles = g_slist_append(profiles, g_strdup(str)); + + g_variant_iter_free(iter); + g_variant_unref(result); + } + + g_slist_free_full(modem_path_list, g_free); + + count = g_slist_length(profiles); + if (count > 0) { + plist = (net_profile_name_t*)malloc(sizeof(net_profile_name_t) * count); + } else { + *profile_count = 0; + goto out; + } + + if (plist == NULL) { + ERR("Failed to allocate memory"); + *profile_count = 0; + ret = -1; + goto out; + } + + for (list = profiles, i = 0; list != NULL; list = list->next, i++) + g_strlcpy(plist[i].profile_name, + (const char *)list->data, NET_PROFILE_NAME_LEN_MAX); + + *profile_list = plist; + *profile_count = count; + +out: + g_slist_free_full(profiles, g_free); + + return ret; +} + +static int __netconfig_telephony_search_pdp_profile(const char* profile_name, net_profile_name_t* pdp_name) +{ + int ret; + net_profile_name_t* profile_list = NULL; + char* prof_name = NULL; + char* tel_prof_name = NULL; + char* found_ptr = NULL; + int profile_count = 0; + int i; + + /* Get pdp profile list from telephony service */ + ret = __netconfig_telephony_get_profile_list(&profile_list, &profile_count); + if (ret < 0) { + ERR("Failed to get profile list from telephony service"); + g_free(profile_list); + return ret; + } + + if (profile_list == NULL || profile_count <= 0) { + ERR("There is no PDP profiles"); + g_free(profile_list); + return -1; + } + + /* Find matching profile */ + prof_name = strrchr(profile_name, '/') + 1; + for (i = 0; i < profile_count; i++) { + tel_prof_name = strrchr(profile_list[i].profile_name, '/') + 1; + found_ptr = strstr(prof_name, tel_prof_name); + + if (found_ptr != NULL && g_strcmp0(found_ptr, tel_prof_name) == 0) { + g_strlcpy(pdp_name->profile_name, + profile_list[i].profile_name, NET_PROFILE_NAME_LEN_MAX); + + DBG("PDP profile name found in cellular profile: %s", pdp_name->profile_name); + break; + } + } + + if (i >= profile_count) { + ERR("There is no matching PDP profiles"); + g_free(profile_list); + return -1; + } + + g_free(profile_list); + + return ret; +} + +static gboolean __netconfig_telephony_get_metered_info(net_profile_name_t* pdp_name) +{ + GVariant *result; + GVariantIter *iter; + const gchar *key = NULL; + const gchar *value = NULL; + gboolean ret = FALSE; + + if (pdp_name == NULL) { + ERR("Invalid parameter!"); + return ret; + } + + result = netconfig_invoke_dbus_method(TELEPHONY_SERVICE, pdp_name->profile_name, + TELEPHONY_PROFILE_INTERFACE, "GetProfile", NULL); + if (result == NULL) { + ERR("_net_invoke_dbus_method failed"); + return ret; + } + + g_variant_get(result, "(a{ss})", &iter); + while (g_variant_iter_next(iter, "{ss}", &key, &value)) { + if (g_strcmp0(key, "is_metered") == 0) { + if (value == NULL) + continue; + + if (g_strcmp0(value, "TRUE") == 0) + ret = TRUE; + } + } + + g_variant_iter_free(iter); + g_variant_unref(result); + + DBG("is_metered = %s", ret ? "TRUE" : "FALSE"); + + return ret; +} + static void __netconfig_get_default_connection_info(const char *profile) { GVariant *message = NULL, *variant = NULL, *variant2 = NULL; @@ -283,6 +481,16 @@ static void __netconfig_get_default_connection_info(const char *profile) } } + if (netconfig_is_cellular_profile(profile) == TRUE) { + net_profile_name_t pdp_name; + int ret; + + ret = __netconfig_telephony_search_pdp_profile(profile, &pdp_name); + if (ret >= 0 && strlen(pdp_name.profile_name) > 0) + if (__netconfig_telephony_get_metered_info(&pdp_name)) + netconfig_default_connection_info.is_metered = TRUE; + } + done: if (message) g_variant_unref(message); @@ -719,6 +927,11 @@ const char *netconfig_wifi_get_connected_essid(const char *default_profile) return netconfig_default_connection_info.essid; } +gboolean netconfig_get_default_is_metered(void) +{ + return netconfig_default_connection_info.is_metered; +} + static int __netconfig_reset_ipv4_socket(void) { int ret; @@ -797,6 +1010,7 @@ void netconfig_update_default_profile(const char *profile) netconfig_default_connection_info.proxy = NULL; netconfig_default_connection_info.freq = 0; + netconfig_default_connection_info.is_metered = FALSE; if (wifi_state_get_service_state() != NETCONFIG_WIFI_CONNECTED) { g_free(netconfig_default_connection_info.essid); @@ -1078,6 +1292,19 @@ gboolean handle_ethernet_cable_state(Network *object, return TRUE; } +gboolean handle_get_metered_info(Network *object, + GDBusMethodInvocation *context) +{ + gboolean state = 0; + + state = netconfig_get_default_is_metered(); + + DBG("Default metered state [%s]", state ? "TRUE" : "FALSE"); + network_complete_get_metered_info(object, context, state); + + return TRUE; +} + void state_object_create_and_init(void) { DBG("Creating network state object"); @@ -1116,6 +1343,8 @@ void state_object_create_and_init(void) G_CALLBACK(handle_device_policy_set_wifi_profile), NULL); g_signal_connect(netconfigstate, "handle-device-policy-get-wifi-profile", G_CALLBACK(handle_device_policy_get_wifi_profile), NULL); + g_signal_connect(netconfigstate, "handle-get-metered-info", + G_CALLBACK(handle_get_metered_info), NULL); if (!g_dbus_interface_skeleton_export(interface_network, connection, NETCONFIG_NETWORK_STATE_PATH, NULL)) {