diff options
author | Daniele Palmas <dnlplm@gmail.com> | 2022-06-05 22:30:38 +0200 |
---|---|---|
committer | Daniele Palmas <dnlplm@gmail.com> | 2022-08-05 18:00:12 +0200 |
commit | 601e0dcfea4ec6e56b7dfe2bfbc70ae49a4f3e3a (patch) | |
tree | 74c891a6c52263bbb84a90440f98d71108773aee | |
parent | 462325fb113b5de67a784135612ef9ee33cc8f8e (diff) | |
download | libmbim-601e0dcfea4ec6e56b7dfe2bfbc70ae49a4f3e3a.tar.gz |
libmbim-glib,net-port-manager: refactor netlink implementation to new files
In preparation for wwan support.
-rw-r--r-- | docs/reference/libmbim-glib/meson.build | 1 | ||||
-rw-r--r-- | src/libmbim-glib/mbim-helpers-netlink.c | 298 | ||||
-rw-r--r-- | src/libmbim-glib/mbim-helpers-netlink.h | 98 | ||||
-rw-r--r-- | src/libmbim-glib/mbim-net-port-manager.c | 355 | ||||
-rw-r--r-- | src/libmbim-glib/meson.build | 1 |
5 files changed, 441 insertions, 312 deletions
diff --git a/docs/reference/libmbim-glib/meson.build b/docs/reference/libmbim-glib/meson.build index 3dcc67e..29c6adc 100644 --- a/docs/reference/libmbim-glib/meson.build +++ b/docs/reference/libmbim-glib/meson.build @@ -12,6 +12,7 @@ src_dirs = [ private_headers = [ 'mbim-helpers.h', + 'mbim-helpers-netlink.h', 'mbim-message-private.h', 'mbim-net-port-manager.h', ] diff --git a/src/libmbim-glib/mbim-helpers-netlink.c b/src/libmbim-glib/mbim-helpers-netlink.c new file mode 100644 index 0000000..9a14086 --- /dev/null +++ b/src/libmbim-glib/mbim-helpers-netlink.c @@ -0,0 +1,298 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * libmbim-glib -- GLib/GIO based library to control MBIM devices + * + * Copyright (C) 2022 Daniele Palmas <dnlplm@gmail.com> + * + * Based on previous work: + * Copyright (C) 2020-2021 Eric Caruso <ejcaruso@chromium.org> + * Copyright (C) 2020-2021 Andrew Lassalle <andrewlassalle@chromium.org> + * Copyright (C) 2021 Aleksander Morgado <aleksander@aleksander.es> + */ + +#include <linux/if_link.h> +#include <linux/netlink.h> +#include <linux/rtnetlink.h> +#include <sys/socket.h> + +#include "mbim-helpers-netlink.h" + +/*****************************************************************************/ +/* + * Netlink message construction functions + */ + +NetlinkHeader * +mbim_helpers_netlink_get_message_header (NetlinkMessage *msg) +{ + return (NetlinkHeader *) (msg->data); +} + +guint +mbim_helpers_netlink_get_pos_of_next_attr (NetlinkMessage *msg) +{ + return NLMSG_ALIGN (msg->len); +} + +static void +append_netlink_attribute (NetlinkMessage *msg, + gushort type, + gconstpointer value, + gushort len) +{ + guint attr_len; + guint old_len; + guint next_attr_rel_pos; + char *next_attr_abs_pos; + struct rtattr new_attr; + + /* Expand the buffer to hold the new attribute */ + attr_len = RTA_ALIGN (RTA_LENGTH (len)); + old_len = msg->len; + next_attr_rel_pos = mbim_helpers_netlink_get_pos_of_next_attr (msg); + + g_byte_array_set_size (msg, next_attr_rel_pos + attr_len); + /* fill new bytes with zero, since some padding is added between attributes. */ + memset ((char *) msg->data + old_len, 0, msg->len - old_len); + + new_attr.rta_type = type; + new_attr.rta_len = RTA_LENGTH (len); + next_attr_abs_pos = (char *) msg->data + next_attr_rel_pos; + memcpy (next_attr_abs_pos, &new_attr, sizeof (struct rtattr)); + + if (value) + memcpy (RTA_DATA (next_attr_abs_pos), value, len); + + /* Update the total netlink message length */ + mbim_helpers_netlink_get_message_header (msg)->msghdr.nlmsg_len = msg->len; +} + +void +mbim_helpers_netlink_append_attribute_nested (NetlinkMessage *msg, + gushort type) +{ + append_netlink_attribute (msg, type, NULL, 0); +} + +void +mbim_helpers_netlink_append_attribute_string (NetlinkMessage *msg, + gushort type, + const gchar *value) +{ + append_netlink_attribute (msg, type, value, strlen (value)); +} + +void +mbim_helpers_netlink_append_attribute_uint16 (NetlinkMessage *msg, + gushort type, + guint16 value) +{ + append_netlink_attribute (msg, type, &value, sizeof (value)); +} + +void +mbim_helpers_netlink_append_attribute_uint32 (NetlinkMessage *msg, + gushort type, + guint32 value) +{ + append_netlink_attribute (msg, type, &value, sizeof (value)); +} + +NetlinkMessage * +mbim_helpers_netlink_message_new (guint16 type, + guint16 extra_flags) +{ + NetlinkMessage *msg; + NetlinkHeader *hdr; + + int size = sizeof (NetlinkHeader); + + msg = g_byte_array_new (); + g_byte_array_set_size (msg, size); + memset ((char *) msg->data, 0, size); + + hdr = mbim_helpers_netlink_get_message_header (msg); + hdr->msghdr.nlmsg_len = msg->len; + hdr->msghdr.nlmsg_type = type; + hdr->msghdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | extra_flags; + hdr->ifreq.ifi_family = AF_UNSPEC; + return msg; +} + +void +mbim_helpers_netlink_message_free (NetlinkMessage *msg) +{ + g_byte_array_unref (msg); +} + +/*****************************************************************************/ +/* + * Transaction management functions + */ + +static gboolean +transaction_timed_out (NetlinkTransaction *tr, + GHashTable *transactions) +{ + GTask *task; + guint32 sequence_id; + + task = g_steal_pointer (&tr->completion_task); + sequence_id = tr->sequence_id; + + g_hash_table_remove (transactions, + GUINT_TO_POINTER (tr->sequence_id)); + + g_task_return_new_error (task, + G_IO_ERROR, + G_IO_ERROR_TIMED_OUT, + "Netlink message with sequence ID %u timed out", + sequence_id); + + g_object_unref (task); + return G_SOURCE_REMOVE; +} + +void +mbim_helpers_netlink_transaction_complete_with_error (NetlinkTransaction *tr, + GHashTable *transactions, + GError *error) +{ + GTask *task; + + task = g_steal_pointer (&tr->completion_task); + + g_hash_table_remove (transactions, + GUINT_TO_POINTER (tr->sequence_id)); + + g_task_return_error (task, error); + g_object_unref (task); +} + +void +mbim_helpers_netlink_transaction_complete (NetlinkTransaction *tr, + GHashTable *transactions, + gint saved_errno) +{ + GTask *task; + guint32 sequence_id; + + task = g_steal_pointer (&tr->completion_task); + sequence_id = tr->sequence_id; + + g_hash_table_remove (transactions, + GUINT_TO_POINTER (tr->sequence_id)); + + if (!saved_errno) { + g_task_return_boolean (task, TRUE); + } else { + g_task_return_new_error (task, + G_IO_ERROR, + g_io_error_from_errno (saved_errno), + "Netlink message with transaction %u failed: %s", + sequence_id, + g_strerror (saved_errno)); + } + + g_object_unref (task); +} + +void +mbim_helpers_netlink_transaction_free (NetlinkTransaction *tr) +{ + g_assert (tr->completion_task == NULL); + g_source_destroy (tr->timeout_source); + g_source_unref (tr->timeout_source); + g_slice_free (NetlinkTransaction, tr); +} + +NetlinkTransaction * +mbim_helpers_netlink_transaction_new (guint *sequence_id, + GHashTable *transactions, + NetlinkMessage *msg, + guint timeout, + GTask *task) +{ + NetlinkTransaction *tr; + + tr = g_slice_new0 (NetlinkTransaction); + tr->sequence_id = ++(*sequence_id); + mbim_helpers_netlink_get_message_header (msg)->msghdr.nlmsg_seq = tr->sequence_id; + if (timeout) { + tr->timeout_source = g_timeout_source_new_seconds (timeout); + g_source_set_callback (tr->timeout_source, + (GSourceFunc) transaction_timed_out, + tr, + NULL); + g_source_attach (tr->timeout_source, + g_main_context_get_thread_default ()); + } + tr->completion_task = g_object_ref (task); + + g_hash_table_insert (transactions, + GUINT_TO_POINTER (tr->sequence_id), + tr); + return tr; +} + +/*****************************************************************************/ + +static gboolean +netlink_message_cb (GSocket *socket, + GIOCondition condition, + GHashTable *transactions) +{ + GError *error = NULL; + gchar buf[512]; + int bytes_received; + unsigned int buffer_len; + struct nlmsghdr *hdr; + + if (condition & G_IO_HUP || condition & G_IO_ERR) { + g_warning ("[netlink] socket connection closed."); + return G_SOURCE_REMOVE; + } + + bytes_received = g_socket_receive (socket, buf, sizeof (buf), NULL, &error); + + if (bytes_received < 0) { + g_warning ("[netlink] socket i/o failure: %s", error->message); + g_error_free (error); + return G_SOURCE_REMOVE; + } + + buffer_len = (unsigned int ) bytes_received; + for (hdr = (struct nlmsghdr *) buf; NLMSG_OK (hdr, buffer_len); + NLMSG_NEXT (hdr, buffer_len)) { + NetlinkTransaction *tr; + struct nlmsgerr *err; + + if (hdr->nlmsg_type != NLMSG_ERROR) + continue; + + tr = g_hash_table_lookup (transactions, + GUINT_TO_POINTER (hdr->nlmsg_seq)); + if (!tr) + continue; + + err = NLMSG_DATA (buf); + mbim_helpers_netlink_transaction_complete (tr, transactions, err->error); + } + return G_SOURCE_CONTINUE; +} + +void +mbim_helpers_netlink_set_callback (GSource **source, + GSocket *socket, + GHashTable *transactions) +{ + *source = g_socket_create_source (socket, + G_IO_IN | G_IO_ERR | G_IO_HUP, + NULL); + g_source_set_callback (*source, + (GSourceFunc) netlink_message_cb, + transactions, + NULL); + g_source_attach (*source, g_main_context_get_thread_default ()); +} diff --git a/src/libmbim-glib/mbim-helpers-netlink.h b/src/libmbim-glib/mbim-helpers-netlink.h new file mode 100644 index 0000000..3c73b32 --- /dev/null +++ b/src/libmbim-glib/mbim-helpers-netlink.h @@ -0,0 +1,98 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * libmbim-glib -- GLib/GIO based library to control MBIM devices + * + * Copyright (C) 2022 Daniele Palmas <dnlplm@gmail.com> + * + * Based on previous work: + * Copyright (C) 2020-2021 Eric Caruso <ejcaruso@chromium.org> + * Copyright (C) 2020-2021 Andrew Lassalle <andrewlassalle@chromium.org> + * Copyright (C) 2021 Aleksander Morgado <aleksander@aleksander.es> + */ + +#ifndef _LIBMBIM_GLIB_MBIM_HELPERS_NETLINK_H_ +#define _LIBMBIM_GLIB_MBIM_HELPERS_NETLINK_H_ + +#if !defined (LIBMBIM_GLIB_COMPILATION) +#error "This is a private header!!" +#endif + +#include <glib.h> +#include <gio/gio.h> + +G_BEGIN_DECLS + +typedef GByteArray NetlinkMessage; + +typedef struct { + struct nlmsghdr msghdr; + struct ifinfomsg ifreq; +} NetlinkHeader; + +G_GNUC_INTERNAL +NetlinkHeader *mbim_helpers_netlink_get_message_header (NetlinkMessage *msg); + +G_GNUC_INTERNAL +guint mbim_helpers_netlink_get_pos_of_next_attr (NetlinkMessage *msg); + +G_GNUC_INTERNAL +void mbim_helpers_netlink_append_attribute_nested (NetlinkMessage *msg, + gushort type); + +G_GNUC_INTERNAL +void mbim_helpers_netlink_append_attribute_string (NetlinkMessage *msg, + gushort type, + const gchar *value); + +G_GNUC_INTERNAL +void mbim_helpers_netlink_append_attribute_uint16 (NetlinkMessage *msg, + gushort type, + guint16 value); + +G_GNUC_INTERNAL +void mbim_helpers_netlink_append_attribute_uint32 (NetlinkMessage *msg, + gushort type, + guint32 value); + +G_GNUC_INTERNAL +NetlinkMessage *mbim_helpers_netlink_message_new (guint16 type, + guint16 extra_flags); + +G_GNUC_INTERNAL +void mbim_helpers_netlink_message_free (NetlinkMessage *msg); + +typedef struct { + guint32 sequence_id; + GSource *timeout_source; + GTask *completion_task; +} NetlinkTransaction; + +G_GNUC_INTERNAL +void mbim_helpers_netlink_transaction_complete_with_error (NetlinkTransaction *tr, + GHashTable *transactions, + GError *error); + +G_GNUC_INTERNAL +void mbim_helpers_netlink_transaction_complete (NetlinkTransaction *tr, + GHashTable *transactions, + gint saved_errno); + +G_GNUC_INTERNAL +void mbim_helpers_netlink_transaction_free (NetlinkTransaction *tr); + +G_GNUC_INTERNAL +NetlinkTransaction *mbim_helpers_netlink_transaction_new (guint *sequence_id, + GHashTable *transactions, + NetlinkMessage *msg, + guint timeout, + GTask *task); + +G_GNUC_INTERNAL +void mbim_helpers_netlink_set_callback (GSource **source, + GSocket *socket, + GHashTable *transactions); + +G_END_DECLS + +#endif /* _LIBMBIM_GLIB_MBIM_HELPERS_NETLINK_H_ */ diff --git a/src/libmbim-glib/mbim-net-port-manager.c b/src/libmbim-glib/mbim-net-port-manager.c index 032ed3f..5958660 100644 --- a/src/libmbim-glib/mbim-net-port-manager.c +++ b/src/libmbim-glib/mbim-net-port-manager.c @@ -23,6 +23,7 @@ #include "mbim-helpers.h" #include "mbim-error-types.h" #include "mbim-net-port-manager.h" +#include "mbim-helpers-netlink.h" G_DEFINE_TYPE (MbimNetPortManager, mbim_net_port_manager, G_TYPE_OBJECT) @@ -55,232 +56,6 @@ session_id_to_ifname (const gchar *ifname_prefix, } /*****************************************************************************/ -/* - * Netlink message construction functions - */ - -typedef GByteArray NetlinkMessage; - -typedef struct { - struct nlmsghdr msghdr; - struct ifinfomsg ifreq; -} NetlinkHeader; - -static NetlinkHeader * -netlink_message_header (NetlinkMessage *msg) -{ - return (NetlinkHeader *) (msg->data); -} - -static guint -get_pos_of_next_attr (NetlinkMessage *msg) -{ - return NLMSG_ALIGN (msg->len); -} - -static void -append_netlink_attribute (NetlinkMessage *msg, - gushort type, - gconstpointer value, - gushort len) -{ - guint attr_len; - guint old_len; - guint next_attr_rel_pos; - char *next_attr_abs_pos; - struct rtattr new_attr; - - /* Expand the buffer to hold the new attribute */ - attr_len = RTA_ALIGN (RTA_LENGTH (len)); - old_len = msg->len; - next_attr_rel_pos = get_pos_of_next_attr (msg); - - g_byte_array_set_size (msg, next_attr_rel_pos + attr_len); - /* fill new bytes with zero, since some padding is added between attributes. */ - memset ((char *) msg->data + old_len, 0, msg->len - old_len); - - new_attr.rta_type = type; - new_attr.rta_len = RTA_LENGTH (len); - next_attr_abs_pos = (char *) msg->data + next_attr_rel_pos; - memcpy (next_attr_abs_pos, &new_attr, sizeof (struct rtattr)); - - if (value) - memcpy (RTA_DATA (next_attr_abs_pos), value, len); - - /* Update the total netlink message length */ - netlink_message_header (msg)->msghdr.nlmsg_len = msg->len; -} - -static void -append_netlink_attribute_nested (NetlinkMessage *msg, - gushort type) -{ - append_netlink_attribute (msg, type, NULL, 0); -} - -static void -append_netlink_attribute_string (NetlinkMessage *msg, - gushort type, - const gchar *value) -{ - append_netlink_attribute (msg, type, value, strlen (value)); -} - -static void -append_netlink_attribute_uint16 (NetlinkMessage *msg, - gushort type, - guint16 value) -{ - append_netlink_attribute (msg, type, &value, sizeof (value)); -} - -static void -append_netlink_attribute_uint32 (NetlinkMessage *msg, - gushort type, - guint32 value) -{ - append_netlink_attribute (msg, type, &value, sizeof (value)); -} - -static NetlinkMessage * -netlink_message_new (guint16 type, - guint16 extra_flags) -{ - NetlinkMessage *msg; - NetlinkHeader *hdr; - - int size = sizeof (NetlinkHeader); - - msg = g_byte_array_new (); - g_byte_array_set_size (msg, size); - memset ((char *) msg->data, 0, size); - - hdr = netlink_message_header (msg); - hdr->msghdr.nlmsg_len = msg->len; - hdr->msghdr.nlmsg_type = type; - hdr->msghdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | extra_flags; - hdr->ifreq.ifi_family = AF_UNSPEC; - return msg; -} - -static void -netlink_message_free (NetlinkMessage *msg) -{ - g_byte_array_unref (msg); -} - -/*****************************************************************************/ - -typedef struct { - MbimNetPortManager *manager; - guint32 sequence_id; - GSource *timeout_source; - GTask *completion_task; -} Transaction; - -static gboolean -transaction_timed_out (Transaction *tr) -{ - GTask *task; - guint32 sequence_id; - - task = g_steal_pointer (&tr->completion_task); - sequence_id = tr->sequence_id; - - g_hash_table_remove (tr->manager->priv->transactions, - GUINT_TO_POINTER (tr->sequence_id)); - - g_task_return_new_error (task, - G_IO_ERROR, - G_IO_ERROR_TIMED_OUT, - "Netlink message with sequence ID %u timed out", - sequence_id); - - g_object_unref (task); - return G_SOURCE_REMOVE; -} - -static void -transaction_complete_with_error (Transaction *tr, - GError *error) -{ - GTask *task; - - task = g_steal_pointer (&tr->completion_task); - - g_hash_table_remove (tr->manager->priv->transactions, - GUINT_TO_POINTER (tr->sequence_id)); - - g_task_return_error (task, error); - g_object_unref (task); -} - -static void -transaction_complete (Transaction *tr, - gint saved_errno) -{ - GTask *task; - guint32 sequence_id; - - task = g_steal_pointer (&tr->completion_task); - sequence_id = tr->sequence_id; - - g_hash_table_remove (tr->manager->priv->transactions, - GUINT_TO_POINTER (tr->sequence_id)); - - if (!saved_errno) { - g_task_return_boolean (task, TRUE); - } else { - g_task_return_new_error (task, - G_IO_ERROR, - g_io_error_from_errno (saved_errno), - "Netlink message with transaction %u failed: %s", - sequence_id, - g_strerror (saved_errno)); - } - - g_object_unref (task); -} - -static void -transaction_free (Transaction *tr) -{ - g_assert (tr->completion_task == NULL); - g_source_destroy (tr->timeout_source); - g_source_unref (tr->timeout_source); - g_slice_free (Transaction, tr); -} - -static Transaction * -transaction_new (MbimNetPortManager *manager, - NetlinkMessage *msg, - guint timeout, - GTask *task) -{ - Transaction *tr; - - tr = g_slice_new0 (Transaction); - tr->manager = manager; - tr->sequence_id = ++manager->priv->current_sequence_id; - netlink_message_header (msg)->msghdr.nlmsg_seq = tr->sequence_id; - if (timeout) { - tr->timeout_source = g_timeout_source_new_seconds (timeout); - g_source_set_callback (tr->timeout_source, - (GSourceFunc) transaction_timed_out, - tr, - NULL); - g_source_attach (tr->timeout_source, - g_main_context_get_thread_default ()); - } - tr->completion_task = g_object_ref (task); - - g_hash_table_insert (manager->priv->transactions, - GUINT_TO_POINTER (tr->sequence_id), - tr); - return tr; -} - -/*****************************************************************************/ static guint session_id_to_vlan_id (guint session_id) @@ -302,19 +77,19 @@ netlink_message_new_link (guint vlan_id, guint linkinfo_pos, datainfo_pos; struct rtattr info; - msg = netlink_message_new (RTM_NEWLINK, NLM_F_CREATE | NLM_F_EXCL); - append_netlink_attribute_uint32 (msg, IFLA_LINK, base_if_index); - append_netlink_attribute_string (msg, IFLA_IFNAME, ifname); + msg = mbim_helpers_netlink_message_new (RTM_NEWLINK, NLM_F_CREATE | NLM_F_EXCL); + mbim_helpers_netlink_append_attribute_uint32 (msg, IFLA_LINK, base_if_index); + mbim_helpers_netlink_append_attribute_string (msg, IFLA_IFNAME, ifname); /* Store the position of the next attribute to adjust its length later. */ - linkinfo_pos = get_pos_of_next_attr (msg); - append_netlink_attribute_nested (msg, IFLA_LINKINFO); - append_netlink_attribute_string (msg, IFLA_INFO_KIND, VLAN_DATA_TYPE); + linkinfo_pos = mbim_helpers_netlink_get_pos_of_next_attr (msg); + mbim_helpers_netlink_append_attribute_nested (msg, IFLA_LINKINFO); + mbim_helpers_netlink_append_attribute_string (msg, IFLA_INFO_KIND, VLAN_DATA_TYPE); /* Store the position of the next attribute to adjust its length later. */ - datainfo_pos = get_pos_of_next_attr (msg); - append_netlink_attribute_nested (msg, IFLA_INFO_DATA); - append_netlink_attribute_uint16 (msg, IFLA_VLAN_ID, vlan_id); + datainfo_pos = mbim_helpers_netlink_get_pos_of_next_attr (msg); + mbim_helpers_netlink_append_attribute_nested (msg, IFLA_INFO_DATA); + mbim_helpers_netlink_append_attribute_uint16 (msg, IFLA_VLAN_ID, vlan_id); /* Use memcpy to preserve byte alignment */ memcpy (&info, (char *) msg->data + datainfo_pos, sizeof (struct rtattr)); @@ -335,8 +110,8 @@ netlink_message_del_link (guint ifindex) g_assert (ifindex != 0); - msg = netlink_message_new (RTM_DELLINK, 0); - netlink_message_header (msg)->ifreq.ifi_index = ifindex; + msg = mbim_helpers_netlink_message_new (RTM_DELLINK, 0); + mbim_helpers_netlink_get_message_header (msg)->ifreq.ifi_index = ifindex; return msg; } @@ -344,52 +119,6 @@ netlink_message_del_link (guint ifindex) /*****************************************************************************/ static gboolean -netlink_message_cb (GSocket *socket, - GIOCondition condition, - MbimNetPortManager *self) -{ - GError *error = NULL; - gchar buf[512]; - int bytes_received; - unsigned int buffer_len; - struct nlmsghdr *hdr; - - if (condition & G_IO_HUP || condition & G_IO_ERR) { - g_warning ("[netlink] socket connection closed."); - return G_SOURCE_REMOVE; - } - - bytes_received = g_socket_receive (socket, buf, sizeof (buf), NULL, &error); - - if (bytes_received < 0) { - g_warning ("[netlink] socket i/o failure: %s", error->message); - g_error_free (error); - return G_SOURCE_REMOVE; - } - - buffer_len = (unsigned int ) bytes_received; - for (hdr = (struct nlmsghdr *) buf; NLMSG_OK (hdr, buffer_len); - NLMSG_NEXT (hdr, buffer_len)) { - Transaction *tr; - struct nlmsgerr *err; - - if (hdr->nlmsg_type != NLMSG_ERROR) - continue; - - tr = g_hash_table_lookup (self->priv->transactions, - GUINT_TO_POINTER (hdr->nlmsg_seq)); - if (!tr) - continue; - - err = NLMSG_DATA (buf); - transaction_complete (tr, err->error); - } - return G_SOURCE_CONTINUE; -} - -/*****************************************************************************/ - -static gboolean get_first_free_session_id (MbimNetPortManager *self, const gchar *ifname_prefix, guint *session_id) @@ -457,13 +186,13 @@ mbim_net_port_manager_add_link (MbimNetPortManager *self, GAsyncReadyCallback callback, gpointer user_data) { - NetlinkMessage *msg; - Transaction *tr; - GTask *task; - GError *error = NULL; - gssize bytes_sent; - guint base_if_index; - AddLinkContext *ctx; + NetlinkMessage *msg; + NetlinkTransaction *tr; + GTask *task; + GError *error = NULL; + gssize bytes_sent; + guint base_if_index; + AddLinkContext *ctx; task = g_task_new (self, cancellable, callback, user_data); @@ -507,17 +236,21 @@ mbim_net_port_manager_add_link (MbimNetPortManager *self, msg = netlink_message_new_link (ctx->vlan_id, ctx->ifname, base_if_index); /* The task ownership is transferred to the transaction. */ - tr = transaction_new (self, msg, timeout, task); + tr = mbim_helpers_netlink_transaction_new (&self->priv->current_sequence_id, + self->priv->transactions, + msg, + timeout, + task); bytes_sent = g_socket_send (self->priv->socket, (const gchar *) msg->data, msg->len, cancellable, &error); - netlink_message_free (msg); + mbim_helpers_netlink_message_free (msg); if (bytes_sent < 0) - transaction_complete_with_error (tr, error); + mbim_helpers_netlink_transaction_complete_with_error (tr, self->priv->transactions, error); g_object_unref (task); } @@ -538,12 +271,12 @@ mbim_net_port_manager_del_link (MbimNetPortManager *self, GAsyncReadyCallback callback, gpointer user_data) { - guint ifindex; - NetlinkMessage *msg; - Transaction *tr; - GTask *task; - GError *error = NULL; - gssize bytes_sent; + guint ifindex; + NetlinkMessage *msg; + NetlinkTransaction *tr; + GTask *task; + GError *error = NULL; + gssize bytes_sent; task = g_task_new (self, cancellable, callback, user_data); @@ -558,17 +291,21 @@ mbim_net_port_manager_del_link (MbimNetPortManager *self, msg = netlink_message_del_link (ifindex); /* The task ownership is transferred to the transaction. */ - tr = transaction_new (self, msg, timeout, task); + tr = mbim_helpers_netlink_transaction_new (&self->priv->current_sequence_id, + self->priv->transactions, + msg, + timeout, + task); bytes_sent = g_socket_send (self->priv->socket, (const gchar *) msg->data, msg->len, cancellable, &error); - netlink_message_free (msg); + mbim_helpers_netlink_message_free (msg); if (bytes_sent < 0) - transaction_complete_with_error (tr, error); + mbim_helpers_netlink_transaction_complete_with_error (tr, self->priv->transactions, error); g_object_unref (task); } @@ -710,21 +447,15 @@ mbim_net_port_manager_new (const gchar *iface, self = g_object_new (MBIM_TYPE_NET_PORT_MANAGER, NULL); self->priv->iface = g_strdup (iface); self->priv->socket = gsocket; - self->priv->source = g_socket_create_source (self->priv->socket, - G_IO_IN | G_IO_ERR | G_IO_HUP, - NULL); - g_source_set_callback (self->priv->source, - (GSourceFunc) netlink_message_cb, - self, - NULL); - g_source_attach (self->priv->source, g_main_context_get_thread_default ()); - self->priv->current_sequence_id = 0; self->priv->transactions = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, - (GDestroyNotify) transaction_free); + (GDestroyNotify) mbim_helpers_netlink_transaction_free); + mbim_helpers_netlink_set_callback (&self->priv->source, + self->priv->socket, + self->priv->transactions); return self; } diff --git a/src/libmbim-glib/meson.build b/src/libmbim-glib/meson.build index dee6368..a182866 100644 --- a/src/libmbim-glib/meson.build +++ b/src/libmbim-glib/meson.build @@ -39,6 +39,7 @@ sources = files( 'mbim-compat.c', 'mbim-device.c', 'mbim-helpers.c', + 'mbim-helpers-netlink.c', 'mbim-message.c', 'mbim-net-port-manager.c', 'mbim-proxy.c', |