static void session_activate(struct connman_session *session) { GHashTableIter iter; gpointer key, value; if (!service_hash) return; g_hash_table_iter_init(&iter, service_hash); while (g_hash_table_iter_next(&iter, &key, &value)) { struct connman_service_info *info = value; enum connman_service_state state; state = __connman_service_get_state(info->service); if (is_session_connected(session, state) && session_match_service(session, info->service)) { DBG("session %p add service %p", session, info->service); info->sessions = g_slist_prepend(info->sessions, session); session->service = info->service; update_session_state(session); return; } } session_notify(session); }
int connman_session_config_update(struct connman_session *session) { struct session_info *info = session->info; GSList *allowed_bearers; int err; DBG("session %p", session); /* * We update all configuration even though only one entry * might have changed. We can still optimize this later. */ if (session->id_type != session->policy_config->id_type) { cleanup_firewall_session(session); err = init_firewall_session(session); if (err < 0) { connman_session_destroy(session); return err; } session->id_type = session->policy_config->id_type; } apply_policy_on_bearers( session->policy_config->allowed_bearers, session->user_allowed_bearers, &allowed_bearers); if (session->active) set_active_session(session, false); session->active = false; session_deactivate(session); g_slist_free(info->config.allowed_bearers); info->config.allowed_bearers = allowed_bearers; session_activate(session); info->config.type = apply_policy_on_type( session->policy_config->type, info->config.type); info->config.roaming_policy = session->policy_config->roaming_policy; info->config.ecall = session->policy_config->ecall; if (info->config.ecall) ecall_session = session; info->config.priority = session->policy_config->priority; session_notify(session); return 0; }
static void update_session_state(struct connman_session *session) { enum connman_service_state service_state; enum connman_session_state state = CONNMAN_SESSION_STATE_DISCONNECTED; if (session->service) { service_state = __connman_service_get_state(session->service); state = service_to_session_state(service_state); session->info->state = state; } session->info->state = state; DBG("session %p state %s", session, state2string(state)); update_routing_table(session); update_nat_rules(session); session_notify(session); }
static DBusMessage *change_session(DBusConnection *conn, DBusMessage *msg, void *user_data) { struct connman_session *session = user_data; struct session_info *info = session->info; DBusMessageIter iter, value; const char *name; const char *val; GSList *allowed_bearers; int err; DBG("session %p", session); if (!dbus_message_iter_init(msg, &iter)) return __connman_error_invalid_arguments(msg); if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) return __connman_error_invalid_arguments(msg); dbus_message_iter_get_basic(&iter, &name); dbus_message_iter_next(&iter); if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) return __connman_error_invalid_arguments(msg); dbus_message_iter_recurse(&iter, &value); switch (dbus_message_iter_get_arg_type(&value)) { case DBUS_TYPE_ARRAY: if (g_str_equal(name, "AllowedBearers")) { err = parse_bearers(&value, &allowed_bearers); if (err < 0) return __connman_error_failed(msg, -err); if (session->active) set_active_session(session, false); session->active = false; session_deactivate(session); g_slist_free(info->config.allowed_bearers); session->user_allowed_bearers = allowed_bearers; apply_policy_on_bearers( session->policy_config->allowed_bearers, session->user_allowed_bearers, &info->config.allowed_bearers); session_activate(session); } else { goto err; } break; case DBUS_TYPE_STRING: if (g_str_equal(name, "ConnectionType")) { dbus_message_iter_get_basic(&value, &val); info->config.type = apply_policy_on_type( session->policy_config->type, connman_session_parse_connection_type(val)); } else { goto err; } break; default: goto err; } session_notify(session); return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); err: return __connman_error_invalid_arguments(msg); }
static void session_changed(struct connman_session *session, enum connman_session_trigger trigger) { struct session_info *info = session->info; struct session_info *info_last = session->info_last; GSequenceIter *service_iter = NULL, *service_iter_last = NULL; GSequence *service_list_last; GHashTable *service_hash_last; /* * TODO: This only a placeholder for the 'real' algorithm to * play a bit around. So we are going to improve it step by step. */ DBG("session %p trigger %s reason %s", session, trigger2string(trigger), reason2string(info->reason)); if (info->entry != NULL) { enum connman_session_state state; state = service_to_session_state(info->entry->state); if (is_type_matching_state(&state, info->config.type) == TRUE) info->state = state; } switch (trigger) { case CONNMAN_SESSION_TRIGGER_UNKNOWN: DBG("ignore session changed event"); return; case CONNMAN_SESSION_TRIGGER_SETTING: if (info->config.allowed_bearers != info_last->config.allowed_bearers) { service_hash_last = session->service_hash; service_list_last = session->service_list; populate_service_list(session); if (info->entry != NULL) { service_iter_last = g_hash_table_lookup( service_hash_last, info->entry->service); service_iter = g_hash_table_lookup( session->service_hash, info->entry->service); } if (service_iter == NULL && service_iter_last != NULL) { /* * The currently selected service is * not part of this session anymore. */ deselect_and_disconnect(session); } g_hash_table_remove_all(service_hash_last); g_sequence_free(service_list_last); } if (info->config.type != info_last->config.type) { if (info->state >= CONNMAN_SESSION_STATE_CONNECTED && is_type_matching_state(&info->state, info->config.type) == FALSE) deselect_and_disconnect(session); } if (info->state == CONNMAN_SESSION_STATE_DISCONNECTED) { select_and_connect(session, CONNMAN_SESSION_REASON_FREE_RIDE); } break; case CONNMAN_SESSION_TRIGGER_ECALL: /* * For the time beeing we fallback to normal connect * strategy. */ case CONNMAN_SESSION_TRIGGER_CONNECT: if (info->state >= CONNMAN_SESSION_STATE_CONNECTED) { if (info->entry->reason == CONNMAN_SESSION_REASON_CONNECT) break; info->entry->reason = CONNMAN_SESSION_REASON_CONNECT; __connman_service_session_inc(info->entry->service); break; } if (info->entry != NULL && is_connecting(info->entry->state) == TRUE) { break; } select_and_connect(session, CONNMAN_SESSION_REASON_CONNECT); break; case CONNMAN_SESSION_TRIGGER_DISCONNECT: deselect_and_disconnect(session); break; case CONNMAN_SESSION_TRIGGER_SERVICE: if (info->entry != NULL && (is_connecting(info->entry->state) == TRUE || is_connected(info->entry->state) == TRUE)) { break; } deselect_and_disconnect(session); if (info->reason == CONNMAN_SESSION_REASON_FREE_RIDE) { select_and_connect(session, info->reason); } break; } session_notify(session); }
static void session_activate(struct connman_session *session) { GHashTableIter iter; gpointer key, value; if (!service_hash) return; if (policy && policy->get_service_for_session) { struct connman_service *service; struct connman_service_info *info; GSList *service_list = NULL; enum connman_service_state state = CONNMAN_SESSION_STATE_DISCONNECTED; g_hash_table_iter_init(&iter, service_hash); while (g_hash_table_iter_next(&iter, &key, &value)) { struct connman_service_info *info = value; state = connman_service_get_state(info->service); if (is_session_connected(session, state)) service_list = g_slist_prepend(service_list, info->service); } service_list = g_slist_reverse(service_list); service = policy->get_service_for_session(session, service_list); if (service) { info = g_hash_table_lookup(service_hash, service); DBG("session %p add service %p", session, info->service); info->sessions = g_slist_prepend(info->sessions, session); session->service = info->service; update_session_state(session); } g_slist_free(service_list); return; } g_hash_table_iter_init(&iter, service_hash); while (g_hash_table_iter_next(&iter, &key, &value)) { struct connman_service_info *info = value; enum connman_service_state state; state = connman_service_get_state(info->service); if (is_session_connected(session, state) && session_match_service(session, info->service)) { DBG("session %p add service %p", session, info->service); info->sessions = g_slist_prepend(info->sessions, session); session->service = info->service; update_session_state(session); return; } } session_notify(session); }