Add new API : connection_set_default_cellular_service_profile_async()
[platform/core/api/connection.git] / src / libnetwork.c
1 /*
2  * Copyright (c) 2011-2013 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License. 
15  */
16
17 #include <stdio.h>
18 #include <string.h>
19 #include <glib.h>
20 #include <vconf/vconf.h>
21 #include "net_connection_private.h"
22
23 static GSList *prof_handle_list = NULL;
24 static GHashTable *profile_cb_table = NULL;
25
26 struct _profile_cb_s {
27         connection_profile_state_changed_cb callback;
28         connection_profile_state_e state;
29         void *user_data;
30 };
31
32 struct _profile_list_s {
33         int count;
34         int next;
35         net_profile_info_t *profiles;
36 };
37
38 struct _libnet_s {
39         connection_opened_cb opened_cb;
40         connection_closed_cb closed_cb;
41         connection_set_default_cb set_default_cb;
42         void *opened_user_data;
43         void *closed_user_data;
44         void *set_default_user_data;
45         bool registered;
46 };
47
48 static struct _profile_list_s profile_iterator = {0, 0, NULL};
49 static struct _libnet_s libnet = {NULL, NULL, NULL, NULL, NULL, NULL, false};
50
51 static connection_error_e __libnet_convert_to_cp_error_type(net_err_t err_type)
52 {
53         switch (err_type) {
54         case NET_ERR_NONE:
55                 return CONNECTION_ERROR_NONE;
56         case NET_ERR_APP_ALREADY_REGISTERED:
57                 return CONNECTION_ERROR_INVALID_OPERATION;
58         case NET_ERR_APP_NOT_REGISTERED:
59                 return CONNECTION_ERROR_INVALID_OPERATION;
60         case NET_ERR_NO_ACTIVE_CONNECTIONS:
61                 return CONNECTION_ERROR_NO_CONNECTION;
62         case NET_ERR_ACTIVE_CONNECTION_EXISTS:
63                 return CONNECTION_ERROR_ALREADY_EXISTS;
64         case NET_ERR_CONNECTION_DHCP_FAILED:
65                 return CONNECTION_ERROR_DHCP_FAILED;
66         case NET_ERR_CONNECTION_INVALID_KEY:
67                 return CONNECTION_ERROR_INVALID_KEY;
68         case NET_ERR_IN_PROGRESS:
69                 return CONNECTION_ERROR_NOW_IN_PROGRESS;
70         case NET_ERR_OPERATION_ABORTED:
71                 return CONNECTION_ERROR_OPERATION_ABORTED;
72         case NET_ERR_TIME_OUT:
73                 return CONNECTION_ERROR_NO_REPLY;
74         default:
75                 return CONNECTION_ERROR_OPERATION_FAILED;
76         }
77 }
78
79 static const char *__libnet_convert_cp_error_type_to_string(connection_error_e err_type)
80 {
81         switch (err_type) {
82         case CONNECTION_ERROR_NONE:
83                 return "NONE";
84         case CONNECTION_ERROR_INVALID_PARAMETER:
85                 return "INVALID_PARAMETER";
86         case CONNECTION_ERROR_OUT_OF_MEMORY:
87                 return "OUT_OF_MEMORY";
88         case CONNECTION_ERROR_INVALID_OPERATION:
89                 return "INVALID_OPERATION";
90         case CONNECTION_ERROR_ADDRESS_FAMILY_NOT_SUPPORTED:
91                 return "ADDRESS_FAMILY_NOT_SUPPORTED";
92         case CONNECTION_ERROR_OPERATION_FAILED:
93                 return "OPERATION_FAILED";
94         case CONNECTION_ERROR_ITERATOR_END:
95                 return "ITERATOR_END";
96         case CONNECTION_ERROR_NO_CONNECTION:
97                 return "NO_CONNECTION";
98         case CONNECTION_ERROR_NOW_IN_PROGRESS:
99                 return "NOW_IN_PROGRESS";
100         case CONNECTION_ERROR_ALREADY_EXISTS:
101                 return "ALREADY_EXISTS";
102         case CONNECTION_ERROR_OPERATION_ABORTED:
103                 return "OPERATION_ABORTED";
104         case CONNECTION_ERROR_DHCP_FAILED:
105                 return "DHCP_FAILED";
106         case CONNECTION_ERROR_INVALID_KEY:
107                 return "INVALID_KEY";
108         case CONNECTION_ERROR_NO_REPLY:
109                 return "NO_REPLY";
110         }
111
112         return "UNKNOWN";
113 }
114
115 static const char *__libnet_convert_cp_state_to_string(connection_profile_state_e state)
116 {
117         switch (state) {
118         case CONNECTION_PROFILE_STATE_DISCONNECTED:
119                 return "DISCONNECTED";
120         case CONNECTION_PROFILE_STATE_ASSOCIATION:
121                 return "ASSOCIATION";
122         case CONNECTION_PROFILE_STATE_CONFIGURATION:
123                 return "CONFIGURATION";
124         case CONNECTION_PROFILE_STATE_CONNECTED:
125                 return "CONNECTED";
126         default:
127                 return "UNKNOWN";
128         }
129 }
130
131 static void __libnet_set_opened_cb(connection_opened_cb user_cb, void *user_data)
132 {
133         if (user_cb) {
134                 libnet.opened_cb = user_cb;
135                 libnet.opened_user_data = user_data;
136         }
137 }
138
139 static void __libnet_opened_cb(connection_error_e result)
140 {
141         if (libnet.opened_cb)
142                 libnet.opened_cb(result, libnet.opened_user_data);
143
144         libnet.opened_cb = NULL;
145         libnet.opened_user_data = NULL;
146 }
147
148 static void __libnet_set_closed_cb(connection_closed_cb user_cb, void *user_data)
149 {
150         if (user_cb) {
151                 libnet.closed_cb = user_cb;
152                 libnet.closed_user_data = user_data;
153         }
154 }
155
156 static void __libnet_closed_cb(connection_error_e result)
157 {
158         if (libnet.closed_cb)
159                 libnet.closed_cb(result, libnet.closed_user_data);
160
161         libnet.closed_cb = NULL;
162         libnet.closed_user_data = NULL;
163 }
164
165 static void __libnet_set_default_cb(connection_set_default_cb user_cb, void *user_data)
166 {
167         if (user_cb) {
168                 libnet.set_default_cb = user_cb;
169                 libnet.set_default_user_data = user_data;
170         }
171 }
172
173 static void __libnet_default_cb(connection_error_e result)
174 {
175         if (libnet.set_default_cb)
176                 libnet.set_default_cb(result, libnet.set_default_user_data);
177
178         libnet.set_default_cb = NULL;
179         libnet.set_default_user_data = NULL;
180 }
181
182 static void __libnet_state_changed_cb(char *profile_name, connection_profile_state_e state)
183 {
184         if (profile_name == NULL)
185                 return;
186
187         struct _profile_cb_s *cb_info;
188         cb_info = g_hash_table_lookup(profile_cb_table, profile_name);
189
190         if (cb_info == NULL)
191                 return;
192
193         if (cb_info->state == state)
194                 return;
195
196         cb_info->state = state;
197
198         if (state >= 0 && cb_info->callback)
199                 cb_info->callback(state, cb_info->user_data);
200 }
201
202 static void __libnet_clear_profile_list(struct _profile_list_s *profile_list)
203 {
204         if (profile_list->count > 0)
205                 g_free(profile_list->profiles);
206
207         profile_list->count = 0;
208         profile_list->next = 0;
209         profile_list->profiles = NULL;
210 }
211
212 static void __libnet_evt_cb(net_event_info_t*  event_cb, void* user_data)
213 {
214         bool is_requested = false;
215         connection_error_e result = CONNECTION_ERROR_NONE;
216
217         switch (event_cb->Event) {
218         case NET_EVENT_OPEN_RSP:
219                 is_requested = true;
220                 /* fall through */
221         case NET_EVENT_OPEN_IND:
222                 result = __libnet_convert_to_cp_error_type(event_cb->Error);
223                 CONNECTION_LOG(CONNECTION_INFO, "Got connection open %s : %s\n",
224                                         (is_requested) ? "RSP":"IND",
225                                         __libnet_convert_cp_error_type_to_string(result));
226
227                 if (is_requested)
228                         __libnet_opened_cb(result);
229
230                 switch (event_cb->Error) {
231                 case NET_ERR_NONE:
232                 case NET_ERR_ACTIVE_CONNECTION_EXISTS:
233                         CONNECTION_LOG(CONNECTION_INFO, "'Open connection' succeeded\n");
234
235                         __libnet_state_changed_cb(event_cb->ProfileName, CONNECTION_PROFILE_STATE_CONNECTED);
236                         return;
237                 default:
238                         CONNECTION_LOG(CONNECTION_ERROR, "'Open connection' failed!! [%s]\n",
239                                                 __libnet_convert_cp_error_type_to_string(result));
240                 }
241
242                 __libnet_state_changed_cb(event_cb->ProfileName, CONNECTION_PROFILE_STATE_DISCONNECTED);
243
244                 break;
245         case NET_EVENT_CLOSE_RSP:
246                 is_requested = true;
247                 /* fall through */
248         case NET_EVENT_CLOSE_IND:
249                 result = __libnet_convert_to_cp_error_type(event_cb->Error);
250                 CONNECTION_LOG(CONNECTION_INFO, "Got connection close %s : %s\n",
251                                         (is_requested) ? "RSP":"IND",
252                                         __libnet_convert_cp_error_type_to_string(result));
253
254                 if (is_requested)
255                         __libnet_closed_cb(result);
256
257                 switch (event_cb->Error) {
258                 case NET_ERR_NONE:
259                         CONNECTION_LOG(CONNECTION_INFO, "'Close connection' succeeded!\n");
260
261                         __libnet_state_changed_cb(event_cb->ProfileName, CONNECTION_PROFILE_STATE_DISCONNECTED);
262                         return;
263                 default:
264                         CONNECTION_LOG(CONNECTION_ERROR, "'Close connection' failed!! [%s]\n",
265                                                 __libnet_convert_cp_error_type_to_string(result));
266                 }
267
268                 break;
269         case NET_EVENT_NET_STATE_IND:
270                 CONNECTION_LOG(CONNECTION_INFO, "Got State changed IND\n");
271
272                 if (event_cb->Datalength != sizeof(net_state_type_t))
273                         return;
274
275                 net_state_type_t *profile_state = (net_state_type_t*)event_cb->Data;
276                 connection_profile_state_e cp_state = _profile_convert_to_cp_state(*profile_state);
277
278                 CONNECTION_LOG(CONNECTION_INFO,
279                                 "Profile State : %s, profile name : %s\n",
280                                 __libnet_convert_cp_state_to_string(cp_state),
281                                 event_cb->ProfileName);
282
283                 __libnet_state_changed_cb(event_cb->ProfileName, cp_state);
284
285                 break;
286         case NET_EVENT_WIFI_SCAN_IND:
287         case NET_EVENT_WIFI_SCAN_RSP:
288                 CONNECTION_LOG(CONNECTION_INFO, "Got wifi scan IND\n");
289                 break;
290         case NET_EVENT_WIFI_POWER_IND:
291         case NET_EVENT_WIFI_POWER_RSP:
292                 CONNECTION_LOG(CONNECTION_INFO, "Got wifi power IND\n");
293                 break;
294         case NET_EVENT_CELLULAR_SET_DEFAULT_RSP:
295                 result = __libnet_convert_to_cp_error_type(event_cb->Error);
296                 CONNECTION_LOG(CONNECTION_INFO, "Got set default profile RSP %d\n", result);
297                 __libnet_default_cb(result);
298                 break;
299         case NET_EVENT_WIFI_WPS_RSP:
300                 CONNECTION_LOG(CONNECTION_INFO, "Got wifi WPS RSP\n");
301                 /* fall through */
302         default :
303                 CONNECTION_LOG(CONNECTION_ERROR, "Error! Unknown Event\n\n");
304                 break;
305         }
306 }
307
308 int __libnet_get_connected_count(struct _profile_list_s *profile_list)
309 {
310         int count = 0;
311         int i = 0;
312
313         for (;i < profile_list->count;i++) {
314                 if (profile_list->profiles[i].ProfileState == NET_STATE_TYPE_ONLINE ||
315                     profile_list->profiles[i].ProfileState == NET_STATE_TYPE_READY)
316                         count++;
317         }
318
319         return count;
320 }
321
322 void __libnet_copy_connected_profile(net_profile_info_t **dest, struct _profile_list_s *source)
323 {
324         int i = 0;
325
326         for (;i < source->count;i++) {
327                 if (source->profiles[i].ProfileState == NET_STATE_TYPE_ONLINE ||
328                     source->profiles[i].ProfileState == NET_STATE_TYPE_READY) {
329                         memcpy(*dest, &source->profiles[i], sizeof(net_profile_info_t));
330                         (*dest)++;
331                 }
332         }
333 }
334
335 bool _connection_libnet_init(void)
336 {
337         int rv;
338
339         if (!libnet.registered) {
340                 rv = net_register_client_ext((net_event_cb_t)__libnet_evt_cb, NET_DEVICE_DEFAULT, NULL);
341                 if (rv != NET_ERR_NONE)
342                         return false;
343
344                 libnet.registered = true;
345
346                 if (profile_cb_table == NULL)
347                         profile_cb_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
348         }
349
350         return true;
351 }
352
353 bool _connection_libnet_deinit(void)
354 {
355         if (libnet.registered) {
356                 if (net_deregister_client_ext(NET_DEVICE_DEFAULT) != NET_ERR_NONE)
357                         return false;
358
359                 libnet.registered = false;
360
361                 if (profile_cb_table) {
362                         g_hash_table_destroy(profile_cb_table);
363                         profile_cb_table = NULL;
364                 }
365
366                 __libnet_clear_profile_list(&profile_iterator);
367
368                 if (prof_handle_list) {
369                         g_slist_free_full(prof_handle_list, g_free);
370                         prof_handle_list = NULL;
371                 }
372         }
373
374         return true;
375 }
376
377 bool _connection_libnet_check_profile_validity(connection_profile_h profile)
378 {
379         GSList *list;
380         int i = 0;
381
382         for (list = prof_handle_list; list; list = list->next)
383                 if (profile == list->data) return true;
384
385         for (;i < profile_iterator.count;i++)
386                 if (profile == &profile_iterator.profiles[i]) return true;
387
388         return false;
389 }
390
391 bool _connection_libnet_check_profile_cb_validity(connection_profile_h profile)
392 {
393         struct _profile_cb_s *cb_info;
394         net_profile_info_t *profile_info = profile;
395
396         if (profile == NULL)
397                 return false;
398
399         cb_info = g_hash_table_lookup(profile_cb_table, profile_info->ProfileName);
400         if (cb_info != NULL)
401                 return true;
402
403         return false;
404 }
405
406
407 bool _connection_libnet_get_wifi_state(connection_wifi_state_e *state)
408 {
409         net_wifi_state_t wlan_state;
410         net_profile_name_t profile_name;
411
412         if (net_get_wifi_state(&wlan_state, &profile_name) != NET_ERR_NONE) {
413                 CONNECTION_LOG(CONNECTION_ERROR, "Error!! net_get_wifi_state() failed.\n");
414                 return false;
415         }
416
417         switch (wlan_state) {
418         case WIFI_OFF:
419                 *state = CONNECTION_WIFI_STATE_DEACTIVATED;
420                 break;
421         case WIFI_ON:
422         case WIFI_CONNECTING:
423                 *state = CONNECTION_WIFI_STATE_DISCONNECTED;
424                 break;
425         case WIFI_CONNECTED:
426         case WIFI_DISCONNECTING:
427                 *state = CONNECTION_WIFI_STATE_CONNECTED;
428                 break;
429         default :
430                 CONNECTION_LOG(CONNECTION_ERROR, "Error!! Unknown state\n");
431                 return false;
432         }
433
434         return true;
435 }
436
437 bool _connection_libnet_get_ethernet_state(connection_ethernet_state_e* state)
438 {
439         struct _profile_list_s ethernet_profiles = {0, 0, NULL};
440         net_get_profile_list(NET_DEVICE_ETHERNET, &ethernet_profiles.profiles, &ethernet_profiles.count);
441
442         if (ethernet_profiles.count == 0) {
443                 *state = CONNECTION_ETHERNET_STATE_DEACTIVATED;
444                 return true;
445         }
446
447         switch (ethernet_profiles.profiles->ProfileState) {
448         case NET_STATE_TYPE_ONLINE:
449         case NET_STATE_TYPE_READY:
450                 *state = CONNECTION_ETHERNET_STATE_CONNECTED;
451                 break;
452         case NET_STATE_TYPE_IDLE:
453         case NET_STATE_TYPE_FAILURE:
454         case NET_STATE_TYPE_ASSOCIATION:
455         case NET_STATE_TYPE_CONFIGURATION:
456         case NET_STATE_TYPE_DISCONNECT:
457                 *state = CONNECTION_ETHERNET_STATE_DISCONNECTED;
458                 break;
459         default:
460                 return false;
461         }
462
463         __libnet_clear_profile_list(&ethernet_profiles);
464
465         return true;
466 }
467
468 bool _connection_libnet_get_bluetooth_state(connection_bt_state_e* state)
469 {
470         int i = 0;
471         struct _profile_list_s bluetooth_profiles = {0, 0, NULL};
472         net_get_profile_list(NET_DEVICE_BLUETOOTH, &bluetooth_profiles.profiles, &bluetooth_profiles.count);
473
474         if (bluetooth_profiles.count == 0) {
475                 *state = CONNECTION_BT_STATE_DEACTIVATED;
476                 return true;
477         }
478
479         for (; i < bluetooth_profiles.count; i++) {
480                 switch (bluetooth_profiles.profiles[i].ProfileState) {
481                 case NET_STATE_TYPE_ONLINE:
482                 case NET_STATE_TYPE_READY:
483                         *state = CONNECTION_BT_STATE_CONNECTED;
484                         goto done;
485                 case NET_STATE_TYPE_IDLE:
486                 case NET_STATE_TYPE_FAILURE:
487                 case NET_STATE_TYPE_ASSOCIATION:
488                 case NET_STATE_TYPE_CONFIGURATION:
489                 case NET_STATE_TYPE_DISCONNECT:
490                         *state = CONNECTION_BT_STATE_DISCONNECTED;
491                         break;
492                 default:
493                         __libnet_clear_profile_list(&bluetooth_profiles);
494                         return false;
495                 }
496         }
497
498 done:
499         __libnet_clear_profile_list(&bluetooth_profiles);
500
501         return true;
502 }
503
504 int _connection_libnet_get_profile_iterator(connection_iterator_type_e type, connection_profile_iterator_h* profile_iter_h)
505 {
506         int count = 0;
507         int rv1, rv2, rv3, rv4;
508         net_profile_info_t *profiles = NULL;
509
510         struct _profile_list_s wifi_profiles = {0, 0, NULL};
511         struct _profile_list_s cellular_profiles = {0, 0, NULL};
512         struct _profile_list_s ethernet_profiles = {0, 0, NULL};
513         struct _profile_list_s bluetooth_profiles = {0, 0, NULL};
514
515         __libnet_clear_profile_list(&profile_iterator);
516
517         rv1 = net_get_profile_list(NET_DEVICE_WIFI, &wifi_profiles.profiles, &wifi_profiles.count);
518         if (rv1 != NET_ERR_NO_SERVICE && rv1 != NET_ERR_NONE)
519                 return CONNECTION_ERROR_OPERATION_FAILED;
520
521         CONNECTION_LOG(CONNECTION_INFO, "Wifi profile count : %d\n", wifi_profiles.count);
522
523         rv2 = net_get_profile_list(NET_DEVICE_CELLULAR, &cellular_profiles.profiles, &cellular_profiles.count);
524         if (rv2 != NET_ERR_NO_SERVICE && rv2 != NET_ERR_NONE) {
525                 __libnet_clear_profile_list(&wifi_profiles);
526                 return CONNECTION_ERROR_OPERATION_FAILED;
527         }
528         CONNECTION_LOG(CONNECTION_INFO, "Cellular profile count : %d\n", cellular_profiles.count);
529
530         rv3 = net_get_profile_list(NET_DEVICE_ETHERNET, &ethernet_profiles.profiles, &ethernet_profiles.count);
531         if (rv3 != NET_ERR_NO_SERVICE && rv3 != NET_ERR_NONE) {
532                 __libnet_clear_profile_list(&wifi_profiles);
533                 __libnet_clear_profile_list(&cellular_profiles);
534                 return CONNECTION_ERROR_OPERATION_FAILED;
535         }
536         CONNECTION_LOG(CONNECTION_INFO, "Ethernet profile count : %d\n", ethernet_profiles.count);
537
538         rv4 = net_get_profile_list(NET_DEVICE_BLUETOOTH, &bluetooth_profiles.profiles, &bluetooth_profiles.count);
539         if (rv4 != NET_ERR_NO_SERVICE && rv4 != NET_ERR_NONE) {
540                 __libnet_clear_profile_list(&wifi_profiles);
541                 __libnet_clear_profile_list(&cellular_profiles);
542                 __libnet_clear_profile_list(&ethernet_profiles);
543                 return CONNECTION_ERROR_OPERATION_FAILED;
544         }
545         CONNECTION_LOG(CONNECTION_INFO, "Bluetooth profile count : %d\n", bluetooth_profiles.count);
546
547         *profile_iter_h = &profile_iterator;
548
549         switch (type) {
550         case CONNECTION_ITERATOR_TYPE_REGISTERED:
551                 count = wifi_profiles.count + cellular_profiles.count + ethernet_profiles.count + bluetooth_profiles.count;
552                 CONNECTION_LOG(CONNECTION_INFO, "Total profile count : %d\n", count);
553                 if (count == 0)
554                         return CONNECTION_ERROR_NONE;
555
556                 profiles = g_try_new0(net_profile_info_t, count);
557                 if (profiles == NULL) {
558                         __libnet_clear_profile_list(&wifi_profiles);
559                         __libnet_clear_profile_list(&cellular_profiles);
560                         __libnet_clear_profile_list(&ethernet_profiles);
561                         __libnet_clear_profile_list(&bluetooth_profiles);
562                         return CONNECTION_ERROR_OUT_OF_MEMORY;
563                 }
564
565                 profile_iterator.profiles = profiles;
566
567                 if (wifi_profiles.count > 0) {
568                         memcpy(profiles, wifi_profiles.profiles,
569                                         sizeof(net_profile_info_t) * wifi_profiles.count);
570                         profiles += wifi_profiles.count;
571                 }
572
573                 if (cellular_profiles.count > 0) {
574                         memcpy(profiles, cellular_profiles.profiles,
575                                         sizeof(net_profile_info_t) * cellular_profiles.count);
576                         profiles += cellular_profiles.count;
577                 }
578
579                 if (ethernet_profiles.count > 0) {
580                         memcpy(profiles, ethernet_profiles.profiles,
581                                         sizeof(net_profile_info_t) * ethernet_profiles.count);
582                         profiles += ethernet_profiles.count;
583                 }
584
585                 if (bluetooth_profiles.count > 0)
586                         memcpy(profiles, bluetooth_profiles.profiles,
587                                         sizeof(net_profile_info_t) * bluetooth_profiles.count);
588
589                 break;
590         case CONNECTION_ITERATOR_TYPE_CONNECTED:
591                 count = __libnet_get_connected_count(&wifi_profiles);
592                 count += __libnet_get_connected_count(&cellular_profiles);
593                 count += __libnet_get_connected_count(&ethernet_profiles);
594                 count += __libnet_get_connected_count(&bluetooth_profiles);
595                 CONNECTION_LOG(CONNECTION_INFO, "Total connected profile count : %d\n", count);
596                 if (count == 0)
597                         return CONNECTION_ERROR_NONE;
598
599                 profiles = g_try_new0(net_profile_info_t, count);
600                 if (profiles == NULL) {
601                         __libnet_clear_profile_list(&wifi_profiles);
602                         __libnet_clear_profile_list(&cellular_profiles);
603                         __libnet_clear_profile_list(&ethernet_profiles);
604                         __libnet_clear_profile_list(&bluetooth_profiles);
605                         return CONNECTION_ERROR_OUT_OF_MEMORY;
606                 }
607
608                 profile_iterator.profiles = profiles;
609
610                 if (wifi_profiles.count > 0)
611                         __libnet_copy_connected_profile(&profiles, &wifi_profiles);
612
613                 if (cellular_profiles.count > 0)
614                         __libnet_copy_connected_profile(&profiles, &cellular_profiles);
615
616                 if (ethernet_profiles.count > 0)
617                         __libnet_copy_connected_profile(&profiles, &ethernet_profiles);
618
619                 if (bluetooth_profiles.count > 0)
620                         __libnet_copy_connected_profile(&profiles, &bluetooth_profiles);
621
622                 break;
623         }
624
625         __libnet_clear_profile_list(&wifi_profiles);
626         __libnet_clear_profile_list(&cellular_profiles);
627         __libnet_clear_profile_list(&ethernet_profiles);
628         __libnet_clear_profile_list(&bluetooth_profiles);
629
630         profile_iterator.count = count;
631
632         return CONNECTION_ERROR_NONE;
633 }
634
635 int _connection_libnet_get_iterator_next(connection_profile_iterator_h profile_iter_h, connection_profile_h *profile)
636 {
637         if (profile_iter_h != &profile_iterator)
638                 return CONNECTION_ERROR_INVALID_PARAMETER;
639
640         if (profile_iterator.count <= profile_iterator.next)
641                 return CONNECTION_ERROR_ITERATOR_END;
642
643         *profile = &profile_iterator.profiles[profile_iterator.next];
644         profile_iterator.next++;
645
646         return CONNECTION_ERROR_NONE;
647 }
648
649 bool _connection_libnet_iterator_has_next(connection_profile_iterator_h profile_iter_h)
650 {
651         if (profile_iter_h != &profile_iterator)
652                 return false;
653
654         if (profile_iterator.count <= profile_iterator.next)
655                 return false;
656
657         return true;
658 }
659
660 int _connection_libnet_destroy_iterator(connection_profile_iterator_h profile_iter_h)
661 {
662         if (profile_iter_h != &profile_iterator)
663                 return CONNECTION_ERROR_INVALID_PARAMETER;
664
665         __libnet_clear_profile_list(&profile_iterator);
666
667         return CONNECTION_ERROR_NONE;
668 }
669
670 int _connection_libnet_get_current_profile(connection_profile_h *profile)
671 {
672         net_profile_info_t active_profile;
673         int rv;
674
675         rv = net_get_active_net_info(&active_profile);
676         if (rv == NET_ERR_NO_SERVICE)
677                 return CONNECTION_ERROR_NO_CONNECTION;
678         else if (rv != NET_ERR_NONE)
679                 return CONNECTION_ERROR_OPERATION_FAILED;
680
681         *profile = g_try_malloc0(sizeof(net_profile_info_t));
682         if (*profile == NULL)
683                 return CONNECTION_ERROR_OUT_OF_MEMORY;
684
685         memcpy(*profile, &active_profile, sizeof(net_profile_info_t));
686         prof_handle_list = g_slist_append(prof_handle_list, *profile);
687
688         return CONNECTION_ERROR_NONE;
689 }
690
691 int _connection_libnet_open_profile(connection_profile_h profile, connection_opened_cb callback, void* user_data)
692 {
693         if (!(_connection_libnet_check_profile_validity(profile))) {
694                 CONNECTION_LOG(CONNECTION_ERROR, "Wrong Parameter Passed\n");
695                 return CONNECTION_ERROR_INVALID_PARAMETER;
696         }
697
698         net_profile_info_t *profile_info = profile;
699
700         if (net_open_connection_with_profile(profile_info->ProfileName) != NET_ERR_NONE)
701                 return CONNECTION_ERROR_OPERATION_FAILED;
702
703         __libnet_set_opened_cb(callback, user_data);
704
705         return CONNECTION_ERROR_NONE;
706 }
707
708 int _connection_libnet_get_cellular_service_profile(connection_cellular_service_type_e type, connection_profile_h *profile)
709 {
710         int i = 0;
711         int j = 0;
712         int rv = NET_ERR_NONE;
713         net_service_type_t service_type = _connection_profile_convert_to_libnet_cellular_service_type(type);
714
715         struct _profile_list_s cellular_profiles = {0, 0, NULL};
716
717         rv = net_get_profile_list(NET_DEVICE_CELLULAR, &cellular_profiles.profiles, &cellular_profiles.count);
718         if (rv != NET_ERR_NONE)
719                 return CONNECTION_ERROR_OPERATION_FAILED;
720
721         for (;i < cellular_profiles.count;i++)
722                 if (cellular_profiles.profiles[i].ProfileInfo.Pdp.ServiceType == service_type)
723                         break;
724
725         if (i >= cellular_profiles.count)
726                 return CONNECTION_ERROR_OPERATION_FAILED;
727
728         *profile = g_try_malloc0(sizeof(net_profile_info_t));
729         if (*profile == NULL)
730                 return CONNECTION_ERROR_OUT_OF_MEMORY;
731
732         memcpy(*profile, &cellular_profiles.profiles[i], sizeof(net_profile_info_t));
733
734         if (cellular_profiles.profiles[i].ProfileInfo.Pdp.DefaultConn)
735                 goto done;
736
737         if (type != CONNECTION_CELLULAR_SERVICE_TYPE_INTERNET &&
738             type != CONNECTION_CELLULAR_SERVICE_TYPE_PREPAID_INTERNET)
739                 goto done;
740
741         for (;j < cellular_profiles.count;j++) {
742                 if (i == j)
743                         continue;
744
745                 if (cellular_profiles.profiles[j].ProfileInfo.Pdp.ServiceType != service_type)
746                         continue;
747
748                 if (cellular_profiles.profiles[j].ProfileInfo.Pdp.DefaultConn) {
749                         memcpy(*profile, &cellular_profiles.profiles[j], sizeof(net_profile_info_t));
750                         goto done;
751                 }
752         }
753
754 done:
755         prof_handle_list = g_slist_append(prof_handle_list, *profile);
756
757         return CONNECTION_ERROR_NONE;
758 }
759
760 int _connection_libnet_set_cellular_service_profile_sync(connection_cellular_service_type_e type, connection_profile_h profile)
761 {
762         if (!(_connection_libnet_check_profile_validity(profile))) {
763                 CONNECTION_LOG(CONNECTION_ERROR, "Wrong Parameter Passed\n");
764                 return CONNECTION_ERROR_INVALID_PARAMETER;
765         }
766
767         net_profile_info_t *profile_info = profile;
768         connection_cellular_service_type_e service_type;
769
770         service_type = _profile_convert_to_connection_cellular_service_type(profile_info->ProfileInfo.Pdp.ServiceType);
771
772         if (service_type != type)
773                 return CONNECTION_ERROR_INVALID_PARAMETER;
774
775         if (net_set_default_cellular_service_profile(profile_info->ProfileName) != NET_ERR_NONE)
776                 return CONNECTION_ERROR_OPERATION_FAILED;
777
778         return CONNECTION_ERROR_NONE;
779 }
780
781 int _connection_libnet_set_cellular_service_profile_async(connection_cellular_service_type_e type,
782                         connection_profile_h profile, connection_set_default_cb callback, void* user_data)
783 {
784         if (!(_connection_libnet_check_profile_validity(profile))) {
785                 CONNECTION_LOG(CONNECTION_ERROR, "Wrong Parameter Passed\n");
786                 return CONNECTION_ERROR_INVALID_PARAMETER;
787         }
788
789         net_profile_info_t *profile_info = profile;
790         connection_cellular_service_type_e service_type;
791
792         service_type = _profile_convert_to_connection_cellular_service_type(profile_info->ProfileInfo.Pdp.ServiceType);
793
794         if (service_type != type)
795                 return CONNECTION_ERROR_INVALID_PARAMETER;
796
797         if (net_set_default_cellular_service_profile_async(profile_info->ProfileName) != NET_ERR_NONE)
798                 return CONNECTION_ERROR_OPERATION_FAILED;
799
800         __libnet_set_default_cb(callback, user_data);
801
802         return CONNECTION_ERROR_NONE;
803 }
804
805 int _connection_libnet_close_profile(connection_profile_h profile, connection_closed_cb callback, void *user_data)
806 {
807         if (!(_connection_libnet_check_profile_validity(profile))) {
808                 CONNECTION_LOG(CONNECTION_ERROR, "Wrong Parameter Passed\n");
809                 return CONNECTION_ERROR_INVALID_PARAMETER;
810         }
811
812         net_profile_info_t *profile_info = profile;
813
814         if (net_close_connection(profile_info->ProfileName) != NET_ERR_NONE)
815                 return CONNECTION_ERROR_OPERATION_FAILED;
816
817         __libnet_set_closed_cb(callback, user_data);
818
819         return CONNECTION_ERROR_NONE;
820 }
821
822 int _connection_libnet_add_route(const char *interface_name, const char *host_address)
823 {
824         char *endstr = strrchr(host_address, '.');
825
826         if (endstr == NULL ||
827             strcmp(endstr, ".0") == 0 ||
828             strncmp(host_address, "0.", 2) == 0 ||
829             strstr(host_address, ".0.") != NULL ||
830             strstr(host_address, "255") != NULL) {
831                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid IP address Passed\n");
832                 return CONNECTION_ERROR_INVALID_PARAMETER;
833         }
834
835         if (net_add_route(host_address, interface_name) != NET_ERR_NONE)
836                 return CONNECTION_ERROR_OPERATION_FAILED;
837
838         return CONNECTION_ERROR_NONE;
839 }
840
841 void _connection_libnet_add_to_profile_list(connection_profile_h profile)
842 {
843         prof_handle_list = g_slist_append(prof_handle_list, profile);
844 }
845
846 void _connection_libnet_remove_from_profile_list(connection_profile_h profile)
847 {
848         prof_handle_list = g_slist_remove(prof_handle_list, profile);
849         g_free(profile);
850 }
851
852 bool _connection_libnet_add_to_profile_cb_list(connection_profile_h profile,
853                 connection_profile_state_changed_cb callback, void *user_data)
854 {
855         net_profile_info_t *profile_info = profile;
856         char *profile_name = g_strdup(profile_info->ProfileName);
857
858         struct _profile_cb_s *profile_cb_info = g_try_malloc0(sizeof(struct _profile_cb_s));
859         if (profile_cb_info == NULL) {
860                 g_free(profile_name);
861                 return false;
862         }
863
864         profile_cb_info->callback = callback;
865         profile_cb_info->user_data = user_data;
866
867         g_hash_table_insert(profile_cb_table, profile_name, profile_cb_info);
868
869         return true;
870 }
871
872 void _connection_libnet_remove_from_profile_cb_list(connection_profile_h profile)
873 {
874         net_profile_info_t *profile_info = profile;
875         g_hash_table_remove(profile_cb_table, profile_info->ProfileName);
876 }
877
878 int _connection_libnet_set_statistics(net_device_t device_type, net_statistics_type_e statistics_type)
879 {
880         if (net_set_statistics(device_type, statistics_type) != NET_ERR_NONE)
881                 return CONNECTION_ERROR_OPERATION_FAILED;
882
883         return CONNECTION_ERROR_NONE;
884 }
885
886 int _connection_libnet_get_statistics(net_statistics_type_e statistics_type, unsigned long long *size)
887 {
888         if (net_get_statistics(NET_DEVICE_WIFI, statistics_type, size) != NET_ERR_NONE)
889                         return CONNECTION_ERROR_OPERATION_FAILED;
890
891                 return CONNECTION_ERROR_NONE;
892 }
893