1 /*
2  *  ALSA server
3  *  Copyright (c) by Abramo Bagnara <abramo@alsa-project.org>
4  *
5  *   This program is free software; you can redistribute it and/or modify
6  *   it under the terms of the GNU General Public License as published by
7  *   the Free Software Foundation; either version 2 of the License, or
8  *   (at your option) any later version.
9  *
10  *   This program is distributed in the hope that it will be useful,
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *   GNU General Public License for more details.
14  *
15  *   You should have received a copy of the GNU General Public License
16  *   along with this program; if not, write to the Free Software
17  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18  *
19  */
20 
21 #include "aserver.h"
22 
23 #include <sys/shm.h>
24 #include <sys/socket.h>
25 #include <poll.h>
26 #include <sys/un.h>
27 #include <sys/uio.h>
28 #include <stdio.h>
29 #include <unistd.h>
30 #include <fcntl.h>
31 #include <stddef.h>
32 #include <getopt.h>
33 #include <netinet/in.h>
34 #include <netdb.h>
35 #include <limits.h>
36 #include <signal.h>
37 
38 
39 char *command;
40 
41 #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)
42 #define ERROR(...) do {\
43 	fprintf(stderr, "%s %s:%i:(%s) ", command, __FILE__, __LINE__, __func__); \
44 	fprintf(stderr, __VA_ARGS__); \
45 	putc('\n', stderr); \
46 } while (0)
47 #else
48 #define ERROR(args...) do {\
49 	fprintf(stderr, "%s %s:%i:(%s) ", command, __FILE__, __LINE__, __func__); \
50 	fprintf(stderr, ##args); \
51 	putc('\n', stderr); \
52 } while (0)
53 #endif
54 
55 #define SYSERROR(string) ERROR(string ": %s", strerror(errno))
56 
make_local_socket(const char *filename)57 static int make_local_socket(const char *filename)
58 {
59 	size_t l = strlen(filename);
60 	size_t size = offsetof(struct sockaddr_un, sun_path) + l;
61 	struct sockaddr_un *addr = alloca(size);
62 	int sock;
63 
64 	sock = socket(PF_LOCAL, SOCK_STREAM, 0);
65 	if (sock < 0) {
66 		int result = -errno;
67 		SYSERROR("socket failed");
68 		return result;
69 	}
70 
71 	unlink(filename);
72 
73 	addr->sun_family = AF_LOCAL;
74 	memcpy(addr->sun_path, filename, l);
75 
76 	if (bind(sock, (struct sockaddr *) addr, size) < 0) {
77 		int result = -errno;
78 		SYSERROR("bind failed");
79 		close(sock);
80 		return result;
81 	}
82 
83 	return sock;
84 }
85 
make_inet_socket(int port)86 static int make_inet_socket(int port)
87 {
88 	struct sockaddr_in addr;
89 	int sock;
90 
91 	sock = socket(PF_INET, SOCK_STREAM, 0);
92 	if (sock < 0) {
93 		int result = -errno;
94 		SYSERROR("socket failed");
95 		return result;
96 	}
97 
98 	memset(&addr, 0, sizeof(addr));
99 	addr.sin_family = AF_INET;
100 	addr.sin_port = htons(port);
101 	addr.sin_addr.s_addr = INADDR_ANY;
102 
103 	if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
104 		int result = -errno;
105 		SYSERROR("bind failed");
106 		close(sock);
107 		return result;
108 	}
109 
110 	return sock;
111 }
112 
113 struct pollfd *pollfds;
114 unsigned int pollfds_count = 0;
115 typedef struct waiter waiter_t;
116 typedef int (*waiter_handler_t)(waiter_t *waiter, unsigned short events);
117 struct waiter {
118 	int fd;
119 	void *private_data;
120 	waiter_handler_t handler;
121 };
122 waiter_t *waiters;
123 
add_waiter(int fd, unsigned short events, waiter_handler_t handler, void *data)124 static void add_waiter(int fd, unsigned short events, waiter_handler_t handler,
125 		void *data)
126 {
127 	waiter_t *w = &waiters[fd];
128 	struct pollfd *pfd = &pollfds[pollfds_count];
129 	assert(!w->handler);
130 	pfd->fd = fd;
131 	pfd->events = events;
132 	pfd->revents = 0;
133 	w->fd = fd;
134 	w->private_data = data;
135 	w->handler = handler;
136 	pollfds_count++;
137 }
138 
del_waiter(int fd)139 static void del_waiter(int fd)
140 {
141 	waiter_t *w = &waiters[fd];
142 	unsigned int k;
143 	assert(w->handler);
144 	w->handler = 0;
145 	for (k = 0; k < pollfds_count; ++k) {
146 		if (pollfds[k].fd == fd)
147 			break;
148 	}
149 	assert(k < pollfds_count);
150 	pollfds_count--;
151 	memmove(&pollfds[k], &pollfds[k + 1], pollfds_count - k);
152 }
153 
154 typedef struct client client_t;
155 
156 typedef struct {
157 	int (*open)(client_t *client, int *cookie);
158 	int (*cmd)(client_t *client);
159 	int (*close)(client_t *client);
160 } transport_ops_t;
161 
162 struct client {
163 	struct list_head list;
164 	int poll_fd;
165 	int ctrl_fd;
166 	int local;
167 	int transport_type;
168 	int dev_type;
169 	char name[256];
170 	int stream;
171 	int mode;
172 	transport_ops_t *ops;
173 	snd_async_handler_t *async_handler;
174 	int async_sig;
175 	pid_t async_pid;
176 	union {
177 		struct {
178 			snd_pcm_t *handle;
179 			int fd;
180 		} pcm;
181 		struct {
182 			snd_ctl_t *handle;
183 			int fd;
184 		} ctl;
185 #if 0
186 		struct {
187 			snd_rawmidi_t *handle;
188 		} rawmidi;
189 		struct {
190 			snd_timer_open_t *handle;
191 		} timer;
192 		struct {
193 			snd_hwdep_t *handle;
194 		} hwdep;
195 		struct {
196 			snd_seq_t *handle;
197 		} seq;
198 #endif
199 	} device;
200 	int polling;
201 	int open;
202 	int cookie;
203 	union {
204 		struct {
205 			int ctrl_id;
206 			void *ctrl;
207 		} shm;
208 	} transport;
209 };
210 
211 LIST_HEAD(clients);
212 
213 typedef struct {
214 	struct list_head list;
215 	int fd;
216 	uint32_t cookie;
217 } inet_pending_t;
218 LIST_HEAD(inet_pendings);
219 
220 #if 0
221 static int pcm_handler(waiter_t *waiter, unsigned short events)
222 {
223 	client_t *client = waiter->private_data;
224 	char buf[1];
225 	ssize_t n;
226 	if (events & POLLIN) {
227 		n = write(client->poll_fd, buf, 1);
228 		if (n != 1) {
229 			SYSERROR("write failed");
230 			return -errno;
231 		}
232 	} else if (events & POLLOUT) {
233 		n = read(client->poll_fd, buf, 1);
234 		if (n != 1) {
235 			SYSERROR("read failed");
236 			return -errno;
237 		}
238 	}
239 	del_waiter(waiter->fd);
240 	client->polling = 0;
241 	return 0;
242 }
243 #endif
244 
pcm_shm_hw_ptr_changed(snd_pcm_t *pcm, snd_pcm_t *src ATTRIBUTE_UNUSED)245 static void pcm_shm_hw_ptr_changed(snd_pcm_t *pcm, snd_pcm_t *src ATTRIBUTE_UNUSED)
246 {
247 	client_t *client = pcm->hw.private_data;
248 	volatile snd_pcm_shm_ctrl_t *ctrl = client->transport.shm.ctrl;
249 	snd_pcm_t *loop;
250 
251 	ctrl->hw.changed = 1;
252 	if (pcm->hw.fd >= 0) {
253 		ctrl->hw.use_mmap = 1;
254 		ctrl->hw.offset = pcm->hw.offset;
255 		return;
256 	}
257 	ctrl->hw.use_mmap = 0;
258 	ctrl->hw.ptr = pcm->hw.ptr ? *pcm->hw.ptr : 0;
259 	for (loop = pcm->hw.master; loop; loop = loop->hw.master)
260 		loop->hw.ptr = &ctrl->hw.ptr;
261 	pcm->hw.ptr = &ctrl->hw.ptr;
262 }
263 
pcm_shm_appl_ptr_changed(snd_pcm_t *pcm, snd_pcm_t *src ATTRIBUTE_UNUSED)264 static void pcm_shm_appl_ptr_changed(snd_pcm_t *pcm, snd_pcm_t *src ATTRIBUTE_UNUSED)
265 {
266 	client_t *client = pcm->appl.private_data;
267 	volatile snd_pcm_shm_ctrl_t *ctrl = client->transport.shm.ctrl;
268 	snd_pcm_t *loop;
269 
270 	ctrl->appl.changed = 1;
271 	if (pcm->appl.fd >= 0) {
272 		ctrl->appl.use_mmap = 1;
273 		ctrl->appl.offset = pcm->appl.offset;
274 		return;
275 	}
276 	ctrl->appl.use_mmap = 0;
277 	ctrl->appl.ptr = pcm->appl.ptr ? *pcm->appl.ptr : 0;
278 	for (loop = pcm->appl.master; loop; loop = loop->appl.master)
279 		loop->appl.ptr = &ctrl->appl.ptr;
280 	pcm->appl.ptr = &ctrl->appl.ptr;
281 }
282 
pcm_shm_open(client_t *client, int *cookie)283 static int pcm_shm_open(client_t *client, int *cookie)
284 {
285 	int shmid;
286 	snd_pcm_t *pcm;
287 	int err;
288 	int result;
289 	err = snd_pcm_open(&pcm, client->name, client->stream, SND_PCM_NONBLOCK);
290 	if (err < 0)
291 		return err;
292 	client->device.pcm.handle = pcm;
293 	client->device.pcm.fd = _snd_pcm_poll_descriptor(pcm);
294 	pcm->hw.private_data = client;
295 	pcm->hw.changed = pcm_shm_hw_ptr_changed;
296 	pcm->appl.private_data = client;
297 	pcm->appl.changed = pcm_shm_appl_ptr_changed;
298 
299 	shmid = shmget(IPC_PRIVATE, PCM_SHM_SIZE, 0666);
300 	if (shmid < 0) {
301 		result = -errno;
302 		SYSERROR("shmget failed");
303 		goto _err;
304 	}
305 	client->transport.shm.ctrl_id = shmid;
306 	client->transport.shm.ctrl = shmat(shmid, 0, 0);
307 	if (client->transport.shm.ctrl == (void*) -1) {
308 		result = -errno;
309 		shmctl(shmid, IPC_RMID, 0);
310 		SYSERROR("shmat failed");
311 		goto _err;
312 	}
313 	*cookie = shmid;
314 	return 0;
315 
316  _err:
317 	snd_pcm_close(pcm);
318 	return result;
319 
320 }
321 
pcm_shm_close(client_t *client)322 static int pcm_shm_close(client_t *client)
323 {
324 	int err;
325 	snd_pcm_shm_ctrl_t *ctrl = client->transport.shm.ctrl;
326 	if (client->polling) {
327 		del_waiter(client->device.pcm.fd);
328 		client->polling = 0;
329 	}
330 	err = snd_pcm_close(client->device.pcm.handle);
331 	ctrl->result = err;
332 	if (err < 0)
333 		ERROR("snd_pcm_close");
334 	if (client->transport.shm.ctrl) {
335 		err = shmdt((void *)client->transport.shm.ctrl);
336 		if (err < 0)
337 			SYSERROR("shmdt failed");
338 		err = shmctl(client->transport.shm.ctrl_id, IPC_RMID, 0);
339 		if (err < 0)
340 			SYSERROR("shmctl IPC_RMID failed");
341 		client->transport.shm.ctrl = 0;
342 	}
343 	client->open = 0;
344 	return 0;
345 }
346 
shm_ack(client_t *client)347 static int shm_ack(client_t *client)
348 {
349 	struct pollfd pfd;
350 	int err;
351 	char buf[1];
352 	pfd.fd = client->ctrl_fd;
353 	pfd.events = POLLHUP;
354 	if (poll(&pfd, 1, 0) == 1)
355 		return -EBADFD;
356 	err = write(client->ctrl_fd, buf, 1);
357 	if (err != 1)
358 		return -EBADFD;
359 	return 0;
360 }
361 
shm_ack_fd(client_t *client, int fd)362 static int shm_ack_fd(client_t *client, int fd)
363 {
364 	struct pollfd pfd;
365 	int err;
366 	char buf[1];
367 	pfd.fd = client->ctrl_fd;
368 	pfd.events = POLLHUP;
369 	if (poll(&pfd, 1, 0) == 1)
370 		return -EBADFD;
371 	err = snd_send_fd(client->ctrl_fd, buf, 1, fd);
372 	if (err != 1)
373 		return -EBADFD;
374 	return 0;
375 }
376 
shm_rbptr_fd(client_t *client, snd_pcm_rbptr_t *rbptr)377 static int shm_rbptr_fd(client_t *client, snd_pcm_rbptr_t *rbptr)
378 {
379 	if (rbptr->fd < 0)
380 		return -EINVAL;
381 	return shm_ack_fd(client, rbptr->fd);
382 }
383 
async_handler(snd_async_handler_t *handler)384 static void async_handler(snd_async_handler_t *handler)
385 {
386 	client_t *client = snd_async_handler_get_callback_private(handler);
387 	/* FIXME: use sigqueue */
388 	kill(client->async_pid, client->async_sig);
389 }
390 
pcm_shm_cmd(client_t *client)391 static int pcm_shm_cmd(client_t *client)
392 {
393 	volatile snd_pcm_shm_ctrl_t *ctrl = client->transport.shm.ctrl;
394 	char buf[1];
395 	int err;
396 	int cmd;
397 	snd_pcm_t *pcm;
398 	err = read(client->ctrl_fd, buf, 1);
399 	if (err != 1)
400 		return -EBADFD;
401 	cmd = ctrl->cmd;
402 	ctrl->cmd = 0;
403 	pcm = client->device.pcm.handle;
404 	switch (cmd) {
405 	case SND_PCM_IOCTL_ASYNC:
406 		ctrl->result = snd_pcm_async(pcm, ctrl->u.async.sig, ctrl->u.async.pid);
407 		if (ctrl->result < 0)
408 			break;
409 		if (ctrl->u.async.sig >= 0) {
410 			assert(client->async_sig < 0);
411 			ctrl->result = snd_async_add_pcm_handler(&client->async_handler, pcm, async_handler, client);
412 			if (ctrl->result < 0)
413 				break;
414 		} else {
415 			assert(client->async_sig >= 0);
416 			snd_async_del_handler(client->async_handler);
417 		}
418 		client->async_sig = ctrl->u.async.sig;
419 		client->async_pid = ctrl->u.async.pid;
420 		break;
421 	case SNDRV_PCM_IOCTL_INFO:
422 		ctrl->result = snd_pcm_info(pcm, (snd_pcm_info_t *) &ctrl->u.info);
423 		break;
424 	case SNDRV_PCM_IOCTL_HW_REFINE:
425 		ctrl->result = snd_pcm_hw_refine(pcm, (snd_pcm_hw_params_t *) &ctrl->u.hw_refine);
426 		break;
427 	case SNDRV_PCM_IOCTL_HW_PARAMS:
428 		ctrl->result = snd_pcm_hw_params(pcm, (snd_pcm_hw_params_t *) &ctrl->u.hw_params);
429 		break;
430 	case SNDRV_PCM_IOCTL_HW_FREE:
431 		ctrl->result = snd_pcm_hw_free(pcm);
432 		break;
433 	case SNDRV_PCM_IOCTL_SW_PARAMS:
434 		ctrl->result = snd_pcm_sw_params(pcm, (snd_pcm_sw_params_t *) &ctrl->u.sw_params);
435 		break;
436 	case SNDRV_PCM_IOCTL_STATUS:
437 		ctrl->result = snd_pcm_status(pcm, (snd_pcm_status_t *) &ctrl->u.status);
438 		break;
439 	case SND_PCM_IOCTL_STATE:
440 		ctrl->result = snd_pcm_state(pcm);
441 		break;
442 	case SND_PCM_IOCTL_HWSYNC:
443 		ctrl->result = snd_pcm_hwsync(pcm);
444 		break;
445 	case SNDRV_PCM_IOCTL_DELAY:
446 		ctrl->result = snd_pcm_delay(pcm, (snd_pcm_sframes_t *) &ctrl->u.delay.frames);
447 		break;
448 	case SND_PCM_IOCTL_AVAIL_UPDATE:
449 		ctrl->result = snd_pcm_avail_update(pcm);
450 		break;
451 	case SNDRV_PCM_IOCTL_PREPARE:
452 		ctrl->result = snd_pcm_prepare(pcm);
453 		break;
454 	case SNDRV_PCM_IOCTL_RESET:
455 		ctrl->result = snd_pcm_reset(pcm);
456 		break;
457 	case SNDRV_PCM_IOCTL_START:
458 		ctrl->result = snd_pcm_start(pcm);
459 		break;
460 	case SNDRV_PCM_IOCTL_DRAIN:
461 		ctrl->result = snd_pcm_drain(pcm);
462 		break;
463 	case SNDRV_PCM_IOCTL_DROP:
464 		ctrl->result = snd_pcm_drop(pcm);
465 		break;
466 	case SNDRV_PCM_IOCTL_PAUSE:
467 		ctrl->result = snd_pcm_pause(pcm, ctrl->u.pause.enable);
468 		break;
469 	case SNDRV_PCM_IOCTL_CHANNEL_INFO:
470 		ctrl->result = snd_pcm_channel_info(pcm, (snd_pcm_channel_info_t *) &ctrl->u.channel_info);
471 		if (ctrl->result >= 0 &&
472 		    ctrl->u.channel_info.type == SND_PCM_AREA_MMAP)
473 			return shm_ack_fd(client, ctrl->u.channel_info.u.mmap.fd);
474 		break;
475 	case SNDRV_PCM_IOCTL_REWIND:
476 		ctrl->result = snd_pcm_rewind(pcm, ctrl->u.rewind.frames);
477 		break;
478 	case SND_PCM_IOCTL_FORWARD:
479 		ctrl->result = snd_pcm_forward(pcm, ctrl->u.forward.frames);
480 		break;
481 	case SNDRV_PCM_IOCTL_LINK:
482 	{
483 		/* FIXME */
484 		ctrl->result = -ENOSYS;
485 		break;
486 	}
487 	case SNDRV_PCM_IOCTL_UNLINK:
488 		ctrl->result = snd_pcm_unlink(pcm);
489 		break;
490 	case SNDRV_PCM_IOCTL_RESUME:
491 		ctrl->result = snd_pcm_resume(pcm);
492 		break;
493 	case SND_PCM_IOCTL_MMAP:
494 	{
495 		ctrl->result = snd_pcm_mmap(pcm);
496 		break;
497 	}
498 	case SND_PCM_IOCTL_MUNMAP:
499 	{
500 		ctrl->result = snd_pcm_munmap(pcm);
501 		break;
502 	}
503 	case SND_PCM_IOCTL_MMAP_COMMIT:
504 		ctrl->result = snd_pcm_mmap_commit(pcm,
505 						   ctrl->u.mmap_commit.offset,
506 						   ctrl->u.mmap_commit.frames);
507 		break;
508 	case SND_PCM_IOCTL_POLL_DESCRIPTOR:
509 		ctrl->result = 0;
510 		return shm_ack_fd(client, _snd_pcm_poll_descriptor(pcm));
511 	case SND_PCM_IOCTL_CLOSE:
512 		client->ops->close(client);
513 		break;
514 	case SND_PCM_IOCTL_HW_PTR_FD:
515 		return shm_rbptr_fd(client, &pcm->hw);
516 	case SND_PCM_IOCTL_APPL_PTR_FD:
517 		return shm_rbptr_fd(client, &pcm->appl);
518 	default:
519 		ERROR("Bogus cmd: %x", ctrl->cmd);
520 		ctrl->result = -ENOSYS;
521 	}
522 	return shm_ack(client);
523 }
524 
525 transport_ops_t pcm_shm_ops = {
526 	.open	= pcm_shm_open,
527 	.cmd	= pcm_shm_cmd,
528 	.close	= pcm_shm_close,
529 };
530 
ctl_handler(waiter_t *waiter, unsigned short events)531 static int ctl_handler(waiter_t *waiter, unsigned short events)
532 {
533 	client_t *client = waiter->private_data;
534 	char buf[1] = "";
535 	ssize_t n;
536 	if (events & POLLIN) {
537 		n = write(client->poll_fd, buf, 1);
538 		if (n != 1) {
539 			SYSERROR("write failed");
540 			return -errno;
541 		}
542 	}
543 	del_waiter(waiter->fd);
544 	client->polling = 0;
545 	return 0;
546 }
547 
ctl_shm_open(client_t *client, int *cookie)548 static int ctl_shm_open(client_t *client, int *cookie)
549 {
550 	int shmid;
551 	snd_ctl_t *ctl;
552 	int err;
553 	int result;
554 	err = snd_ctl_open(&ctl, client->name, SND_CTL_NONBLOCK);
555 	if (err < 0)
556 		return err;
557 	client->device.ctl.handle = ctl;
558 	client->device.ctl.fd = _snd_ctl_poll_descriptor(ctl);
559 
560 	shmid = shmget(IPC_PRIVATE, CTL_SHM_SIZE, 0666);
561 	if (shmid < 0) {
562 		result = -errno;
563 		SYSERROR("shmget failed");
564 		goto _err;
565 	}
566 	client->transport.shm.ctrl_id = shmid;
567 	client->transport.shm.ctrl = shmat(shmid, 0, 0);
568 	if (!client->transport.shm.ctrl) {
569 		result = -errno;
570 		shmctl(shmid, IPC_RMID, 0);
571 		SYSERROR("shmat failed");
572 		goto _err;
573 	}
574 	*cookie = shmid;
575 	add_waiter(client->device.ctl.fd, POLLIN, ctl_handler, client);
576 	client->polling = 1;
577 	return 0;
578 
579  _err:
580 	snd_ctl_close(ctl);
581 	return result;
582 
583 }
584 
ctl_shm_close(client_t *client)585 static int ctl_shm_close(client_t *client)
586 {
587 	int err;
588 	snd_ctl_shm_ctrl_t *ctrl = client->transport.shm.ctrl;
589 	if (client->polling) {
590 		del_waiter(client->device.ctl.fd);
591 		client->polling = 0;
592 	}
593 	err = snd_ctl_close(client->device.ctl.handle);
594 	ctrl->result = err;
595 	if (err < 0)
596 		ERROR("snd_ctl_close");
597 	if (client->transport.shm.ctrl) {
598 		err = shmdt((void *)client->transport.shm.ctrl);
599 		if (err < 0)
600 			SYSERROR("shmdt failed");
601 		err = shmctl(client->transport.shm.ctrl_id, IPC_RMID, 0);
602 		if (err < 0)
603 			SYSERROR("shmctl failed");
604 		client->transport.shm.ctrl = 0;
605 	}
606 	client->open = 0;
607 	return 0;
608 }
609 
ctl_shm_cmd(client_t *client)610 static int ctl_shm_cmd(client_t *client)
611 {
612 	snd_ctl_shm_ctrl_t *ctrl = client->transport.shm.ctrl;
613 	char buf[1];
614 	int err;
615 	int cmd;
616 	snd_ctl_t *ctl;
617 	err = read(client->ctrl_fd, buf, 1);
618 	if (err != 1)
619 		return -EBADFD;
620 	cmd = ctrl->cmd;
621 	ctrl->cmd = 0;
622 	ctl = client->device.ctl.handle;
623 	switch (cmd) {
624 	case SND_CTL_IOCTL_ASYNC:
625 		ctrl->result = snd_ctl_async(ctl, ctrl->u.async.sig, ctrl->u.async.pid);
626 		if (ctrl->result < 0)
627 			break;
628 		if (ctrl->u.async.sig >= 0) {
629 			assert(client->async_sig < 0);
630 			ctrl->result = snd_async_add_ctl_handler(&client->async_handler, ctl, async_handler, client);
631 			if (ctrl->result < 0)
632 				break;
633 		} else {
634 			assert(client->async_sig >= 0);
635 			snd_async_del_handler(client->async_handler);
636 		}
637 		client->async_sig = ctrl->u.async.sig;
638 		client->async_pid = ctrl->u.async.pid;
639 		break;
640 		break;
641 	case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS:
642 		ctrl->result = snd_ctl_subscribe_events(ctl, ctrl->u.subscribe_events);
643 		break;
644 	case SNDRV_CTL_IOCTL_CARD_INFO:
645 		ctrl->result = snd_ctl_card_info(ctl, &ctrl->u.card_info);
646 		break;
647 	case SNDRV_CTL_IOCTL_ELEM_LIST:
648 	{
649 		size_t maxsize = CTL_SHM_DATA_MAXLEN;
650 		if (ctrl->u.element_list.space * sizeof(*ctrl->u.element_list.pids) > maxsize) {
651 			ctrl->result = -EFAULT;
652 			break;
653 		}
654 		ctrl->u.element_list.pids = (snd_ctl_elem_id_t*) ctrl->data;
655 		ctrl->result = snd_ctl_elem_list(ctl, &ctrl->u.element_list);
656 		break;
657 	}
658 	case SNDRV_CTL_IOCTL_ELEM_INFO:
659 		ctrl->result = snd_ctl_elem_info(ctl, &ctrl->u.element_info);
660 		break;
661 	case SNDRV_CTL_IOCTL_ELEM_READ:
662 		ctrl->result = snd_ctl_elem_read(ctl, &ctrl->u.element_read);
663 		break;
664 	case SNDRV_CTL_IOCTL_ELEM_WRITE:
665 		ctrl->result = snd_ctl_elem_write(ctl, &ctrl->u.element_write);
666 		break;
667 	case SNDRV_CTL_IOCTL_ELEM_LOCK:
668 		ctrl->result = snd_ctl_elem_lock(ctl, &ctrl->u.element_lock);
669 		break;
670 	case SNDRV_CTL_IOCTL_ELEM_UNLOCK:
671 		ctrl->result = snd_ctl_elem_unlock(ctl, &ctrl->u.element_unlock);
672 		break;
673 	case SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE:
674 		ctrl->result = snd_ctl_hwdep_next_device(ctl, &ctrl->u.device);
675 		break;
676 	case SNDRV_CTL_IOCTL_HWDEP_INFO:
677 		ctrl->result = snd_ctl_hwdep_info(ctl, &ctrl->u.hwdep_info);
678 		break;
679 	case SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE:
680 		ctrl->result = snd_ctl_pcm_next_device(ctl, &ctrl->u.device);
681 		break;
682 	case SNDRV_CTL_IOCTL_PCM_INFO:
683 		ctrl->result = snd_ctl_pcm_info(ctl, &ctrl->u.pcm_info);
684 		break;
685 	case SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE:
686 		ctrl->result = snd_ctl_pcm_prefer_subdevice(ctl, ctrl->u.pcm_prefer_subdevice);
687 		break;
688 	case SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE:
689 		ctrl->result = snd_ctl_rawmidi_next_device(ctl, &ctrl->u.device);
690 		break;
691 	case SNDRV_CTL_IOCTL_RAWMIDI_INFO:
692 		ctrl->result = snd_ctl_rawmidi_info(ctl, &ctrl->u.rawmidi_info);
693 		break;
694 	case SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE:
695 		ctrl->result = snd_ctl_rawmidi_prefer_subdevice(ctl, ctrl->u.rawmidi_prefer_subdevice);
696 		break;
697 	case SNDRV_CTL_IOCTL_POWER:
698 		ctrl->result = snd_ctl_set_power_state(ctl, ctrl->u.power_state);
699 		break;
700 	case SNDRV_CTL_IOCTL_POWER_STATE:
701 		ctrl->result = snd_ctl_get_power_state(ctl, &ctrl->u.power_state);
702 		break;
703 	case SND_CTL_IOCTL_READ:
704 		ctrl->result = snd_ctl_read(ctl, &ctrl->u.read);
705 		break;
706 	case SND_CTL_IOCTL_CLOSE:
707 		client->ops->close(client);
708 		break;
709 	case SND_CTL_IOCTL_POLL_DESCRIPTOR:
710 		ctrl->result = 0;
711 		return shm_ack_fd(client, _snd_ctl_poll_descriptor(ctl));
712 	default:
713 		ERROR("Bogus cmd: %x", ctrl->cmd);
714 		ctrl->result = -ENOSYS;
715 	}
716 	return shm_ack(client);
717 }
718 
719 transport_ops_t ctl_shm_ops = {
720 	.open	= ctl_shm_open,
721 	.cmd	= ctl_shm_cmd,
722 	.close	= ctl_shm_close,
723 };
724 
snd_client_open(client_t *client)725 static int snd_client_open(client_t *client)
726 {
727 	int err;
728 	snd_client_open_request_t req;
729 	snd_client_open_answer_t ans;
730 	char *name;
731 	memset(&ans, 0, sizeof(ans));
732 	err = read(client->ctrl_fd, &req, sizeof(req));
733 	if (err < 0) {
734 		SYSERROR("read failed");
735 		exit(1);
736 	}
737 	if (err != sizeof(req)) {
738 		ans.result = -EINVAL;
739 		goto _answer;
740 	}
741 	name = alloca(req.namelen + 1);
742 	err = read(client->ctrl_fd, name, req.namelen);
743 	if (err < 0) {
744 		SYSERROR("read failed");
745 		exit(1);
746 	}
747 	if (err != req.namelen) {
748 		ans.result = -EINVAL;
749 		goto _answer;
750 	}
751 
752 	switch (req.transport_type) {
753 	case SND_TRANSPORT_TYPE_SHM:
754 		if (!client->local) {
755 			ans.result = -EINVAL;
756 			goto _answer;
757 		}
758 		switch (req.dev_type) {
759 		case SND_DEV_TYPE_PCM:
760 			client->ops = &pcm_shm_ops;
761 			break;
762 		case SND_DEV_TYPE_CONTROL:
763 			client->ops = &ctl_shm_ops;
764 			break;
765 		default:
766 			ans.result = -EINVAL;
767 			goto _answer;
768 		}
769 		break;
770 	default:
771 		ans.result = -EINVAL;
772 		goto _answer;
773 	}
774 
775 	name[req.namelen] = '\0';
776 
777 	client->transport_type = req.transport_type;
778 	if (sizeof(client->name) < (size_t)(req.namelen + 1)) {
779 		ans.result = -ENOMEM;
780 		goto _answer;
781 	}
782 	strcpy(client->name, name);
783 	client->stream = req.stream;
784 	client->mode = req.mode;
785 
786 	err = client->ops->open(client, &ans.cookie);
787 	if (err < 0) {
788 		ans.result = err;
789 	} else {
790 		client->open = 1;
791 		ans.result = 0;
792 	}
793 
794  _answer:
795 	err = write(client->ctrl_fd, &ans, sizeof(ans));
796 	if (err != sizeof(ans)) {
797 		SYSERROR("write failed");
798 		exit(1);
799 	}
800 	return 0;
801 }
802 
client_poll_handler(waiter_t *waiter, unsigned short events ATTRIBUTE_UNUSED)803 static int client_poll_handler(waiter_t *waiter, unsigned short events ATTRIBUTE_UNUSED)
804 {
805 	client_t *client = waiter->private_data;
806 	if (client->open)
807 		client->ops->close(client);
808 	close(client->poll_fd);
809 	close(client->ctrl_fd);
810 	del_waiter(client->poll_fd);
811 	del_waiter(client->ctrl_fd);
812 	list_del(&client->list);
813 	free(client);
814 	return 0;
815 }
816 
client_ctrl_handler(waiter_t *waiter, unsigned short events)817 static int client_ctrl_handler(waiter_t *waiter, unsigned short events)
818 {
819 	client_t *client = waiter->private_data;
820 	if (events & POLLHUP) {
821 		if (client->open)
822 			client->ops->close(client);
823 		close(client->ctrl_fd);
824 		del_waiter(client->ctrl_fd);
825 		list_del(&client->list);
826 		free(client);
827 		return 0;
828 	}
829 	if (client->open)
830 		return client->ops->cmd(client);
831 	else
832 		return snd_client_open(client);
833 }
834 
inet_pending_handler(waiter_t *waiter, unsigned short events)835 static int inet_pending_handler(waiter_t *waiter, unsigned short events)
836 {
837 	inet_pending_t *pending = waiter->private_data;
838 	inet_pending_t *pdata;
839 	client_t *client;
840 	uint32_t cookie;
841 	struct list_head *item;
842 	int remove = 0;
843 	if (events & POLLHUP)
844 		remove = 1;
845 	else {
846 		int err = read(waiter->fd, &cookie, sizeof(cookie));
847 		if (err != sizeof(cookie))
848 			remove = 1;
849 		else {
850 			err = write(waiter->fd, &cookie, sizeof(cookie));
851 			if (err != sizeof(cookie))
852 				remove = 1;
853 		}
854 	}
855 	del_waiter(waiter->fd);
856 	if (remove) {
857 		close(waiter->fd);
858 		list_del(&pending->list);
859 		free(pending);
860 		return 0;
861 	}
862 
863 	list_for_each(item, &inet_pendings) {
864 		pdata = list_entry(item, inet_pending_t, list);
865 		if (pdata->cookie == cookie)
866 			goto found;
867 	}
868 	pending->cookie = cookie;
869 	return 0;
870 
871  found:
872 	client = calloc(1, sizeof(*client));
873 	client->local = 0;
874 	client->poll_fd = pdata->fd;
875 	client->ctrl_fd = waiter->fd;
876 	add_waiter(client->ctrl_fd, POLLIN | POLLHUP, client_ctrl_handler, client);
877 	add_waiter(client->poll_fd, POLLHUP, client_poll_handler, client);
878 	client->open = 0;
879 	list_add_tail(&client->list, &clients);
880 	list_del(&pending->list);
881 	list_del(&pdata->list);
882 	free(pending);
883 	free(pdata);
884 	return 0;
885 }
886 
local_handler(waiter_t *waiter, unsigned short events ATTRIBUTE_UNUSED)887 static int local_handler(waiter_t *waiter, unsigned short events ATTRIBUTE_UNUSED)
888 {
889 	int sock;
890 	sock = accept(waiter->fd, 0, 0);
891 	if (sock < 0) {
892 		int result = -errno;
893 		SYSERROR("accept failed");
894 		return result;
895 	} else {
896 		client_t *client = calloc(1, sizeof(*client));
897 		client->ctrl_fd = sock;
898 		client->local = 1;
899 		client->open = 0;
900 		add_waiter(sock, POLLIN | POLLHUP, client_ctrl_handler, client);
901 		list_add_tail(&client->list, &clients);
902 	}
903 	return 0;
904 }
905 
inet_handler(waiter_t *waiter, unsigned short events ATTRIBUTE_UNUSED)906 static int inet_handler(waiter_t *waiter, unsigned short events ATTRIBUTE_UNUSED)
907 {
908 	int sock;
909 	sock = accept(waiter->fd, 0, 0);
910 	if (sock < 0) {
911 		int result = -errno;
912 		SYSERROR("accept failed");
913 		return result;
914 	} else {
915 		inet_pending_t *pending = calloc(1, sizeof(*pending));
916 		pending->fd = sock;
917 		pending->cookie = 0;
918 		add_waiter(sock, POLLIN, inet_pending_handler, pending);
919 		list_add_tail(&pending->list, &inet_pendings);
920 	}
921 	return 0;
922 }
923 
server(const char *sockname, int port)924 static int server(const char *sockname, int port)
925 {
926 	int err, result, sockn = -1, socki = -1;
927 	unsigned int k;
928 	long open_max;
929 
930 	if (!sockname && port < 0)
931 		return -EINVAL;
932 	open_max = sysconf(_SC_OPEN_MAX);
933 	if (open_max < 0) {
934 		result = -errno;
935 		SYSERROR("sysconf failed");
936 		return result;
937 	}
938 	pollfds = calloc((size_t) open_max, sizeof(*pollfds));
939 	waiters = calloc((size_t) open_max, sizeof(*waiters));
940 
941 	if (sockname) {
942 		sockn = make_local_socket(sockname);
943 		if (sockn < 0)
944 			return sockn;
945 		if (fcntl(sockn, F_SETFL, O_NONBLOCK) < 0) {
946 			result = -errno;
947 			SYSERROR("fcntl O_NONBLOCK failed");
948 			goto _end;
949 		}
950 		if (listen(sockn, 4) < 0) {
951 			result = -errno;
952 			SYSERROR("listen failed");
953 			goto _end;
954 		}
955 		add_waiter(sockn, POLLIN, local_handler, NULL);
956 	}
957 	if (port >= 0) {
958 		socki = make_inet_socket(port);
959 		if (socki < 0)
960 			return socki;
961 		if (fcntl(socki, F_SETFL, O_NONBLOCK) < 0) {
962 			result = -errno;
963 			SYSERROR("fcntl failed");
964 			goto _end;
965 		}
966 		if (listen(socki, 4) < 0) {
967 			result = -errno;
968 			SYSERROR("listen failed");
969 			goto _end;
970 		}
971 		add_waiter(socki, POLLIN, inet_handler, NULL);
972 	}
973 
974 	while (1) {
975 		struct pollfd pfds[open_max];
976 		size_t pfds_count;
977 		do {
978 			err = poll(pollfds, pollfds_count, -1);
979 		} while (err == 0);
980 		if (err < 0) {
981 			SYSERROR("poll failed");
982 			continue;
983 		}
984 
985 		pfds_count = pollfds_count;
986 		memcpy(pfds, pollfds, sizeof(*pfds) * pfds_count);
987 		for (k = 0; k < pfds_count; k++) {
988 			struct pollfd *pfd = &pfds[k];
989 			if (pfd->revents) {
990 				waiter_t *w = &waiters[pfd->fd];
991 				if (!w->handler)
992 					continue;
993 				err = w->handler(w, pfd->revents);
994 				if (err < 0)
995 					ERROR("waiter handler failed");
996 			}
997 		}
998 	}
999  _end:
1000 	if (sockn >= 0)
1001 		close(sockn);
1002 	if (socki >= 0)
1003 		close(socki);
1004 	free(pollfds);
1005 	free(waiters);
1006 	return result;
1007 }
1008 
1009 
usage(void)1010 static void usage(void)
1011 {
1012 	fprintf(stderr,
1013 		"Usage: %s [OPTIONS] server\n"
1014 		"--help			help\n",
1015 		command);
1016 }
1017 
main(int argc, char **argv)1018 int main(int argc, char **argv)
1019 {
1020 	static const struct option long_options[] = {
1021 		{"help", 0, 0, 'h'},
1022 		{ 0 , 0 , 0, 0 }
1023 	};
1024 	int c;
1025 	snd_config_t *conf;
1026 	snd_config_iterator_t i, next;
1027 	const char *sockname = NULL;
1028 	long port = -1;
1029 	int err;
1030 	char *srvname;
1031 
1032 	command = argv[0];
1033 	while ((c = getopt_long(argc, argv, "h", long_options, 0)) != -1) {
1034 		switch (c) {
1035 		case 'h':
1036 			usage();
1037 			return 0;
1038 		default:
1039 			fprintf(stderr, "Try `%s --help' for more information\n", command);
1040 			return 1;
1041 		}
1042 	}
1043 	if (argc - optind != 1) {
1044 		ERROR("you need to specify server name");
1045 		return 1;
1046 	}
1047 	err = snd_config_update();
1048 	if (err < 0) {
1049 		ERROR("cannot read configuration file");
1050 		return 1;
1051 	}
1052 	srvname = argv[optind];
1053 	err = snd_config_search_definition(snd_config, "server", srvname, &conf);
1054 	if (err < 0) {
1055 		ERROR("Missing definition for server %s", srvname);
1056 		return 1;
1057 	}
1058 	if (snd_config_get_type(conf) != SND_CONFIG_TYPE_COMPOUND) {
1059 		SNDERR("Invalid type for server %s definition", srvname);
1060 		return -EINVAL;
1061 	}
1062 	snd_config_for_each(i, next, conf) {
1063 		snd_config_t *n = snd_config_iterator_entry(i);
1064 		const char *id;
1065 		if (snd_config_get_id(n, &id) < 0)
1066 			continue;
1067 		if (strcmp(id, "comment") == 0)
1068 			continue;
1069 		if (strcmp(id, "host") == 0)
1070 			continue;
1071 		if (strcmp(id, "socket") == 0) {
1072 			err = snd_config_get_string(n, &sockname);
1073 			if (err < 0) {
1074 				ERROR("Invalid type for %s", id);
1075 				return 1;
1076 			}
1077 			continue;
1078 		}
1079 		if (strcmp(id, "port") == 0) {
1080 			err = snd_config_get_integer(n, &port);
1081 			if (err < 0) {
1082 				ERROR("Invalid type for %s", id);
1083 				return 1;
1084 			}
1085 			continue;
1086 		}
1087 		ERROR("Unknown field %s", id);
1088 		return 1;
1089 	}
1090 	if (!sockname && port < 0) {
1091 		ERROR("either socket or port need to be defined");
1092 		return 1;
1093 	}
1094 	server(sockname, port);
1095 	return 0;
1096 }
1097