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