[pulseaudio-discuss] [PATCH 03/12] iochannel/pstream: Support sending file descriptors
David Henningsson
david.henningsson at canonical.com
Fri May 30 04:59:22 PDT 2014
This patch adds support to iochannel, pstream and pstream-util
to send file descriptors over a unix pipe.
Currently we don't support writing both creds and fds in the same
packet, it's either one or the other (or neither).
Signed-off-by: David Henningsson <david.henningsson at canonical.com>
---
src/pulsecore/iochannel.c | 43 +++++++++++++++++++++++++++++++++++++++++
src/pulsecore/iochannel.h | 1 +
src/pulsecore/pstream-util.c | 31 +++++++++++++++++++++++++++--
src/pulsecore/pstream-util.h | 1 +
src/pulsecore/pstream.c | 46 ++++++++++++++++++++++++++------------------
src/pulsecore/pstream.h | 2 +-
6 files changed, 102 insertions(+), 22 deletions(-)
diff --git a/src/pulsecore/iochannel.c b/src/pulsecore/iochannel.c
index 4f9eca7..f4006b5 100644
--- a/src/pulsecore/iochannel.c
+++ b/src/pulsecore/iochannel.c
@@ -348,6 +348,49 @@ ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l
return r;
}
+ssize_t pa_iochannel_write_with_fds(pa_iochannel*io, const void*data, size_t l, int nfd, const int *fds) {
+ ssize_t r;
+ int *msgdata;
+ struct msghdr mh;
+ struct iovec iov;
+ union {
+ struct cmsghdr hdr;
+ uint8_t data[CMSG_SPACE(sizeof(int) * MAX_ANCIL_FDS)];
+ } cmsg;
+
+ pa_assert(io);
+ pa_assert(data);
+ pa_assert(l);
+ pa_assert(io->ofd >= 0);
+ pa_assert(fds);
+ pa_assert(nfd > 0);
+ pa_assert(nfd <= MAX_ANCIL_FDS);
+
+ pa_zero(iov);
+ iov.iov_base = (void*) data;
+ iov.iov_len = l;
+
+ pa_zero(cmsg);
+ cmsg.hdr.cmsg_level = SOL_SOCKET;
+ cmsg.hdr.cmsg_type = SCM_RIGHTS;
+
+ msgdata = (int*) CMSG_DATA(&cmsg.hdr);
+ memcpy(msgdata, fds, nfd * sizeof(int));
+ cmsg.hdr.cmsg_len = CMSG_LEN(sizeof(int) * nfd);
+
+ pa_zero(mh);
+ mh.msg_iov = &iov;
+ mh.msg_iovlen = 1;
+ mh.msg_control = &cmsg;
+ mh.msg_controllen = sizeof(cmsg);
+
+ if ((r = sendmsg(io->ofd, &mh, MSG_NOSIGNAL)) >= 0) {
+ io->writable = io->hungup = false;
+ enable_events(io);
+ }
+ return r;
+}
+
ssize_t pa_iochannel_read_with_ancil(pa_iochannel*io, void*data, size_t l, pa_ancil *ancil) {
ssize_t r;
struct msghdr mh;
diff --git a/src/pulsecore/iochannel.h b/src/pulsecore/iochannel.h
index 4da8902..390f798 100644
--- a/src/pulsecore/iochannel.h
+++ b/src/pulsecore/iochannel.h
@@ -57,6 +57,7 @@ ssize_t pa_iochannel_read(pa_iochannel*io, void*data, size_t l);
bool pa_iochannel_creds_supported(pa_iochannel *io);
int pa_iochannel_creds_enable(pa_iochannel *io);
+ssize_t pa_iochannel_write_with_fds(pa_iochannel*io, const void*data, size_t l, int nfd, const int *fds);
ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l, const pa_creds *ucred);
ssize_t pa_iochannel_read_with_ancil(pa_iochannel*io, void*data, size_t l, pa_ancil *ancil);
#endif
diff --git a/src/pulsecore/pstream-util.c b/src/pulsecore/pstream-util.c
index f84f486..ac256e2 100644
--- a/src/pulsecore/pstream-util.c
+++ b/src/pulsecore/pstream-util.c
@@ -28,7 +28,7 @@
#include "pstream-util.h"
-void pa_pstream_send_tagstruct_with_creds(pa_pstream *p, pa_tagstruct *t, const pa_creds *creds) {
+static void pa_pstream_send_tagstruct_with_ancil(pa_pstream *p, pa_tagstruct *t, const pa_ancil *ancil) {
size_t length;
uint8_t *data;
pa_packet *packet;
@@ -38,10 +38,37 @@ void pa_pstream_send_tagstruct_with_creds(pa_pstream *p, pa_tagstruct *t, const
pa_assert_se(data = pa_tagstruct_free_data(t, &length));
pa_assert_se(packet = pa_packet_new_dynamic(data, length));
- pa_pstream_send_packet(p, packet, creds);
+ pa_pstream_send_packet(p, packet, ancil);
pa_packet_unref(packet);
}
+void pa_pstream_send_tagstruct_with_creds(pa_pstream *p, pa_tagstruct *t, const pa_creds *creds) {
+ if (creds) {
+ pa_ancil a;
+
+ a.nfd = 0;
+ a.creds_valid = true;
+ a.creds = *creds;
+ pa_pstream_send_tagstruct_with_ancil(p, t, &a);
+ }
+ else
+ pa_pstream_send_tagstruct_with_ancil(p, t, NULL);
+}
+
+void pa_pstream_send_tagstruct_with_fds(pa_pstream *p, pa_tagstruct *t, int nfd, const int *fds) {
+ if (nfd > 0) {
+ pa_ancil a;
+
+ a.nfd = nfd;
+ a.creds_valid = false;
+ pa_assert(nfd <= MAX_ANCIL_FDS);
+ memcpy(a.fds, fds, sizeof(int) * nfd);
+ pa_pstream_send_tagstruct_with_ancil(p, t, &a);
+ }
+ else
+ pa_pstream_send_tagstruct_with_ancil(p, t, NULL);
+}
+
void pa_pstream_send_error(pa_pstream *p, uint32_t tag, uint32_t error) {
pa_tagstruct *t;
diff --git a/src/pulsecore/pstream-util.h b/src/pulsecore/pstream-util.h
index ae0d79c..7ea89ba 100644
--- a/src/pulsecore/pstream-util.h
+++ b/src/pulsecore/pstream-util.h
@@ -29,6 +29,7 @@
/* The tagstruct is freed!*/
void pa_pstream_send_tagstruct_with_creds(pa_pstream *p, pa_tagstruct *t, const pa_creds *creds);
+void pa_pstream_send_tagstruct_with_fds(pa_pstream *p, pa_tagstruct *t, int nfd, const int *fds);
#define pa_pstream_send_tagstruct(p, t) pa_pstream_send_tagstruct_with_creds((p), (t), NULL)
diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c
index a3afed5..22ea250 100644
--- a/src/pulsecore/pstream.c
+++ b/src/pulsecore/pstream.c
@@ -94,8 +94,8 @@ struct item_info {
/* packet info */
pa_packet *packet;
#ifdef HAVE_CREDS
- bool with_creds;
- pa_creds creds;
+ bool with_ancil;
+ pa_ancil ancil;
#endif
/* memblock info */
@@ -165,9 +165,8 @@ struct pa_pstream {
pa_mempool *mempool;
#ifdef HAVE_CREDS
- pa_ancil read_ancil;
- pa_creds write_creds;
- bool send_creds_now;
+ pa_ancil read_ancil, write_ancil;
+ bool send_ancil_now;
#endif
};
@@ -298,7 +297,7 @@ static void pstream_free(pa_pstream *p) {
pa_xfree(p);
}
-void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const pa_creds *creds) {
+void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const pa_ancil *ancil) {
struct item_info *i;
pa_assert(p);
@@ -315,8 +314,13 @@ void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const pa_creds *cre
i->packet = pa_packet_ref(packet);
#ifdef HAVE_CREDS
- if ((i->with_creds = !!creds))
- i->creds = *creds;
+ if ((i->with_ancil = !!ancil)) {
+ i->ancil = *ancil;
+ if (ancil->creds_valid)
+ pa_assert(ancil->nfd == 0);
+ else
+ pa_assert(ancil->nfd > 0);
+ }
#endif
pa_queue_push(p->send_queue, i);
@@ -358,7 +362,7 @@ void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa
i->offset = offset;
i->seek_mode = seek_mode;
#ifdef HAVE_CREDS
- i->with_creds = false;
+ i->with_ancil = false;
#endif
pa_queue_push(p->send_queue, i);
@@ -385,7 +389,7 @@ void pa_pstream_send_release(pa_pstream *p, uint32_t block_id) {
item->type = PA_PSTREAM_ITEM_SHMRELEASE;
item->block_id = block_id;
#ifdef HAVE_CREDS
- item->with_creds = false;
+ item->with_ancil = false;
#endif
pa_queue_push(p->send_queue, item);
@@ -422,7 +426,7 @@ void pa_pstream_send_revoke(pa_pstream *p, uint32_t block_id) {
item->type = PA_PSTREAM_ITEM_SHMREVOKE;
item->block_id = block_id;
#ifdef HAVE_CREDS
- item->with_creds = false;
+ item->with_ancil = false;
#endif
pa_queue_push(p->send_queue, item);
@@ -536,8 +540,8 @@ static void prepare_next_write_item(pa_pstream *p) {
}
#ifdef HAVE_CREDS
- if ((p->send_creds_now = p->write.current->with_creds))
- p->write_creds = p->write.current->creds;
+ if ((p->send_ancil_now = p->write.current->with_ancil))
+ p->write_ancil = p->write.current->ancil;
#endif
}
@@ -579,12 +583,16 @@ static int do_write(pa_pstream *p) {
pa_assert(l > 0);
#ifdef HAVE_CREDS
- if (p->send_creds_now) {
-
- if ((r = pa_iochannel_write_with_creds(p->io, d, l, &p->write_creds)) < 0)
- goto fail;
-
- p->send_creds_now = false;
+ if (p->send_ancil_now) {
+ if (p->write_ancil.creds_valid) {
+ pa_assert(p->write_ancil.nfd == 0);
+ if ((r = pa_iochannel_write_with_creds(p->io, d, l, &p->write_ancil.creds)) < 0)
+ goto fail;
+ }
+ else
+ if ((r = pa_iochannel_write_with_fds(p->io, d, l, p->write_ancil.nfd, p->write_ancil.fds)) < 0)
+ goto fail;
+ p->send_ancil_now = false;
} else
#endif
diff --git a/src/pulsecore/pstream.h b/src/pulsecore/pstream.h
index 9316d92..4961570 100644
--- a/src/pulsecore/pstream.h
+++ b/src/pulsecore/pstream.h
@@ -49,7 +49,7 @@ void pa_pstream_unref(pa_pstream*p);
void pa_pstream_unlink(pa_pstream *p);
-void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const pa_creds *creds);
+void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const pa_ancil *ancil);
void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk);
void pa_pstream_send_release(pa_pstream *p, uint32_t block_id);
void pa_pstream_send_revoke(pa_pstream *p, uint32_t block_id);
--
1.9.1
More information about the pulseaudio-discuss
mailing list