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