telephony: Fixed memory leak
[platform/upstream/connman.git] / plugins / telephony.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2012  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <errno.h>
27 #include <gdbus.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #define CONNMAN_API_SUBJECT_TO_CHANGE
32 #include <connman/dbus.h>
33 #include <connman/inet.h>
34 #include <connman/plugin.h>
35 #include <connman/network.h>
36 #include <connman/setting.h>
37 #include <connman/technology.h>
38
39 #include <connman.h>
40
41 #define PS_DBUS_SERVICE                         "com.tcore.ps"
42
43 #define PS_MASTER_INTERFACE                     PS_DBUS_SERVICE ".master"
44 #define PS_MODEM_INTERFACE                      PS_DBUS_SERVICE ".modem"
45 #define PS_SERVICE_INTERFACE            PS_DBUS_SERVICE ".service"
46 #define PS_CONTEXT_INTERFACE            PS_DBUS_SERVICE ".context"
47
48 /* methods */
49 #define GET_MODEMS                              "GetModems"
50 #define GET_SERVICES                    "GetServices"
51 #define GET_CONTEXTS                    "GetContexts"
52 #define ACTIVATE_CONTEXT                "Activate"
53 #define DEACTIVATE_CONTEXT              "Deactivate"
54 #define GET_PROPERTIES                  "GetProperties"
55 #define SET_PROPERTY                    "SetProperties"
56
57 /* signals */
58 #define MODEM_ADDED                             "ModemAdded"
59 #define MODEM_REMOVED                   "ModemRemoved"
60 #define SERVICE_ADDED                   "ServiceAdded"
61 #define SERVICE_REMOVED                 "ServiceRemoved"
62 #define CONTEXT_ADDED                   "ContextAdded"
63 #define CONTEXT_REMOVED                 "ContextRemoved"
64 #define PROPERTY_CHANGED                "PropertyChanged"
65
66 #define TIMEOUT 130000
67
68 #define STRING2BOOL(a)  (!(g_strcmp0(a, "TRUE")) ? (TRUE):(FALSE))
69
70 static DBusConnection *connection;
71 static GHashTable       *modem_hash;
72 static GHashTable       *service_hash;
73 static GHashTable       *network_hash;
74
75 struct telephony_service {
76         char *path;
77
78         gpointer p_modem;
79         char *act;
80         gboolean roaming; /* global roaming state */
81         gboolean ps_attached; /* packet service is available */
82 };
83
84 struct telephony_modem {
85         char *path;
86
87         char *operator;
88         gboolean powered;
89         gboolean sim_init;
90         gboolean flight_mode;
91         gboolean data_allowed;
92         gboolean roaming_allowed;
93
94         struct connman_device *device;
95         struct telephony_service *s_service;
96 };
97
98 struct telephony_network {
99         char *path;
100         int if_index;
101         gboolean routing_only;
102         gboolean ipv6_link_only;
103
104         struct connman_network *network;
105
106         enum connman_ipconfig_method ipv4_method;
107         struct connman_ipaddress *ipv4_address;
108
109         enum connman_ipconfig_method ipv6_method;
110         struct connman_ipaddress *ipv6_address;
111 };
112
113 static int telephony_default_subscription_id = 0;
114
115 /* function prototype */
116 static void telephony_connect(DBusConnection *connection, void *user_data);
117 static void telephony_disconnect(DBusConnection *connection, void *user_data);
118 static void __remove_modem(gpointer data);
119 static void __remove_service(gpointer data);
120 static void __remove_network(gpointer data);
121
122 static int __modem_probe(struct connman_device *device);
123 static void __modem_remove(struct connman_device *device);
124 static int __modem_enable(struct connman_device *device);
125 static int __modem_disable(struct connman_device *device);
126
127 static int __network_probe(struct connman_network *network);
128 static void __network_remove(struct connman_network *network);
129 static int __network_connect(struct connman_network *network);
130 static int __network_disconnect(struct connman_network *network);
131
132
133 /* dbus request and reply */
134 static int __dbus_request(const char *path, const char *interface,
135                         const char *method,
136                         DBusPendingCallNotifyFunction notify, void *user_data,
137                         DBusFreeFunction free_function, int type, ...);
138
139 static int __request_get_modems(void);
140 static void __response_get_modems(DBusPendingCall *call, void *user_data);
141 static int __request_get_services(const char *path);
142 static void __response_get_services(DBusPendingCall *call, void *user_data);
143 static int __request_get_contexts(struct telephony_modem *modem);
144 static void __response_get_contexts(DBusPendingCall *call, void *user_data);
145 static int __request_network_activate(struct connman_network *network);
146 static void __response_network_activate(DBusPendingCall *call, void *user_data);
147 static int __request_network_deactivate(struct connman_network *network);
148
149 /* telephony internal function */
150 static void __add_modem(const char *path, DBusMessageIter *prop);
151 static void __add_service(struct telephony_modem *modem,
152                         const char *service_path, DBusMessageIter *prop);
153 static void __add_connman_device(const char *modem_path, const char *operator);
154 static void __remove_connman_device(struct telephony_modem *modem);
155 static void __remove_connman_networks(struct connman_device *device);
156 static int __add_context(struct connman_device *device, const char *path,
157                                                         DBusMessageIter *prop);
158
159 /* signal handler */
160 static gboolean __changed_modem(DBusConnection *connection,
161                                 DBusMessage *message, void *user_data);
162 static gboolean __added_modem(DBusConnection *connection,
163                                 DBusMessage *message, void *user_data);
164 static gboolean __removed_modem(DBusConnection *connection,
165                                 DBusMessage *message, void *user_data);
166 static gboolean __changed_service(DBusConnection *connection,
167                                 DBusMessage *message, void *user_data);
168 static gboolean __added_service(DBusConnection *connection,
169                                 DBusMessage *message, void *user_data);
170 static gboolean __removed_service(DBusConnection *connection,
171                                 DBusMessage *message, void *user_data);
172 static gboolean __changed_context(DBusConnection *connection,
173                                 DBusMessage *message, void *user_data);
174 static gboolean __added_context(DBusConnection *connection,
175                                 DBusMessage *message, void *user_data);
176 static gboolean __removed_context(DBusConnection *connection,
177                                 DBusMessage *message, void *user_data);
178
179 /* device driver */
180 static struct connman_device_driver modem_driver = {
181         .name           = "device",
182         .type           = CONNMAN_DEVICE_TYPE_CELLULAR,
183         .probe          = __modem_probe,
184         .remove         = __modem_remove,
185         .enable         = __modem_enable,
186         .disable        = __modem_disable,
187 };
188
189 /* network driver */
190 static struct connman_network_driver network_driver = {
191         .name           = "network",
192         .type           = CONNMAN_NETWORK_TYPE_CELLULAR,
193         .probe          = __network_probe,
194         .remove         = __network_remove,
195         .connect        = __network_connect,
196         .disconnect     = __network_disconnect,
197 };
198
199 static int tech_probe(struct connman_technology *technology)
200 {
201         return 0;
202 }
203
204 static void tech_remove(struct connman_technology *technology)
205 {
206         return;
207 }
208
209 static struct connman_technology_driver tech_driver = {
210         .name           = "cellular",
211         .type           = CONNMAN_SERVICE_TYPE_CELLULAR,
212         .probe          = tech_probe,
213         .remove         = tech_remove,
214 };
215
216 /* local function */
217 static void telephony_connect(DBusConnection *connection, void *user_data)
218 {
219         DBG("connection %p", connection);
220         modem_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
221                                                 g_free, __remove_modem);
222         service_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
223                                                 g_free, __remove_service);
224         network_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
225                                                 g_free, __remove_network);
226
227         __request_get_modems();
228 }
229
230 static void telephony_disconnect(DBusConnection *connection, void *user_data)
231 {
232         DBG("connection %p", connection);
233
234         if (modem_hash != NULL) {
235                 g_hash_table_destroy(modem_hash);
236                 modem_hash = NULL;
237         }
238
239         if (network_hash != NULL) {
240                 g_hash_table_destroy(network_hash);
241                 network_hash = NULL;
242         }
243 }
244
245 static void __remove_modem(gpointer data)
246 {
247         struct telephony_modem *modem = data;
248
249         __remove_connman_device(modem);
250
251         g_free(modem->path);
252         g_free(modem->operator);
253         g_free(modem);
254 }
255
256 static void __remove_service(gpointer data)
257 {
258         struct telephony_service *service = data;
259
260         g_free(service->path);
261         g_free(service->act);
262         g_free(service);
263 }
264
265 static void __remove_network(gpointer data)
266 {
267         struct telephony_network *info = data;
268         struct connman_device *device;
269
270         device = connman_network_get_device(info->network);
271         if (device != NULL)
272                 connman_device_remove_network(device, info->network);
273
274         connman_network_unref(info->network);
275
276         g_free(info->path);
277
278         connman_ipaddress_free(info->ipv4_address);
279         connman_ipaddress_free(info->ipv6_address);
280
281         g_free(info);
282 }
283
284 static void __set_device_powered(struct telephony_modem *modem,
285                                         gboolean powered)
286 {
287         DBG("set modem(%s) powered(%d)", modem->path, powered);
288
289         if (modem->device)
290                 connman_device_set_powered(modem->device, powered);
291 }
292
293 static int __check_device_powered(const char *path, gboolean powered)
294 {
295         struct telephony_modem *modem = g_hash_table_lookup(modem_hash, path);
296
297         if (modem == NULL)
298                 return -ENODEV;
299
300         DBG("check modem (%s) powered (%d)", modem->path, modem->powered);
301
302         if (modem->powered == powered)
303                 return -EALREADY;
304
305         return 0;
306 }
307
308 static int __modem_probe(struct connman_device *device)
309 {
310         DBG("device %p", device);
311         return 0;
312 }
313
314 static void __modem_remove(struct connman_device *device)
315 {
316         DBG("device %p", device);
317 }
318
319 static int __modem_enable(struct connman_device *device)
320 {
321         const char *path = connman_device_get_string(device, "Path");
322         DBG("device %p, path, %s", device, path);
323
324         return __check_device_powered(path, TRUE);
325 }
326
327 static int __modem_disable(struct connman_device *device)
328 {
329         const char *path = connman_device_get_string(device, "Path");
330         DBG("device %p, path, %s", device, path);
331
332         return __check_device_powered(path, FALSE);
333 }
334
335 static int __network_probe(struct connman_network *network)
336 {
337         DBG("network_prove network(%p)", network);
338         return 0;
339 }
340
341 static int __network_connect(struct connman_network *network)
342 {
343         DBG("network %p", network);
344
345         return __request_network_activate(network);
346 }
347
348 static int __network_disconnect(struct connman_network *network)
349 {
350         DBG("network %p", network);
351
352         if (connman_network_get_associating(network) == TRUE)
353                 connman_network_clear_associating(network);
354
355         connman_network_set_associating(network, FALSE);
356
357         return __request_network_deactivate(network);
358 }
359
360 static void __network_remove(struct connman_network *network)
361 {
362         char const *path = connman_network_get_string(network, "Path");
363         DBG("network %p path %s", network, path);
364
365         g_hash_table_remove(network_hash, path);
366 }
367
368 static int __dbus_request(const char *path, const char *interface,
369                 const char *method,
370                 DBusPendingCallNotifyFunction notify, void *user_data,
371                 DBusFreeFunction free_function, int type, ...)
372 {
373         DBusMessage *message;
374         DBusPendingCall *call;
375         dbus_bool_t ok;
376         va_list va;
377
378         DBG("path %s %s.%s", path, interface, method);
379
380         if (path == NULL)
381                 return -EINVAL;
382
383         message = dbus_message_new_method_call(PS_DBUS_SERVICE, path, interface, method);
384         if (message == NULL)
385                 return -ENOMEM;
386
387         dbus_message_set_auto_start(message, FALSE);
388
389         va_start(va, type);
390         ok = dbus_message_append_args_valist(message, type, va);
391         va_end(va);
392
393         if (!ok) {
394                 dbus_message_unref(message);
395                 return -ENOMEM;
396         }
397
398         if (dbus_connection_send_with_reply(connection, message,
399                                                 &call, TIMEOUT) == FALSE) {
400                 connman_error("Failed to call %s.%s", interface, method);
401                 dbus_message_unref(message);
402                 return -EINVAL;
403         }
404
405         if (call == NULL) {
406                 connman_error("D-Bus connection not available");
407                 dbus_message_unref(message);
408                 return -EINVAL;
409         }
410
411         dbus_pending_call_set_notify(call, notify, user_data, free_function);
412
413         dbus_message_unref(message);
414
415         return -EINPROGRESS;
416 }
417
418 static int __request_get_modems(void)
419 {
420         DBG("request get modem");
421         /* call connect master */
422         return __dbus_request("/", PS_MASTER_INTERFACE, GET_MODEMS,
423                         __response_get_modems, NULL, NULL, DBUS_TYPE_INVALID);
424 }
425
426 static void __response_get_modems(DBusPendingCall *call, void *user_data)
427 {
428         DBusMessage *reply;
429         DBusError error;
430         DBusMessageIter args, dict;
431
432         DBG("");
433
434         reply = dbus_pending_call_steal_reply(call);
435
436         dbus_error_init(&error);
437
438         if (dbus_set_error_from_message(&error, reply)) {
439                 connman_error("GetModems() %s %s", error.name, error.message);
440                 dbus_error_free(&error);
441                 goto done;
442         }
443
444         DBG("message signature (%s)", dbus_message_get_signature(reply));
445
446         if (dbus_message_iter_init(reply, &args) == FALSE)
447                 goto done;
448
449         dbus_message_iter_recurse(&args, &dict);
450
451         /* DBG("message type (%d) dic(%d)",
452          *      dbus_message_iter_get_arg_type(&dict), DBUS_TYPE_DICT_ENTRY);
453          */
454
455         while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
456                 DBusMessageIter entry, property;
457                 const char *modem_path;
458
459                 dbus_message_iter_recurse(&dict, &entry);
460                 dbus_message_iter_get_basic(&entry, &modem_path);
461                 DBG("modem path (%s)", modem_path);
462
463                 dbus_message_iter_next(&entry);
464                 dbus_message_iter_recurse(&entry, &property);
465
466                 __add_modem(modem_path, &property);
467
468                 dbus_message_iter_next(&dict);
469         }
470
471 done:
472         dbus_message_unref(reply);
473         dbus_pending_call_unref(call);
474 }
475
476 static int __request_get_services(const char *path)
477 {
478         DBG("request get service");
479         return __dbus_request(path, PS_MODEM_INTERFACE, GET_SERVICES,
480                         __response_get_services, g_strdup(path),
481                         g_free, DBUS_TYPE_INVALID);
482 }
483
484 static void __response_get_services(DBusPendingCall *call, void *user_data)
485 {
486         DBusMessage *reply;
487         DBusError error;
488         DBusMessageIter args, dict;
489
490         const char *path = user_data;
491         struct telephony_modem *modem;
492
493         modem = g_hash_table_lookup(modem_hash, path);
494
495         DBG("");
496
497         reply = dbus_pending_call_steal_reply(call);
498
499         dbus_error_init(&error);
500
501         if (dbus_set_error_from_message(&error, reply)) {
502                 connman_error("GetServices() %s %s", error.name, error.message);
503                 dbus_error_free(&error);
504                 goto done;
505         }
506
507         if (modem == NULL || modem->device == NULL)
508                 goto done;
509
510         DBG("message signature (%s)", dbus_message_get_signature(reply));
511
512         if (dbus_message_iter_init(reply, &args) == FALSE)
513                 goto done;
514
515         dbus_message_iter_recurse(&args, &dict);
516
517         /* DBG("message type (%d) dic(%d)",
518          *       dbus_message_iter_get_arg_type(&dict), DBUS_TYPE_DICT_ENTRY);
519          */
520
521         while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
522                 DBusMessageIter entry, property;
523                 const char *service_path;
524
525                 dbus_message_iter_recurse(&dict, &entry);
526                 dbus_message_iter_get_basic(&entry, &service_path);
527                 DBG("service path (%s)", service_path);
528
529                 dbus_message_iter_next(&entry);
530                 dbus_message_iter_recurse(&entry, &property);
531
532                 __add_service(modem, service_path, &property);
533
534                 dbus_message_iter_next(&dict);
535         }
536
537 done:
538         dbus_message_unref(reply);
539         dbus_pending_call_unref(call);
540 }
541
542 static int __request_get_contexts(struct telephony_modem *modem)
543 {
544         DBG("request get contexts");
545         return __dbus_request(modem->s_service->path,
546                         PS_SERVICE_INTERFACE, GET_CONTEXTS,
547                         __response_get_contexts, g_strdup(modem->path),
548                         g_free, DBUS_TYPE_INVALID);
549 }
550
551 static void __response_get_contexts(DBusPendingCall *call, void *user_data)
552 {
553         DBusError error;
554         DBusMessage *reply;
555         DBusMessageIter args, dict;
556
557         const char *path = user_data;
558         struct telephony_modem *modem;
559
560         DBG("");
561
562         modem = g_hash_table_lookup(modem_hash, path);
563         if (modem == NULL)
564                 return;
565         if (modem->s_service == NULL)
566                         return;
567         if (modem->device == NULL)
568                 return;
569
570         reply = dbus_pending_call_steal_reply(call);
571
572         dbus_error_init(&error);
573
574         if (dbus_set_error_from_message(&error, reply)) {
575                 connman_error("GetContexts() %s %s", error.name, error.message);
576                 dbus_error_free(&error);
577                 goto done;
578         }
579
580         DBG("message signature (%s)", dbus_message_get_signature(reply));
581
582         if (dbus_message_iter_init(reply, &args) == FALSE)
583                 goto done;
584
585         dbus_message_iter_recurse(&args, &dict);
586
587         while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
588                 DBusMessageIter entry, property;
589                 const char *context_path;
590
591                 dbus_message_iter_recurse(&dict, &entry);
592                 dbus_message_iter_get_basic(&entry, &context_path);
593                 DBG("context path (%s)", context_path);
594
595                 dbus_message_iter_next(&entry);
596                 dbus_message_iter_recurse(&entry, &property);
597
598                 __add_context(modem->device, context_path, &property);
599
600                 dbus_message_iter_next(&dict);
601         }
602
603 done:
604         dbus_message_unref(reply);
605         dbus_pending_call_unref(call);
606 }
607
608 static int __request_network_activate(struct connman_network *network)
609 {
610         int n_modems;
611         const char *path = NULL;
612         struct telephony_modem *modem = NULL;
613
614         n_modems = g_hash_table_size(modem_hash);
615         path = connman_network_get_string(network, "Path");
616         modem = connman_device_get_data(connman_network_get_device(network));
617         DBG("network %p, path %s, modem %s[%d]", network, path, modem->path,
618                         telephony_default_subscription_id);
619
620         if (modem && n_modems > 1 && g_str_has_suffix(path, "_1") == TRUE) {
621                 char *subscribe_id = g_strdup_printf("%d", telephony_default_subscription_id);
622
623                 if (g_str_has_suffix(modem->path, subscribe_id) != TRUE) {
624                         g_free(subscribe_id);
625                         return -ENOLINK;
626                 }
627                 g_free(subscribe_id);
628         }
629
630         return __dbus_request(path, PS_CONTEXT_INTERFACE, ACTIVATE_CONTEXT,
631                         __response_network_activate,
632                         g_strdup(path), NULL, DBUS_TYPE_INVALID);
633 }
634
635 static gboolean __check_network_available(struct connman_network *network)
636 {
637         if (network == NULL || connman_network_get_device(network) == NULL)
638                 return FALSE;
639
640         return TRUE;
641 }
642
643 static void __response_network_activate(DBusPendingCall *call, void *user_data)
644 {
645         DBG("network activation response");
646
647         DBusError error;
648         DBusMessage *reply;
649
650         struct telephony_network *info;
651         const char *path = user_data;
652
653         info = g_hash_table_lookup(network_hash, path);
654         reply = dbus_pending_call_steal_reply(call);
655
656         if (info == NULL)
657                 goto done;
658
659         if (__check_network_available(info->network) == FALSE) {
660                 g_hash_table_remove(network_hash, path);
661                 goto done;
662         }
663
664         dbus_error_init(&error);
665         if (dbus_set_error_from_message(&error, reply)) {
666                 connman_error("connection activate() %s %s",
667                                         error.name, error.message);
668
669                 if (connman_network_get_associating(info->network) == TRUE)
670                         connman_network_set_error(info->network,
671                                         CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
672
673                 if (connman_network_get_connecting(info->network) == TRUE)
674                         connman_network_set_error(info->network,
675                                         CONNMAN_NETWORK_ERROR_CONNECT_FAIL);
676
677                 if (connman_network_get_index(info->network) < 0)
678                         connman_network_set_error(info->network,
679                                         CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
680
681                 dbus_error_free(&error);
682                 goto done;
683         }
684
685 done:
686         dbus_message_unref(reply);
687         dbus_pending_call_unref(call);
688 }
689
690 static int __request_network_deactivate(struct connman_network *network)
691 {
692         const char *path = connman_network_get_string(network, "Path");
693         DBG("network %p, path %s", network, path);
694
695         return __dbus_request(path, PS_CONTEXT_INTERFACE, DEACTIVATE_CONTEXT,
696                         NULL, NULL, NULL, DBUS_TYPE_INVALID);
697 }
698
699 static void __response_get_default_subscription_id(DBusPendingCall *call,
700                 void *user_data)
701 {
702         DBusMessage *reply;
703         DBusError error;
704         DBusMessageIter args;
705
706         DBG("");
707
708         reply = dbus_pending_call_steal_reply(call);
709
710         dbus_error_init(&error);
711         if (dbus_set_error_from_message(&error, reply)) {
712                 connman_error("GetDefaultDataSubscription() %s %s", error.name, error.message);
713                 dbus_error_free(&error);
714                 goto done;
715         }
716
717         DBG("message signature (%s)", dbus_message_get_signature(reply));
718
719         if (dbus_message_iter_init(reply, &args) == FALSE)
720                 goto done;
721
722         dbus_message_iter_get_basic(&args, &telephony_default_subscription_id);
723         DBG("default subscription: %d", telephony_default_subscription_id);
724
725 done:
726         dbus_message_unref(reply);
727         dbus_pending_call_unref(call);
728 }
729
730 static int __request_get_default_subscription_id(const char *path)
731 {
732         int ret;
733         char *telephony_modem_path = NULL;
734
735         telephony_modem_path = g_strdup_printf("/org/tizen/telephony%s", path);
736         DBG("request get default subscription id %s", telephony_modem_path);
737
738         ret = __dbus_request(telephony_modem_path,
739                         "org.tizen.telephony.Network", "GetDefaultDataSubscription",
740                         __response_get_default_subscription_id, NULL, NULL, DBUS_TYPE_INVALID);
741
742         g_free(telephony_modem_path);
743         return ret;
744 }
745
746 static void __add_modem(const char *path, DBusMessageIter *prop)
747 {
748         struct telephony_modem *modem;
749
750         modem = g_hash_table_lookup(modem_hash, path);
751         if (modem != NULL)
752                 return;
753
754         modem = g_try_new0(struct telephony_modem, 1);
755         if (modem == NULL)
756                 return;
757
758         modem->path = g_strdup(path);
759         modem->device = NULL;
760         modem->s_service = NULL;
761
762         g_hash_table_insert(modem_hash, g_strdup(path), modem);
763
764         while (dbus_message_iter_get_arg_type(prop) != DBUS_TYPE_INVALID) {
765                 DBusMessageIter entry;
766                 const char *key, *tmp;
767
768                 dbus_message_iter_recurse(prop, &entry);
769                 dbus_message_iter_get_basic(&entry, &key);
770
771                 dbus_message_iter_next(&entry);
772                 dbus_message_iter_get_basic(&entry, &tmp);
773
774                 DBG("key (%s) value(%s)", key, tmp);
775
776                 if (g_strcmp0(key, "powered") == 0) {
777                         modem->powered = STRING2BOOL(tmp);
778                 } else if (g_strcmp0(key, "operator") == 0) {
779                         modem->operator = g_strdup(tmp);
780                 } else if (g_strcmp0(key, "sim_init") == 0) {
781                         modem->sim_init = STRING2BOOL(tmp);
782                 } else if (g_strcmp0(key, "flight_mode") == 0) {
783                         modem->flight_mode = STRING2BOOL(tmp);
784                 } else if (g_strcmp0(key, "roaming_allowed") == 0) {
785                         modem->roaming_allowed = STRING2BOOL(tmp);
786                 } else if (g_strcmp0(key, "data_allowed") == 0) {
787                         modem->data_allowed = STRING2BOOL(tmp);
788                 }
789                 dbus_message_iter_next(prop);
790         }
791
792         __add_connman_device(path, modem->operator);
793         __set_device_powered(modem, modem->powered);
794
795         if (g_hash_table_size(modem_hash) > 1)
796                 __request_get_default_subscription_id(modem->path);
797
798         if (modem->powered != TRUE) {
799                 DBG("modem is not powered");
800                 return;
801         }
802
803         __request_get_services(modem->path);
804 }
805
806 static void __add_service(struct telephony_modem *modem,
807                                 const char *service_path, DBusMessageIter *prop)
808 {
809         struct telephony_service *service;
810
811         if (modem->s_service != NULL)
812                 return;
813
814         service = g_try_new0(struct telephony_service, 1);
815         if (service == NULL)
816                 return;
817
818         service->path = g_strdup(service_path);
819         service->p_modem = modem;
820         g_hash_table_insert(service_hash, g_strdup(service_path), service);
821
822         while (dbus_message_iter_get_arg_type(prop) != DBUS_TYPE_INVALID) {
823                 DBusMessageIter entry;
824                 const char *key, *tmp;
825
826                 dbus_message_iter_recurse(prop, &entry);
827                 dbus_message_iter_get_basic(&entry, &key);
828
829                 dbus_message_iter_next(&entry);
830                 dbus_message_iter_get_basic(&entry, &tmp);
831
832                 DBG("key (%s) value(%s)", key, tmp);
833
834                 if (g_strcmp0(key, "roaming") == 0) {
835                         service->roaming = STRING2BOOL(tmp);
836                 } else if (g_strcmp0(key, "act") == 0) {
837                         service->act = g_strdup(tmp);
838                 } else if (g_strcmp0(key, "ps_attached") == 0) {
839                         service->ps_attached = STRING2BOOL(tmp);
840                 }
841
842                 dbus_message_iter_next(prop);
843         }
844
845         modem->s_service = service;
846         __request_get_contexts(modem);
847 }
848
849 static char *__get_ident(const char *path)
850 {
851         char *pos;
852
853         if (*path != '/')
854                 return NULL;
855
856         pos = strrchr(path, '/');
857         if (pos == NULL)
858                 return NULL;
859
860         return pos + 1;
861 }
862
863 static void __add_connman_device(const char *modem_path, const char *operator)
864 {
865         char* ident = NULL;
866         struct telephony_modem *modem;
867         struct connman_device *device;
868
869         DBG("path %s operator %s", modem_path, operator);
870
871         if (modem_path == NULL)
872                 return;
873
874         if (operator == NULL)
875                 return;
876
877         modem = g_hash_table_lookup(modem_hash, modem_path);
878         if (modem == NULL)
879                 return;
880
881         if (modem->device) {
882                 if (!g_strcmp0(operator,
883                                 connman_device_get_ident(modem->device)))
884                         return;
885
886                 __remove_connman_device(modem);
887         }
888
889         if (strlen(operator) == 0)
890                 return;
891
892         device = connman_device_create(operator, CONNMAN_DEVICE_TYPE_CELLULAR);
893         if (device == NULL)
894                 return;
895
896         ident = g_strdup_printf("%s_%s", __get_ident(modem_path), operator);
897         connman_device_set_ident(device, ident);
898         g_free(ident);
899
900         connman_device_set_string(device, "Path", modem_path);
901         connman_device_set_data(device, modem);
902
903         if (connman_device_register(device) < 0) {
904                 connman_error("Failed to register cellular device");
905                 connman_device_unref(device);
906                 return;
907         }
908
909         modem->device = device;
910 }
911
912 static void __remove_connman_device(struct telephony_modem *modem)
913 {
914         DBG("modem %p path %s device %p", modem, modem->path, modem->device);
915
916         if (modem->device == NULL)
917                 return;
918
919         __remove_connman_networks(modem->device);
920
921         connman_device_unregister(modem->device);
922         connman_device_unref(modem->device);
923
924         modem->device = NULL;
925 }
926
927 static void __remove_connman_networks(struct connman_device *device)
928 {
929         GHashTableIter iter;
930         gpointer key, value;
931         GSList *info_list = NULL;
932         GSList *list;
933
934         if (network_hash == NULL)
935                 return;
936
937         g_hash_table_iter_init(&iter, network_hash);
938
939         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
940                 struct telephony_network *info = value;
941
942                 if (connman_network_get_device(info->network) != device)
943                         continue;
944
945                 info_list = g_slist_append(info_list, info);
946         }
947
948         for (list = info_list; list != NULL; list = list->next) {
949                 struct telephony_network *info = list->data;
950                 connman_device_remove_network(device, info->network);
951         }
952
953         g_slist_free(info_list);
954 }
955
956 static gboolean connman_ipaddress_updated(struct connman_ipaddress *ipaddress,
957                                         const char *address, const char *gateway)
958 {
959         if (ipaddress == NULL || address == NULL)
960                 return FALSE;
961
962         if (g_strcmp0(ipaddress->local, address) != 0)
963                 return TRUE;
964
965         if (g_strcmp0(ipaddress->gateway, gateway) != 0)
966                 return TRUE;
967
968         return FALSE;
969 }
970
971 static void __set_network_connected(struct telephony_network *network,
972                                         gboolean connected)
973 {
974         gboolean setip = FALSE;
975
976         DBG("network %p connected %d", network, connected);
977
978         connman_network_set_index(network->network, network->if_index);
979         if (connman_network_get_connected(network->network) == connected)
980                 return;
981
982         switch (network->ipv4_method) {
983         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
984         case CONNMAN_IPCONFIG_METHOD_DHCP:
985         case CONNMAN_IPCONFIG_METHOD_AUTO:
986         case CONNMAN_IPCONFIG_METHOD_OFF:
987                 connman_network_set_ipv4_method(network->network,
988                                                         network->ipv4_method);
989                 break;
990         case CONNMAN_IPCONFIG_METHOD_MANUAL:
991         case CONNMAN_IPCONFIG_METHOD_FIXED:
992                 connman_network_set_ipv4_method(network->network,
993                                                         network->ipv4_method);
994                 connman_network_set_ipaddress(network->network,
995                                                         network->ipv4_address);
996                 setip = TRUE;
997                 break;
998         }
999
1000         switch (network->ipv6_method) {
1001         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1002         case CONNMAN_IPCONFIG_METHOD_OFF:
1003         case CONNMAN_IPCONFIG_METHOD_DHCP:
1004                 break;
1005         case CONNMAN_IPCONFIG_METHOD_AUTO:
1006                 connman_network_set_ipv6_method(network->network,
1007                                                         network->ipv6_method);
1008                 setip = TRUE;
1009                 break;
1010         case CONNMAN_IPCONFIG_METHOD_MANUAL:
1011         case CONNMAN_IPCONFIG_METHOD_FIXED:
1012                 connman_network_set_ipv6_method(network->network,
1013                                                         network->ipv6_method);
1014                 connman_network_set_ipaddress(network->network,
1015                                                         network->ipv6_address);
1016                 setip = TRUE;
1017                 break;
1018         }
1019
1020         if (setip == TRUE)
1021                 connman_network_set_connected(network->network, connected);
1022 }
1023
1024 static gboolean __set_network_context(
1025                                                         struct telephony_network *network,
1026                                                         DBusMessageIter *dict)
1027 {
1028         int index = 0;
1029         gboolean active = FALSE;
1030         gboolean routing_only = FALSE;
1031         gboolean ipv4_updated = FALSE;
1032         gboolean ipv6_updated = FALSE;
1033         gboolean ipv6_link_only = FALSE;
1034         gboolean default_internet = FALSE;
1035         gboolean active_proxy = FALSE;
1036         char **proxies = NULL;
1037         const char *dev_name = NULL;
1038         const char *proxy_addr = NULL;
1039         char *ipv4_addr = NULL, *ipv4_gw = NULL, *ipv4_netmask = NULL,
1040                                         *ipv4_dns1 = NULL, *ipv4_dns2 = NULL;
1041         char *ipv6_addr = NULL, *ipv6_gw = NULL, *ipv6_netmask = NULL,
1042                                         *ipv6_dns1 = NULL, *ipv6_dns2 = NULL;
1043         struct connman_service *service;
1044
1045         while (dbus_message_iter_get_arg_type(dict) != DBUS_TYPE_INVALID) {
1046                 DBusMessageIter entry;
1047                 const char *key, *value;
1048
1049                 dbus_message_iter_recurse(dict, &entry);
1050                 dbus_message_iter_get_basic(&entry, &key);
1051
1052                 dbus_message_iter_next(&entry);
1053
1054                 if (g_strcmp0(key, "dev_name") == 0) {
1055                         dbus_message_iter_get_basic(&entry, &dev_name);
1056                         DBG("dev_name (%s)", dev_name);
1057                 } else if (g_strcmp0(key, "proxy") == 0) {
1058                         dbus_message_iter_get_basic(&entry, &proxy_addr);
1059                         DBG("proxy_addr (%s)", proxy_addr);
1060                 } else if (g_strcmp0(key, "ipv4_address") == 0) {
1061                         dbus_message_iter_get_basic(&entry, &ipv4_addr);
1062                         DBG("ipv4_addr (%s)", ipv4_addr);
1063                 } else if (g_strcmp0(key, "ipv4_gateway") == 0) {
1064                         dbus_message_iter_get_basic(&entry, &ipv4_gw);
1065                         DBG("ipv4_gw (%s)", ipv4_gw);
1066                 } else if (g_strcmp0(key, "ipv4_netmask") == 0) {
1067                         dbus_message_iter_get_basic(&entry, &ipv4_netmask);
1068                         DBG("ipv4_netmask (%s)", ipv4_netmask);
1069                 } else if (g_strcmp0(key, "ipv4_dns1") == 0) {
1070                         dbus_message_iter_get_basic(&entry, &ipv4_dns1);
1071                         DBG("ipv4_dns1 (%s)", ipv4_dns1);
1072                 } else if (g_strcmp0(key, "ipv4_dns2") == 0) {
1073                         dbus_message_iter_get_basic(&entry, &ipv4_dns2);
1074                         DBG("ipv4_dns2 (%s)", ipv4_dns2);
1075                 } else if (g_strcmp0(key, "ipv6_address") == 0) {
1076                         dbus_message_iter_get_basic(&entry, &ipv6_addr);
1077                         DBG("ipv6 address (%s)", ipv6_addr);
1078                 } else if (g_strcmp0(key, "ipv6_gateway") == 0) {
1079                         dbus_message_iter_get_basic(&entry, &ipv6_gw);
1080                         DBG("ipv6_gw (%s)", ipv6_gw);
1081                 } else if (g_strcmp0(key, "ipv6_netmask") == 0) {
1082                         dbus_message_iter_get_basic(&entry, &ipv6_netmask);
1083                         DBG("ipv6_netmask (%s)", ipv6_netmask);
1084                 } else if (g_strcmp0(key, "ipv6_dns1") == 0) {
1085                         dbus_message_iter_get_basic(&entry, &ipv6_dns1);
1086                         DBG("ipv6_dns1 (%s)", ipv6_dns1);
1087                 } else if (g_strcmp0(key, "ipv6_dns2") == 0) {
1088                         dbus_message_iter_get_basic(&entry, &ipv6_dns2);
1089                         DBG("ipv6_dns2 (%s)", ipv6_dns2);
1090                 } else if (g_strcmp0(key, "active") == 0) {
1091                         dbus_message_iter_get_basic(&entry, &value);
1092                         DBG("active (%s)", value);
1093                         active = STRING2BOOL(value);
1094                 } else if (g_strcmp0(key, "routing_only") == 0) {
1095                         dbus_message_iter_get_basic(&entry, &value);
1096                         DBG("routing_only (%s)", value);
1097                         routing_only = STRING2BOOL(value);
1098                         network->routing_only = routing_only;
1099                 } else if (g_strcmp0(key, "ipv6_link_only") == 0) {
1100                         dbus_message_iter_get_basic(&entry, &value);
1101                         DBG("ipv6_link_only (%s)", value);
1102                         ipv6_link_only = STRING2BOOL(value);
1103                         network->ipv6_link_only = ipv6_link_only;
1104                 }
1105                 else if (g_strcmp0(key, "default_internet_conn") == 0) {
1106                         dbus_message_iter_get_basic(&entry, &value);
1107                         DBG("default_internet (%s)", value);
1108                         default_internet = STRING2BOOL(value);
1109                 }
1110
1111                 dbus_message_iter_next(dict);
1112         }
1113
1114         if(routing_only){
1115                 //context active does not effect the connman service status.
1116                 //it only for setting the routing path.
1117                 DBG("routing_only(%d), active(%d)", routing_only, active);
1118                 return active;
1119         }
1120
1121         if (g_strcmp0(proxy_addr, ":") == 0)
1122                 proxy_addr = NULL;
1123         if (g_strcmp0(ipv4_addr, "0.0.0.0") == 0)
1124                 ipv4_addr = NULL;
1125         if (g_strcmp0(ipv4_gw, "0.0.0.0") == 0)
1126                 ipv4_gw = NULL;
1127         if (g_strcmp0(ipv4_netmask, "0.0.0.0") == 0)
1128                 ipv4_netmask = NULL;
1129         if (g_strcmp0(ipv4_dns1, "0.0.0.0") == 0)
1130                 ipv4_dns1 = NULL;
1131         if (g_strcmp0(ipv4_dns2, "0.0.0.0") == 0)
1132                 ipv4_dns2 = NULL;
1133         if (g_strcmp0(ipv6_addr, "::") == 0)
1134                 ipv6_addr = NULL;
1135         if (g_strcmp0(ipv6_gw, "::") == 0)
1136                 ipv6_gw = NULL;
1137         if (g_strcmp0(ipv6_netmask, "::") == 0)
1138                 ipv6_netmask = NULL;
1139         if (g_strcmp0(ipv6_dns1, "::") == 0)
1140                 ipv6_dns1 = NULL;
1141         if (g_strcmp0(ipv6_dns2, "::") == 0)
1142                 ipv6_dns2 = NULL;
1143
1144         connman_network_set_bool(network->network, "DefaultInternet",
1145                                                                 (bool)default_internet);
1146
1147         service = connman_service_lookup_from_network(network->network);
1148         if (service == NULL)
1149                 return FALSE;
1150
1151         if (connman_setting_get_bool("SingleConnectedTechnology") == TRUE) {
1152                 /* Wi-Fi technology is always a top priority */
1153                 if (active == TRUE &&
1154                                 connman_service_is_no_ref_user_pdn_connection(service) == TRUE &&
1155                                 connman_service_get_type(connman_service_get_default_connection())
1156                                         == CONNMAN_SERVICE_TYPE_WIFI) {
1157                         __request_network_deactivate(network->network);
1158
1159                         return FALSE;
1160                 }
1161         }
1162
1163         /* interface index set */
1164         if (dev_name != NULL) {
1165                 index = connman_inet_ifindex(dev_name);
1166                 network->if_index = index;
1167                 DBG("interface index %d", index);
1168         }
1169
1170         /* proxy set */
1171         if (active == TRUE &&
1172                         connman_network_get_connected(network->network) == TRUE)
1173                 active_proxy = TRUE;
1174
1175         proxies = connman_service_get_proxy_servers(service);
1176         if (proxies != NULL) {
1177                 if (proxy_addr == NULL)
1178                         connman_service_set_proxy(service, proxy_addr, active_proxy);
1179                 else if (g_strcmp0(proxy_addr, proxies[0]) != 0)
1180                         connman_service_set_proxy(service, proxy_addr, active_proxy);
1181         } else if (proxy_addr != NULL)
1182                 connman_service_set_proxy(service, proxy_addr, active_proxy);
1183
1184         if (proxies != NULL)
1185                 g_strfreev(proxies);
1186
1187         __connman_service_nameserver_clear(service);
1188
1189         /* ipv4 set */
1190         if (network->ipv4_address == NULL)
1191                 network->ipv4_address =
1192                                 connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV4);
1193
1194         if (network->ipv4_address == NULL)
1195                 return FALSE;
1196
1197         if (ipv4_addr == NULL && active == TRUE)
1198                 network->ipv4_method = CONNMAN_IPCONFIG_METHOD_OFF;
1199         else
1200                 network->ipv4_method = CONNMAN_IPCONFIG_METHOD_FIXED;
1201
1202         connman_network_set_ipv4_method(network->network, network->ipv4_method);
1203
1204         ipv4_updated = connman_ipaddress_updated(network->ipv4_address,
1205                                                 ipv4_addr, ipv4_gw);
1206         if (ipv4_updated == TRUE)
1207                 connman_ipaddress_set_ipv4(network->ipv4_address, ipv4_addr,
1208                                                 ipv4_netmask, ipv4_gw);
1209
1210         if (ipv4_dns1)
1211 #if defined TIZEN_EXT
1212                 __connman_service_nameserver_append(service, ipv4_dns1, FALSE,
1213                                 CONNMAN_IPCONFIG_TYPE_IPV4);
1214 #else
1215                 __connman_service_nameserver_append(service, ipv4_dns1, FALSE);
1216 #endif
1217         //if (ipv4_dns2)
1218         if (ipv4_dns2 && !ipv4_dns1)
1219 #if defined TIZEN_EXT
1220                 __connman_service_nameserver_append(service, ipv4_dns2, FALSE,
1221                                 CONNMAN_IPCONFIG_TYPE_IPV4);
1222 #else
1223                 __connman_service_nameserver_append(service, ipv4_dns2, FALSE);
1224 #endif
1225         /* ipv6 set */
1226         if (network->ipv6_address == NULL)
1227                 network->ipv6_address =
1228                                 connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV6);
1229
1230         if (network->ipv6_address == NULL)
1231                 return FALSE;
1232
1233         if(ipv6_link_only)
1234                 network->ipv6_method = CONNMAN_IPCONFIG_METHOD_AUTO;
1235         else
1236                 network->ipv6_method = CONNMAN_IPCONFIG_METHOD_FIXED;
1237
1238         if (ipv6_addr == NULL)
1239                 network->ipv6_method = CONNMAN_IPCONFIG_METHOD_OFF;
1240
1241         connman_network_set_ipv6_method(network->network, network->ipv6_method);
1242
1243         ipv6_updated = connman_ipaddress_updated(network->ipv6_address,
1244                                                 ipv6_addr, ipv6_gw);
1245         if (ipv6_updated == TRUE)
1246                 connman_ipaddress_set_ipv6(network->ipv6_address, ipv6_addr,
1247                                                 64, ipv6_gw);
1248
1249         if (ipv6_dns1)
1250 #if defined TIZEN_EXT
1251                 __connman_service_nameserver_append(service, ipv6_dns1, FALSE,
1252                                 CONNMAN_IPCONFIG_TYPE_IPV6);
1253 #else
1254                 __connman_service_nameserver_append(service, ipv6_dns1, FALSE);
1255 #endif
1256         //if (ipv6_dns2)
1257         if (ipv6_dns2 && !ipv6_dns1)
1258 #if defined TIZEN_EXT
1259                 __connman_service_nameserver_append(service, ipv6_dns2, FALSE,
1260                                 CONNMAN_IPCONFIG_TYPE_IPV6);
1261 #else
1262                 __connman_service_nameserver_append(service, ipv6_dns2, FALSE);
1263 #endif
1264
1265         if (active == TRUE &&
1266                         connman_network_get_connected(network->network) == TRUE) {
1267                 if (ipv4_updated == TRUE || ipv6_updated == TRUE) {
1268                         DBG("IPv4 updated %d, IPv6 updated %d", ipv4_updated, ipv6_updated);
1269
1270                         __set_network_connected(network, FALSE);
1271                 } else {
1272                         DBG("Already connected");
1273
1274                         return active;
1275                 }
1276         }
1277
1278         if (active == TRUE)
1279                 connman_network_set_associating(network->network, TRUE);
1280
1281         return active;
1282 }
1283
1284 static int __add_context(struct connman_device *device, const char *path,
1285                                 DBusMessageIter *prop)
1286 {
1287         char *ident;
1288         gboolean active = FALSE;
1289
1290         struct telephony_modem *modem = connman_device_get_data(device);
1291         struct connman_network *network;
1292         struct telephony_network *info;
1293
1294         DBG("modem %p device %p path %s", modem, device, path);
1295
1296         ident = __get_ident(path);
1297
1298         network = connman_device_get_network(device, ident);
1299         if (network != NULL)
1300                 return -EALREADY;
1301
1302         info = g_hash_table_lookup(network_hash, path);
1303         if (info != NULL) {
1304                 DBG("path %p already exists with device %p", path,
1305                         connman_network_get_device(info->network));
1306
1307                 if (connman_network_get_device(info->network))
1308                         return -EALREADY;
1309
1310                 g_hash_table_remove(network_hash, path);
1311         }
1312
1313         network = connman_network_create(ident, CONNMAN_NETWORK_TYPE_CELLULAR);
1314         if (network == NULL)
1315                 return -ENOMEM;
1316
1317         info = g_try_new0(struct telephony_network, 1);
1318         if (info == NULL) {
1319                 connman_network_unref(network);
1320                 return -ENOMEM;
1321         }
1322
1323         info->path = g_strdup(path);
1324
1325         connman_ipaddress_clear(info->ipv4_address);
1326         connman_ipaddress_clear(info->ipv6_address);
1327
1328         info->network = network;
1329
1330         connman_network_set_string(network, "Path", path);
1331         connman_network_set_name(network, path);
1332
1333         connman_network_set_group(network, ident);
1334
1335         g_hash_table_insert(network_hash, g_strdup(path), info);
1336
1337         connman_network_set_available(network, TRUE);
1338         connman_network_set_bool(network, "Roaming", (bool)modem->s_service->roaming);
1339
1340         if (connman_device_add_network(device, network) != 0) {
1341                 g_hash_table_remove(network_hash, path);
1342                 return -EIO;
1343         }
1344
1345         active = __set_network_context(info, prop);
1346         if(info->routing_only){
1347                 int err = 0;
1348                 struct connman_service *routing_service;
1349                 struct connman_ipconfig *routing_ipconfig;
1350
1351                 if(!active)
1352                         return TRUE;
1353
1354                 routing_service = connman_service_lookup_from_network(info->network);
1355                 routing_ipconfig = __connman_service_get_ip4config(routing_service);
1356                 err = __connman_ipconfig_gateway_add(routing_ipconfig, routing_service);
1357
1358                 DBG("set gateway rv(%d)", err);
1359                 return TRUE;
1360         }
1361
1362         if (active == TRUE && (connman_network_get_associating(network) == TRUE ||
1363                         connman_network_get_connecting(network) == TRUE))
1364                 __set_network_connected(info, active);
1365
1366         return 0;
1367 }
1368
1369 static gboolean __changed_modem(DBusConnection *connection,
1370                                 DBusMessage *message, void *user_data)
1371 {
1372         gboolean old_powered;
1373         DBusMessageIter args, dict;
1374         struct telephony_modem *modem;
1375         const char *path = dbus_message_get_path(message);
1376
1377         DBG("modem changed signal %s", path);
1378
1379         modem = g_hash_table_lookup(modem_hash, path);
1380         if (modem == NULL) {
1381                 DBG("modem object does not exists");
1382                 return TRUE;
1383         }
1384
1385         old_powered = modem->powered;
1386
1387         DBG("message signature (%s)", dbus_message_get_signature(message));
1388
1389         if (dbus_message_iter_init(message, &args) == FALSE) {
1390                 DBG("error to read message");
1391                 return TRUE;
1392         }
1393
1394         dbus_message_iter_recurse(&args, &dict);
1395
1396         while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
1397                 DBusMessageIter entry;
1398                 const char *key, *tmp;
1399
1400                 dbus_message_iter_recurse(&dict, &entry);
1401                 dbus_message_iter_get_basic(&entry, &key);
1402
1403                 dbus_message_iter_next(&entry);
1404                 dbus_message_iter_get_basic(&entry, &tmp);
1405
1406                 DBG("key(%s), value(%s)", key, tmp);
1407
1408                 if (g_strcmp0(key, "powered") == 0) {
1409                         modem->powered = STRING2BOOL(tmp);
1410                 } else if (g_strcmp0(key, "operator") == 0) {
1411                         modem->operator = g_strdup(tmp);
1412                 } else if (g_strcmp0(key, "sim_init") == 0) {
1413                         modem->sim_init = STRING2BOOL(tmp);
1414                 } else if (g_strcmp0(key, "flight_mode") == 0) {
1415                         modem->flight_mode = STRING2BOOL(tmp);
1416                 } else if (g_strcmp0(key, "roaming_allowed") == 0) {
1417                         modem->roaming_allowed = STRING2BOOL(tmp);
1418                 } else if (g_strcmp0(key, "data_allowed") == 0) {
1419                         modem->data_allowed = STRING2BOOL(tmp);
1420                 }
1421
1422                 dbus_message_iter_next(&dict);
1423         }
1424
1425         if (modem->device == NULL)
1426                 __add_connman_device(path, modem->operator);
1427
1428         if (old_powered != modem->powered)
1429                 __set_device_powered(modem, modem->powered);
1430
1431         if (modem->powered != TRUE) {
1432                 DBG("modem is not powered");
1433                 return TRUE;
1434         }
1435
1436         if (modem->s_service == NULL) {
1437                 __request_get_services(modem->path);
1438                 return TRUE;
1439         }
1440
1441         DBG("modem(%s) flight mode(%d) data allowed(%d)",
1442                         modem->path, modem->flight_mode, modem->data_allowed);
1443
1444         return TRUE;
1445 }
1446
1447 static gboolean __added_modem(DBusConnection *connection,
1448                                 DBusMessage *message, void *user_data)
1449 {
1450         const char *modem_path = NULL;
1451         DBusMessageIter args, dict, tmp;
1452
1453         DBG("modem added signal (%s)", dbus_message_get_signature(message));
1454
1455         if (dbus_message_iter_init(message, &args) == FALSE) {
1456                 DBG("error to read message");
1457                 return TRUE;
1458         }
1459
1460         dbus_message_iter_recurse(&args, &dict);
1461         memcpy(&tmp, &dict, sizeof(struct DBusMessageIter));
1462
1463         while (dbus_message_iter_get_arg_type(&tmp) != DBUS_TYPE_INVALID) {
1464                 DBusMessageIter entry;
1465                 const char *key, *value;
1466
1467                 dbus_message_iter_recurse(&tmp, &entry);
1468                 dbus_message_iter_get_basic(&entry, &key);
1469
1470                 dbus_message_iter_next(&entry);
1471                 dbus_message_iter_get_basic(&entry, &value);
1472
1473                 DBG("key (%s) value(%s)", key, value);
1474
1475                 if (g_strcmp0(key, "path") == 0)
1476                         modem_path = g_strdup(value);
1477
1478                 dbus_message_iter_next(&tmp);
1479         }
1480
1481         if (modem_path != NULL)
1482                 __add_modem(modem_path, &dict);
1483
1484         return TRUE;
1485 }
1486
1487 static gboolean __removed_modem(DBusConnection *connection,
1488                                         DBusMessage *message, void *user_data)
1489 {
1490         DBusMessageIter iter;
1491         const char *modem_path;
1492
1493         DBG("modem removed signal");
1494
1495         if (dbus_message_iter_init(message, &iter) == FALSE) {
1496                 DBG("error to read message");
1497                 return TRUE;
1498         }
1499
1500         dbus_message_iter_get_basic(&iter, &modem_path);
1501         g_hash_table_remove(modem_hash, modem_path);
1502
1503         return TRUE;
1504 }
1505
1506 static gboolean __changed_service(DBusConnection *connection,
1507                                         DBusMessage *message, void *user_data)
1508 {
1509         DBusMessageIter args, dict;
1510         struct telephony_modem *modem;
1511         gboolean roaming_option = TRUE;
1512         struct telephony_service *s_service;
1513         const char *service_path = dbus_message_get_path(message);
1514
1515         DBG("service changed signal %s", service_path);
1516
1517         s_service = g_hash_table_lookup(service_hash, service_path);
1518         if (s_service == NULL) {
1519                 DBG("service object does not exists");
1520                 return TRUE;
1521         }
1522
1523         modem = s_service->p_modem;
1524         if (modem == NULL) {
1525                 DBG("modem object does not exists");
1526                 return TRUE;
1527         }
1528
1529         DBG("message signature (%s)", dbus_message_get_signature(message));
1530
1531         if (dbus_message_iter_init(message, &args) == FALSE) {
1532                 DBG("error to read message");
1533                 return TRUE;
1534         }
1535
1536         dbus_message_iter_recurse(&args, &dict);
1537
1538         while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
1539                 DBusMessageIter entry;
1540                 const char *key, *tmp;
1541
1542                 dbus_message_iter_recurse(&dict, &entry);
1543                 dbus_message_iter_get_basic(&entry, &key);
1544
1545                 dbus_message_iter_next(&entry);
1546                 dbus_message_iter_get_basic(&entry, &tmp);
1547
1548                 DBG("key(%s), value(%s)", key, tmp);
1549
1550                 if (g_strcmp0(key, "roaming") == 0) {
1551                         s_service->roaming = STRING2BOOL(tmp);
1552                 } else if (g_strcmp0(key, "act") == 0) {
1553                         s_service->act = g_strdup(tmp);
1554                 } else if (g_strcmp0(key, "ps_attached") == 0) {
1555                         s_service->ps_attached = STRING2BOOL(tmp);
1556                 }
1557
1558                 dbus_message_iter_next(&dict);
1559         }
1560
1561         roaming_option &= (!s_service->roaming && !modem->roaming_allowed)
1562                                 || modem->roaming_allowed;
1563
1564         return TRUE;
1565 }
1566
1567 static gboolean __added_service(DBusConnection *connection,
1568                                 DBusMessage *message, void *user_data)
1569 {
1570         struct telephony_modem *modem;
1571         const char *service_path = NULL;
1572         DBusMessageIter args, dict, tmp;
1573         const char *path = dbus_message_get_path(message);
1574
1575         DBG("service added signal %s", path);
1576
1577         modem = g_hash_table_lookup(modem_hash, path);
1578         if (modem == NULL || modem->device == NULL)
1579                 return TRUE;
1580
1581         DBG("message signature (%s)", dbus_message_get_signature(message));
1582         if (dbus_message_iter_init(message, &args) == FALSE) {
1583                 DBG("error to read message");
1584                 return TRUE;
1585         }
1586
1587         dbus_message_iter_recurse(&args, &dict);
1588         memcpy(&tmp, &dict, sizeof(struct DBusMessageIter));
1589
1590         while (dbus_message_iter_get_arg_type(&tmp) != DBUS_TYPE_INVALID) {
1591                 DBusMessageIter entry;
1592                 const char *key, *value;
1593
1594                 dbus_message_iter_recurse(&tmp, &entry);
1595                 dbus_message_iter_get_basic(&entry, &key);
1596
1597                 dbus_message_iter_next(&entry);
1598                 dbus_message_iter_get_basic(&entry, &value);
1599
1600                 DBG("key (%s) value(%s)", key, value);
1601
1602                 if (g_strcmp0(key, "path") == 0)
1603                         service_path = value;
1604
1605                 dbus_message_iter_next(&tmp);
1606         }
1607
1608         if (service_path != NULL)
1609                 __add_service(modem, service_path, &dict);
1610
1611         return TRUE;
1612 }
1613
1614 static gboolean __removed_service(DBusConnection *connection,
1615                                         DBusMessage *message, void *user_data)
1616 {
1617         DBusMessageIter iter;
1618         const char *service_path;
1619
1620         DBG("service removed signal");
1621
1622         if (dbus_message_iter_init(message, &iter) == FALSE) {
1623                 DBG("error to read message");
1624                 return TRUE;
1625         }
1626
1627         dbus_message_iter_get_basic(&iter, &service_path);
1628         g_hash_table_remove(service_hash, service_path);
1629
1630         return TRUE;
1631 }
1632
1633 static gboolean __changed_context(DBusConnection *connection,
1634                                         DBusMessage *message, void *user_data)
1635 {
1636         gboolean active = FALSE;
1637         DBusMessageIter args, dict;
1638         struct telephony_network *info;
1639         const char *path = dbus_message_get_path(message);
1640
1641         DBG("network changed signal %s", path);
1642
1643         info = g_hash_table_lookup(network_hash, path);
1644         if (info == NULL)
1645                 return TRUE;
1646
1647         if (__check_network_available(info->network) == FALSE) {
1648                 g_hash_table_remove(network_hash, path);
1649                 return TRUE;
1650         }
1651
1652         if (dbus_message_iter_init(message, &args) == FALSE) {
1653                 DBG("error to read message");
1654                 return TRUE;
1655         }
1656
1657         dbus_message_iter_recurse(&args, &dict);
1658
1659         active = __set_network_context(info, &dict);
1660         if(info->routing_only){
1661                 int err = 0;
1662                 struct connman_service *routing_service;
1663                 struct connman_ipconfig *routing_ipconfig;
1664
1665                 if(!active)
1666                         return TRUE;
1667
1668                 routing_service = connman_service_lookup_from_network(info->network);
1669                 routing_ipconfig = __connman_service_get_ip4config(routing_service);
1670                 err = __connman_ipconfig_gateway_add(routing_ipconfig, routing_service);
1671
1672                 DBG("set gateway rv(%d)", err);
1673                 return TRUE;
1674         }
1675
1676         __set_network_connected(info, active);
1677
1678         if (active == FALSE &&
1679                         connman_network_get_connecting(info->network) == TRUE)
1680                 connman_network_set_connected(info->network, FALSE);
1681
1682         return TRUE;
1683 }
1684
1685 static gboolean __added_context(DBusConnection *connection,
1686                                         DBusMessage *message, void *user_data)
1687 {
1688         const char *network_path = NULL;
1689         DBusMessageIter args, dict, tmp;
1690         struct telephony_modem *modem = NULL;
1691         struct telephony_service *service = NULL;
1692         const char *path = dbus_message_get_path(message);
1693
1694         DBG("network added signal %s", path);
1695
1696         service = g_hash_table_lookup(service_hash, path);
1697         if (service == NULL || service->p_modem == NULL)
1698                 return TRUE;
1699
1700         modem = service->p_modem;
1701         if (modem == NULL || modem->device == NULL)
1702                 return TRUE;
1703
1704         DBG("message signature (%s)", dbus_message_get_signature(message));
1705         if (dbus_message_iter_init(message, &args) == FALSE) {
1706                 DBG("error to read message");
1707                 return TRUE;
1708         }
1709
1710         dbus_message_iter_recurse(&args, &dict);
1711         memcpy(&tmp, &dict, sizeof(struct DBusMessageIter));
1712
1713         while (dbus_message_iter_get_arg_type(&tmp) != DBUS_TYPE_INVALID) {
1714                 DBusMessageIter entry;
1715                 const char *key, *value;
1716
1717                 dbus_message_iter_recurse(&tmp, &entry);
1718                 dbus_message_iter_get_basic(&entry, &key);
1719
1720                 dbus_message_iter_next(&entry);
1721                 dbus_message_iter_get_basic(&entry, &value);
1722
1723                 DBG("key (%s) value(%s)", key, value);
1724
1725                 if (g_strcmp0(key, "path") == 0)
1726                         network_path = g_strdup(value);
1727
1728                 dbus_message_iter_next(&tmp);
1729         }
1730
1731         if (network_path != NULL)
1732                 __add_context(modem->device, network_path, &dict);
1733
1734         return TRUE;
1735 }
1736
1737 static gboolean __removed_context(DBusConnection *connection,
1738                                         DBusMessage *message, void *user_data)
1739 {
1740         DBusMessageIter iter;
1741         const char *network_path = NULL;
1742         struct telephony_service *service = NULL;
1743         const char *path = dbus_message_get_path(message);
1744
1745         DBG("network removed signal %s", path);
1746
1747         service = g_hash_table_lookup(service_hash, path);
1748         if (service == NULL || service->p_modem == NULL)
1749                 return TRUE;
1750
1751         if (dbus_message_iter_init(message, &iter) == FALSE) {
1752                 DBG("error to read message");
1753                 return TRUE;
1754         }
1755
1756         dbus_message_iter_get_basic(&iter, &network_path);
1757         g_hash_table_remove(network_hash, network_path);
1758
1759         return TRUE;
1760 }
1761
1762 static gboolean __changed_default_subscription(DBusConnection *connection,
1763                 DBusMessage *message, void *user_data)
1764 {
1765         DBusMessageIter args;
1766
1767         DBG("message signature (%s)", dbus_message_get_signature(message));
1768         if (dbus_message_iter_init(message, &args) == FALSE)
1769                 return TRUE;
1770
1771         dbus_message_iter_get_basic(&args, &telephony_default_subscription_id);
1772         DBG("default subscription: %d", telephony_default_subscription_id);
1773
1774         return TRUE;
1775 }
1776
1777 /* telephony initialization */
1778 static guint watch = 0;
1779 static guint modem_watch = 0;
1780 static guint modem_added_watch = 0;
1781 static guint modem_removed_watch = 0;
1782 static guint service_watch = 0;
1783 static guint service_added_watch = 0;
1784 static guint service_removed_watch = 0;
1785 static guint context_watch = 0;
1786 static guint context_added_watch = 0;
1787 static guint context_removed_watch = 0;
1788 static guint default_subscription_watch = 0;
1789
1790 static int telephony_init(void)
1791 {
1792         int err;
1793
1794         DBG("telephony plugin");
1795
1796         connection = connman_dbus_get_connection();
1797         if (connection == NULL)
1798                 return -EIO;
1799
1800         /* telephony watch */
1801         watch = g_dbus_add_service_watch(connection, PS_DBUS_SERVICE,
1802                                         telephony_connect, telephony_disconnect,
1803                                         NULL, NULL);
1804
1805         modem_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1806                                                 PS_MODEM_INTERFACE,
1807                                                 PROPERTY_CHANGED,
1808                                                 __changed_modem,
1809                                                 NULL, NULL);
1810
1811         modem_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1812                                                 PS_MASTER_INTERFACE,
1813                                                 MODEM_ADDED,
1814                                                 __added_modem,
1815                                                 NULL, NULL);
1816
1817         modem_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1818                                                 PS_MASTER_INTERFACE,
1819                                                 MODEM_REMOVED,
1820                                                 __removed_modem,
1821                                                 NULL, NULL);
1822
1823         service_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1824                                                 PS_SERVICE_INTERFACE,
1825                                                 PROPERTY_CHANGED,
1826                                                 __changed_service,
1827                                                 NULL, NULL);
1828
1829         service_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1830                                                 PS_MODEM_INTERFACE,
1831                                                 SERVICE_ADDED,
1832                                                 __added_service,
1833                                                 NULL, NULL);
1834
1835         service_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1836                                                 PS_MODEM_INTERFACE,
1837                                                 SERVICE_REMOVED,
1838                                                 __removed_service,
1839                                                 NULL, NULL);
1840
1841         context_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1842                                                 PS_CONTEXT_INTERFACE,
1843                                                 PROPERTY_CHANGED,
1844                                                 __changed_context,
1845                                                 NULL, NULL);
1846
1847         context_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1848                                                 PS_SERVICE_INTERFACE,
1849                                                 CONTEXT_ADDED,
1850                                                 __added_context,
1851                                                 NULL, NULL);
1852
1853         context_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1854                                                 PS_SERVICE_INTERFACE,
1855                                                 CONTEXT_REMOVED,
1856                                                 __removed_context,
1857                                                 NULL, NULL);
1858
1859         default_subscription_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1860                                                 "org.tizen.telephony.Network",
1861                                                 "DefaultDataSubscription",
1862                                                 __changed_default_subscription,
1863                                                 NULL, NULL);
1864
1865         if (watch == 0 || modem_watch == 0 || modem_added_watch == 0
1866                         || modem_removed_watch == 0 || service_watch == 0
1867                         || service_added_watch == 0 || context_watch == 0
1868                         || service_removed_watch == 0
1869                         || context_added_watch == 0
1870                         || context_removed_watch == 0
1871                         || default_subscription_watch == 0) {
1872                 err = -EIO;
1873                 goto remove;
1874         }
1875
1876         err = connman_network_driver_register(&network_driver);
1877         if (err < 0)
1878                 goto remove;
1879
1880         err = connman_device_driver_register(&modem_driver);
1881         if (err < 0) {
1882                 connman_network_driver_unregister(&network_driver);
1883                 goto remove;
1884         }
1885
1886         err = connman_technology_driver_register(&tech_driver);
1887         if (err < 0) {
1888                 connman_device_driver_unregister(&modem_driver);
1889                 connman_network_driver_unregister(&network_driver);
1890                 goto remove;
1891         }
1892
1893         return 0;
1894
1895 remove:
1896         g_dbus_remove_watch(connection, watch);
1897         g_dbus_remove_watch(connection, modem_watch);
1898         g_dbus_remove_watch(connection, modem_added_watch);
1899         g_dbus_remove_watch(connection, modem_removed_watch);
1900         g_dbus_remove_watch(connection, service_watch);
1901         g_dbus_remove_watch(connection, service_added_watch);
1902         g_dbus_remove_watch(connection, service_removed_watch);
1903         g_dbus_remove_watch(connection, context_watch);
1904         g_dbus_remove_watch(connection, context_added_watch);
1905         g_dbus_remove_watch(connection, context_removed_watch);
1906         g_dbus_remove_watch(connection, default_subscription_watch);
1907
1908         dbus_connection_unref(connection);
1909         return err;
1910 }
1911
1912 static void telephony_exit(void)
1913 {
1914         g_dbus_remove_watch(connection, watch);
1915         g_dbus_remove_watch(connection, modem_watch);
1916         g_dbus_remove_watch(connection, modem_added_watch);
1917         g_dbus_remove_watch(connection, modem_removed_watch);
1918         g_dbus_remove_watch(connection, service_watch);
1919         g_dbus_remove_watch(connection, service_added_watch);
1920         g_dbus_remove_watch(connection, service_removed_watch);
1921         g_dbus_remove_watch(connection, context_watch);
1922         g_dbus_remove_watch(connection, context_added_watch);
1923         g_dbus_remove_watch(connection, context_removed_watch);
1924         g_dbus_remove_watch(connection, default_subscription_watch);
1925
1926         telephony_disconnect(connection, NULL);
1927
1928         connman_device_driver_unregister(&modem_driver);
1929         connman_network_driver_unregister(&network_driver);
1930
1931         dbus_connection_unref(connection);
1932 }
1933
1934 CONNMAN_PLUGIN_DEFINE(telephony, "Samsung Telephony Framework plug-in", VERSION,
1935                 CONNMAN_PLUGIN_PRIORITY_DEFAULT, telephony_init, telephony_exit)