From 24fe43d735b26895025f2aa7706819d4a6663104 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Wed, 2 Mar 2016 16:58:27 -0500 Subject: [PATCH] add new wireless module/gadget this is the successor to the connman module/gadget. it does not use or depend on econnman. --- configure.ac | 2 + src/bin/e_module.c | 1 + src/modules/Makefile.mk | 2 + src/modules/Makefile_wireless.mk | 27 + src/modules/wireless/connman.c | 1634 ++++++++++++++++++++ src/modules/wireless/e-module-wireless.edj | Bin 0 -> 21146 bytes src/modules/wireless/mod.c | 33 + src/modules/wireless/module.desktop.in | 8 + src/modules/wireless/wireless.c | 1476 ++++++++++++++++++ src/modules/wireless/wireless.h | 134 ++ 10 files changed, 3317 insertions(+) create mode 100644 src/modules/Makefile_wireless.mk create mode 100644 src/modules/wireless/connman.c create mode 100644 src/modules/wireless/e-module-wireless.edj create mode 100644 src/modules/wireless/mod.c create mode 100644 src/modules/wireless/module.desktop.in create mode 100644 src/modules/wireless/wireless.c create mode 100644 src/modules/wireless/wireless.h diff --git a/configure.ac b/configure.ac index 917d65244..7b286c626 100644 --- a/configure.ac +++ b/configure.ac @@ -924,6 +924,7 @@ AC_E_OPTIONAL_MODULE([wl_weekeyboard], $have_wayland, [CHECK_MODULE_WL_WEEKEYBOA AC_E_OPTIONAL_MODULE([policy_mobile], true) AC_E_OPTIONAL_MODULE([geolocation], true) AC_E_OPTIONAL_MODULE([xwayland], $have_wayland, [CHECK_MODULE_XWAYLAND]) +AC_E_OPTIONAL_MODULE([wireless], true) if test "x${HAVE_WL_X11}" != "xyes" && test "x${have_wayland}" = "xyes" && test "x${HAVE_XWAYLAND}" != "xyes"; then AC_DEFINE_UNQUOTED([HAVE_WAYLAND_ONLY],[1],[enable wayland-only version of enlightenment]) @@ -1125,6 +1126,7 @@ src/modules/tiling/module.desktop src/modules/music-control/module.desktop src/modules/packagekit/module.desktop src/modules/wl_desktop_shell/module.desktop +src/modules/wireless/module.desktop data/xsession/enlightenment.desktop data/etc/sysactions.conf data/units/enlightenment.service diff --git a/src/bin/e_module.c b/src/bin/e_module.c index c211b93b8..945788de6 100644 --- a/src/bin/e_module.c +++ b/src/bin/e_module.c @@ -1025,6 +1025,7 @@ _e_module_whitelist_check(void) "temperature", "tiling", "winlist", + "wireless", "wizard", "wl_desktop_shell", "wl_x11", diff --git a/src/modules/Makefile.mk b/src/modules/Makefile.mk index f4d5f6a55..bb618da1e 100644 --- a/src/modules/Makefile.mk +++ b/src/modules/Makefile.mk @@ -127,3 +127,5 @@ include src/modules/Makefile_wl_weekeyboard.mk include src/modules/Makefile_policy_mobile.mk include src/modules/Makefile_geolocation.mk + +include src/modules/Makefile_wireless.mk diff --git a/src/modules/Makefile_wireless.mk b/src/modules/Makefile_wireless.mk new file mode 100644 index 000000000..0d28d4044 --- /dev/null +++ b/src/modules/Makefile_wireless.mk @@ -0,0 +1,27 @@ +EXTRA_DIST += \ +src/modules/wireless/module.desktop.in \ +src/modules/wireless/e-module-wireless.edj + +if USE_MODULE_WIRELESS +wirelessdir = $(MDIR)/wireless +wireless_DATA = \ +src/modules/wireless/module.desktop \ +src/modules/wireless/e-module-wireless.edj + +wirelesspkgdir = $(MDIR)/wireless/$(MODULE_ARCH) +wirelesspkg_LTLIBRARIES = src/modules/wireless/module.la + +src_modules_wireless_module_la_LDFLAGS = $(MOD_LDFLAGS) +src_modules_wireless_module_la_SOURCES = \ +src/modules/wireless/connman.c \ +src/modules/wireless/mod.c \ +src/modules/wireless/wireless.c \ +src/modules/wireless/wireless.h + +src_modules_wireless_module_la_CPPFLAGS = $(MOD_CPPFLAGS) +src_modules_wireless_module_la_LIBADD = $(MOD_LIBS) + +PHONIES += wireless install-wireless +wireless: $(wirelesspkg_LTLIBRARIES) $(wireless_DATA) +install-wireless: install-wirelessDATA install-wirelesspkgLTLIBRARIES +endif diff --git a/src/modules/wireless/connman.c b/src/modules/wireless/connman.c new file mode 100644 index 000000000..662e23a8f --- /dev/null +++ b/src/modules/wireless/connman.c @@ -0,0 +1,1634 @@ +#include "wireless.h" + +#define CONNMAN_BUS_NAME "net.connman" +#define CONNMAN_MANAGER_IFACE CONNMAN_BUS_NAME ".Manager" +#define CONNMAN_SERVICE_IFACE CONNMAN_BUS_NAME ".Service" +#define CONNMAN_TECHNOLOGY_IFACE CONNMAN_BUS_NAME ".Technology" +#define CONNMAN_TECHNOLOGY_PATH_ETHERNET "/net/connman/technology/ethernet" +#define CONNMAN_TECHNOLOGY_PATH_WIFI "/net/connman/technology/wifi" +#define CONNMAN_TECHNOLOGY_PATH_BT "/net/connman/technology/bluetooth" +#define CONNMAN_TECHNOLOGY_PATH_CELLULAR "/net/connman/technology/cellular" +#define CONNMAN_AGENT_IFACE "net.connman.Agent" +#define CONNMAN_AGENT_PATH "/org/enlightenment/wireless/agent" + +#define CONNMAN_SERVICE_TYPE_ITER(i) \ + for ((i) = 0; (i) < CONNMAN_SERVICE_TYPE_LAST; (i)++) + +#define MILLI_PER_SEC 1000 +#define CONNMAN_CONNECTION_TIMEOUT 60 * MILLI_PER_SEC + +#undef DBG +#undef INF +#undef WRN +#undef ERR + +#define DBG(...) EINA_LOG_DOM_DBG(_connman_log_dom, __VA_ARGS__) +#define INF(...) EINA_LOG_DOM_INFO(_connman_log_dom, __VA_ARGS__) +#define WRN(...) EINA_LOG_DOM_WARN(_connman_log_dom, __VA_ARGS__) +#define ERR(...) EINA_LOG_DOM_ERR(_connman_log_dom, __VA_ARGS__) + +typedef enum +{ + CONNMAN_STATE_NONE = -1, /* All unknown states */ + CONNMAN_STATE_OFFLINE, + CONNMAN_STATE_IDLE, + CONNMAN_STATE_ASSOCIATION, + CONNMAN_STATE_CONFIGURATION, + CONNMAN_STATE_READY, + CONNMAN_STATE_ONLINE, + CONNMAN_STATE_DISCONNECT, + CONNMAN_STATE_FAILURE, +} Connman_State; + +typedef enum +{ + CONNMAN_SERVICE_TYPE_NONE = -1, /* All non-supported types */ + CONNMAN_SERVICE_TYPE_ETHERNET = 0, + CONNMAN_SERVICE_TYPE_WIFI = 1, + CONNMAN_SERVICE_TYPE_BLUETOOTH = 2, + CONNMAN_SERVICE_TYPE_CELLULAR = 3, + CONNMAN_SERVICE_TYPE_LAST = 4, +} Connman_Service_Type; + +typedef struct Connman_Technology +{ + Connman_Service_Type type; + Eldbus_Proxy *proxy; + Eina_Stringshare *tethering_ssid; + Eina_Stringshare *tethering_passwd; + Eina_Bool powered : 1; + Eina_Bool connected : 1; + Eina_Bool tethering : 1; +} Connman_Technology; + +typedef struct +{ + EINA_INLIST; + Eldbus_Proxy *proxy; + + /* Private */ + struct + { + Eldbus_Pending *connect; + Eldbus_Pending *disconnect; + Eldbus_Pending *remov; + void *data; + } pending; + Eldbus_Signal_Handler *handler; + + /* Properties */ + Eina_Stringshare *path; + Eina_Stringshare *name; + Wireless_Network_Security security; + Connman_State state; + Connman_Service_Type type; + uint8_t strength; + + /* Connection */ + unsigned int method; + Eina_Stringshare *address; + Eina_Stringshare *gateway; + union + { + struct + { + Eina_Stringshare *netmask; + } v4; + struct + { + Eina_Stringshare *prefixlength; + Wireless_Network_IPv6_Privacy privacy; + } v6; + } ip; + + Eina_Array *domain_servers; + Eina_Array *name_servers; + Eina_Array *time_servers; + + /* Proxy */ + unsigned int proxy_type; + Eina_Stringshare *proxy_url; + Eina_Array *proxy_servers; + Eina_Array *proxy_excludes; + Eina_Bool ipv6 : 1; + Eina_Bool favorite : 1; +} Connman_Service; + +typedef enum +{ + CONNMAN_FIELD_STATE_MANDATORY, + CONNMAN_FIELD_STATE_OPTIONAL, + CONNMAN_FIELD_STATE_ALTERNATE, + CONNMAN_FIELD_STATE_INFO, +} Connman_Field_State; + +typedef struct Connman_Field +{ + const char *name; + + Connman_Field_State requirement; + const char *type; + const char *value; +} Connman_Field; + +static int _connman_log_dom = -1; + +static Eldbus_Proxy *proxy_manager; + +static Eldbus_Pending *pending_gettechnologies; +static Eldbus_Pending *pending_getservices; +static Eldbus_Pending *pending_getproperties_manager; + +static Eina_List *signal_handlers; + +static Eina_Inlist *connman_services_list[CONNMAN_SERVICE_TYPE_LAST]; +static Eina_Hash *connman_services[CONNMAN_SERVICE_TYPE_LAST]; +static Eldbus_Service_Interface *agent_iface; + +static Connman_Service *connman_current_service[CONNMAN_SERVICE_TYPE_LAST]; +static Wireless_Connection *connman_current_connection[CONNMAN_SERVICE_TYPE_LAST]; + +static Connman_Technology connman_technology[CONNMAN_SERVICE_TYPE_LAST]; + +/* connman -> wireless */ +static Eina_Hash *connman_services_map[CONNMAN_SERVICE_TYPE_LAST]; + +static inline Eina_Bool +_connman_service_is_connected(const Connman_Service *cs) +{ + return (cs->state >= CONNMAN_STATE_ASSOCIATION) && (cs->state <= CONNMAN_STATE_ONLINE); +} + +static void +_eldbus_proxy_del(Eldbus_Proxy *proxy) +{ + Eldbus_Object *obj; + + obj = eldbus_proxy_object_get(proxy); + eldbus_proxy_unref(proxy); + eldbus_object_unref(obj); +} + +static void +_connman_service_connect_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED) +{ + Connman_Service *cs = data; + const char *error; + + /* FIXME */ + cs->pending.connect = NULL; + eldbus_message_error_get(msg, NULL, &error); +} + +static Eina_Bool +_connman_service_connect(Wireless_Network *wn) +{ + Connman_Service *cs; + + cs = eina_hash_find(connman_services[wn->type], wn->path); + EINA_SAFETY_ON_NULL_RETURN_VAL(cs, EINA_FALSE); + if (!cs->pending.connect) + cs->pending.connect = eldbus_proxy_call(cs->proxy, "Connect", + _connman_service_connect_cb, cs, + CONNMAN_CONNECTION_TIMEOUT, ""); + return !!cs->pending.connect; +} + +static void +_connman_update_technologies(void) +{ + Eina_Bool avail[CONNMAN_SERVICE_TYPE_LAST]; + int i; + + CONNMAN_SERVICE_TYPE_ITER(i) + avail[i] = connman_technology[i].type > -1; + wireless_service_type_available_set(avail); +} + +static void +_connman_update_enabled_technologies(void) +{ + Eina_Bool enabled[CONNMAN_SERVICE_TYPE_LAST]; + int i; + + CONNMAN_SERVICE_TYPE_ITER(i) + enabled[i] = connman_technology[i].powered; + wireless_service_type_enabled_set(enabled); +} + +static Wireless_Network_State +_connman_wifi_state_convert(Connman_State state) +{ + Wireless_Network_State wifi_state; + switch (state) + { + case CONNMAN_STATE_ASSOCIATION: + case CONNMAN_STATE_CONFIGURATION: + wifi_state = WIRELESS_NETWORK_STATE_CONFIGURING; + break; + case CONNMAN_STATE_READY: + wifi_state = WIRELESS_NETWORK_STATE_CONNECTED; + break; + case CONNMAN_STATE_ONLINE: + wifi_state = WIRELESS_NETWORK_STATE_ONLINE; + break; + case CONNMAN_STATE_FAILURE: + wifi_state = WIRELESS_NETWORK_STATE_FAILURE; + break; + case CONNMAN_STATE_NONE: + case CONNMAN_STATE_OFFLINE: + case CONNMAN_STATE_IDLE: + case CONNMAN_STATE_DISCONNECT: + default: + wifi_state = WIRELESS_NETWORK_STATE_NONE; + } + return wifi_state; +} + +static Wireless_Network * +_connman_service_convert(Connman_Service *cs) +{ + Wireless_Network *wn; + + wn = E_NEW(Wireless_Network, 1); + memcpy(wn, &cs->path, offsetof(Wireless_Network, connect_cb)); + wn->state = _connman_wifi_state_convert(cs->state); + wn->connect_cb = _connman_service_connect; + return wn; +} + +static void +_connman_update_current_network(Connman_Service *cs, Connman_Service_Type type) +{ + if (connman_current_service[type] != cs) + { + E_FREE(connman_current_connection[type]); + if (cs) + connman_current_connection[type] = E_NEW(Wireless_Connection, 1); + } + connman_current_service[type] = cs; + if (cs) + { + connman_current_connection[type]->wn = eina_hash_find(connman_services_map[type], &cs); + memcpy(&connman_current_connection[type]->method, + &cs->method, sizeof(Wireless_Connection) - sizeof(void*)); + } + else + connman_current_connection[type] = NULL; + wireless_wifi_current_networks_set(connman_current_connection); +} + +static void +_connman_update_networks(Connman_Service_Type type) +{ + Eina_Array *arr; + Connman_Service *cs; + Wireless_Network *wn; + Eina_Hash *map; + Connman_Service *services[CONNMAN_SERVICE_TYPE_LAST] = {NULL}; + + map = connman_services_map[type]; + connman_services_map[type] = eina_hash_pointer_new(free); + arr = eina_array_new(eina_hash_population(connman_services[type])); + EINA_INLIST_FOREACH(connman_services_list[type], cs) + { + wn = _connman_service_convert(cs); + eina_hash_add(connman_services_map[type], &cs, wn); + eina_array_push(arr, wn); + if (connman_current_service[type] && _connman_service_is_connected(cs)) + services[type] = cs; + } + memcpy(&connman_current_service, services, CONNMAN_SERVICE_TYPE_LAST * sizeof(void*)); + arr = wireless_networks_set(arr); + _connman_update_current_network(connman_current_service[type], type); + eina_hash_free(map); + eina_array_free(arr); +} + +static void +_connman_update_airplane_mode(Eina_Bool offline) +{ + wireless_airplane_mode_set(offline); +} + +static Connman_State +str_to_state(const char *s) +{ + if (!strcmp(s, "offline")) + return CONNMAN_STATE_OFFLINE; + if (!strcmp(s, "idle")) + return CONNMAN_STATE_IDLE; + if (!strcmp(s, "association")) + return CONNMAN_STATE_ASSOCIATION; + if (!strcmp(s, "configuration")) + return CONNMAN_STATE_CONFIGURATION; + if (!strcmp(s, "ready")) + return CONNMAN_STATE_READY; + if (!strcmp(s, "online")) + return CONNMAN_STATE_ONLINE; + if (!strcmp(s, "disconnect")) + return CONNMAN_STATE_DISCONNECT; + if (!strcmp(s, "failure")) + return CONNMAN_STATE_FAILURE; + + ERR("Unknown state %s", s); + return CONNMAN_STATE_NONE; +} + +static Connman_Service_Type +str_to_type(const char *s) +{ + if (!strcmp(s, "ethernet")) + return CONNMAN_SERVICE_TYPE_ETHERNET; + if (!strcmp(s, "wifi")) + return CONNMAN_SERVICE_TYPE_WIFI; + if (!strcmp(s, "bluetooth")) + return CONNMAN_SERVICE_TYPE_BLUETOOTH; + if (!strcmp(s, "cellular")) + return CONNMAN_SERVICE_TYPE_CELLULAR; + + DBG("Unknown type %s", s); + return CONNMAN_SERVICE_TYPE_NONE; +} + +static Wireless_Network_Security +str_to_security(const char *s) +{ + if (!strcmp(s, "none")) return WIRELESS_NETWORK_SECURITY_NONE; + if (!strcmp(s, "wep")) return WIRELESS_NETWORK_SECURITY_WEP; + if (!strcmp(s, "psk")) return WIRELESS_NETWORK_SECURITY_PSK; + if (!strcmp(s, "ieee8021x")) return WIRELESS_NETWORK_SECURITY_IEEE8021X; + if (!strcmp(s, "wps")) return WIRELESS_NETWORK_SECURITY_WPS; + CRI("UNKNOWN TYPE %s", s); + return WIRELESS_NETWORK_SECURITY_NONE; +} + +static void +_connman_service_free(Connman_Service *cs) +{ + if (!cs) return; + + if (cs->pending.connect) + { + eldbus_pending_cancel(cs->pending.connect); + free(cs->pending.data); + } + else if (cs->pending.disconnect) + { + eldbus_pending_cancel(cs->pending.disconnect); + free(cs->pending.data); + } + else if (cs->pending.remov) + { + eldbus_pending_cancel(cs->pending.remov); + free(cs->pending.data); + } + eina_stringshare_del(cs->address); + eina_stringshare_del(cs->gateway); + if (cs->ipv6) + eina_stringshare_del(cs->ip.v6.prefixlength); + else + eina_stringshare_del(cs->ip.v4.netmask); + + eina_stringshare_del(cs->proxy_url); + + array_clear(cs->domain_servers); + array_clear(cs->name_servers); + array_clear(cs->time_servers); + + array_clear(cs->proxy_servers); + array_clear(cs->proxy_excludes); + + eina_stringshare_del(cs->name); + eina_stringshare_del(cs->path); + eldbus_signal_handler_del(cs->handler); + DBG("service free %p || proxy %p", cs, cs->proxy); + _eldbus_proxy_del(cs->proxy); + connman_services_list[cs->type] = eina_inlist_remove(connman_services_list[cs->type], EINA_INLIST_GET(cs)); + + free(cs); +} + +static void +_connman_service_parse_stringarray(Eldbus_Message_Iter *value, Eina_Array **arr) +{ + Eldbus_Message_Iter *itr_array; + const char *s; + + EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(value, "as", + &itr_array)); + if (*arr) + { + while (eina_array_count(*arr)) + eina_stringshare_del(eina_array_pop(*arr)); + } + else + *arr = eina_array_new(1); + while (eldbus_message_iter_get_and_next(itr_array, 's', &s)) + eina_array_push(*arr, eina_stringshare_add(s)); +} + +static void +_connman_service_parse_prop_changed(Connman_Service *cs, const char *prop_name, Eldbus_Message_Iter *value) +{ + DBG("service %p %s prop %s", cs, cs->path, prop_name); + + if (!strcmp(prop_name, "State")) + { + const char *state; + EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(value, + "s", + &state)); + cs->state = str_to_state(state); + DBG("New state: %s %d", state, cs->state); + } + if (!strcmp(prop_name, "Favorite")) + { + Eina_Bool state; + EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(value, + "b", + &state)); + cs->favorite = !!state; + DBG("New favorite state: %d", cs->favorite); + } + else if (!strcmp(prop_name, "Name")) + { + const char *name; + EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(value, + "s", + &name)); + eina_stringshare_replace(&cs->name, name); + DBG("New name: %s", cs->name); + } + else if (!strcmp(prop_name, "Type")) + { + const char *type; + EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(value, + "s", + &type)); + cs->type = str_to_type(type); + DBG("New type: %s %d", type, cs->type); + } + else if (!strcmp(prop_name, "Strength")) + { + uint8_t strength; + EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(value, + "y", + &strength)); + cs->strength = strength; + DBG("New strength: %d", strength); + } + else if (!strcmp(prop_name, "Security")) + { + const char *s; + Eldbus_Message_Iter *itr_array; + + DBG("Old security: %u", cs->security); + cs->security = WIRELESS_NETWORK_SECURITY_NONE; + + EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(value, "as", + &itr_array)); + while (eldbus_message_iter_get_and_next(itr_array, 's', &s)) + cs->security |= str_to_security(s); + DBG("New security %u", cs->security); + } + else if (!strcmp(prop_name, "IPv4")) + { + Eldbus_Message_Iter *array, *dict; + + EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(value, "a{sv}", &array)); + while (eldbus_message_iter_get_and_next(array, 'e', &dict)) + { + Eldbus_Message_Iter *var; + const char *name, *val; + + EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(dict, "sv", &name, &var)); + if (!strcmp(name, "Method")) + { + cs->method = WIRELESS_NETWORK_IPV4_METHOD_OFF; + EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(var, "s", &val)); + if (!strcmp(val, "off")) + cs->method = WIRELESS_NETWORK_IPV4_METHOD_OFF; + else if (!strcmp(val, "dhcp")) + cs->method = WIRELESS_NETWORK_IPV4_METHOD_DHCP; + else if (!strcmp(val, "manual")) + cs->method = WIRELESS_NETWORK_IPV4_METHOD_MANUAL; + else if (!strcmp(val, "fixed")) + cs->method = WIRELESS_NETWORK_IPV4_METHOD_FIXED; + } + else if (!strcmp(name, "Address")) + { + EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(var, "s", &val)); + eina_stringshare_replace(&cs->address, val); + } + else if (!strcmp(name, "Netmask")) + { + EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(var, "s", &val)); + eina_stringshare_replace(&cs->ip.v4.netmask, val); + } + else if (!strcmp(name, "Gateway")) + { + EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(var, "s", &val)); + eina_stringshare_replace(&cs->gateway, val); + } + } + } + else if (!strcmp(prop_name, "IPv6")) + { + Eldbus_Message_Iter *array, *dict; + + EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(value, "a{sv}", &array)); + while (eldbus_message_iter_get_and_next(array, 'e', &dict)) + { + Eldbus_Message_Iter *var; + const char *name, *val; + + EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(dict, "sv", &name, &var)); + if (!strcmp(name, "Method")) + { + cs->method = WIRELESS_NETWORK_IPV6_METHOD_OFF; + EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(var, "s", &val)); + if (!strcmp(val, "auto")) + cs->method = WIRELESS_NETWORK_IPV6_METHOD_AUTO; + else if (!strcmp(val, "manual")) + cs->method = WIRELESS_NETWORK_IPV6_METHOD_MANUAL; + else if (!strcmp(val, "6to4")) + cs->method = WIRELESS_NETWORK_IPV6_METHOD_6TO4; + else if (!strcmp(val, "fixed")) + cs->method = WIRELESS_NETWORK_IPV6_METHOD_FIXED; + } + else if (!strcmp(name, "Privacy")) + { + cs->ip.v6.privacy = WIRELESS_NETWORK_IPV6_PRIVACY_DISABLED; + EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(var, "s", &val)); + if (!strcmp(val, "disabled")) + cs->ip.v6.privacy = WIRELESS_NETWORK_IPV6_PRIVACY_DISABLED; + else if (!strcmp(val, "enabled")) + cs->ip.v6.privacy = WIRELESS_NETWORK_IPV6_PRIVACY_ENABLED; + else if (!strcmp(val, "preferred")) + cs->ip.v6.privacy = WIRELESS_NETWORK_IPV6_PRIVACY_PREFERRED; + } + else if (!strcmp(name, "Address")) + { + EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(var, "s", &val)); + eina_stringshare_replace(&cs->address, val); + } + else if (!strcmp(name, "PrefixLength")) + { + EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(var, "s", &val)); + eina_stringshare_replace(&cs->ip.v6.prefixlength, val); + } + else if (!strcmp(name, "Gateway")) + { + EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(var, "s", &val)); + eina_stringshare_replace(&cs->gateway, val); + } + } + } + else if (!strcmp(prop_name, "Proxy")) + { + Eldbus_Message_Iter *array, *dict; + + EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(value, "a{sv}", &array)); + while (eldbus_message_iter_get_and_next(array, 'e', &dict)) + { + Eldbus_Message_Iter *var; + const char *name, *val; + + EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(dict, "sv", &name, &var)); + if (!strcmp(name, "Method")) + { + cs->proxy_type = WIRELESS_PROXY_TYPE_DIRECT; + EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(var, "s", &val)); + if (!strcmp(val, "manual")) + cs->proxy_type = WIRELESS_PROXY_TYPE_MANUAL; + else if (!strcmp(val, "auto")) + cs->proxy_type = WIRELESS_PROXY_TYPE_AUTO; + } + else if (!strcmp(name, "URL")) + { + EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_iter_arguments_get(var, "s", &val)); + eina_stringshare_replace(&cs->proxy_url, val); + } + else if (!strcmp(name, "Servers")) + _connman_service_parse_stringarray(value, &cs->proxy_servers); + else if (!strcmp(name, "Excludes")) + _connman_service_parse_stringarray(value, &cs->proxy_excludes); + } + } + else if (!strcmp(prop_name, "Nameservers")) + _connman_service_parse_stringarray(value, &cs->name_servers); + else if (!strcmp(prop_name, "Timeservers")) + _connman_service_parse_stringarray(value, &cs->time_servers); + else if (!strcmp(prop_name, "Domains")) + _connman_service_parse_stringarray(value, &cs->domain_servers); +} + +static void +_connman_service_prop_dict_changed(Connman_Service *cs, Eldbus_Message_Iter *props) +{ + Eldbus_Message_Iter *dict; + + while (eldbus_message_iter_get_and_next(props, 'e', &dict)) + { + char *name; + Eldbus_Message_Iter *var; + + if (eldbus_message_iter_arguments_get(dict, "sv", &name, &var)) + _connman_service_parse_prop_changed(cs, name, var); + } + if (_connman_service_is_connected(cs)) + _connman_update_current_network(cs, cs->type); +} + +static void +_connman_service_property(void *data, const Eldbus_Message *msg) +{ + Connman_Service *cs = data; + Eldbus_Message_Iter *var; + const char *name; + + if (eldbus_message_arguments_get(msg, "sv", &name, &var)) + _connman_service_parse_prop_changed(cs, name, var); + if (_connman_service_is_connected(cs)) + _connman_update_current_network(cs, cs->type); +} + +static Connman_Service * +_connman_service_new(const char *path, Eldbus_Message_Iter *props) +{ + Connman_Service *cs; + Eldbus_Object *obj; + + cs = E_NEW(Connman_Service, 1); + cs->path = eina_stringshare_add(path); + + obj = eldbus_object_get(dbus_conn, CONNMAN_BUS_NAME, path); + cs->proxy = eldbus_proxy_get(obj, CONNMAN_SERVICE_IFACE); + cs->handler = eldbus_proxy_signal_handler_add(cs->proxy, "PropertyChanged", + _connman_service_property, cs); + + _connman_service_prop_dict_changed(cs, props); + connman_services_list[cs->type] = eina_inlist_append(connman_services_list[cs->type], EINA_INLIST_GET(cs)); + eina_hash_add(connman_services[cs->type], cs->path, cs); + DBG("Added service: %p %s || proxy %p", cs, path, cs->proxy); + return cs; +} + +static void +_connman_manager_agent_register(void *data EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED, Eldbus_Pending *pending EINA_UNUSED) +{ + /* FIXME: should this do something? */ +} + +static Eina_Bool +_connman_technology_parse_prop_changed(Connman_Technology *ct, const char *name, Eldbus_Message_Iter *value) +{ + Eina_Bool val; + const char *str; + Eina_Bool ret = EINA_FALSE; + + if (!strcmp(name, "Powered")) + { + eldbus_message_iter_arguments_get(value, "b", &val); + val = !!val; + if (val != ct->powered) ret = EINA_TRUE; + ct->powered = !!val; + } + else if (!strcmp(name, "Connected")) + { + eldbus_message_iter_arguments_get(value, "b", &val); + ct->connected = !!val; + } + else if (!strcmp(name, "Tethering")) + { + eldbus_message_iter_arguments_get(value, "b", &val); + ct->tethering = !!val; + } + else if (!strcmp(name, "TetheringIdentifier")) + { + eldbus_message_iter_arguments_get(value, "b", &str); + ct->tethering_ssid = eina_stringshare_add(str); + } + else if (!strcmp(name, "TetheringPassphrase")) + { + eldbus_message_iter_arguments_get(value, "b", &str); + ct->tethering_passwd = eina_stringshare_add(str); + } + return ret; +} + +static void +_connman_technology_event_property(void *data, const Eldbus_Message *msg) +{ + Eldbus_Message_Iter *var; + const char *name; + Connman_Technology *ct = NULL; + int i; + + CONNMAN_SERVICE_TYPE_ITER(i) + if (data == connman_technology[i].proxy) + { + ct = &connman_technology[i]; + break; + } + if (!ct) return; + + if (!eldbus_message_arguments_get(msg, "sv", &name, &var)) + ERR("Could not parse message %p", msg); + else if (_connman_technology_parse_prop_changed(ct, name, var)) + _connman_update_enabled_technologies(); +} + +static Eina_Bool +_connman_manager_parse_prop_changed(const char *name, Eldbus_Message_Iter *value) +{ + if (!strcmp(name, "State")) + { + const char *state; + + if (!eldbus_message_iter_arguments_get(value, "s", &state)) + return EINA_FALSE; + DBG("New state: %s", state); + //_connman_update_state(str_to_state(state)); + } + else if (!strcmp(name, "OfflineMode")) + { + Eina_Bool offline; + if (!eldbus_message_iter_arguments_get(value, "b", &offline)) + return EINA_FALSE; + _connman_update_airplane_mode(offline); + } + else + return EINA_FALSE; + + return EINA_TRUE; +} + +static void +_connman_manager_getproperties(void *data EINA_UNUSED, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED) +{ + Eldbus_Message_Iter *array, *dict; + const char *name, *text; + + pending_getproperties_manager = NULL; + if (eldbus_message_error_get(msg, &name, &text)) + { + ERR("Could not get properties. %s: %s", name, text); + return; + } + + if (!eldbus_message_arguments_get(msg, "a{sv}", &array)) + { + ERR("Error getting arguments."); + return; + } + + while (eldbus_message_iter_get_and_next(array, 'e', &dict)) + { + const char *key; + Eldbus_Message_Iter *var; + + if (eldbus_message_iter_arguments_get(dict, "sv", &key, &var)) + _connman_manager_parse_prop_changed(key, var); + } +} + +static void +_connman_manager_getservices(void *data EINA_UNUSED, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED) +{ + Eldbus_Message_Iter *array, *s; + const char *name, *text; + int i; + Eina_Bool update[CONNMAN_SERVICE_TYPE_LAST] = {0}; + + pending_getservices = NULL; + CONNMAN_SERVICE_TYPE_ITER(i) + eina_hash_free_buckets(connman_services[i]); + if (eldbus_message_error_get(msg, &name, &text)) + { + ERR("Could not get services. %s: %s", name, text); + return; + } + + if (!eldbus_message_arguments_get(msg, "a(oa{sv})", &array)) + { + ERR("Error getting array"); + return; + } + + while (eldbus_message_iter_get_and_next(array, 'r', &s)) + { + const char *path; + Eldbus_Message_Iter *inner_array; + Connman_Service *cs; + + if (!eldbus_message_iter_arguments_get(s, "oa{sv}", &path, &inner_array)) + continue; + + cs = _connman_service_new(path, inner_array); + update[cs->type] = 1; + } + CONNMAN_SERVICE_TYPE_ITER(i) + if (update[i]) _connman_update_networks(i); +} + +static void +_connman_manager_gettechnologies(void *data EINA_UNUSED, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED) +{ + Eldbus_Message_Iter *array, *s; + const char *name, *text; + + pending_gettechnologies = NULL; + if (eldbus_message_error_get(msg, &name, &text)) + { + ERR("Could not get technologies. %s: %s", name, text); + return; + } + + if (!eldbus_message_arguments_get(msg, "a(oa{sv})", &array)) + { + ERR("Error getting array"); + return; + } + + while (eldbus_message_iter_get_and_next(array, 'r', &s)) + { + const char *path; + Eldbus_Message_Iter *inner_array, *dict; + Connman_Technology *ct = NULL; + Eldbus_Object *obj; + int i; + const char *paths[] = + { + CONNMAN_TECHNOLOGY_PATH_ETHERNET, + CONNMAN_TECHNOLOGY_PATH_WIFI, + CONNMAN_TECHNOLOGY_PATH_BT, + CONNMAN_TECHNOLOGY_PATH_CELLULAR, + }; + + if (!eldbus_message_iter_arguments_get(s, "oa{sv}", &path, &inner_array)) + continue; + CONNMAN_SERVICE_TYPE_ITER(i) + { + if (strcmp(path, paths[i])) continue; + ct = &connman_technology[i]; + ct->type = i; + + obj = eldbus_object_get(dbus_conn, CONNMAN_BUS_NAME, paths[i]); + ct->proxy = eldbus_proxy_get(obj, CONNMAN_TECHNOLOGY_IFACE); + signal_handlers = eina_list_append(signal_handlers, + eldbus_proxy_signal_handler_add(ct->proxy, "PropertyChanged", + _connman_technology_event_property, ct->proxy)); + } + if (!ct) + { + ERR("No handler for technology: %s", path); + continue; + } + while (eldbus_message_iter_get_and_next(inner_array, 'e', &dict)) + { + Eldbus_Message_Iter *var; + + if (eldbus_message_iter_arguments_get(dict, "sv", &name, &var)) + _connman_technology_parse_prop_changed(ct, name, var); + } + } + /* scan not supported on bluetooth */ + if (connman_technology[CONNMAN_SERVICE_TYPE_BLUETOOTH].proxy) + pending_getservices = eldbus_proxy_call(proxy_manager, "GetServices", _connman_manager_getservices, + NULL, -1, ""); + else if (connman_technology[CONNMAN_SERVICE_TYPE_WIFI].proxy) + eldbus_proxy_call(connman_technology[CONNMAN_SERVICE_TYPE_WIFI].proxy, "Scan", NULL, NULL, -1, ""); + _connman_update_technologies(); + _connman_update_enabled_technologies(); +} + +static void +_connman_manager_event_services(void *data EINA_UNUSED, const Eldbus_Message *msg) +{ + Eldbus_Message_Iter *changed, *removed, *s; + const char *path; + int i; + Eina_Bool update[CONNMAN_SERVICE_TYPE_LAST] = {0}; + + if (pending_getservices) return; + + if (!eldbus_message_arguments_get(msg, "a(oa{sv})ao", &changed, &removed)) + { + ERR("Error getting arguments"); + return; + } + + while (eldbus_message_iter_get_and_next(removed, 'o', &path)) + { + CONNMAN_SERVICE_TYPE_ITER(i) + { + if (!eina_hash_del_by_key(connman_services[i], path)) continue; + DBG("Removed service: %s", path); + update[i] = 1; + break; + } + } + + while (eldbus_message_iter_get_and_next(changed, 'r', &s)) + { + Connman_Service *cs; + Eldbus_Message_Iter *array; + Eina_Bool found = EINA_FALSE; + + if (!eldbus_message_iter_arguments_get(s, "oa{sv}", &path, &array)) + continue; + + CONNMAN_SERVICE_TYPE_ITER(i) + { + cs = eina_hash_find(connman_services[i], path); + if (!cs) continue; + _connman_service_prop_dict_changed(cs, array); + found = update[cs->type] = 1; + DBG("Changed service: %p %s", cs, path); + break; + } + if (!found) + { + cs = _connman_service_new(path, array); + update[cs->type] = 1; + } + } + CONNMAN_SERVICE_TYPE_ITER(i) + if (update[i]) _connman_update_networks(i); +} + +static void +_connman_manager_event_property(void *data EINA_UNUSED, const Eldbus_Message *msg) +{ + Eldbus_Message_Iter *var; + const char *name; + + if (pending_getproperties_manager) return; + if (!eldbus_message_arguments_get(msg, "sv", &name, &var)) + { + ERR("Could not parse message %p", msg); + return; + } + + _connman_manager_parse_prop_changed(name, var); +} + +static Eldbus_Message * +_connman_agent_release(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg) +{ + DBG("Agent released"); + wireless_authenticate_cancel(); + return eldbus_message_method_return_new(msg); +} + +static Eldbus_Message * +_connman_agent_report_error(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED) +{ +#warning FIXME + return NULL; +} + +static Eldbus_Message * +_connman_agent_request_browser(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg) +{ + const char *path, *url; + int i; + Connman_Service *cs; + Wireless_Network *wn; + + if (!eldbus_message_arguments_get(msg, "ss", &path, &url)) + { + ERR("Could not parse message %p", msg); + return NULL; + } + + CONNMAN_SERVICE_TYPE_ITER(i) + { + cs = eina_hash_find(connman_services[i], path); + if (cs) break; + } + if (!cs) return NULL; + wn = eina_hash_find(connman_services_map[i], &cs); + EINA_SAFETY_ON_NULL_RETURN_VAL(wn, NULL); + wireless_authenticate_external(wn, url); + return NULL; +} + +static Eina_Bool +_connman_field_parse_value(Connman_Field *field, const char *key, Eldbus_Message_Iter *value, const char *signature) +{ + if (!strcmp(key, "Type")) + { + EINA_SAFETY_ON_FALSE_RETURN_VAL(signature[0] == 's', EINA_FALSE); + eldbus_message_iter_basic_get(value, &field->type); + return EINA_TRUE; + } + + if (!strcmp(key, "Requirement")) + { + const char *req; + const char *types[] = + { + [CONNMAN_FIELD_STATE_MANDATORY] = "mandatory", + [CONNMAN_FIELD_STATE_OPTIONAL] = "optional", + [CONNMAN_FIELD_STATE_ALTERNATE] = "alternate", + [CONNMAN_FIELD_STATE_INFO] = "informational", + }; + int i; + EINA_SAFETY_ON_FALSE_RETURN_VAL(signature[0] == 's', EINA_FALSE); + eldbus_message_iter_basic_get(value, &req); + for (i = 0; i <= CONNMAN_FIELD_STATE_INFO; i++) + if (!strcmp(req, types[i])) + { + field->requirement = i; + break; + } + return EINA_TRUE; + } + + if (!strcmp(key, "Alternates")) + { + EINA_SAFETY_ON_FALSE_RETURN_VAL(signature[0] == 'a', EINA_FALSE); + /* ignore alternates */ + return EINA_TRUE; + } + + if (!strcmp(key, "Value")) + { + EINA_SAFETY_ON_FALSE_RETURN_VAL(signature[0] == 's', EINA_FALSE); + eldbus_message_iter_basic_get(value, &field->value); + return EINA_TRUE; + } + + DBG("Ignored unknown argument: %s", key); + return EINA_FALSE; +} + +static Eina_Bool +_connman_field_parse(Connman_Field *field, Eldbus_Message_Iter *value, const char *signature EINA_UNUSED) +{ + Eldbus_Message_Iter *array, *dict; + + eldbus_message_iter_arguments_get(value, "a{sv}", &array); + EINA_SAFETY_ON_NULL_RETURN_VAL(array, EINA_FALSE); + + while (eldbus_message_iter_get_and_next(array, 'e', &dict)) + { + Eldbus_Message_Iter *var; + const char *key; + char *sig2; + + if (!eldbus_message_iter_arguments_get(dict, "sv", &key, &var)) + return EINA_FALSE; + sig2 = eldbus_message_iter_signature_get(var); + if (!sig2) + return EINA_FALSE; + + if (!_connman_field_parse_value(field, key, var, sig2)) + { + free(sig2); + return EINA_FALSE; + } + free(sig2); + } + + return EINA_TRUE; +} + +static void +_connman_dbus_dict_append_array(Eldbus_Message_Iter *array, const char *key, Eina_Array *val) +{ + Eldbus_Message_Iter *dict, *variant, *array2; + Eina_Stringshare *str; + unsigned int i; + Eina_Array_Iterator it; + + eldbus_message_iter_arguments_append(array, "{sv}", &dict); + eldbus_message_iter_basic_append(dict, 's', key); + variant = eldbus_message_iter_container_new(dict, 'v', "as"); + array2 = eldbus_message_iter_container_new(variant, 'a', "s"); + EINA_ARRAY_ITER_NEXT(val, i, str, it) + eldbus_message_iter_basic_append(array2, 's', str ?: ""); + eldbus_message_iter_container_close(variant, array2); + eldbus_message_iter_container_close(dict, variant); + eldbus_message_iter_container_close(array, dict); +} + +static void +_connman_dbus_dict_append_string(Eldbus_Message_Iter *array, const char *key, const char *val) +{ + Eldbus_Message_Iter *dict, *variant; + + eldbus_message_iter_arguments_append(array, "{sv}", &dict); + eldbus_message_iter_basic_append(dict, 's', key); + variant = eldbus_message_iter_container_new(dict, 'v', "s"); + eldbus_message_iter_basic_append(variant, 's', val ?: ""); + eldbus_message_iter_container_close(dict, variant); + eldbus_message_iter_container_close(array, dict); +} + +static void +_connman_dbus_dict_append_bool(Eldbus_Message_Iter *array, const char *key, Eina_Bool val) +{ + Eldbus_Message_Iter *dict, *variant; + + eldbus_message_iter_arguments_append(array, "{sv}", &dict); + eldbus_message_iter_basic_append(dict, 's', key); + variant = eldbus_message_iter_container_new(dict, 'v', "b"); + eldbus_message_iter_basic_append(variant, 'b', !!val); + eldbus_message_iter_container_close(dict, variant); + eldbus_message_iter_container_close(array, dict); +} + +static void +_connman_agent_auth_send(void *data, const Eina_Array *fields) +{ + Eldbus_Message *reply; + Eldbus_Message_Iter *iter, *array; + const char *f, *fprev; + unsigned int i; + Eina_Array_Iterator it; + + if (!fields) + { + reply = eldbus_message_error_new(data, + "net.connman.Agent.Error.Canceled", + "User canceled dialog"); + eldbus_connection_send(dbus_conn, reply, NULL, NULL, -1); + return; + } + reply = eldbus_message_method_return_new(data); + iter = eldbus_message_iter_get(reply); + eldbus_message_iter_arguments_append(iter, "a{sv}", &array); + + EINA_ARRAY_ITER_NEXT(fields, i, f, it) + { + if (i % 2) + _connman_dbus_dict_append_string(array, fprev, f); + else + fprev = f; + } + eldbus_message_iter_container_close(iter, array); + + eldbus_connection_send(dbus_conn, reply, NULL, NULL, -1); +} + +static Eldbus_Message * +_connman_agent_request_input(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg) +{ + Eldbus_Message_Iter *array, *dict; + const char *path; + Eina_Array *arr = NULL; + + if (!eldbus_message_arguments_get(msg, "oa{sv}", &path, &array)) + return eldbus_message_method_return_new(msg); + + /* FIXME: WISPr - net.connman.Agent.Error.LaunchBrowser */ + while (eldbus_message_iter_get_and_next(array, 'e', &dict)) + { + Eldbus_Message_Iter *var; + char *signature; + Connman_Field field = { NULL }; + + if (!eldbus_message_iter_arguments_get(dict, "sv", &field.name, &var)) + goto err; + signature = eldbus_message_iter_signature_get(var); + if (!signature) goto err; + + if (!_connman_field_parse(&field, var, signature)) + { + free(signature); + goto err; + } + free(signature); + + DBG("AGENT Got field:\n" + "\tName: %s\n" + "\tType: %s\n" + "\tRequirement: %d\n" + "\tAlternates: (omit array)\n" + "\tValue: %s", + field.name, field.type, field.requirement, field.value); + + if (field.requirement != CONNMAN_FIELD_STATE_MANDATORY) continue; + if (!arr) arr = eina_array_new(1); + eina_array_push(arr, eina_stringshare_add(field.name)); + } + wireless_authenticate(arr, _connman_agent_auth_send, eldbus_message_ref((Eldbus_Message *)msg)); + array_clear(arr); + return NULL; + +err: + eina_array_free(arr); + WRN("Failed to parse msg"); + return eldbus_message_method_return_new(msg); +} + +static Eldbus_Message * +_connman_agent_cancel(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg) +{ + Eldbus_Message *reply = eldbus_message_method_return_new(msg); + + DBG("Agent canceled"); + wireless_authenticate_cancel(); + + return reply; +} + +static const Eldbus_Method methods[] = { + { "Release", NULL, NULL, _connman_agent_release, 0 }, + { + "ReportError", ELDBUS_ARGS({"o", "service"}, {"s", "error"}), NULL, + _connman_agent_report_error, 0 + }, + //{ + //"ReportPeerError", ELDBUS_ARGS({"o", "peer"}, {"s", "error"}), NULL, + //_connman_agent_report_peer_error, 0 + //}, + { + "RequestBrowser", ELDBUS_ARGS({"o", "service"}, {"s", "url"}), NULL, + _connman_agent_request_browser, 0 + }, + { + "RequestInput", ELDBUS_ARGS({"o", "service"}, {"a{sv}", "fields"}), + ELDBUS_ARGS({"a{sv}", ""}), _connman_agent_request_input, 0 + }, + //{ + //"RequestPeerAuthorization", ELDBUS_ARGS({"o", "peer"}, {"a{sv}", "fields"}), + //ELDBUS_ARGS({"a{sv}", ""}), _connman_agent_request_peer_auth, 0 + //}, + { "Cancel", NULL, NULL, _connman_agent_cancel, 0 }, + { NULL, NULL, NULL, NULL, 0 } +}; + +static const Eldbus_Service_Interface_Desc desc = { + CONNMAN_AGENT_IFACE, methods, NULL, NULL, NULL, NULL +}; + +static void +_connman_start(void) +{ + Eldbus_Object *obj; + int i; + + CONNMAN_SERVICE_TYPE_ITER(i) + connman_services[i] = eina_hash_string_superfast_new((Eina_Free_Cb)_connman_service_free); + + obj = eldbus_object_get(dbus_conn, CONNMAN_BUS_NAME, "/"); + proxy_manager = eldbus_proxy_get(obj, CONNMAN_MANAGER_IFACE); + + signal_handlers = eina_list_append(signal_handlers, + eldbus_proxy_signal_handler_add(proxy_manager, "PropertyChanged", + _connman_manager_event_property, NULL)); + signal_handlers = eina_list_append(signal_handlers, + eldbus_proxy_signal_handler_add(proxy_manager, "ServicesChanged", + _connman_manager_event_services, NULL)); + + pending_gettechnologies = eldbus_proxy_call(proxy_manager, "GetTechnologies", _connman_manager_gettechnologies, + NULL, -1, ""); + pending_getproperties_manager = eldbus_proxy_call(proxy_manager, "GetProperties", _connman_manager_getproperties, + NULL, -1, ""); + + agent_iface = eldbus_service_interface_register(dbus_conn, CONNMAN_AGENT_PATH, &desc); + eldbus_proxy_call(proxy_manager, "RegisterAgent", + _connman_manager_agent_register, NULL, -1, "o", CONNMAN_AGENT_PATH); +} + +static void +_connman_end(void) +{ + int i; + + if (!proxy_manager) return; + eldbus_proxy_call(proxy_manager, "UnregisterAgent", NULL, NULL, -1, "o", CONNMAN_AGENT_PATH); + + CONNMAN_SERVICE_TYPE_ITER(i) + { + E_FREE_FUNC(connman_services[i], eina_hash_free); + if (!connman_technology[i].proxy) continue; + E_FREE_FUNC(connman_technology[i].proxy, _eldbus_proxy_del); + } + E_FREE_FUNC(pending_getservices, eldbus_pending_cancel); + E_FREE_FUNC(pending_getproperties_manager, eldbus_pending_cancel); + signal_handlers = eina_list_free(signal_handlers); + + E_FREE_FUNC(proxy_manager, _eldbus_proxy_del); + E_FREE_FUNC(agent_iface, eldbus_service_object_unregister); +} + +static void +_connman_name_owner_changed(void *data EINA_UNUSED, const char *bus EINA_UNUSED, const char *from EINA_UNUSED, const char *to) +{ + if (to[0]) + _connman_start(); + else + _connman_end(); +} + +EINTERN void +connman_init(void) +{ + int i; + + if (_connman_log_dom > -1) return; + CONNMAN_SERVICE_TYPE_ITER(i) + connman_technology[i].type = -1; + eldbus_name_owner_changed_callback_add(dbus_conn, CONNMAN_BUS_NAME, + _connman_name_owner_changed, + NULL, EINA_TRUE); + _connman_log_dom = eina_log_domain_register("wireless.connman", EINA_COLOR_ORANGE); +} + +EINTERN void +connman_shutdown(void) +{ + int i; + CONNMAN_SERVICE_TYPE_ITER(i) + { + E_FREE_FUNC(connman_services_map[i], eina_hash_free); + E_FREE(connman_current_connection[i]); + connman_current_service[i] = NULL; + } + _connman_end(); + eldbus_name_owner_changed_callback_del(dbus_conn, CONNMAN_BUS_NAME, _connman_name_owner_changed, NULL); + eina_log_domain_unregister(_connman_log_dom); + _connman_log_dom = -1; +} + +EINTERN void +connman_technology_enabled_set(Wireless_Service_Type type, Eina_Bool state) +{ + Eldbus_Message_Iter *main_iter, *var; + Eldbus_Message *msg; + + EINA_SAFETY_ON_NULL_RETURN(connman_technology[type].proxy); + msg = eldbus_proxy_method_call_new(connman_technology[type].proxy, "SetProperty"); + main_iter = eldbus_message_iter_get(msg); + eldbus_message_iter_basic_append(main_iter, 's', "Powered"); + var = eldbus_message_iter_container_new(main_iter, 'v', "b"); + eldbus_message_iter_basic_append(var, 'b', state); + eldbus_message_iter_container_close(main_iter, var); + + eldbus_proxy_send(connman_technology[type].proxy, msg, NULL, NULL, -1); +} + +static void +_connman_service_edit_timeservers_cb(void *data EINA_UNUSED, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED) +{ + const char *name, *text; + /* FIXME */ + if (eldbus_message_error_get(msg, &name, &text)) + { + ERR("Could not set properties. %s: %s", name, text); + } +} + +static void +_connman_service_edit_nameservers_cb(void *data EINA_UNUSED, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED) +{ + const char *name, *text; + /* FIXME */ + if (eldbus_message_error_get(msg, &name, &text)) + { + ERR("Could not set properties. %s: %s", name, text); + } +} + +static void +_connman_service_edit_domains_cb(void *data EINA_UNUSED, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED) +{ + const char *name, *text; + /* FIXME */ + if (eldbus_message_error_get(msg, &name, &text)) + { + ERR("Could not set properties. %s: %s", name, text); + } +} + +static void +_connman_service_edit_proxy_cb(void *data EINA_UNUSED, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED) +{ + const char *name, *text; + /* FIXME */ + if (eldbus_message_error_get(msg, &name, &text)) + { + ERR("Could not set properties. %s: %s", name, text); + } +} + +static void +_connman_service_edit_cb(void *data EINA_UNUSED, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED) +{ + const char *name, *text; + /* FIXME */ + if (eldbus_message_error_get(msg, &name, &text)) + { + ERR("Could not set properties. %s: %s", name, text); + } +} + +static void +_connman_service_remove_cb(void *data EINA_UNUSED, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED) +{ + const char *name, *text; + + if (eldbus_message_error_get(msg, &name, &text)) + ERR("Could not remove service. %s: %s", name, text); +} + +EINTERN void +connman_service_edit(const char *path, Wireless_Connection *wc) +{ + int i; + Eldbus_Message *msg; + Eldbus_Message_Iter *iter, *variant, *array; + Connman_Service *cs = NULL; + const char *prop[] = + { + "IPv4.Configuration", + "IPv6.Configuration", + }; + const char *method[] = + { + "off", + "manual", + "dhcp", + "fixed", + }; + + CONNMAN_SERVICE_TYPE_ITER(i) + { + cs = eina_hash_find(connman_services[i], path); + if (cs) break; + } + EINA_SAFETY_ON_NULL_RETURN(cs); + + msg = eldbus_proxy_method_call_new(cs->proxy, "SetProperty"); + iter = eldbus_message_iter_get(msg); + eldbus_message_iter_basic_append(iter, 's', prop[cs->ipv6]); + variant = eldbus_message_iter_container_new(iter, 'v', "a{sv}"); + eldbus_message_iter_arguments_append(variant, "a{sv}", &array); + _connman_dbus_dict_append_string(array, "Method", method[wc->method]); + _connman_dbus_dict_append_string(array, "Address", wc->address); + _connman_dbus_dict_append_string(array, "Gateway", wc->gateway); + if (wc->ipv6) + { + const char *privacy[] = + { + [WIRELESS_NETWORK_IPV6_PRIVACY_DISABLED] = "disabled", + [WIRELESS_NETWORK_IPV6_PRIVACY_ENABLED] = "enabled", + [WIRELESS_NETWORK_IPV6_PRIVACY_PREFERRED] = "preferred", + }; + _connman_dbus_dict_append_string(array, "PrefixLength", wc->ip.v6.prefixlength); + if (wc->method == WIRELESS_NETWORK_IPV6_METHOD_AUTO) + _connman_dbus_dict_append_string(array, "Privacy", privacy[wc->ip.v6.privacy]); + } + else + _connman_dbus_dict_append_string(array, "Netmask", wc->ip.v4.netmask); + eldbus_message_iter_container_close(variant, array); + eldbus_message_iter_container_close(iter, variant); + + eldbus_proxy_send(cs->proxy, msg, _connman_service_edit_cb, NULL, -1); +} + +EINTERN void +connman_service_edit_proxy(const char *path, Wireless_Connection *wc) +{ + int i; + Eldbus_Message *msg; + Eldbus_Message_Iter *iter, *variant, *array; + Connman_Service *cs = NULL; + const char *method[] = + { + "direct", + "manual", + "auto", + }; + + CONNMAN_SERVICE_TYPE_ITER(i) + { + cs = eina_hash_find(connman_services[i], path); + if (cs) break; + } + EINA_SAFETY_ON_NULL_RETURN(cs); + + msg = eldbus_proxy_method_call_new(cs->proxy, "SetProperty"); + iter = eldbus_message_iter_get(msg); + eldbus_message_iter_basic_append(iter, 's', "Proxy"); + variant = eldbus_message_iter_container_new(iter, 'v', "a{sv}"); + eldbus_message_iter_arguments_append(variant, "a{sv}", &array); + _connman_dbus_dict_append_string(array, "Method", method[wc->proxy_type]); + switch (wc->proxy_type) + { + case WIRELESS_PROXY_TYPE_DIRECT: break; + case WIRELESS_PROXY_TYPE_MANUAL: + _connman_dbus_dict_append_array(array, "Servers", wc->proxy_servers); + _connman_dbus_dict_append_array(array, "Excludes", wc->proxy_excludes); + break; + case WIRELESS_PROXY_TYPE_AUTO: + _connman_dbus_dict_append_string(array, "Address", wc->proxy_url); + break; + } + eldbus_message_iter_container_close(variant, array); + eldbus_message_iter_container_close(iter, variant); + + eldbus_proxy_send(cs->proxy, msg, _connman_service_edit_proxy_cb, NULL, -1); +} + +EINTERN void +connman_service_edit_domains(const char *path, Wireless_Connection *wc) +{ + int i; + Eldbus_Message *msg; + Eldbus_Message_Iter *iter; + Connman_Service *cs = NULL; + + CONNMAN_SERVICE_TYPE_ITER(i) + { + cs = eina_hash_find(connman_services[i], path); + if (cs) break; + } + EINA_SAFETY_ON_NULL_RETURN(cs); + + msg = eldbus_proxy_method_call_new(cs->proxy, "SetProperty"); + iter = eldbus_message_iter_get(msg); + _connman_dbus_dict_append_array(iter, "Domains.Configuration", wc->domain_servers); + + eldbus_proxy_send(cs->proxy, msg, _connman_service_edit_domains_cb, NULL, -1); +} + +EINTERN void +connman_service_edit_nameservers(const char *path, Wireless_Connection *wc) +{ + int i; + Eldbus_Message *msg; + Eldbus_Message_Iter *iter; + Connman_Service *cs = NULL; + + CONNMAN_SERVICE_TYPE_ITER(i) + { + cs = eina_hash_find(connman_services[i], path); + if (cs) break; + } + EINA_SAFETY_ON_NULL_RETURN(cs); + + msg = eldbus_proxy_method_call_new(cs->proxy, "SetProperty"); + iter = eldbus_message_iter_get(msg); + _connman_dbus_dict_append_array(iter, "Nameservers.Configuration", wc->name_servers); + + eldbus_proxy_send(cs->proxy, msg, _connman_service_edit_nameservers_cb, NULL, -1); +} + +EINTERN void +connman_service_edit_timeservers(const char *path, Wireless_Connection *wc) +{ + int i; + Eldbus_Message *msg; + Eldbus_Message_Iter *iter; + Connman_Service *cs = NULL; + + CONNMAN_SERVICE_TYPE_ITER(i) + { + cs = eina_hash_find(connman_services[i], path); + if (cs) break; + } + EINA_SAFETY_ON_NULL_RETURN(cs); + + msg = eldbus_proxy_method_call_new(cs->proxy, "SetProperty"); + iter = eldbus_message_iter_get(msg); + _connman_dbus_dict_append_array(iter, "Timeservers.Configuration", wc->time_servers); + + eldbus_proxy_send(cs->proxy, msg, _connman_service_edit_timeservers_cb, NULL, -1); +} + +EINTERN void +connman_service_remove(const char *path) +{ + int i; + Eldbus_Message *msg; + Connman_Service *cs = NULL; + + CONNMAN_SERVICE_TYPE_ITER(i) + { + cs = eina_hash_find(connman_services[i], path); + if (cs) break; + } + EINA_SAFETY_ON_NULL_RETURN(cs); + + msg = eldbus_proxy_method_call_new(cs->proxy, "Remove"); + eldbus_proxy_send(cs->proxy, msg, _connman_service_remove_cb, NULL, -1); +} + +EINTERN void +connman_airplane_mode_set(Eina_Bool set) +{ + Eldbus_Message *msg; + Eldbus_Message_Iter *iter; + + msg = eldbus_proxy_method_call_new(proxy_manager, "SetProperty"); + iter = eldbus_message_iter_get(msg); + _connman_dbus_dict_append_bool(iter, "OfflineMode", set); + eldbus_proxy_send(proxy_manager, msg, NULL, NULL, -1); +} diff --git a/src/modules/wireless/e-module-wireless.edj b/src/modules/wireless/e-module-wireless.edj new file mode 100644 index 0000000000000000000000000000000000000000..2b7ed6f679c56097d5b33130d47fbe59a64576cc GIT binary patch literal 21146 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 zZcount = 2; + msg->val[0] = state; + msg->val[1] = strength; + edje_object_message_send(elm_layout_edje_get(icon), EDJE_MESSAGE_INT_SET, 1, msg); +} + +static void +_wifi_icon_init(Evas_Object *icon, Wireless_Network *wn, int type) +{ + int state = 0, strength = 0; + + if (wn) + { + state = wn->state; + strength = wn->strength; + } + _wifi_icon_signal(icon, state, strength); + + if (!wn) + { + if (wireless_type_available[type]) + elm_object_signal_emit(icon, "e,state,default", "e"); + else + elm_object_signal_emit(icon, "e,state,error", "e"); + elm_object_signal_emit(icon, "e,state,unsecured", "e"); + return; + } + if (wn->state == WIRELESS_NETWORK_STATE_FAILURE) + { + elm_object_signal_emit(icon, "e,state,error", "e"); + return; + } + elm_object_signal_emit(icon, "e,state,default", "e"); + switch (wn->type) + { + case WIRELESS_SERVICE_TYPE_WIFI: + if (wn->security > WIRELESS_NETWORK_SECURITY_WEP) + elm_object_signal_emit(icon, "e,state,secure", "e"); + else if (wn->security == WIRELESS_NETWORK_SECURITY_WEP) + elm_object_signal_emit(icon, "e,state,insecure", "e"); + else if (!wn->security) + elm_object_signal_emit(icon, "e,state,unsecured", "e"); + break; + default: break; + } +} + +static void +_wireless_popup_toggle(void *data EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) +{ + connman_technology_enabled_set(wireless_popup.type, elm_check_state_get(obj)); +} + +static void +_wireless_popup_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Instance *inst = data; + inst->popup = 0; + E_FREE_FUNC(wireless_popup.items, eina_hash_free); + E_FREE_FUNC(wireless_popup.entries, eina_list_free); + eina_stringshare_replace(&wireless_popup.proxy_servers, NULL); + eina_stringshare_replace(&wireless_popup.proxy_excludes, NULL); + wireless_popup.box = NULL; + wireless_popup.content = NULL; + wireless_popup.popup = NULL; + wireless_popup.type = -1; +} + +static void +_wireless_edit_basic_entries_update(void) +{ + Eina_List *l; + Evas_Object *ent; + Eina_Bool disabled; + + if (wireless_edit[1]->ipv6) + disabled = wireless_edit[1]->method != WIRELESS_NETWORK_IPV6_METHOD_MANUAL; + else + disabled = wireless_edit[1]->method != WIRELESS_NETWORK_IPV4_METHOD_MANUAL; + EINA_LIST_FOREACH(wireless_popup.entries, l, ent) + elm_object_disabled_set(ent, disabled); +} + +static Evas_Object * +_wireless_popup_table_entry_row(Evas_Object *tb, const char *name, Evas_Smart_Cb cb, void *data, int *row) +{ + Evas_Object *fr, *entry; + + fr = elm_frame_add(tb); + evas_object_show(fr); + E_EXPAND(fr); + E_FILL(fr); + elm_object_text_set(fr, name); + elm_table_pack(tb, fr, 0, *row, 2, 2); + *row += 2; + + entry = elm_entry_add(tb); + evas_object_show(entry); + elm_entry_single_line_set(entry, 1); + elm_entry_scrollable_set(entry, 1); + evas_object_data_set(entry, "table", tb); + evas_object_smart_callback_add(entry, "activated", cb, data); + elm_object_content_set(fr, entry); + return entry; +} + +static void +_wireless_edit_entry_changed(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) +{ + Eina_Stringshare **str = data; + + eina_stringshare_replace(str, elm_entry_entry_get(obj)); +} + +static void +_wireless_gadget_edit_array_entry(Eina_Array *arr, Eina_Stringshare **ptr) +{ + Eina_Stringshare *str; + unsigned int i; + Eina_Array_Iterator it; + Eina_Strbuf *buf; + + if (!arr) return; + buf = eina_strbuf_new(); + EINA_ARRAY_ITER_NEXT(arr, i, str, it) + { + if (eina_strbuf_length_get(buf)) eina_strbuf_append(buf, ", "); + eina_strbuf_append(buf, str); + } + eina_stringshare_replace(ptr, eina_strbuf_string_get(buf)); + eina_strbuf_free(buf); +} + +static void +_wireless_gadget_edit_proxy_method_update(void) +{ + Evas_Object *ent, *tb = wireless_popup.content; + int row = 1; + Wireless_Connection *wc = wireless_edit[1]; + + evas_object_del(elm_table_child_get(wireless_popup.content, 0, 1)); + evas_object_del(elm_table_child_get(wireless_popup.content, 0, 3)); + evas_object_del(elm_table_child_get(wireless_popup.content, 0, 5)); + switch (wc->proxy_type) + { + case WIRELESS_PROXY_TYPE_DIRECT: + _wireless_popup_table_entry_row(tb, NULL, NULL, NULL, &row); + evas_object_hide(elm_table_child_get(wireless_popup.content, 0, 1)); + _wireless_popup_table_entry_row(tb, NULL, NULL, NULL, &row); + evas_object_hide(elm_table_child_get(wireless_popup.content, 0, 3)); + _wireless_popup_table_entry_row(tb, NULL, NULL, NULL, &row); + evas_object_hide(elm_table_child_get(wireless_popup.content, 0, 5)); + break; + case WIRELESS_PROXY_TYPE_MANUAL: + ent = _wireless_popup_table_entry_row(tb, _("Proxy Servers"), NULL, NULL, &row); + elm_entry_entry_set(ent, wireless_popup.proxy_servers); + evas_object_smart_callback_add(ent, "changed,user", _wireless_edit_entry_changed, &wireless_popup.proxy_servers); + ent = _wireless_popup_table_entry_row(tb, _("Proxy Excludes"), NULL, NULL, &row); + elm_entry_entry_set(ent, wireless_popup.proxy_excludes); + evas_object_smart_callback_add(ent, "changed,user", _wireless_edit_entry_changed, &wireless_popup.proxy_excludes); + _wireless_popup_table_entry_row(tb, NULL, NULL, NULL, &row); + evas_object_hide(elm_table_child_get(wireless_popup.content, 0, 5)); + break; + case WIRELESS_PROXY_TYPE_AUTO: + ent = _wireless_popup_table_entry_row(tb, _("Proxy Address"), NULL, NULL, &row); + elm_entry_entry_set(ent, wc->proxy_url); + evas_object_smart_callback_add(ent, "changed,user", _wireless_edit_entry_changed, &wireless_edit[1]->address); + _wireless_popup_table_entry_row(tb, NULL, NULL, NULL, &row); + evas_object_hide(elm_table_child_get(wireless_popup.content, 0, 3)); + _wireless_popup_table_entry_row(tb, NULL, NULL, NULL, &row); + evas_object_hide(elm_table_child_get(wireless_popup.content, 0, 5)); + break; + } +} + +static void +_wireless_gadget_edit_proxy_method(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info) +{ + wireless_edit[1]->proxy_type = (intptr_t)elm_object_item_data_get(event_info); + _wireless_gadget_edit_proxy_method_update(); +} + +static void +_wireless_gadget_edit_method(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info) +{ + wireless_edit[1]->method = (intptr_t)elm_object_item_data_get(event_info); + _wireless_edit_basic_entries_update(); +} + +static void +_wireless_gadget_edit_method_open(void *data EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) +{ + int i, fixed; + const char **methods; + + elm_hoversel_clear(obj); + evas_object_layer_set(obj, E_LAYER_MENU); + if (wireless_edit[1]->ipv6) + { + fixed = WIRELESS_NETWORK_IPV6_METHOD_FIXED; + methods = wireless_ipv6_methods; + } + else + { + fixed = WIRELESS_NETWORK_IPV6_METHOD_FIXED; + methods = wireless_ipv4_methods; + } + for (i = 0; i < fixed; i++) + { + if ((int)wireless_edit[1]->method != i) + elm_hoversel_item_add(obj, methods[i], NULL, ELM_ICON_NONE, NULL, (intptr_t*)(long)i); + } +} + +static void +_wireless_edit_del(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + int i; + + wireless_popup.entries = eina_list_free(wireless_popup.entries); + eina_stringshare_del(wireless_edit[0]->wn->path); + free(wireless_edit[0]->wn); + for (i = 0; i <= 1; i++) + { + eina_stringshare_del(wireless_edit[i]->address); + eina_stringshare_del(wireless_edit[i]->gateway); + if (wireless_edit[i]->ipv6) + eina_stringshare_del(wireless_edit[i]->ip.v6.prefixlength); + else + eina_stringshare_del(wireless_edit[i]->ip.v4.netmask); + eina_stringshare_del(wireless_edit[i]->proxy_url); + array_clear(wireless_edit[i]->proxy_excludes); + array_clear(wireless_edit[i]->proxy_servers); + E_FREE(wireless_edit[i]); + } + wireless_edit_popup = NULL; +} + +static Eina_Array * +string_to_array(const char *str) +{ + const char *p = str; + Eina_Array *arr; + + arr = eina_array_new(1); + do + { + const char *start, *end; + + start = p; + p = strchr(p, ','); + if (!p) break; + end = p - 1; + while (isspace(start[0])) start++; + while (isspace(end[0])) end--; + end++; + + if (start == end) break; + eina_array_push(arr, eina_stringshare_add_length(start, end - start)); + p++; + } while (p[0]); + return arr; +} + +static Eina_Bool +_wireless_array_notequal(Eina_Array *a, Eina_Array *b) +{ + unsigned int i; + + if ((!!a) != (!!b)) return EINA_TRUE; + if (eina_array_count(a) != eina_array_count(b)) return EINA_TRUE; + for (i = 0; i < eina_array_count(a); i++) + if (eina_array_data_get(a, i) != eina_array_data_get(b, i)) return EINA_TRUE; + return EINA_FALSE; +} + +static void +_wireless_edit_send() +{ + Eina_Bool basic = EINA_FALSE, proxy = EINA_FALSE; + + EINTERN void connman_service_edit(const char *path, Wireless_Connection *wc); + EINTERN void connman_service_edit_proxy(const char *path, Wireless_Connection *wc); + EINTERN void connman_service_edit_domains(const char *path, Wireless_Connection *wc); + EINTERN void connman_service_edit_nameservers(const char *path, Wireless_Connection *wc); + EINTERN void connman_service_edit_timeservers(const char *path, Wireless_Connection *wc); + + if (wireless_edit[0]->method == wireless_edit[1]->method) + { + if (wireless_edit[1]->ipv6) + switch (wireless_edit[1]->method) + { + case WIRELESS_NETWORK_IPV6_METHOD_AUTO: + basic = wireless_edit[0]->ip.v6.privacy != wireless_edit[1]->ip.v6.privacy; + break; + case WIRELESS_NETWORK_IPV6_METHOD_MANUAL: + basic = wireless_edit[0]->address != wireless_edit[1]->address; + if (basic) break; + basic = wireless_edit[0]->gateway != wireless_edit[1]->gateway; + if (basic) break; + basic = wireless_edit[0]->ip.v6.prefixlength != wireless_edit[1]->ip.v6.prefixlength; + break; + default: break; + } + else + switch (wireless_edit[1]->method) + { + case WIRELESS_NETWORK_IPV4_METHOD_MANUAL: + basic = wireless_edit[0]->address != wireless_edit[1]->address; + if (basic) break; + basic = wireless_edit[0]->gateway != wireless_edit[1]->gateway; + if (basic) break; + basic = wireless_edit[0]->ip.v4.netmask != wireless_edit[1]->ip.v4.netmask; + break; + default: break; + } + } + else + basic = EINA_TRUE; + + if (basic) + connman_service_edit(wireless_edit[1]->wn->path, wireless_edit[1]); + + if (wireless_edit[1]->proxy_type == WIRELESS_PROXY_TYPE_MANUAL) + { + array_clear(wireless_edit[1]->proxy_servers); + array_clear(wireless_edit[1]->proxy_excludes); + if (wireless_popup.proxy_servers) + wireless_edit[1]->proxy_servers = string_to_array(wireless_popup.proxy_servers); + if (wireless_popup.proxy_excludes) + wireless_edit[1]->proxy_excludes = string_to_array(wireless_popup.proxy_excludes); + } + if (wireless_edit[0]->proxy_type == wireless_edit[1]->proxy_type) + { + switch (wireless_edit[0]->proxy_type) + { + case WIRELESS_PROXY_TYPE_MANUAL: + proxy = _wireless_array_notequal(wireless_edit[0]->proxy_servers, + wireless_edit[1]->proxy_servers); + if (proxy) break; + proxy = _wireless_array_notequal(wireless_edit[0]->proxy_excludes, + wireless_edit[1]->proxy_excludes); + break; + case WIRELESS_PROXY_TYPE_AUTO: + proxy = wireless_edit[0]->proxy_url != wireless_edit[1]->proxy_url; + break; + break; + default: break; + } + + } + else + proxy = EINA_TRUE; + if (proxy) + connman_service_edit_proxy(wireless_edit[1]->wn->path, wireless_edit[1]); + + array_clear(wireless_edit[1]->domain_servers); + if (wireless_popup.domain_servers) + wireless_edit[1]->domain_servers = string_to_array(wireless_popup.domain_servers); + array_clear(wireless_edit[1]->name_servers); + if (wireless_popup.name_servers) + wireless_edit[1]->name_servers = string_to_array(wireless_popup.name_servers); + array_clear(wireless_edit[1]->name_servers); + if (wireless_popup.name_servers) + wireless_edit[1]->name_servers = string_to_array(wireless_popup.name_servers); + + if (_wireless_array_notequal(wireless_edit[0]->domain_servers, wireless_edit[1]->domain_servers)) + connman_service_edit_domains(wireless_edit[1]->wn->path, wireless_edit[1]); + if (_wireless_array_notequal(wireless_edit[0]->name_servers, wireless_edit[1]->name_servers)) + connman_service_edit_nameservers(wireless_edit[1]->wn->path, wireless_edit[1]); + if (_wireless_array_notequal(wireless_edit[0]->time_servers, wireless_edit[1]->time_servers)) + connman_service_edit_timeservers(wireless_edit[1]->wn->path, wireless_edit[1]); +} + +static void +_wireless_edit_send_button() +{ + e_comp_object_util_autoclose(NULL, NULL, NULL, NULL); + _wireless_edit_send(); +} + +static void +_wireless_edit_remove() +{ + EINTERN void connman_service_remove(const char *path); + e_comp_object_util_autoclose(NULL, NULL, NULL, NULL); + connman_service_remove(wireless_edit[1]->wn->path); +} + +static Eina_Bool +_wireless_edit_key(void *d EINA_UNUSED, Ecore_Event_Key *ev) +{ + if ((!strcmp(ev->key, "Return")) || (!strcmp(ev->key, "KP_Enter"))) + { + _wireless_edit_send(); + return EINA_FALSE; + } + return strcmp(ev->key, "Escape"); +} + +static void +_wireless_gadget_edit_proxy_method_open(void *data EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) +{ + int i; + + elm_hoversel_clear(obj); + for (i = 0; i <= WIRELESS_PROXY_TYPE_AUTO; i++) + { + if ((int)wireless_edit[1]->proxy_type != i) + elm_hoversel_item_add(obj, wireless_proxy_methods[i], NULL, ELM_ICON_NONE, NULL, (intptr_t*)(long)i); + } +} + +static void +_wireless_gadget_edit_proxy(void) +{ + Evas_Object *tb, *fr, *hoversel; + int row = 0; + Wireless_Connection *wc = wireless_edit[1]; + + wireless_popup.content = tb = elm_table_add(wireless_popup.popup); + E_FILL(tb); + E_EXPAND(tb); + evas_object_show(tb); + elm_box_pack_end(wireless_popup.box, tb); + + fr = elm_frame_add(tb); + E_EXPAND(fr); + E_FILL(fr); + evas_object_show(fr); + elm_object_text_set(fr, _("Proxy Type")); + elm_table_pack(tb, fr, 0, row++, 2, 1); + + hoversel = elm_hoversel_add(tb); + elm_hoversel_hover_parent_set(hoversel, wireless_popup.popup); + elm_hoversel_auto_update_set(hoversel, 1); + evas_object_show(hoversel); + elm_object_content_set(fr, hoversel); + evas_object_smart_callback_add(hoversel, "selected", _wireless_gadget_edit_proxy_method, NULL); + evas_object_smart_callback_add(hoversel, "clicked", _wireless_gadget_edit_proxy_method_open, NULL); + elm_object_text_set(hoversel, wireless_proxy_methods[wc->proxy_type]); + _wireless_gadget_edit_proxy_method_update(); +} + +static void +_wireless_gadget_edit_dnstime(void) +{ + Evas_Object *tb, *ent; + int row = 0; + + wireless_popup.content = tb = elm_table_add(wireless_popup.popup); + E_FILL(tb); + E_EXPAND(tb); + evas_object_show(tb); + elm_box_pack_end(wireless_popup.box, tb); + + ent = _wireless_popup_table_entry_row(tb, _("Nameservers"), NULL, NULL, &row); + elm_entry_entry_set(ent, wireless_popup.name_servers); + evas_object_smart_callback_add(ent, "changed,user", _wireless_edit_entry_changed, &wireless_popup.name_servers); + + ent = _wireless_popup_table_entry_row(tb, _("Timeservers"), NULL, NULL, &row); + elm_entry_entry_set(ent, wireless_popup.time_servers); + evas_object_smart_callback_add(ent, "changed,user", _wireless_edit_entry_changed, &wireless_popup.time_servers); + + ent = _wireless_popup_table_entry_row(tb, _("Search Domains"), NULL, NULL, &row); + elm_entry_entry_set(ent, wireless_popup.domain_servers); + evas_object_smart_callback_add(ent, "changed,user", _wireless_edit_entry_changed, &wireless_popup.domain_servers); + + _wireless_popup_table_entry_row(tb, NULL, NULL, NULL, &row); + evas_object_hide(elm_table_child_get(tb, 0, 6)); +} + +static Evas_Object * +_wireless_gadget_edit_basic(void) +{ + Evas_Object *tb, *fr, *hoversel, *ent, *entry; + Eina_Bool disabled; + int row = 0, fixed; + const char **methods; + Wireless_Connection *wc = wireless_edit[1]; + + wireless_popup.content = tb = elm_table_add(wireless_popup.box); + E_FILL(tb); + E_EXPAND(tb); + evas_object_show(tb); + elm_box_pack_end(wireless_popup.box, tb); + + fr = elm_frame_add(tb); + E_EXPAND(fr); + E_FILL(fr); + evas_object_show(fr); + elm_object_text_set(fr, _("Method")); + elm_table_pack(tb, fr, 0, row++, 2, 1); + + hoversel = elm_hoversel_add(tb); + elm_hoversel_hover_parent_set(hoversel, wireless_popup.popup); + elm_hoversel_auto_update_set(hoversel, 1); + evas_object_show(hoversel); + elm_object_content_set(fr, hoversel); + evas_object_smart_callback_add(hoversel, "selected", _wireless_gadget_edit_method, NULL); + if (wc->ipv6) + { + fixed = WIRELESS_NETWORK_IPV6_METHOD_FIXED; + methods = wireless_ipv6_methods; + } + else + { + fixed = WIRELESS_NETWORK_IPV6_METHOD_FIXED; + methods = wireless_ipv4_methods; + } + disabled = (int)wc->method == fixed; + elm_object_disabled_set(hoversel, disabled); + if (disabled) + elm_hoversel_item_add(hoversel, _("Fixed"), NULL, ELM_ICON_NONE, NULL, NULL); + else + { + elm_object_text_set(hoversel, methods[wc->method]); + evas_object_smart_callback_add(hoversel, "clicked", _wireless_gadget_edit_method_open, NULL); + } + + ent = entry = _wireless_popup_table_entry_row(tb, _("Address"), NULL, NULL, &row); + elm_object_disabled_set(ent, disabled); + wireless_popup.entries = eina_list_append(wireless_popup.entries, ent); + elm_entry_entry_set(ent, wc->address); + evas_object_smart_callback_add(ent, "changed,user", _wireless_edit_entry_changed, &wireless_edit[1]->address); + if (wc->ipv6) + { + ent = _wireless_popup_table_entry_row(tb, _("PrefixLength"), NULL, NULL, &row); + elm_entry_entry_set(ent, wc->ip.v6.prefixlength); + evas_object_smart_callback_add(ent, "changed,user", _wireless_edit_entry_changed, &wireless_edit[1]->ip.v6.prefixlength); + } + else + { + ent = _wireless_popup_table_entry_row(tb, _("Netmask"), NULL, NULL, &row); + elm_entry_entry_set(ent, wc->ip.v4.netmask); + evas_object_smart_callback_add(ent, "changed,user", _wireless_edit_entry_changed, &wireless_edit[1]->ip.v4.netmask); + } + elm_object_disabled_set(ent, disabled); + wireless_popup.entries = eina_list_append(wireless_popup.entries, ent); + ent = _wireless_popup_table_entry_row(tb, _("Gateway"), NULL, NULL, &row); + elm_entry_entry_set(ent, wc->gateway); + elm_object_disabled_set(ent, disabled); + evas_object_smart_callback_add(ent, "changed,user", _wireless_edit_entry_changed, &wireless_edit[1]->gateway); + wireless_popup.entries = eina_list_append(wireless_popup.entries, ent); + _wireless_edit_basic_entries_update(); + + return entry; +} + +static void +_wireless_gadget_edit_select_pre(void) +{ + elm_box_unpack(wireless_popup.box, wireless_popup.content); + evas_object_del(wireless_popup.content); + wireless_popup.entries = eina_list_free(wireless_popup.entries); +} + +static void +_wireless_gadget_edit_select_basic(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + _wireless_gadget_edit_select_pre(); + _wireless_gadget_edit_basic(); +} + +static void +_wireless_gadget_edit_select_proxy(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + _wireless_gadget_edit_select_pre(); + _wireless_gadget_edit_proxy(); +} + +static void +_wireless_gadget_edit_select_dnstime(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + _wireless_gadget_edit_select_pre(); + _wireless_gadget_edit_dnstime(); +} + +static void +_wireless_gadget_edit(int type) +{ + Evas_Object *popup, *entry, *box1, *box, *list, *lbl, *bt; + Elm_Object_Item *it; + Eina_Bool disabled; + int i; + char buf[1024] = {0}; + Wireless_Connection *wc = wireless_current[type]; + Wireless_Network *wn; + + if (!wc) return; + wireless_edit[0] = E_NEW(Wireless_Connection, 1); + wireless_edit[1] = E_NEW(Wireless_Connection, 1); + wn = E_NEW(Wireless_Network, 1); + wn->path = eina_stringshare_ref(wc->wn->path); + for (i = 0; i <= 1; i++) + { + Eina_Array *arrays[] = + { wc->domain_servers, wc->name_servers, wc->time_servers, wc->proxy_servers, + wc->proxy_excludes, NULL }; + Eina_Array **arrays2[] = + { &wireless_edit[i]->domain_servers, &wireless_edit[i]->name_servers, + &wireless_edit[i]->time_servers, &wireless_edit[i]->proxy_servers, + &wireless_edit[i]->proxy_excludes, NULL }; + unsigned int ii; + + wireless_edit[i]->wn = wn; + wireless_edit[i]->method = wc->method; + wireless_edit[i]->address = eina_stringshare_ref(wc->address); + wireless_edit[i]->gateway = eina_stringshare_ref(wc->gateway); + wireless_edit[i]->ipv6 = wc->ipv6; + if (wc->ipv6) + { + wireless_edit[i]->ip.v6.prefixlength = eina_stringshare_ref(wc->ip.v6.prefixlength); + wireless_edit[i]->ip.v6.privacy = wc->ip.v6.privacy; + } + else + wireless_edit[i]->ip.v4.netmask = eina_stringshare_ref(wc->ip.v4.netmask); + wireless_edit[i]->proxy_type = wc->proxy_type; + wireless_edit[i]->proxy_url = eina_stringshare_ref(wc->proxy_url); + /* fuuuuck thiiiiiiis */ + for (ii = 0; ii < EINA_C_ARRAY_LENGTH(arrays); ii++) + { + unsigned int iii; + Eina_Stringshare *str; + Eina_Array_Iterator itr; + + if (!arrays[ii]) continue; + *arrays2[ii] = eina_array_new(eina_array_count(arrays[ii])); + EINA_ARRAY_ITER_NEXT(arrays[ii], iii, str, itr) + eina_array_push(*arrays2[ii], eina_stringshare_ref(str)); + } + } + _wireless_gadget_edit_array_entry(wc->domain_servers, &wireless_popup.domain_servers); + _wireless_gadget_edit_array_entry(wc->name_servers, &wireless_popup.name_servers); + _wireless_gadget_edit_array_entry(wc->time_servers, &wireless_popup.time_servers); + _wireless_gadget_edit_array_entry(wc->proxy_servers, &wireless_popup.proxy_servers); + _wireless_gadget_edit_array_entry(wc->proxy_excludes, &wireless_popup.proxy_excludes); + + wireless_popup.popup = popup = elm_popup_add(e_comp->elm); + evas_object_layer_set(popup, E_LAYER_MENU); + elm_popup_allow_events_set(popup, 1); + elm_popup_scrollable_set(popup, 1); + + box = elm_box_add(popup); + E_EXPAND(box); + E_FILL(box); + evas_object_show(box); + elm_object_content_set(popup, box); + + lbl = elm_label_add(box); + elm_object_style_set(lbl, "marker"); + evas_object_show(lbl); + if (wireless_popup.type == WIRELESS_SERVICE_TYPE_ETHERNET) + strncpy(buf, _("Edit Connection Details: Ethernet"), sizeof(buf) - 1); + else + snprintf(buf, sizeof(buf), "%s: %s", _("Edit Connection Details"), wc->wn->name); + elm_object_text_set(lbl, buf); + elm_box_pack_end(box, lbl); + + wireless_popup.box = box1 = elm_box_add(popup); + E_EXPAND(box1); + E_FILL(box1); + elm_box_horizontal_set(box1, 1); + evas_object_show(box1); + elm_box_pack_end(box, box1); + + list = elm_list_add(box1); + E_ALIGN(list, 0, EVAS_HINT_FILL); + E_WEIGHT(list, 0, EVAS_HINT_EXPAND); + elm_box_pack_end(box1, list); + elm_list_select_mode_set(list, ELM_OBJECT_SELECT_MODE_ALWAYS); + elm_scroller_content_min_limit(list, 1, 1); + + entry = _wireless_gadget_edit_basic(); + it = elm_list_item_append(list, _("Basic"), NULL, NULL, _wireless_gadget_edit_select_basic, NULL); + elm_list_item_selected_set(it, 1); + elm_list_item_append(list, _("Proxy"), NULL, NULL, _wireless_gadget_edit_select_proxy, NULL); + elm_list_item_append(list, _("DNS/Time"), NULL, NULL, _wireless_gadget_edit_select_dnstime, NULL); + elm_list_go(list); + evas_object_show(list); + + if (wc->ipv6) + disabled = wc->method == WIRELESS_NETWORK_IPV4_METHOD_FIXED; + else + disabled = wc->method == WIRELESS_NETWORK_IPV6_METHOD_FIXED; + if (!disabled) + { + bt = elm_button_add(box); + E_EXPAND(bt); + E_FILL(bt); + evas_object_show(bt); + elm_object_text_set(bt, _("Deal with it")); + evas_object_smart_callback_add(bt, "clicked", _wireless_edit_send_button, NULL); + elm_box_pack_end(box, bt); + + bt = elm_button_add(box); + E_EXPAND(bt); + E_FILL(bt); + evas_object_show(bt); + elm_object_text_set(bt, _("Forget Network")); + evas_object_smart_callback_add(bt, "clicked", _wireless_edit_remove, NULL); + elm_box_pack_end(box, bt); + } + wireless_edit_popup = e_comp_object_util_add(popup, E_COMP_OBJECT_TYPE_NONE); + evas_object_layer_set(wireless_edit_popup, E_LAYER_POPUP); + evas_object_resize(wireless_edit_popup, e_zone_current_get()->w / 3, e_zone_current_get()->h / 2); + e_comp_object_util_center(wireless_edit_popup); + evas_object_show(wireless_edit_popup); + e_comp_object_util_autoclose(wireless_edit_popup, NULL, _wireless_edit_key, NULL); + evas_object_event_callback_add(wireless_edit_popup, EVAS_CALLBACK_DEL, _wireless_edit_del, NULL); + elm_object_focus_set(entry, 1); +} + +static void +_wireless_popup_network_click(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Wireless_Network *wn = data; + + if ((wn->state == WIRELESS_NETWORK_STATE_CONNECTED) || (wn->state == WIRELESS_NETWORK_STATE_ONLINE)) + { + int type = wireless_popup.type; + + evas_object_hide(wireless_popup.popup); + evas_object_del(wireless_popup.popup); + _wireless_gadget_edit(type); + } + else + { + /* FIXME */ + if (!wn->connect_cb(wn)) + {} + } +} + +static void +_wireless_popup_list_populate(void) +{ + Eina_Iterator *it; + Wireless_Network *wn; + + if (!wireless_networks) return; + it = eina_array_iterator_new(wireless_networks); + EINA_ITERATOR_FOREACH(it, wn) + { + Evas_Object *icon; + Elm_Object_Item *item; + const char *name = wn->name; + + if (wn->type != wireless_popup.type) continue; + icon = elm_layout_add(wireless_popup.content); + e_theme_edje_object_set(icon, NULL, wireless_theme_groups[wireless_popup.type]); + _wifi_icon_init(icon, wn, wn->type); + if (!name) + name = _("