[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