diff options
Diffstat (limited to 'binding-wifi/agent.c')
-rw-r--r-- | binding-wifi/agent.c | 292 |
1 files changed, 292 insertions, 0 deletions
diff --git a/binding-wifi/agent.c b/binding-wifi/agent.c new file mode 100644 index 0000000..6b0f235 --- /dev/null +++ b/binding-wifi/agent.c @@ -0,0 +1,292 @@ +/* Copyright 2016 ALPS ELECTRIC CO., LTD. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include <stdio.h> +#include <errno.h> + +#include <gio/gio.h> +#include "wifi-connman.h" + +static GMainLoop *loop = NULL; + +static GDBusNodeInfo *introspection_data = NULL; + +GDBusConnection *connectionAgent; + +GDBusMethodInvocation *invocation_passkey = NULL; + +/* Introspection data for the agent service */ +static const gchar introspection_xml[] = "<node>" + " <interface name='net.connman.Agent'>" + " <method name='RequestInput'>" + " <arg type='o' name='service' direction='in'/>" + " <arg type='a{sv}' name='fields' direction='in'/>" + " <arg type='a{sv}' name='fields' direction='out'/>" + " </method>" + " <method name='ReportError'>" + " <arg type='o' name='service' direction='in'/>" + " <arg type='s' name='error' direction='in'/>" + " </method>" + " </interface>" + "</node>"; + +callback password_callback; +callback wifiListChanged_callback; + +static void handle_method_call(GDBusConnection *connection, const gchar *sender, + const gchar *object_path, const gchar *interface_name, + const gchar *method_name, GVariant *parameters, + GDBusMethodInvocation *invocation, gpointer user_data) { + //MyObject *myobj = user_data; + + if (g_strcmp0(method_name, "RequestInput") == 0) { + DEBUG(afbitf,"RequestInput method on Agent interface has been called\n"); + + invocation_passkey = invocation; + + GVariantIter *array; + gchar * object_path; + g_variant_get(parameters, "(oa{sv})", &object_path, &array); + //TODO: get only object path for now, complete parameters are + + /* + object path "/net/connman/service/wifi_d85d4c880b1a_4c656e6f766f204b3520506c7573_managed_psk" + array [ + dict entry( + string "Passphrase" + variant array [ + dict entry( + string "Type" + variant string "psk" + ) + dict entry( + string "Requirement" + variant string "mandatory" + ) + ] + ) + ] + */ + NOTICE(afbitf,"Passphrase requested for network : %s\n", object_path); + (*password_callback)(0, object_path); + + + } + + if (g_strcmp0(method_name, "ReportError") == 0) { + ERROR(afbitf,"ReportError method on Agent interface has een called\n"); + + gchar *error_string; // = NULL; + + gchar * object_path; + g_variant_get(parameters, "(os)", &object_path, &error_string); + + ERROR(afbitf, "Error %s for %s\n", error_string, object_path); + + if (g_strcmp0(error_string, "invalid-key") == 0) { + + WARNING(afbitf, "Passkey is not correct.\n"); + (*password_callback)(1, "invalid-key"); + + } + + } +} + +GError* sendPasskey(gchar *passkey) { + + GVariantBuilder *builder; + GVariant *value = NULL; + + NOTICE(afbitf, "Passkey to send: %s\n", passkey); + + builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}")); + + g_variant_builder_add(builder, "{sv}", "Passphrase", + g_variant_new_string(passkey)); + + value = g_variant_new("(a{sv})", builder); + + g_dbus_method_invocation_return_value(invocation_passkey, value); + + return NULL; + +} + +static const GDBusInterfaceVTable interface_vtable = { handle_method_call, NULL, + NULL }; + +static void on_bus_acquired(GDBusConnection *connection, const gchar *name, + gpointer user_data) { + //MyObject *myobj = user_data; + guint registration_id; + + registration_id = g_dbus_connection_register_object(connection, + "/net/connman/Agent", introspection_data->interfaces[0], + &interface_vtable, NULL, NULL, /* user_data_free_func */ + NULL); /* GError** */ + //TODO: make some proper error message rather than exiting + //g_assert(registration_id > 0); + + return NULL; +} + +static void test_signal_handler (GDBusConnection *connection, const gchar *sender_name, const gchar *object_path, const gchar *interface_name, const gchar *signal_name, GVariant *parameters, gpointer user_data) { + + //do not parse, just check what has changed and make callback - + // we need to refresh completelist anyway.. + if (g_strcmp0(signal_name, "PropertiesChanged") == 0) { + + (*wifiListChanged_callback)(1, "PropertiesChanged"); + } + else if (g_strcmp0(signal_name, "BSSRemoved") == 0) { + (*wifiListChanged_callback)(2, "BSSRemoved"); + } + + else if (g_strcmp0(signal_name, "BSSAdded") == 0) { + (*wifiListChanged_callback)(2, "BSSAdded"); + } + else WARNING(afbitf,"unhandled signal %s %s %s, %s", sender_name, object_path, interface_name, signal_name); + + +} + +void* register_agent(void *data) { + + guint owner_id; + + guint networkChangedID; + + introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, NULL); + g_assert(introspection_data != NULL); + + //myobj = g_object_new(my_object_get_type(), NULL); + +// owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM, "org.agent", +// G_BUS_NAME_OWNER_FLAGS_NONE, on_bus_acquired, on_name_acquired, +// on_name_lost, myobj, +// NULL); + +//FIXME: ALLOW_REPLACEMENT for now, make proper deinitialization + owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM, AGENT_SERVICE, + G_BUS_NAME_OWNER_FLAGS_REPLACE, on_bus_acquired, NULL, NULL, NULL, + NULL); + //G_BUS_NAME_OWNER_FLAGS_NONE G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT + + + //"net.connman.Manager", "ServicesChanged", + networkChangedID = g_dbus_connection_signal_subscribe(connectionAgent, NULL, "fi.w1.wpa_supplicant1.Interface", NULL, NULL, NULL, G_DBUS_SIGNAL_FLAGS_NONE, test_signal_handler, NULL, NULL); + + g_assert(networkChangedID !=0); + + loop = g_main_loop_new(NULL, FALSE); + + //sleep(10); + g_main_loop_run(loop); + + g_bus_unown_name(owner_id); + + g_dbus_node_info_unref(introspection_data); + + //g_object_unref(myobj); + + return NULL; + +} + +GError* create_agent(GDBusConnection *connection) { + + int err = -1; + pthread_t tid[1]; + + + connectionAgent = connection; + + err = pthread_create((&tid[0]), NULL, register_agent, NULL); + + if (err != 0) { + ERROR(afbitf,"\ncan't create thread :[%d]", err); + ERROR(afbitf,"Fatal error!\n\n"); + return NULL; + } + + GVariant *message = NULL; + GError *error = NULL; + + GVariant *params = NULL; + + char *agent_path = AGENT_PATH; + + params = g_variant_new("(o)", agent_path); + + message = g_dbus_connection_call_sync(connection, CONNMAN_SERVICE, + CONNMAN_MANAGER_PATH, CONNMAN_MANAGER_INTERFACE, "RegisterAgent", params, + NULL, G_DBUS_CALL_FLAGS_NONE, + DBUS_REPLY_TIMEOUT, NULL, &error); + + if (error) { + ERROR(afbitf,"error: %d:%s\n", error->code, error->message); + + return error; + + } else { + INFO(afbitf,"Agent registered\n"); + return NULL; + } + +} + +GError* stop_agent(GDBusConnection *connection) { + + GVariant *message = NULL; + GError *error = NULL; + + + GVariant *params = NULL; + + char *agent_path = AGENT_PATH; + + + params = g_variant_new("(o)", agent_path); + + message = g_dbus_connection_call_sync(connection, CONNMAN_SERVICE, + CONNMAN_MANAGER_PATH, CONNMAN_MANAGER_INTERFACE, "UnregisterAgent", params, + NULL, G_DBUS_CALL_FLAGS_NONE, + DBUS_REPLY_TIMEOUT, NULL, &error); + + if (error) { + ERROR(afbitf, "error: %d:%s\n", error->code, error->message); + return error; + + } else { + DEBUG(afbitf,"Agent unregistered\n"); + return NULL; + } + +} + +void register_callbackSecurity(callback callback_function) { + + password_callback = callback_function; + +} + +void register_callbackWiFiList(callback callback_function) { + + wifiListChanged_callback = callback_function; + +} + + |