/* 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 #include #include #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[] = "" " " " " " " " " " " " " " " " " " " " " " " ""; 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; }