gprs: Add DBus method to reset contexts
authorAlfonso Sanchez-Beato <alfonso.sanchez-beato@canonical.com>
Mon, 18 May 2015 06:47:06 +0000 (08:47 +0200)
committerDenis Kenzior <denkenz@gmail.com>
Mon, 18 May 2015 14:08:13 +0000 (09:08 -0500)
Add DBus method that removes the current contexts and re-provisions
using the APN database.

src/gprs.c

index 05ab499457188e184129dadb0d38d1a513a4fd82..64fa6f106f79c412d28fd9239c4d2c86684aaa9d 100644 (file)
@@ -149,6 +149,8 @@ struct pri_context {
 
 static void gprs_netreg_update(struct ofono_gprs *gprs);
 static void gprs_deactivate_next(struct ofono_gprs *gprs);
+static void provision_contexts(struct ofono_gprs *gprs, const char *mcc,
+                               const char *mnc, const char *spn);
 
 static GSList *g_drivers = NULL;
 static GSList *g_context_drivers = NULL;
@@ -1885,6 +1887,36 @@ static struct pri_context *add_context(struct ofono_gprs *gprs,
        return context;
 }
 
+static void send_context_added_signal(struct ofono_gprs *gprs,
+                                       struct pri_context *context,
+                                       DBusConnection *conn)
+{
+       const char *path;
+       DBusMessage *signal;
+       DBusMessageIter iter;
+       DBusMessageIter dict;
+
+       path = __ofono_atom_get_path(gprs->atom);
+       signal = dbus_message_new_signal(path,
+                                       OFONO_CONNECTION_MANAGER_INTERFACE,
+                                       "ContextAdded");
+       if (!signal)
+               return;
+
+       dbus_message_iter_init_append(signal, &iter);
+
+       path = context->path;
+       dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &path);
+
+       dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+                                       OFONO_PROPERTIES_ARRAY_SIGNATURE,
+                                       &dict);
+       append_context_properties(context, &dict);
+       dbus_message_iter_close_container(&iter, &dict);
+
+       g_dbus_send_message(conn, signal);
+}
+
 static DBusMessage *gprs_add_context(DBusConnection *conn,
                                        DBusMessage *msg, void *data)
 {
@@ -1894,7 +1926,6 @@ static DBusMessage *gprs_add_context(DBusConnection *conn,
        const char *name;
        const char *path;
        enum ofono_gprs_context_type type;
-       DBusMessage *signal;
 
        if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &typestr,
                                        DBUS_TYPE_INVALID))
@@ -1916,29 +1947,7 @@ static DBusMessage *gprs_add_context(DBusConnection *conn,
        g_dbus_send_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &path,
                                        DBUS_TYPE_INVALID);
 
-       path = __ofono_atom_get_path(gprs->atom);
-       signal = dbus_message_new_signal(path,
-                                       OFONO_CONNECTION_MANAGER_INTERFACE,
-                                       "ContextAdded");
-
-       if (signal) {
-               DBusMessageIter iter;
-               DBusMessageIter dict;
-
-               dbus_message_iter_init_append(signal, &iter);
-
-               path = context->path;
-               dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
-                                               &path);
-
-               dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
-                                       OFONO_PROPERTIES_ARRAY_SIGNATURE,
-                                       &dict);
-               append_context_properties(context, &dict);
-               dbus_message_iter_close_container(&iter, &dict);
-
-               g_dbus_send_message(conn, signal);
-       }
+       send_context_added_signal(gprs, context, conn);
 
        return NULL;
 }
@@ -2173,6 +2182,89 @@ static DBusMessage *gprs_get_contexts(DBusConnection *conn,
        return reply;
 }
 
+static void remove_non_active_context(struct ofono_gprs *gprs,
+                               struct pri_context *ctx, DBusConnection *conn)
+{
+       char *path;
+       const char *atompath;
+
+       if (gprs->settings) {
+               g_key_file_remove_group(gprs->settings, ctx->key, NULL);
+               storage_sync(gprs->imsi, SETTINGS_STORE, gprs->settings);
+       }
+
+       /* Make a backup copy of path for signal emission below */
+       path = g_strdup(ctx->path);
+
+       context_dbus_unregister(ctx);
+       gprs->contexts = g_slist_remove(gprs->contexts, ctx);
+
+       atompath = __ofono_atom_get_path(gprs->atom);
+       g_dbus_emit_signal(conn, atompath, OFONO_CONNECTION_MANAGER_INTERFACE,
+                               "ContextRemoved", DBUS_TYPE_OBJECT_PATH, &path,
+                               DBUS_TYPE_INVALID);
+       g_free(path);
+}
+
+static DBusMessage *gprs_reset_contexts(DBusConnection *conn,
+                                       DBusMessage *msg, void *data)
+{
+       struct ofono_gprs *gprs = data;
+       struct ofono_modem *modem = __ofono_atom_get_modem(gprs->atom);
+       struct ofono_sim *sim = __ofono_atom_find(OFONO_ATOM_TYPE_SIM, modem);
+       DBusMessage *reply;
+       GSList *l;
+
+       if (gprs->pending)
+               return __ofono_error_busy(msg);
+
+       for (l = gprs->contexts; l; l = l->next) {
+               struct pri_context *ctx = l->data;
+
+               if (ctx->pending)
+                       return __ofono_error_busy(msg);
+       }
+
+       if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_INVALID))
+               return __ofono_error_invalid_args(msg);
+
+       if (gprs->powered)
+               return __ofono_error_not_allowed(msg);
+
+       for (l = gprs->contexts; l; l = l->next) {
+               struct pri_context *ctx = l->data;
+
+               if (ctx->active)
+                       return __ofono_error_not_allowed(msg);
+       }
+
+       reply = dbus_message_new_method_return(msg);
+       if (reply == NULL)
+               return NULL;
+
+       /* Remove first the current contexts, re-provision after */
+
+       while (gprs->contexts != NULL) {
+               struct pri_context *ctx = gprs->contexts->data;
+               remove_non_active_context(gprs, ctx, conn);
+       }
+
+       gprs->last_context_id = 0;
+
+       provision_contexts(gprs, ofono_sim_get_mcc(sim),
+                               ofono_sim_get_mnc(sim), ofono_sim_get_spn(sim));
+
+       if (gprs->contexts == NULL) /* Automatic provisioning failed */
+               add_context(gprs, NULL, OFONO_GPRS_CONTEXT_TYPE_INTERNET);
+
+       for (l = gprs->contexts; l; l = l->next) {
+               struct pri_context *ctx = l->data;
+               send_context_added_signal(gprs, ctx, conn);
+       }
+
+       return reply;
+}
+
 static const GDBusMethodTable manager_methods[] = {
        { GDBUS_METHOD("GetProperties",
                        NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
@@ -2192,6 +2284,8 @@ static const GDBusMethodTable manager_methods[] = {
        { GDBUS_METHOD("GetContexts", NULL,
                        GDBUS_ARGS({ "contexts_with_properties", "a(oa{sv})" }),
                        gprs_get_contexts) },
+       { GDBUS_ASYNC_METHOD("ResetContexts", NULL, NULL,
+                       gprs_reset_contexts) },
        { }
 };