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