forked from enlightenment/efl
1234 lines
38 KiB
C
1234 lines
38 KiB
C
#ifdef HAVE_CONFIG_H
|
|
# include <config.h>
|
|
#endif
|
|
|
|
#include "Ecore.h"
|
|
#include "Ecore_Con.h"
|
|
#include "ecore_con_private.h"
|
|
#include "efl_net-connman.h"
|
|
|
|
typedef struct
|
|
{
|
|
/* Eldbus_Proxy/Eldbus_Object keeps a list of pending calls, but
|
|
* they are reference counted singletons and will only cancel
|
|
* pending calls when everything is gone. However we operate on
|
|
* our private data, that may be gone before other refs. So
|
|
* keep the pending list.
|
|
*/
|
|
Eina_List *pending;
|
|
Eina_List *signal_handlers;
|
|
Eina_List *technologies;
|
|
Eina_List *access_points;
|
|
Eldbus_Service_Interface *agent; /* net.connman.Agent */
|
|
Eldbus_Pending *agent_pending;
|
|
struct {
|
|
Eldbus_Message *msg;
|
|
} agent_request_input;
|
|
Efl_Net_Control_State state;
|
|
Eina_Bool radios_offline;
|
|
Eina_Bool operating; /* connman exists */
|
|
Eina_Bool agent_enabled;
|
|
struct {
|
|
unsigned char radios_offline; /* 0xff = not requested */
|
|
Eldbus_Pending *radios_offline_pending;
|
|
} request;
|
|
} Efl_Net_Control_Data;
|
|
|
|
#define MY_CLASS EFL_NET_CONTROL_CLASS
|
|
|
|
static void _efl_net_control_agent_enabled_set(Eo *o, Efl_Net_Control_Data *pd, Eina_Bool agent_enabled);
|
|
|
|
static Eo *
|
|
_efl_net_control_technology_find(const Efl_Net_Control_Data *pd, const char *path)
|
|
{
|
|
const Eina_List *n;
|
|
Eo *child;
|
|
|
|
EINA_LIST_FOREACH(pd->technologies, n, child)
|
|
{
|
|
Eina_Stringshare *cp = efl_net_connman_technology_path_get(child);
|
|
if (strcmp(path, cp) == 0)
|
|
return child;
|
|
}
|
|
|
|
WRN("technology path='%s' not found!", path);
|
|
return NULL;
|
|
}
|
|
|
|
static Eo *
|
|
_efl_net_control_access_point_find(const Efl_Net_Control_Data *pd, const char *path)
|
|
{
|
|
const Eina_List *n;
|
|
Eo *child;
|
|
|
|
EINA_LIST_FOREACH(pd->access_points, n, child)
|
|
{
|
|
Eina_Stringshare *cp = efl_net_connman_access_point_path_get(child);
|
|
if (strcmp(path, cp) == 0)
|
|
return child;
|
|
}
|
|
|
|
DBG("access_point path='%s' not found!", path);
|
|
return NULL;
|
|
}
|
|
|
|
static Eldbus_Message *
|
|
_efl_net_control_agent_release(const Eldbus_Service_Interface *service, const Eldbus_Message *msg)
|
|
{
|
|
Eo *o = eldbus_service_object_data_get(service, "efl_net");
|
|
Efl_Net_Control_Data *pd = efl_data_scope_get(o, MY_CLASS);
|
|
|
|
DBG("Agent %p is released %s", o, eldbus_message_path_get(msg));
|
|
EINA_SAFETY_ON_NULL_GOTO(o, end);
|
|
EINA_SAFETY_ON_NULL_GOTO(pd, end);
|
|
|
|
pd->agent_enabled = EINA_FALSE;
|
|
efl_event_callback_call(o, EFL_NET_CONTROL_EVENT_AGENT_RELEASED, NULL);
|
|
|
|
end:
|
|
return eldbus_message_method_return_new(msg);
|
|
}
|
|
|
|
static Eldbus_Message *
|
|
_efl_net_control_agent_cancel(const Eldbus_Service_Interface *service, const Eldbus_Message *msg)
|
|
{
|
|
Eo *o = eldbus_service_object_data_get(service, "efl_net");
|
|
Efl_Net_Control_Data *pd = efl_data_scope_get(o, MY_CLASS);
|
|
Eldbus_Message *reply;
|
|
|
|
DBG("Agent %p request canceled %s", o, eldbus_message_path_get(msg));
|
|
EINA_SAFETY_ON_NULL_GOTO(o, end);
|
|
EINA_SAFETY_ON_NULL_GOTO(pd, end);
|
|
|
|
if (!pd->agent_request_input.msg) goto end;
|
|
|
|
reply = eldbus_message_error_new(pd->agent_request_input.msg,
|
|
"net.connman.Error.Canceled",
|
|
"Cancel requested.");
|
|
eldbus_connection_send(efl_net_connman_connection_get(), reply, NULL, NULL, -1.0);
|
|
eldbus_message_unref(pd->agent_request_input.msg);
|
|
pd->agent_request_input.msg = NULL;
|
|
|
|
end:
|
|
return eldbus_message_method_return_new(msg);
|
|
}
|
|
|
|
static const char *
|
|
_efl_net_control_agent_entry_type_get(Eldbus_Message_Iter *dict)
|
|
{
|
|
Eldbus_Message_Iter *array, *entry;
|
|
|
|
if (!eldbus_message_iter_arguments_get(dict, "a{sv}", &array))
|
|
{
|
|
ERR("Expected dict, got %s", eldbus_message_iter_signature_get(dict));
|
|
return NULL;
|
|
}
|
|
|
|
while (eldbus_message_iter_get_and_next(array, 'e', &entry))
|
|
{
|
|
Eldbus_Message_Iter *var;
|
|
const char *key, *c;
|
|
if (!eldbus_message_iter_arguments_get(entry, "sv", &key, &var))
|
|
{
|
|
ERR("Expected dict entry, got %s", eldbus_message_iter_signature_get(entry));
|
|
continue;
|
|
}
|
|
|
|
if (!eldbus_message_iter_arguments_get(var, "s", &c))
|
|
{
|
|
ERR("Expected string, got %s", eldbus_message_iter_signature_get(var));
|
|
continue;
|
|
}
|
|
|
|
if (strcmp(key, "Type") == 0)
|
|
return c;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static Efl_Net_Control_Agent_Request_Input_Information *
|
|
_efl_net_control_agent_informational_get(const char *name, Eldbus_Message_Iter *dict)
|
|
{
|
|
Eldbus_Message_Iter *array, *entry;
|
|
Eina_Bool is_informational = EINA_FALSE;
|
|
const char *value = NULL;
|
|
|
|
if (!eldbus_message_iter_arguments_get(dict, "a{sv}", &array))
|
|
{
|
|
ERR("Expected dict, got %s", eldbus_message_iter_signature_get(dict));
|
|
return NULL;
|
|
}
|
|
|
|
while (eldbus_message_iter_get_and_next(array, 'e', &entry))
|
|
{
|
|
Eldbus_Message_Iter *var;
|
|
const char *key, *c;
|
|
if (!eldbus_message_iter_arguments_get(entry, "sv", &key, &var))
|
|
{
|
|
ERR("Expected dict entry, got %s", eldbus_message_iter_signature_get(entry));
|
|
continue;
|
|
}
|
|
|
|
if (!eldbus_message_iter_arguments_get(var, "s", &c))
|
|
{
|
|
ERR("Expected string, got %s", eldbus_message_iter_signature_get(var));
|
|
continue;
|
|
}
|
|
|
|
if (strcmp(key, "Requirement") == 0)
|
|
{
|
|
if (strcmp(c, "informational") == 0)
|
|
is_informational = EINA_TRUE;
|
|
}
|
|
else if (strcmp(key, "Value") == 0)
|
|
value = c;
|
|
else if (strcmp(key, "Alternates") == 0)
|
|
{ }
|
|
else if (strcmp(key, "Type") == 0)
|
|
{ }
|
|
else WRN("Unknown key '%s' for requested input entry %s", key, name);
|
|
}
|
|
|
|
if (is_informational && value)
|
|
{
|
|
Efl_Net_Control_Agent_Request_Input_Information *info;
|
|
info = calloc(1, sizeof(*info));
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(info, NULL);
|
|
info->name = name;
|
|
info->value = value;
|
|
DBG("Field %s=%s is informational", name, value);
|
|
return info;
|
|
}
|
|
|
|
DBG("Field %s=%s is not informational", name, value);
|
|
return NULL;
|
|
}
|
|
|
|
static Eldbus_Message *
|
|
_efl_net_control_agent_request_input(const Eldbus_Service_Interface *service, const Eldbus_Message *msg)
|
|
{
|
|
Eo *o = eldbus_service_object_data_get(service, "efl_net");
|
|
Efl_Net_Control_Data *pd = efl_data_scope_get(o, MY_CLASS);
|
|
Efl_Net_Control_Agent_Request_Input event = { };
|
|
Efl_Net_Control_Agent_Request_Input_Information *info;
|
|
Eldbus_Message_Iter *array, *entry;
|
|
const char *path;
|
|
|
|
DBG("Agent %p requested input %s", o, eldbus_message_path_get(msg));
|
|
EINA_SAFETY_ON_NULL_GOTO(o, err);
|
|
EINA_SAFETY_ON_NULL_GOTO(pd, err);
|
|
|
|
if (pd->agent_request_input.msg)
|
|
{
|
|
Eldbus_Message *reply = eldbus_message_error_new(pd->agent_request_input.msg,
|
|
"net.connman.Error.OperationAborted",
|
|
"Received new input request, aborting previous.");
|
|
eldbus_connection_send(efl_net_connman_connection_get(), reply, NULL, NULL, -1.0);
|
|
eldbus_message_unref(pd->agent_request_input.msg);
|
|
pd->agent_request_input.msg = NULL;
|
|
}
|
|
|
|
if (!eldbus_message_arguments_get(msg, "oa{sv}", &path, &array))
|
|
goto err;
|
|
|
|
event.access_point = _efl_net_control_access_point_find(pd, path);
|
|
|
|
while (eldbus_message_iter_get_and_next(array, 'e', &entry))
|
|
{
|
|
Eldbus_Message_Iter *var;
|
|
const char *name;
|
|
if (!eldbus_message_iter_arguments_get(entry, "sv", &name, &var))
|
|
goto err;
|
|
|
|
if (strcmp(name, "Name") == 0)
|
|
event.fields |= EFL_NET_CONTROL_AGENT_REQUEST_INPUT_FIELD_NAME;
|
|
else if (strcmp(name, "SSID") == 0)
|
|
event.fields |= EFL_NET_CONTROL_AGENT_REQUEST_INPUT_FIELD_SSID;
|
|
else if (strcmp(name, "WPS") == 0)
|
|
event.fields |= EFL_NET_CONTROL_AGENT_REQUEST_INPUT_FIELD_WPS;
|
|
else if ((strcmp(name, "Identity") == 0) ||
|
|
(strcmp(name, "Username") == 0))
|
|
event.fields |= EFL_NET_CONTROL_AGENT_REQUEST_INPUT_FIELD_USERNAME;
|
|
else if ((strcmp(name, "Passphrase") == 0) ||
|
|
(strcmp(name, "Password") == 0))
|
|
{
|
|
const char *value = _efl_net_control_agent_entry_type_get(var);
|
|
if ((!event.passphrase_type) && (value))
|
|
event.passphrase_type = value;
|
|
event.fields |= EFL_NET_CONTROL_AGENT_REQUEST_INPUT_FIELD_PASSPHRASE;
|
|
}
|
|
else
|
|
{
|
|
info = _efl_net_control_agent_informational_get(name, var);
|
|
if (info)
|
|
event.informational = eina_list_append(event.informational, info);
|
|
else
|
|
WRN("Unknown field name '%s'", name);
|
|
}
|
|
}
|
|
|
|
pd->agent_request_input.msg = eldbus_message_ref((Eldbus_Message *)msg);
|
|
efl_event_callback_call(o, EFL_NET_CONTROL_EVENT_AGENT_REQUEST_INPUT, &event);
|
|
|
|
EINA_LIST_FREE(event.informational, info) free(info);
|
|
|
|
return NULL; /* reply later */
|
|
|
|
err:
|
|
return eldbus_message_method_return_new(msg);
|
|
}
|
|
|
|
static Eldbus_Message *
|
|
_efl_net_control_agent_report_error(const Eldbus_Service_Interface *service, const Eldbus_Message *msg)
|
|
{
|
|
Eo *o = eldbus_service_object_data_get(service, "efl_net");
|
|
Efl_Net_Control_Data *pd = efl_data_scope_get(o, MY_CLASS);
|
|
const char *path, *err_msg;
|
|
Efl_Net_Control_Agent_Error event = { };
|
|
|
|
if (!eldbus_message_arguments_get(msg, "os", &path, &err_msg))
|
|
{
|
|
ERR("Invalid net.connman.ReportError signature=%s", eldbus_message_signature_get(msg));
|
|
goto end;
|
|
}
|
|
|
|
DBG("Agent %p error %s: %s", o, path, err_msg);
|
|
|
|
EINA_SAFETY_ON_NULL_GOTO(o, end);
|
|
EINA_SAFETY_ON_NULL_GOTO(pd, end);
|
|
|
|
event.access_point = _efl_net_control_access_point_find(pd, path);
|
|
event.message = err_msg;
|
|
|
|
efl_event_callback_call(o, EFL_NET_CONTROL_EVENT_AGENT_ERROR, &event);
|
|
|
|
end:
|
|
return eldbus_message_method_return_new(msg);
|
|
}
|
|
|
|
static Eldbus_Message *
|
|
_efl_net_control_agent_request_browser(const Eldbus_Service_Interface *service, const Eldbus_Message *msg)
|
|
{
|
|
Eo *o = eldbus_service_object_data_get(service, "efl_net");
|
|
Efl_Net_Control_Data *pd = efl_data_scope_get(o, MY_CLASS);
|
|
const char *path, *url;
|
|
Efl_Net_Control_Agent_Browser_Url event = { };
|
|
|
|
if (!eldbus_message_arguments_get(msg, "os", &path, &url))
|
|
{
|
|
ERR("Invalid net.connman.RequestBrowser signature=%s", eldbus_message_signature_get(msg));
|
|
goto end;
|
|
}
|
|
|
|
DBG("Agent %p browser %s: %s", o, path, url);
|
|
|
|
EINA_SAFETY_ON_NULL_GOTO(o, end);
|
|
EINA_SAFETY_ON_NULL_GOTO(pd, end);
|
|
|
|
event.access_point = _efl_net_control_access_point_find(pd, path);
|
|
event.url = url;
|
|
|
|
efl_event_callback_call(o, EFL_NET_CONTROL_EVENT_AGENT_BROWSER_URL, &event);
|
|
|
|
end:
|
|
return eldbus_message_method_return_new(msg);
|
|
}
|
|
|
|
static Eldbus_Message *
|
|
_efl_net_control_agent_report_peer_error(const Eldbus_Service_Interface *service, const Eldbus_Message *msg)
|
|
{
|
|
Eo *o = eldbus_service_object_data_get(service, "efl_net");
|
|
const char *path, *err_msg;
|
|
|
|
if (!eldbus_message_arguments_get(msg, "os", &path, &err_msg))
|
|
{
|
|
ERR("Invalid net.connman.ReportPeerError signature=%s", eldbus_message_signature_get(msg));
|
|
goto end;
|
|
}
|
|
|
|
DBG("Agent %p peer error %s: %s", o, path, err_msg);
|
|
|
|
end:
|
|
return eldbus_message_method_return_new(msg);
|
|
}
|
|
|
|
|
|
static Eldbus_Message *
|
|
_efl_net_control_agent_request_peer_authorization(const Eldbus_Service_Interface *service, const Eldbus_Message *msg)
|
|
{
|
|
Eo *o = eldbus_service_object_data_get(service, "efl_net");
|
|
DBG("Agent %p peer authorization required", o);
|
|
return eldbus_message_method_return_new(msg);
|
|
}
|
|
|
|
static const Eldbus_Service_Interface_Desc _efl_net_control_agent_desc = {
|
|
.interface = "net.connman.Agent",
|
|
.methods = (const Eldbus_Method []){
|
|
{
|
|
.member = "Release",
|
|
.cb = _efl_net_control_agent_release,
|
|
},
|
|
{
|
|
.member = "ReportError",
|
|
.in = ELDBUS_ARGS({"o", "service"}, {"s", "message"}),
|
|
.cb = _efl_net_control_agent_report_error,
|
|
},
|
|
{
|
|
.member = "RequestBrowser",
|
|
.in = ELDBUS_ARGS({"o", "service"}, {"s", "url"}),
|
|
.cb = _efl_net_control_agent_request_browser,
|
|
},
|
|
{
|
|
.member = "RequestInput",
|
|
.in = ELDBUS_ARGS({"o", "service"}, {"a{sv}", "fields"}),
|
|
.cb = _efl_net_control_agent_request_input,
|
|
},
|
|
{
|
|
.member = "Cancel",
|
|
.cb = _efl_net_control_agent_cancel,
|
|
},
|
|
{
|
|
.member = "ReportPeerError",
|
|
.in = ELDBUS_ARGS({"o", "peer"}, {"s", "message"}),
|
|
.cb = _efl_net_control_agent_report_peer_error,
|
|
},
|
|
{
|
|
.member = "RequestPeerAuthorization",
|
|
.in = ELDBUS_ARGS({"o", "peer"}, {"a{sv}", "fields"}),
|
|
.cb = _efl_net_control_agent_request_peer_authorization,
|
|
},
|
|
{ }
|
|
},
|
|
};
|
|
|
|
static void
|
|
_efl_net_control_technology_added_internal(Eo *o, Efl_Net_Control_Data *pd, Eldbus_Message_Iter *itr)
|
|
{
|
|
const char *path;
|
|
Eldbus_Message_Iter *array;
|
|
Eo *child;
|
|
|
|
if (!eldbus_message_iter_arguments_get(itr, "oa{sv}", &path, &array))
|
|
{
|
|
ERR("could not get technology path or properties, signature=%s", eldbus_message_iter_signature_get(itr));
|
|
return;
|
|
}
|
|
|
|
child = efl_net_connman_technology_new(o, path, array);
|
|
if (!child)
|
|
{
|
|
ERR("could not create technology for path=%s", path);
|
|
return;
|
|
}
|
|
|
|
pd->technologies = eina_list_append(pd->technologies, child);
|
|
DBG("Technology Added Path=%s", path);
|
|
efl_event_callback_call(o, EFL_NET_CONTROL_EVENT_TECHNOLOGY_ADD, child);
|
|
}
|
|
|
|
static void
|
|
_efl_net_control_technology_added(void *data, const Eldbus_Message *msg)
|
|
{
|
|
Eo *o = data;
|
|
Efl_Net_Control_Data *pd = efl_data_scope_get(o, MY_CLASS);
|
|
Eldbus_Message_Iter *itr = eldbus_message_iter_get(msg);
|
|
_efl_net_control_technology_added_internal(o, pd, itr);
|
|
}
|
|
|
|
static void
|
|
_efl_net_control_technology_removed(void *data, const Eldbus_Message *msg)
|
|
{
|
|
Eo *o = data;
|
|
Efl_Net_Control_Data *pd = efl_data_scope_get(o, MY_CLASS);
|
|
Eo *child;
|
|
const char *path;
|
|
|
|
if (!eldbus_message_arguments_get(msg, "o", &path))
|
|
{
|
|
ERR("Could not get removed technology's path");
|
|
return;
|
|
}
|
|
|
|
child = _efl_net_control_technology_find(pd, path);
|
|
if (!child)
|
|
{
|
|
WRN("Technology path '%s' doesn't exist", path);
|
|
return;
|
|
}
|
|
|
|
pd->technologies = eina_list_remove(pd->technologies, child);
|
|
DBG("Technology Removed Path=%s", path);
|
|
efl_event_callback_call(o, EFL_NET_CONTROL_EVENT_TECHNOLOGY_DEL, child);
|
|
efl_del(child);
|
|
}
|
|
|
|
static void
|
|
_efl_net_control_access_point_added(Eo *o, Efl_Net_Control_Data *pd, const char *path, Eldbus_Message_Iter *properties, unsigned int priority)
|
|
{
|
|
Eo *child;
|
|
|
|
child = efl_net_connman_access_point_new(o, path, properties, priority);
|
|
if (!child)
|
|
{
|
|
ERR("could not create access point for path=%s", path);
|
|
return;
|
|
}
|
|
|
|
pd->access_points = eina_list_append(pd->access_points, child);
|
|
DBG("Access Point Added Path=%s", path);
|
|
efl_event_callback_call(o, EFL_NET_CONTROL_EVENT_ACCESS_POINT_ADD, child);
|
|
}
|
|
|
|
static void
|
|
_efl_net_control_access_point_updated(Eo *o, Efl_Net_Control_Data *pd, const char *path, Eldbus_Message_Iter *properties, unsigned int priority)
|
|
{
|
|
Eo *child = _efl_net_control_access_point_find(pd, path);
|
|
if (!child)
|
|
{
|
|
_efl_net_control_access_point_added(o, pd, path, properties, priority);
|
|
return;
|
|
}
|
|
|
|
efl_net_connman_access_point_update(child, properties, priority);
|
|
}
|
|
|
|
static void
|
|
_efl_net_control_access_point_removed(Eo *o, Efl_Net_Control_Data *pd, const char *path)
|
|
{
|
|
Eo *child = _efl_net_control_access_point_find(pd, path);
|
|
if (!child)
|
|
{
|
|
WRN("Access Point path '%s' doesn't exist", path);
|
|
return;
|
|
}
|
|
|
|
pd->access_points = eina_list_remove(pd->access_points, child);
|
|
DBG("Access Point Removed Path=%s", path);
|
|
efl_event_callback_call(o, EFL_NET_CONTROL_EVENT_ACCESS_POINT_DEL, child);
|
|
efl_del(child);
|
|
}
|
|
|
|
static int
|
|
_efl_net_control_access_point_sort_cb(const void *d1, const void *d2)
|
|
{
|
|
const Eo *a = d1;
|
|
const Eo *b = d2;
|
|
unsigned int pa = efl_net_control_access_point_priority_get(a);
|
|
unsigned int pb = efl_net_control_access_point_priority_get(b);
|
|
if (pa < pb) return -1;
|
|
else if (pa > pb) return 1;
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
_efl_net_control_services_changed(void *data, const Eldbus_Message *msg)
|
|
{
|
|
Eo *o = data;
|
|
Efl_Net_Control_Data *pd = efl_data_scope_get(o, MY_CLASS);
|
|
Eldbus_Message_Iter *changed, *invalidated, *sub;
|
|
const char *path;
|
|
unsigned int priority;
|
|
|
|
if (!eldbus_message_arguments_get(msg, "a(oa{sv})ao", &changed, &invalidated))
|
|
{
|
|
ERR("could not get services changed, signature=%s", eldbus_message_signature_get(msg));
|
|
return;
|
|
}
|
|
|
|
efl_ref(o); /* will trigger events, which call user which may delete us */
|
|
|
|
priority = 0;
|
|
while (eldbus_message_iter_get_and_next(changed, 'r', &sub))
|
|
{
|
|
Eldbus_Message_Iter *properties;
|
|
if (!eldbus_message_iter_arguments_get(sub, "oa{sv}", &path, &properties))
|
|
{
|
|
ERR("could not get access point path or properties, signature=%s", eldbus_message_iter_signature_get(sub));
|
|
continue;
|
|
}
|
|
_efl_net_control_access_point_updated(o, pd, path, properties, priority++);
|
|
}
|
|
|
|
while (eldbus_message_iter_get_and_next(invalidated, 'o', &path))
|
|
_efl_net_control_access_point_removed(o, pd, path);
|
|
|
|
pd->access_points = eina_list_sort(pd->access_points, 0, _efl_net_control_access_point_sort_cb);
|
|
|
|
efl_event_callback_call(o, EFL_NET_CONTROL_EVENT_ACCESS_POINTS_CHANGED, NULL);
|
|
efl_unref(o);
|
|
}
|
|
|
|
static Efl_Net_Control_State
|
|
_efl_net_control_state_from_str(const char *str)
|
|
{
|
|
const struct {
|
|
const char *name;
|
|
Efl_Net_Control_State state;
|
|
} *itr, map[] = {
|
|
{"offline", EFL_NET_CONTROL_STATE_OFFLINE},
|
|
{"idle", EFL_NET_CONTROL_STATE_OFFLINE},
|
|
{"ready", EFL_NET_CONTROL_STATE_LOCAL},
|
|
{"online", EFL_NET_CONTROL_STATE_ONLINE},
|
|
{ }
|
|
};
|
|
for (itr = map; itr->name != NULL; itr++)
|
|
if (strcmp(itr->name, str) == 0) return itr->state;
|
|
|
|
ERR("Unknown State '%s', assume offline.", str);
|
|
return EFL_NET_CONTROL_STATE_OFFLINE;
|
|
}
|
|
|
|
static void
|
|
_efl_net_control_property_state_changed(Eo *o, Efl_Net_Control_Data *pd, Eldbus_Message_Iter *value)
|
|
{
|
|
const char *str;
|
|
Efl_Net_Control_State state;
|
|
|
|
if (!eldbus_message_iter_arguments_get(value, "s", &str))
|
|
{
|
|
ERR("Expected string, got %s", eldbus_message_iter_signature_get(value));
|
|
return;
|
|
}
|
|
|
|
state = _efl_net_control_state_from_str(str);
|
|
if (pd->state == state) return;
|
|
pd->state = state;
|
|
DBG("state=%d (%s)", state, str);
|
|
efl_event_callback_call(o, EFL_NET_CONTROL_EVENT_STATE_CHANGED, NULL);
|
|
}
|
|
|
|
static void
|
|
_efl_net_control_property_radios_offline_changed(Eo *o, Efl_Net_Control_Data *pd, Eldbus_Message_Iter *value)
|
|
{
|
|
Eina_Bool offline;
|
|
|
|
if (!eldbus_message_iter_arguments_get(value, "b", &offline))
|
|
{
|
|
ERR("Expected boolean, got %s", eldbus_message_iter_signature_get(value));
|
|
return;
|
|
}
|
|
|
|
if (pd->radios_offline == offline) return;
|
|
pd->radios_offline = offline;
|
|
DBG("radios offline=%hhu", offline);
|
|
efl_event_callback_call(o, EFL_NET_CONTROL_EVENT_RADIOS_OFFLINE_CHANGED, NULL);
|
|
}
|
|
|
|
static void
|
|
_efl_net_control_property_changed_internal(Eo *o, Efl_Net_Control_Data *pd, Eldbus_Message_Iter *itr)
|
|
{
|
|
Eldbus_Message_Iter *value;
|
|
const char *name;
|
|
|
|
if (!eldbus_message_iter_arguments_get(itr, "sv", &name, &value))
|
|
{
|
|
ERR("Unexpected signature: %s", eldbus_message_iter_signature_get(itr));
|
|
return;
|
|
}
|
|
|
|
if (strcmp(name, "State") == 0)
|
|
_efl_net_control_property_state_changed(o, pd, value);
|
|
else if (strcmp(name, "OfflineMode") == 0)
|
|
_efl_net_control_property_radios_offline_changed(o, pd, value);
|
|
else if (strcmp(name, "SessionMode") == 0)
|
|
{ }
|
|
else
|
|
WRN("Unknown property name: %s", name);
|
|
}
|
|
|
|
static void
|
|
_efl_net_control_property_changed(void *data, const Eldbus_Message *msg)
|
|
{
|
|
Eo *o = data;
|
|
Efl_Net_Control_Data *pd = efl_data_scope_get(o, MY_CLASS);
|
|
Eldbus_Message_Iter *itr;
|
|
|
|
itr = eldbus_message_iter_get(msg);
|
|
_efl_net_control_property_changed_internal(o, pd, itr);
|
|
}
|
|
|
|
static void
|
|
_efl_net_control_properties_get_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
|
|
{
|
|
Eo *o = data;
|
|
Efl_Net_Control_Data *pd = efl_data_scope_get(o, MY_CLASS);
|
|
Eldbus_Message_Iter *array, *entry;
|
|
const char *err_name, *err_msg;
|
|
|
|
pd->pending = eina_list_remove(pd->pending, pending);
|
|
if (eldbus_message_error_get(msg, &err_name, &err_msg))
|
|
{
|
|
ERR("Could not get properties %p: %s=%s", o, err_name, err_msg);
|
|
return;
|
|
}
|
|
|
|
if (!eldbus_message_arguments_get(msg, "a{sv}", &array))
|
|
{
|
|
ERR("Expected dict ('a{sv}'), got '%s'", eldbus_message_signature_get(msg));
|
|
return;
|
|
}
|
|
|
|
efl_ref(o); /* properties will trigger events, which call user which may delete us */
|
|
|
|
/* force changed to be emitted */
|
|
pd->radios_offline = 0xff;
|
|
pd->state = 0xff;
|
|
while (eldbus_message_iter_get_and_next(array, 'e', &entry))
|
|
_efl_net_control_property_changed_internal(o, pd, entry);
|
|
|
|
efl_unref(o);
|
|
}
|
|
|
|
static void
|
|
_efl_net_control_technologies_get_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
|
|
{
|
|
Eo *o = data;
|
|
Efl_Net_Control_Data *pd = efl_data_scope_get(o, MY_CLASS);
|
|
Eldbus_Message_Iter *array, *entry;
|
|
const char *err_name, *err_msg;
|
|
|
|
pd->pending = eina_list_remove(pd->pending, pending);
|
|
if (eldbus_message_error_get(msg, &err_name, &err_msg))
|
|
{
|
|
ERR("Could not get technologies %p: %s=%s", o, err_name, err_msg);
|
|
return;
|
|
}
|
|
|
|
if (!eldbus_message_arguments_get(msg, "a(oa{sv})", &array))
|
|
{
|
|
ERR("Expected 'a{oa{sv}}', got '%s'", eldbus_message_signature_get(msg));
|
|
return;
|
|
}
|
|
|
|
efl_ref(o); /* will trigger events, which call user which may delete us */
|
|
|
|
while (eldbus_message_iter_get_and_next(array, 'r', &entry))
|
|
_efl_net_control_technology_added_internal(o, pd, entry);
|
|
|
|
efl_unref(o);
|
|
}
|
|
|
|
static void
|
|
_efl_net_control_services_get_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
|
|
{
|
|
Eo *o = data;
|
|
Efl_Net_Control_Data *pd = efl_data_scope_get(o, MY_CLASS);
|
|
Eldbus_Message_Iter *array, *sub;
|
|
const char *err_name, *err_msg, *path;
|
|
unsigned int priority = 0;
|
|
|
|
pd->pending = eina_list_remove(pd->pending, pending);
|
|
if (eldbus_message_error_get(msg, &err_name, &err_msg))
|
|
{
|
|
ERR("Could not get services %p: %s=%s", o, err_name, err_msg);
|
|
return;
|
|
}
|
|
|
|
if (!eldbus_message_arguments_get(msg, "a(oa{sv})", &array))
|
|
{
|
|
ERR("Expected 'a{oa{sv}}', got '%s'", eldbus_message_signature_get(msg));
|
|
return;
|
|
}
|
|
|
|
efl_ref(o); /* will trigger events, which call user which may delete us */
|
|
|
|
while (eldbus_message_iter_get_and_next(array, 'r', &sub))
|
|
{
|
|
Eldbus_Message_Iter *properties;
|
|
if (!eldbus_message_iter_arguments_get(sub, "oa{sv}", &path, &properties))
|
|
{
|
|
ERR("could not get access point path or properties, signature=%s", eldbus_message_iter_signature_get(sub));
|
|
continue;
|
|
}
|
|
_efl_net_control_access_point_updated(o, pd, path, properties, priority++);
|
|
}
|
|
|
|
pd->access_points = eina_list_sort(pd->access_points, 0, _efl_net_control_access_point_sort_cb);
|
|
|
|
efl_event_callback_call(o, EFL_NET_CONTROL_EVENT_ACCESS_POINTS_CHANGED, NULL);
|
|
efl_unref(o);
|
|
}
|
|
|
|
static void
|
|
_efl_net_control_radios_offline_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
|
|
{
|
|
Eo *o = data;
|
|
Efl_Net_Control_Data *pd = efl_data_scope_get(o, MY_CLASS);
|
|
const char *err_name, *err_msg;
|
|
Eina_Bool radios_offline = pd->request.radios_offline;
|
|
|
|
if (pd->request.radios_offline_pending == pending)
|
|
{
|
|
pd->request.radios_offline_pending = NULL;
|
|
pd->request.radios_offline = 0xff;
|
|
}
|
|
|
|
pd->pending = eina_list_remove(pd->pending, pending);
|
|
if (eldbus_message_error_get(msg, &err_name, &err_msg))
|
|
{
|
|
ERR("Could not set property radios_offline=%hhu %p: %s=%s", radios_offline, o, err_name, err_msg);
|
|
return;
|
|
}
|
|
|
|
DBG("Set radios_offline=%hhu", radios_offline);
|
|
}
|
|
|
|
static void
|
|
_efl_net_control_radios_offline_apply(Eo *o, Efl_Net_Control_Data *pd)
|
|
{
|
|
Eldbus_Proxy *mgr = efl_net_connman_manager_get();
|
|
Eldbus_Message *msg = eldbus_proxy_method_call_new(mgr, "SetProperty");
|
|
Eldbus_Message_Iter *msg_itr, *var;
|
|
Eldbus_Pending *p;
|
|
|
|
if (pd->request.radios_offline_pending)
|
|
{
|
|
pd->pending = eina_list_remove(pd->pending, pd->request.radios_offline_pending);
|
|
eldbus_pending_cancel(pd->request.radios_offline_pending);
|
|
pd->request.radios_offline_pending = NULL;
|
|
}
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN(msg);
|
|
|
|
msg_itr = eldbus_message_iter_get(msg);
|
|
EINA_SAFETY_ON_NULL_GOTO(msg_itr, error_send);
|
|
|
|
eldbus_message_iter_basic_append(msg_itr, 's', "OfflineMode");
|
|
var = eldbus_message_iter_container_new(msg_itr, 'v', "b");
|
|
eldbus_message_iter_basic_append(var, 'b', pd->request.radios_offline);
|
|
eldbus_message_iter_container_close(msg_itr, var);
|
|
|
|
p = eldbus_proxy_send(mgr, msg, _efl_net_control_radios_offline_cb, o, DEFAULT_TIMEOUT);
|
|
EINA_SAFETY_ON_NULL_GOTO(p, error_send);
|
|
|
|
pd->pending = eina_list_append(pd->pending, p);
|
|
pd->request.radios_offline_pending = p;
|
|
DBG("setting radios offline=%hhu", pd->request.radios_offline);
|
|
return;
|
|
|
|
error_send:
|
|
eldbus_message_unref(msg);
|
|
}
|
|
|
|
static void
|
|
_efl_net_control_clear(Eo *o, Efl_Net_Control_Data *pd)
|
|
{
|
|
Eo *child;
|
|
|
|
EINA_LIST_FREE(pd->access_points, child)
|
|
{
|
|
efl_event_callback_call(o, EFL_NET_CONTROL_EVENT_ACCESS_POINT_DEL, child);
|
|
efl_del(child);
|
|
}
|
|
efl_event_callback_call(o, EFL_NET_CONTROL_EVENT_ACCESS_POINTS_CHANGED, NULL);
|
|
|
|
EINA_LIST_FREE(pd->technologies, child)
|
|
{
|
|
efl_event_callback_call(o, EFL_NET_CONTROL_EVENT_TECHNOLOGY_DEL, child);
|
|
efl_del(child);
|
|
}
|
|
|
|
pd->state = EFL_NET_CONTROL_STATE_OFFLINE;
|
|
efl_event_callback_call(o, EFL_NET_CONTROL_EVENT_STATE_CHANGED, NULL);
|
|
pd->radios_offline = EINA_TRUE;
|
|
efl_event_callback_call(o, EFL_NET_CONTROL_EVENT_RADIOS_OFFLINE_CHANGED, NULL);
|
|
}
|
|
|
|
static void
|
|
_efl_net_control_connman_name_owner_changed(void *data, const char *bus, const char *old_id, const char *new_id)
|
|
{
|
|
Eo *o = data;
|
|
Efl_Net_Control_Data *pd = efl_data_scope_get(o, MY_CLASS);
|
|
Eldbus_Proxy *mgr;
|
|
|
|
DBG("Name Owner Changed %s: %s->%s", bus, old_id, new_id);
|
|
if ((!new_id) || (new_id[0] == '\0'))
|
|
{
|
|
_efl_net_control_clear(o, pd);
|
|
pd->operating = EINA_FALSE;
|
|
if (pd->agent_enabled)
|
|
{
|
|
pd->agent_enabled = EINA_FALSE;
|
|
efl_event_callback_call(o, EFL_NET_CONTROL_EVENT_AGENT_RELEASED, NULL);
|
|
}
|
|
return;
|
|
}
|
|
|
|
mgr = efl_net_connman_manager_get();
|
|
EINA_SAFETY_ON_NULL_RETURN(mgr);
|
|
|
|
#define SH(sig, cb) \
|
|
do { \
|
|
Eldbus_Signal_Handler *sh = eldbus_proxy_signal_handler_add(mgr, sig, cb, o); \
|
|
if (sh) pd->signal_handlers = eina_list_append(pd->signal_handlers, sh); \
|
|
else ERR("could not add DBus signal handler %s", sig); \
|
|
} while (0)
|
|
|
|
SH("TechnologyAdded", _efl_net_control_technology_added);
|
|
SH("TechnologyRemoved", _efl_net_control_technology_removed);
|
|
SH("ServicesChanged", _efl_net_control_services_changed);
|
|
SH("PropertyChanged", _efl_net_control_property_changed);
|
|
#undef SH
|
|
|
|
#define CALL(meth, cb) \
|
|
do { \
|
|
Eldbus_Pending *p = eldbus_proxy_call(mgr, meth, cb, o, DEFAULT_TIMEOUT, ""); \
|
|
if (p) pd->pending = eina_list_append(pd->pending, p); \
|
|
else ERR("could not call DBus method %s", meth); \
|
|
} while (0)
|
|
|
|
CALL("GetProperties", _efl_net_control_properties_get_cb);
|
|
CALL("GetTechnologies", _efl_net_control_technologies_get_cb);
|
|
CALL("GetServices", _efl_net_control_services_get_cb);
|
|
#undef CALL
|
|
|
|
pd->operating = EINA_TRUE;
|
|
|
|
if (pd->request.radios_offline != 0xff) _efl_net_control_radios_offline_apply(o, pd);
|
|
|
|
if (pd->agent_pending)
|
|
{
|
|
eldbus_pending_cancel(pd->agent_pending);
|
|
pd->agent_pending = NULL;
|
|
}
|
|
if (pd->agent_enabled)
|
|
{
|
|
pd->agent_enabled = EINA_FALSE;
|
|
_efl_net_control_agent_enabled_set(o, pd, EINA_TRUE);
|
|
}
|
|
}
|
|
|
|
void
|
|
efl_net_connman_control_access_points_reload(Eo *o)
|
|
{
|
|
Efl_Net_Control_Data *pd = efl_data_scope_get(o, MY_CLASS);
|
|
Eldbus_Proxy *mgr;
|
|
Eldbus_Pending *p;
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN(pd);
|
|
mgr = efl_net_connman_manager_get();
|
|
EINA_SAFETY_ON_NULL_RETURN(mgr);
|
|
|
|
p = eldbus_proxy_call(mgr, "GetServices", _efl_net_control_services_get_cb, o, DEFAULT_TIMEOUT, "");
|
|
if (p) pd->pending = eina_list_append(pd->pending, p);
|
|
else ERR("could not call DBus method %s", "GetServices");
|
|
}
|
|
|
|
EOLIAN static Eo *
|
|
_efl_net_control_efl_object_constructor(Eo *o, Efl_Net_Control_Data *pd EINA_UNUSED)
|
|
{
|
|
pd->radios_offline = EINA_TRUE;
|
|
pd->request.radios_offline = 0xff;
|
|
|
|
if (!efl_net_connman_init())
|
|
{
|
|
ERR("could not initialize connman infrastructure");
|
|
return NULL;
|
|
}
|
|
|
|
return efl_constructor(efl_super(o, MY_CLASS));
|
|
}
|
|
|
|
EOLIAN static Eo *
|
|
_efl_net_control_efl_object_finalize(Eo *o, Efl_Net_Control_Data *pd EINA_UNUSED)
|
|
{
|
|
Eldbus_Connection *conn;
|
|
char path[128];
|
|
|
|
o = efl_finalize(efl_super(o, MY_CLASS));
|
|
if (!o) return NULL;
|
|
|
|
conn = efl_net_connman_connection_get();
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(conn, NULL);
|
|
|
|
snprintf(path, sizeof(path), "/connman/agent_%p", o);
|
|
pd->agent = eldbus_service_interface_register(conn, path, &_efl_net_control_agent_desc);
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(pd->agent, NULL);
|
|
eldbus_service_object_data_set(pd->agent, "efl_net", o);
|
|
|
|
eldbus_name_owner_changed_callback_add(conn, "net.connman", _efl_net_control_connman_name_owner_changed, o, EINA_TRUE);
|
|
DBG("waiting for net.connman to show on the DBus system bus...");
|
|
|
|
return o;
|
|
}
|
|
|
|
EOLIAN static void
|
|
_efl_net_control_efl_object_destructor(Eo *o, Efl_Net_Control_Data *pd)
|
|
{
|
|
Eldbus_Pending *p;
|
|
Eldbus_Signal_Handler *sh;
|
|
|
|
pd->operating = EINA_FALSE;
|
|
|
|
pd->request.radios_offline_pending = NULL;
|
|
EINA_LIST_FREE(pd->pending, p)
|
|
eldbus_pending_cancel(p);
|
|
|
|
EINA_LIST_FREE(pd->signal_handlers, sh)
|
|
eldbus_signal_handler_del(sh);
|
|
|
|
if (pd->agent_request_input.msg)
|
|
{
|
|
Eldbus_Message *reply = eldbus_message_error_new(pd->agent_request_input.msg,
|
|
"net.connman.Error.OperationAborted",
|
|
"Agent is gone.");
|
|
eldbus_connection_send(efl_net_connman_connection_get(), reply, NULL, NULL, -1.0);
|
|
eldbus_message_unref(pd->agent_request_input.msg);
|
|
pd->agent_request_input.msg = NULL;
|
|
}
|
|
|
|
if (pd->agent_enabled)
|
|
{
|
|
Eldbus_Proxy *mgr = efl_net_connman_manager_get();
|
|
|
|
/* UnregisterAgent is required since the manager proxy and bus
|
|
* may be alive, thus connman won't get any NameOwnerChanged
|
|
* or related to know the object is gone
|
|
*/
|
|
eldbus_proxy_call(mgr, "UnregisterAgent", NULL, NULL, DEFAULT_TIMEOUT,
|
|
"o", eldbus_service_object_path_get(pd->agent));
|
|
}
|
|
|
|
if (pd->agent)
|
|
{
|
|
eldbus_service_object_data_del(pd->agent, "efl_net");
|
|
eldbus_service_object_unregister(pd->agent);
|
|
pd->agent = NULL;
|
|
}
|
|
|
|
_efl_net_control_clear(o, pd);
|
|
|
|
efl_destructor(efl_super(o, MY_CLASS));
|
|
efl_net_connman_shutdown();
|
|
}
|
|
|
|
EOLIAN static void
|
|
_efl_net_control_radios_offline_set(Eo *o, Efl_Net_Control_Data *pd, Eina_Bool radios_offline)
|
|
{
|
|
pd->request.radios_offline = radios_offline;
|
|
if (pd->operating) _efl_net_control_radios_offline_apply(o, pd);
|
|
}
|
|
|
|
EOLIAN static Eina_Bool
|
|
_efl_net_control_radios_offline_get(Eo *o EINA_UNUSED, Efl_Net_Control_Data *pd)
|
|
{
|
|
return pd->radios_offline;
|
|
}
|
|
|
|
EOLIAN static Efl_Net_Control_State
|
|
_efl_net_control_state_get(Eo *o EINA_UNUSED, Efl_Net_Control_Data *pd)
|
|
{
|
|
return pd->state;
|
|
}
|
|
|
|
EOLIAN static Eina_Iterator *
|
|
_efl_net_control_access_points_get(Eo *o EINA_UNUSED, Efl_Net_Control_Data *pd)
|
|
{
|
|
return eina_list_iterator_new(pd->access_points);
|
|
}
|
|
|
|
EOLIAN static Eina_Iterator *
|
|
_efl_net_control_technologies_get(Eo *o EINA_UNUSED, Efl_Net_Control_Data *pd)
|
|
{
|
|
return eina_list_iterator_new(pd->technologies);
|
|
}
|
|
|
|
Efl_Net_Control_Technology *
|
|
efl_net_connman_control_find_technology_by_type(Efl_Net_Control *o, const char *tech_type)
|
|
{
|
|
Efl_Net_Control_Data *pd = efl_data_scope_get(o, MY_CLASS);
|
|
Efl_Net_Control_Technology_Type desired = efl_net_connman_technology_type_from_str(tech_type);
|
|
const Eina_List *n;
|
|
Eo *child;
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(pd, NULL);
|
|
|
|
EINA_LIST_FOREACH(pd->technologies, n, child)
|
|
{
|
|
Efl_Net_Control_Technology_Type type = efl_net_control_technology_type_get(child);
|
|
if (type == desired)
|
|
return child;
|
|
}
|
|
|
|
WRN("Could not find technology type %#x '%s'", desired, tech_type);
|
|
return NULL;
|
|
}
|
|
|
|
static void
|
|
_efl_net_control_agent_register_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
|
|
{
|
|
Eo *o = data;
|
|
Efl_Net_Control_Data *pd = efl_data_scope_get(o, MY_CLASS);
|
|
const char *err_name, *err_msg;
|
|
|
|
pd->pending = eina_list_remove(pd->pending, pending);
|
|
if (pd->agent_pending == pending)
|
|
pd->agent_pending = NULL;
|
|
if (eldbus_message_error_get(msg, &err_name, &err_msg))
|
|
{
|
|
ERR("Could not Register Agent %p: %s=%s", o, err_name, err_msg);
|
|
return;
|
|
}
|
|
|
|
DBG("Agent registered %p: %s", o, eldbus_service_object_path_get(pd->agent));
|
|
pd->agent_enabled = EINA_TRUE;
|
|
}
|
|
|
|
static void
|
|
_efl_net_control_agent_unregister_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
|
|
{
|
|
Eo *o = data;
|
|
Efl_Net_Control_Data *pd = efl_data_scope_get(o, MY_CLASS);
|
|
const char *err_name, *err_msg;
|
|
|
|
pd->pending = eina_list_remove(pd->pending, pending);
|
|
if (pd->agent_pending == pending)
|
|
pd->agent_pending = NULL;
|
|
if (eldbus_message_error_get(msg, &err_name, &err_msg))
|
|
{
|
|
ERR("Could not Unregister Agent %p: %s=%s", o, err_name, err_msg);
|
|
return;
|
|
}
|
|
DBG("Agent unregistered %p: %s", o, eldbus_service_object_path_get(pd->agent));
|
|
pd->agent_enabled = EINA_FALSE;
|
|
}
|
|
|
|
EOLIAN static void
|
|
_efl_net_control_agent_enabled_set(Eo *o, Efl_Net_Control_Data *pd, Eina_Bool agent_enabled)
|
|
{
|
|
Eldbus_Pending *p;
|
|
Eldbus_Proxy *mgr;
|
|
|
|
if (!pd->operating)
|
|
{
|
|
DBG("no connman yet, postpone agent_enabled=%hhu", agent_enabled);
|
|
pd->agent_enabled = agent_enabled;
|
|
return;
|
|
}
|
|
if (pd->agent_enabled == agent_enabled)
|
|
{
|
|
DBG("Already agent_enabled=%hhu", agent_enabled);
|
|
return;
|
|
}
|
|
|
|
if (pd->agent_pending)
|
|
{
|
|
eldbus_pending_cancel(pd->agent_pending);
|
|
pd->agent_pending = NULL;
|
|
}
|
|
|
|
mgr = efl_net_connman_manager_get();
|
|
EINA_SAFETY_ON_NULL_RETURN(mgr);
|
|
|
|
if (agent_enabled)
|
|
{
|
|
p = eldbus_proxy_call(mgr, "RegisterAgent",
|
|
_efl_net_control_agent_register_cb, o, DEFAULT_TIMEOUT,
|
|
"o", eldbus_service_object_path_get(pd->agent));
|
|
DBG("%p RegisterAgent=%p", o, p);
|
|
}
|
|
else
|
|
{
|
|
p = eldbus_proxy_call(mgr, "UnregisterAgent",
|
|
_efl_net_control_agent_unregister_cb, o, DEFAULT_TIMEOUT,
|
|
"o", eldbus_service_object_path_get(pd->agent));
|
|
DBG("%p UnregisterAgent=%p", o, p);
|
|
}
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN(p);
|
|
|
|
pd->pending = eina_list_append(pd->pending, p);
|
|
pd->agent_pending = p;
|
|
}
|
|
|
|
EOLIAN static Eina_Bool
|
|
_efl_net_control_agent_enabled_get(Eo *o EINA_UNUSED, Efl_Net_Control_Data *pd)
|
|
{
|
|
return pd->agent_enabled;
|
|
}
|
|
|
|
static void
|
|
_append_dict_entry(Eldbus_Message_Iter *array, const char *name, const char *signature, ...)
|
|
{
|
|
Eldbus_Message_Iter *entry, *var;
|
|
va_list ap;
|
|
|
|
if (!eldbus_message_iter_arguments_append(array, "{sv}", &entry))
|
|
{
|
|
ERR("could not append dict entry");
|
|
return;
|
|
}
|
|
|
|
eldbus_message_iter_basic_append(entry, 's', name);
|
|
var = eldbus_message_iter_container_new(entry, 'v', signature);
|
|
|
|
va_start(ap, signature);
|
|
eldbus_message_iter_arguments_vappend(var, signature, ap);
|
|
va_end(ap);
|
|
eldbus_message_iter_container_close(entry, var);
|
|
eldbus_message_iter_container_close(array, entry);
|
|
}
|
|
|
|
|
|
static void
|
|
_append_dict_entry_byte_array(Eldbus_Message_Iter *array, const char *name, const Eina_Slice *slice)
|
|
{
|
|
Eldbus_Message_Iter *entry, *var, *sub;
|
|
|
|
if (!eldbus_message_iter_arguments_append(array, "{sv}", &entry))
|
|
{
|
|
ERR("could not append dict entry");
|
|
return;
|
|
}
|
|
|
|
eldbus_message_iter_basic_append(entry, 's', name);
|
|
var = eldbus_message_iter_container_new(entry, 'v', "ay");
|
|
sub = eldbus_message_iter_container_new(var, 'a', "y");
|
|
|
|
eldbus_message_iter_fixed_array_append(sub, 'y', slice->mem, slice->len);
|
|
|
|
eldbus_message_iter_container_close(var, sub);
|
|
eldbus_message_iter_container_close(entry, var);
|
|
eldbus_message_iter_container_close(array, entry);
|
|
}
|
|
|
|
EOLIAN static void
|
|
_efl_net_control_agent_reply(Eo *o EINA_UNUSED, Efl_Net_Control_Data *pd, const char *name, const Eina_Slice *ssid, const char *username, const char *passphrase, const char *wps)
|
|
{
|
|
Eldbus_Message *reply;
|
|
Eldbus_Message_Iter *msg_itr, *array;
|
|
|
|
if (!pd->agent_request_input.msg)
|
|
{
|
|
ERR("no agent input was required.");
|
|
return;
|
|
}
|
|
|
|
reply = eldbus_message_method_return_new(pd->agent_request_input.msg);
|
|
EINA_SAFETY_ON_NULL_RETURN(reply);
|
|
eldbus_message_unref(pd->agent_request_input.msg);
|
|
pd->agent_request_input.msg = NULL;
|
|
|
|
msg_itr = eldbus_message_iter_get(reply);
|
|
eldbus_message_iter_arguments_append(msg_itr, "a{sv}", &array);
|
|
|
|
if (name) _append_dict_entry(array, "Name", "s", name);
|
|
if (ssid) _append_dict_entry_byte_array(array, "SSID", ssid);
|
|
if (username)
|
|
{
|
|
_append_dict_entry(array, "Username", "s", username);
|
|
_append_dict_entry(array, "Identity", "s", username);
|
|
}
|
|
if (passphrase)
|
|
{
|
|
_append_dict_entry(array, "Password", "s", passphrase);
|
|
_append_dict_entry(array, "Passphrase", "s", passphrase);
|
|
}
|
|
if (wps) _append_dict_entry(array, "WPS", "s", wps);
|
|
|
|
eldbus_message_iter_container_close(msg_itr, array);
|
|
eldbus_connection_send(efl_net_connman_connection_get(), reply, NULL, NULL, -1.0);
|
|
}
|
|
|
|
#include "efl_net_control.eo.c"
|