3 * Copyright (c) by Abramo Bagnara <abramo@alsa-project.org>
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.
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.
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
22 #include <sys/socket.h>
31 #include <netinet/in.h>
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__); \
47 #define ERROR(args...) do {\
48 fprintf(stderr, "%s %s:%i:(%s) ", command, __FILE__, __LINE__, __FUNCTION__); \
49 fprintf(stderr, ##args); \
54 #define SYSERROR(string) ERROR(string ": %s", strerror(errno))
56 static int make_local_socket(const char *filename)
58 size_t l = strlen(filename);
59 size_t size = offsetof(struct sockaddr_un, sun_path) + l;
60 struct sockaddr_un *addr = alloca(size);
63 sock = socket(PF_LOCAL, SOCK_STREAM, 0);
66 SYSERROR("socket failed");
72 addr->sun_family = AF_LOCAL;
73 memcpy(addr->sun_path, filename, l);
75 if (bind(sock, (struct sockaddr *) addr, size) < 0) {
77 SYSERROR("bind failed");
84 static int make_inet_socket(int port)
86 struct sockaddr_in addr;
89 sock = socket(PF_INET, SOCK_STREAM, 0);
92 SYSERROR("socket failed");
96 addr.sin_family = AF_INET;
97 addr.sin_port = htons(port);
98 addr.sin_addr.s_addr = INADDR_ANY;
100 if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
102 SYSERROR("bind failed");
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);
116 waiter_handler_t handler;
120 static void add_waiter(int fd, unsigned short events, waiter_handler_t handler,
123 waiter_t *w = &waiters[fd];
124 struct pollfd *pfd = &pollfds[pollfds_count];
127 pfd->events = events;
130 w->private_data = data;
131 w->handler = handler;
135 static void del_waiter(int fd)
137 waiter_t *w = &waiters[fd];
141 for (k = 0; k < pollfds_count; ++k) {
142 if (pollfds[k].fd == fd)
145 assert(k < pollfds_count);
147 memmove(&pollfds[k], &pollfds[k + 1], pollfds_count - k);
150 typedef struct client client_t;
153 int (*open)(client_t *client, int *cookie);
154 int (*cmd)(client_t *client);
155 int (*close)(client_t *client);
159 struct list_head list;
168 transport_ops_t *ops;
169 snd_async_handler_t *async_handler;
183 snd_rawmidi_t *handle;
186 snd_timer_open_t *handle;
210 struct list_head list;
214 LIST_HEAD(inet_pendings);
217 static int pcm_handler(waiter_t *waiter, unsigned short events)
219 client_t *client = waiter->private_data;
222 if (events & POLLIN) {
223 n = write(client->poll_fd, buf, 1);
225 SYSERROR("write failed");
228 } else if (events & POLLOUT) {
229 n = read(client->poll_fd, buf, 1);
231 SYSERROR("read failed");
235 del_waiter(waiter->fd);
241 static void pcm_shm_hw_ptr_changed(snd_pcm_t *pcm, snd_pcm_t *src ATTRIBUTE_UNUSED)
243 client_t *client = pcm->hw.private_data;
244 volatile snd_pcm_shm_ctrl_t *ctrl = client->transport.shm.ctrl;
247 ctrl->hw.changed = 1;
248 if (pcm->hw.fd >= 0) {
249 ctrl->hw.use_mmap = 1;
250 ctrl->hw.offset = pcm->hw.offset;
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;
260 static void pcm_shm_appl_ptr_changed(snd_pcm_t *pcm, snd_pcm_t *src ATTRIBUTE_UNUSED)
262 client_t *client = pcm->appl.private_data;
263 volatile snd_pcm_shm_ctrl_t *ctrl = client->transport.shm.ctrl;
266 ctrl->appl.changed = 1;
267 if (pcm->appl.fd >= 0) {
268 ctrl->appl.use_mmap = 1;
269 ctrl->appl.offset = pcm->appl.offset;
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;
279 static int pcm_shm_open(client_t *client, int *cookie)
285 err = snd_pcm_open(&pcm, client->name, client->stream, SND_PCM_NONBLOCK);
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;
295 shmid = shmget(IPC_PRIVATE, PCM_SHM_SIZE, 0666);
298 SYSERROR("shmget failed");
301 client->transport.shm.ctrl_id = shmid;
302 client->transport.shm.ctrl = shmat(shmid, 0, 0);
303 if (client->transport.shm.ctrl == (void*) -1) {
305 shmctl(shmid, IPC_RMID, 0);
306 SYSERROR("shmat failed");
318 static int pcm_shm_close(client_t *client)
321 snd_pcm_shm_ctrl_t *ctrl = client->transport.shm.ctrl;
322 if (client->polling) {
323 del_waiter(client->device.pcm.fd);
326 err = snd_pcm_close(client->device.pcm.handle);
329 ERROR("snd_pcm_close");
330 if (client->transport.shm.ctrl) {
331 err = shmdt((void *)client->transport.shm.ctrl);
333 SYSERROR("shmdt failed");
334 err = shmctl(client->transport.shm.ctrl_id, IPC_RMID, 0);
336 SYSERROR("shmctl IPC_RMID failed");
337 client->transport.shm.ctrl = 0;
343 static int shm_ack(client_t *client)
348 pfd.fd = client->ctrl_fd;
349 pfd.events = POLLHUP;
350 if (poll(&pfd, 1, 0) == 1)
352 err = write(client->ctrl_fd, buf, 1);
358 static int shm_ack_fd(client_t *client, int fd)
363 pfd.fd = client->ctrl_fd;
364 pfd.events = POLLHUP;
365 if (poll(&pfd, 1, 0) == 1)
367 err = snd_send_fd(client->ctrl_fd, buf, 1, fd);
373 static int shm_rbptr_fd(client_t *client, snd_pcm_rbptr_t *rbptr)
377 return shm_ack_fd(client, rbptr->fd);
380 static void async_handler(snd_async_handler_t *handler)
382 client_t *client = snd_async_handler_get_callback_private(handler);
383 /* FIXME: use sigqueue */
384 kill(client->async_pid, client->async_sig);
387 static int pcm_shm_cmd(client_t *client)
389 volatile snd_pcm_shm_ctrl_t *ctrl = client->transport.shm.ctrl;
394 err = read(client->ctrl_fd, buf, 1);
399 pcm = client->device.pcm.handle;
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)
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)
411 assert(client->async_sig >= 0);
412 snd_async_del_handler(client->async_handler);
414 client->async_sig = ctrl->u.async.sig;
415 client->async_pid = ctrl->u.async.pid;
417 case SNDRV_PCM_IOCTL_INFO:
418 ctrl->result = snd_pcm_info(pcm, (snd_pcm_info_t *) &ctrl->u.info);
420 case SNDRV_PCM_IOCTL_HW_REFINE:
421 ctrl->result = snd_pcm_hw_refine(pcm, (snd_pcm_hw_params_t *) &ctrl->u.hw_refine);
423 case SNDRV_PCM_IOCTL_HW_PARAMS:
424 ctrl->result = snd_pcm_hw_params(pcm, (snd_pcm_hw_params_t *) &ctrl->u.hw_params);
426 case SNDRV_PCM_IOCTL_HW_FREE:
427 ctrl->result = snd_pcm_hw_free(pcm);
429 case SNDRV_PCM_IOCTL_SW_PARAMS:
430 ctrl->result = snd_pcm_sw_params(pcm, (snd_pcm_sw_params_t *) &ctrl->u.sw_params);
432 case SNDRV_PCM_IOCTL_STATUS:
433 ctrl->result = snd_pcm_status(pcm, (snd_pcm_status_t *) &ctrl->u.status);
435 case SND_PCM_IOCTL_STATE:
436 ctrl->result = snd_pcm_state(pcm);
438 case SND_PCM_IOCTL_HWSYNC:
439 ctrl->result = snd_pcm_hwsync(pcm);
441 case SNDRV_PCM_IOCTL_DELAY:
442 ctrl->result = snd_pcm_delay(pcm, (snd_pcm_sframes_t *) &ctrl->u.delay.frames);
444 case SND_PCM_IOCTL_AVAIL_UPDATE:
445 ctrl->result = snd_pcm_avail_update(pcm);
447 case SNDRV_PCM_IOCTL_PREPARE:
448 ctrl->result = snd_pcm_prepare(pcm);
450 case SNDRV_PCM_IOCTL_RESET:
451 ctrl->result = snd_pcm_reset(pcm);
453 case SNDRV_PCM_IOCTL_START:
454 ctrl->result = snd_pcm_start(pcm);
456 case SNDRV_PCM_IOCTL_DRAIN:
457 ctrl->result = snd_pcm_drain(pcm);
459 case SNDRV_PCM_IOCTL_DROP:
460 ctrl->result = snd_pcm_drop(pcm);
462 case SNDRV_PCM_IOCTL_PAUSE:
463 ctrl->result = snd_pcm_pause(pcm, ctrl->u.pause.enable);
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);
471 case SNDRV_PCM_IOCTL_REWIND:
472 ctrl->result = snd_pcm_rewind(pcm, ctrl->u.rewind.frames);
474 case SND_PCM_IOCTL_FORWARD:
475 ctrl->result = snd_pcm_forward(pcm, ctrl->u.forward.frames);
477 case SNDRV_PCM_IOCTL_LINK:
480 ctrl->result = -ENOSYS;
483 case SNDRV_PCM_IOCTL_UNLINK:
484 ctrl->result = snd_pcm_unlink(pcm);
486 case SNDRV_PCM_IOCTL_RESUME:
487 ctrl->result = snd_pcm_resume(pcm);
489 case SND_PCM_IOCTL_MMAP:
491 ctrl->result = snd_pcm_mmap(pcm);
493 case SND_PCM_IOCTL_MUNMAP:
495 ctrl->result = snd_pcm_munmap(pcm);
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);
503 case SND_PCM_IOCTL_POLL_DESCRIPTOR:
505 return shm_ack_fd(client, _snd_pcm_poll_descriptor(pcm));
506 case SND_PCM_IOCTL_CLOSE:
507 client->ops->close(client);
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);
514 ERROR("Bogus cmd: %x", ctrl->cmd);
515 ctrl->result = -ENOSYS;
517 return shm_ack(client);
520 transport_ops_t pcm_shm_ops = {
521 .open = pcm_shm_open,
523 .close = pcm_shm_close,
526 static int ctl_handler(waiter_t *waiter, unsigned short events)
528 client_t *client = waiter->private_data;
531 if (events & POLLIN) {
532 n = write(client->poll_fd, buf, 1);
534 SYSERROR("write failed");
538 del_waiter(waiter->fd);
543 static int ctl_shm_open(client_t *client, int *cookie)
549 err = snd_ctl_open(&ctl, client->name, SND_CTL_NONBLOCK);
552 client->device.ctl.handle = ctl;
553 client->device.ctl.fd = _snd_ctl_poll_descriptor(ctl);
555 shmid = shmget(IPC_PRIVATE, CTL_SHM_SIZE, 0666);
558 SYSERROR("shmget failed");
561 client->transport.shm.ctrl_id = shmid;
562 client->transport.shm.ctrl = shmat(shmid, 0, 0);
563 if (!client->transport.shm.ctrl) {
565 shmctl(shmid, IPC_RMID, 0);
566 SYSERROR("shmat failed");
570 add_waiter(client->device.ctl.fd, POLLIN, ctl_handler, client);
580 static int ctl_shm_close(client_t *client)
583 snd_ctl_shm_ctrl_t *ctrl = client->transport.shm.ctrl;
584 if (client->polling) {
585 del_waiter(client->device.ctl.fd);
588 err = snd_ctl_close(client->device.ctl.handle);
591 ERROR("snd_ctl_close");
592 if (client->transport.shm.ctrl) {
593 err = shmdt((void *)client->transport.shm.ctrl);
595 SYSERROR("shmdt failed");
596 err = shmctl(client->transport.shm.ctrl_id, IPC_RMID, 0);
598 SYSERROR("shmctl failed");
599 client->transport.shm.ctrl = 0;
605 static int ctl_shm_cmd(client_t *client)
607 snd_ctl_shm_ctrl_t *ctrl = client->transport.shm.ctrl;
612 err = read(client->ctrl_fd, buf, 1);
617 ctl = client->device.ctl.handle;
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)
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)
629 assert(client->async_sig >= 0);
630 snd_async_del_handler(client->async_handler);
632 client->async_sig = ctrl->u.async.sig;
633 client->async_pid = ctrl->u.async.pid;
636 case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS:
637 ctrl->result = snd_ctl_subscribe_events(ctl, ctrl->u.subscribe_events);
639 case SNDRV_CTL_IOCTL_CARD_INFO:
640 ctrl->result = snd_ctl_card_info(ctl, &ctrl->u.card_info);
642 case SNDRV_CTL_IOCTL_ELEM_LIST:
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;
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);
653 case SNDRV_CTL_IOCTL_ELEM_INFO:
654 ctrl->result = snd_ctl_elem_info(ctl, &ctrl->u.element_info);
656 case SNDRV_CTL_IOCTL_ELEM_READ:
657 ctrl->result = snd_ctl_elem_read(ctl, &ctrl->u.element_read);
659 case SNDRV_CTL_IOCTL_ELEM_WRITE:
660 ctrl->result = snd_ctl_elem_write(ctl, &ctrl->u.element_write);
662 case SNDRV_CTL_IOCTL_ELEM_LOCK:
663 ctrl->result = snd_ctl_elem_lock(ctl, &ctrl->u.element_lock);
665 case SNDRV_CTL_IOCTL_ELEM_UNLOCK:
666 ctrl->result = snd_ctl_elem_unlock(ctl, &ctrl->u.element_unlock);
668 case SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE:
669 ctrl->result = snd_ctl_hwdep_next_device(ctl, &ctrl->u.device);
671 case SNDRV_CTL_IOCTL_HWDEP_INFO:
672 ctrl->result = snd_ctl_hwdep_info(ctl, &ctrl->u.hwdep_info);
674 case SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE:
675 ctrl->result = snd_ctl_pcm_next_device(ctl, &ctrl->u.device);
677 case SNDRV_CTL_IOCTL_PCM_INFO:
678 ctrl->result = snd_ctl_pcm_info(ctl, &ctrl->u.pcm_info);
680 case SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE:
681 ctrl->result = snd_ctl_pcm_prefer_subdevice(ctl, ctrl->u.pcm_prefer_subdevice);
683 case SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE:
684 ctrl->result = snd_ctl_rawmidi_next_device(ctl, &ctrl->u.device);
686 case SNDRV_CTL_IOCTL_RAWMIDI_INFO:
687 ctrl->result = snd_ctl_rawmidi_info(ctl, &ctrl->u.rawmidi_info);
689 case SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE:
690 ctrl->result = snd_ctl_rawmidi_prefer_subdevice(ctl, ctrl->u.rawmidi_prefer_subdevice);
692 case SNDRV_CTL_IOCTL_POWER:
693 ctrl->result = snd_ctl_set_power_state(ctl, ctrl->u.power_state);
695 case SNDRV_CTL_IOCTL_POWER_STATE:
696 ctrl->result = snd_ctl_get_power_state(ctl, &ctrl->u.power_state);
698 case SND_CTL_IOCTL_READ:
699 ctrl->result = snd_ctl_read(ctl, &ctrl->u.read);
701 case SND_CTL_IOCTL_CLOSE:
702 client->ops->close(client);
704 case SND_CTL_IOCTL_POLL_DESCRIPTOR:
706 return shm_ack_fd(client, _snd_ctl_poll_descriptor(ctl));
708 ERROR("Bogus cmd: %x", ctrl->cmd);
709 ctrl->result = -ENOSYS;
711 return shm_ack(client);
714 transport_ops_t ctl_shm_ops = {
715 .open = ctl_shm_open,
717 .close = ctl_shm_close,
720 static int snd_client_open(client_t *client)
723 snd_client_open_request_t req;
724 snd_client_open_answer_t ans;
726 memset(&ans, 0, sizeof(ans));
727 err = read(client->ctrl_fd, &req, sizeof(req));
729 SYSERROR("read failed");
732 if (err != sizeof(req)) {
733 ans.result = -EINVAL;
736 name = alloca(req.namelen);
737 err = read(client->ctrl_fd, name, req.namelen);
739 SYSERROR("read failed");
742 if (err != req.namelen) {
743 ans.result = -EINVAL;
747 switch (req.transport_type) {
748 case SND_TRANSPORT_TYPE_SHM:
749 if (!client->local) {
750 ans.result = -EINVAL;
753 switch (req.dev_type) {
754 case SND_DEV_TYPE_PCM:
755 client->ops = &pcm_shm_ops;
757 case SND_DEV_TYPE_CONTROL:
758 client->ops = &ctl_shm_ops;
761 ans.result = -EINVAL;
766 ans.result = -EINVAL;
770 name[req.namelen] = '\0';
772 client->transport_type = req.transport_type;
773 strcpy(client->name, name);
774 client->stream = req.stream;
775 client->mode = req.mode;
777 err = client->ops->open(client, &ans.cookie);
786 err = write(client->ctrl_fd, &ans, sizeof(ans));
787 if (err != sizeof(ans)) {
788 SYSERROR("write failed");
794 static int client_poll_handler(waiter_t *waiter, unsigned short events ATTRIBUTE_UNUSED)
796 client_t *client = waiter->private_data;
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);
808 static int client_ctrl_handler(waiter_t *waiter, unsigned short events)
810 client_t *client = waiter->private_data;
811 if (events & POLLHUP) {
813 client->ops->close(client);
814 close(client->ctrl_fd);
815 del_waiter(client->ctrl_fd);
816 list_del(&client->list);
821 return client->ops->cmd(client);
823 return snd_client_open(client);
826 static int inet_pending_handler(waiter_t *waiter, unsigned short events)
828 inet_pending_t *pending = waiter->private_data;
829 inet_pending_t *pdata;
832 struct list_head *item;
834 if (events & POLLHUP)
837 int err = read(waiter->fd, &cookie, sizeof(cookie));
838 if (err != sizeof(cookie))
841 err = write(waiter->fd, &cookie, sizeof(cookie));
842 if (err != sizeof(cookie))
846 del_waiter(waiter->fd);
849 list_del(&pending->list);
854 list_for_each(item, &inet_pendings) {
855 pdata = list_entry(item, inet_pending_t, list);
856 if (pdata->cookie == cookie)
859 pending->cookie = cookie;
863 client = calloc(1, sizeof(*client));
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);
870 list_add_tail(&client->list, &clients);
871 list_del(&pending->list);
872 list_del(&pdata->list);
878 static int local_handler(waiter_t *waiter, unsigned short events ATTRIBUTE_UNUSED)
881 sock = accept(waiter->fd, 0, 0);
884 SYSERROR("accept failed");
887 client_t *client = calloc(1, sizeof(*client));
888 client->ctrl_fd = sock;
891 add_waiter(sock, POLLIN | POLLHUP, client_ctrl_handler, client);
892 list_add_tail(&client->list, &clients);
897 static int inet_handler(waiter_t *waiter, unsigned short events ATTRIBUTE_UNUSED)
900 sock = accept(waiter->fd, 0, 0);
903 SYSERROR("accept failed");
906 inet_pending_t *pending = calloc(1, sizeof(*pending));
909 add_waiter(sock, POLLIN, inet_pending_handler, pending);
910 list_add_tail(&pending->list, &inet_pendings);
915 static int server(const char *sockname, int port)
922 if (!sockname && port < 0)
924 open_max = sysconf(_SC_OPEN_MAX);
927 SYSERROR("sysconf failed");
930 pollfds = calloc((size_t) open_max, sizeof(*pollfds));
931 waiters = calloc((size_t) open_max, sizeof(*waiters));
934 int sock = make_local_socket(sockname);
937 if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) {
939 SYSERROR("fcntl O_NONBLOCK failed");
942 if (listen(sock, 4) < 0) {
944 SYSERROR("listen failed");
947 add_waiter(sock, POLLIN, local_handler, NULL);
950 int sock = make_inet_socket(port);
953 if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) {
955 SYSERROR("fcntl failed");
958 if (listen(sock, 4) < 0) {
960 SYSERROR("listen failed");
963 add_waiter(sock, POLLIN, inet_handler, NULL);
967 struct pollfd pfds[open_max];
970 err = poll(pollfds, pollfds_count, -1);
973 SYSERROR("poll failed");
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];
982 waiter_t *w = &waiters[pfd->fd];
985 err = w->handler(w, pfd->revents);
987 ERROR("waiter handler failed");
998 static void usage(void)
1001 "Usage: %s [OPTIONS] server\n"
1006 int main(int argc, char **argv)
1008 static const struct option long_options[] = {
1009 {"help", 0, 0, 'h'},
1014 snd_config_iterator_t i, next;
1015 const char *sockname = NULL;
1016 const char *host = NULL;
1022 while ((c = getopt_long(argc, argv, "h", long_options, 0)) != -1) {
1028 fprintf(stderr, "Try `%s --help' for more information\n", command);
1032 if (argc - optind != 1) {
1033 ERROR("you need to specify server name");
1036 err = snd_config_update();
1038 ERROR("cannot read configuration file");
1041 srvname = argv[optind];
1042 err = snd_config_search_definition(snd_config, "server", srvname, &conf);
1044 ERROR("Missing definition for server %s", srvname);
1047 if (snd_config_get_type(conf) != SND_CONFIG_TYPE_COMPOUND) {
1048 SNDERR("Invalid type for server %s definition", srvname);
1051 snd_config_for_each(i, next, conf) {
1052 snd_config_t *n = snd_config_iterator_entry(i);
1054 if (snd_config_get_id(n, &id) < 0)
1056 if (strcmp(id, "comment") == 0)
1058 if (strcmp(id, "host") == 0) {
1059 err = snd_config_get_string(n, &host);
1061 ERROR("Invalid type for %s", id);
1066 if (strcmp(id, "socket") == 0) {
1067 err = snd_config_get_string(n, &sockname);
1069 ERROR("Invalid type for %s", id);
1074 if (strcmp(id, "port") == 0) {
1075 err = snd_config_get_integer(n, &port);
1077 ERROR("Invalid type for %s", id);
1082 ERROR("Unknown field %s", id);
1086 ERROR("host is not defined");
1089 h = gethostbyname(host);
1091 ERROR("Cannot resolve %s", host);
1094 if (!snd_is_local(h)) {
1095 ERROR("%s is not the local host", host);
1098 if (!sockname && port < 0) {
1099 ERROR("either socket or port need to be defined");
1102 server(sockname, port);