diff --git a/pinos/Makefile.am b/pinos/Makefile.am index 88ffdf52e..0b76adf1c 100644 --- a/pinos/Makefile.am +++ b/pinos/Makefile.am @@ -211,7 +211,6 @@ lib_LTLIBRARIES += libpinoscore-@PINOS_MAJORMINOR@.la # Pure core stuff libpinoscore_@PINOS_MAJORMINOR@_la_SOURCES = \ - server/client.c server/client.h \ server/daemon.c server/daemon.h \ server/server-node.c server/server-node.h \ server/server-port.c server/server-port.h \ diff --git a/pinos/client/client-node.c b/pinos/client/client-node.c index 553eab527..b91db0466 100644 --- a/pinos/client/client-node.c +++ b/pinos/client/client-node.c @@ -205,7 +205,7 @@ client_node_create_port (PinosNode *node, data->direction = direction; data->name = g_strdup (name); data->possible_formats = possible_formats ? g_bytes_ref (possible_formats) : NULL; - data->properties = properties ? pinos_properties_copy (properties) : NULL; + data->properties = pinos_properties_merge (pinos_node_get_properties (node), properties); g_task_set_task_data (task, data, (GDestroyNotify) create_port_data_free); @@ -365,3 +365,43 @@ pinos_client_node_get_context (PinosClientNode *node) return priv->context; } + +/** + * pinos_client_port_new: + * @node: a #PinosClientNode + * @id: an id + * @socket: a socket with the server port + * + * Create a new client port. + * + * Returns: a new client port + */ +PinosClientNode * +pinos_client_node_new (PinosContext *context, + gpointer id) +{ + PinosClientNode *node; + GDBusProxy *proxy = id; + GVariant *variant; + PinosProperties *properties = NULL; + const gchar *name = NULL; + + variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "Name"); + if (variant != NULL) { + name = g_variant_get_string (variant, NULL); + g_variant_unref (variant); + } + variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "Properties"); + if (variant != NULL) { + properties = pinos_properties_from_variant (variant); + g_variant_unref (variant); + } + + node = g_object_new (PINOS_TYPE_CLIENT_NODE, + "context", context, + "proxy", proxy, + "name", name, + "properties", properties, + NULL); + return node; +} diff --git a/pinos/client/client-node.h b/pinos/client/client-node.h index d18172341..5ef7de986 100644 --- a/pinos/client/client-node.h +++ b/pinos/client/client-node.h @@ -64,6 +64,9 @@ struct _PinosClientNodeClass { /* normal GObject stuff */ GType pinos_client_node_get_type (void); +PinosClientNode * pinos_client_node_new (PinosContext *context, + gpointer id); + PinosContext * pinos_client_node_get_context (PinosClientNode *node); G_END_DECLS diff --git a/pinos/client/context.c b/pinos/client/context.c index b018075fe..40eafe325 100644 --- a/pinos/client/context.c +++ b/pinos/client/context.c @@ -150,7 +150,6 @@ pinos_context_finalize (GObject * object) g_list_free (priv->nodes); g_list_free (priv->ports); - g_list_free (priv->clients); g_clear_object (&priv->subscribe); g_clear_error (&priv->error); @@ -377,62 +376,6 @@ context_set_state (PinosContext *context, g_error_free (error); } } -static void -on_client_proxy (GObject *source_object, - GAsyncResult *res, - gpointer user_data) -{ - PinosContext *context = user_data; - PinosContextPrivate *priv = context->priv; - GError *error = NULL; - - priv->client = pinos_subscribe_get_proxy_finish (priv->subscribe, - res, - &error); - if (priv->client == NULL) - goto client_failed; - - context_set_state (context, PINOS_CONTEXT_STATE_READY, NULL); - - return; - -client_failed: - { - g_warning ("failed to get client proxy: %s", error->message); - context_set_state (context, PINOS_STREAM_STATE_ERROR, error); - return; - } -} - -static void -on_client_connected (GObject *source_object, - GAsyncResult *res, - gpointer user_data) -{ - PinosContext *context = user_data; - PinosContextPrivate *priv = context->priv; - GVariant *ret; - GError *error = NULL; - const gchar *client_path; - - ret = g_dbus_proxy_call_finish (priv->daemon, res, &error); - if (ret == NULL) { - g_warning ("failed to connect client: %s", error->message); - context_set_state (context, PINOS_CONTEXT_STATE_ERROR, error); - return; - } - - g_variant_get (ret, "(&o)", &client_path); - - pinos_subscribe_get_proxy (priv->subscribe, - PINOS_DBUS_SERVICE, - client_path, - "org.pinos.Client1", - NULL, - on_client_proxy, - context); - g_variant_unref (ret); -} static void on_daemon_connected (GObject *source_object, @@ -440,21 +383,9 @@ on_daemon_connected (GObject *source_object, gpointer user_data) { PinosContext *context = user_data; - PinosContextPrivate *priv = context->priv; - GVariant *variant; context_set_state (context, PINOS_CONTEXT_STATE_REGISTERING, NULL); - - variant = pinos_properties_to_variant (priv->properties); - - g_dbus_proxy_call (priv->daemon, - "ConnectClient", - g_variant_new ("(@a{sv})", variant), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - on_client_connected, - context); + context_set_state (context, PINOS_CONTEXT_STATE_READY, NULL); } static void @@ -472,22 +403,6 @@ subscription_cb (PinosSubscribe *subscribe, priv->daemon = g_object_ref (object); break; - case PINOS_SUBSCRIPTION_FLAG_CLIENT: - if (event == PINOS_SUBSCRIPTION_EVENT_NEW) { - priv->clients = g_list_prepend (priv->clients, object); - } else if (event == PINOS_SUBSCRIPTION_EVENT_REMOVE) { - priv->clients = g_list_remove (priv->clients, object); - - if (object == priv->client && !priv->disconnecting) { - context_set_state (context, - PINOS_CONTEXT_STATE_ERROR, - g_error_new_literal (G_IO_ERROR, - G_IO_ERROR_CLOSED, - "Client disappeared")); - } - } - break; - case PINOS_SUBSCRIPTION_FLAG_NODE: if (event == PINOS_SUBSCRIPTION_EVENT_NEW) priv->nodes = g_list_prepend (priv->nodes, object); @@ -628,62 +543,18 @@ pinos_context_connect (PinosContext *context, } static void -finish_client_disconnect (PinosContext *context) +do_disconnect (PinosContext *context) { PinosContextPrivate *priv = context->priv; - g_clear_object (&priv->client); g_clear_object (&priv->daemon); if (priv->id) { g_bus_unwatch_name(priv->id); priv->id = 0; } - context_set_state (context, PINOS_CONTEXT_STATE_UNCONNECTED, NULL); } -static void -on_client_disconnected (GObject *source_object, - GAsyncResult *res, - gpointer user_data) -{ - PinosContext *context = user_data; - PinosContextPrivate *priv = context->priv; - GError *error = NULL; - GVariant *ret; - - priv->disconnecting = FALSE; - - ret = g_dbus_proxy_call_finish (priv->client, res, &error); - if (ret == NULL) { - g_warning ("failed to disconnect client: %s", error->message); - context_set_state (context, PINOS_CONTEXT_STATE_ERROR, error); - g_object_unref (context); - return; - } - g_variant_unref (ret); - - finish_client_disconnect (context); - g_object_unref (context); -} - -static gboolean -do_disconnect (PinosContext *context) -{ - PinosContextPrivate *priv = context->priv; - - g_dbus_proxy_call (priv->client, - "Disconnect", - g_variant_new ("()"), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - on_client_disconnected, - context); - - return FALSE; -} - /** * pinos_context_disconnect: * @context: a #PinosContext @@ -702,11 +573,6 @@ pinos_context_disconnect (PinosContext *context) priv = context->priv; g_return_val_if_fail (!priv->disconnecting, FALSE); - if (priv->client == NULL) { - finish_client_disconnect (context); - return TRUE; - } - priv->disconnecting = TRUE; g_main_context_invoke (priv->context, @@ -756,6 +622,7 @@ pinos_context_get_error (PinosContext *context) } typedef struct { + gchar *factory_name; gchar *name; PinosProperties *properties; } CreateNodeData; @@ -763,6 +630,7 @@ typedef struct { static void create_node_data_free (CreateNodeData *data) { + g_free (data->factory_name); g_free (data->name); if (data->properties) pinos_properties_free (data->properties); @@ -786,10 +654,7 @@ on_node_proxy (GObject *source_object, if (proxy == NULL) goto node_failed; - node = g_object_new (PINOS_TYPE_CLIENT_NODE, - "context", context, - "proxy", proxy, - NULL); + node = pinos_client_node_new (context, proxy); g_task_return_pointer (task, node, (GDestroyNotify) g_object_unref); g_object_unref (task); @@ -805,7 +670,6 @@ node_failed: } } - static void on_node_created (GObject *source_object, GAsyncResult *res, @@ -817,9 +681,9 @@ on_node_created (GObject *source_object, GError *error = NULL; const gchar *node_path; - g_assert (context->priv->client == G_DBUS_PROXY (source_object)); + g_assert (context->priv->daemon == G_DBUS_PROXY (source_object)); - ret = g_dbus_proxy_call_finish (context->priv->client, res, &error); + ret = g_dbus_proxy_call_finish (context->priv->daemon, res, &error); if (ret == NULL) goto create_failed; @@ -853,10 +717,11 @@ do_create_node (GTask *task) PinosContext *context = g_task_get_source_object (task); CreateNodeData *data = g_task_get_task_data (task); - g_dbus_proxy_call (context->priv->client, + g_dbus_proxy_call (context->priv->daemon, "CreateNode", - g_variant_new ("(s@a{sv})", - "client-node", + g_variant_new ("(ss@a{sv})", + data->factory_name, + data->name, pinos_properties_to_variant (data->properties)), G_DBUS_CALL_FLAGS_NONE, -1, @@ -879,16 +744,19 @@ do_create_node (GTask *task) */ void pinos_context_create_node (PinosContext *context, + const gchar *factory_name, const gchar *name, PinosProperties *properties, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { + PinosContextPrivate *priv; GTask *task; CreateNodeData *data; g_return_if_fail (PINOS_IS_CONTEXT (context)); + priv = context->priv; task = g_task_new (context, cancellable, @@ -896,8 +764,9 @@ pinos_context_create_node (PinosContext *context, user_data); data = g_slice_new (CreateNodeData); + data->factory_name = g_strdup (factory_name); data->name = g_strdup (name); - data->properties = properties ? pinos_properties_copy (properties) : NULL; + data->properties = pinos_properties_merge (priv->properties, properties); g_task_set_task_data (task, data, (GDestroyNotify) create_node_data_free); diff --git a/pinos/client/context.h b/pinos/client/context.h index 85c8f88b2..83ff7c65c 100644 --- a/pinos/client/context.h +++ b/pinos/client/context.h @@ -109,6 +109,7 @@ gboolean pinos_context_connect (PinosContext *context, Pi gboolean pinos_context_disconnect (PinosContext *context); void pinos_context_create_node (PinosContext *context, + const gchar *factory_name, const gchar *name, PinosProperties *properties, GCancellable *cancellable, diff --git a/pinos/client/introspect.c b/pinos/client/introspect.c index 041f3bc2e..06df2f0e6 100644 --- a/pinos/client/introspect.c +++ b/pinos/client/introspect.c @@ -165,114 +165,6 @@ pinos_context_get_daemon_info (PinosContext *context, g_object_unref (task); } -static void -client_fill_info (PinosClientInfo *info, GDBusProxy *proxy) -{ - GHashTable *changed = g_object_get_data (G_OBJECT (proxy), "pinos-changed-properties"); - - info->id = proxy; - info->client_path = g_dbus_proxy_get_object_path (proxy); - SET_STRING ("Sender", sender, 0); - - info->change_mask = 0; - SET_PROPERTIES ("Properties", properties, 0); - - if (changed) - g_hash_table_remove_all (changed); -} - -static void -client_clear_info (PinosClientInfo *info) -{ - if (info->properties) - pinos_properties_free (info->properties); -} - - -/** - * pinos_context_list_client_info: - * @context: a connected #PinosContext - * @flags: extra #PinosClientInfoFlags - * @cb: a #PinosClientInfoCallback - * @cancelable: a #GCancellable - * @callback: a #GAsyncReadyCallback to call when the operation is finished - * @user_data: user data passed to @cb - * - * Call @cb for each client. - */ -void -pinos_context_list_client_info (PinosContext *context, - PinosClientInfoFlags flags, - PinosClientInfoCallback cb, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - PinosContextPrivate *priv; - GList *walk; - GTask *task; - - g_return_if_fail (PINOS_IS_CONTEXT (context)); - g_return_if_fail (cb != NULL); - - task = g_task_new (context, cancellable, callback, user_data); - - priv = context->priv; - - for (walk = priv->clients; walk; walk = g_list_next (walk)) { - GDBusProxy *proxy = walk->data; - PinosClientInfo info; - - client_fill_info (&info, proxy); - cb (context, &info, user_data); - client_clear_info (&info); - } - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -/** - * pinos_context_get_client_info_by_id: - * @context: a connected #PinosContext - * @id: a client id - * @flags: extra #PinosClientInfoFlags - * @cb: a #PinosClientInfoCallback - * @cancelable: a #GCancellable - * @callback: a #GAsyncReadyCallback to call when the operation is finished - * @user_data: user data passed to @cb - * - * Call @cb for the client with @id. - */ -void -pinos_context_get_client_info_by_id (PinosContext *context, - gpointer id, - PinosClientInfoFlags flags, - PinosClientInfoCallback cb, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - PinosClientInfo info; - GDBusProxy *proxy; - GTask *task; - - g_return_if_fail (PINOS_IS_CONTEXT (context)); - g_return_if_fail (id != NULL); - g_return_if_fail (cb != NULL); - - task = g_task_new (context, cancellable, callback, user_data); - - proxy = G_DBUS_PROXY (id); - - client_fill_info (&info, proxy); - cb (context, &info, user_data); - client_clear_info (&info); - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - /** * pinos_node_state_as_string: * @state: a #PinosNodeeState @@ -299,6 +191,7 @@ node_fill_info (PinosNodeInfo *info, GDBusProxy *proxy) info->id = proxy; info->node_path = g_dbus_proxy_get_object_path (proxy); + SET_STRING ("Owner", owner, 0); info->change_mask = 0; SET_STRING ("Name", name, 0); diff --git a/pinos/client/introspect.h b/pinos/client/introspect.h index 04fb5f4ac..0a32cf02b 100644 --- a/pinos/client/introspect.h +++ b/pinos/client/introspect.h @@ -144,66 +144,11 @@ void pinos_context_get_daemon_info (PinosContext *context, GAsyncReadyCallback callback, gpointer user_data); -/** - * PinosClientInfo: - * @id: generic id of the client - * @client_path: unique path of the client - * @sender: sender of client - * @change_mask: bitfield of changed fields since last call - * @properties: extra properties - * - * The client information. Extra information can be added in later - * versions. - */ -typedef struct { - gpointer id; - const char *client_path; - const char *sender; - guint64 change_mask; - PinosProperties *properties; -} PinosClientInfo; - -/** - * PinosClientInfoFlags: - * @PINOS_CLIENT_INFO_FLAGS_NONE: no flags - * - * Extra flags for pinos_context_list_client_info() and - * pinos_context_get_client_info_by_id(). - */ -typedef enum { - PINOS_CLIENT_INFO_FLAGS_NONE = 0, -} PinosClientInfoFlags; - -/** - * PinosClientInfoCallback: - * @c: a #PinosContext - * @info: a #PinosClientInfo - * @user_data: user data - * - * Callback with information about the Pinos client in @info. - */ -typedef void (*PinosClientInfoCallback) (PinosContext *c, - const PinosClientInfo *info, - gpointer user_data); - -void pinos_context_list_client_info (PinosContext *context, - PinosClientInfoFlags flags, - PinosClientInfoCallback cb, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -void pinos_context_get_client_info_by_id (PinosContext *context, - gpointer id, - PinosClientInfoFlags flags, - PinosClientInfoCallback cb, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - /** * PinosNodeInfo: * @id: generic id of the node * @node_path: the unique path of the node + * @owner: the unique name of the owner * @change_mask: bitfield of changed fields since last call * @name: name the node, suitable for display * @properties: the properties of the node @@ -215,6 +160,7 @@ void pinos_context_get_client_info_by_id (PinosContext *context, typedef struct { gpointer id; const char *node_path; + const char *owner; guint64 change_mask; const char *name; PinosProperties *properties; diff --git a/pinos/client/port.c b/pinos/client/port.c index 6d2b4af53..52b5f64be 100644 --- a/pinos/client/port.c +++ b/pinos/client/port.c @@ -56,14 +56,16 @@ struct _PinosPortPrivate GBytes *format; PinosProperties *properties; + int fd; GSource *socket_source; PinosBuffer recv_buffer; + guint8 recv_data[MAX_BUFFER_SIZE]; - gint recv_fds[MAX_FDS]; + int recv_fds[MAX_FDS]; guint8 send_data[MAX_BUFFER_SIZE]; - gint send_fds[MAX_FDS]; + int send_fds[MAX_FDS]; PinosBuffer *buffer; PinosPort *peers[16]; @@ -463,14 +465,13 @@ read_buffer (PinosPort *port, { PinosPortPrivate *priv = port->priv; gssize len; - GInputVector ivec; PinosStackHeader *hdr; - GSocketControlMessage **messages = NULL; PinosStackBuffer *sb = (PinosStackBuffer *) &priv->recv_buffer; - gint num_messages = 0; - gint flags = 0; gsize need; - gint i; + struct cmsghdr *cmsg; + struct msghdr msg = {0}; + struct iovec iov[1]; + char cmsgbuf[CMSG_SPACE (MAX_FDS * sizeof (int))]; g_assert (sb->refcount == 0); @@ -479,28 +480,31 @@ read_buffer (PinosPort *port, sb->size = 0; sb->free_data = NULL; sb->fds = priv->recv_fds; - sb->max_fds = MAX_FDS; + sb->max_fds = 0; sb->n_fds = 0; sb->free_fds = NULL; hdr = sb->data; - /* read header first */ - ivec.buffer = hdr; - ivec.size = sizeof (PinosStackHeader); - - len = g_socket_receive_message (priv->sockets[0], - NULL, - &ivec, - 1, - &messages, - &num_messages, - &flags, - NULL, - error); - if (len == -1) - return NULL; + /* read header and control messages first */ + iov[0].iov_base = hdr; + iov[0].iov_len = sizeof (PinosStackHeader);; + msg.msg_iov = iov; + msg.msg_iovlen = 1; + msg.msg_control = cmsgbuf; + msg.msg_controllen = sizeof (cmsgbuf); + msg.msg_flags = MSG_CMSG_CLOEXEC; + while (TRUE) { + len = recvmsg (priv->fd, &msg, msg.msg_flags); + if (len < 0) { + if (errno == EINTR) + continue; + else + goto recv_error; + } + break; + } g_assert (len == sizeof (PinosStackHeader)); /* now we know the total length */ @@ -515,103 +519,94 @@ read_buffer (PinosPort *port, if (hdr->length > 0) { /* read data */ - len = g_socket_receive (priv->sockets[0], - (gchar *)sb->data + sizeof (PinosStackHeader), - hdr->length, - NULL, - error); - if (len == -1) - return NULL; - + while (TRUE) { + len = recv (priv->fd, (gchar *)sb->data + sizeof (PinosStackHeader), hdr->length, 0); + if (len < 0) { + if (errno == EINTR) + continue; + else + goto recv_error; + } + break; + } g_assert (len == hdr->length); } - if (sb->max_fds < num_messages) { - g_warning ("port %p: realloc receive fds %d -> %d", port, sb->max_fds, num_messages); - sb->max_fds = num_messages; - sb->fds = sb->free_fds = g_realloc (sb->free_fds, num_messages * sizeof (int)); - } - /* handle control messages */ - for (i = 0; i < num_messages; i++) { - GSocketControlMessage *msg = messages[i]; - gint *fds, n_fds, j; - - if (g_socket_control_message_get_msg_type (msg) != SCM_RIGHTS) + for (cmsg = CMSG_FIRSTHDR (&msg); cmsg != NULL; cmsg = CMSG_NXTHDR (&msg, cmsg)) { + if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) continue; - fds = g_unix_fd_message_steal_fds (G_UNIX_FD_MESSAGE (msg), &n_fds); - for (j = 0; j < n_fds; j++) - sb->fds[i] = fds[i]; - sb->n_fds = n_fds; - g_free (fds); - g_object_unref (msg); + sb->n_fds = (cmsg->cmsg_len - ((char *)CMSG_DATA (cmsg) - (char *)cmsg)) / sizeof (int); + memcpy (sb->fds, CMSG_DATA (cmsg), sb->n_fds * sizeof (int)); } - g_free (messages); - sb->refcount = 1; sb->magic = PSB_MAGIC; PINOS_DEBUG_TRANSPORT ("port %p: buffer %p init", &priv->recv_buffer, sb); return &priv->recv_buffer; + + /* ERRORS */ +recv_error: + { + g_set_error (error, + G_IO_ERROR, + g_io_error_from_errno (errno), + "could not recvmsg: %s", strerror (errno)); + return NULL; + } } static gboolean -write_buffer (GSocket *socket, +write_buffer (PinosPort *port, PinosBuffer *buffer, GError **error) { - gssize len; + PinosPortPrivate *priv = port->priv; PinosStackBuffer *sb = (PinosStackBuffer *) buffer; - GOutputVector ovec[1]; - GSocketControlMessage *msg = NULL; - gint n_msg, i, flags = 0; + gssize len; + struct msghdr msg = {0}; + struct iovec iov[1]; + struct cmsghdr *cmsg; + char cmsgbuf[CMSG_SPACE (MAX_FDS * sizeof (int))]; + gint fds_len = sb->n_fds * sizeof (int); - g_return_val_if_fail (buffer != NULL, FALSE); + iov[0].iov_base = sb->data; + iov[0].iov_len = sb->size; + msg.msg_iov = iov; + msg.msg_iovlen = 1; + msg.msg_control = cmsgbuf; + msg.msg_controllen = CMSG_SPACE (fds_len); + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN (fds_len); + memcpy(CMSG_DATA(cmsg), sb->fds, fds_len); + msg.msg_controllen = cmsg->cmsg_len; - ovec[0].buffer = sb->data; - ovec[0].size = sb->size; - - if (sb->n_fds) { - msg = g_unix_fd_message_new (); - for (i = 0; i < sb->n_fds; i++) { - if (!g_unix_fd_message_append_fd (G_UNIX_FD_MESSAGE (msg), sb->fds[i], error)) - goto append_failed; + while (TRUE) { + len = sendmsg (priv->fd, &msg, 0); + if (len < 0) { + if (errno == EINTR) + continue; + else + goto send_error; } - n_msg = 1; + break; } - else { - n_msg = 0; - } - - len = g_socket_send_message (socket, - NULL, - ovec, - 1, - &msg, - n_msg, - flags, - NULL, - error); - g_clear_object (&msg); - - if (len == -1) - goto send_error; - g_assert (len == (gssize) sb->size); return TRUE; -append_failed: - { - g_warning ("failed to append fd: %s", error ? (*error)->message : "unknown reason" ); - return FALSE; - } + /* ERRORS */ send_error: { - g_warning ("failed to send message: %s", error ? (*error)->message : "unknown reason" ); + g_set_error (error, + G_IO_ERROR, + g_io_error_from_errno (errno), + "could not sendmsg: %s", strerror (errno)); return FALSE; } } @@ -661,7 +656,7 @@ pinos_port_receive_buffer (PinosPort *port, if (priv->sockets[0]) { PINOS_DEBUG_TRANSPORT ("port %p: write buffer %p", port, buffer); - res = write_buffer (priv->sockets[0], buffer, error); + res = write_buffer (port, buffer, error); } else { res = TRUE; @@ -750,6 +745,7 @@ handle_socket (PinosPort *port, GSocket *socket) GMainContext *context = g_main_context_get_thread_default(); g_debug ("port %p: handle socket in context %p", port, context); + priv->fd = g_socket_get_fd (socket); priv->socket_source = g_socket_create_source (socket, G_IO_IN, NULL); g_source_set_callback (priv->socket_source, (GSourceFunc) on_socket_condition, port, NULL); g_source_attach (priv->socket_source, context); @@ -764,6 +760,7 @@ unhandle_socket (PinosPort *port) if (priv->socket_source) { g_source_destroy (priv->socket_source); g_clear_pointer (&priv->socket_source, g_source_unref); + priv->fd = -1; } } @@ -819,6 +816,7 @@ pinos_port_send_buffer (PinosPort *port, PinosPort *peer; gboolean res = TRUE; gint i; + GError *err = NULL; g_return_val_if_fail (PINOS_IS_PORT (port), FALSE); priv = port->priv; @@ -829,14 +827,20 @@ pinos_port_send_buffer (PinosPort *port, PINOS_DEBUG_TRANSPORT ("port %p: send buffer %p", port, buffer); if (priv->sockets[0]) { PINOS_DEBUG_TRANSPORT ("port %p: write buffer %p", port, buffer); - res = write_buffer (priv->sockets[0], buffer, error); + res = write_buffer (port, buffer, &err); } for (i = 0; i < priv->n_peers; i++) { peer = priv->peers[i]; if (peer == NULL) continue; - res = pinos_port_receive_buffer (peer, buffer, error); + res = pinos_port_receive_buffer (peer, buffer, &err); } + if (!res) { + if (error == NULL) + g_warning ("could not send buffer: %s", err->message); + g_propagate_error (error, err); + } + return res; } diff --git a/pinos/client/private.h b/pinos/client/private.h index 4da5cc7a2..b3456f3cc 100644 --- a/pinos/client/private.h +++ b/pinos/client/private.h @@ -33,13 +33,11 @@ struct _PinosContextPrivate GError *error; GDBusProxy *daemon; - GDBusProxy *client; gboolean disconnecting; PinosSubscriptionFlags subscription_mask; PinosSubscribe *subscribe; - GList *clients; GList *nodes; GList *ports; GList *connections; diff --git a/pinos/client/properties.c b/pinos/client/properties.c index 48d3eeeb3..fc5677f1c 100644 --- a/pinos/client/properties.c +++ b/pinos/client/properties.c @@ -82,6 +82,33 @@ pinos_properties_copy (PinosProperties *properties) return copy; } +PinosProperties * +pinos_properties_merge (PinosProperties *oldprops, + PinosProperties *newprops) +{ + PinosProperties *res = NULL; + + if (oldprops == NULL) { + if (newprops == NULL) + res = NULL; + else + res = pinos_properties_copy (newprops); + } else if (newprops == NULL) { + res = pinos_properties_copy (oldprops); + } else { + const gchar *key; + gpointer state = NULL; + + res = pinos_properties_copy (oldprops); + while ((key = pinos_properties_iterate (newprops, &state))) { + pinos_properties_set (res, + key, + pinos_properties_get (newprops, key)); + } + } + return res; +} + /** * pinos_properties_free: * @properties: a #PinosProperties diff --git a/pinos/client/properties.h b/pinos/client/properties.h index 3b3976477..545c65573 100644 --- a/pinos/client/properties.h +++ b/pinos/client/properties.h @@ -31,6 +31,8 @@ GType pinos_properties_get_type (void); PinosProperties * pinos_properties_new (const gchar *key, ...) G_GNUC_NULL_TERMINATED; PinosProperties * pinos_properties_copy (PinosProperties *properties); +PinosProperties * pinos_properties_merge (PinosProperties *oldprops, + PinosProperties *newprops); void pinos_properties_free (PinosProperties *properties); void pinos_properties_set (PinosProperties *properties, diff --git a/pinos/client/stream.c b/pinos/client/stream.c index 1685e014d..d2c36bbab 100644 --- a/pinos/client/stream.c +++ b/pinos/client/stream.c @@ -580,6 +580,7 @@ do_connect (PinosStream *stream) PinosContext *context = priv->context; pinos_context_create_node (context, + "client-node", "client-node", priv->properties, NULL, /* GCancellable *cancellable */ diff --git a/pinos/client/subscribe.c b/pinos/client/subscribe.c index 3b235df10..089d6abb7 100644 --- a/pinos/client/subscribe.c +++ b/pinos/client/subscribe.c @@ -102,9 +102,6 @@ notify_event (PinosSubscribe *subscribe, if (g_strcmp0 (interface_name, "org.pinos.Daemon1") == 0) { flags = PINOS_SUBSCRIPTION_FLAG_DAEMON; } - else if (g_strcmp0 (interface_name, "org.pinos.Client1") == 0) { - flags = PINOS_SUBSCRIPTION_FLAG_CLIENT; - } else if (g_strcmp0 (interface_name, "org.pinos.Node1") == 0) { flags = PINOS_SUBSCRIPTION_FLAG_NODE; } diff --git a/pinos/client/subscribe.h b/pinos/client/subscribe.h index 245c6ab2b..eb14a2b1a 100644 --- a/pinos/client/subscribe.h +++ b/pinos/client/subscribe.h @@ -46,12 +46,11 @@ typedef enum { typedef enum { PINOS_SUBSCRIPTION_FLAG_DAEMON = (1 << 0), - PINOS_SUBSCRIPTION_FLAG_CLIENT = (1 << 1), - PINOS_SUBSCRIPTION_FLAG_NODE = (1 << 2), - PINOS_SUBSCRIPTION_FLAG_PORT = (1 << 3) + PINOS_SUBSCRIPTION_FLAG_NODE = (1 << 1), + PINOS_SUBSCRIPTION_FLAG_PORT = (1 << 2) } PinosSubscriptionFlags; -#define PINOS_SUBSCRIPTION_FLAGS_ALL 0x0f +#define PINOS_SUBSCRIPTION_FLAGS_ALL 0x07 typedef enum { PINOS_SUBSCRIPTION_EVENT_NEW = 0, diff --git a/pinos/dbus/org.pinos.xml b/pinos/dbus/org.pinos.xml index 42c5c4c33..665863ae0 100644 --- a/pinos/dbus/org.pinos.xml +++ b/pinos/dbus/org.pinos.xml @@ -22,63 +22,21 @@ - - - - - - - - - - - - - - - - + + - - - - - - - - - +