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