mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-10-29 05:40:23 -04:00
iochannel/pstream/pdispatch: Add support for receiving file descriptors
The file descriptors are read from the iochannel just like the creds are. So instead of passing just creds (and creds_valid), we now pass the entire pa_ancil struct. Signed-off-by: David Henningsson <david.henningsson@canonical.com>
This commit is contained in:
parent
cc7a317e85
commit
06bc22b220
9 changed files with 84 additions and 31 deletions
|
|
@ -1780,14 +1780,14 @@ static void pstream_die_callback(pa_pstream *p, void *userdata) {
|
|||
}
|
||||
|
||||
/* Called from main context */
|
||||
static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_creds *creds, void *userdata) {
|
||||
static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_ancil *ancil, void *userdata) {
|
||||
struct userdata *u = userdata;
|
||||
|
||||
pa_assert(p);
|
||||
pa_assert(packet);
|
||||
pa_assert(u);
|
||||
|
||||
if (pa_pdispatch_run(u->pdispatch, packet, creds, u) < 0) {
|
||||
if (pa_pdispatch_run(u->pdispatch, packet, ancil, u) < 0) {
|
||||
pa_log("Invalid packet");
|
||||
pa_module_unload_request(u->module, true);
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -316,7 +316,7 @@ static void pstream_die_callback(pa_pstream *p, void *userdata) {
|
|||
pa_context_fail(c, PA_ERR_CONNECTIONTERMINATED);
|
||||
}
|
||||
|
||||
static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_creds *creds, void *userdata) {
|
||||
static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_ancil *ancil, void *userdata) {
|
||||
pa_context *c = userdata;
|
||||
|
||||
pa_assert(p);
|
||||
|
|
@ -325,7 +325,7 @@ static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_c
|
|||
|
||||
pa_context_ref(c);
|
||||
|
||||
if (pa_pdispatch_run(c->pdispatch, packet, creds, c) < 0)
|
||||
if (pa_pdispatch_run(c->pdispatch, packet, ancil, c) < 0)
|
||||
pa_context_fail(c, PA_ERR_PROTOCOL);
|
||||
|
||||
pa_context_unref(c);
|
||||
|
|
|
|||
|
|
@ -348,21 +348,26 @@ ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l
|
|||
return r;
|
||||
}
|
||||
|
||||
ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, pa_creds *creds, bool *creds_valid) {
|
||||
ssize_t pa_iochannel_read_with_ancil(pa_iochannel*io, void*data, size_t l, pa_ancil *ancil) {
|
||||
ssize_t r;
|
||||
struct msghdr mh;
|
||||
struct iovec iov;
|
||||
union {
|
||||
struct cmsghdr hdr;
|
||||
uint8_t data[CMSG_SPACE(sizeof(struct ucred))];
|
||||
uint8_t data[CMSG_SPACE(sizeof(struct ucred)) + CMSG_SPACE(sizeof(int) * MAX_ANCIL_FDS)];
|
||||
} cmsg;
|
||||
|
||||
pa_assert(io);
|
||||
pa_assert(data);
|
||||
pa_assert(l);
|
||||
pa_assert(io->ifd >= 0);
|
||||
pa_assert(creds);
|
||||
pa_assert(creds_valid);
|
||||
pa_assert(ancil);
|
||||
|
||||
if (io->ifd_type > 0) {
|
||||
ancil->creds_valid = false;
|
||||
ancil->nfd = 0;
|
||||
return pa_iochannel_read(io, data, l);
|
||||
}
|
||||
|
||||
pa_zero(iov);
|
||||
iov.iov_base = data;
|
||||
|
|
@ -378,19 +383,34 @@ ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, pa_cr
|
|||
if ((r = recvmsg(io->ifd, &mh, 0)) >= 0) {
|
||||
struct cmsghdr *cmh;
|
||||
|
||||
*creds_valid = false;
|
||||
ancil->creds_valid = false;
|
||||
ancil->nfd = 0;
|
||||
|
||||
for (cmh = CMSG_FIRSTHDR(&mh); cmh; cmh = CMSG_NXTHDR(&mh, cmh)) {
|
||||
|
||||
if (cmh->cmsg_level == SOL_SOCKET && cmh->cmsg_type == SCM_CREDENTIALS) {
|
||||
if (cmh->cmsg_level != SOL_SOCKET)
|
||||
continue;
|
||||
|
||||
if (cmh->cmsg_type == SCM_CREDENTIALS) {
|
||||
struct ucred u;
|
||||
pa_assert(cmh->cmsg_len == CMSG_LEN(sizeof(struct ucred)));
|
||||
memcpy(&u, CMSG_DATA(cmh), sizeof(struct ucred));
|
||||
|
||||
creds->gid = u.gid;
|
||||
creds->uid = u.uid;
|
||||
*creds_valid = true;
|
||||
break;
|
||||
ancil->creds.gid = u.gid;
|
||||
ancil->creds.uid = u.uid;
|
||||
ancil->creds_valid = true;
|
||||
}
|
||||
else if (cmh->cmsg_type == SCM_RIGHTS) {
|
||||
int nfd = (cmh->cmsg_len - CMSG_LEN(0)) / sizeof(int);
|
||||
if (nfd > MAX_ANCIL_FDS) {
|
||||
int i;
|
||||
pa_log("Trying to receive too many file descriptors!");
|
||||
for (i = 0; i < nfd; i++)
|
||||
pa_close(((int*) CMSG_DATA(cmh))[i]);
|
||||
continue;
|
||||
}
|
||||
memcpy(ancil->fds, CMSG_DATA(cmh), nfd * sizeof(int));
|
||||
ancil->nfd = nfd;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -398,6 +418,11 @@ ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, pa_cr
|
|||
enable_events(io);
|
||||
}
|
||||
|
||||
if (r == -1 && errno == ENOTSOCK) {
|
||||
io->ifd_type = 1;
|
||||
return pa_iochannel_read_with_ancil(io, data, l, ancil);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ bool pa_iochannel_creds_supported(pa_iochannel *io);
|
|||
int pa_iochannel_creds_enable(pa_iochannel *io);
|
||||
|
||||
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_creds(pa_iochannel*io, void*data, size_t l, pa_creds *ucred, bool *creds_valid);
|
||||
ssize_t pa_iochannel_read_with_ancil(pa_iochannel*io, void*data, size_t l, pa_ancil *ancil);
|
||||
#endif
|
||||
|
||||
bool pa_iochannel_is_readable(pa_iochannel*io);
|
||||
|
|
|
|||
|
|
@ -216,7 +216,7 @@ struct pa_pdispatch {
|
|||
PA_LLIST_HEAD(struct reply_info, replies);
|
||||
pa_pdispatch_drain_cb_t drain_callback;
|
||||
void *drain_userdata;
|
||||
const pa_creds *creds;
|
||||
const pa_ancil *ancil;
|
||||
bool use_rtclock;
|
||||
};
|
||||
|
||||
|
|
@ -286,7 +286,7 @@ static void run_action(pa_pdispatch *pd, struct reply_info *r, uint32_t command,
|
|||
pa_pdispatch_unref(pd);
|
||||
}
|
||||
|
||||
int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*packet, const pa_creds *creds, void *userdata) {
|
||||
int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*packet, const pa_ancil *ancil, void *userdata) {
|
||||
uint32_t tag, command;
|
||||
pa_tagstruct *ts = NULL;
|
||||
int ret = -1;
|
||||
|
|
@ -320,7 +320,7 @@ int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*packet, const pa_creds *creds,
|
|||
}
|
||||
#endif
|
||||
|
||||
pd->creds = creds;
|
||||
pd->ancil = ancil;
|
||||
|
||||
if (command == PA_COMMAND_ERROR || command == PA_COMMAND_REPLY) {
|
||||
struct reply_info *r;
|
||||
|
|
@ -344,7 +344,7 @@ int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*packet, const pa_creds *creds,
|
|||
ret = 0;
|
||||
|
||||
finish:
|
||||
pd->creds = NULL;
|
||||
pd->ancil = NULL;
|
||||
|
||||
if (ts)
|
||||
pa_tagstruct_free(ts);
|
||||
|
|
@ -437,5 +437,21 @@ const pa_creds * pa_pdispatch_creds(pa_pdispatch *pd) {
|
|||
pa_assert(pd);
|
||||
pa_assert(PA_REFCNT_VALUE(pd) >= 1);
|
||||
|
||||
return pd->creds;
|
||||
if (pd->ancil && pd->ancil->creds_valid)
|
||||
return &pd->ancil->creds;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const int * pa_pdispatch_fds(pa_pdispatch *pd, int *nfd) {
|
||||
pa_assert(pd);
|
||||
pa_assert(PA_REFCNT_VALUE(pd) >= 1);
|
||||
pa_assert(nfd);
|
||||
|
||||
if (pd->ancil) {
|
||||
*nfd = pd->ancil->nfd;
|
||||
return pd->ancil->fds;
|
||||
}
|
||||
|
||||
*nfd = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ pa_pdispatch* pa_pdispatch_new(pa_mainloop_api *m, bool use_rtclock, const pa_pd
|
|||
void pa_pdispatch_unref(pa_pdispatch *pd);
|
||||
pa_pdispatch* pa_pdispatch_ref(pa_pdispatch *pd);
|
||||
|
||||
int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*p, const pa_creds *creds, void *userdata);
|
||||
int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*p, const pa_ancil *ancil, void *userdata);
|
||||
|
||||
void pa_pdispatch_register_reply(pa_pdispatch *pd, uint32_t tag, int timeout, pa_pdispatch_cb_t callback, void *userdata, pa_free_cb_t free_cb);
|
||||
|
||||
|
|
@ -54,4 +54,6 @@ void pa_pdispatch_unregister_reply(pa_pdispatch *pd, void *userdata);
|
|||
|
||||
const pa_creds * pa_pdispatch_creds(pa_pdispatch *pd);
|
||||
|
||||
const int * pa_pdispatch_fds(pa_pdispatch *pd, int *nfd);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -4816,14 +4816,14 @@ static void command_set_port_latency_offset(pa_pdispatch *pd, uint32_t command,
|
|||
|
||||
/*** pstream callbacks ***/
|
||||
|
||||
static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_creds *creds, void *userdata) {
|
||||
static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_ancil *ancil, void *userdata) {
|
||||
pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
|
||||
|
||||
pa_assert(p);
|
||||
pa_assert(packet);
|
||||
pa_native_connection_assert_ref(c);
|
||||
|
||||
if (pa_pdispatch_run(c->pdispatch, packet, creds, c) < 0) {
|
||||
if (pa_pdispatch_run(c->pdispatch, packet, ancil, c) < 0) {
|
||||
pa_log("invalid packet.");
|
||||
native_connection_unlink(c);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -165,8 +165,9 @@ struct pa_pstream {
|
|||
pa_mempool *mempool;
|
||||
|
||||
#ifdef HAVE_CREDS
|
||||
pa_creds read_creds, write_creds;
|
||||
bool read_creds_valid, send_creds_now;
|
||||
pa_ancil read_ancil;
|
||||
pa_creds write_creds;
|
||||
bool send_creds_now;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
@ -646,12 +647,20 @@ static int do_read(pa_pstream *p) {
|
|||
|
||||
#ifdef HAVE_CREDS
|
||||
{
|
||||
bool b = 0;
|
||||
pa_ancil b;
|
||||
|
||||
if ((r = pa_iochannel_read_with_creds(p->io, d, l, &p->read_creds, &b)) <= 0)
|
||||
if ((r = pa_iochannel_read_with_ancil(p->io, d, l, &b)) <= 0)
|
||||
goto fail;
|
||||
|
||||
p->read_creds_valid = p->read_creds_valid || b;
|
||||
if (b.creds_valid) {
|
||||
p->read_ancil.creds_valid = true;
|
||||
p->read_ancil.creds = b.creds;
|
||||
}
|
||||
if (b.nfd > 0) {
|
||||
pa_assert(b.nfd <= MAX_ANCIL_FDS);
|
||||
p->read_ancil.nfd = b.nfd;
|
||||
memcpy(p->read_ancil.fds, b.fds, sizeof(int) * b.nfd);
|
||||
}
|
||||
}
|
||||
#else
|
||||
if ((r = pa_iochannel_read(p->io, d, l)) <= 0)
|
||||
|
|
@ -799,7 +808,7 @@ static int do_read(pa_pstream *p) {
|
|||
|
||||
if (p->receive_packet_callback)
|
||||
#ifdef HAVE_CREDS
|
||||
p->receive_packet_callback(p, p->read.packet, p->read_creds_valid ? &p->read_creds : NULL, p->receive_packet_callback_userdata);
|
||||
p->receive_packet_callback(p, p->read.packet, &p->read_ancil, p->receive_packet_callback_userdata);
|
||||
#else
|
||||
p->receive_packet_callback(p, p->read.packet, NULL, p->receive_packet_callback_userdata);
|
||||
#endif
|
||||
|
|
@ -860,7 +869,8 @@ frame_done:
|
|||
p->read.data = NULL;
|
||||
|
||||
#ifdef HAVE_CREDS
|
||||
p->read_creds_valid = false;
|
||||
p->read_ancil.creds_valid = false;
|
||||
p->read_ancil.nfd = 0;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
|
||||
typedef struct pa_pstream pa_pstream;
|
||||
|
||||
typedef void (*pa_pstream_packet_cb_t)(pa_pstream *p, pa_packet *packet, const pa_creds *creds, void *userdata);
|
||||
typedef void (*pa_pstream_packet_cb_t)(pa_pstream *p, pa_packet *packet, const pa_ancil *ancil, void *userdata);
|
||||
typedef void (*pa_pstream_memblock_cb_t)(pa_pstream *p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk, void *userdata);
|
||||
typedef void (*pa_pstream_notify_cb_t)(pa_pstream *p, void *userdata);
|
||||
typedef void (*pa_pstream_block_id_cb_t)(pa_pstream *p, uint32_t block_id, void *userdata);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue