5 * Copyright (C) 2007-2009 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30 static DBusConnection *connection = NULL;
32 static GSequence *service_list = NULL;
33 static GHashTable *service_hash = NULL;
35 struct connman_service {
39 enum connman_service_type type;
40 enum connman_service_mode mode;
41 enum connman_service_security security;
42 enum connman_service_state state;
43 enum connman_service_error error;
44 connman_uint8_t strength;
45 connman_bool_t favorite;
46 connman_bool_t hidden;
47 connman_bool_t ignore;
53 struct connman_ipconfig *ipconfig;
54 struct connman_device *device;
55 struct connman_network *network;
60 static void append_path(gpointer value, gpointer user_data)
62 struct connman_service *service = value;
63 DBusMessageIter *iter = user_data;
65 if (service->path == NULL)
68 dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
72 void __connman_service_list(DBusMessageIter *iter)
76 g_sequence_foreach(service_list, append_path, iter);
81 struct connman_service *service;
84 static void compare_path(gpointer value, gpointer user_data)
86 struct connman_service *service = value;
87 struct find_data *data = user_data;
89 if (data->service != NULL)
92 if (g_strcmp0(service->path, data->path) == 0)
93 data->service = service;
96 static struct connman_service *find_service(const char *path)
98 struct find_data data = { .path = path, .service = NULL };
100 DBG("path %s", path);
102 g_sequence_foreach(service_list, compare_path, &data);
107 static const char *type2string(enum connman_service_type type)
110 case CONNMAN_SERVICE_TYPE_UNKNOWN:
112 case CONNMAN_SERVICE_TYPE_ETHERNET:
114 case CONNMAN_SERVICE_TYPE_WIFI:
116 case CONNMAN_SERVICE_TYPE_WIMAX:
118 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
120 case CONNMAN_SERVICE_TYPE_CELLULAR:
127 static const char *mode2string(enum connman_service_mode mode)
130 case CONNMAN_SERVICE_MODE_UNKNOWN:
132 case CONNMAN_SERVICE_MODE_MANAGED:
134 case CONNMAN_SERVICE_MODE_ADHOC:
141 static const char *security2string(enum connman_service_security security)
144 case CONNMAN_SERVICE_SECURITY_UNKNOWN:
146 case CONNMAN_SERVICE_SECURITY_NONE:
148 case CONNMAN_SERVICE_SECURITY_WEP:
150 case CONNMAN_SERVICE_SECURITY_WPA:
152 case CONNMAN_SERVICE_SECURITY_RSN:
159 static const char *state2string(enum connman_service_state state)
162 case CONNMAN_SERVICE_STATE_UNKNOWN:
164 case CONNMAN_SERVICE_STATE_IDLE:
166 case CONNMAN_SERVICE_STATE_CARRIER:
168 case CONNMAN_SERVICE_STATE_ASSOCIATION:
169 return "association";
170 case CONNMAN_SERVICE_STATE_CONFIGURATION:
171 return "configuration";
172 case CONNMAN_SERVICE_STATE_READY:
174 case CONNMAN_SERVICE_STATE_DISCONNECT:
176 case CONNMAN_SERVICE_STATE_FAILURE:
183 static const char *error2string(enum connman_service_error error)
186 case CONNMAN_SERVICE_ERROR_UNKNOWN:
188 case CONNMAN_SERVICE_ERROR_DHCP_FAILED:
189 return "dhcp-failed";
190 case CONNMAN_SERVICE_ERROR_PIN_MISSING:
191 return "pin-missing";
197 static enum connman_service_error string2error(const char *error)
199 if (g_strcmp0(error, "dhcp-failed") == 0)
200 return CONNMAN_SERVICE_ERROR_DHCP_FAILED;
201 else if (g_strcmp0(error, "pin-missing") == 0)
202 return CONNMAN_SERVICE_ERROR_PIN_MISSING;
204 return CONNMAN_SERVICE_ERROR_UNKNOWN;
207 static void state_changed(struct connman_service *service)
210 DBusMessageIter entry, value;
211 const char *str, *key = "State";
213 if (service->path == NULL)
216 str = state2string(service->state);
220 signal = dbus_message_new_signal(service->path,
221 CONNMAN_SERVICE_INTERFACE, "PropertyChanged");
225 dbus_message_iter_init_append(signal, &entry);
227 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
229 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
230 DBUS_TYPE_STRING_AS_STRING, &value);
231 dbus_message_iter_append_basic(&value, DBUS_TYPE_STRING, &str);
232 dbus_message_iter_close_container(&entry, &value);
234 g_dbus_send_message(connection, signal);
237 static void strength_changed(struct connman_service *service)
240 DBusMessageIter entry, value;
241 const char *key = "Strength";
243 if (service->path == NULL)
246 if (service->strength == 0)
249 signal = dbus_message_new_signal(service->path,
250 CONNMAN_SERVICE_INTERFACE, "PropertyChanged");
254 dbus_message_iter_init_append(signal, &entry);
256 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
258 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
259 DBUS_TYPE_BYTE_AS_STRING, &value);
260 dbus_message_iter_append_basic(&value, DBUS_TYPE_BYTE,
262 dbus_message_iter_close_container(&entry, &value);
264 g_dbus_send_message(connection, signal);
267 static DBusMessage *get_properties(DBusConnection *conn,
268 DBusMessage *msg, void *user_data)
270 struct connman_service *service = user_data;
272 DBusMessageIter array, dict;
275 DBG("service %p", service);
277 reply = dbus_message_new_method_return(msg);
281 dbus_message_iter_init_append(reply, &array);
283 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
284 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
285 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
286 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
288 str = type2string(service->type);
290 connman_dbus_dict_append_variant(&dict, "Type",
291 DBUS_TYPE_STRING, &str);
293 str = mode2string(service->mode);
295 connman_dbus_dict_append_variant(&dict, "Mode",
296 DBUS_TYPE_STRING, &str);
298 str = security2string(service->security);
300 connman_dbus_dict_append_variant(&dict, "Security",
301 DBUS_TYPE_STRING, &str);
303 str = state2string(service->state);
305 connman_dbus_dict_append_variant(&dict, "State",
306 DBUS_TYPE_STRING, &str);
308 str = error2string(service->error);
310 connman_dbus_dict_append_variant(&dict, "Error",
311 DBUS_TYPE_STRING, &str);
313 if (service->strength > 0)
314 connman_dbus_dict_append_variant(&dict, "Strength",
315 DBUS_TYPE_BYTE, &service->strength);
317 connman_dbus_dict_append_variant(&dict, "Favorite",
318 DBUS_TYPE_BOOLEAN, &service->favorite);
320 if (service->name != NULL)
321 connman_dbus_dict_append_variant(&dict, "Name",
322 DBUS_TYPE_STRING, &service->name);
324 if (service->passphrase != NULL &&
325 __connman_security_check_privilege(msg,
326 CONNMAN_SECURITY_PRIVILEGE_SECRET) == 0)
327 connman_dbus_dict_append_variant(&dict, "Passphrase",
328 DBUS_TYPE_STRING, &service->passphrase);
330 __connman_ipconfig_append_ipv4(service->ipconfig, &dict, "IPv4.");
332 dbus_message_iter_close_container(&array, &dict);
337 static DBusMessage *set_property(DBusConnection *conn,
338 DBusMessage *msg, void *user_data)
340 struct connman_service *service = user_data;
341 DBusMessageIter iter, value;
345 DBG("service %p", service);
347 if (dbus_message_iter_init(msg, &iter) == FALSE)
348 return __connman_error_invalid_arguments(msg);
350 dbus_message_iter_get_basic(&iter, &name);
351 dbus_message_iter_next(&iter);
352 dbus_message_iter_recurse(&iter, &value);
354 if (__connman_security_check_privilege(msg,
355 CONNMAN_SECURITY_PRIVILEGE_MODIFY) < 0)
356 return __connman_error_permission_denied(msg);
358 type = dbus_message_iter_get_arg_type(&value);
360 if (g_str_equal(name, "Passphrase") == TRUE) {
361 const char *passphrase;
363 if (type != DBUS_TYPE_STRING)
364 return __connman_error_invalid_arguments(msg);
366 if (__connman_security_check_privilege(msg,
367 CONNMAN_SECURITY_PRIVILEGE_SECRET) < 0)
368 return __connman_error_permission_denied(msg);
370 dbus_message_iter_get_basic(&value, &passphrase);
372 g_free(service->passphrase);
373 service->passphrase = g_strdup(passphrase);
375 if (service->network != NULL)
376 connman_network_set_string(service->network,
377 "WiFi.Passphrase", service->passphrase);
379 __connman_storage_save_service(service);
380 } else if (g_str_has_prefix(name, "IPv4.") == TRUE) {
383 err = __connman_ipconfig_set_ipv4(service->ipconfig,
386 return __connman_error_failed(msg, -err);
388 return __connman_error_invalid_property(msg);
390 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
393 static DBusMessage *clear_property(DBusConnection *conn,
394 DBusMessage *msg, void *user_data)
396 struct connman_service *service = user_data;
399 DBG("service %p", service);
401 dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name,
404 if (__connman_security_check_privilege(msg,
405 CONNMAN_SECURITY_PRIVILEGE_MODIFY) < 0)
406 return __connman_error_permission_denied(msg);
408 if (g_str_equal(name, "Error") == TRUE) {
409 service->state = CONNMAN_SERVICE_STATE_IDLE;
410 service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
411 state_changed(service);
413 g_get_current_time(&service->modified);
414 __connman_storage_save_service(service);
416 return __connman_error_invalid_property(msg);
418 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
421 static connman_bool_t is_connecting(struct connman_service *service)
423 switch (service->state) {
424 case CONNMAN_SERVICE_STATE_UNKNOWN:
425 case CONNMAN_SERVICE_STATE_IDLE:
426 case CONNMAN_SERVICE_STATE_CARRIER:
427 case CONNMAN_SERVICE_STATE_FAILURE:
428 case CONNMAN_SERVICE_STATE_DISCONNECT:
429 case CONNMAN_SERVICE_STATE_READY:
431 case CONNMAN_SERVICE_STATE_ASSOCIATION:
432 case CONNMAN_SERVICE_STATE_CONFIGURATION:
439 static struct connman_service *find_pending_service(void)
441 struct connman_service *service;
444 iter = g_sequence_get_begin_iter(service_list);
446 while (g_sequence_iter_is_end(iter) == FALSE) {
447 service = g_sequence_get(iter);
448 if (service->pending != NULL)
451 iter = g_sequence_iter_next(iter);
457 static connman_bool_t is_ignore(struct connman_service *service)
459 if (service->ignore == TRUE)
462 if (service->state == CONNMAN_SERVICE_STATE_FAILURE)
468 static void __connman_service_auto_connect(void)
470 struct connman_service *service;
475 service = find_pending_service();
479 iter = g_sequence_get_begin_iter(service_list);
480 if (g_sequence_iter_is_end(iter) == TRUE)
483 service = g_sequence_get(iter);
485 while (is_ignore(service) == TRUE) {
486 iter = g_sequence_iter_next(iter);
487 if (g_sequence_iter_is_end(iter))
489 service = g_sequence_get(iter);
492 if (service->favorite == FALSE)
495 if (service->state == CONNMAN_SERVICE_STATE_READY)
498 if (is_connecting(service) == TRUE)
501 if (service->state == CONNMAN_SERVICE_STATE_IDLE)
502 __connman_service_connect(service);
505 static gboolean connect_timeout(gpointer user_data)
507 struct connman_service *service = user_data;
508 connman_bool_t auto_connect = FALSE;
510 DBG("service %p", service);
512 service->timeout = 0;
514 if (service->network != NULL) {
515 connman_bool_t connected;
517 connected = connman_network_get_connected(service->network);
518 if (connected == TRUE) {
519 __connman_service_indicate_state(service,
520 CONNMAN_SERVICE_STATE_READY);
524 __connman_network_disconnect(service->network);
525 } else if (service->device != NULL) {
526 connman_bool_t disconnected;
528 disconnected = connman_device_get_disconnected(service->device);
529 if (disconnected == FALSE) {
530 __connman_service_indicate_state(service,
531 CONNMAN_SERVICE_STATE_READY);
535 __connman_device_disconnect(service->device);
538 if (service->pending != NULL) {
541 reply = __connman_error_operation_timeout(service->pending);
543 g_dbus_send_message(connection, reply);
545 dbus_message_unref(service->pending);
546 service->pending = NULL;
550 __connman_service_indicate_state(service,
551 CONNMAN_SERVICE_STATE_FAILURE);
553 if (auto_connect == TRUE)
554 __connman_service_auto_connect();
559 static DBusMessage *connect_service(DBusConnection *conn,
560 DBusMessage *msg, void *user_data)
562 struct connman_service *service = user_data;
565 DBG("service %p", service);
567 if (service->pending != NULL)
568 return __connman_error_in_progress(msg);
570 service->ignore = FALSE;
572 service->pending = dbus_message_ref(msg);
574 err = __connman_service_connect(service);
576 if (err != -EINPROGRESS) {
577 dbus_message_unref(service->pending);
578 service->pending = NULL;
580 return __connman_error_failed(msg, -err);
586 dbus_message_unref(service->pending);
587 service->pending = NULL;
589 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
592 static DBusMessage *disconnect_service(DBusConnection *conn,
593 DBusMessage *msg, void *user_data)
595 struct connman_service *service = user_data;
598 DBG("service %p", service);
600 if (service->pending != NULL) {
603 reply = __connman_error_operation_aborted(service->pending);
605 g_dbus_send_message(conn, reply);
607 dbus_message_unref(service->pending);
608 service->pending = NULL;
610 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
613 service->ignore = TRUE;
615 err = __connman_service_disconnect(service);
617 if (err != -EINPROGRESS)
618 return __connman_error_failed(msg, -err);
623 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
626 static DBusMessage *remove_service(DBusConnection *conn,
627 DBusMessage *msg, void *user_data)
629 struct connman_service *service = user_data;
631 DBG("service %p", service);
633 if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET)
634 return __connman_error_not_supported(msg);
636 if (service->favorite == FALSE)
637 return __connman_error_not_supported(msg);
639 if (service->network != NULL)
640 __connman_network_disconnect(service->network);
642 g_free(service->passphrase);
643 service->passphrase = NULL;
645 connman_service_set_favorite(service, FALSE);
646 __connman_storage_save_service(service);
648 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
651 static DBusMessage *move_before(DBusConnection *conn,
652 DBusMessage *msg, void *user_data)
654 struct connman_service *service = user_data;
655 struct connman_service *target;
657 GSequenceIter *src, *dst;
659 DBG("service %p", service);
661 dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
664 if (service->favorite == FALSE)
665 return __connman_error_not_supported(msg);
667 target = find_service(path);
668 if (target == NULL || target->favorite == FALSE || target == service)
669 return __connman_error_invalid_service(msg);
671 DBG("target %s", target->identifier);
673 g_get_current_time(&service->modified);
674 __connman_storage_save_service(service);
676 src = g_hash_table_lookup(service_hash, service->identifier);
677 dst = g_hash_table_lookup(service_hash, target->identifier);
679 g_sequence_move(src, dst);
681 __connman_profile_changed();
683 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
686 static DBusMessage *move_after(DBusConnection *conn,
687 DBusMessage *msg, void *user_data)
689 struct connman_service *service = user_data;
690 struct connman_service *target;
693 DBG("service %p", service);
695 dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
698 if (service->favorite == FALSE)
699 return __connman_error_not_supported(msg);
701 target = find_service(path);
702 if (target == NULL || target->favorite == FALSE || target == service)
703 return __connman_error_invalid_service(msg);
705 DBG("target %s", target->identifier);
707 g_get_current_time(&service->modified);
708 __connman_storage_save_service(service);
710 return __connman_error_not_implemented(msg);
713 static GDBusMethodTable service_methods[] = {
714 { "GetProperties", "", "a{sv}", get_properties },
715 { "SetProperty", "sv", "", set_property },
716 { "ClearProperty", "s", "", clear_property },
717 { "Connect", "", "", connect_service,
718 G_DBUS_METHOD_FLAG_ASYNC },
719 { "Disconnect", "", "", disconnect_service },
720 { "Remove", "", "", remove_service },
721 { "MoveBefore", "o", "", move_before },
722 { "MoveAfter", "o", "", move_after },
726 static GDBusSignalTable service_signals[] = {
727 { "PropertyChanged", "sv" },
731 static void service_free(gpointer user_data)
733 struct connman_service *service = user_data;
734 char *path = service->path;
736 DBG("service %p", service);
738 g_hash_table_remove(service_hash, service->identifier);
740 if (service->timeout > 0) {
741 g_source_remove(service->timeout);
742 service->timeout = 0;
745 if (service->pending != NULL) {
746 dbus_message_unref(service->pending);
747 service->pending = NULL;
750 service->path = NULL;
753 __connman_profile_changed();
755 g_dbus_unregister_interface(connection, path,
756 CONNMAN_SERVICE_INTERFACE);
760 if (service->network != NULL)
761 connman_network_unref(service->network);
763 connman_ipconfig_unref(service->ipconfig);
765 g_free(service->profile);
766 g_free(service->name);
767 g_free(service->passphrase);
768 g_free(service->identifier);
773 * __connman_service_put:
774 * @service: service structure
776 * Release service if no longer needed
778 void __connman_service_put(struct connman_service *service)
780 DBG("service %p", service);
782 if (g_atomic_int_dec_and_test(&service->refcount) == TRUE) {
785 iter = g_hash_table_lookup(service_hash, service->identifier);
787 g_sequence_remove(iter);
789 service_free(service);
793 static void __connman_service_initialize(struct connman_service *service)
795 DBG("service %p", service);
797 service->refcount = 1;
799 service->type = CONNMAN_SERVICE_TYPE_UNKNOWN;
800 service->mode = CONNMAN_SERVICE_MODE_UNKNOWN;
801 service->security = CONNMAN_SERVICE_SECURITY_UNKNOWN;
802 service->state = CONNMAN_SERVICE_STATE_UNKNOWN;
804 service->favorite = FALSE;
805 service->hidden = FALSE;
807 service->ignore = FALSE;
813 * connman_service_create:
815 * Allocate a new service.
817 * Returns: a newly-allocated #connman_service structure
819 struct connman_service *connman_service_create(void)
821 struct connman_service *service;
823 service = g_try_new0(struct connman_service, 1);
827 DBG("service %p", service);
829 __connman_service_initialize(service);
831 service->ipconfig = connman_ipconfig_create();
832 if (service->ipconfig == NULL) {
837 connman_ipconfig_set_method(service->ipconfig,
838 CONNMAN_IPCONFIG_METHOD_DHCP);
844 * connman_service_ref:
845 * @service: service structure
847 * Increase reference counter of service
849 struct connman_service *connman_service_ref(struct connman_service *service)
851 g_atomic_int_inc(&service->refcount);
857 * connman_service_unref:
858 * @service: service structure
860 * Decrease reference counter of service
862 void connman_service_unref(struct connman_service *service)
864 __connman_service_put(service);
867 static gint service_compare(gconstpointer a, gconstpointer b,
870 struct connman_service *service_a = (void *) a;
871 struct connman_service *service_b = (void *) b;
873 if (service_a->state != service_b->state) {
874 if (service_a->state == CONNMAN_SERVICE_STATE_READY)
876 if (service_b->state == CONNMAN_SERVICE_STATE_READY)
880 if (service_a->order > service_b->order)
883 if (service_a->order < service_b->order)
886 if (service_a->favorite == TRUE && service_b->favorite == FALSE)
889 if (service_a->favorite == FALSE && service_b->favorite == TRUE)
892 return (gint) service_b->strength - (gint) service_a->strength;
896 * connman_service_set_favorite:
897 * @service: service structure
898 * @favorite: favorite value
900 * Change the favorite setting of service
902 int connman_service_set_favorite(struct connman_service *service,
903 connman_bool_t favorite)
907 iter = g_hash_table_lookup(service_hash, service->identifier);
911 if (service->favorite == favorite)
914 service->favorite = favorite;
916 g_sequence_sort_changed(iter, service_compare, NULL);
918 __connman_profile_changed();
923 int __connman_service_set_carrier(struct connman_service *service,
924 connman_bool_t carrier)
926 DBG("service %p carrier %d", service, carrier);
931 switch (service->type) {
932 case CONNMAN_SERVICE_TYPE_UNKNOWN:
933 case CONNMAN_SERVICE_TYPE_WIFI:
934 case CONNMAN_SERVICE_TYPE_WIMAX:
935 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
936 case CONNMAN_SERVICE_TYPE_CELLULAR:
938 case CONNMAN_SERVICE_TYPE_ETHERNET:
942 if (carrier == FALSE) {
943 service->state = CONNMAN_SERVICE_STATE_DISCONNECT;
944 state_changed(service);
946 service->state = CONNMAN_SERVICE_STATE_IDLE;
947 state_changed(service);
949 service->state = CONNMAN_SERVICE_STATE_CARRIER;
950 state_changed(service);
953 return connman_service_set_favorite(service, carrier);
956 int __connman_service_indicate_state(struct connman_service *service,
957 enum connman_service_state state)
961 DBG("service %p state %d", service, state);
966 if (state == CONNMAN_SERVICE_STATE_CARRIER)
967 return __connman_service_set_carrier(service, TRUE);
969 if (service->state == state)
972 if (service->state == CONNMAN_SERVICE_STATE_IDLE &&
973 state == CONNMAN_SERVICE_STATE_DISCONNECT)
976 if (state == CONNMAN_SERVICE_STATE_IDLE &&
977 service->state != CONNMAN_SERVICE_STATE_DISCONNECT) {
978 service->state = CONNMAN_SERVICE_STATE_DISCONNECT;
979 state_changed(service);
982 service->state = state;
983 state_changed(service);
985 if (state == CONNMAN_SERVICE_STATE_READY) {
986 connman_service_set_favorite(service, TRUE);
988 if (service->timeout > 0) {
989 g_source_remove(service->timeout);
990 service->timeout = 0;
993 if (service->pending != NULL) {
994 g_dbus_send_reply(connection, service->pending,
997 dbus_message_unref(service->pending);
998 service->pending = NULL;
1001 g_get_current_time(&service->modified);
1002 __connman_storage_save_service(service);
1005 if (state == CONNMAN_SERVICE_STATE_FAILURE) {
1006 if (service->timeout > 0) {
1007 g_source_remove(service->timeout);
1008 service->timeout = 0;
1011 if (service->pending != NULL) {
1014 reply = __connman_error_failed(service->pending, EIO);
1016 g_dbus_send_message(connection, reply);
1018 dbus_message_unref(service->pending);
1019 service->pending = NULL;
1022 g_get_current_time(&service->modified);
1023 __connman_storage_save_service(service);
1025 service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
1027 iter = g_hash_table_lookup(service_hash, service->identifier);
1029 g_sequence_sort_changed(iter, service_compare, NULL);
1031 __connman_profile_changed();
1036 int __connman_service_indicate_error(struct connman_service *service,
1037 enum connman_service_error error)
1039 DBG("service %p error %d", service, error);
1041 if (service == NULL)
1044 service->error = error;
1046 return __connman_service_indicate_state(service,
1047 CONNMAN_SERVICE_STATE_FAILURE);
1050 int __connman_service_indicate_default(struct connman_service *service)
1052 DBG("service %p", service);
1057 int __connman_service_connect(struct connman_service *service)
1061 DBG("service %p", service);
1063 if (service->state == CONNMAN_SERVICE_STATE_READY)
1066 if (service->network != NULL) {
1067 if (service->hidden == TRUE)
1070 connman_network_set_string(service->network,
1071 "WiFi.Passphrase", service->passphrase);
1073 err = __connman_network_connect(service->network);
1074 } else if (service->device != NULL) {
1075 if (service->favorite == FALSE)
1078 err = __connman_device_connect(service->device);
1083 if (err != -EINPROGRESS)
1086 service->timeout = g_timeout_add_seconds(45,
1087 connect_timeout, service);
1089 return -EINPROGRESS;
1095 int __connman_service_disconnect(struct connman_service *service)
1099 DBG("service %p", service);
1101 if (service->network != NULL) {
1102 err = __connman_network_disconnect(service->network);
1103 } else if (service->device != NULL) {
1104 if (service->favorite == FALSE)
1106 err = __connman_device_disconnect(service->device);
1111 if (err != -EINPROGRESS)
1114 return -EINPROGRESS;
1121 * __connman_service_lookup:
1122 * @identifier: service identifier
1124 * Look up a service by identifier (reference count will not be increased)
1126 static struct connman_service *__connman_service_lookup(const char *identifier)
1128 GSequenceIter *iter;
1130 iter = g_hash_table_lookup(service_hash, identifier);
1132 return g_sequence_get(iter);
1138 * __connman_service_get:
1139 * @identifier: service identifier
1141 * Look up a service by identifier or create a new one if not found
1143 static struct connman_service *__connman_service_get(const char *identifier)
1145 struct connman_service *service;
1146 GSequenceIter *iter;
1148 iter = g_hash_table_lookup(service_hash, identifier);
1150 service = g_sequence_get(iter);
1151 if (service != NULL)
1152 g_atomic_int_inc(&service->refcount);
1156 service = connman_service_create();
1157 if (service == NULL)
1160 DBG("service %p", service);
1162 service->identifier = g_strdup(identifier);
1164 service->profile = g_strdup(__connman_profile_active_ident());
1166 __connman_storage_load_service(service);
1168 iter = g_sequence_insert_sorted(service_list, service,
1169 service_compare, NULL);
1171 g_hash_table_insert(service_hash, service->identifier, iter);
1176 static int service_register(struct connman_service *service)
1178 const char *path = __connman_profile_active_path();
1179 GSequenceIter *iter;
1181 DBG("service %p", service);
1183 if (service->path != NULL)
1186 service->path = g_strdup_printf("%s/%s", path, service->identifier);
1188 DBG("path %s", service->path);
1190 g_dbus_register_interface(connection, service->path,
1191 CONNMAN_SERVICE_INTERFACE,
1192 service_methods, service_signals,
1193 NULL, service, NULL);
1195 __connman_storage_load_service(service);
1197 iter = g_hash_table_lookup(service_hash, service->identifier);
1199 g_sequence_sort_changed(iter, service_compare, NULL);
1201 __connman_profile_changed();
1207 * connman_service_lookup_from_device:
1208 * @device: device structure
1210 * Look up a service by device (reference count will not be increased)
1212 struct connman_service *__connman_service_lookup_from_device(struct connman_device *device)
1214 struct connman_service *service;
1218 ident = __connman_device_get_ident(device);
1222 name = g_strdup_printf("%s_%s",
1223 __connman_device_get_type(device), ident);
1225 service = __connman_service_lookup(name);
1232 static enum connman_service_type convert_device_type(struct connman_device *device)
1234 enum connman_device_type type = connman_device_get_type(device);
1237 case CONNMAN_DEVICE_TYPE_UNKNOWN:
1238 case CONNMAN_DEVICE_TYPE_VENDOR:
1239 case CONNMAN_DEVICE_TYPE_WIFI:
1240 case CONNMAN_DEVICE_TYPE_WIMAX:
1241 case CONNMAN_DEVICE_TYPE_BLUETOOTH:
1242 case CONNMAN_DEVICE_TYPE_GPS:
1243 case CONNMAN_DEVICE_TYPE_MBM:
1244 case CONNMAN_DEVICE_TYPE_HSO:
1245 case CONNMAN_DEVICE_TYPE_NOZOMI:
1246 case CONNMAN_DEVICE_TYPE_HUAWEI:
1247 case CONNMAN_DEVICE_TYPE_NOVATEL:
1249 case CONNMAN_DEVICE_TYPE_ETHERNET:
1250 return CONNMAN_SERVICE_TYPE_ETHERNET;
1253 return CONNMAN_SERVICE_TYPE_UNKNOWN;
1257 * connman_service_create_from_device:
1258 * @device: device structure
1260 * Look up service by device and if not found, create one
1262 struct connman_service *__connman_service_create_from_device(struct connman_device *device)
1264 struct connman_service *service;
1268 ident = __connman_device_get_ident(device);
1272 name = g_strdup_printf("%s_%s",
1273 __connman_device_get_type(device), ident);
1275 service = __connman_service_get(name);
1276 if (service == NULL)
1279 if (service->path != NULL) {
1280 __connman_service_put(service);
1285 service->type = convert_device_type(device);
1287 service->device = device;
1289 service_register(service);
1291 if (service->favorite == TRUE)
1292 __connman_service_auto_connect();
1301 * connman_service_lookup_from_network:
1302 * @network: network structure
1304 * Look up a service by network (reference count will not be increased)
1306 struct connman_service *__connman_service_lookup_from_network(struct connman_network *network)
1308 struct connman_service *service;
1309 const char *ident, *group;
1312 ident = __connman_network_get_ident(network);
1316 group = connman_network_get_group(network);
1320 name = g_strdup_printf("%s_%s_%s",
1321 __connman_network_get_type(network), ident, group);
1323 service = __connman_service_lookup(name);
1330 unsigned int __connman_service_get_order(struct connman_service *service)
1332 if (service == NULL)
1335 return service->order;
1338 static enum connman_service_type convert_network_type(struct connman_network *network)
1340 enum connman_network_type type = connman_network_get_type(network);
1343 case CONNMAN_NETWORK_TYPE_UNKNOWN:
1344 case CONNMAN_NETWORK_TYPE_VENDOR:
1345 case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
1346 case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
1347 case CONNMAN_NETWORK_TYPE_HSO:
1349 case CONNMAN_NETWORK_TYPE_WIFI:
1350 return CONNMAN_SERVICE_TYPE_WIFI;
1351 case CONNMAN_NETWORK_TYPE_WIMAX:
1352 return CONNMAN_SERVICE_TYPE_WIMAX;
1355 return CONNMAN_SERVICE_TYPE_UNKNOWN;
1358 static enum connman_service_mode convert_wifi_mode(const char *mode)
1361 return CONNMAN_SERVICE_MODE_UNKNOWN;
1362 else if (g_str_equal(mode, "managed") == TRUE)
1363 return CONNMAN_SERVICE_MODE_MANAGED;
1364 else if (g_str_equal(mode, "adhoc") == TRUE)
1365 return CONNMAN_SERVICE_MODE_ADHOC;
1367 return CONNMAN_SERVICE_MODE_UNKNOWN;
1370 static enum connman_service_mode convert_wifi_security(const char *security)
1372 if (security == NULL)
1373 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
1374 else if (g_str_equal(security, "none") == TRUE)
1375 return CONNMAN_SERVICE_SECURITY_NONE;
1376 else if (g_str_equal(security, "wep") == TRUE)
1377 return CONNMAN_SERVICE_SECURITY_WEP;
1378 else if (g_str_equal(security, "wpa") == TRUE)
1379 return CONNMAN_SERVICE_SECURITY_WPA;
1380 else if (g_str_equal(security, "rsn") == TRUE)
1381 return CONNMAN_SERVICE_SECURITY_RSN;
1383 return CONNMAN_SERVICE_SECURITY_UNKNOWN;
1386 static void update_from_network(struct connman_service *service,
1387 struct connman_network *network)
1389 connman_uint8_t strength = service->strength;
1390 GSequenceIter *iter;
1393 if (service->state == CONNMAN_SERVICE_STATE_READY)
1396 if (is_connecting(service) == TRUE)
1399 str = connman_network_get_string(network, "Name");
1401 g_free(service->name);
1402 service->name = g_strdup(str);
1403 service->hidden = FALSE;
1405 g_free(service->name);
1406 service->name = NULL;
1407 service->hidden = TRUE;
1410 service->strength = connman_network_get_uint8(network, "Strength");
1412 str = connman_network_get_string(network, "WiFi.Mode");
1413 service->mode = convert_wifi_mode(str);
1415 str = connman_network_get_string(network, "WiFi.Security");
1416 service->security = convert_wifi_security(str);
1418 if (service->strength > strength && service->network != NULL) {
1419 connman_network_unref(service->network);
1420 service->network = NULL;
1422 strength_changed(service);
1425 if (service->network == NULL) {
1426 service->network = connman_network_ref(network);
1428 str = connman_network_get_string(network, "WiFi.Passphrase");
1430 g_free(service->passphrase);
1431 service->passphrase = g_strdup(str);
1435 iter = g_hash_table_lookup(service_hash, service->identifier);
1437 g_sequence_sort_changed(iter, service_compare, NULL);
1441 * connman_service_create_from_network:
1442 * @network: network structure
1444 * Look up service by network and if not found, create one
1446 struct connman_service *__connman_service_create_from_network(struct connman_network *network)
1448 struct connman_service *service;
1449 const char *ident, *group;
1452 service = __connman_service_lookup_from_network(network);
1453 if (service != NULL) {
1454 update_from_network(service, network);
1458 ident = __connman_network_get_ident(network);
1462 group = connman_network_get_group(network);
1466 name = g_strdup_printf("%s_%s_%s",
1467 __connman_network_get_type(network), ident, group);
1469 service = __connman_service_get(name);
1470 if (service == NULL)
1473 if (service->path != NULL) {
1474 update_from_network(service, network);
1476 __connman_profile_changed();
1478 __connman_service_put(service);
1483 service->type = convert_network_type(network);
1485 service->state = CONNMAN_SERVICE_STATE_IDLE;
1487 update_from_network(service, network);
1489 service_register(service);
1491 if (service->favorite == TRUE)
1492 __connman_service_auto_connect();
1500 static int service_load(struct connman_service *service)
1503 gchar *pathname, *data = NULL;
1507 DBG("service %p", service);
1509 if (service->profile == NULL)
1512 pathname = g_strdup_printf("%s/%s.conf", STORAGEDIR, service->profile);
1513 if (pathname == NULL)
1516 keyfile = g_key_file_new();
1518 if (g_file_get_contents(pathname, &data, &length, NULL) == FALSE) {
1525 if (g_key_file_load_from_data(keyfile, data, length,
1526 0, NULL) == FALSE) {
1533 switch (service->type) {
1534 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1535 case CONNMAN_SERVICE_TYPE_ETHERNET:
1537 case CONNMAN_SERVICE_TYPE_WIFI:
1538 case CONNMAN_SERVICE_TYPE_WIMAX:
1539 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1540 case CONNMAN_SERVICE_TYPE_CELLULAR:
1541 service->favorite = g_key_file_get_boolean(keyfile,
1542 service->identifier, "Favorite", NULL);
1544 str = g_key_file_get_string(keyfile,
1545 service->identifier, "Failure", NULL);
1547 service->state = CONNMAN_SERVICE_STATE_FAILURE;
1548 service->error = string2error(str);
1553 str = g_key_file_get_string(keyfile,
1554 service->identifier, "Modified", NULL);
1556 g_time_val_from_iso8601(str, &service->modified);
1560 str = g_key_file_get_string(keyfile,
1561 service->identifier, "Passphrase", NULL);
1563 g_free(service->passphrase);
1564 service->passphrase = str;
1567 __connman_ipconfig_load(service->ipconfig, keyfile,
1568 service->identifier, "IPv4.");
1570 g_key_file_free(keyfile);
1575 static int service_save(struct connman_service *service)
1578 gchar *pathname, *data = NULL;
1582 DBG("service %p", service);
1584 if (service->profile == NULL)
1587 pathname = g_strdup_printf("%s/%s.conf", STORAGEDIR, service->profile);
1588 if (pathname == NULL)
1591 keyfile = g_key_file_new();
1593 if (g_file_get_contents(pathname, &data, &length, NULL) == FALSE)
1597 if (g_key_file_load_from_data(keyfile, data, length,
1605 if (service->name != NULL)
1606 g_key_file_set_string(keyfile, service->identifier,
1607 "Name", service->name);
1609 switch (service->type) {
1610 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1611 case CONNMAN_SERVICE_TYPE_ETHERNET:
1613 case CONNMAN_SERVICE_TYPE_WIFI:
1614 case CONNMAN_SERVICE_TYPE_WIMAX:
1615 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1616 case CONNMAN_SERVICE_TYPE_CELLULAR:
1617 g_key_file_set_boolean(keyfile, service->identifier,
1618 "Favorite", service->favorite);
1620 if (service->state == CONNMAN_SERVICE_STATE_FAILURE) {
1621 const char *failure = error2string(service->error);
1622 if (failure != NULL)
1623 g_key_file_set_string(keyfile,
1624 service->identifier,
1625 "Failure", failure);
1627 g_key_file_remove_key(keyfile, service->identifier,
1633 str = g_time_val_to_iso8601(&service->modified);
1635 g_key_file_set_string(keyfile, service->identifier,
1640 if (service->passphrase != NULL)
1641 g_key_file_set_string(keyfile, service->identifier,
1642 "Passphrase", service->passphrase);
1644 g_key_file_remove_key(keyfile, service->identifier,
1645 "Passphrase", NULL);
1647 __connman_ipconfig_save(service->ipconfig, keyfile,
1648 service->identifier, "IPv4.");
1650 data = g_key_file_to_data(keyfile, &length, NULL);
1652 if (g_file_set_contents(pathname, data, length, NULL) == FALSE)
1653 connman_error("Failed to store service information");
1658 g_key_file_free(keyfile);
1665 static struct connman_storage service_storage = {
1667 .priority = CONNMAN_STORAGE_PRIORITY_LOW,
1668 .service_load = service_load,
1669 .service_save = service_save,
1672 int __connman_service_init(void)
1676 connection = connman_dbus_get_connection();
1678 if (connman_storage_register(&service_storage) < 0)
1679 connman_error("Failed to register service storage");
1681 service_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
1684 service_list = g_sequence_new(service_free);
1689 void __connman_service_cleanup(void)
1693 g_sequence_free(service_list);
1694 service_list = NULL;
1696 g_hash_table_destroy(service_hash);
1697 service_hash = NULL;
1699 connman_storage_unregister(&service_storage);
1701 dbus_connection_unref(connection);