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 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
+