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