tizen 2.4 release
[framework/connectivity/mobileap-agent.git] / src / mobileap_main.c
1 /*
2  * mobileap-agent
3  * Copyright (c) 2012 Samsung Electronics Co., Ltd.
4  *
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
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  */
17
18 #include <fcntl.h>
19 #include <unistd.h>
20 #include <glib.h>
21 #include <dbus/dbus.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include <time.h>
26 #include <dd-display.h>
27 #include <vconf.h>
28 #include <net_connection.h>
29 #include <appcore-common.h>
30 #include <wifi.h>
31 #include <alarm.h>
32
33 #include "mobileap_softap.h"
34 #include "mobileap_handler.h"
35 #include "mobileap_common.h"
36 #include "mobileap_bluetooth.h"
37 #include "mobileap_wifi.h"
38 #include "mobileap_usb.h"
39 #include "mobileap_network.h"
40 #include "mobileap_notification.h"
41 #include "mobileap_iptables.h"
42
43 GMainLoop *mainloop = NULL;
44 int mobileap_state = MOBILE_AP_STATE_NONE;
45
46 GDBusObjectManagerServer *manager_server = NULL;
47 guint owner_id = 0;
48 GDBusConnection *teth_gdbus_conn = NULL;
49 Tethering *tethering_obj = NULL;
50 static int init_count = 0;
51 guint conn_sig_id = 0;
52 guint deleted_sig_id = 0;
53 gboolean tethering_disable(Tethering *obj, GDBusMethodInvocation *context);
54 gboolean tethering_get_station_info(Tethering *obj,
55                 GDBusMethodInvocation *context);
56 gboolean tethering_get_data_packet_usage(Tethering *obj,
57                 GDBusMethodInvocation *context);
58
59 Tethering *_get_tethering_obj(void)
60 {
61         return tethering_obj;
62 }
63
64 gboolean _mobileap_set_state(int state)
65 {
66         int vconf_ret = 0;
67
68         mobileap_state |= state;
69
70         vconf_ret = vconf_set_int(VCONFKEY_MOBILE_HOTSPOT_MODE, mobileap_state);
71         if (vconf_ret != 0) {
72                 ERR("vconf_set_int is failed : %d\n", vconf_ret);
73                 return FALSE;
74         }
75
76         return TRUE;
77 }
78
79 gboolean _mobileap_is_disabled(void)
80 {
81         return mobileap_state ? FALSE : TRUE;
82 }
83
84 gboolean _mobileap_is_enabled(int state)
85 {
86         return (mobileap_state & state) ? TRUE : FALSE;
87 }
88
89 gboolean _mobileap_is_enabled_by_type(mobile_ap_type_e type)
90 {
91         switch (type) {
92         case MOBILE_AP_TYPE_WIFI:
93                 if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI))
94                         return TRUE;
95                 break;
96
97         case MOBILE_AP_TYPE_BT:
98                 if (_mobileap_is_enabled(MOBILE_AP_STATE_BT))
99                         return TRUE;
100                 break;
101
102         case MOBILE_AP_TYPE_USB:
103                 if (_mobileap_is_enabled(MOBILE_AP_STATE_USB))
104                         return TRUE;
105                 break;
106
107         case MOBILE_AP_TYPE_WIFI_AP:
108                 if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI_AP))
109                         return TRUE;
110                 break;
111
112         default:
113                 ERR("Unknow type : %d\n", type);
114                 break;
115         }
116
117         return FALSE;
118 }
119
120 gboolean _mobileap_clear_state(int state)
121 {
122         int vconf_ret = 0;
123
124         mobileap_state &= (~state);
125
126         vconf_ret = vconf_set_int(VCONFKEY_MOBILE_HOTSPOT_MODE, mobileap_state);
127         if (vconf_ret != 0) {
128                 ERR("vconf_set_int is failed : %d\n", vconf_ret);
129                 return FALSE;
130         }
131
132         return TRUE;
133 }
134
135 gboolean _terminate_mobileap_agent(gpointer user_data)
136 {
137         if (mainloop == NULL) {
138                 return FALSE;
139         }
140
141         if (!_mobileap_is_disabled()) {
142                 DBG("Tethering is enabled\n");
143                 return FALSE;
144         }
145
146         if (_is_trying_network_operation()) {
147                 DBG("Network operation is going on\n");
148                 return FALSE;
149         }
150
151         if (_is_trying_wifi_operation()) {
152                 DBG("Wi-Fi operation is going on\n");
153                 return FALSE;
154         }
155
156         if (_is_trying_bt_operation()) {
157                 DBG("BT operation is going on\n");
158                 return FALSE;
159         }
160
161         if (_is_trying_usb_operation()) {
162                 DBG("USB operation is going on\n");
163                 return FALSE;
164         }
165
166         DBG("All tethering / AP's are turned off\n");
167         g_main_loop_quit(mainloop);
168         mainloop = NULL;
169
170         return FALSE;
171 }
172
173 void _block_device_sleep(void)
174 {
175         int ret = 0;
176
177         ret = display_lock_state(LCD_OFF, STAY_CUR_STATE, 0);
178         if (ret < 0)
179                 ERR("PM control [ERROR] result = %d\n", ret);
180         else
181                 DBG("PM control [SUCCESS]\n");
182 }
183
184 void _unblock_device_sleep(void)
185 {
186         int ret = 0;
187
188         ret = display_unlock_state(LCD_OFF, PM_SLEEP_MARGIN);
189         if (ret < 0)
190                 ERR("PM control [ERROR] result = %d\n", ret);
191         else
192                 DBG("PM control [SUCCESS]\n");
193 }
194
195 int _init_tethering(void)
196 {
197         int ret = MOBILE_AP_ERROR_NONE;
198
199         DBG("init_count: %d\n", init_count);
200
201         if (init_count > 0) {
202                 init_count++;
203                 return MOBILE_AP_ERROR_NONE;
204         }
205
206         if (!_mobileap_is_enabled(MOBILE_AP_STATE_WIFI_AP)) {
207                 ret = _open_network();
208         }
209         _mh_core_execute_dhcp_server();
210
211         init_count++;
212
213         return ret;
214 }
215
216 gboolean _deinit_tethering(void)
217 {
218         DBG("obj->init_count: %d\n", init_count);
219
220         guint idle_id;
221
222         if (init_count > 1) {
223                 init_count--;
224                 return TRUE;
225         } else if (init_count <= 0) {
226                 ERR("Already deinitialized\n");
227                 init_count = 0;
228                 return TRUE;
229         }
230
231         init_count = 0;
232
233         _mh_core_terminate_dhcp_server();
234
235         if (!_mobileap_is_enabled(MOBILE_AP_STATE_WIFI_AP)) {
236                 _close_network();
237         }
238
239         idle_id = g_idle_add(_terminate_mobileap_agent, NULL);
240         if (idle_id == 0) {
241                 ERR("g_idle_add is failed\n");
242         }
243
244         return TRUE;
245 }
246
247 gboolean tethering_disable(Tethering *obj, GDBusMethodInvocation *context)
248 {
249         int ret = MOBILE_AP_ERROR_NONE;
250
251         DBG("+\n");
252         g_assert(obj != NULL);
253         g_assert(context != NULL);
254
255         if (_mobileap_is_disabled()) {
256                 ERR("Mobile hotspot has not been enabled\n");
257                 ret = MOBILE_AP_ERROR_NOT_ENABLED;
258                 tethering_complete_disable(obj, context, MOBILE_AP_DISABLE_CFM, ret);
259                 return FALSE;
260         }
261
262         _disable_wifi_tethering(obj);
263         _disable_bt_tethering(obj);
264         _disable_usb_tethering(obj);
265
266         tethering_complete_disable(obj, context, MOBILE_AP_DISABLE_CFM, ret);
267
268         return TRUE;
269 }
270
271 gboolean tethering_get_station_info(Tethering *obj,
272                         GDBusMethodInvocation *context)
273 {
274         DBG("+\n");
275
276         GVariant *var = NULL;
277
278         g_assert(obj != NULL);
279         g_assert(context != NULL);
280
281         var = _station_info_foreach();
282
283         g_dbus_method_invocation_return_value(context, var);
284         g_variant_unref(var);
285
286         DBG("-\n");
287         return TRUE;
288 }
289
290 gboolean tethering_get_data_packet_usage(Tethering *obj,
291                                 GDBusMethodInvocation *context)
292 {
293         char *if_name = NULL;
294         unsigned long long wifi_tx_bytes = 0;
295         unsigned long long wifi_rx_bytes = 0;
296         unsigned long long bt_tx_bytes = 0;
297         unsigned long long bt_rx_bytes = 0;
298         unsigned long long usb_tx_bytes = 0;
299         unsigned long long usb_rx_bytes = 0;
300         unsigned long long tx_bytes = 0;
301         unsigned long long rx_bytes = 0;
302
303         if (_get_network_interface_name(&if_name) == FALSE) {
304                 tethering_complete_get_data_packet_usage(obj, context,
305                                 MOBILE_AP_GET_DATA_PACKET_USAGE_CFM,
306                                 0ULL, 0ULL);
307                 return FALSE;
308         }
309
310         if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI))
311                 _get_data_usage(WIFI_IF, if_name,
312                                 &wifi_tx_bytes, &wifi_rx_bytes);
313
314         if (_mobileap_is_enabled(MOBILE_AP_STATE_BT))
315                 _get_data_usage(BT_IF_ALL, if_name,
316                                 &bt_tx_bytes, &bt_rx_bytes);
317
318         if (_mobileap_is_enabled(MOBILE_AP_STATE_USB))
319                 _get_data_usage(USB_IF, if_name,
320                                 &usb_tx_bytes, &usb_rx_bytes);
321         free(if_name);
322
323         tx_bytes = wifi_tx_bytes + bt_tx_bytes + usb_tx_bytes;
324         rx_bytes = wifi_rx_bytes + bt_rx_bytes + usb_rx_bytes;
325
326         tethering_complete_get_data_packet_usage(obj, context, MOBILE_AP_GET_DATA_PACKET_USAGE_CFM,
327                         tx_bytes, rx_bytes);
328
329         return TRUE;
330 }
331
332 void static __handle_dnsmasq_dhcp_status_changed_cb(GDBusConnection *connection,
333                         const gchar *sender_name, const gchar *object_path,
334                         const gchar *interface_name, const gchar *signal_name,
335                         GVariant *parameters, gpointer user_data)
336 {
337         DBG("+\n");
338         char *ip_addr = NULL;
339         char *mac = NULL;
340         char *name = NULL;
341         char *bt_remote_device_name = NULL;
342         mobile_ap_type_e type = MOBILE_AP_TYPE_MAX;
343         mobile_ap_station_info_t *info = NULL;
344         int n_station = 0;
345         time_t tm;
346
347         if (signal_name == NULL) {
348                 ERR("singal name is NULL\n");
349                 return;
350         }
351         g_variant_get(parameters, "(sss)",  &ip_addr, &mac, &name);
352         if (!g_strcmp0(signal_name, "DhcpConnected")) {
353                 SDBG("DhcpConnected signal : %s  %s %s\n", ip_addr, mac, name);
354                 /*
355                  * DHCP ACK received, destroy timeout if exists
356                  */
357                 if (ip_addr == NULL || mac == NULL) {
358                         goto EXIT;
359                 }
360                 _destroy_dhcp_ack_timer(mac);
361
362                 if (_get_tethering_type_from_ip(ip_addr, &type) != MOBILE_AP_ERROR_NONE)
363                         goto EXIT;
364
365                 if (_mobileap_is_enabled_by_type(type) == FALSE) {
366                         goto EXIT;
367                 }
368
369                 info = (mobile_ap_station_info_t *)g_malloc(sizeof(mobile_ap_station_info_t));
370                 if (info == NULL) {
371                         ERR("malloc failed\n");
372                         goto EXIT;
373                 }
374
375                 info->interface = type;
376                 g_strlcpy(info->ip, ip_addr, sizeof(info->ip));
377                 g_strlcpy(info->mac, mac, sizeof(info->mac));
378                 if (type == MOBILE_AP_TYPE_WIFI || type == MOBILE_AP_TYPE_USB ||
379                                 type == MOBILE_AP_TYPE_WIFI_AP) {
380                         if (name[0] == '\0')
381                                 info->hostname = g_strdup(MOBILE_AP_NAME_UNKNOWN);
382                         else
383                                 info->hostname = g_strdup(name);
384                 } else if (type == MOBILE_AP_TYPE_BT) {
385                         _bt_get_remote_device_name(mac, &bt_remote_device_name);
386                         if (bt_remote_device_name == NULL)
387                                 info->hostname = g_strdup(MOBILE_AP_NAME_UNKNOWN);
388                         else
389                                 info->hostname = bt_remote_device_name;
390                 }
391                 time(&tm);
392                 info->tm = tm;
393                 if (_add_station_info(info) != MOBILE_AP_ERROR_NONE) {
394                         ERR("_add_station_info is failed\n");
395                         g_free(info->hostname);
396                         g_free(info);
397                         goto EXIT;
398                 }
399
400                 _get_station_count((gconstpointer)type,
401                                 _slist_find_station_by_interface, &n_station);
402                 if (n_station == 1)
403                         _stop_timeout_cb(type);
404
405                 _send_dbus_station_info("DhcpConnected", info);
406         } else if (!g_strcmp0(signal_name, "DhcpLeaseDeleted")) {
407                 SDBG("DhcpLeaseDeleted signal : %s %s %s\n", ip_addr, mac, name);
408                 _remove_station_info(ip_addr, _slist_find_station_by_ip_addr);
409         } else {
410                 SDBG("UNKNOWN member signal\n");
411         }
412 EXIT :
413         g_free(ip_addr);
414         g_free(mac);
415         g_free(name);
416         DBG("-\n");
417 }
418
419 static void on_bus_acquired_cb (GDBusConnection *connection, const gchar *name,
420                                 gpointer user_data)
421 {
422         DBG("+\n");
423         GDBusInterfaceSkeleton *intf = NULL;
424         teth_gdbus_conn = connection;
425
426         manager_server = g_dbus_object_manager_server_new(TETHERING_SERVICE_OBJECT_PATH);
427         if(manager_server == NULL) {
428                 DBG("Manager server not created.");
429                 return;
430         }
431         tethering_obj = tethering_skeleton_new();
432         intf = G_DBUS_INTERFACE_SKELETON(tethering_obj);
433         if (!g_dbus_interface_skeleton_export(intf, connection,
434                         TETHERING_SERVICE_OBJECT_PATH, NULL)) {
435                 ERR("Export with path failed");
436         } else {
437                 DBG("Export sucessss");
438         }
439
440         g_signal_connect(tethering_obj, "handle-enable-wifi-tethering",
441                         G_CALLBACK(tethering_enable_wifi_tethering), NULL);
442         g_signal_connect(tethering_obj, "handle-enable-bt-tethering",
443                         G_CALLBACK(tethering_enable_bt_tethering), NULL);
444         g_signal_connect(tethering_obj, "handle-enable-usb-tethering",
445                         G_CALLBACK(tethering_enable_usb_tethering), NULL);
446         g_signal_connect(tethering_obj, "handle-disable-wifi-tethering",
447                         G_CALLBACK(tethering_disable_wifi_tethering), NULL);
448         g_signal_connect(tethering_obj, "handle-disable-bt-tethering",
449                         G_CALLBACK(tethering_disable_bt_tethering), NULL);
450         g_signal_connect(tethering_obj, "handle-disable-usb-tethering",
451                         G_CALLBACK(tethering_disable_usb_tethering), NULL);
452         g_signal_connect(tethering_obj, "handle-enable-wifi-ap",
453                         G_CALLBACK(tethering_enable_wifi_ap), NULL);
454
455         g_signal_connect(tethering_obj, "handle-disable-wifi-ap",
456                         G_CALLBACK(tethering_disable_wifi_ap), NULL);
457         g_signal_connect(tethering_obj, "handle-reload-wifi-settings",
458                         G_CALLBACK(tethering_reload_wifi_settings), NULL);
459         g_signal_connect(tethering_obj, "handle-reload-wifi-ap-settings",
460                         G_CALLBACK(tethering_reload_wifi_ap_settings), NULL);
461         g_signal_connect(tethering_obj, "handle-get-station-info",
462                         G_CALLBACK(tethering_get_station_info), NULL);
463         g_signal_connect(tethering_obj, "handle-get-data-packet-usage",
464                         G_CALLBACK(tethering_get_data_packet_usage), NULL);
465
466         _init_network((void *)tethering_obj);
467         _register_vconf_cb((void *)tethering_obj);
468
469         conn_sig_id = g_dbus_connection_signal_subscribe(connection, NULL, DNSMASQ_DBUS_INTERFACE,
470                         "DhcpConnected", NULL, NULL, G_DBUS_SIGNAL_FLAGS_NONE,
471                         __handle_dnsmasq_dhcp_status_changed_cb, NULL, NULL);
472         deleted_sig_id = g_dbus_connection_signal_subscribe(connection, NULL, DNSMASQ_DBUS_INTERFACE,
473                         "DhcpLeaseDeleted", NULL, NULL, G_DBUS_SIGNAL_FLAGS_NONE,
474                         __handle_dnsmasq_dhcp_status_changed_cb, NULL, NULL);
475
476         g_dbus_object_manager_server_set_connection(manager_server, connection);
477         DBG("-\n");
478 }
479
480 static void on_name_acquired_cb(GDBusConnection *connection, const gchar *name,
481                 gpointer user_data)
482 {
483         DBG("+\n");
484
485         DBG("-\n");
486 }
487
488 static void on_name_lost_db(GDBusConnection *conn, const gchar *name,
489                 gpointer user_data)
490 {
491         DBG("+\n");
492         /* May service name is already in use */
493         ERR("Service name is already in use");
494
495         /* The result of DBus name request is only permitted,
496          *  such as DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER.
497          */
498         exit(2);
499
500         DBG("-\n");
501 }
502
503 static int __tethering_setup_gdbus(void)
504 {
505         DBG("+\n");
506
507         owner_id = g_bus_own_name(DBUS_BUS_SYSTEM, TETHERING_SERVICE_NAME,
508                                 G_BUS_NAME_OWNER_FLAGS_NONE, on_bus_acquired_cb,
509                                 on_name_acquired_cb, on_name_lost_db, NULL, NULL);
510
511         if (!owner_id) {
512                 ERR("g_bus_own_name is failed\n");
513                 return -1;
514         }
515         return 0;
516 }
517 int main(int argc, char **argv)
518 {
519         int ret = 0;
520
521         DBG("+\n");
522
523 #if !GLIB_CHECK_VERSION(2,36,0)
524         g_type_init();
525 #endif
526
527         mainloop = g_main_loop_new(NULL, FALSE);
528         if (mainloop == NULL) {
529                 ERR("Couldn't create GMainLoop\n");
530                 return 0;
531         }
532
533         ret = __tethering_setup_gdbus();
534         if (ret < 0) {
535                 ERR("tethering_setup_gdbus is failed\n");
536                 return 0;
537         }
538         /* Platform modules */
539         if (appcore_set_i18n(MOBILEAP_LOCALE_COMMON_PKG, MOBILEAP_LOCALE_COMMON_RES) < 0) {
540                 ERR("appcore_set_i18n is failed\n");
541         }
542
543         if (vconf_get_int(VCONFKEY_MOBILE_HOTSPOT_MODE, &mobileap_state) < 0) {
544                 ERR("vconf_get_int is failed\n");
545                 mobileap_state = MOBILE_AP_STATE_NONE;
546         }
547
548         _register_wifi_station_handler();
549
550         ret = wifi_initialize();
551         if (ret != WIFI_ERROR_NONE) {
552                 ERR("wifi_initialize() is failed : %d\n", ret);
553         }
554
555         ret = alarmmgr_init(APPNAME);
556         if (ret != ALARMMGR_RESULT_SUCCESS) {
557                 ERR("alarmmgr_init(%s) is failed : %d\n", APPNAME, ret);
558         } else {
559                 ret = alarmmgr_set_cb(_sp_timeout_handler, NULL);
560                 if (ret != ALARMMGR_RESULT_SUCCESS) {
561                         ERR("alarmmgr_set_cb is failed : %d\n", ret);
562                 }
563         }
564
565         g_main_loop_run(mainloop);
566
567         alarmmgr_fini();
568
569         ret = wifi_deinitialize();
570         if (ret != WIFI_ERROR_NONE) {
571                 ERR("wifi_deinitialize() is failed : %d\n", ret);
572         }
573
574         _unregister_vconf_cb();
575         _unregister_wifi_station_handler();
576         _deinit_network();
577
578         g_dbus_connection_signal_unsubscribe(teth_gdbus_conn, conn_sig_id);
579         g_dbus_connection_signal_unsubscribe(teth_gdbus_conn, deleted_sig_id);
580
581         g_object_unref(tethering_obj);
582         g_bus_unown_name(owner_id);
583         g_object_unref(manager_server);
584         DBG("-\n");
585         return 0;
586 }