mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-11-29 22:19:23 +01:00
agent: Enable multi-agent support
If an application initiates the Connect() operation and that application has an agent registered, then that application's agent will be called. Otherwise, the default agent is called.
This commit is contained in:
parent
ff319b8234
commit
7bd22770ed
91
src/agent.c
91
src/agent.c
@ -51,7 +51,7 @@ struct agent {
|
|||||||
struct l_queue *requests;
|
struct l_queue *requests;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct agent *default_agent = NULL;
|
static struct l_queue *agents;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* How long we wait for user to input things.
|
* How long we wait for user to input things.
|
||||||
@ -195,8 +195,6 @@ static void agent_free(void *data)
|
|||||||
l_free(agent->owner);
|
l_free(agent->owner);
|
||||||
l_free(agent->path);
|
l_free(agent->path);
|
||||||
l_free(agent);
|
l_free(agent);
|
||||||
|
|
||||||
default_agent = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void agent_send_next_request(struct agent *agent);
|
static void agent_send_next_request(struct agent *agent);
|
||||||
@ -277,6 +275,35 @@ static unsigned int agent_queue_request(struct agent *agent,
|
|||||||
return request->id;
|
return request->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct agent *agent_lookup(const char *owner)
|
||||||
|
{
|
||||||
|
const struct l_queue_entry *entry;
|
||||||
|
|
||||||
|
if (!owner)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (entry = l_queue_get_entries(agents); entry; entry = entry->next) {
|
||||||
|
struct agent *agent = entry->data;
|
||||||
|
|
||||||
|
if (strcmp(agent->owner, owner))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return agent;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct agent *get_agent(const char *owner)
|
||||||
|
{
|
||||||
|
struct agent *agent = agent_lookup(owner);
|
||||||
|
|
||||||
|
if (agent)
|
||||||
|
return agent;
|
||||||
|
|
||||||
|
return l_queue_peek_head(agents);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* agent_request_passphrase:
|
* agent_request_passphrase:
|
||||||
* @path: object path related to this request (like network object path)
|
* @path: object path related to this request (like network object path)
|
||||||
@ -298,10 +325,8 @@ unsigned int agent_request_passphrase(const char *path,
|
|||||||
struct l_dbus_message *trigger,
|
struct l_dbus_message *trigger,
|
||||||
void *user_data)
|
void *user_data)
|
||||||
{
|
{
|
||||||
|
struct agent *agent = get_agent(l_dbus_message_get_sender(trigger));
|
||||||
struct l_dbus_message *message;
|
struct l_dbus_message *message;
|
||||||
struct agent *agent;
|
|
||||||
|
|
||||||
agent = default_agent;
|
|
||||||
|
|
||||||
if (!agent || !callback)
|
if (!agent || !callback)
|
||||||
return 0;
|
return 0;
|
||||||
@ -334,17 +359,25 @@ static bool find_request(const void *a, const void *b)
|
|||||||
bool agent_request_cancel(unsigned int req_id, int reason)
|
bool agent_request_cancel(unsigned int req_id, int reason)
|
||||||
{
|
{
|
||||||
struct agent_request *request;
|
struct agent_request *request;
|
||||||
|
struct agent *agent;
|
||||||
|
const struct l_queue_entry *entry;
|
||||||
|
|
||||||
if (!default_agent)
|
for (entry = l_queue_get_entries(agents); entry; entry = entry->next) {
|
||||||
return false;
|
agent = entry->data;
|
||||||
|
|
||||||
request = l_queue_remove_if(default_agent->requests, find_request,
|
request = l_queue_remove_if(agent->requests, find_request,
|
||||||
L_UINT_TO_PTR(req_id));
|
L_UINT_TO_PTR(req_id));
|
||||||
|
if (!request)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (!request)
|
if (!request)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!request->message)
|
if (!request->message)
|
||||||
send_cancel_request(default_agent, reason);
|
send_cancel_request(agent, reason);
|
||||||
|
|
||||||
agent_request_free(request);
|
agent_request_free(request);
|
||||||
|
|
||||||
@ -357,6 +390,8 @@ static void agent_disconnect(struct l_dbus *dbus, void *user_data)
|
|||||||
|
|
||||||
l_debug("agent %s disconnected", agent->owner);
|
l_debug("agent %s disconnected", agent->owner);
|
||||||
|
|
||||||
|
l_queue_remove(agents, agent);
|
||||||
|
|
||||||
l_idle_oneshot(agent_free, agent, NULL);
|
l_idle_oneshot(agent_free, agent, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -380,11 +415,11 @@ static struct l_dbus_message *agent_register(struct l_dbus *dbus,
|
|||||||
struct l_dbus_message *message,
|
struct l_dbus_message *message,
|
||||||
void *user_data)
|
void *user_data)
|
||||||
{
|
{
|
||||||
|
struct agent *agent = agent_lookup(l_dbus_message_get_sender(message));
|
||||||
struct l_dbus_message *reply;
|
struct l_dbus_message *reply;
|
||||||
struct agent *agent;
|
|
||||||
const char *path;
|
const char *path;
|
||||||
|
|
||||||
if (default_agent)
|
if (agent)
|
||||||
return dbus_error_already_exists(message);
|
return dbus_error_already_exists(message);
|
||||||
|
|
||||||
l_debug("agent register called");
|
l_debug("agent register called");
|
||||||
@ -396,7 +431,7 @@ static struct l_dbus_message *agent_register(struct l_dbus *dbus,
|
|||||||
if (!agent)
|
if (!agent)
|
||||||
return dbus_error_failed(message);
|
return dbus_error_failed(message);
|
||||||
|
|
||||||
default_agent = agent;
|
l_queue_push_tail(agents, agent);
|
||||||
|
|
||||||
l_debug("agent %s path %s", agent->owner, agent->path);
|
l_debug("agent %s path %s", agent->owner, agent->path);
|
||||||
|
|
||||||
@ -411,23 +446,17 @@ static struct l_dbus_message *agent_unregister(struct l_dbus *dbus,
|
|||||||
struct l_dbus_message *message,
|
struct l_dbus_message *message,
|
||||||
void *user_data)
|
void *user_data)
|
||||||
{
|
{
|
||||||
|
struct agent *agent = agent_lookup(l_dbus_message_get_sender(message));
|
||||||
struct l_dbus_message *reply;
|
struct l_dbus_message *reply;
|
||||||
const char *path, *sender;
|
|
||||||
|
|
||||||
if (!default_agent)
|
|
||||||
return dbus_error_failed(message);
|
|
||||||
|
|
||||||
l_debug("agent unregister");
|
l_debug("agent unregister");
|
||||||
|
|
||||||
if (!l_dbus_message_get_arguments(message, "o", &path))
|
if (!agent)
|
||||||
return dbus_error_invalid_args(message);
|
|
||||||
|
|
||||||
sender = l_dbus_message_get_sender(message);
|
|
||||||
|
|
||||||
if (strcmp(default_agent->owner, sender))
|
|
||||||
return dbus_error_not_found(message);
|
return dbus_error_not_found(message);
|
||||||
|
|
||||||
agent_free(default_agent);
|
l_queue_remove(agents, agent);
|
||||||
|
|
||||||
|
agent_free(agent);
|
||||||
|
|
||||||
reply = l_dbus_message_new_method_return(message);
|
reply = l_dbus_message_new_method_return(message);
|
||||||
|
|
||||||
@ -446,15 +475,21 @@ static void setup_agent_interface(struct l_dbus_interface *interface)
|
|||||||
"", "o", "path");
|
"", "o", "path");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void release_agent(struct agent *agent)
|
static bool release_agent(void *data, void *user_data)
|
||||||
{
|
{
|
||||||
|
struct agent *agent = data;
|
||||||
|
|
||||||
send_request(agent, "Release");
|
send_request(agent, "Release");
|
||||||
|
|
||||||
agent_free(agent);
|
agent_free(agent);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool agent_init(struct l_dbus *dbus)
|
bool agent_init(struct l_dbus *dbus)
|
||||||
{
|
{
|
||||||
|
agents = l_queue_new();
|
||||||
|
|
||||||
if (!l_dbus_register_interface(dbus, IWD_AGENT_MANAGER_INTERFACE,
|
if (!l_dbus_register_interface(dbus, IWD_AGENT_MANAGER_INTERFACE,
|
||||||
setup_agent_interface,
|
setup_agent_interface,
|
||||||
NULL, false)) {
|
NULL, false)) {
|
||||||
@ -480,11 +515,13 @@ bool agent_exit(struct l_dbus *dbus)
|
|||||||
l_dbus_unregister_object(dbus, IWD_AGENT_MANAGER_PATH);
|
l_dbus_unregister_object(dbus, IWD_AGENT_MANAGER_PATH);
|
||||||
l_dbus_unregister_interface(dbus, IWD_AGENT_MANAGER_INTERFACE);
|
l_dbus_unregister_interface(dbus, IWD_AGENT_MANAGER_INTERFACE);
|
||||||
|
|
||||||
|
l_queue_destroy(agents, agent_free);
|
||||||
|
agents = NULL;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void agent_shutdown(void)
|
void agent_shutdown(void)
|
||||||
{
|
{
|
||||||
if (default_agent)
|
l_queue_foreach_remove(agents, release_agent, NULL);
|
||||||
release_agent(default_agent);
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user