[PATCH 3/3] libmbim-glib,proxy: Allow for --no-close and --no-open options by mbimcli

Aleksander Morgado aleksander at aleksander.es
Sun Jul 27 05:01:06 PDT 2014


On Wed, Jul 23, 2014 at 11:21 PM, Greg Suarez <gpsuarez2512 at gmail.com> wrote:
> To support the --no-close option the proxy will no longer send the close
> message to the device. The proxy will also only exit once all devices
> are removed.  Thus the proxy connects to the MBIM_DEVICE_SIGNAL_REMOVED
> signal for each device. A new property, MBIM_PROXY_N_DEVICES, was added
> to indicate the number of devices the proxy is managing.
>
> To support the --no-open option the proxy now calls the
> mbim_device_new() upon receiving the
> MBIM_CID_PROXY_CONTROL_CONFIGURATION with the device path.

Pushed to greg/proxy branch, thanks.


> ---
>  src/libmbim-glib/mbim-proxy.c | 287 +++++++++++++++++++++++-------------------
>  src/libmbim-glib/mbim-proxy.h |   2 +
>  2 files changed, 157 insertions(+), 132 deletions(-)
>
> diff --git a/src/libmbim-glib/mbim-proxy.c b/src/libmbim-glib/mbim-proxy.c
> index 5be5241..17ea7d9 100644
> --- a/src/libmbim-glib/mbim-proxy.c
> +++ b/src/libmbim-glib/mbim-proxy.c
> @@ -47,6 +47,7 @@ G_DEFINE_TYPE (MbimProxy, mbim_proxy, G_TYPE_OBJECT)
>  enum {
>      PROP_0,
>      PROP_N_CLIENTS,
> +    PROP_N_DEVICES,
>      PROP_LAST
>  };
>
> @@ -82,6 +83,22 @@ mbim_proxy_get_n_clients (MbimProxy *self)
>      return g_list_length (self->priv->clients);
>  }
>
> +/**
> + * mbim_proxy_get_n_devices:
> + * @self: a #MbimProxy.
> + *
> + * Get the number of devices currently connected to the proxy.
> + *
> + * Returns: a #guint.
> + */
> +guint
> +mbim_proxy_get_n_devices (MbimProxy *self)
> +{
> +    g_return_val_if_fail (MBIM_IS_PROXY (self), 0);
> +
> +    return g_list_length (self->priv->devices);
> +}
> +
>  /*****************************************************************************/
>
>  typedef struct {
> @@ -96,6 +113,7 @@ typedef struct {
>      MbimDevice *device;
>      MbimMessage *internal_proxy_open_request;
>      guint indication_id;
> +    guint device_removed_id;
>      gchar *device_file_path;
>      gboolean opening_device;
>      gboolean service_subscriber_list_enabled;
> @@ -107,6 +125,12 @@ typedef struct {
>      Client *client;
>  } DeviceOpenContext;
>
> +typedef struct {
> +    MbimProxy *proxy;
> +    Client *client;
> +    MbimMessage *response;
> +} DeviceNewContext;
> +
>  static gboolean connection_readable_cb (GSocket *socket, GIOCondition condition, Client *client);
>
>  static void
> @@ -118,6 +142,8 @@ client_free (Client *client)
>      if (client->device) {
>          if (g_signal_handler_is_connected (client->device, client->indication_id))
>              g_signal_handler_disconnect (client->device, client->indication_id);
> +        if (g_signal_handler_is_connected (client->device, client->device_removed_id))
> +            g_signal_handler_disconnect (client->device, client->device_removed_id);
>          g_object_unref (client->device);
>      }
>
> @@ -139,25 +165,6 @@ client_free (Client *client)
>      g_slice_free (Client, client);
>  }
>
> -static guint
> -get_n_clients_with_device (MbimProxy *self,
> -                           MbimDevice *device)
> -{
> -    GList *l;
> -    guint n = 0;
> -    Client *client;
> -
> -    for (l = self->priv->clients; l; l = g_list_next (l)) {
> -        client = l->data;
> -
> -        if (device == client->device ||
> -            g_str_equal (mbim_device_get_path (device), mbim_device_get_path (client->device)))
> -            n++;
> -    }
> -
> -    return n;
> -}
> -
>  static Client *
>  get_client (MbimProxy *self,
>              Client    *client)
> @@ -171,50 +178,6 @@ get_client (MbimProxy *self,
>  }
>
>  static void
> -device_close_ready (MbimDevice   *device,
> -                    GAsyncResult *result)
> -{
> -    GError *error = NULL;
> -
> -    if (!mbim_device_close_finish (device, result, &error)) {
> -        g_debug ("error: couldn't close device: %s", error->message);
> -        g_error_free (error);
> -    } else
> -        g_debug ("Device closed");
> -
> -    g_object_unref (device);
> -}
> -
> -static void
> -device_close (MbimProxy *self,
> -              MbimDevice *device)
> -{
> -    if (!device)
> -        return;
> -
> -    /* If no more clients using the device, close and cleanup */
> -    if (get_n_clients_with_device (self, device) == 0) {
> -        GList *l;
> -
> -        for (l = self->priv->devices; l; l = g_list_next (l)) {
> -            MbimDevice *device_in_list = MBIM_DEVICE (l->data);
> -
> -            if (device == device_in_list ||
> -                g_str_equal (mbim_device_get_path (device), mbim_device_get_path (device_in_list))) {
> -                g_debug ("closing device '%s': no longer used", mbim_device_get_path_display (device));
> -                mbim_device_close (device_in_list,
> -                                   15,
> -                                   NULL,
> -                                   (GAsyncReadyCallback) device_close_ready,
> -                                   NULL);
> -                self->priv->devices = g_list_remove (self->priv->devices, device_in_list);
> -                break;
> -            }
> -        }
> -    }
> -}
> -
> -static void
>  connection_close (Client *client)
>  {
>      MbimProxy *self;
> @@ -223,10 +186,6 @@ connection_close (Client *client)
>
>      g_debug ("Client (%d) connection closed...", g_socket_get_fd (g_socket_connection_get_socket (client->connection)));
>
> -    /* Close device */
> -    if (client->device)
> -        device_close (self, client->device);
> -
>      /* Remove client */
>      self->priv->clients = g_list_remove (self->priv->clients, client);
>      g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_N_CLIENTS]);
> @@ -345,12 +304,43 @@ indication_cb (MbimDevice *device,
>  }
>
>  static void
> +proxy_device_removed_cb (MbimDevice *device,
> +                         MbimProxy *self)
> +{
> +    if (g_list_find (self->priv->devices, device)) {
> +        self->priv->devices = g_list_remove (self->priv->devices, device);
> +        g_object_unref (device);
> +        g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_N_DEVICES]);
> +    }
> +}
> +
> +static void
> +client_device_removed_cb (MbimDevice *device,
> +                          Client *client)
> +{
> +    connection_close (client);
> +}
> +
> +
> +static void
> +client_device_connect_signals (Client *client)
> +{
> +    client->indication_id = g_signal_connect (client->device,
> +                                              MBIM_DEVICE_SIGNAL_INDICATE_STATUS,
> +                                              G_CALLBACK (indication_cb),
> +                                              client);
> +    client->device_removed_id = g_signal_connect (client->device,
> +                                                  MBIM_DEVICE_SIGNAL_REMOVED,
> +                                                  G_CALLBACK (client_device_removed_cb),
> +                                                  client);
> +}
> +
> +static void
>  device_open_ready (MbimDevice *device,
>                     GAsyncResult *res,
>                     DeviceOpenContext *ctx)
>  {
>      MbimProxy *self = ctx->proxy;
> -    MbimDevice *existing;
>      Client *client;
>      GError *error = NULL;
>
> @@ -358,7 +348,6 @@ device_open_ready (MbimDevice *device,
>      if (!client) {
>          /* client must've been disconnected */
>          mbim_device_open_finish (device, res, NULL);
> -        device_close (self, device);
>          g_slice_free (DeviceOpenContext, ctx);
>          return;
>      }
> @@ -371,35 +360,31 @@ device_open_ready (MbimDevice *device,
>          return;
>      }
>
> -    /* Store device in the proxy independently */
> -    existing = find_device_for_path (self, mbim_device_get_path (client->device));
> -    if (existing) {
> -        /* Race condition, we created two MbimDevices for the same port, just skip ours, no big deal */
> -        g_object_unref (client->device);
> -        client->device = g_object_ref (existing);
> -    } else {
> -        /* Keep the newly added device in the proxy */
> -        self->priv->devices = g_list_append (self->priv->devices, g_object_ref (client->device));
> -    }
> -
> -    /* Register for device indications */
> -    client->indication_id = g_signal_connect (client->device,
> -                                              MBIM_DEVICE_SIGNAL_INDICATE_STATUS,
> -                                              G_CALLBACK (indication_cb),
> -                                              client);
> -
>      g_slice_free (DeviceOpenContext, ctx);
>      complete_internal_proxy_open (client);
>  }
>
>  static void
> +complete_internal_proxy_config (Client *client,
> +                                MbimMessage *response)
> +{
> +    if (!send_message (client, response, NULL))
> +        connection_close (client);
> +
> +    mbim_message_unref (response);
> +}
> +
> +static void
>  device_new_ready (GObject *source,
>                    GAsyncResult *res,
> -                  DeviceOpenContext *ctx)
> +                  DeviceNewContext *ctx)
>  {
>      GError *error = NULL;
>      Client *client;
>      MbimDevice *device;
> +    MbimDevice *existing;
> +    MbimProxy *self = ctx->proxy;
> +    MbimMessage *response = ctx->response;
>
>      device = mbim_device_new_finish (res, &error);
>      client = get_client (ctx->proxy, ctx->client);
> @@ -407,25 +392,43 @@ device_new_ready (GObject *source,
>          /* client must've been disconnected */
>          if (!device)
>              g_error_free (error);
> -        device_close (ctx->proxy, device);
> -        g_slice_free (DeviceOpenContext, ctx);
> +        mbim_message_unref (response);
> +        g_slice_free (DeviceNewContext, ctx);
>          return;
>      }
>
> +
>      client->device = device;
>      if (!client->device) {
>          g_debug ("couldn't open MBIM device: %s", error->message);
>          connection_close (client);
>          g_error_free (error);
> -        g_slice_free (DeviceOpenContext, ctx);
> +        mbim_message_unref (response);
> +        g_slice_free (DeviceNewContext, ctx);
>          return;
>      }
>
> -    mbim_device_open (client->device,
> -                      30,
> -                      NULL,
> -                      (GAsyncReadyCallback)device_open_ready,
> -                      ctx);
> +    /* Store device in the proxy independently */
> +    existing = find_device_for_path (self, mbim_device_get_path (client->device));
> +    if (existing) {
> +        /* Race condition, we created two MbimDevices for the same port, just skip ours, no big deal */
> +        g_object_unref (client->device);
> +        client->device = g_object_ref (existing);
> +    } else {
> +        /* Keep the newly added device in the proxy */
> +        self->priv->devices = g_list_append (self->priv->devices, g_object_ref (client->device));
> +        g_signal_connect (client->device,
> +                          MBIM_DEVICE_SIGNAL_REMOVED,
> +                          G_CALLBACK (proxy_device_removed_cb),
> +                          self);
> +        g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_N_DEVICES]);
> +    }
> +
> +    /* Register for device indications */
> +    client_device_connect_signals (client);
> +
> +    g_slice_free (DeviceNewContext, ctx);
> +    complete_internal_proxy_config (client, response);
>  }
>
>  static gboolean
> @@ -438,40 +441,25 @@ process_internal_proxy_open (Client *client,
>      /* Keep it */
>      client->internal_proxy_open_request = mbim_message_ref (message);
>
> -    if (client->device_file_path) {
> -        client->device = find_device_for_path (self, client->device_file_path);
> -    } else {
> -        g_debug ("missing device file path");
> +    if (!client->device) {
> +        /* device should've been created in process_internal_proxy_config() */
> +        g_debug ("can't find device for path, send MBIM_CID_PROXY_CONTROL_CONFIGURATION first");
>          complete_internal_proxy_open (client);
>          return FALSE;
> -    }
> -
> -    /* Need to create a device ourselves */
> -    if (!client->device) {
> -        GFile *file;
> -
> +    } else if (!mbim_device_is_open (client->device)) {
> +        /* device found but not open, open it */
>          ctx = g_slice_new0 (DeviceOpenContext);
>          ctx->proxy = self;
>          ctx->client = client;
>
> -        file = g_file_new_for_path (client->device_file_path);
> -        mbim_device_new (file,
> -                         NULL,
> -                         (GAsyncReadyCallback)device_new_ready,
> -                         ctx);
> -        g_object_unref (file);
> +        mbim_device_open (client->device,
> +                          30,
> +                          NULL,
> +                          (GAsyncReadyCallback)device_open_ready,
> +                          ctx);
>          return TRUE;
>      }
>
> -    /* register client for notifications */
> -    client->indication_id = g_signal_connect (client->device,
> -                                              MBIM_DEVICE_SIGNAL_INDICATE_STATUS,
> -                                              G_CALLBACK (indication_cb),
> -                                              client);
> -
> -    /* Keep a reference to the device in the client */
> -    g_object_ref (client->device);
> -
>      complete_internal_proxy_open (client);
>      return FALSE;
>  }
> @@ -480,15 +468,9 @@ static gboolean
>  process_internal_proxy_close (Client *client,
>                                MbimMessage *message)
>  {
> -    MbimProxy *self = client->proxy;
> -    MbimDevice *device;
>      MbimMessage *response;
>      GError *error = NULL;
>
> -    device = client->device ? g_object_ref (client->device) : NULL;
> -    device_close (self, device);
> -    g_object_unref (device);
> -
>      response = mbim_message_close_done_new (mbim_message_get_transaction_id (message), MBIM_STATUS_ERROR_NONE);
>      if (!send_message (client, response, &error)) {
>          mbim_message_unref (response);
> @@ -504,10 +486,11 @@ static gboolean
>  process_internal_proxy_config (Client *client,
>                                 MbimMessage *message)
>  {
> +    MbimProxy *self = client->proxy;
> +    DeviceNewContext  *ctx;
>      MbimMessage *response;
>      MbimStatusError error_status_code;
>      struct command_done_message *command_done;
> -    GError *error = NULL;
>
>      if (mbim_message_command_get_command_type (message) == MBIM_MESSAGE_COMMAND_TYPE_SET) {
>          if (client->device_file_path)
> @@ -528,13 +511,35 @@ process_internal_proxy_config (Client *client,
>      command_done->command_id  = GUINT32_TO_LE (mbim_message_command_get_cid(message));
>      command_done->status_code = GUINT32_TO_LE (error_status_code);
>
> -    if (!send_message (client, response, &error)) {
> -        mbim_message_unref (response);
> -        connection_close (client);
> -        return FALSE;
> +    /* create a device to allow clients access without sending the open */
> +    if (client->device_file_path) {
> +        client->device = find_device_for_path (self, client->device_file_path);
> +        if (!client->device) {
> +            GFile *file;
> +
> +            ctx = g_slice_new0 (DeviceNewContext);
> +            ctx->proxy = self;
> +            ctx->client = client;
> +            ctx->response = response;
> +
> +            file = g_file_new_for_path (client->device_file_path);
> +            mbim_device_new (file,
> +                             NULL,
> +                             (GAsyncReadyCallback)device_new_ready,
> +                             ctx);
> +            g_object_unref (file);
> +
> +            return TRUE;
> +        } else {
> +            /* register client for notifications */
> +            client_device_connect_signals (client);
> +
> +            /* Keep a reference to the device in the client */
> +            g_object_ref (client->device);
> +        }
>      }
>
> -    mbim_message_unref (response);
> +    complete_internal_proxy_config (client, response);
>      return TRUE;
>  }
>
> @@ -1068,6 +1073,9 @@ get_property (GObject *object,
>      case PROP_N_CLIENTS:
>          g_value_set_uint (value, g_list_length (self->priv->clients));
>          break;
> +    case PROP_N_DEVICES:
> +        g_value_set_uint (value, g_list_length (self->priv->devices));
> +        break;
>      default:
>          G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
>          break;
> @@ -1084,6 +1092,11 @@ dispose (GObject *object)
>          priv->clients = NULL;
>      }
>
> +    if (priv->devices) {
> +        g_list_free_full (priv->devices, (GDestroyNotify) g_object_unref);
> +        priv->devices = NULL;
> +    }
> +
>      if (priv->socket_service) {
>          if (g_socket_service_is_active (priv->socket_service))
>              g_socket_service_stop (priv->socket_service);
> @@ -1116,4 +1129,14 @@ mbim_proxy_class_init (MbimProxyClass *proxy_class)
>                             0,
>                             G_PARAM_READABLE);
>      g_object_class_install_property (object_class, PROP_N_CLIENTS, properties[PROP_N_CLIENTS]);
> +
> +    properties[PROP_N_DEVICES] =
> +        g_param_spec_uint (MBIM_PROXY_N_DEVICES,
> +                           "Number of devices",
> +                           "Number of devices currently managed by the proxy",
> +                           0,
> +                           G_MAXUINT,
> +                           0,
> +                           G_PARAM_READABLE);
> +    g_object_class_install_property (object_class, PROP_N_DEVICES, properties[PROP_N_DEVICES]);
>  }
> diff --git a/src/libmbim-glib/mbim-proxy.h b/src/libmbim-glib/mbim-proxy.h
> index decd662..f874cc4 100644
> --- a/src/libmbim-glib/mbim-proxy.h
> +++ b/src/libmbim-glib/mbim-proxy.h
> @@ -41,6 +41,7 @@ typedef struct _MbimProxyPrivate MbimProxyPrivate;
>  #define MBIM_PROXY_SOCKET_PATH "mbim-proxy"
>
>  #define MBIM_PROXY_N_CLIENTS   "mbim-proxy-n-clients"
> +#define MBIM_PROXY_N_DEVICES   "mbim-proxy-n-devices"
>
>  struct _MbimProxy {
>      GObject parent;
> @@ -55,5 +56,6 @@ GType mbim_proxy_get_type (void);
>
>  MbimProxy *mbim_proxy_new           (GError **error);
>  guint      mbim_proxy_get_n_clients (MbimProxy *self);
> +guint      mbim_proxy_get_n_devices (MbimProxy *self);
>
>  #endif /* MBIM_PROXY_H */
> --
> 1.9.3
>



-- 
Aleksander
https://aleksander.es


More information about the libmbim-devel mailing list