delete README file
[framework/telephony/tel-plugin-packetservice.git] / src / context.c
1 /*
2  * PacketService Control Module
3  *
4  * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: DongHoo Park <donghoo.park@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 #include "ps-context.h"
23
24 #include "ps.h"
25 #include "ps-error.h"
26
27 #include <tcore.h>
28 #include <plugin.h>
29 #include <server.h>
30 #include <storage.h>
31 #include <core_object.h>
32 #include <co_context.h>
33
34 #include <netinet/in.h>
35 #include <arpa/inet.h>
36
37 #define PROP_DEFAULT            FALSE
38 #define PROP_DEFAULT_STR        NULL
39 #define BOOL2STRING(a)          ((a==TRUE) ? ("TRUE"):("FALSE"))
40 #define DATABASE_PATH           "/opt/dbspace/.dnet.db"
41
42 /*Properties*/
43 enum {
44         PROP_CONTEXT_O,
45
46         PROP_CONTEXT_PATH,
47         PROP_CONTEXT_CONN,
48         PROP_CONTEXT_PLUGIN,
49         PROP_CONTEXT_MCCMNC
50 };
51
52 enum {
53         SIG_CONTEXT_PROPERTY_CHANGED,
54         SIG_CONTEXT_LAST
55 };
56
57 static guint32 signals[SIG_CONTEXT_LAST] = { 0, };
58
59 struct PsContextClass {
60         GObjectClass parent;
61
62         //method and signals
63         void (*property_changed)(PsContext *context, GHashTable *context_property);
64 };
65
66 struct PsContext {
67         GObject parent;
68
69         gchar* path;
70         gchar* mccmnc;
71         DBusGConnection *conn;
72         TcorePlugin *plg;
73
74         gboolean alwayson;
75         gpointer p_service;
76         int profile_id;
77         CoreObject *co_context;
78 };
79
80 static Storage *strg_db;
81 static gpointer handle;
82 static GHashTable *contexts;
83
84 G_DEFINE_TYPE(PsContext, ps_context, G_TYPE_OBJECT);
85
86 static void     __ps_context_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
87 static void     __ps_context_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
88
89 gboolean        ps_iface_context_get_properties(PsContext *pscontext, DBusGMethodInvocation *context);
90 gboolean        ps_iface_context_get_profile(PsContext *pscontext, DBusGMethodInvocation *context);
91 gboolean        ps_iface_context_activate(PsContext *pscontext, DBusGMethodInvocation *context);
92 gboolean        ps_iface_context_deactivate(PsContext *pscontext, DBusGMethodInvocation *context);
93 gboolean        ps_iface_context_modify_profile(PsContext *pscontext, GHashTable *profile_property, gboolean* result, GError **error);
94 gboolean        ps_iface_context_remove_profile(PsContext *pscontext, gboolean* result, GError **error);
95
96 static void     __ps_context_emit_property_changed_signal(PsContext *context);
97
98 static void     __remove_context(gpointer data);
99 static gboolean __remove_contexts(gpointer key, gpointer value, gpointer user_data);
100 static gboolean __ps_context_remove_context(PsContext *context);
101 static gboolean __ps_context_create_storage_handle(gpointer plugin);
102 static gboolean __ps_context_create_context_hash(void);
103 static gchar*   __ps_context_create_path(char *profile_name,int svc_ctg_id);
104 static gboolean __ps_context_create_co_context(gpointer context, GHashTable *property);
105 static gboolean __ps_context_update_profile(PsContext *context, GHashTable *property);
106 static gboolean __ps_context_update_database(PsContext *context);
107 static gboolean __ps_context_remove_database(PsContext *context);
108 static int      __ps_context_insert_network_id_to_database(gchar *mccmnc);
109 static int      __ps_context_load_network_id_from_database(gchar *mccmnc);
110 static int      __ps_context_load_profile_id_from_database(void);
111 static int      __ps_context_insert_profile_to_database(GHashTable *property, int network_id);
112 static gboolean __ps_context_reset_database(void);
113 static int      __ps_context_get_network_id(gchar *mccmnc);
114 static gboolean __ps_context_get_profile_properties(gpointer context, GHashTable *properties);
115 static gboolean __ps_context_set_alwayson_enable(gpointer object, gboolean enabled);
116
117 #include "ps-iface-context-glue.h"
118
119 static void ps_context_init(PsContext *context)
120 {
121         dbg("context initialize");
122
123         context->path = NULL;
124         context->mccmnc = NULL;
125         context->conn = NULL;
126         context->plg = NULL;
127
128         context->alwayson = PROP_DEFAULT;
129         context->p_service = NULL;
130         context->profile_id = 0;
131         context->co_context = NULL;
132
133         return;
134 }
135
136 static void ps_context_class_init(PsContextClass *klass)
137 {
138         GObjectClass *object_class = G_OBJECT_CLASS(klass);
139
140         //class init
141         dbg("context class init");
142
143         object_class->get_property = __ps_context_get_property;
144         object_class->set_property = __ps_context_set_property;
145
146         //dbus register
147         dbus_g_object_type_install_info(PS_TYPE_CONTEXT, &dbus_glib_ps_iface_context_object_info);
148
149         //property add
150         g_object_class_install_property(
151                         object_class,
152                         PROP_CONTEXT_CONN,
153                         g_param_spec_boxed("conn", "CONNECTION", "DBus connection", DBUS_TYPE_G_CONNECTION,
154                                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
155         g_object_class_install_property(
156                         object_class,
157                         PROP_CONTEXT_PATH,
158                         g_param_spec_string("path", "PATH", "Context Path", PROP_DEFAULT_STR,
159                                         G_PARAM_READWRITE));
160         g_object_class_install_property(
161                         object_class,
162                         PROP_CONTEXT_MCCMNC,
163                         g_param_spec_string("mccmnc", "MCCMNC", "Profile Country and Context Provider Code",
164                                         PROP_DEFAULT_STR, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
165         g_object_class_install_property(
166                         object_class,
167                         PROP_CONTEXT_PLUGIN,
168                         g_param_spec_pointer("plg", "PLUGIN", "Plug in Object",
169                                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
170
171         //add signal handler
172         signals[SIG_CONTEXT_PROPERTY_CHANGED] = g_signal_new("property-changed",
173                         G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_LAST,
174                         G_STRUCT_OFFSET(PsContextClass, property_changed), NULL, NULL,
175                         g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, DBUS_TYPE_G_STRING_STRING_HASHTABLE);
176
177         return;
178 }
179
180 static void __ps_context_set_property(GObject *object, guint prop_id, const GValue *value,
181                 GParamSpec *pspec)
182 {
183         PsContext *context = PS_CONTEXT(object);
184
185         switch (prop_id) {
186                 case PROP_CONTEXT_CONN: {
187                         context->conn = g_value_get_boxed(value);
188                         msg("context (%p) set conn(%p)", context, context->conn);
189                 }
190                         break;
191                 case PROP_CONTEXT_PLUGIN: {
192                         context->plg = g_value_get_pointer(value);
193                         msg("context (%p) set plg(%p)", context, context->plg);
194                 }
195                         break;
196                 case PROP_CONTEXT_PATH: {
197                         if (context->path) {
198                                 g_free(context->path);
199                         }
200                         context->path = g_value_dup_string(value);
201                         msg("context (%p) path(%s)", context, context->path);
202                 }
203                         break;
204                 case PROP_CONTEXT_MCCMNC: {
205                         if (context->mccmnc) {
206                                 g_free(context->mccmnc);
207                         }
208                         context->mccmnc = g_value_dup_string(value);
209                         msg("context (%p) mccmnc(%s)", context, context->mccmnc);
210                 }
211                         break;
212                 default:
213                         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
214                         break;
215         } //end of switch
216
217         return;
218 }
219
220 static void __ps_context_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
221 {
222         return;
223 }
224
225 static void __ps_context_emit_property_changed_signal(PsContext *context)
226 {
227         GHashTable *property;
228
229         property = g_hash_table_new(g_str_hash, g_str_equal);
230         _ps_context_get_properties(context, property);
231         g_signal_emit(context, signals[SIG_CONTEXT_PROPERTY_CHANGED], 0, property);
232         g_hash_table_destroy(property);
233         dbg("context (%p) emit the context property changed signal", context);
234         return;
235 }
236
237 gboolean ps_iface_context_get_properties(PsContext *pscontext, DBusGMethodInvocation *context)
238 {
239         GHashTable *property;
240
241         dbg("Get properties of context(%s)", _ps_context_ref_path(pscontext));
242         property = g_hash_table_new(g_str_hash, g_str_equal);
243         _ps_context_get_properties(pscontext, property);
244
245         dbus_g_method_return(context, property);
246         g_hash_table_destroy(property);
247         return TRUE;
248 }
249
250 gboolean ps_iface_context_get_profile(PsContext *pscontext, DBusGMethodInvocation *context)
251 {
252         GHashTable *profile;
253
254         dbg("Get profile properties of context(%s)", _ps_context_ref_path(pscontext));
255         profile = g_hash_table_new(g_str_hash, g_str_equal);
256         __ps_context_get_profile_properties(pscontext, profile);
257
258         dbus_g_method_return(context, profile);
259         g_hash_table_destroy(profile);
260         return TRUE;
261 }
262
263 gboolean ps_iface_context_activate(PsContext *pscontext, DBusGMethodInvocation *context)
264 {
265         int rv = 0;
266         int context_state = 0;
267         GError *error = NULL;
268
269         dbg("activate context(%s)", _ps_context_ref_path(pscontext));
270
271         /*support always on connection*/
272         __ps_context_set_alwayson_enable(pscontext, TRUE);
273         _ps_service_reset_connection_timer(pscontext);
274
275         rv = _ps_service_activate_context(pscontext->p_service, pscontext);
276         if (rv != TCORE_RETURN_SUCCESS) {
277                 dbg("fail to activate context connection");
278                 g_set_error(&error, PS_ERROR, PS_ERR_TRASPORT, "fail to activate context err(%d)", rv);
279                 goto FAIL;
280         }
281
282         dbg("success to activate context");
283         dbus_g_method_return(context, pscontext->path);
284
285         context_state =    tcore_context_get_state(pscontext->co_context);
286         if (context_state == CONTEXT_STATE_ACTIVATED) {
287                 dbg("context is already connected");
288                 _ps_context_set_connected(pscontext, TRUE);
289         }
290
291         return TRUE;
292
293         FAIL: dbus_g_method_return_error(context, error);
294         return TRUE;
295 }
296
297 gboolean ps_iface_context_deactivate(PsContext *pscontext, DBusGMethodInvocation *context)
298 {
299         int rv = 0;
300         int context_state = 0;
301         GError *error = NULL;
302
303         dbg("deactivate context(%s)", _ps_context_ref_path(pscontext));
304
305         __ps_context_set_alwayson_enable(pscontext, FALSE);
306         rv = _ps_service_deactivate_context(pscontext->p_service, pscontext);
307         if (rv != TCORE_RETURN_SUCCESS) {
308                 dbg("fail to deactivate context connection");
309                 g_set_error(&error, PS_ERROR, PS_ERR_TRASPORT, "fail to deactivate context err(%d)", rv);
310                 goto FAIL;
311         }
312
313         dbg("success to deactivate context");
314         dbus_g_method_return(context, pscontext->path);
315
316         context_state =    tcore_context_get_state(pscontext->co_context);
317         if (context_state == CONTEXT_STATE_DEACTIVATED) {
318                 dbg("context is already disconnected");
319                 _ps_context_set_connected(pscontext, FALSE);
320         }
321
322         return TRUE;
323
324         FAIL: dbus_g_method_return_error(context, error);
325         return TRUE;
326 }
327
328 gboolean ps_iface_context_modify_profile(PsContext *context, GHashTable *profile_property,
329                 gboolean* result, GError **error)
330 {
331         gboolean rv = FALSE;
332         int context_state = 0;
333
334         *result = TRUE;
335         dbg("modify context's profile properties");
336
337         rv = __ps_context_update_profile(context, profile_property);
338         if (rv != TRUE) {
339                 g_set_error(error, PS_ERROR, PS_ERR_INTERNAL, "fail to modify profile");
340                 *result = FALSE;
341                 return TRUE;
342         }
343
344         context_state =    tcore_context_get_state(context->co_context);
345         if (context_state == CONTEXT_STATE_DEACTIVATED)
346                 return TRUE;
347
348         _ps_service_deactivate_context(context->p_service, context);
349         context_state =    tcore_context_get_state(context->co_context);
350         if (context_state == CONTEXT_STATE_DEACTIVATED) {
351                 dbg("context is already disconnected");
352                 _ps_context_set_connected(context, FALSE);
353         }
354
355         return TRUE;
356 }
357
358 gboolean ps_iface_context_remove_profile(PsContext *context, gboolean* result, GError **error)
359 {
360         gboolean rv = FALSE;
361         __ps_context_remove_database(context);
362         rv = __ps_context_remove_context(context);
363         *result = rv;
364         return TRUE;
365 }
366
367 static void __remove_context(gpointer data)
368 {
369         dbg("context removed");
370         return;
371 }
372
373 static gboolean __remove_contexts(gpointer key, gpointer value, gpointer user_data)
374 {
375         gchar *context_path = (gchar *) key;
376         dbg("context(%s) remove", context_path);
377         __ps_context_remove_context(value);
378         return TRUE;
379 }
380
381 static gboolean __ps_context_remove_context(PsContext *context)
382 {
383         dbg("remove context and profile");
384
385         dbus_g_connection_unregister_g_object(context->conn, (GObject *) context);
386
387         __ps_context_set_alwayson_enable(context, FALSE);
388         _ps_service_deactivate_context(context->p_service, context);
389         _ps_context_set_connected(context, FALSE);
390         _ps_service_unref_context(context->p_service, context);
391         g_hash_table_remove(contexts, _ps_context_ref_path(context));
392
393         tcore_context_free(context->co_context);
394         //__ps_context_remove_database(context);
395         g_object_unref(context);
396
397         return TRUE;
398 }
399
400 static gboolean __ps_context_create_storage_handle(gpointer plugin)
401 {
402         TcorePlugin *p = plugin;
403         Server *s = tcore_plugin_ref_server(p);
404         strg_db = tcore_server_find_storage(s, "database");
405
406         handle = tcore_storage_create_handle(strg_db, DATABASE_PATH);
407         if (!handle)
408                 err("fail to create database handle");
409
410         dbg("storage(%p) handle (%p)", strg_db, handle);
411         return TRUE;
412 }
413
414 static gboolean __ps_context_create_context_hash()
415 {
416         g_return_val_if_fail(contexts == NULL, FALSE);
417
418         contexts = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, __remove_context);
419         if (contexts == NULL) {
420                 err("fail to create context hashtable");
421                 return FALSE;
422         }
423
424         dbg("context hashtable(%p)", contexts);
425         return TRUE;
426 }
427
428 static gchar* __ps_context_create_path(char *profile_name, int svc_ctg_id)
429 {
430         gchar **strv, *str, *path;
431
432         strv = g_strsplit(profile_name, " ", 0);
433         str = g_strjoinv("_", strv);
434         path = g_strdup_printf("/context/%s_%d", str, svc_ctg_id);
435         g_strfreev(strv);
436         g_free(str);
437         dbg("path (%s)", path);
438
439         return path;
440 }
441
442 static gboolean __ps_context_create_co_context(gpointer object, GHashTable *property)
443 {
444         GHashTableIter iter;
445         gpointer key, value;
446         PsContext *context = NULL;
447         CoreObject *co_context = NULL;
448
449         gchar *path = NULL;
450         int profile_id = 0;
451         gchar *profile_name = NULL;
452         gchar *apn = NULL;
453         int auth_type = 0;
454         gchar *auth_id = NULL, *auth_pwd = NULL, *home_url = NULL, *proxy_addr = NULL;
455         int pdp_protocol = 0, svc_ctg_id = 0;
456
457         g_hash_table_iter_init(&iter, (GHashTable *) property);
458         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
459                 if (g_str_equal(key, "3") == TRUE) { /*Profile ID*/
460                         profile_id = atoi((const char*) value);
461                         dbg("profile id (%d)", profile_id);
462                 }
463                 else if (g_str_equal(key, "4") == TRUE) {
464                         profile_name = g_strdup((const char*) value);
465                         dbg("profile name (%s)", profile_name);
466                 }
467                 else if (g_str_equal(key, "5") == TRUE) {
468                         apn = g_strdup((const char*) value);
469                         dbg("APN (%s)", apn);
470                 }
471                 else if (g_str_equal(key, "6") == TRUE) {
472                         auth_type = atoi((const char*) value);
473                         dbg("auth type (%d)", auth_type);
474                 }
475                 else if (g_str_equal(key, "7") == TRUE) {
476                         auth_id = g_strdup((const char*) value);
477                         dbg("auth id (%s)", auth_id);
478                 }
479                 else if (g_str_equal(key, "8") == TRUE) {
480                         auth_pwd = g_strdup((const char*) value);
481                         dbg("auth pwd (%s)", auth_pwd);
482                 }
483                 else if (g_str_equal(key, "9") == TRUE) {
484                         proxy_addr = g_strdup((const char*) value);
485                         dbg("proxy addr (%s)", proxy_addr);
486                 }
487                 else if (g_str_equal(key, "10") == TRUE) {
488                         home_url = g_strdup((const char*) value);
489                         dbg("home url (%s)", home_url);
490                 }
491                 else if (g_str_equal(key, "11") == TRUE) {
492                         pdp_protocol = atoi((const char*) value);
493                         dbg("pdp protocol (%d)", pdp_protocol);
494                 }
495                 else if (g_str_equal(key, "21") == TRUE) {
496                         svc_ctg_id = atoi((const char*) value);
497                         dbg("context category type (%d)", svc_ctg_id);
498                 }
499         }
500
501         path = __ps_context_create_path(profile_name, svc_ctg_id);
502
503         context = (PsContext *) object;
504         co_context = tcore_context_new(context->plg, path, NULL);
505         tcore_context_set_state(co_context, CONTEXT_STATE_DEACTIVATED);
506         tcore_context_set_role(co_context, svc_ctg_id);
507         tcore_context_set_apn(co_context, apn);
508         tcore_context_set_auth(co_context, auth_type);
509         tcore_context_set_username(co_context, auth_id);
510         tcore_context_set_password(co_context, auth_pwd);
511         tcore_context_set_proxy(co_context, proxy_addr);
512         tcore_context_set_mmsurl(co_context, home_url);
513
514         context->profile_id = profile_id;
515         context->path = g_strdup(path);
516         context->co_context = co_context;
517
518         g_free(path);
519         return TRUE;
520 }
521
522 static gpointer __ps_context_create_context(DBusGConnection *conn, TcorePlugin *p,
523                 gchar *mccmnc, GHashTable *property)
524 {
525         guint rv = 0;
526         GError *error = NULL;
527         DBusGProxy *proxy;
528         GObject *object = NULL;
529         gchar *path = NULL;
530
531         proxy = dbus_g_proxy_new_for_name(conn, "org.freedesktop.DBus", "/org/freedesktop/DBus",
532                         "org.freedesktop.DBus");
533
534         if (!dbus_g_proxy_call(proxy, "RequestName", &error, G_TYPE_STRING, PS_DBUS_SERVICE,
535                         G_TYPE_UINT, 0, G_TYPE_INVALID, G_TYPE_UINT, &rv, G_TYPE_INVALID)) {
536                 err("Failed to acquire context(%s) error(%s)", PS_DBUS_SERVICE, error->message);
537                 return NULL;
538         }
539
540         object = g_object_new(PS_TYPE_CONTEXT, "conn", conn, "plg", p, "mccmnc", mccmnc);
541
542         __ps_context_create_co_context(object, property);
543         __ps_context_set_alwayson_enable(object, TRUE);
544         path = _ps_context_ref_path(object);
545
546         dbus_g_connection_register_g_object(conn, g_strdup(path), object);
547         msg("context(%p) register dbus path(%s)", object, path);
548
549         return object;
550 }
551
552 static gboolean __ps_context_update_profile(PsContext *context, GHashTable *property)
553 {
554         CoreObject *co_context = NULL;
555         GHashTableIter iter;
556         gpointer key, value;
557
558         co_context = context->co_context;
559         if (!co_context)
560                 return FALSE;
561
562         g_hash_table_iter_init(&iter, property);
563         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
564                 if (g_str_equal(key, "apn") == TRUE) {
565                         tcore_context_set_apn(co_context, (const char *) value);
566                 }
567                 else if (g_str_equal(key, "auth_type") == TRUE) {
568                         int i_tmp = 0;
569                         i_tmp = atoi((const char *) value);
570                         tcore_context_set_auth(co_context, i_tmp);
571                 }
572                 else if (g_str_equal(key, "auth_id") == TRUE) {
573                         tcore_context_set_username(co_context, (const char *) value);
574                 }
575                 else if (g_str_equal(key, "auth_pwd") == TRUE) {
576                         tcore_context_set_password(co_context, (const char *) value);
577                 }
578                 else if (g_str_equal(key, "proxy_addr") == TRUE) {
579                         tcore_context_set_proxy(co_context, (const char *) value);
580                 }
581                 else if (g_str_equal(key, "home_url") == TRUE) {
582                         tcore_context_set_mmsurl(co_context, (const char *) value);
583                 }
584         }
585
586         return __ps_context_update_database(context);
587 }
588
589 static gboolean __ps_context_update_database(PsContext *context)
590 {
591         gchar *s_id = NULL, *s_authtype = NULL;
592         gchar *s_apn = NULL, *s_username = NULL, *s_pwd = NULL, *s_proxy = NULL, *s_mms = NULL;
593         gboolean rv = FALSE;
594         char szQuery[3000];
595
596         GHashTable *in_param;
597         in_param = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
598
599         strcpy(szQuery, " update pdp_profile set ");
600         strcat(szQuery, " apn = ?, auth_type = ?, auth_id = ?, auth_pwd = ?, ");
601         strcat(szQuery, " proxy_ip_addr = ?, home_url = ?");
602         strcat(szQuery, " where profile_id = ?");
603
604         s_id = g_strdup_printf("%d", context->profile_id);
605         s_authtype = g_strdup_printf("%d", tcore_context_get_auth(context->co_context));
606
607         s_apn = tcore_context_get_apn(context->co_context);
608         s_username = tcore_context_get_username(context->co_context);
609         s_pwd = tcore_context_get_password(context->co_context);
610         s_proxy = tcore_context_get_proxy(context->co_context);
611         s_mms = tcore_context_get_mmsurl(context->co_context);
612
613         g_hash_table_insert(in_param, "1", g_strdup(s_apn));
614         g_hash_table_insert(in_param, "2", g_strdup(s_authtype));
615         g_hash_table_insert(in_param, "3", g_strdup(s_username));
616         g_hash_table_insert(in_param, "4", g_strdup(s_pwd));
617         g_hash_table_insert(in_param, "5", g_strdup(s_proxy));
618         g_hash_table_insert(in_param, "6", g_strdup(s_mms));
619         g_hash_table_insert(in_param, "7", g_strdup(s_id));
620
621         rv = tcore_storage_update_query_database(strg_db, handle, szQuery, in_param);
622         g_hash_table_destroy(in_param);
623
624         g_free(s_id);
625         g_free(s_authtype);
626         g_free(s_apn);
627         g_free(s_username);
628         g_free(s_pwd);
629         g_free(s_proxy);
630         g_free(s_mms);
631
632         return rv;
633 }
634
635 static gboolean __ps_context_remove_database(PsContext *context)
636 {
637         gchar *s_id = NULL;
638         gboolean rv = FALSE;
639         char szQuery[1000];
640
641         GHashTable *in_param;
642         in_param = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
643
644         memset(szQuery, 0, sizeof(szQuery));
645         strcpy(szQuery, " delete from pdp_profile where profile_id = ? ");
646
647         s_id = g_strdup_printf("%d", context->profile_id);
648         g_hash_table_insert(in_param, "1", g_strdup(s_id));
649
650         rv = tcore_storage_remove_query_database(strg_db, handle, szQuery, in_param);
651         g_free(s_id);
652         g_hash_table_destroy(in_param);
653
654         return rv;
655 }
656
657 static int __ps_context_insert_network_id_to_database(gchar *mccmnc)
658 {
659         char szQuery[5000];
660         int network_id = 0;
661         gboolean rv = FALSE;
662         gchar *insert_key = NULL;
663         GHashTableIter iter;
664         gpointer key, value;
665         GHashTable *in_param, *out_param;
666
667         in_param = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
668         out_param = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
669                                 (GDestroyNotify) g_hash_table_destroy);
670
671         memset(szQuery, 0, sizeof(szQuery));
672         strcpy(szQuery," select  max(network_info_id) from network_info ");
673
674         tcore_storage_read_query_database(strg_db, handle, szQuery, NULL, out_param, 1);
675
676         g_hash_table_iter_init(&iter, out_param);
677         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
678                 GHashTableIter iter2;
679                 gpointer key2, value2;
680
681                 if(value){
682                         g_hash_table_iter_init(&iter2, (GHashTable *) value);
683                         while (g_hash_table_iter_next(&iter2, &key2, &value2) == TRUE) {
684                                 if (g_str_equal(key, "0") == TRUE) {
685                                         network_id = atoi((const char*) value2);
686                                 }
687                         }
688                         break;
689                 }
690         }
691
692         g_hash_table_destroy(out_param);
693         network_id++;
694
695
696         memset(szQuery, 0, sizeof(szQuery));
697         strcpy(szQuery," insert into network_info( network_info_id, network_name, mccmnc) values( ?, ?, ?) ");
698
699         insert_key = g_strdup_printf("%d", network_id);
700         g_hash_table_insert(in_param, "1", g_strdup(insert_key));
701         g_hash_table_insert(in_param, "2", "TEMP_NETWORK");
702         g_hash_table_insert(in_param, "3", g_strdup(mccmnc));
703
704         rv = tcore_storage_insert_query_database(strg_db, handle, szQuery, in_param);
705         if(!rv)
706                 return 0;
707
708         g_free(insert_key);
709         return network_id;
710 }
711
712 static int __ps_context_insert_profile_to_database(GHashTable *property, int network_id)
713 {
714         int profile_id = 0;
715         char szQuery[5000];
716
717         gboolean rv = FALSE;
718         GHashTableIter iter;
719         gpointer key, value;
720         GHashTable *in_param;
721         gchar *insert_key1 = NULL, *insert_key2 = NULL;
722         gchar *profile_name=NULL, *apn=NULL, *auth_type=NULL, *auth_id = NULL, *auth_pwd = NULL;
723         gchar *proxy_addr = NULL, *home_url = NULL, *svc_id = NULL;
724
725         in_param = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
726
727         g_hash_table_iter_init(&iter, property);
728         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
729
730                 if (g_str_equal(key, "apn") == TRUE) {
731                         apn = g_strdup(value);
732                 }
733                 else if (g_str_equal(key, "auth_type") == TRUE) {
734                         auth_type = g_strdup(value);
735                 }
736                 else if (g_str_equal(key, "auth_id") == TRUE) {
737                         auth_id = g_strdup(value);
738                 }
739                 else if (g_str_equal(key, "auth_pwd") == TRUE) {
740                         auth_pwd = g_strdup(value);
741                 }
742                 else if (g_str_equal(key, "proxy_addr") == TRUE) {
743                         proxy_addr = g_strdup(value);
744                 }
745                 else if (g_str_equal(key, "home_url") == TRUE) {
746                         home_url = g_strdup(value);
747                 }
748                 else if (g_str_equal(key, "svc_ctg_id") == TRUE) {
749                         svc_id = g_strdup(value);
750                 }
751
752         }
753
754         dbg("apn (%s), auth_type (%s), auth_id(%s), auth_pwd(%s), proxy_addr(%s), home_url(%s), svc_id(%s)",
755                 apn, auth_type, auth_id, auth_pwd, proxy_addr, home_url, svc_id);
756
757         profile_id = __ps_context_load_profile_id_from_database();
758         if(profile_id <= 0){
759                 dbg("fail to get last profile id");
760                 return 0;
761         }
762         profile_id++;
763
764         memset(szQuery, 0, sizeof(szQuery));
765         strcpy(szQuery," insert into pdp_profile( ");
766         strcat(szQuery," profile_id, transport_type, profile_name, apn, auth_type, auth_id, auth_pwd, ");
767         strcat(szQuery," pdp_protocol, proxy_ip_addr, home_url, linger_time, is_secure_connection, app_protocol_type, ");
768         strcat(szQuery," network_info_id, svc_category_id) values( ");
769         strcat(szQuery," ?, 1, ? , ?, ?, ?, ?, ");//1,2,3,4,5,6
770         strcat(szQuery," 1, ?, ?, 300, 0, 1, ");//7,8
771         strcat(szQuery," ?, ? )");//9,10
772
773         insert_key1 = g_strdup_printf("%d", profile_id);
774         insert_key2 = g_strdup_printf("%d", network_id);
775         profile_name = g_strdup_printf("tmp_profile%d", profile_id);
776
777         g_hash_table_insert(in_param, "1", g_strdup(insert_key1));
778         g_hash_table_insert(in_param, "2", g_strdup(profile_name));
779         g_hash_table_insert(in_param, "3", g_strdup(apn));
780         g_hash_table_insert(in_param, "4", g_strdup(auth_type));
781         g_hash_table_insert(in_param, "5", g_strdup(auth_id));
782         g_hash_table_insert(in_param, "6", g_strdup(auth_pwd));
783         g_hash_table_insert(in_param, "7", g_strdup(proxy_addr));
784         g_hash_table_insert(in_param, "8", g_strdup(home_url));
785         g_hash_table_insert(in_param, "9", g_strdup(insert_key2));
786         g_hash_table_insert(in_param, "10", g_strdup(svc_id));
787
788         g_free(insert_key1);g_free(insert_key2);g_free(profile_name);
789         g_free(apn);g_free(auth_type);g_free(auth_id);g_free(auth_pwd);
790         g_free(proxy_addr);g_free(home_url);g_free(svc_id);
791
792         rv = tcore_storage_insert_query_database(strg_db, handle, szQuery, in_param);
793         g_hash_table_destroy(in_param);
794
795         if(!rv)
796                 return 0;
797
798         return profile_id;
799 }
800
801 static int __ps_context_load_network_id_from_database(gchar *mccmnc)
802 {
803         char szQuery[5000];
804         int network_id = 0;
805         GHashTableIter iter;
806         gpointer key, value;
807         GHashTable *in_param, *out_param;
808
809         in_param = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
810         out_param = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
811                         (GDestroyNotify) g_hash_table_destroy);
812
813         memset(szQuery, 0, sizeof(szQuery));
814         strcpy(szQuery,"select network_info_id from network_info where mccmnc = ? ");
815
816         g_hash_table_insert(in_param, "1", g_strdup(mccmnc));
817         tcore_storage_read_query_database(strg_db, handle, szQuery, in_param, out_param, 1);
818
819         g_hash_table_iter_init(&iter, out_param);
820         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
821                 GHashTableIter iter2;
822                 gpointer key2, value2;
823
824                 if(value){
825                         g_hash_table_iter_init(&iter2, (GHashTable *) value);
826                         while (g_hash_table_iter_next(&iter2, &key2, &value2) == TRUE) {
827                                 if (g_str_equal(key, "0") == TRUE) {
828                                         network_id = atoi((const char*) value2);
829                                 }
830                         }
831                         break;
832                 }
833         }
834
835         g_hash_table_destroy(in_param);
836         g_hash_table_destroy(out_param);
837
838         return network_id;
839 }
840
841 static int __ps_context_load_profile_id_from_database(void)
842 {
843         char szQuery[5000];
844         int profile_id = 0;
845         GHashTableIter iter;
846         gpointer key, value;
847         GHashTable *out_param;
848
849         out_param = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
850                         (GDestroyNotify) g_hash_table_destroy);
851
852         memset(szQuery, 0, sizeof(szQuery));
853         strcpy(szQuery,"select max(profile_id) as last_profile from pdp_profile");
854
855         tcore_storage_read_query_database(strg_db, handle, szQuery, NULL, out_param, 1);
856
857         g_hash_table_iter_init(&iter, out_param);
858         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
859                 GHashTableIter iter2;
860                 gpointer key2, value2;
861
862                 if(value){
863                         g_hash_table_iter_init(&iter2, (GHashTable *) value);
864                         while (g_hash_table_iter_next(&iter2, &key2, &value2) == TRUE) {
865                                 if (g_str_equal(key, "0") == TRUE) {
866                                         profile_id = atoi((const char*) value2);
867                                 }
868                         }
869                         break;
870                 }
871         }
872
873         g_hash_table_destroy(out_param);
874         return profile_id;
875 }
876
877 static gboolean __ps_context_reset_database(void)
878 {
879         int rv = 0;
880         gchar *extract_sql, *recover_sql, *remove_tmp;
881
882         extract_sql = g_strdup("tar --extract --file=/opt/system/customer_selected/preconfig/customer.tar.gz opt/dbspace/.dnet.db -C /tmp");
883         dbg("system extract command (%s)", extract_sql);
884         rv = system(extract_sql);
885
886         recover_sql = g_strdup("sqlite3 /opt/dbspace/.dnet.db \"attach database '/tmp/opt/dbspace/.dnet.db' as csc; replace into pdp_profile select * from csc.pdp_profile;\" ");
887         dbg("system recover db command (%s)", recover_sql);
888         rv = system(recover_sql);
889
890         remove_tmp = g_strdup("rm -rf /tmp/opt/dbspace/.dnet.db");
891         dbg("system recover db command (%s)", remove_tmp);
892         rv = system(remove_tmp);
893
894         g_free(extract_sql);
895         g_free(recover_sql);
896         g_free(remove_tmp);
897
898         return TRUE;
899 }
900
901 static int __ps_context_get_network_id(gchar *mccmnc)
902 {
903         int network_id;
904
905         network_id = __ps_context_load_network_id_from_database(mccmnc);
906         if(network_id > 0)
907                 return network_id;
908
909         network_id = __ps_context_insert_network_id_to_database(mccmnc);
910         if(network_id <= 0 )
911                 return -1;
912
913         return network_id;
914 }
915
916 static gboolean __ps_context_get_profile_properties(gpointer object, GHashTable *properties)
917 {
918         gchar *s_authtype = NULL, *s_role = NULL;
919         PsContext *context = NULL;
920
921         g_return_val_if_fail(object != NULL, FALSE);
922         g_return_val_if_fail(properties != NULL, FALSE);
923
924         context = (PsContext *) object;
925         dbg("get profile properties");
926
927         s_authtype = g_strdup_printf("%d", tcore_context_get_auth(context->co_context));
928         s_role = g_strdup_printf("%d", tcore_context_get_role(context->co_context));
929
930         g_hash_table_insert(properties, "path", g_strdup(context->path));
931         g_hash_table_insert(properties, "apn", tcore_context_get_apn(context->co_context));
932         g_hash_table_insert(properties, "auth_type", g_strdup(s_authtype));
933         g_hash_table_insert(properties, "auth_id", tcore_context_get_username(context->co_context));
934         g_hash_table_insert(properties, "auth_pwd", tcore_context_get_password(context->co_context));
935         g_hash_table_insert(properties, "proxy_addr", tcore_context_get_proxy(context->co_context));
936         g_hash_table_insert(properties, "home_url", tcore_context_get_mmsurl(context->co_context));
937         g_hash_table_insert(properties, "svc_ctg_id", g_strdup(s_role));
938
939         g_free(s_authtype);
940         g_free(s_role);
941
942         return TRUE;
943 }
944
945 static gboolean __ps_context_set_alwayson_enable(gpointer object, gboolean enabled)
946 {
947         PsContext *context = object;
948         int role = CONTEXT_ROLE_UNKNOWN;
949         g_return_val_if_fail(context != NULL, FALSE);
950
951         role = tcore_context_get_role(context->co_context);
952         if(role == CONTEXT_ROLE_INTERNET){
953                 context->alwayson = enabled;
954         }
955
956         return TRUE;
957 }
958
959 static gpointer __ps_context_add_context(gpointer modem, gchar *mccmnc, int profile_id)
960 {
961         char szQuery[5000];
962         DBusGConnection *conn = NULL;
963         TcorePlugin *p = NULL;
964
965         GHashTableIter iter;
966         gpointer object = NULL;
967         gpointer key, value;
968         gchar *insert_key1 = NULL;
969         GHashTable *in_param, *out_param;
970         in_param = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
971         out_param = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
972                         (GDestroyNotify) g_hash_table_destroy);
973
974         dbg("create profile by profile id (%d)", profile_id);
975         conn = _ps_modem_ref_dbusconn(modem);
976         p = _ps_modem_ref_plugin(modem);
977
978         memset(szQuery, '\0', 5000);
979         strcpy(szQuery, "select");
980         strcat(szQuery, " a.network_info_id, a.network_name, a.mccmnc,"); //0 , 1, 2
981         strcat(szQuery, " b.profile_id, b.profile_name, b.apn, "); //3, 4, 5
982         strcat(szQuery, " b.auth_type, b.auth_id, b.auth_pwd,"); //6, 7, 8
983         strcat(szQuery, " b.proxy_ip_addr, b.home_url, b.pdp_protocol, "); //9, 10 , 11
984         strcat(szQuery, " b.linger_time, b.is_secure_connection, b.app_protocol_type, b.traffic_class,"); //12, 13, 14, 15
985         strcat(szQuery, " b.is_static_ip_addr, b.ip_addr, b.is_static_dns_addr, b.dns_addr1, b.dns_addr2, b.svc_category_id"); //16,17, 18, 19, 20, 21
986         strcat(szQuery, " from network_info a, pdp_profile b");
987         strcat(szQuery, " where b.profile_id = ? and a.network_info_id = b.network_info_id ");
988
989         insert_key1 = g_strdup_printf("%d", profile_id);
990         g_hash_table_insert(in_param, "1", g_strdup(insert_key1));
991         tcore_storage_read_query_database(strg_db, handle, szQuery, in_param, out_param, 22);
992
993         g_hash_table_iter_init(&iter, out_param);
994         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
995                 gchar *path = NULL;
996
997                 object = __ps_context_create_context(conn, p, mccmnc, (GHashTable *) value);
998                 path = _ps_context_ref_path(object);
999
1000                 g_hash_table_insert(contexts, g_strdup(path), object);
1001                 dbg("context (%p, %s) insert to hash", object, path);
1002         }
1003
1004         g_hash_table_destroy(in_param);
1005         g_hash_table_destroy(out_param);
1006         g_free(insert_key1);
1007
1008         return object;
1009 }
1010
1011 gboolean _ps_context_initialize(gpointer plugin)
1012 {
1013         gboolean rv = TRUE;
1014
1015         dbg("global variable initialized");
1016         rv &=__ps_context_create_storage_handle(plugin);
1017         rv &=__ps_context_create_context_hash();
1018
1019         return rv;
1020 }
1021
1022 gboolean _ps_context_reset_hashtable(void)
1023 {
1024         if(!contexts)
1025                 return TRUE;
1026
1027         g_hash_table_foreach_remove(contexts, __remove_contexts, NULL);
1028         __ps_context_reset_database();
1029         return TRUE;
1030 }
1031
1032 GHashTable* _ps_context_create_hashtable(DBusGConnection *conn, TcorePlugin *p, gchar *mccmnc)
1033 {
1034         char szQuery[5000];
1035         GHashTableIter iter;
1036         gpointer key, value;
1037         GHashTable *in_param, *out_param;
1038         in_param = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
1039         out_param = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
1040                         (GDestroyNotify) g_hash_table_destroy);
1041
1042         dbg("create profile by mccmnc (%s)", mccmnc);
1043
1044         memset(szQuery, '\0', 5000);
1045         strcpy(szQuery, "select");
1046         strcat(szQuery, " a.network_info_id, a.network_name, a.mccmnc,"); //0 , 1, 2
1047         strcat(szQuery, " b.profile_id, b.profile_name, b.apn, "); //3, 4, 5
1048         strcat(szQuery, " b.auth_type, b.auth_id, b.auth_pwd,"); //6, 7, 8
1049         strcat(szQuery, " b.proxy_ip_addr, b.home_url, b.pdp_protocol, "); //9, 10 , 11
1050         strcat(szQuery, " b.linger_time, b.is_secure_connection, b.app_protocol_type, b.traffic_class,"); //12, 13, 14, 15
1051         strcat(szQuery, " b.is_static_ip_addr, b.ip_addr, b.is_static_dns_addr, b.dns_addr1, b.dns_addr2, b.svc_category_id"); //16,17, 18, 19, 20, 21
1052         strcat(szQuery, " from network_info a, pdp_profile b");
1053         strcat(szQuery, " where a.mccmnc= ? and a.network_info_id = b.network_info_id ");
1054
1055         g_hash_table_insert(in_param, "1", g_strdup(mccmnc));
1056         tcore_storage_read_query_database(strg_db, handle, szQuery, in_param, out_param, 22);
1057
1058         g_hash_table_iter_init(&iter, out_param);
1059         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
1060                 gchar *path = NULL;
1061                 gpointer object = NULL;
1062
1063                 object = __ps_context_create_context(conn, p, mccmnc, (GHashTable *) value);
1064                 path = _ps_context_ref_path(object);
1065
1066                 g_hash_table_insert(contexts, g_strdup(path), object);
1067                 dbg("context (%p, %s) insert to hash", object, path);
1068         }
1069
1070         g_hash_table_destroy(in_param);
1071         g_hash_table_destroy(out_param);
1072
1073         return contexts;
1074 }
1075
1076 GHashTable* _ps_context_ref_hashtable(void)
1077 {
1078         g_return_val_if_fail(contexts != NULL, NULL);
1079         return contexts;
1080 }
1081
1082 gboolean _ps_context_add_context(gpointer modem, gchar *operator, GHashTable *property)
1083 {
1084         GHashTable *services = NULL;
1085         gpointer context = NULL;
1086
1087         GHashTableIter iter;
1088         gpointer key, value;
1089         int network_id = 0;
1090         int profile_id = 0;
1091
1092         network_id = __ps_context_get_network_id(operator);
1093         if(network_id <= 0){
1094                 dbg("fail to add network info");
1095                 return FALSE;
1096         }
1097
1098         profile_id = __ps_context_insert_profile_to_database(property, network_id);
1099         if(profile_id <= 0){
1100                 dbg("fail to insert profile info to database");
1101                 return FALSE;
1102         }
1103
1104         context = __ps_context_add_context(modem, operator, profile_id);
1105         if(!context)
1106                 return FALSE;
1107
1108         services = _ps_modem_ref_services(modem);
1109         if(!services)
1110                 return FALSE;
1111
1112         g_hash_table_iter_init(&iter, services);
1113         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
1114                 _ps_service_ref_context(value, context);
1115         }
1116
1117         return TRUE;
1118 }
1119
1120 gboolean _ps_context_get_properties(gpointer object, GHashTable *properties)
1121 {
1122         int context_state = 0;
1123         gboolean active = FALSE;
1124         PsContext *context = object;
1125
1126         dbg("get context properties");
1127         g_return_val_if_fail(context != NULL, FALSE);
1128         g_return_val_if_fail(properties != NULL, FALSE);
1129
1130         context_state =    tcore_context_get_state(context->co_context);
1131         if (context_state == CONTEXT_STATE_ACTIVATED)
1132                 active = TRUE;
1133
1134         g_hash_table_insert(properties, "path", g_strdup(context->path));
1135         g_hash_table_insert(properties, "active", g_strdup(BOOL2STRING(active)));
1136         g_hash_table_insert(properties, "ipv4_address", tcore_context_get_ipv4_addr(context->co_context));
1137         g_hash_table_insert(properties, "ipv4_gateway", tcore_context_get_ipv4_gw(context->co_context));
1138         g_hash_table_insert(properties, "ipv4_dns1", tcore_context_get_ipv4_dns1(context->co_context));
1139         g_hash_table_insert(properties, "ipv4_dns2", tcore_context_get_ipv4_dns2(context->co_context));
1140         g_hash_table_insert(properties, "ipv6_address", "::" );
1141         g_hash_table_insert(properties, "ipv6_gateway", "::" );
1142         g_hash_table_insert(properties, "ipv6_dns1", "::" );
1143         g_hash_table_insert(properties, "ipv6_dns2", "::" );
1144         g_hash_table_insert(properties, "proxy", tcore_context_get_proxy(context->co_context));
1145         g_hash_table_insert(properties, "dev_name", tcore_context_get_ipv4_devname(context->co_context));
1146
1147         return TRUE;
1148 }
1149
1150 gboolean _ps_context_set_service(gpointer object, gpointer service)
1151 {
1152         PsContext *context = object;
1153         g_return_val_if_fail(context != NULL, FALSE);
1154
1155         context->p_service = service;
1156         return TRUE;
1157 }
1158
1159 gpointer _ps_context_ref_service(gpointer object)
1160 {
1161         PsContext *context = object;
1162         g_return_val_if_fail(context != NULL, FALSE);
1163
1164         return context->p_service;
1165 }
1166
1167 gchar* _ps_context_ref_path(gpointer object)
1168 {
1169         PsContext *context = object;
1170         g_return_val_if_fail(context != NULL, NULL);
1171
1172         return context->path;
1173 }
1174
1175 gboolean _ps_context_get_alwayson_enable(gpointer object)
1176 {
1177         PsContext *context = object;
1178         g_return_val_if_fail(context != NULL, FALSE);
1179
1180         return context->alwayson;
1181 }
1182
1183 gpointer _ps_context_ref_co_context(gpointer object)
1184 {
1185         PsContext *context = object;
1186         g_return_val_if_fail(context != NULL, NULL);
1187
1188         return context->co_context;
1189 }
1190
1191 gboolean _ps_context_set_connected(gpointer object, gboolean enabled)
1192 {
1193         gchar *ipv4 = NULL;
1194         PsContext *context = object;
1195         g_return_val_if_fail(context != NULL, FALSE);
1196
1197
1198         ipv4 = tcore_context_get_ipv4_addr(context->co_context);
1199
1200         if (enabled) {
1201
1202                 tcore_context_set_state(context->co_context, CONTEXT_STATE_ACTIVATED);
1203                 if( g_str_equal(ipv4, "0.0.0.0") == TRUE ){
1204                         dbg("ip address is 0.0.0.0");
1205                         _ps_service_deactivate_context(context->p_service, context);
1206                         return TRUE;
1207                 }
1208                 _ps_service_reset_connection_timer(context);
1209
1210         }
1211         else {
1212                 tcore_context_set_state(context->co_context, CONTEXT_STATE_DEACTIVATED);
1213                 tcore_context_reset_devinfo(context->co_context);
1214                 _ps_service_connection_timer(context->p_service, context);
1215         }
1216
1217         __ps_context_emit_property_changed_signal(context);
1218         g_free(ipv4);
1219         return TRUE;
1220 }