From bf1da3faea4605a9a1305993b04e9db425561b1d Mon Sep 17 00:00:00 2001 From: Aleksander Morgado Date: Tue, 4 Sep 2012 11:34:00 +0200 Subject: [PATCH] iface-modem-simple: never remove connected bearers Modems have a maximum of bearers allowed to be connected at a time, number which is given by the number of available ports that may be used for data connections. When Simple.Connect() tries to launch a connection, it will try to find first an existing bearer with the required parameters (e.g. APN, IP type). If such bearer is found, it will just use it. If no such bearer is found, it will try to create one. When trying to create one, if there is no more room for bearers in the modem, we will remove the first disconnected bearer that we find, if any, before trying to create the new one. This logic now makes sure that no connected bearer gets removed in order to create a new one, and also that only one existing gets removed if possible (not every bearer as we did previously). Further logic to connect multiple bearers at a time cannot be done using the Simple interface. --- src/mm-iface-modem-simple.c | 59 ++++++++++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 4 deletions(-) diff --git a/src/mm-iface-modem-simple.c b/src/mm-iface-modem-simple.c index e4bc466e..cfec2805 100644 --- a/src/mm-iface-modem-simple.c +++ b/src/mm-iface-modem-simple.c @@ -489,6 +489,22 @@ unlock_check_ready (MMIfaceModem *self, g_object_unref (sim); } +typedef struct { + MMBearer *found; +} BearerListFindContext; + +static void +bearer_list_find_disconnected (MMBearer *bearer, + BearerListFindContext *ctx) +{ + /* If already marked one to remove, do nothing */ + if (ctx->found) + return; + + if (mm_bearer_get_status (bearer) == MM_BEARER_STATUS_DISCONNECTED) + ctx->found = g_object_ref (bearer); +} + static void connection_step (ConnectionContext *ctx) { @@ -634,10 +650,45 @@ connection_step (ConnectionContext *ctx) if (!ctx->bearer) { mm_dbg ("Creating new bearer..."); /* If we don't have enough space to create the bearer, try to remove - * all existing ones first. */ - if (mm_bearer_list_get_max (list) == mm_bearer_list_get_count (list)) - /* We'll remove all existing bearers, and then go on creating the new one */ - mm_bearer_list_delete_all_bearers (list); + * a disconnected bearer first. */ + if (mm_bearer_list_get_max (list) == mm_bearer_list_get_count (list)) { + BearerListFindContext foreach_ctx; + + foreach_ctx.found = NULL; + mm_bearer_list_foreach (list, + (MMBearerListForeachFunc)bearer_list_find_disconnected, + &foreach_ctx); + + /* Found a disconnected bearer, remove it */ + if (foreach_ctx.found) { + GError *error = NULL; + + if (!mm_bearer_list_delete_bearer (list, + mm_bearer_get_path (foreach_ctx.found), + &error)) { + mm_dbg ("Couldn't delete disconnected bearer at '%s': '%s'", + mm_bearer_get_path (foreach_ctx.found), + error->message); + g_error_free (error); + } else + mm_dbg ("Deleted disconnected bearer at '%s'", + mm_bearer_get_path (foreach_ctx.found)); + g_object_unref (foreach_ctx.found); + } + + /* Re-check space, and if we still are in max, return an error */ + if (mm_bearer_list_get_max (list) == mm_bearer_list_get_count (list)) { + g_dbus_method_invocation_return_error ( + ctx->invocation, + MM_CORE_ERROR, + MM_CORE_ERROR_TOO_MANY, + "Cannot create new bearer: all existing bearers are connected"); + connection_context_free (ctx); + g_object_unref (list); + g_object_unref (bearer_properties); + return; + } + } mm_iface_modem_create_bearer (MM_IFACE_MODEM (ctx->self), bearer_properties,