Annotation of src/usr.bin/sndiod/sock.c, Revision 1.15
1.15 ! ratchov 1: /* $OpenBSD: sock.c,v 1.14 2014/11/21 09:05:38 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.7 ratchov 41: void sock_slot_onvol(void *, unsigned int);
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);
155: xfree(f);
156: }
157:
158: void
159: sock_slot_fill(void *arg)
160: {
161: struct sock *f = arg;
162: struct slot *s = f->slot;
163:
164: f->fillpending += s->round;
165: #ifdef DEBUG
166: if (log_level >= 4) {
167: sock_log(f);
168: log_puts(": fill, rmax -> ");
169: log_puti(f->rmax);
170: log_puts(", pending -> ");
171: log_puti(f->fillpending);
172: log_puts("\n");
173: }
174: #endif
175: }
176:
177: void
178: sock_slot_flush(void *arg)
179: {
180: struct sock *f = arg;
181: struct slot *s = f->slot;
182:
183: f->wmax += s->round * s->sub.bpf;
184: #ifdef DEBUG
185: if (log_level >= 4) {
186: sock_log(f);
187: log_puts(": flush, wmax -> ");
188: log_puti(f->wmax);
189: log_puts("\n");
190: }
191: #endif
192: }
193:
194: void
195: sock_slot_eof(void *arg)
196: {
197: struct sock *f = arg;
198:
199: #ifdef DEBUG
200: if (log_level >= 3) {
201: sock_log(f);
202: log_puts(": stopped\n");
203: }
204: #endif
205: f->stoppending = 1;
206: }
207:
208: void
1.12 ratchov 209: sock_slot_onmove(void *arg)
1.1 ratchov 210: {
211: struct sock *f = (struct sock *)arg;
212: struct slot *s = f->slot;
213:
214: #ifdef DEBUG
215: if (log_level >= 4) {
216: sock_log(f);
217: log_puts(": onmove: delta -> ");
218: log_puti(s->delta);
219: log_puts("\n");
220: }
221: #endif
222: if (s->pstate != SOCK_START)
223: return;
224: f->tickpending++;
225: }
226:
227: void
228: sock_slot_onvol(void *arg, unsigned int delta)
229: {
230: struct sock *f = (struct sock *)arg;
231: struct slot *s = f->slot;
232:
233: #ifdef DEBUG
234: if (log_level >= 4) {
235: sock_log(f);
236: log_puts(": onvol: vol -> ");
237: log_puti(s->vol);
238: log_puts("\n");
239: }
240: #endif
241: if (s->pstate != SOCK_START)
242: return;
243: }
244:
245: void
246: sock_midi_imsg(void *arg, unsigned char *msg, int size)
247: {
248: struct sock *f = arg;
249:
250: midi_send(f->midi, msg, size);
251: }
252:
253: void
254: sock_midi_omsg(void *arg, unsigned char *msg, int size)
255: {
256: struct sock *f = arg;
257:
258: midi_out(f->midi, msg, size);
259: }
260:
261: void
262: sock_midi_fill(void *arg, int count)
263: {
264: struct sock *f = arg;
265:
266: f->fillpending += count;
267: }
268:
269: struct sock *
270: sock_new(int fd)
271: {
272: struct sock *f;
273:
274: f = xmalloc(sizeof(struct sock));
275: f->pstate = SOCK_AUTH;
276: f->opt = NULL;
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: /*
315: * write on the socke fd and handle errors
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 {
339: #ifdef DEBUG
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: /*
356: * read from the socke fd and handle errors
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 {
380: #ifdef DEBUG
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: /*
510: * read data into the slot/midi ring buffer
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.15 ! ratchov 542: if (f->slot)
! 543: data = abuf_rgetblk(&f->slot->sub.buf, &count);
! 544: else if (f->midi)
! 545: data = abuf_rgetblk(&f->midi->obuf, &count);
1.1 ratchov 546: if (count > f->wtodo)
547: count = f->wtodo;
548: n = sock_fdwrite(f, data, count);
549: if (n == 0)
550: return 0;
551: f->wtodo -= n;
1.15 ! ratchov 552: if (f->slot)
! 553: abuf_rdiscard(&f->slot->sub.buf, n);
! 554: else if (f->midi)
! 555: abuf_rdiscard(&f->midi->obuf, n);
1.1 ratchov 556: }
557: if (f->slot)
558: slot_read(f->slot);
559: if (f->midi)
560: midi_fill(f->midi);
561: #ifdef DEBUG
562: if (log_level >= 4) {
563: sock_log(f);
564: log_puts(": wrote complete block\n");
565: }
566: #endif
567: return 1;
568: }
569:
570: int
571: sock_setpar(struct sock *f)
572: {
573: struct slot *s = f->slot;
574: struct dev *d = s->dev;
575: struct amsg_par *p = &f->rmsg.u.par;
1.9 ratchov 576: unsigned int min, max;
577: uint32_t rate, appbufsz;
578: uint16_t pchan, rchan;
1.1 ratchov 579:
580: rchan = ntohs(p->rchan);
581: pchan = ntohs(p->pchan);
582: appbufsz = ntohl(p->appbufsz);
583: rate = ntohl(p->rate);
584:
585: if (AMSG_ISSET(p->bits)) {
586: if (p->bits < BITS_MIN || p->bits > BITS_MAX) {
587: #ifdef DEBUG
588: if (log_level >= 1) {
589: sock_log(f);
590: log_puts(": ");
591: log_putu(p->bits);
592: log_puts(": bits out of bounds\n");
593: }
594: #endif
595: return 0;
596: }
597: if (AMSG_ISSET(p->bps)) {
598: if (p->bps < ((p->bits + 7) / 8) || p->bps > 4) {
599: #ifdef DEBUG
600: if (log_level >= 1) {
601: sock_log(f);
602: log_puts(": ");
603: log_putu(p->bps);
604: log_puts(": wrong bytes per sample\n");
605: }
606: #endif
607: return 0;
608: }
609: } else
610: p->bps = APARAMS_BPS(p->bits);
611: s->par.bits = p->bits;
612: s->par.bps = p->bps;
613: }
614: if (AMSG_ISSET(p->sig))
615: s->par.sig = p->sig ? 1 : 0;
616: if (AMSG_ISSET(p->le))
617: s->par.le = p->le ? 1 : 0;
618: if (AMSG_ISSET(p->msb))
619: s->par.msb = p->msb ? 1 : 0;
620: if (AMSG_ISSET(rchan) && (s->mode & MODE_RECMASK)) {
621: if (rchan < 1)
622: rchan = 1;
623: if (rchan > NCHAN_MAX)
624: rchan = NCHAN_MAX;
625: s->sub.slot_cmin = f->opt->rmin;
626: s->sub.slot_cmax = f->opt->rmin + rchan - 1;
627: s->sub.dev_cmin = f->opt->rmin;
628: s->sub.dev_cmax = f->opt->rmax;
629: #ifdef DEBUG
630: if (log_level >= 3) {
631: sock_log(f);
632: log_puts(": recording channels ");
1.6 ratchov 633: log_putu(s->sub.dev_cmin);
634: log_puts(":");
635: log_putu(s->sub.dev_cmax);
636: log_puts(" -> ");
1.1 ratchov 637: log_putu(s->sub.slot_cmin);
638: log_puts(":");
639: log_putu(s->sub.slot_cmax);
640: log_puts("\n");
641: }
642: #endif
643: }
644: if (AMSG_ISSET(pchan) && (s->mode & MODE_PLAY)) {
645: if (pchan < 1)
646: pchan = 1;
647: if (pchan > NCHAN_MAX)
648: pchan = NCHAN_MAX;
649: s->mix.slot_cmin = f->opt->pmin;
650: s->mix.slot_cmax = f->opt->pmin + pchan - 1;
651: s->mix.dev_cmin = f->opt->pmin;
652: s->mix.dev_cmax = f->opt->pmax;
653: #ifdef DEBUG
654: if (log_level >= 3) {
655: sock_log(f);
656: log_puts(": playback channels ");
657: log_putu(s->mix.slot_cmin);
658: log_puts(":");
659: log_putu(s->mix.slot_cmax);
660: log_puts(" -> ");
661: log_putu(s->mix.dev_cmin);
662: log_puts(":");
663: log_putu(s->mix.dev_cmax);
664: log_puts("\n");
665: }
666: #endif
667: }
668: if (AMSG_ISSET(rate)) {
669: if (rate < RATE_MIN)
670: rate = RATE_MIN;
671: if (rate > RATE_MAX)
672: rate = RATE_MAX;
673: s->round = dev_roundof(d, rate);
674: s->rate = rate;
675: if (!AMSG_ISSET(appbufsz)) {
676: appbufsz = d->bufsz / d->round * s->round;
677: #ifdef DEBUG
678: if (log_level >= 3) {
679: sock_log(f);
680: log_puts(": ");
681: log_putu(appbufsz);
682: log_puts(" frame buffer\n");
683: }
684: #endif
685: }
686: #ifdef DEBUG
687: if (log_level >= 3) {
688: sock_log(f);
689: log_puts(": ");
690: log_putu(rate);
691: log_puts("Hz sample rate, ");
692: log_putu(s->round);
693: log_puts(" frame blocks\n");
694: }
695: #endif
696: }
697: if (AMSG_ISSET(p->xrun)) {
698: if (p->xrun != XRUN_IGNORE &&
699: p->xrun != XRUN_SYNC &&
700: p->xrun != XRUN_ERROR) {
701: #ifdef DEBUG
702: if (log_level >= 1) {
703: sock_log(f);
704: log_puts(": ");
705: log_putx(p->xrun);
706: log_puts(": bad xrun policy\n");
707: }
708: #endif
709: return 0;
710: }
711: s->xrun = p->xrun;
712: if (f->opt->mmc && s->xrun == XRUN_IGNORE)
713: s->xrun = XRUN_SYNC;
714: #ifdef DEBUG
715: if (log_level >= 3) {
716: sock_log(f);
717: log_puts(": 0x");
718: log_putx(s->xrun);
719: log_puts(" xrun policy\n");
720: }
721: #endif
722: }
723: if (AMSG_ISSET(appbufsz)) {
724: rate = s->rate;
725: min = 1;
726: max = 1 + rate / d->round;
727: min *= s->round;
728: max *= s->round;
1.8 ratchov 729: appbufsz += s->round / 2;
1.1 ratchov 730: appbufsz -= appbufsz % s->round;
731: if (appbufsz < min)
732: appbufsz = min;
733: if (appbufsz > max)
734: appbufsz = max;
735: s->appbufsz = appbufsz;
736: #ifdef DEBUG
737: if (log_level >= 3) {
738: sock_log(f);
739: log_puts(": ");
740: log_putu(s->appbufsz);
741: log_puts(" frame buffer\n");
742: }
743: #endif
744: }
745: return 1;
746: }
747:
748: int
749: sock_auth(struct sock *f)
750: {
751: struct amsg_auth *p = &f->rmsg.u.auth;
752:
753: if (sock_sesrefs == 0) {
754: /* start a new session */
755: memcpy(sock_sescookie, p->cookie, AMSG_COOKIELEN);
756: } else if (memcmp(sock_sescookie, p->cookie, AMSG_COOKIELEN) != 0) {
757: /* another session is active, drop connection */
758: return 0;
759: }
760: sock_sesrefs++;
761: f->pstate = SOCK_HELLO;
762: return 1;
763: }
764:
765: int
766: sock_hello(struct sock *f)
767: {
768: struct amsg_hello *p = &f->rmsg.u.hello;
769: struct slot *s;
770: struct port *c;
771: struct dev *d;
772: unsigned int mode;
773:
774: mode = ntohs(p->mode);
775: #ifdef DEBUG
776: if (log_level >= 3) {
777: sock_log(f);
778: log_puts(": hello from <");
779: log_puts(p->who);
780: log_puts(">, mode = ");
781: log_putx(mode);
782: log_puts(", ver ");
783: log_putu(p->version);
784: log_puts("\n");
785: }
786: #endif
787: if (p->version != AMSG_VERSION) {
788: if (log_level >= 1) {
789: sock_log(f);
790: log_puts(": ");
791: log_putu(p->version);
792: log_puts(": unsupported protocol version\n");
793: }
794: return 0;
795: }
796: switch (mode) {
797: case MODE_MIDIIN:
798: case MODE_MIDIOUT:
799: case MODE_MIDIOUT | MODE_MIDIIN:
800: case MODE_REC:
801: case MODE_PLAY:
802: case MODE_PLAY | MODE_REC:
803: break;
804: default:
805: #ifdef DEBUG
806: if (log_level >= 1) {
807: sock_log(f);
808: log_puts(": ");
809: log_putx(mode);
810: log_puts(": unsupported mode\n");
811: }
812: #endif
813: return 0;
814: }
815: f->pstate = SOCK_INIT;
1.5 ratchov 816: f->port = NULL;
1.1 ratchov 817: if (mode & MODE_MIDIMASK) {
818: f->slot = NULL;
819: f->midi = midi_new(&sock_midiops, f, mode);
820: if (f->midi == NULL)
821: return 0;
822: /* XXX: add 'devtype' to libsndio */
823: if (p->devnum < 16) {
824: d = dev_bynum(p->devnum);
825: if (d == NULL)
826: return 0;
827: midi_tag(f->midi, p->devnum);
828: } else if (p->devnum < 32) {
829: midi_tag(f->midi, p->devnum);
830: } else if (p->devnum < 48) {
831: c = port_bynum(p->devnum - 32);
1.3 ratchov 832: if (c == NULL || !port_ref(c))
1.1 ratchov 833: return 0;
1.3 ratchov 834: f->port = c;
1.2 ratchov 835: midi_link(f->midi, c->midi);
1.1 ratchov 836: } else
837: return 0;
838: return 1;
839: }
840: f->opt = opt_byname(p->opt, p->devnum);
841: if (f->opt == NULL)
842: return 0;
843: #ifdef DEBUG
844: if (log_level >= 3) {
845: sock_log(f);
846: log_puts(": using ");
847: dev_log(f->opt->dev);
848: log_puts(".");
849: log_puts(f->opt->name);
850: log_puts(", mode = ");
851: log_putx(mode);
852: log_puts("\n");
853: }
854: #endif
855: if ((mode & MODE_REC) && (f->opt->mode & MODE_MON)) {
856: mode |= MODE_MON;
857: mode &= ~MODE_REC;
858: }
859: if ((mode & f->opt->mode) != mode) {
860: if (log_level >= 1) {
861: sock_log(f);
862: log_puts(": requested mode not allowed\n");
863: }
864: return 0;
865: }
866: s = slot_new(f->opt->dev, p->who, &sock_slotops, f, mode);
867: if (s == NULL)
868: return 0;
869: f->midi = NULL;
870: if (s->mode & MODE_PLAY) {
1.6 ratchov 871: s->mix.slot_cmin = s->mix.dev_cmin = f->opt->pmin;
872: s->mix.slot_cmax = s->mix.dev_cmax = f->opt->pmax;
1.1 ratchov 873: }
874: if (s->mode & MODE_RECMASK) {
1.6 ratchov 875: s->sub.slot_cmin = s->sub.dev_cmin = f->opt->rmin;
876: s->sub.slot_cmax = s->sub.dev_cmax = f->opt->rmax;
1.1 ratchov 877: }
878: if (f->opt->mmc) {
879: s->xrun = XRUN_SYNC;
880: s->tstate = MMC_STOP;
881: } else {
882: s->xrun = XRUN_IGNORE;
883: s->tstate = MMC_OFF;
884: }
885: s->mix.maxweight = f->opt->maxweight;
886: s->dup = f->opt->dup;
887: f->slot = s;
888: return 1;
889: }
890:
891: /*
892: * execute the message in f->rmsg, return 1 on success
893: */
894: int
895: sock_execmsg(struct sock *f)
896: {
897: struct slot *s = f->slot;
898: struct amsg *m = &f->rmsg;
899: unsigned char *data;
900: int size, ctl;
901:
902: switch (ntohl(m->cmd)) {
903: case AMSG_DATA:
904: #ifdef DEBUG
905: if (log_level >= 4) {
906: sock_log(f);
907: log_puts(": DATA message\n");
908: }
909: #endif
910: if (s != NULL && f->pstate != SOCK_START) {
911: #ifdef DEBUG
912: if (log_level >= 1) {
913: sock_log(f);
914: log_puts(": DATA, wrong state\n");
915: }
916: #endif
917: sock_close(f);
918: return 0;
919: }
920: if ((f->slot && !(f->slot->mode & MODE_PLAY)) ||
921: (f->midi && !(f->midi->mode & MODE_MIDIOUT))) {
922: #ifdef DEBUG
923: if (log_level >= 1) {
924: sock_log(f);
925: log_puts(": DATA, input-only mode\n");
926: }
927: #endif
928: sock_close(f);
929: return 0;
930: }
931: size = ntohl(m->u.data.size);
932: if (size <= 0) {
933: #ifdef DEBUG
934: if (log_level >= 1) {
935: sock_log(f);
936: log_puts(": zero size payload\n");
937: }
938: #endif
939: sock_close(f);
940: return 0;
941: }
942: if (s != NULL && size % s->mix.bpf != 0) {
943: #ifdef DEBUG
944: if (log_level >= 1) {
945: sock_log(f);
946: log_puts(": not aligned to frame\n");
947: }
948: #endif
949: sock_close(f);
950: return 0;
951: }
952: if (s != NULL && size > f->ralign) {
953: #ifdef DEBUG
954: if (log_level >= 1) {
955: sock_log(f);
956: log_puts(": size = ");
957: log_puti(size);
958: log_puts(": ralign = ");
959: log_puti(f->ralign);
960: log_puts(": not aligned to block\n");
961: }
962: #endif
963: sock_close(f);
964: return 0;
965: }
966: f->rstate = SOCK_RDATA;
967: f->rsize = f->rtodo = size;
968: if (s != NULL) {
969: f->ralign -= size;
970: if (f->ralign == 0)
971: f->ralign = s->round * s->mix.bpf;
972: }
973: if (f->rtodo > f->rmax) {
974: #ifdef DEBUG
975: if (log_level >= 1) {
976: sock_log(f);
977: log_puts(": unexpected data, size = ");
978: log_putu(size);
979: log_puts(", rmax = ");
980: log_putu(f->rmax);
981: log_puts("\n");
982: }
983: #endif
984: sock_close(f);
985: return 0;
986: }
987: f->rmax -= f->rtodo;
988: if (f->rtodo == 0) {
989: #ifdef DEBUG
990: if (log_level >= 1) {
991: sock_log(f);
992: log_puts(": zero-length data chunk\n");
993: }
994: #endif
995: sock_close(f);
996: return 0;
997: }
998: break;
999: case AMSG_START:
1000: #ifdef DEBUG
1001: if (log_level >= 3) {
1002: sock_log(f);
1003: log_puts(": START message\n");
1004: }
1005: #endif
1.15 ! ratchov 1006: if (f->pstate != SOCK_INIT || s == NULL) {
1.1 ratchov 1007: #ifdef DEBUG
1008: if (log_level >= 1) {
1009: sock_log(f);
1010: log_puts(": START, wrong state\n");
1011: }
1012: #endif
1013: sock_close(f);
1014: return 0;
1015: }
1016: f->tickpending = 0;
1017: f->stoppending = 0;
1018: slot_start(s);
1019: if (s->mode & MODE_PLAY) {
1020: f->fillpending = s->appbufsz;
1021: f->ralign = s->round * s->mix.bpf;
1022: f->rmax = 0;
1023: }
1024: if (s->mode & MODE_RECMASK) {
1025: f->walign = s->round * s->sub.bpf;
1026: f->wmax = 0;
1027: }
1028: f->pstate = SOCK_START;
1029: f->rstate = SOCK_RMSG;
1030: f->rtodo = sizeof(struct amsg);
1031: if (log_level >= 2) {
1032: slot_log(f->slot);
1033: log_puts(": ");
1034: log_putu(s->rate);
1035: log_puts("Hz, ");
1036: aparams_log(&s->par);
1037: if (s->mode & MODE_PLAY) {
1038: log_puts(", play ");
1039: log_puti(s->mix.slot_cmin);
1040: log_puts(":");
1041: log_puti(s->mix.slot_cmax);
1042: }
1043: if (s->mode & MODE_RECMASK) {
1044: log_puts(", rec ");
1045: log_puti(s->sub.slot_cmin);
1046: log_puts(":");
1047: log_puti(s->sub.slot_cmax);
1048: }
1049: log_puts(", ");
1050: log_putu(s->appbufsz / s->round);
1051: log_puts(" blocks of ");
1052: log_putu(s->round);
1053: log_puts(" frames\n");
1054: }
1055: break;
1056: case AMSG_STOP:
1057: #ifdef DEBUG
1058: if (log_level >= 3) {
1059: sock_log(f);
1060: log_puts(": STOP message\n");
1061: }
1062: #endif
1063: if (f->pstate != SOCK_START) {
1064: #ifdef DEBUG
1065: if (log_level >= 1) {
1066: sock_log(f);
1067: log_puts(": STOP, wrong state\n");
1068: }
1069: #endif
1070: sock_close(f);
1071: return 0;
1072: }
1073: f->rmax = 0;
1074: if (!(s->mode & MODE_PLAY))
1075: f->stoppending = 1;
1076: f->pstate = SOCK_STOP;
1077: f->rstate = SOCK_RMSG;
1078: f->rtodo = sizeof(struct amsg);
1079: if (s->mode & MODE_PLAY) {
1080: if (f->ralign < s->round * s->mix.bpf) {
1081: data = abuf_wgetblk(&s->mix.buf, &size);
1082: #ifdef DEBUG
1083: if (size < f->ralign) {
1084: sock_log(f);
1085: log_puts(": unaligned stop, size = ");
1086: log_putu(size);
1087: log_puts(", ralign = ");
1088: log_putu(f->ralign);
1089: log_puts("\n");
1090: panic();
1091: }
1092: #endif
1093: memset(data, 0, f->ralign);
1094: abuf_wcommit(&s->mix.buf, f->ralign);
1095: f->ralign = s->round * s->mix.bpf;
1096: }
1097: }
1098: slot_stop(s);
1099: break;
1100: case AMSG_SETPAR:
1101: #ifdef DEBUG
1102: if (log_level >= 3) {
1103: sock_log(f);
1104: log_puts(": SETPAR message\n");
1105: }
1106: #endif
1.15 ! ratchov 1107: if (f->pstate != SOCK_INIT || s == NULL) {
1.1 ratchov 1108: #ifdef DEBUG
1109: if (log_level >= 1) {
1110: sock_log(f);
1111: log_puts(": SETPAR, wrong state\n");
1112: }
1113: #endif
1114: sock_close(f);
1115: return 0;
1116: }
1117: if (!sock_setpar(f)) {
1118: sock_close(f);
1119: return 0;
1120: }
1121: f->rtodo = sizeof(struct amsg);
1122: f->rstate = SOCK_RMSG;
1123: break;
1124: case AMSG_GETPAR:
1125: #ifdef DEBUG
1126: if (log_level >= 3) {
1127: sock_log(f);
1128: log_puts(": GETPAR message\n");
1129: }
1130: #endif
1.15 ! ratchov 1131: if (f->pstate != SOCK_INIT || s == NULL) {
1.1 ratchov 1132: #ifdef DEBUG
1133: if (log_level >= 1) {
1134: sock_log(f);
1135: log_puts(": GETPAR, wrong state\n");
1136: }
1137: #endif
1138: sock_close(f);
1139: return 0;
1140: }
1141: AMSG_INIT(m);
1142: m->cmd = htonl(AMSG_GETPAR);
1143: m->u.par.legacy_mode = s->mode;
1.14 ratchov 1144: m->u.par.xrun = s->xrun;
1.1 ratchov 1145: m->u.par.bits = s->par.bits;
1146: m->u.par.bps = s->par.bps;
1147: m->u.par.sig = s->par.sig;
1148: m->u.par.le = s->par.le;
1149: m->u.par.msb = s->par.msb;
1150: if (s->mode & MODE_PLAY) {
1151: m->u.par.pchan = htons(s->mix.slot_cmax -
1152: s->mix.slot_cmin + 1);
1153: }
1154: if (s->mode & MODE_RECMASK) {
1155: m->u.par.rchan = htons(s->sub.slot_cmax -
1156: s->sub.slot_cmin + 1);
1157: }
1158: m->u.par.rate = htonl(s->rate);
1159: m->u.par.appbufsz = htonl(s->appbufsz);
1160: m->u.par.bufsz = htonl(SLOT_BUFSZ(s));
1161: m->u.par.round = htonl(s->round);
1162: f->rstate = SOCK_RRET;
1163: f->rtodo = sizeof(struct amsg);
1164: break;
1165: case AMSG_SETVOL:
1166: #ifdef DEBUG
1167: if (log_level >= 3) {
1168: sock_log(f);
1169: log_puts(": SETVOL message\n");
1170: }
1171: #endif
1.15 ! ratchov 1172: if (f->pstate < SOCK_INIT || s == NULL) {
1.1 ratchov 1173: #ifdef DEBUG
1174: if (log_level >= 1) {
1175: sock_log(f);
1176: log_puts(": SETVOL, wrong state\n");
1177: }
1178: #endif
1179: sock_close(f);
1180: return 0;
1181: }
1182: ctl = ntohl(m->u.vol.ctl);
1183: if (ctl > MIDI_MAXCTL) {
1184: #ifdef DEBUG
1185: if (log_level >= 1) {
1186: sock_log(f);
1187: log_puts(": SETVOL, volume out of range\n");
1188: }
1189: #endif
1190: sock_close(f);
1191: return 0;
1192: }
1193: f->rtodo = sizeof(struct amsg);
1194: f->rstate = SOCK_RMSG;
1195: f->lastvol = ctl; /* dont trigger feedback message */
1.15 ! ratchov 1196: slot_setvol(s, ctl);
1.1 ratchov 1197: dev_midi_vol(s->dev, s);
1198: break;
1199: case AMSG_AUTH:
1200: #ifdef DEBUG
1201: if (log_level >= 3) {
1202: sock_log(f);
1203: log_puts(": AUTH message\n");
1204: }
1205: #endif
1206: if (f->pstate != SOCK_AUTH) {
1207: #ifdef DEBUG
1208: if (log_level >= 1) {
1209: sock_log(f);
1210: log_puts(": AUTH, wrong state\n");
1211: }
1212: #endif
1213: sock_close(f);
1214: return 0;
1215: }
1216: if (!sock_auth(f)) {
1217: sock_close(f);
1218: return 0;
1219: }
1220: f->rstate = SOCK_RMSG;
1221: f->rtodo = sizeof(struct amsg);
1222: break;
1223: case AMSG_HELLO:
1224: #ifdef DEBUG
1225: if (log_level >= 3) {
1226: sock_log(f);
1227: log_puts(": HELLO message\n");
1228: }
1229: #endif
1230: if (f->pstate != SOCK_HELLO) {
1231: #ifdef DEBUG
1232: if (log_level >= 1) {
1233: sock_log(f);
1234: log_puts(": HELLO, wrong state\n");
1235: }
1236: #endif
1237: sock_close(f);
1238: return 0;
1239: }
1240: if (!sock_hello(f)) {
1241: sock_close(f);
1242: return 0;
1243: }
1244: AMSG_INIT(m);
1245: m->cmd = htonl(AMSG_ACK);
1246: f->rstate = SOCK_RRET;
1247: f->rtodo = sizeof(struct amsg);
1248: break;
1249: case AMSG_BYE:
1250: #ifdef DEBUG
1251: if (log_level >= 3) {
1252: sock_log(f);
1253: log_puts(": BYE message\n");
1254: }
1255: #endif
1256: if (s != NULL && f->pstate != SOCK_INIT) {
1257: #ifdef DEBUG
1258: if (log_level >= 1) {
1259: sock_log(f);
1260: log_puts(": BYE, wrong state\n");
1261: }
1262: #endif
1263: }
1264: sock_close(f);
1265: return 0;
1266: default:
1267: #ifdef DEBUG
1268: if (log_level >= 1) {
1269: sock_log(f);
1270: log_puts(": unknown command in message\n");
1271: }
1272: #endif
1273: sock_close(f);
1274: return 0;
1275: }
1276: return 1;
1277: }
1278:
1279: /*
1280: * build a message in f->wmsg, return 1 on success and 0 if
1281: * there's nothing to do. Assume f->wstate is SOCK_WIDLE
1282: */
1283: int
1284: sock_buildmsg(struct sock *f)
1285: {
1286: unsigned int size;
1287:
1288: /*
1289: * If pos changed (or initial tick), build a MOVE message.
1290: */
1291: if (f->tickpending) {
1292: #ifdef DEBUG
1293: if (log_level >= 4) {
1294: sock_log(f);
1295: log_puts(": building MOVE message, delta = ");
1296: log_puti(f->slot->delta);
1297: log_puts("\n");
1298: }
1299: #endif
1300: AMSG_INIT(&f->wmsg);
1301: f->wmsg.cmd = htonl(AMSG_MOVE);
1302: f->wmsg.u.ts.delta = htonl(f->slot->delta);
1303: f->wtodo = sizeof(struct amsg);
1304: f->wstate = SOCK_WMSG;
1305: f->tickpending = 0;
1306: /*
1307: * XXX: use tickpending as accumulator rather than
1308: * slot->delta
1309: */
1310: f->slot->delta = 0;
1311: return 1;
1312: }
1313:
1314: if (f->fillpending > 0) {
1315: AMSG_INIT(&f->wmsg);
1316: f->wmsg.cmd = htonl(AMSG_FLOWCTL);
1317: f->wmsg.u.ts.delta = htonl(f->fillpending);
1318: size = f->fillpending;
1319: if (f->slot)
1320: size *= f->slot->mix.bpf;
1321: f->rmax += size;
1322: #ifdef DEBUG
1323: if (log_level >= 4) {
1324: sock_log(f);
1325: log_puts(": building FLOWCTL message, count = ");
1326: log_puti(f->fillpending);
1327: log_puts(", rmax -> ");
1328: log_puti(f->rmax);
1329: log_puts("\n");
1330: }
1331: #endif
1332: f->wtodo = sizeof(struct amsg);
1333: f->wstate = SOCK_WMSG;
1334: f->fillpending = 0;
1335: return 1;
1336: }
1337:
1338: /*
1339: * if volume changed build a SETVOL message
1340: */
1341: if (f->pstate >= SOCK_START && f->slot->vol != f->lastvol) {
1342: #ifdef DEBUG
1343: if (log_level >= 3) {
1344: sock_log(f);
1345: log_puts(": building SETVOL message, vol = ");
1346: log_puti(f->slot->vol);
1347: log_puts("\n");
1348: }
1349: #endif
1350: AMSG_INIT(&f->wmsg);
1351: f->wmsg.cmd = htonl(AMSG_SETVOL);
1352: f->wmsg.u.vol.ctl = htonl(f->slot->vol);
1353: f->wtodo = sizeof(struct amsg);
1354: f->wstate = SOCK_WMSG;
1355: f->lastvol = f->slot->vol;
1356: return 1;
1357: }
1358:
1359: if (f->midi != NULL && f->midi->obuf.used > 0) {
1360: size = f->midi->obuf.used;
1361: if (size > AMSG_DATAMAX)
1362: size = AMSG_DATAMAX;
1363: AMSG_INIT(&f->wmsg);
1364: f->wmsg.cmd = htonl(AMSG_DATA);
1365: f->wmsg.u.data.size = htonl(size);
1366: f->wtodo = sizeof(struct amsg);
1367: f->wstate = SOCK_WMSG;
1368: return 1;
1369: }
1370:
1371: /*
1372: * If data available, build a DATA message.
1373: */
1.10 ratchov 1374: if (f->slot != NULL && f->wmax > 0 && f->slot->sub.buf.used > 0) {
1.1 ratchov 1375: size = f->slot->sub.buf.used;
1376: if (size > AMSG_DATAMAX)
1377: size = AMSG_DATAMAX;
1378: if (size > f->walign)
1379: size = f->walign;
1380: if (size > f->wmax)
1381: size = f->wmax;
1382: size -= size % f->slot->sub.bpf;
1383: #ifdef DEBUG
1384: if (size == 0) {
1385: sock_log(f);
1386: log_puts(": sock_buildmsg size == 0\n");
1387: panic();
1388: }
1389: #endif
1390: f->walign -= size;
1391: f->wmax -= size;
1392: if (f->walign == 0)
1393: f->walign = f->slot->round * f->slot->sub.bpf;
1394: #ifdef DEBUG
1395: if (log_level >= 4) {
1396: sock_log(f);
1397: log_puts(": building audio DATA message, size = ");
1398: log_puti(size);
1399: log_puts("\n");
1400: }
1401: #endif
1402: AMSG_INIT(&f->wmsg);
1403: f->wmsg.cmd = htonl(AMSG_DATA);
1404: f->wmsg.u.data.size = htonl(size);
1405: f->wtodo = sizeof(struct amsg);
1406: f->wstate = SOCK_WMSG;
1407: return 1;
1408: }
1409:
1410: if (f->stoppending) {
1411: #ifdef DEBUG
1412: if (log_level >= 3) {
1413: sock_log(f);
1414: log_puts(": building STOP message\n");
1415: }
1416: #endif
1417: f->stoppending = 0;
1418: f->pstate = SOCK_INIT;
1419: AMSG_INIT(&f->wmsg);
1420: f->wmsg.cmd = htonl(AMSG_STOP);
1421: f->wtodo = sizeof(struct amsg);
1422: f->wstate = SOCK_WMSG;
1423: return 1;
1424: }
1425: #ifdef DEBUG
1426: if (log_level >= 4) {
1427: sock_log(f);
1428: log_puts(": no messages to build anymore, idling...\n");
1429: }
1430: #endif
1431: f->wstate = SOCK_WIDLE;
1432: return 0;
1433: }
1434:
1435: /*
1436: * iteration of the socket reader loop, return 1 on success
1437: */
1438: int
1439: sock_read(struct sock *f)
1440: {
1441: #ifdef DEBUG
1442: if (log_level >= 4) {
1443: sock_log(f);
1444: log_puts(": reading ");
1445: log_putu(f->rtodo);
1446: log_puts(" todo\n");
1447: }
1448: #endif
1449: switch (f->rstate) {
1450: case SOCK_RIDLE:
1451: return 0;
1452: case SOCK_RMSG:
1453: if (!sock_rmsg(f))
1454: return 0;
1455: if (!sock_execmsg(f))
1456: return 0;
1457: break;
1458: case SOCK_RDATA:
1459: if (!sock_rdata(f))
1460: return 0;
1461: f->rstate = SOCK_RMSG;
1462: f->rtodo = sizeof(struct amsg);
1463: break;
1464: case SOCK_RRET:
1465: if (f->wstate != SOCK_WIDLE) {
1466: #ifdef DEBUG
1467: if (log_level >= 4) {
1468: sock_log(f);
1469: log_puts(": can't reply, write-end blocked\n");
1470: }
1471: #endif
1472: return 0;
1473: }
1474: f->wmsg = f->rmsg;
1475: f->wstate = SOCK_WMSG;
1476: f->wtodo = sizeof(struct amsg);
1477: f->rstate = SOCK_RMSG;
1478: f->rtodo = sizeof(struct amsg);
1479: #ifdef DEBUG
1480: if (log_level >= 4) {
1481: sock_log(f);
1482: log_puts(": copied RRET message\n");
1483: }
1484: #endif
1485: }
1486: return 1;
1487: }
1488:
1489: /*
1490: * iteration of the socket writer loop, return 1 on success
1491: */
1492: int
1493: sock_write(struct sock *f)
1494: {
1495: #ifdef DEBUG
1496: if (log_level >= 4) {
1497: sock_log(f);
1498: log_puts(": writing");
1499: if (f->wstate != SOCK_WIDLE) {
1500: log_puts(" todo = ");
1501: log_putu(f->wtodo);
1502: }
1503: log_puts("\n");
1504: }
1505: #endif
1506: switch (f->wstate) {
1507: case SOCK_WMSG:
1508: if (!sock_wmsg(f))
1509: return 0;
1510: if (ntohl(f->wmsg.cmd) != AMSG_DATA) {
1511: f->wstate = SOCK_WIDLE;
1512: f->wtodo = 0xdeadbeef;
1513: break;
1514: }
1515: f->wstate = SOCK_WDATA;
1516: f->wsize = f->wtodo = ntohl(f->wmsg.u.data.size);
1517: /* PASSTHROUGH */
1518: case SOCK_WDATA:
1519: if (!sock_wdata(f))
1520: return 0;
1521: if (f->wtodo > 0)
1522: break;
1523: f->wstate = SOCK_WIDLE;
1524: f->wtodo = 0xdeadbeef;
1525: if (f->pstate == SOCK_STOP) {
1526: f->pstate = SOCK_INIT;
1527: f->wmax = 0;
1528: #ifdef DEBUG
1529: if (log_level >= 4) {
1530: sock_log(f);
1531: log_puts(": drained, moved to INIT state\n");
1532: }
1533: #endif
1534: }
1535: /* PASSTHROUGH */
1536: case SOCK_WIDLE:
1537: if (f->rstate == SOCK_RRET) {
1538: f->wmsg = f->rmsg;
1539: f->wstate = SOCK_WMSG;
1540: f->wtodo = sizeof(struct amsg);
1541: f->rstate = SOCK_RMSG;
1542: f->rtodo = sizeof(struct amsg);
1543: #ifdef DEBUG
1544: if (log_level >= 4) {
1545: sock_log(f);
1546: log_puts(": copied RRET message\n");
1547: }
1548: #endif
1549: } else {
1550: if (!sock_buildmsg(f))
1551: return 0;
1552: }
1553: break;
1554: #ifdef DEBUG
1555: default:
1556: sock_log(f);
1557: log_puts(": bad writing end state\n");
1558: panic();
1559: #endif
1560: }
1561: return 1;
1562: }
1563:
1564: int
1565: sock_pollfd(void *arg, struct pollfd *pfd)
1566: {
1567: struct sock *f = arg;
1568: int events = 0;
1569:
1570: /*
1571: * feedback counters, clock ticks and alike may have changed,
1572: * prepare a message to trigger writes
1573: *
1574: * XXX: doing this at the beginning of the cycle is not optimal,
1575: * because state is changed at the end of the read cycle, and
1576: * thus counters, ret message and alike are generated then.
1577: */
1578: if (f->wstate == SOCK_WIDLE && f->rstate != SOCK_RRET)
1579: sock_buildmsg(f);
1580:
1581: if (f->rstate == SOCK_RMSG ||
1582: f->rstate == SOCK_RDATA)
1583: events |= POLLIN;
1584: if (f->rstate == SOCK_RRET ||
1585: f->wstate == SOCK_WMSG ||
1586: f->wstate == SOCK_WDATA)
1587: events |= POLLOUT;
1588: pfd->fd = f->fd;
1589: pfd->events = events;
1590: return 1;
1591: }
1592:
1593: int
1594: sock_revents(void *arg, struct pollfd *pfd)
1595: {
1596: return pfd->revents;
1597: }
1598:
1599: void
1600: sock_in(void *arg)
1601: {
1602: struct sock *f = arg;
1603:
1604: while (sock_read(f))
1605: ;
1606: }
1607:
1608: void
1609: sock_out(void *arg)
1610: {
1611: struct sock *f = arg;
1612:
1613: while (sock_write(f))
1614: ;
1615: }
1616:
1617: void
1618: sock_hup(void *arg)
1619: {
1620: struct sock *f = arg;
1621:
1622: sock_close(f);
1623: }