3 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
5 * Licensed under the Apache License, Version 2.0 (the License);
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
21 #include <dbus/dbus.h>
22 #include <dbus/dbus-glib.h>
23 #include <dbus/dbus-glib-lowlevel.h>
28 #include <dd-display.h>
30 #include <net_connection.h>
31 #include <appcore-common.h>
35 #include "mobileap_softap.h"
36 #include "mobileap_handler.h"
37 #include "mobileap_common.h"
38 #include "mobileap_bluetooth.h"
39 #include "mobileap_wifi.h"
40 #include "mobileap_usb.h"
41 #include "mobileap_network.h"
42 #include "mobileap_notification.h"
43 #include "mobileap_iptables.h"
45 GType tethering_object_get_type(void);
46 #define TETHERING_TYPE_OBJECT (tethering_object_get_type())
47 G_DEFINE_TYPE(TetheringObject, tethering_object, G_TYPE_OBJECT)
49 GMainLoop *mainloop = NULL;
50 int mobileap_state = MOBILE_AP_STATE_NONE;
51 DBusConnection *tethering_conn = NULL;
53 gboolean tethering_disable(TetheringObject *obj, DBusGMethodInvocation *context);
54 gboolean tethering_get_station_info(TetheringObject *obj,
55 DBusGMethodInvocation *context);
56 gboolean tethering_get_data_packet_usage(TetheringObject *obj,
57 DBusGMethodInvocation *context);
59 #include "tethering-server-stub.h"
61 static void tethering_object_init(TetheringObject *obj)
64 g_assert(obj != NULL);
67 memset(&obj->softap_settings, 0x00, sizeof(obj->softap_settings));
70 static void tethering_object_finalize(GObject *obj)
74 G_OBJECT_CLASS(tethering_object_parent_class)->finalize(obj);
77 static void tethering_object_class_init(TetheringObjectClass *klass)
79 GObjectClass *object_class = (GObjectClass *)klass;
80 const gchar *signalNames[E_SIGNAL_MAX] = {
81 SIGNAL_NAME_NET_CLOSED,
82 SIGNAL_NAME_STA_CONNECT,
83 SIGNAL_NAME_STA_DISCONNECT,
84 SIGNAL_NAME_WIFI_TETHER_ON,
85 SIGNAL_NAME_WIFI_TETHER_OFF,
86 SIGNAL_NAME_USB_TETHER_ON,
87 SIGNAL_NAME_USB_TETHER_OFF,
88 SIGNAL_NAME_BT_TETHER_ON,
89 SIGNAL_NAME_BT_TETHER_OFF,
90 SIGNAL_NAME_WIFI_AP_ON,
91 SIGNAL_NAME_WIFI_AP_OFF,
92 SIGNAL_NAME_NO_DATA_TIMEOUT,
93 SIGNAL_NAME_LOW_BATTERY_MODE,
94 SIGNAL_NAME_FLIGHT_MODE,
95 SIGNAL_NAME_POWER_SAVE_MODE,
96 SIGNAL_NAME_SECURITY_TYPE_CHANGED,
97 SIGNAL_NAME_SSID_VISIBILITY_CHANGED,
98 SIGNAL_NAME_PASSPHRASE_CHANGED
103 g_assert(klass != NULL);
105 object_class->finalize = tethering_object_finalize;
107 DBG("Creating signals\n");
109 for (i = 0; i < E_SIGNAL_MAX; i++) {
112 signalId = g_signal_new(signalNames[i],
113 G_OBJECT_CLASS_TYPE(klass),
116 g_cclosure_marshal_VOID__STRING,
117 G_TYPE_NONE, 1, G_TYPE_STRING);
118 klass->signals[i] = signalId;
121 DBG("Binding to GLib/D-Bus\n");
123 dbus_g_object_type_install_info(TETHERING_TYPE_OBJECT,
124 &dbus_glib_tethering_object_info);
127 static void __add_station_info_to_array(gpointer data, gpointer user_data)
129 mobile_ap_station_info_t *si = (mobile_ap_station_info_t *)data;
130 GPtrArray *array = (GPtrArray *)user_data;
131 GValue value = {0, {{0}}};
133 g_value_init(&value, DBUS_STRUCT_STATIONS);
134 g_value_take_boxed(&value,
135 dbus_g_type_specialized_construct(DBUS_STRUCT_STATIONS));
136 dbus_g_type_struct_set(&value, 0, si->interface, 1, si->ip,
137 2, si->mac, 3, si->hostname, 4, (guint)(si->tm), G_MAXUINT);
138 g_ptr_array_add(array, g_value_get_boxed(&value));
141 gboolean _mobileap_set_state(int state)
145 mobileap_state |= state;
147 vconf_ret = vconf_set_int(VCONFKEY_MOBILE_HOTSPOT_MODE, mobileap_state);
148 if (vconf_ret != 0) {
149 ERR("vconf_set_int is failed : %d\n", vconf_ret);
156 gboolean _mobileap_is_disabled(void)
158 return mobileap_state ? FALSE : TRUE;
161 gboolean _mobileap_is_enabled(int state)
163 return (mobileap_state & state) ? TRUE : FALSE;
166 gboolean _mobileap_is_enabled_by_type(mobile_ap_type_e type)
169 case MOBILE_AP_TYPE_WIFI:
170 if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI))
174 case MOBILE_AP_TYPE_BT:
175 if (_mobileap_is_enabled(MOBILE_AP_STATE_BT))
179 case MOBILE_AP_TYPE_USB:
180 if (_mobileap_is_enabled(MOBILE_AP_STATE_USB))
184 case MOBILE_AP_TYPE_WIFI_AP:
185 if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI_AP))
190 ERR("Unknow type : %d\n", type);
197 gboolean _mobileap_clear_state(int state)
201 mobileap_state &= (~state);
203 vconf_ret = vconf_set_int(VCONFKEY_MOBILE_HOTSPOT_MODE, mobileap_state);
204 if (vconf_ret != 0) {
205 ERR("vconf_set_int is failed : %d\n", vconf_ret);
212 gboolean _terminate_mobileap_agent(gpointer user_data)
214 if (mainloop == NULL) {
218 if (!_mobileap_is_disabled()) {
219 DBG("Tethering is enabled\n");
223 if (_is_trying_network_operation()) {
224 DBG("Network operation is going on\n");
228 if (_is_trying_wifi_operation()) {
229 DBG("Wi-Fi operation is going on\n");
233 if (_is_trying_bt_operation()) {
234 DBG("BT operation is going on\n");
238 if (_is_trying_usb_operation()) {
239 DBG("USB operation is going on\n");
243 DBG("All tethering / AP's are turned off\n");
244 g_main_loop_quit(mainloop);
250 void _block_device_sleep(void)
254 ret = display_lock_state(LCD_OFF, STAY_CUR_STATE, 0);
256 ERR("PM control [ERROR] result = %d\n", ret);
258 DBG("PM control [SUCCESS]\n");
261 void _unblock_device_sleep(void)
265 ret = display_unlock_state(LCD_OFF, PM_SLEEP_MARGIN);
267 ERR("PM control [ERROR] result = %d\n", ret);
269 DBG("PM control [SUCCESS]\n");
272 int _init_tethering(TetheringObject *obj)
274 int ret = MOBILE_AP_ERROR_NONE;
276 DBG("obj->init_count: %d\n", obj->init_count);
278 if (obj->init_count > 0) {
280 return MOBILE_AP_ERROR_NONE;
283 if (!_mobileap_is_enabled(MOBILE_AP_STATE_WIFI_AP)) {
284 ret = _open_network();
286 _mh_core_execute_dhcp_server();
293 gboolean _deinit_tethering(TetheringObject *obj)
295 DBG("obj->init_count: %d\n", obj->init_count);
299 if (obj->init_count > 1) {
302 } else if (obj->init_count <= 0) {
303 ERR("Already deinitialized\n");
310 _mh_core_terminate_dhcp_server();
312 if (!_mobileap_is_enabled(MOBILE_AP_STATE_WIFI_AP)) {
316 idle_id = g_idle_add(_terminate_mobileap_agent, NULL);
318 ERR("g_idle_add is failed\n");
324 gboolean tethering_disable(TetheringObject *obj, DBusGMethodInvocation *context)
326 int ret = MOBILE_AP_ERROR_NONE;
329 g_assert(obj != NULL);
330 g_assert(context != NULL);
332 if (_mobileap_is_disabled()) {
333 ERR("Mobile hotspot has not been enabled\n");
334 ret = MOBILE_AP_ERROR_NOT_ENABLED;
335 dbus_g_method_return(context, MOBILE_AP_DISABLE_CFM, ret);
339 _disable_wifi_tethering(obj);
340 _disable_bt_tethering(obj);
341 _disable_usb_tethering(obj);
343 dbus_g_method_return(context, MOBILE_AP_DISABLE_CFM, ret);
348 gboolean tethering_get_station_info(TetheringObject *obj,
349 DBusGMethodInvocation *context)
353 GPtrArray *array = g_ptr_array_new();
355 g_assert(obj != NULL);
356 g_assert(context != NULL);
358 _station_info_foreach(__add_station_info_to_array, array);
360 dbus_g_method_return(context, MOBILE_AP_GET_STATION_INFO_CFM, array);
361 g_ptr_array_free(array, TRUE);
368 gboolean tethering_get_data_packet_usage(TetheringObject *obj,
369 DBusGMethodInvocation *context)
371 char *if_name = NULL;
372 unsigned long long wifi_tx_bytes = 0;
373 unsigned long long wifi_rx_bytes = 0;
374 unsigned long long bt_tx_bytes = 0;
375 unsigned long long bt_rx_bytes = 0;
376 unsigned long long usb_tx_bytes = 0;
377 unsigned long long usb_rx_bytes = 0;
378 unsigned long long tx_bytes = 0;
379 unsigned long long rx_bytes = 0;
381 if (_get_network_interface_name(&if_name) == FALSE) {
382 dbus_g_method_return(context, MOBILE_AP_GET_DATA_PACKET_USAGE_CFM,
387 if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI))
388 _get_data_usage(WIFI_IF, if_name,
389 &wifi_tx_bytes, &wifi_rx_bytes);
391 if (_mobileap_is_enabled(MOBILE_AP_STATE_BT))
392 _get_data_usage(BT_IF_ALL, if_name,
393 &bt_tx_bytes, &bt_rx_bytes);
395 if (_mobileap_is_enabled(MOBILE_AP_STATE_USB))
396 _get_data_usage(USB_IF, if_name,
397 &usb_tx_bytes, &usb_rx_bytes);
400 tx_bytes = wifi_tx_bytes + bt_tx_bytes + usb_tx_bytes;
401 rx_bytes = wifi_rx_bytes + bt_rx_bytes + usb_rx_bytes;
403 dbus_g_method_return(context, MOBILE_AP_GET_DATA_PACKET_USAGE_CFM,
409 static DBusHandlerResult __dnsmasq_signal_filter(DBusConnection *conn,
410 DBusMessage *msg, void *user_data)
413 ERR("Invalid param\n");
414 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
417 char *ip_addr = NULL;
420 char *bt_remote_device_name = NULL;
422 mobile_ap_type_e type = MOBILE_AP_TYPE_MAX;
423 TetheringObject *obj = (TetheringObject *)user_data;
424 mobile_ap_station_info_t *info = NULL;
428 dbus_error_init(&error);
429 if (dbus_message_is_signal(msg, DNSMASQ_DBUS_INTERFACE,
431 if (!dbus_message_get_args(msg, &error,
432 DBUS_TYPE_STRING, &ip_addr,
433 DBUS_TYPE_STRING, &mac,
434 DBUS_TYPE_STRING, &name,
435 DBUS_TYPE_INVALID)) {
436 ERR("Cannot read message, cause: %s\n", error.message);
437 dbus_error_free(&error);
438 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
440 SDBG("DhcpConnected signal : %s %s %s\n", ip_addr, mac, name);
442 * DHCP ACK received, destroy timeout if exists
444 _destroy_dhcp_ack_timer(mac);
446 if (_get_tethering_type_from_ip(ip_addr, &type) != MOBILE_AP_ERROR_NONE)
447 return DBUS_HANDLER_RESULT_HANDLED;
449 if (_mobileap_is_enabled_by_type(type) == FALSE) {
450 return DBUS_HANDLER_RESULT_HANDLED;
453 info = (mobile_ap_station_info_t *)malloc(sizeof(mobile_ap_station_info_t));
455 ERR("malloc failed\n");
456 return DBUS_HANDLER_RESULT_HANDLED;
459 info->interface = type;
460 g_strlcpy(info->ip, ip_addr, sizeof(info->ip));
461 g_strlcpy(info->mac, mac, sizeof(info->mac));
462 if (type == MOBILE_AP_TYPE_WIFI || type == MOBILE_AP_TYPE_USB ||
463 type == MOBILE_AP_TYPE_WIFI_AP) {
465 info->hostname = g_strdup(MOBILE_AP_NAME_UNKNOWN);
467 info->hostname = g_strdup(name);
468 } else if (type == MOBILE_AP_TYPE_BT) {
469 _bt_get_remote_device_name(obj, mac, &bt_remote_device_name);
470 if (bt_remote_device_name == NULL)
471 info->hostname = g_strdup(MOBILE_AP_NAME_UNKNOWN);
473 info->hostname = bt_remote_device_name;
478 if (_add_station_info(info) != MOBILE_AP_ERROR_NONE) {
479 g_free(info->hostname);
481 return DBUS_HANDLER_RESULT_HANDLED;
484 _get_station_count((gconstpointer)type,
485 _slist_find_station_by_interface, &n_station);
487 _stop_timeout_cb(type);
489 _send_dbus_station_info("DhcpConnected", info);
491 return DBUS_HANDLER_RESULT_HANDLED;
492 } else if (dbus_message_is_signal(msg, DNSMASQ_DBUS_INTERFACE,
493 "DhcpLeaseDeleted")) {
494 if (!dbus_message_get_args(msg, &error,
495 DBUS_TYPE_STRING, &ip_addr,
496 DBUS_TYPE_STRING, &mac,
497 DBUS_TYPE_STRING, &name,
498 DBUS_TYPE_INVALID)) {
499 ERR("Cannot read message, cause: %s\n", error.message);
500 dbus_error_free(&error);
501 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
503 SDBG("DhcpLeaseDeleted signal : %s %s %s\n", ip_addr, mac, name);
505 _remove_station_info(ip_addr, _slist_find_station_by_ip_addr);
507 return DBUS_HANDLER_RESULT_HANDLED;
510 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
513 int main(int argc, char **argv)
515 const char *rule = "type='signal',interface='"DNSMASQ_DBUS_INTERFACE"'";
517 TetheringObject *tethering_obj = NULL;
518 DBusGConnection *tethering_bus = NULL;
519 DBusGProxy *tethering_bus_proxy = NULL;
520 DBusError dbus_error;
521 GError *error = NULL;
527 #if !GLIB_CHECK_VERSION(2,36,0)
531 mainloop = g_main_loop_new(NULL, FALSE);
532 if (mainloop == NULL) {
533 ERR("Couldn't create GMainLoop\n");
538 tethering_bus = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
540 ERR("Couldn't connect to system bus[%s]\n", error->message);
545 tethering_bus_proxy = dbus_g_proxy_new_for_name(tethering_bus,
546 DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);
547 if (tethering_bus_proxy == NULL) {
548 ERR("Failed to get a proxy for D-Bus\n");
551 if (!dbus_g_proxy_call(tethering_bus_proxy, "RequestName", &error,
552 G_TYPE_STRING, TETHERING_SERVICE_NAME,
553 G_TYPE_UINT, 0, G_TYPE_INVALID,
554 G_TYPE_UINT, &result, G_TYPE_INVALID)) {
555 ERR("dbus_g_proxy_call is failed\n");
557 ERR("D-Bus.RequestName RPC failed[%s]\n",
564 ERR("Failed to get the primary well-known name.\n");
567 g_object_unref(tethering_bus_proxy);
568 tethering_bus_proxy = NULL;
570 tethering_obj = g_object_new(TETHERING_TYPE_OBJECT, NULL);
571 if (tethering_obj == NULL) {
572 ERR("Failed to create one Tethering instance.\n");
575 dbus_g_connection_register_g_object(tethering_bus,
576 TETHERING_SERVICE_OBJECT_PATH, G_OBJECT(tethering_obj));
578 tethering_conn = dbus_g_connection_get_connection(tethering_bus);
579 dbus_error_init(&dbus_error);
580 dbus_bus_add_match(tethering_conn, rule, &dbus_error);
581 if (dbus_error_is_set(&dbus_error)) {
582 ERR("Cannot add D-BUS match rule, cause: %s", dbus_error.message);
583 dbus_error_free(&dbus_error);
586 dbus_connection_add_filter(tethering_conn, __dnsmasq_signal_filter, tethering_obj, NULL);
588 /* Platform modules */
589 if (appcore_set_i18n(MOBILEAP_LOCALE_COMMON_PKG, MOBILEAP_LOCALE_COMMON_RES) < 0) {
590 ERR("appcore_set_i18n is failed\n");
593 if (vconf_get_int(VCONFKEY_MOBILE_HOTSPOT_MODE, &mobileap_state) < 0) {
594 ERR("vconf_get_int is failed\n");
595 mobileap_state = MOBILE_AP_STATE_NONE;
598 _init_network((void *)tethering_obj);
599 _register_wifi_station_handler();
600 _register_vconf_cb((void *)tethering_obj);
602 ret = wifi_initialize();
603 if (ret != WIFI_ERROR_NONE) {
604 ERR("wifi_initialize() is failed : %d\n", ret);
607 ret = alarmmgr_init(APPNAME);
608 if (ret != ALARMMGR_RESULT_SUCCESS) {
609 ERR("alarmmgr_init(%s) is failed : %d\n", APPNAME, ret);
611 ret = alarmmgr_set_cb(_sp_timeout_handler, NULL);
612 if (ret != ALARMMGR_RESULT_SUCCESS) {
613 ERR("alarmmgr_set_cb is failed : %d\n", ret);
617 g_main_loop_run(mainloop);
621 ret = wifi_deinitialize();
622 if (ret != WIFI_ERROR_NONE) {
623 ERR("wifi_deinitialize() is failed : %d\n", ret);
626 _unregister_vconf_cb((void *)tethering_obj);
627 _unregister_wifi_station_handler();
630 dbus_connection_remove_filter(tethering_conn, __dnsmasq_signal_filter, tethering_obj);
631 dbus_bus_remove_match(tethering_conn, rule, NULL);
633 g_object_unref(tethering_obj);
634 dbus_g_connection_unref(tethering_bus);
641 g_object_unref(tethering_obj);
642 if (tethering_bus_proxy)
643 g_object_unref(tethering_bus_proxy);
645 dbus_g_connection_unref(tethering_bus);