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