xref: /openbsd-src/usr.bin/sndiod/sock.c (revision f1dd7b858388b4a23f4f67a4957ec5ff656ebbe8)
1 /*	$OpenBSD: sock.c,v 1.44 2021/03/03 10:19:06 ratchov Exp $	*/
2 /*
3  * Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 #include <sys/types.h>
18 #include <sys/socket.h>
19 #include <netinet/in.h>
20 #include <errno.h>
21 #include <poll.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <unistd.h>
26 
27 #include "abuf.h"
28 #include "defs.h"
29 #include "dev.h"
30 #include "file.h"
31 #include "midi.h"
32 #include "opt.h"
33 #include "sock.h"
34 #include "utils.h"
35 
36 #define SOCK_CTLDESC_SIZE	16	/* number of entries in s->ctldesc */
37 
38 void sock_log(struct sock *);
39 void sock_close(struct sock *);
40 void sock_slot_fill(void *);
41 void sock_slot_flush(void *);
42 void sock_slot_eof(void *);
43 void sock_slot_onmove(void *);
44 void sock_slot_onvol(void *);
45 void sock_midi_imsg(void *, unsigned char *, int);
46 void sock_midi_omsg(void *, unsigned char *, int);
47 void sock_midi_fill(void *, int);
48 void sock_ctl_sync(void *);
49 struct sock *sock_new(int);
50 void sock_exit(void *);
51 int sock_fdwrite(struct sock *, void *, int);
52 int sock_fdread(struct sock *, void *, int);
53 int sock_rmsg(struct sock *);
54 int sock_wmsg(struct sock *);
55 int sock_rdata(struct sock *);
56 int sock_wdata(struct sock *);
57 int sock_setpar(struct sock *);
58 int sock_auth(struct sock *);
59 int sock_hello(struct sock *);
60 int sock_execmsg(struct sock *);
61 int sock_buildmsg(struct sock *);
62 int sock_read(struct sock *);
63 int sock_write(struct sock *);
64 int sock_pollfd(void *, struct pollfd *);
65 int sock_revents(void *, struct pollfd *);
66 void sock_in(void *);
67 void sock_out(void *);
68 void sock_hup(void *);
69 
70 struct fileops sock_fileops = {
71 	"sock",
72 	sock_pollfd,
73 	sock_revents,
74 	sock_in,
75 	sock_out,
76 	sock_hup
77 };
78 
79 struct slotops sock_slotops = {
80 	sock_slot_onmove,
81 	sock_slot_onvol,
82 	sock_slot_fill,
83 	sock_slot_flush,
84 	sock_slot_eof,
85 	sock_exit
86 };
87 
88 struct midiops sock_midiops = {
89 	sock_midi_imsg,
90 	sock_midi_omsg,
91 	sock_midi_fill,
92 	sock_exit
93 };
94 
95 struct ctlops sock_ctlops = {
96 	sock_exit,
97 	sock_ctl_sync
98 };
99 
100 struct sock *sock_list = NULL;
101 unsigned int sock_sesrefs = 0;		/* connections to the session */
102 uint8_t sock_sescookie[AMSG_COOKIELEN];	/* owner of the session */
103 
104 void
105 sock_log(struct sock *f)
106 {
107 #ifdef DEBUG
108 	static char *rstates[] = { "ridl", "rmsg", "rdat", "rret" };
109 	static char *wstates[] = { "widl", "wmsg", "wdat" };
110 #endif
111 	if (f->slot)
112 		slot_log(f->slot);
113 	else if (f->midi)
114 		midi_log(f->midi);
115 	else if (f->ctlslot) {
116 		log_puts("ctlslot");
117 		log_putu(f->ctlslot - ctlslot_array);
118 	} else
119 		log_puts("sock");
120 #ifdef DEBUG
121 	if (log_level >= 3) {
122 		log_puts(",");
123 		log_puts(rstates[f->rstate]);
124 		log_puts(",");
125 		log_puts(wstates[f->wstate]);
126 	}
127 #endif
128 }
129 
130 void
131 sock_close(struct sock *f)
132 {
133 	struct dev *d;
134 	struct sock **pf;
135 	unsigned int tags, i;
136 
137 	for (pf = &sock_list; *pf != f; pf = &(*pf)->next) {
138 #ifdef DEBUG
139 		if (*pf == NULL) {
140 			log_puts("sock_close: not on list\n");
141 			panic();
142 		}
143 #endif
144 	}
145 	*pf = f->next;
146 
147 #ifdef DEBUG
148 	if (log_level >= 3) {
149 		sock_log(f);
150 		log_puts(": closing\n");
151 	}
152 #endif
153 	if (f->pstate > SOCK_AUTH)
154 		sock_sesrefs -= f->sesrefs;
155 	if (f->slot) {
156 		slot_del(f->slot);
157 		f->slot = NULL;
158 	}
159 	if (f->midi) {
160 		tags = midi_tags(f->midi);
161 		for (i = 0; i < DEV_NMAX; i++) {
162 			if ((tags & (1 << i)) && (d = dev_bynum(i)) != NULL)
163 				dev_unref(d);
164 		}
165 		midi_del(f->midi);
166 		f->midi = NULL;
167 	}
168 	if (f->port) {
169 		port_unref(f->port);
170 		f->port = NULL;
171 	}
172 	if (f->ctlslot) {
173 		ctlslot_del(f->ctlslot);
174 		f->ctlslot = NULL;
175 		xfree(f->ctldesc);
176 	}
177 	file_del(f->file);
178 	close(f->fd);
179 	file_slowaccept = 0;
180 	xfree(f);
181 }
182 
183 void
184 sock_slot_fill(void *arg)
185 {
186 	struct sock *f = arg;
187 	struct slot *s = f->slot;
188 
189 	f->fillpending += s->round;
190 #ifdef DEBUG
191 	if (log_level >= 4) {
192 		sock_log(f);
193 		log_puts(": fill, rmax -> ");
194 		log_puti(f->rmax);
195 		log_puts(", pending -> ");
196 		log_puti(f->fillpending);
197 		log_puts("\n");
198 	}
199 #endif
200 }
201 
202 void
203 sock_slot_flush(void *arg)
204 {
205 	struct sock *f = arg;
206 	struct slot *s = f->slot;
207 
208 	f->wmax += s->round * s->sub.bpf;
209 #ifdef DEBUG
210 	if (log_level >= 4) {
211 		sock_log(f);
212 		log_puts(": flush, wmax -> ");
213 		log_puti(f->wmax);
214 		log_puts("\n");
215 	}
216 #endif
217 }
218 
219 void
220 sock_slot_eof(void *arg)
221 {
222 	struct sock *f = arg;
223 
224 #ifdef DEBUG
225 	if (log_level >= 3) {
226 		sock_log(f);
227 		log_puts(": stopped\n");
228 	}
229 #endif
230 	f->stoppending = 1;
231 }
232 
233 void
234 sock_slot_onmove(void *arg)
235 {
236 	struct sock *f = (struct sock *)arg;
237 	struct slot *s = f->slot;
238 
239 #ifdef DEBUG
240 	if (log_level >= 4) {
241 		sock_log(f);
242 		log_puts(": onmove: delta -> ");
243 		log_puti(s->delta);
244 		log_puts("\n");
245 	}
246 #endif
247 	if (s->pstate != SOCK_START)
248 		return;
249 	f->tickpending++;
250 }
251 
252 void
253 sock_slot_onvol(void *arg)
254 {
255 	struct sock *f = (struct sock *)arg;
256 	struct slot *s = f->slot;
257 
258 #ifdef DEBUG
259 	if (log_level >= 4) {
260 		sock_log(f);
261 		log_puts(": onvol: vol -> ");
262 		log_puti(s->vol);
263 		log_puts("\n");
264 	}
265 #endif
266 	if (s->pstate != SOCK_START)
267 		return;
268 }
269 
270 void
271 sock_midi_imsg(void *arg, unsigned char *msg, int size)
272 {
273 	struct sock *f = arg;
274 
275 	midi_send(f->midi, msg, size);
276 }
277 
278 void
279 sock_midi_omsg(void *arg, unsigned char *msg, int size)
280 {
281 	struct sock *f = arg;
282 
283 	midi_out(f->midi, msg, size);
284 }
285 
286 void
287 sock_midi_fill(void *arg, int count)
288 {
289 	struct sock *f = arg;
290 
291 	f->fillpending += count;
292 }
293 
294 void
295 sock_ctl_sync(void *arg)
296 {
297 	struct sock *f = arg;
298 
299 	if (f->ctlops & SOCK_CTLDESC)
300 		f->ctlsyncpending = 1;
301 }
302 
303 struct sock *
304 sock_new(int fd)
305 {
306 	struct sock *f;
307 
308 	f = xmalloc(sizeof(struct sock));
309 	f->pstate = SOCK_AUTH;
310 	f->slot = NULL;
311 	f->port = NULL;
312 	f->midi = NULL;
313 	f->ctlslot = NULL;
314 	f->tickpending = 0;
315 	f->fillpending = 0;
316 	f->stoppending = 0;
317 	f->wstate = SOCK_WIDLE;
318 	f->wtodo = 0xdeadbeef;
319 	f->rstate = SOCK_RMSG;
320 	f->rtodo = sizeof(struct amsg);
321 	f->wmax = f->rmax = 0;
322 	f->lastvol = -1;
323 	f->ctlops = 0;
324 	f->ctlsyncpending = 0;
325 	f->file = file_new(&sock_fileops, f, "sock", 1);
326 	f->fd = fd;
327 	if (f->file == NULL) {
328 		xfree(f);
329 		return NULL;
330 	}
331 	f->next = sock_list;
332 	sock_list = f;
333 	return f;
334 }
335 
336 void
337 sock_exit(void *arg)
338 {
339 	struct sock *f = (struct sock *)arg;
340 
341 #ifdef DEBUG
342 	if (log_level >= 3) {
343 		sock_log(f);
344 		log_puts(": exit\n");
345 	}
346 #endif
347 	sock_close(f);
348 }
349 
350 /*
351  * write on the socket fd and handle errors
352  */
353 int
354 sock_fdwrite(struct sock *f, void *data, int count)
355 {
356 	int n;
357 
358 	n = write(f->fd, data, count);
359 	if (n == -1) {
360 #ifdef DEBUG
361 		if (errno == EFAULT) {
362 			log_puts("sock_fdwrite: fault\n");
363 			panic();
364 		}
365 #endif
366 		if (errno != EAGAIN) {
367 			if (log_level >= 1) {
368 				sock_log(f);
369 				log_puts(": write filed, errno = ");
370 				log_puti(errno);
371 				log_puts("\n");
372 			}
373 			sock_close(f);
374 		} else {
375 #ifdef DEBUG
376 			if (log_level >= 4) {
377 				sock_log(f);
378 				log_puts(": write blocked\n");
379 			}
380 #endif
381 		}
382 		return 0;
383 	}
384 	if (n == 0) {
385 		sock_close(f);
386 		return 0;
387 	}
388 	return n;
389 }
390 
391 /*
392  * read from the socket fd and handle errors
393  */
394 int
395 sock_fdread(struct sock *f, void *data, int count)
396 {
397 	int n;
398 
399 	n = read(f->fd, data, count);
400 	if (n == -1) {
401 #ifdef DEBUG
402 		if (errno == EFAULT) {
403 			log_puts("sock_fdread: fault\n");
404 			panic();
405 		}
406 #endif
407 		if (errno != EAGAIN) {
408 			if (log_level >= 1) {
409 				sock_log(f);
410 				log_puts(": read failed, errno = ");
411 				log_puti(errno);
412 				log_puts("\n");
413 			}
414 			sock_close(f);
415 		} else {
416 #ifdef DEBUG
417 			if (log_level >= 4) {
418 				sock_log(f);
419 				log_puts(": read blocked\n");
420 			}
421 #endif
422 		}
423 		return 0;
424 	}
425 	if (n == 0) {
426 		sock_close(f);
427 		return 0;
428 	}
429 	return n;
430 }
431 
432 /*
433  * read the next message into f->rmsg, return 1 on success
434  */
435 int
436 sock_rmsg(struct sock *f)
437 {
438 	int n;
439 	char *data;
440 
441 #ifdef DEBUG
442 	if (f->rtodo == 0) {
443 		sock_log(f);
444 		log_puts(": sock_rmsg: nothing to read\n");
445 		panic();
446 	}
447 #endif
448 	data = (char *)&f->rmsg + sizeof(struct amsg) - f->rtodo;
449 	n = sock_fdread(f, data, f->rtodo);
450 	if (n == 0)
451 		return 0;
452 	if (n < f->rtodo) {
453 		f->rtodo -= n;
454 		return 0;
455 	}
456 	f->rtodo = 0;
457 #ifdef DEBUG
458 	if (log_level >= 4) {
459 		sock_log(f);
460 		log_puts(": read full message\n");
461 	}
462 #endif
463 	return 1;
464 }
465 
466 /*
467  * write the message in f->rmsg, return 1 on success
468  */
469 int
470 sock_wmsg(struct sock *f)
471 {
472 	int n;
473 	char *data;
474 
475 #ifdef DEBUG
476 	if (f->wtodo == 0) {
477 		sock_log(f);
478 		log_puts(": sock_wmsg: already written\n");
479 	}
480 #endif
481 	data = (char *)&f->wmsg + sizeof(struct amsg) - f->wtodo;
482 	n = sock_fdwrite(f, data, f->wtodo);
483 	if (n == 0)
484 		return 0;
485 	if (n < f->wtodo) {
486 		f->wtodo -= n;
487 		return 0;
488 	}
489 	f->wtodo = 0;
490 #ifdef DEBUG
491 	if (log_level >= 4) {
492 		sock_log(f);
493 		log_puts(": wrote full message\n");
494 	}
495 #endif
496 	return 1;
497 }
498 
499 /*
500  * read data into the slot/midi ring buffer
501  */
502 int
503 sock_rdata(struct sock *f)
504 {
505 	unsigned char midibuf[MIDI_BUFSZ];
506 	unsigned char *data;
507 	int n, count;
508 
509 #ifdef DEBUG
510 	if (f->rtodo == 0) {
511 		sock_log(f);
512 		log_puts(": data block already read\n");
513 		panic();
514 	}
515 #endif
516 	while (f->rtodo > 0) {
517 		if (f->slot)
518 			data = abuf_wgetblk(&f->slot->mix.buf, &count);
519 		else {
520 			data = midibuf;
521 			count = MIDI_BUFSZ;
522 		}
523 		if (count > f->rtodo)
524 			count = f->rtodo;
525 		n = sock_fdread(f, data, count);
526 		if (n == 0)
527 			return 0;
528 		f->rtodo -= n;
529 		if (f->slot)
530 			abuf_wcommit(&f->slot->mix.buf, n);
531 		else
532 			midi_in(f->midi, midibuf, n);
533 	}
534 #ifdef DEBUG
535 	if (log_level >= 4) {
536 		sock_log(f);
537 		log_puts(": read complete block\n");
538 	}
539 #endif
540 	if (f->slot)
541 		slot_write(f->slot);
542 	return 1;
543 }
544 
545 /*
546  * write data to the slot/midi ring buffer
547  */
548 int
549 sock_wdata(struct sock *f)
550 {
551 	static unsigned char dummy[AMSG_DATAMAX];
552 	unsigned char *data = NULL;
553 	int n, count;
554 
555 #ifdef DEBUG
556 	if (f->wtodo == 0) {
557 		sock_log(f);
558 		log_puts(": attempted to write zero-sized data block\n");
559 		panic();
560 	}
561 #endif
562 	if (f->pstate == SOCK_STOP) {
563 		while (f->wtodo > 0) {
564 			n = sock_fdwrite(f, dummy, f->wtodo);
565 			if (n == 0)
566 				return 0;
567 			f->wtodo -= n;
568 		}
569 #ifdef DEBUG
570 		if (log_level >= 4) {
571 			sock_log(f);
572 			log_puts(": zero-filled remaining block\n");
573 		}
574 #endif
575 		return 1;
576 	}
577 	while (f->wtodo > 0) {
578 		/*
579 		 * f->slot and f->midi are set by sock_hello(), so
580 		 * count is always properly initialized
581 		 */
582 		if (f->slot)
583 			data = abuf_rgetblk(&f->slot->sub.buf, &count);
584 		else if (f->midi)
585 			data = abuf_rgetblk(&f->midi->obuf, &count);
586 		else {
587 			data = (unsigned char *)f->ctldesc +
588 			    (f->wsize - f->wtodo);
589 			count = f->wtodo;
590 		}
591 		if (count > f->wtodo)
592 			count = f->wtodo;
593 		n = sock_fdwrite(f, data, count);
594 		if (n == 0)
595 			return 0;
596 		f->wtodo -= n;
597 		if (f->slot)
598 			abuf_rdiscard(&f->slot->sub.buf, n);
599 		else if (f->midi)
600 			abuf_rdiscard(&f->midi->obuf, n);
601 	}
602 	if (f->slot)
603 		slot_read(f->slot);
604 	if (f->midi)
605 		midi_fill(f->midi);
606 #ifdef DEBUG
607 	if (log_level >= 4) {
608 		sock_log(f);
609 		log_puts(": wrote complete block\n");
610 	}
611 #endif
612 	return 1;
613 }
614 
615 int
616 sock_setpar(struct sock *f)
617 {
618 	struct slot *s = f->slot;
619 	struct dev *d = s->opt->dev;
620 	struct amsg_par *p = &f->rmsg.u.par;
621 	unsigned int min, max;
622 	uint32_t rate, appbufsz;
623 	uint16_t pchan, rchan;
624 
625 	rchan = ntohs(p->rchan);
626 	pchan = ntohs(p->pchan);
627 	appbufsz = ntohl(p->appbufsz);
628 	rate = ntohl(p->rate);
629 
630 	if (AMSG_ISSET(p->bits)) {
631 		if (p->bits < BITS_MIN || p->bits > BITS_MAX) {
632 #ifdef DEBUG
633 			if (log_level >= 1) {
634 				sock_log(f);
635 				log_puts(": ");
636 				log_putu(p->bits);
637 				log_puts(": bits out of bounds\n");
638 			}
639 #endif
640 			return 0;
641 		}
642 		if (AMSG_ISSET(p->bps)) {
643 			if (p->bps < ((p->bits + 7) / 8) || p->bps > 4) {
644 #ifdef DEBUG
645 				if (log_level >= 1) {
646 					sock_log(f);
647 					log_puts(": ");
648 					log_putu(p->bps);
649 					log_puts(": wrong bytes per sample\n");
650 				}
651 #endif
652 				return 0;
653 			}
654 		} else
655 			p->bps = APARAMS_BPS(p->bits);
656 		s->par.bits = p->bits;
657 		s->par.bps = p->bps;
658 	}
659 	if (AMSG_ISSET(p->sig))
660 		s->par.sig = p->sig ? 1 : 0;
661 	if (AMSG_ISSET(p->le))
662 		s->par.le = p->le ? 1 : 0;
663 	if (AMSG_ISSET(p->msb))
664 		s->par.msb = p->msb ? 1 : 0;
665 	if (AMSG_ISSET(rchan) && (s->mode & MODE_RECMASK)) {
666 		if (rchan < 1)
667 			rchan = 1;
668 		else if (rchan > NCHAN_MAX)
669 			rchan = NCHAN_MAX;
670 		s->sub.nch = rchan;
671 #ifdef DEBUG
672 		if (log_level >= 3) {
673 			sock_log(f);
674 			log_puts(": recording channels ");
675 			log_putu(s->opt->rmin);
676 			log_puts(":");
677 			log_putu(s->opt->rmax);
678 			log_puts(" -> ");
679 			log_putu(s->opt->rmin);
680 			log_puts(":");
681 			log_putu(s->opt->rmin + s->sub.nch - 1);
682 			log_puts("\n");
683 		}
684 #endif
685 	}
686 	if (AMSG_ISSET(pchan) && (s->mode & MODE_PLAY)) {
687 		if (pchan < 1)
688 			pchan = 1;
689 		else if (pchan > NCHAN_MAX)
690 			pchan = NCHAN_MAX;
691 		s->mix.nch = pchan;
692 #ifdef DEBUG
693 		if (log_level >= 3) {
694 			sock_log(f);
695 			log_puts(": playback channels ");
696 			log_putu(s->opt->pmin);
697 			log_puts(":");
698 			log_putu(s->opt->pmin + s->mix.nch - 1);
699 			log_puts(" -> ");
700 			log_putu(s->opt->pmin);
701 			log_puts(":");
702 			log_putu(s->opt->pmax);
703 			log_puts("\n");
704 		}
705 #endif
706 	}
707 	if (AMSG_ISSET(rate)) {
708 		if (rate < RATE_MIN)
709 			rate = RATE_MIN;
710 		else if (rate > RATE_MAX)
711 			rate = RATE_MAX;
712 		s->round = dev_roundof(d, rate);
713 		s->rate = rate;
714 		if (!AMSG_ISSET(appbufsz)) {
715 			appbufsz = d->bufsz / d->round * s->round;
716 #ifdef DEBUG
717 			if (log_level >= 3) {
718 				sock_log(f);
719 				log_puts(": ");
720 				log_putu(appbufsz);
721 				log_puts(" frame buffer\n");
722 			}
723 #endif
724 		}
725 #ifdef DEBUG
726 		if (log_level >= 3) {
727 			sock_log(f);
728 			log_puts(": ");
729 			log_putu(rate);
730 			log_puts("Hz sample rate, ");
731 			log_putu(s->round);
732 			log_puts(" frame blocks\n");
733 		}
734 #endif
735 	}
736 	if (AMSG_ISSET(p->xrun)) {
737 		if (p->xrun != XRUN_IGNORE &&
738 		    p->xrun != XRUN_SYNC &&
739 		    p->xrun != XRUN_ERROR) {
740 #ifdef DEBUG
741 			if (log_level >= 1) {
742 				sock_log(f);
743 				log_puts(": ");
744 				log_putx(p->xrun);
745 				log_puts(": bad xrun policy\n");
746 			}
747 #endif
748 			return 0;
749 		}
750 		s->xrun = p->xrun;
751 		if (s->opt->mtc != NULL && s->xrun == XRUN_IGNORE)
752 			s->xrun = XRUN_SYNC;
753 #ifdef DEBUG
754 		if (log_level >= 3) {
755 			sock_log(f);
756 			log_puts(": 0x");
757 			log_putx(s->xrun);
758 			log_puts(" xrun policy\n");
759 		}
760 #endif
761 	}
762 	if (AMSG_ISSET(appbufsz)) {
763 		rate = s->rate;
764 		min = 1;
765 		max = 1 + rate / d->round;
766 		min *= s->round;
767 		max *= s->round;
768 		appbufsz += s->round / 2;
769 		appbufsz -= appbufsz % s->round;
770 		if (appbufsz < min)
771 			appbufsz = min;
772 		if (appbufsz > max)
773 			appbufsz = max;
774 		s->appbufsz = appbufsz;
775 #ifdef DEBUG
776 		if (log_level >= 3) {
777 			sock_log(f);
778 			log_puts(": ");
779 			log_putu(s->appbufsz);
780 			log_puts(" frame buffer\n");
781 		}
782 #endif
783 	}
784 	return 1;
785 }
786 
787 int
788 sock_auth(struct sock *f)
789 {
790 	struct amsg_auth *p = &f->rmsg.u.auth;
791 	uid_t euid;
792 	gid_t egid;
793 
794 	/*
795 	 * root bypasses any authenication checks and has no session
796 	 */
797 	if (getpeereid(f->fd, &euid, &egid) == 0 && euid == 0) {
798 		f->pstate = SOCK_HELLO;
799 		f->sesrefs = 0;
800 		return 1;
801 	}
802 
803 	if (sock_sesrefs == 0) {
804 		/* start a new session */
805 		memcpy(sock_sescookie, p->cookie, AMSG_COOKIELEN);
806 		f->sesrefs = 1;
807 	} else if (memcmp(sock_sescookie, p->cookie, AMSG_COOKIELEN) != 0) {
808 		/* another session is active, drop connection */
809 		return 0;
810 	}
811 	sock_sesrefs += f->sesrefs;
812 	f->pstate = SOCK_HELLO;
813 	return 1;
814 }
815 
816 int
817 sock_hello(struct sock *f)
818 {
819 	struct amsg_hello *p = &f->rmsg.u.hello;
820 	struct port *c;
821 	struct dev *d;
822 	struct opt *opt;
823 	unsigned int mode;
824 	unsigned int id;
825 
826 	mode = ntohs(p->mode);
827 	id = ntohl(p->id);
828 #ifdef DEBUG
829 	if (log_level >= 3) {
830 		sock_log(f);
831 		log_puts(": hello from <");
832 		log_puts(p->who);
833 		log_puts(">, mode = ");
834 		log_putx(mode);
835 		log_puts(", ver ");
836 		log_putu(p->version);
837 		log_puts("\n");
838 	}
839 #endif
840 	if (p->version != AMSG_VERSION) {
841 		if (log_level >= 1) {
842 			sock_log(f);
843 			log_puts(": ");
844 			log_putu(p->version);
845 			log_puts(": unsupported protocol version\n");
846 		}
847 		return 0;
848 	}
849 	switch (mode) {
850 	case MODE_MIDIIN:
851 	case MODE_MIDIOUT:
852 	case MODE_MIDIOUT | MODE_MIDIIN:
853 	case MODE_REC:
854 	case MODE_PLAY:
855 	case MODE_PLAY | MODE_REC:
856 	case MODE_CTLREAD:
857 	case MODE_CTLWRITE:
858 	case MODE_CTLREAD | MODE_CTLWRITE:
859 		break;
860 	default:
861 #ifdef DEBUG
862 		if (log_level >= 1) {
863 			sock_log(f);
864 			log_puts(": ");
865 			log_putx(mode);
866 			log_puts(": unsupported mode\n");
867 		}
868 #endif
869 		return 0;
870 	}
871 	f->pstate = SOCK_INIT;
872 	f->port = NULL;
873 	if (mode & MODE_MIDIMASK) {
874 		f->slot = NULL;
875 		f->midi = midi_new(&sock_midiops, f, mode);
876 		if (f->midi == NULL)
877 			return 0;
878 		/* XXX: add 'devtype' to libsndio */
879 		if (p->devnum < 16) {
880 			d = dev_bynum(p->devnum);
881 			if (d == NULL)
882 				return 0;
883 			opt = opt_byname(d, p->opt);
884 			if (opt == NULL)
885 				return 0;
886 			if (!dev_ref(d))
887 				return 0;
888 			midi_tag(f->midi, opt->num);
889 		} else if (p->devnum < 32) {
890 			midi_tag(f->midi, p->devnum);
891 		} else if (p->devnum < 48) {
892 			c = port_bynum(p->devnum - 32);
893 			if (c == NULL || !port_ref(c))
894 				return 0;
895 			f->port = c;
896 			midi_link(f->midi, c->midi);
897 		} else
898 			return 0;
899 		return 1;
900 	}
901 	if (mode & MODE_CTLMASK) {
902 		d = dev_bynum(p->devnum);
903 		if (d == NULL) {
904 			if (log_level >= 2) {
905 				sock_log(f);
906 				log_puts(": ");
907 				log_putu(p->devnum);
908 				log_puts(": no such device\n");
909 			}
910 			return 0;
911 		}
912 		opt = opt_byname(d, p->opt);
913 		if (opt == NULL)
914 			return 0;
915 		f->ctlslot = ctlslot_new(opt, &sock_ctlops, f);
916 		if (f->ctlslot == NULL) {
917 			if (log_level >= 2) {
918 				sock_log(f);
919 				log_puts(": couldn't get slot\n");
920 			}
921 			return 0;
922 		}
923 		f->ctldesc = xmalloc(SOCK_CTLDESC_SIZE *
924 		    sizeof(struct amsg_ctl_desc));
925 		f->ctlops = 0;
926 		f->ctlsyncpending = 0;
927 		return 1;
928 	}
929 	d = dev_bynum(p->devnum);
930 	if (d == NULL)
931 		return 0;
932 	opt = opt_byname(d, p->opt);
933 	if (opt == NULL)
934 		return 0;
935 	f->slot = slot_new(opt, id, p->who, &sock_slotops, f, mode);
936 	if (f->slot == NULL)
937 		return 0;
938 	f->midi = NULL;
939 	return 1;
940 }
941 
942 /*
943  * execute the message in f->rmsg, return 1 on success
944  */
945 int
946 sock_execmsg(struct sock *f)
947 {
948 	struct ctl *c;
949 	struct slot *s = f->slot;
950 	struct amsg *m = &f->rmsg;
951 	unsigned char *data;
952 	int size, ctl;
953 
954 	switch (ntohl(m->cmd)) {
955 	case AMSG_DATA:
956 #ifdef DEBUG
957 		if (log_level >= 4) {
958 			sock_log(f);
959 			log_puts(": DATA message\n");
960 		}
961 #endif
962 		if (s != NULL && f->pstate != SOCK_START) {
963 #ifdef DEBUG
964 			if (log_level >= 1) {
965 				sock_log(f);
966 				log_puts(": DATA, wrong state\n");
967 			}
968 #endif
969 			sock_close(f);
970 			return 0;
971 		}
972 		if ((f->slot && !(f->slot->mode & MODE_PLAY)) ||
973 		    (f->midi && !(f->midi->mode & MODE_MIDIOUT))) {
974 #ifdef DEBUG
975 			if (log_level >= 1) {
976 				sock_log(f);
977 				log_puts(": DATA, input-only mode\n");
978 			}
979 #endif
980 			sock_close(f);
981 			return 0;
982 		}
983 		size = ntohl(m->u.data.size);
984 		if (size <= 0) {
985 #ifdef DEBUG
986 			if (log_level >= 1) {
987 				sock_log(f);
988 				log_puts(": zero size payload\n");
989 			}
990 #endif
991 			sock_close(f);
992 			return 0;
993 		}
994 		if (s != NULL && size % s->mix.bpf != 0) {
995 #ifdef DEBUG
996 			if (log_level >= 1) {
997 				sock_log(f);
998 				log_puts(": not aligned to frame\n");
999 			}
1000 #endif
1001 			sock_close(f);
1002 			return 0;
1003 		}
1004 		if (s != NULL && size > f->ralign) {
1005 #ifdef DEBUG
1006 			if (log_level >= 1) {
1007 				sock_log(f);
1008 				log_puts(": size = ");
1009 				log_puti(size);
1010 				log_puts(": ralign = ");
1011 				log_puti(f->ralign);
1012 				log_puts(": not aligned to block\n");
1013 			}
1014 #endif
1015 			sock_close(f);
1016 			return 0;
1017 		}
1018 		f->rstate = SOCK_RDATA;
1019 		f->rsize = f->rtodo = size;
1020 		if (s != NULL) {
1021 			f->ralign -= size;
1022 			if (f->ralign == 0)
1023 				f->ralign = s->round * s->mix.bpf;
1024 		}
1025 		if (f->rtodo > f->rmax) {
1026 #ifdef DEBUG
1027 			if (log_level >= 1) {
1028 				sock_log(f);
1029 				log_puts(": unexpected data, size = ");
1030 				log_putu(size);
1031 				log_puts(", rmax = ");
1032 				log_putu(f->rmax);
1033 				log_puts("\n");
1034 			}
1035 #endif
1036 			sock_close(f);
1037 			return 0;
1038 		}
1039 		f->rmax -= f->rtodo;
1040 		if (f->rtodo == 0) {
1041 #ifdef DEBUG
1042 			if (log_level >= 1) {
1043 				sock_log(f);
1044 				log_puts(": zero-length data chunk\n");
1045 			}
1046 #endif
1047 			sock_close(f);
1048 			return 0;
1049 		}
1050 		break;
1051 	case AMSG_START:
1052 #ifdef DEBUG
1053 		if (log_level >= 3) {
1054 			sock_log(f);
1055 			log_puts(": START message\n");
1056 		}
1057 #endif
1058 		if (f->pstate != SOCK_INIT || s == NULL) {
1059 #ifdef DEBUG
1060 			if (log_level >= 1) {
1061 				sock_log(f);
1062 				log_puts(": START, wrong state\n");
1063 			}
1064 #endif
1065 			sock_close(f);
1066 			return 0;
1067 		}
1068 		f->tickpending = 0;
1069 		f->stoppending = 0;
1070 		slot_start(s);
1071 		if (s->mode & MODE_PLAY) {
1072 			f->fillpending = s->appbufsz;
1073 			f->ralign = s->round * s->mix.bpf;
1074 			f->rmax = 0;
1075 		}
1076 		if (s->mode & MODE_RECMASK) {
1077 			f->walign = s->round * s->sub.bpf;
1078 			f->wmax = 0;
1079 		}
1080 		f->pstate = SOCK_START;
1081 		f->rstate = SOCK_RMSG;
1082 		f->rtodo = sizeof(struct amsg);
1083 		if (log_level >= 2) {
1084 			slot_log(f->slot);
1085 			log_puts(": ");
1086 			log_putu(s->rate);
1087 			log_puts("Hz, ");
1088 			aparams_log(&s->par);
1089 			if (s->mode & MODE_PLAY) {
1090 				log_puts(", play ");
1091 				log_puti(s->opt->pmin);
1092 				log_puts(":");
1093 				log_puti(s->opt->pmin + s->mix.nch - 1);
1094 			}
1095 			if (s->mode & MODE_RECMASK) {
1096 				log_puts(", rec ");
1097 				log_puti(s->opt->rmin);
1098 				log_puts(":");
1099 				log_puti(s->opt->rmin + s->sub.nch - 1);
1100 			}
1101 			log_puts(", ");
1102 			log_putu(s->appbufsz / s->round);
1103 			log_puts(" blocks of ");
1104 			log_putu(s->round);
1105 			log_puts(" frames\n");
1106 		}
1107 		break;
1108 	case AMSG_STOP:
1109 #ifdef DEBUG
1110 		if (log_level >= 3) {
1111 			sock_log(f);
1112 			log_puts(": STOP message\n");
1113 		}
1114 #endif
1115 		if (f->pstate != SOCK_START) {
1116 #ifdef DEBUG
1117 			if (log_level >= 1) {
1118 				sock_log(f);
1119 				log_puts(": STOP, wrong state\n");
1120 			}
1121 #endif
1122 			sock_close(f);
1123 			return 0;
1124 		}
1125 		f->rmax = 0;
1126 		if (!(s->mode & MODE_PLAY))
1127 			f->stoppending = 1;
1128 		f->pstate = SOCK_STOP;
1129 		f->rstate = SOCK_RMSG;
1130 		f->rtodo = sizeof(struct amsg);
1131 		if (s->mode & MODE_PLAY) {
1132 			if (f->ralign < s->round * s->mix.bpf) {
1133 				data = abuf_wgetblk(&s->mix.buf, &size);
1134 #ifdef DEBUG
1135 				if (size < f->ralign) {
1136 					sock_log(f);
1137 					log_puts(": unaligned stop, size = ");
1138 					log_putu(size);
1139 					log_puts(", ralign = ");
1140 					log_putu(f->ralign);
1141 					log_puts("\n");
1142 					panic();
1143 				}
1144 #endif
1145 				memset(data, 0, f->ralign);
1146 				abuf_wcommit(&s->mix.buf, f->ralign);
1147 				f->ralign = s->round * s->mix.bpf;
1148 			}
1149 		}
1150 		slot_stop(s, 1);
1151 		break;
1152 	case AMSG_SETPAR:
1153 #ifdef DEBUG
1154 		if (log_level >= 3) {
1155 			sock_log(f);
1156 			log_puts(": SETPAR message\n");
1157 		}
1158 #endif
1159 		if (f->pstate != SOCK_INIT || s == NULL) {
1160 #ifdef DEBUG
1161 			if (log_level >= 1) {
1162 				sock_log(f);
1163 				log_puts(": SETPAR, wrong state\n");
1164 			}
1165 #endif
1166 			sock_close(f);
1167 			return 0;
1168 		}
1169 		if (!sock_setpar(f)) {
1170 			sock_close(f);
1171 			return 0;
1172 		}
1173 		f->rtodo = sizeof(struct amsg);
1174 		f->rstate = SOCK_RMSG;
1175 		break;
1176 	case AMSG_GETPAR:
1177 #ifdef DEBUG
1178 		if (log_level >= 3) {
1179 			sock_log(f);
1180 			log_puts(": GETPAR message\n");
1181 		}
1182 #endif
1183 		if (f->pstate != SOCK_INIT || s == NULL) {
1184 #ifdef DEBUG
1185 			if (log_level >= 1) {
1186 				sock_log(f);
1187 				log_puts(": GETPAR, wrong state\n");
1188 			}
1189 #endif
1190 			sock_close(f);
1191 			return 0;
1192 		}
1193 		AMSG_INIT(m);
1194 		m->cmd = htonl(AMSG_GETPAR);
1195 		m->u.par.legacy_mode = s->mode;
1196 		m->u.par.xrun = s->xrun;
1197 		m->u.par.bits = s->par.bits;
1198 		m->u.par.bps = s->par.bps;
1199 		m->u.par.sig = s->par.sig;
1200 		m->u.par.le = s->par.le;
1201 		m->u.par.msb = s->par.msb;
1202 		if (s->mode & MODE_PLAY)
1203 			m->u.par.pchan = htons(s->mix.nch);
1204 		if (s->mode & MODE_RECMASK)
1205 			m->u.par.rchan = htons(s->sub.nch);
1206 		m->u.par.rate = htonl(s->rate);
1207 		m->u.par.appbufsz = htonl(s->appbufsz);
1208 		m->u.par.bufsz = htonl(SLOT_BUFSZ(s));
1209 		m->u.par.round = htonl(s->round);
1210 		f->rstate = SOCK_RRET;
1211 		f->rtodo = sizeof(struct amsg);
1212 		break;
1213 	case AMSG_SETVOL:
1214 #ifdef DEBUG
1215 		if (log_level >= 3) {
1216 			sock_log(f);
1217 			log_puts(": SETVOL message\n");
1218 		}
1219 #endif
1220 		if (f->pstate < SOCK_INIT || s == NULL) {
1221 #ifdef DEBUG
1222 			if (log_level >= 1) {
1223 				sock_log(f);
1224 				log_puts(": SETVOL, wrong state\n");
1225 			}
1226 #endif
1227 			sock_close(f);
1228 			return 0;
1229 		}
1230 		ctl = ntohl(m->u.vol.ctl);
1231 		if (ctl > MIDI_MAXCTL) {
1232 #ifdef DEBUG
1233 			if (log_level >= 1) {
1234 				sock_log(f);
1235 				log_puts(": SETVOL, volume out of range\n");
1236 			}
1237 #endif
1238 			sock_close(f);
1239 			return 0;
1240 		}
1241 		f->rtodo = sizeof(struct amsg);
1242 		f->rstate = SOCK_RMSG;
1243 		f->lastvol = ctl; /* dont trigger feedback message */
1244 		slot_setvol(s, ctl);
1245 		dev_midi_vol(s->opt->dev, s);
1246 		ctl_onval(CTL_SLOT_LEVEL, s, NULL, ctl);
1247 		break;
1248 	case AMSG_CTLSUB:
1249 #ifdef DEBUG
1250 		if (log_level >= 3) {
1251 			sock_log(f);
1252 			log_puts(": CTLSUB message, desc = ");
1253 			log_putx(m->u.ctlsub.desc);
1254 			log_puts(", val = ");
1255 			log_putx(m->u.ctlsub.val);
1256 			log_puts("\n");
1257 		}
1258 #endif
1259 		if (f->pstate != SOCK_INIT || f->ctlslot == NULL) {
1260 #ifdef DEBUG
1261 			if (log_level >= 1) {
1262 				sock_log(f);
1263 				log_puts(": CTLSUB, wrong state\n");
1264 			}
1265 #endif
1266 			sock_close(f);
1267 			return 0;
1268 		}
1269 		if (m->u.ctlsub.desc) {
1270 			if (!(f->ctlops & SOCK_CTLDESC)) {
1271 				ctl = f->ctlslot->self;
1272 				c = ctl_list;
1273 				while (c != NULL) {
1274 					if (ctlslot_visible(f->ctlslot, c))
1275 						c->desc_mask |= ctl;
1276 					c = c->next;
1277 				}
1278 				f->ctlops |= SOCK_CTLDESC;
1279 				f->ctlsyncpending = 1;
1280 			}
1281 		} else
1282 			f->ctlops &= ~SOCK_CTLDESC;
1283 		if (m->u.ctlsub.val) {
1284 			f->ctlops |= SOCK_CTLVAL;
1285 		} else
1286 			f->ctlops &= ~SOCK_CTLVAL;
1287 		f->rstate = SOCK_RMSG;
1288 		f->rtodo = sizeof(struct amsg);
1289 		break;
1290 	case AMSG_CTLSET:
1291 #ifdef DEBUG
1292 		if (log_level >= 3) {
1293 			sock_log(f);
1294 			log_puts(": CTLSET message\n");
1295 		}
1296 #endif
1297 		if (f->pstate < SOCK_INIT || f->ctlslot == NULL) {
1298 #ifdef DEBUG
1299 			if (log_level >= 1) {
1300 				sock_log(f);
1301 				log_puts(": CTLSET, wrong state\n");
1302 			}
1303 #endif
1304 			sock_close(f);
1305 			return 0;
1306 		}
1307 
1308 		c = ctlslot_lookup(f->ctlslot, ntohs(m->u.ctlset.addr));
1309 		if (c == NULL) {
1310 #ifdef DEBUG
1311 			if (log_level >= 1) {
1312 				sock_log(f);
1313 				log_puts(": CTLSET, wrong addr\n");
1314 			}
1315 #endif
1316 			sock_close(f);
1317 			return 0;
1318 		}
1319 		if (!ctl_setval(c, ntohs(m->u.ctlset.val))) {
1320 #ifdef DEBUG
1321 			if (log_level >= 1) {
1322 				sock_log(f);
1323 				log_puts(": CTLSET, bad value\n");
1324 			}
1325 #endif
1326 			sock_close(f);
1327 			return 0;
1328 		}
1329 		f->rtodo = sizeof(struct amsg);
1330 		f->rstate = SOCK_RMSG;
1331 		break;
1332 	case AMSG_AUTH:
1333 #ifdef DEBUG
1334 		if (log_level >= 3) {
1335 			sock_log(f);
1336 			log_puts(": AUTH message\n");
1337 		}
1338 #endif
1339 		if (f->pstate != SOCK_AUTH) {
1340 #ifdef DEBUG
1341 			if (log_level >= 1) {
1342 				sock_log(f);
1343 				log_puts(": AUTH, wrong state\n");
1344 			}
1345 #endif
1346 			sock_close(f);
1347 			return 0;
1348 		}
1349 		if (!sock_auth(f)) {
1350 			sock_close(f);
1351 			return 0;
1352 		}
1353 		f->rstate = SOCK_RMSG;
1354 		f->rtodo = sizeof(struct amsg);
1355 		break;
1356 	case AMSG_HELLO:
1357 #ifdef DEBUG
1358 		if (log_level >= 3) {
1359 			sock_log(f);
1360 			log_puts(": HELLO message\n");
1361 		}
1362 #endif
1363 		if (f->pstate != SOCK_HELLO) {
1364 #ifdef DEBUG
1365 			if (log_level >= 1) {
1366 				sock_log(f);
1367 				log_puts(": HELLO, wrong state\n");
1368 			}
1369 #endif
1370 			sock_close(f);
1371 			return 0;
1372 		}
1373 		if (!sock_hello(f)) {
1374 			sock_close(f);
1375 			return 0;
1376 		}
1377 		AMSG_INIT(m);
1378 		m->cmd = htonl(AMSG_ACK);
1379 		f->rstate = SOCK_RRET;
1380 		f->rtodo = sizeof(struct amsg);
1381 		break;
1382 	case AMSG_BYE:
1383 #ifdef DEBUG
1384 		if (log_level >= 3) {
1385 			sock_log(f);
1386 			log_puts(": BYE message\n");
1387 		}
1388 #endif
1389 		if (s != NULL && f->pstate != SOCK_INIT) {
1390 #ifdef DEBUG
1391 			if (log_level >= 1) {
1392 				sock_log(f);
1393 				log_puts(": BYE, wrong state\n");
1394 			}
1395 #endif
1396 		}
1397 		sock_close(f);
1398 		return 0;
1399 	default:
1400 #ifdef DEBUG
1401 		if (log_level >= 1) {
1402 			sock_log(f);
1403 			log_puts(": unknown command in message\n");
1404 		}
1405 #endif
1406 		sock_close(f);
1407 		return 0;
1408 	}
1409 	return 1;
1410 }
1411 
1412 /*
1413  * build a message in f->wmsg, return 1 on success and 0 if
1414  * there's nothing to do. Assume f->wstate is SOCK_WIDLE
1415  */
1416 int
1417 sock_buildmsg(struct sock *f)
1418 {
1419 	unsigned int size, type, mask;
1420 	struct amsg_ctl_desc *desc;
1421 	struct ctl *c, **pc;
1422 
1423 	/*
1424 	 * If pos changed (or initial tick), build a MOVE message.
1425 	 */
1426 	if (f->tickpending) {
1427 #ifdef DEBUG
1428 		if (log_level >= 4) {
1429 			sock_log(f);
1430 			log_puts(": building MOVE message, delta = ");
1431 			log_puti(f->slot->delta);
1432 			log_puts("\n");
1433 		}
1434 #endif
1435 		AMSG_INIT(&f->wmsg);
1436 		f->wmsg.cmd = htonl(AMSG_MOVE);
1437 		f->wmsg.u.ts.delta = htonl(f->slot->delta);
1438 		f->wtodo = sizeof(struct amsg);
1439 		f->wstate = SOCK_WMSG;
1440 		f->tickpending = 0;
1441 		/*
1442 		 * XXX: use tickpending as accumulator rather than
1443 		 * slot->delta
1444 		 */
1445 		f->slot->delta = 0;
1446 		return 1;
1447 	}
1448 
1449 	if (f->fillpending > 0) {
1450 		AMSG_INIT(&f->wmsg);
1451 		f->wmsg.cmd = htonl(AMSG_FLOWCTL);
1452 		f->wmsg.u.ts.delta = htonl(f->fillpending);
1453 		size = f->fillpending;
1454 		if (f->slot)
1455 			size *= f->slot->mix.bpf;
1456 		f->rmax += size;
1457 #ifdef DEBUG
1458 		if (log_level >= 4) {
1459 			sock_log(f);
1460 			log_puts(": building FLOWCTL message, count = ");
1461 			log_puti(f->fillpending);
1462 			log_puts(", rmax -> ");
1463 			log_puti(f->rmax);
1464 			log_puts("\n");
1465 		}
1466 #endif
1467 		f->wtodo = sizeof(struct amsg);
1468 		f->wstate = SOCK_WMSG;
1469 		f->fillpending = 0;
1470 		return 1;
1471 	}
1472 
1473 	/*
1474 	 * if volume changed build a SETVOL message
1475 	 */
1476 	if (f->pstate >= SOCK_START && f->slot->vol != f->lastvol) {
1477 #ifdef DEBUG
1478 		if (log_level >= 3) {
1479 			sock_log(f);
1480 			log_puts(": building SETVOL message, vol = ");
1481 			log_puti(f->slot->vol);
1482 			log_puts("\n");
1483 		}
1484 #endif
1485 		AMSG_INIT(&f->wmsg);
1486 		f->wmsg.cmd = htonl(AMSG_SETVOL);
1487 		f->wmsg.u.vol.ctl = htonl(f->slot->vol);
1488 		f->wtodo = sizeof(struct amsg);
1489 		f->wstate = SOCK_WMSG;
1490 		f->lastvol = f->slot->vol;
1491 		return 1;
1492 	}
1493 
1494 	if (f->midi != NULL && f->midi->obuf.used > 0) {
1495 		size = f->midi->obuf.used;
1496 		if (size > AMSG_DATAMAX)
1497 			size = AMSG_DATAMAX;
1498 		AMSG_INIT(&f->wmsg);
1499 		f->wmsg.cmd = htonl(AMSG_DATA);
1500 		f->wmsg.u.data.size = htonl(size);
1501 		f->wtodo = sizeof(struct amsg);
1502 		f->wstate = SOCK_WMSG;
1503 		return 1;
1504 	}
1505 
1506 	/*
1507 	 * If data available, build a DATA message.
1508 	 */
1509 	if (f->slot != NULL && f->wmax > 0 && f->slot->sub.buf.used > 0) {
1510 		size = f->slot->sub.buf.used;
1511 		if (size > AMSG_DATAMAX)
1512 			size = AMSG_DATAMAX;
1513 		if (size > f->walign)
1514 			size = f->walign;
1515 		if (size > f->wmax)
1516 			size = f->wmax;
1517 		size -= size % f->slot->sub.bpf;
1518 #ifdef DEBUG
1519 		if (size == 0) {
1520 			sock_log(f);
1521 			log_puts(": sock_buildmsg size == 0\n");
1522 			panic();
1523 		}
1524 #endif
1525 		f->walign -= size;
1526 		f->wmax -= size;
1527 		if (f->walign == 0)
1528 			f->walign = f->slot->round * f->slot->sub.bpf;
1529 #ifdef DEBUG
1530 		if (log_level >= 4) {
1531 			sock_log(f);
1532 			log_puts(": building audio DATA message, size = ");
1533 			log_puti(size);
1534 			log_puts("\n");
1535 		}
1536 #endif
1537 		AMSG_INIT(&f->wmsg);
1538 		f->wmsg.cmd = htonl(AMSG_DATA);
1539 		f->wmsg.u.data.size = htonl(size);
1540 		f->wtodo = sizeof(struct amsg);
1541 		f->wstate = SOCK_WMSG;
1542 		return 1;
1543 	}
1544 
1545 	if (f->stoppending) {
1546 #ifdef DEBUG
1547 		if (log_level >= 3) {
1548 			sock_log(f);
1549 			log_puts(": building STOP message\n");
1550 		}
1551 #endif
1552 		f->stoppending = 0;
1553 		f->pstate = SOCK_INIT;
1554 		AMSG_INIT(&f->wmsg);
1555 		f->wmsg.cmd = htonl(AMSG_STOP);
1556 		f->wtodo = sizeof(struct amsg);
1557 		f->wstate = SOCK_WMSG;
1558 		return 1;
1559 	}
1560 
1561 	/*
1562 	 * XXX: add a flag indicating if there are changes
1563 	 * in controls not seen by this client, rather
1564 	 * than walking through the full list of control
1565 	 * searching for the {desc,val}_mask bits
1566 	 */
1567 	if (f->ctlslot && (f->ctlops & SOCK_CTLDESC)) {
1568 		desc = f->ctldesc;
1569 		mask = f->ctlslot->self;
1570 		size = 0;
1571 		pc = &ctl_list;
1572 		while ((c = *pc) != NULL) {
1573 			if ((c->desc_mask & mask) == 0 ||
1574 			    (c->refs_mask & mask) == 0) {
1575 				pc = &c->next;
1576 				continue;
1577 			}
1578 			if (size == SOCK_CTLDESC_SIZE *
1579 				sizeof(struct amsg_ctl_desc))
1580 				break;
1581 			c->desc_mask &= ~mask;
1582 			c->val_mask &= ~mask;
1583 			type = ctlslot_visible(f->ctlslot, c) ?
1584 			    c->type : CTL_NONE;
1585 			strlcpy(desc->group, (f->ctlslot->opt == NULL ||
1586 			    strcmp(c->group, f->ctlslot->opt->dev->name) != 0) ?
1587 			    c->group : "",
1588 			    AMSG_CTL_NAMEMAX);
1589 			strlcpy(desc->node0.name, c->node0.name,
1590 			    AMSG_CTL_NAMEMAX);
1591 			desc->node0.unit = ntohs(c->node0.unit);
1592 			strlcpy(desc->node1.name, c->node1.name,
1593 			    AMSG_CTL_NAMEMAX);
1594 			desc->node1.unit = ntohs(c->node1.unit);
1595 			desc->type = type;
1596 			strlcpy(desc->func, c->func, AMSG_CTL_NAMEMAX);
1597 			desc->addr = htons(c->addr);
1598 			desc->maxval = htons(c->maxval);
1599 			desc->curval = htons(c->curval);
1600 			size += sizeof(struct amsg_ctl_desc);
1601 			desc++;
1602 
1603 			/* if this is a deleted entry unref it */
1604 			if (type == CTL_NONE) {
1605 				c->refs_mask &= ~mask;
1606 				if (c->refs_mask == 0) {
1607 					*pc = c->next;
1608 					xfree(c);
1609 					continue;
1610 				}
1611 			}
1612 
1613 			pc = &c->next;
1614 		}
1615 		if (size > 0) {
1616 			AMSG_INIT(&f->wmsg);
1617 			f->wmsg.cmd = htonl(AMSG_DATA);
1618 			f->wmsg.u.data.size = htonl(size);
1619 			f->wtodo = sizeof(struct amsg);
1620 			f->wstate = SOCK_WMSG;
1621 #ifdef DEBUG
1622 			if (log_level >= 3) {
1623 				sock_log(f);
1624 				log_puts(": building control DATA message\n");
1625 			}
1626 #endif
1627 			return 1;
1628 		}
1629 	}
1630 	if (f->ctlslot && (f->ctlops & SOCK_CTLVAL)) {
1631 		mask = f->ctlslot->self;
1632 		for (c = ctl_list; c != NULL; c = c->next) {
1633 			if (!ctlslot_visible(f->ctlslot, c))
1634 				continue;
1635 			if ((c->val_mask & mask) == 0)
1636 				continue;
1637 			c->val_mask &= ~mask;
1638 			AMSG_INIT(&f->wmsg);
1639 			f->wmsg.cmd = htonl(AMSG_CTLSET);
1640 			f->wmsg.u.ctlset.addr = htons(c->addr);
1641 			f->wmsg.u.ctlset.val = htons(c->curval);
1642 			f->wtodo = sizeof(struct amsg);
1643 			f->wstate = SOCK_WMSG;
1644 #ifdef DEBUG
1645 			if (log_level >= 3) {
1646 				sock_log(f);
1647 				log_puts(": building CTLSET message\n");
1648 			}
1649 #endif
1650 			return 1;
1651 		}
1652 	}
1653 	if (f->ctlslot && f->ctlsyncpending) {
1654 		f->ctlsyncpending = 0;
1655 		f->wmsg.cmd = htonl(AMSG_CTLSYNC);
1656 		f->wtodo = sizeof(struct amsg);
1657 		f->wstate = SOCK_WMSG;
1658 #ifdef DEBUG
1659 		if (log_level >= 3) {
1660 			sock_log(f);
1661 			log_puts(": building CTLSYNC message\n");
1662 		}
1663 #endif
1664 		return 1;
1665 	}
1666 #ifdef DEBUG
1667 	if (log_level >= 4) {
1668 		sock_log(f);
1669 		log_puts(": no messages to build anymore, idling...\n");
1670 	}
1671 #endif
1672 	f->wstate = SOCK_WIDLE;
1673 	return 0;
1674 }
1675 
1676 /*
1677  * iteration of the socket reader loop, return 1 on success
1678  */
1679 int
1680 sock_read(struct sock *f)
1681 {
1682 #ifdef DEBUG
1683 	if (log_level >= 4) {
1684 		sock_log(f);
1685 		log_puts(": reading ");
1686 		log_putu(f->rtodo);
1687 		log_puts(" todo\n");
1688 	}
1689 #endif
1690 	switch (f->rstate) {
1691 	case SOCK_RIDLE:
1692 		return 0;
1693 	case SOCK_RMSG:
1694 		if (!sock_rmsg(f))
1695 			return 0;
1696 		if (!sock_execmsg(f))
1697 			return 0;
1698 		break;
1699 	case SOCK_RDATA:
1700 		if (!sock_rdata(f))
1701 			return 0;
1702 		f->rstate = SOCK_RMSG;
1703 		f->rtodo = sizeof(struct amsg);
1704 		break;
1705 	case SOCK_RRET:
1706 		if (f->wstate != SOCK_WIDLE) {
1707 #ifdef DEBUG
1708 			if (log_level >= 4) {
1709 				sock_log(f);
1710 				log_puts(": can't reply, write-end blocked\n");
1711 			}
1712 #endif
1713 			return 0;
1714 		}
1715 		f->wmsg = f->rmsg;
1716 		f->wstate = SOCK_WMSG;
1717 		f->wtodo = sizeof(struct amsg);
1718 		f->rstate = SOCK_RMSG;
1719 		f->rtodo = sizeof(struct amsg);
1720 #ifdef DEBUG
1721 		if (log_level >= 4) {
1722 			sock_log(f);
1723 			log_puts(": copied RRET message\n");
1724 		}
1725 #endif
1726 	}
1727 	return 1;
1728 }
1729 
1730 /*
1731  * iteration of the socket writer loop, return 1 on success
1732  */
1733 int
1734 sock_write(struct sock *f)
1735 {
1736 #ifdef DEBUG
1737 	if (log_level >= 4) {
1738 		sock_log(f);
1739 		log_puts(": writing");
1740 		if (f->wstate != SOCK_WIDLE) {
1741 			log_puts(" todo = ");
1742 			log_putu(f->wtodo);
1743 		}
1744 		log_puts("\n");
1745 	}
1746 #endif
1747 	switch (f->wstate) {
1748 	case SOCK_WMSG:
1749 		if (!sock_wmsg(f))
1750 			return 0;
1751 		/*
1752 		 * f->wmsg is either build by sock_buildmsg() or
1753 		 * copied from f->rmsg (in the SOCK_RRET state), so
1754 		 * it's safe.
1755 		 */
1756 		if (ntohl(f->wmsg.cmd) != AMSG_DATA) {
1757 			f->wstate = SOCK_WIDLE;
1758 			f->wtodo = 0xdeadbeef;
1759 			break;
1760 		}
1761 		f->wstate = SOCK_WDATA;
1762 		f->wsize = f->wtodo = ntohl(f->wmsg.u.data.size);
1763 		/* PASSTHROUGH */
1764 	case SOCK_WDATA:
1765 		if (!sock_wdata(f))
1766 			return 0;
1767 		if (f->wtodo > 0)
1768 			break;
1769 		f->wstate = SOCK_WIDLE;
1770 		f->wtodo = 0xdeadbeef;
1771 		if (f->pstate == SOCK_STOP) {
1772 			f->pstate = SOCK_INIT;
1773 			f->wmax = 0;
1774 #ifdef DEBUG
1775 			if (log_level >= 4) {
1776 				sock_log(f);
1777 				log_puts(": drained, moved to INIT state\n");
1778 			}
1779 #endif
1780 		}
1781 		/* PASSTHROUGH */
1782 	case SOCK_WIDLE:
1783 		if (f->rstate == SOCK_RRET) {
1784 			f->wmsg = f->rmsg;
1785 			f->wstate = SOCK_WMSG;
1786 			f->wtodo = sizeof(struct amsg);
1787 			f->rstate = SOCK_RMSG;
1788 			f->rtodo = sizeof(struct amsg);
1789 #ifdef DEBUG
1790 			if (log_level >= 4) {
1791 				sock_log(f);
1792 				log_puts(": copied RRET message\n");
1793 			}
1794 #endif
1795 		} else {
1796 			if (!sock_buildmsg(f))
1797 				return 0;
1798 		}
1799 		break;
1800 #ifdef DEBUG
1801 	default:
1802 		sock_log(f);
1803 		log_puts(": bad writing end state\n");
1804 		panic();
1805 #endif
1806 	}
1807 	return 1;
1808 }
1809 
1810 int
1811 sock_pollfd(void *arg, struct pollfd *pfd)
1812 {
1813 	struct sock *f = arg;
1814 	int events = 0;
1815 
1816 	/*
1817 	 * feedback counters, clock ticks and alike may have changed,
1818 	 * prepare a message to trigger writes
1819 	 *
1820 	 * XXX: doing this at the beginning of the cycle is not optimal,
1821 	 * because state is changed at the end of the read cycle, and
1822 	 * thus counters, ret message and alike are generated then.
1823 	 */
1824 	if (f->wstate == SOCK_WIDLE && f->rstate != SOCK_RRET)
1825 		sock_buildmsg(f);
1826 
1827 	if (f->rstate == SOCK_RMSG ||
1828 	    f->rstate == SOCK_RDATA)
1829 		events |= POLLIN;
1830 	if (f->rstate == SOCK_RRET ||
1831 	    f->wstate == SOCK_WMSG ||
1832 	    f->wstate == SOCK_WDATA)
1833 		events |= POLLOUT;
1834 	pfd->fd = f->fd;
1835 	pfd->events = events;
1836 	return 1;
1837 }
1838 
1839 int
1840 sock_revents(void *arg, struct pollfd *pfd)
1841 {
1842 	return pfd->revents;
1843 }
1844 
1845 void
1846 sock_in(void *arg)
1847 {
1848 	struct sock *f = arg;
1849 
1850 	while (sock_read(f))
1851 		;
1852 }
1853 
1854 void
1855 sock_out(void *arg)
1856 {
1857 	struct sock *f = arg;
1858 
1859 	while (sock_write(f))
1860 		;
1861 }
1862 
1863 void
1864 sock_hup(void *arg)
1865 {
1866 	struct sock *f = arg;
1867 
1868 	sock_close(f);
1869 }
1870