+ struct service_entry *entry = user_data;
+ struct connman_service *service = entry->service;
+
+ DBG("connect service %p", service);
+ __connman_service_connect(service);
+
+ return FALSE;
+}
+
+static void deselect_service(struct session_info *info)
+{
+ struct service_entry *entry;
+ connman_bool_t disconnect, connected;
+
+ DBG("");
+
+ if (info->entry == NULL)
+ return;
+
+ disconnect = explicit_disconnect(info);
+
+ connected = is_connecting(info->entry->state) == TRUE ||
+ is_connected(info->entry->state) == TRUE;
+
+ info->state = CONNMAN_SESSION_STATE_DISCONNECTED;
+ info->entry->reason = CONNMAN_SESSION_REASON_UNKNOWN;
+
+ entry = info->entry;
+ info->entry = NULL;
+
+ DBG("disconnect %d connected %d", disconnect, connected);
+
+ if (disconnect == TRUE && connected == TRUE)
+ pending_timeout_add(0, call_disconnect, entry);
+}
+
+static void deselect_and_disconnect(struct connman_session *session,
+ enum connman_session_reason reason)
+{
+ struct session_info *info = session->info;
+
+ deselect_service(info);
+
+ info->reason = reason;
+}
+
+static void select_connected_service(struct session_info *info,
+ struct service_entry *entry)
+{
+ enum connman_session_state state;
+
+ state = service_to_session_state(entry->state);
+ if (is_type_matching_state(&state, info->type) == FALSE)
+ return;
+
+ info->state = state;
+
+ info->entry = entry;
+ info->entry->reason = info->reason;
+
+ if (explicit_connect(info->reason) == FALSE)
+ return;
+
+ __connman_service_session_inc(info->entry->service);
+}
+
+static void select_offline_service(struct session_info *info,
+ struct service_entry *entry)
+{
+ if (explicit_connect(info->reason) == FALSE)
+ return;
+
+ info->state = service_to_session_state(entry->state);
+
+ info->entry = entry;
+ info->entry->reason = info->reason;
+
+ __connman_service_session_inc(info->entry->service);
+ pending_timeout_add(0, call_connect, entry);
+}
+
+static void select_service(struct session_info *info,
+ struct service_entry *entry)
+{
+ DBG("service %p", entry->service);
+
+ if (is_connected(entry->state) == TRUE)
+ select_connected_service(info, entry);
+ else
+ select_offline_service(info, entry);
+}
+
+static void select_and_connect(struct connman_session *session,
+ enum connman_session_reason reason)
+{
+ struct session_info *info = session->info;
+ struct service_entry *entry = NULL;
+ GSequenceIter *iter;
+
+ DBG("session %p reason %s", session, reason2string(reason));
+
+ info->reason = reason;
+
+ iter = g_sequence_get_begin_iter(session->service_list);
+
+ while (g_sequence_iter_is_end(iter) == FALSE) {
+ entry = g_sequence_get(iter);
+
+ switch (entry->state) {
+ case CONNMAN_SERVICE_STATE_ASSOCIATION:
+ case CONNMAN_SERVICE_STATE_CONFIGURATION:
+ case CONNMAN_SERVICE_STATE_READY:
+ case CONNMAN_SERVICE_STATE_ONLINE:
+ case CONNMAN_SERVICE_STATE_IDLE:
+ case CONNMAN_SERVICE_STATE_DISCONNECT:
+ select_service(info, entry);
+ return;
+ case CONNMAN_SERVICE_STATE_UNKNOWN:
+ case CONNMAN_SERVICE_STATE_FAILURE:
+ break;
+ }
+
+ iter = g_sequence_iter_next(iter);
+ }
+}
+
+static struct service_entry *create_service_entry(struct connman_service *service,
+ const char *name,
+ enum connman_service_state state)
+{
+ struct service_entry *entry;