daemon: add nice value in service file to improve performance
[platform/upstream/pulseaudio.git] / src / pulsecore / iochannel.c
1 /***
2   This file is part of PulseAudio.
3
4   Copyright 2004-2006 Lennart Poettering
5   Copyright 2006-2007 Pierre Ossman <ossman@cendio.se> for Cendio AB
6
7   PulseAudio is free software; you can redistribute it and/or modify
8   it under the terms of the GNU Lesser General Public License as
9   published by the Free Software Foundation; either version 2.1 of the
10   License, or (at your option) any later version.
11
12   PulseAudio is distributed in the hope that it will be useful, but
13   WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   Lesser General Public License for more details.
16
17   You should have received a copy of the GNU Lesser General Public
18   License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <errno.h>
28
29 #ifdef HAVE_SYS_UN_H
30 #include <sys/un.h>
31 #endif
32
33 #include <pulse/xmalloc.h>
34
35 #include <pulsecore/core-error.h>
36 #include <pulsecore/core-util.h>
37 #include <pulsecore/socket.h>
38 #include <pulsecore/socket-util.h>
39 #include <pulsecore/log.h>
40 #include <pulsecore/macro.h>
41
42 #include "iochannel.h"
43
44 struct pa_iochannel {
45     int ifd, ofd;
46     int ifd_type, ofd_type;
47     pa_mainloop_api* mainloop;
48
49     pa_iochannel_cb_t callback;
50     void*userdata;
51
52     bool readable:1;
53     bool writable:1;
54     bool hungup:1;
55     bool no_close:1;
56
57     pa_io_event* input_event, *output_event;
58 };
59
60 static void callback(pa_mainloop_api* m, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata);
61
62 static void delete_events(pa_iochannel *io) {
63     pa_assert(io);
64
65     if (io->input_event)
66         io->mainloop->io_free(io->input_event);
67
68     if (io->output_event && io->output_event != io->input_event)
69         io->mainloop->io_free(io->output_event);
70
71     io->input_event = io->output_event = NULL;
72 }
73
74 static void enable_events(pa_iochannel *io) {
75     pa_assert(io);
76
77     if (io->hungup) {
78         delete_events(io);
79         return;
80     }
81
82     if (io->ifd == io->ofd && io->ifd >= 0) {
83         pa_io_event_flags_t f = PA_IO_EVENT_NULL;
84
85         if (!io->readable)
86             f |= PA_IO_EVENT_INPUT;
87         if (!io->writable)
88             f |= PA_IO_EVENT_OUTPUT;
89
90         pa_assert(io->input_event == io->output_event);
91
92         if (f != PA_IO_EVENT_NULL) {
93             if (io->input_event)
94                 io->mainloop->io_enable(io->input_event, f);
95             else
96                 io->input_event = io->output_event = io->mainloop->io_new(io->mainloop, io->ifd, f, callback, io);
97         } else
98             delete_events(io);
99
100     } else {
101
102         if (io->ifd >= 0) {
103             if (!io->readable) {
104                 if (io->input_event)
105                     io->mainloop->io_enable(io->input_event, PA_IO_EVENT_INPUT);
106                 else
107                     io->input_event = io->mainloop->io_new(io->mainloop, io->ifd, PA_IO_EVENT_INPUT, callback, io);
108             } else if (io->input_event) {
109                 io->mainloop->io_free(io->input_event);
110                 io->input_event = NULL;
111             }
112         }
113
114         if (io->ofd >= 0) {
115             if (!io->writable) {
116                 if (io->output_event)
117                     io->mainloop->io_enable(io->output_event, PA_IO_EVENT_OUTPUT);
118                 else
119                     io->output_event = io->mainloop->io_new(io->mainloop, io->ofd, PA_IO_EVENT_OUTPUT, callback, io);
120             } else if (io->output_event) {
121                 io->mainloop->io_free(io->output_event);
122                 io->output_event = NULL;
123             }
124         }
125     }
126 }
127
128 static void callback(pa_mainloop_api* m, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) {
129     pa_iochannel *io = userdata;
130     bool changed = false;
131
132     pa_assert(m);
133     pa_assert(e);
134     pa_assert(fd >= 0);
135     pa_assert(userdata);
136
137     if ((f & (PA_IO_EVENT_HANGUP|PA_IO_EVENT_ERROR)) && !io->hungup) {
138         io->hungup = true;
139         changed = true;
140     }
141
142     if ((f & PA_IO_EVENT_INPUT) && !io->readable) {
143         io->readable = true;
144         changed = true;
145         pa_assert(e == io->input_event);
146     }
147
148     if ((f & PA_IO_EVENT_OUTPUT) && !io->writable) {
149         io->writable = true;
150         changed = true;
151         pa_assert(e == io->output_event);
152     }
153
154     if (changed) {
155         enable_events(io);
156
157         if (io->callback)
158             io->callback(io, io->userdata);
159     }
160 }
161
162 pa_iochannel* pa_iochannel_new(pa_mainloop_api*m, int ifd, int ofd) {
163     pa_iochannel *io;
164
165     pa_assert(m);
166     pa_assert(ifd >= 0 || ofd >= 0);
167
168     io = pa_xnew0(pa_iochannel, 1);
169     io->ifd = ifd;
170     io->ofd = ofd;
171     io->mainloop = m;
172
173     if (io->ifd >= 0)
174         pa_make_fd_nonblock(io->ifd);
175
176     if (io->ofd >= 0 && io->ofd != io->ifd)
177         pa_make_fd_nonblock(io->ofd);
178
179     enable_events(io);
180     return io;
181 }
182
183 void pa_iochannel_free(pa_iochannel*io) {
184     pa_assert(io);
185
186     delete_events(io);
187
188     if (!io->no_close) {
189         if (io->ifd >= 0)
190             pa_close(io->ifd);
191         if (io->ofd >= 0 && io->ofd != io->ifd)
192             pa_close(io->ofd);
193     }
194
195     pa_xfree(io);
196 }
197
198 bool pa_iochannel_is_readable(pa_iochannel*io) {
199     pa_assert(io);
200
201     return io->readable || io->hungup;
202 }
203
204 bool pa_iochannel_is_writable(pa_iochannel*io) {
205     pa_assert(io);
206
207     return io->writable && !io->hungup;
208 }
209
210 bool pa_iochannel_is_hungup(pa_iochannel*io) {
211     pa_assert(io);
212
213     return io->hungup;
214 }
215
216 ssize_t pa_iochannel_write(pa_iochannel*io, const void*data, size_t l) {
217     ssize_t r;
218
219     pa_assert(io);
220     pa_assert(data);
221     pa_assert(l);
222     pa_assert(io->ofd >= 0);
223
224     r = pa_write(io->ofd, data, l, &io->ofd_type);
225
226     if ((size_t) r == l)
227         return r; /* Fast path - we almost always successfully write everything */
228
229     if (r < 0) {
230         if (errno == EAGAIN)
231             r = 0;
232         else
233             return r;
234     }
235
236     /* Partial write - let's get a notification when we can write more */
237     io->writable = io->hungup = false;
238     enable_events(io);
239
240     return r;
241 }
242
243 ssize_t pa_iochannel_read(pa_iochannel*io, void*data, size_t l) {
244     ssize_t r;
245
246     pa_assert(io);
247     pa_assert(data);
248     pa_assert(io->ifd >= 0);
249
250     if ((r = pa_read(io->ifd, data, l, &io->ifd_type)) >= 0) {
251
252         /* We also reset the hangup flag here to ensure that another
253          * IO callback is triggered so that we will again call into
254          * user code */
255         io->readable = io->hungup = false;
256         enable_events(io);
257     }
258
259     return r;
260 }
261
262 #ifdef HAVE_CREDS
263
264 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
265 typedef struct cmsgcred pa_ucred_t;
266 #define SCM_CREDENTIALS SCM_CREDS
267 #else
268 typedef struct ucred pa_ucred_t;
269 #endif
270
271 bool pa_iochannel_creds_supported(pa_iochannel *io) {
272     struct {
273         struct sockaddr sa;
274 #ifdef HAVE_SYS_UN_H
275         struct sockaddr_un un;
276 #endif
277         struct sockaddr_storage storage;
278     } sa;
279
280     socklen_t l;
281
282     pa_assert(io);
283     pa_assert(io->ifd >= 0);
284     pa_assert(io->ofd == io->ifd);
285
286     l = sizeof(sa);
287     if (getsockname(io->ifd, &sa.sa, &l) < 0)
288         return false;
289
290     return sa.sa.sa_family == AF_UNIX;
291 }
292
293 int pa_iochannel_creds_enable(pa_iochannel *io) {
294 #if !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__)
295     int t = 1;
296 #endif
297
298     pa_assert(io);
299     pa_assert(io->ifd >= 0);
300
301 #if !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__)
302     if (setsockopt(io->ifd, SOL_SOCKET, SO_PASSCRED, &t, sizeof(t)) < 0) {
303         pa_log_error("setsockopt(SOL_SOCKET, SO_PASSCRED): %s", pa_cstrerror(errno));
304         return -1;
305     }
306 #endif
307
308     return 0;
309 }
310
311 ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l, const pa_creds *ucred) {
312     ssize_t r;
313     struct msghdr mh;
314     struct iovec iov;
315     union {
316         struct cmsghdr hdr;
317         uint8_t data[CMSG_SPACE(sizeof(pa_ucred_t))];
318     } cmsg;
319     pa_ucred_t *u;
320
321     pa_assert(io);
322     pa_assert(data);
323     pa_assert(l);
324     pa_assert(io->ofd >= 0);
325
326     pa_zero(iov);
327     iov.iov_base = (void*) data;
328     iov.iov_len = l;
329
330     pa_zero(cmsg);
331     cmsg.hdr.cmsg_len = CMSG_LEN(sizeof(pa_ucred_t));
332     cmsg.hdr.cmsg_level = SOL_SOCKET;
333     cmsg.hdr.cmsg_type = SCM_CREDENTIALS;
334
335     u = (pa_ucred_t*) CMSG_DATA(&cmsg.hdr);
336
337 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
338     // the kernel fills everything
339 #else
340     u->pid = getpid();
341     if (ucred) {
342         u->uid = ucred->uid;
343         u->gid = ucred->gid;
344     } else {
345         u->uid = getuid();
346         u->gid = getgid();
347     }
348 #endif
349
350     pa_zero(mh);
351     mh.msg_iov = &iov;
352     mh.msg_iovlen = 1;
353     mh.msg_control = &cmsg;
354     mh.msg_controllen = sizeof(cmsg);
355
356     if ((r = sendmsg(io->ofd, &mh, MSG_NOSIGNAL)) >= 0) {
357         io->writable = io->hungup = false;
358         enable_events(io);
359     }
360
361     return r;
362 }
363
364 /* For more details on FD passing, check the cmsg(3) manpage
365  * and IETF RFC #2292: "Advanced Sockets API for IPv6" */
366 ssize_t pa_iochannel_write_with_fds(pa_iochannel*io, const void*data, size_t l, int nfd, const int *fds) {
367     ssize_t r;
368     int *msgdata;
369     struct msghdr mh;
370     struct iovec iov;
371     union {
372         struct cmsghdr hdr;
373         uint8_t data[CMSG_SPACE(sizeof(int) * MAX_ANCIL_DATA_FDS)];
374     } cmsg;
375
376     pa_assert(io);
377     pa_assert(data);
378     pa_assert(l);
379     pa_assert(io->ofd >= 0);
380     pa_assert(fds);
381     pa_assert(nfd > 0);
382     pa_assert(nfd <= MAX_ANCIL_DATA_FDS);
383
384     pa_zero(iov);
385     iov.iov_base = (void*) data;
386     iov.iov_len = l;
387
388     pa_zero(cmsg);
389     cmsg.hdr.cmsg_level = SOL_SOCKET;
390     cmsg.hdr.cmsg_type = SCM_RIGHTS;
391
392     msgdata = (int*) CMSG_DATA(&cmsg.hdr);
393     memcpy(msgdata, fds, nfd * sizeof(int));
394     cmsg.hdr.cmsg_len = CMSG_LEN(sizeof(int) * nfd);
395
396     pa_zero(mh);
397     mh.msg_iov = &iov;
398     mh.msg_iovlen = 1;
399     mh.msg_control = &cmsg;
400
401     /* If we followed the example on the cmsg man page, we'd use
402      * sizeof(cmsg.data) here, but if nfd < MAX_ANCIL_DATA_FDS, then the data
403      * buffer is larger than needed, and the kernel doesn't like it if we set
404      * msg_controllen to a larger than necessary value. The commit message for
405      * commit 451d1d6762 contains a longer explanation. */
406     mh.msg_controllen = CMSG_SPACE(sizeof(int) * nfd);
407
408     if ((r = sendmsg(io->ofd, &mh, MSG_NOSIGNAL)) >= 0) {
409         io->writable = io->hungup = false;
410         enable_events(io);
411     }
412     return r;
413 }
414
415 ssize_t pa_iochannel_read_with_ancil_data(pa_iochannel*io, void*data, size_t l, pa_cmsg_ancil_data *ancil_data) {
416     ssize_t r;
417     struct msghdr mh;
418     struct iovec iov;
419     union {
420         struct cmsghdr hdr;
421         uint8_t data[CMSG_SPACE(sizeof(pa_ucred_t)) + CMSG_SPACE(sizeof(int) * MAX_ANCIL_DATA_FDS)];
422     } cmsg;
423
424     pa_assert(io);
425     pa_assert(data);
426     pa_assert(l);
427     pa_assert(io->ifd >= 0);
428     pa_assert(ancil_data);
429
430     if (io->ifd_type > 0) {
431         ancil_data->creds_valid = false;
432         ancil_data->nfd = 0;
433         return pa_iochannel_read(io, data, l);
434     }
435
436     iov.iov_base = data;
437     iov.iov_len = l;
438
439     pa_zero(mh);
440     mh.msg_iov = &iov;
441     mh.msg_iovlen = 1;
442     mh.msg_control = &cmsg;
443     mh.msg_controllen = sizeof(cmsg);
444
445     if ((r = recvmsg(io->ifd, &mh, 0)) >= 0) {
446         struct cmsghdr *cmh;
447
448         ancil_data->creds_valid = false;
449         ancil_data->nfd = 0;
450
451         for (cmh = CMSG_FIRSTHDR(&mh); cmh; cmh = CMSG_NXTHDR(&mh, cmh)) {
452
453             if (cmh->cmsg_level != SOL_SOCKET)
454                 continue;
455
456             if (cmh->cmsg_type == SCM_CREDENTIALS) {
457                 pa_ucred_t u;
458                 pa_assert(cmh->cmsg_len == CMSG_LEN(sizeof(pa_ucred_t)));
459                 memcpy(&u, CMSG_DATA(cmh), sizeof(pa_ucred_t));
460 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
461                 ancil_data->creds.gid = u.cmcred_gid;
462                 ancil_data->creds.uid = u.cmcred_uid;
463 #else
464                 ancil_data->creds.gid = u.gid;
465                 ancil_data->creds.uid = u.uid;
466 #endif
467                 ancil_data->creds_valid = true;
468             }
469             else if (cmh->cmsg_type == SCM_RIGHTS) {
470                 int nfd = (cmh->cmsg_len - CMSG_LEN(0)) / sizeof(int);
471                 if (nfd > MAX_ANCIL_DATA_FDS) {
472                     int i;
473                     pa_log("Trying to receive too many file descriptors!");
474                     for (i = 0; i < nfd; i++)
475                         pa_close(((int*) CMSG_DATA(cmh))[i]);
476                     continue;
477                 }
478                 memcpy(ancil_data->fds, CMSG_DATA(cmh), nfd * sizeof(int));
479                 ancil_data->nfd = nfd;
480                 ancil_data->close_fds_on_cleanup = true;
481             }
482         }
483
484         io->readable = io->hungup = false;
485         enable_events(io);
486     }
487
488     if (r == -1 && errno == ENOTSOCK) {
489         io->ifd_type = 1;
490         return pa_iochannel_read_with_ancil_data(io, data, l, ancil_data);
491     }
492
493     return r;
494 }
495
496 #endif /* HAVE_CREDS */
497
498 void pa_iochannel_set_callback(pa_iochannel*io, pa_iochannel_cb_t _callback, void *userdata) {
499     pa_assert(io);
500
501     io->callback = _callback;
502     io->userdata = userdata;
503 }
504
505 void pa_iochannel_set_noclose(pa_iochannel*io, bool b) {
506     pa_assert(io);
507
508     io->no_close = b;
509 }
510
511 void pa_iochannel_socket_peer_to_string(pa_iochannel*io, char*s, size_t l) {
512     pa_assert(io);
513     pa_assert(s);
514     pa_assert(l);
515
516     pa_socket_peer_to_string(io->ifd, s, l);
517 }
518
519 int pa_iochannel_socket_set_rcvbuf(pa_iochannel *io, size_t l) {
520     pa_assert(io);
521
522     return pa_socket_set_rcvbuf(io->ifd, l);
523 }
524
525 int pa_iochannel_socket_set_sndbuf(pa_iochannel *io, size_t l) {
526     pa_assert(io);
527
528     return pa_socket_set_sndbuf(io->ofd, l);
529 }
530
531 pa_mainloop_api* pa_iochannel_get_mainloop_api(pa_iochannel *io) {
532     pa_assert(io);
533
534     return io->mainloop;
535 }
536
537 int pa_iochannel_get_recv_fd(pa_iochannel *io) {
538     pa_assert(io);
539
540     return io->ifd;
541 }
542
543 int pa_iochannel_get_send_fd(pa_iochannel *io) {
544     pa_assert(io);
545
546     return io->ofd;
547 }
548
549 bool pa_iochannel_socket_is_local(pa_iochannel *io) {
550     pa_assert(io);
551
552     if (pa_socket_is_local(io->ifd))
553         return true;
554
555     if (io->ifd != io->ofd)
556         if (pa_socket_is_local(io->ofd))
557             return true;
558
559     return false;
560 }