Annotation of src/usr.bin/sndiod/sock.c, Revision 1.3
1.3 ! ratchov 1: /* $OpenBSD: sock.c,v 1.2 2012/11/30 20:30:24 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 ");
673: log_putu(s->sub.slot_cmin);
674: log_puts(":");
675: log_putu(s->sub.slot_cmax);
676: log_puts(" -> ");
677: log_putu(s->sub.dev_cmin);
678: log_puts(":");
679: log_putu(s->sub.dev_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;
856: if (mode & MODE_MIDIMASK) {
1.3 ! ratchov 857: f->port = NULL;
1.1 ratchov 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: aparams_init(&s->par);
911: if (s->mode & MODE_PLAY) {
912: s->mix.slot_cmin = f->opt->pmin;
913: s->mix.slot_cmax = f->opt->pmax;
914: }
915: if (s->mode & MODE_RECMASK) {
916: s->sub.slot_cmin = f->opt->rmin;
917: s->sub.slot_cmax = f->opt->rmax;
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: /* XXX: must convert to slot rate */
929: f->slot = s;
930: return 1;
931: }
932:
933: /*
934: * execute the message in f->rmsg, return 1 on success
935: */
936: int
937: sock_execmsg(struct sock *f)
938: {
939: struct slot *s = f->slot;
940: struct amsg *m = &f->rmsg;
941: unsigned char *data;
942: int size, ctl;
943:
944: switch (ntohl(m->cmd)) {
945: case AMSG_DATA:
946: #ifdef DEBUG
947: if (log_level >= 4) {
948: sock_log(f);
949: log_puts(": DATA message\n");
950: }
951: #endif
952: if (s != NULL && f->pstate != SOCK_START) {
953: #ifdef DEBUG
954: if (log_level >= 1) {
955: sock_log(f);
956: log_puts(": DATA, wrong state\n");
957: }
958: #endif
959: sock_close(f);
960: return 0;
961: }
962: if ((f->slot && !(f->slot->mode & MODE_PLAY)) ||
963: (f->midi && !(f->midi->mode & MODE_MIDIOUT))) {
964: #ifdef DEBUG
965: if (log_level >= 1) {
966: sock_log(f);
967: log_puts(": DATA, input-only mode\n");
968: }
969: #endif
970: sock_close(f);
971: return 0;
972: }
973: size = ntohl(m->u.data.size);
974: if (size <= 0) {
975: #ifdef DEBUG
976: if (log_level >= 1) {
977: sock_log(f);
978: log_puts(": zero size payload\n");
979: }
980: #endif
981: sock_close(f);
982: return 0;
983: }
984: if (s != NULL && size % s->mix.bpf != 0) {
985: #ifdef DEBUG
986: if (log_level >= 1) {
987: sock_log(f);
988: log_puts(": not aligned to frame\n");
989: }
990: #endif
991: sock_close(f);
992: return 0;
993: }
994: if (s != NULL && size > f->ralign) {
995: #ifdef DEBUG
996: if (log_level >= 1) {
997: sock_log(f);
998: log_puts(": size = ");
999: log_puti(size);
1000: log_puts(": ralign = ");
1001: log_puti(f->ralign);
1002: log_puts(": not aligned to block\n");
1003: }
1004: #endif
1005: sock_close(f);
1006: return 0;
1007: }
1008: f->rstate = SOCK_RDATA;
1009: f->rsize = f->rtodo = size;
1010: if (s != NULL) {
1011: f->ralign -= size;
1012: if (f->ralign == 0)
1013: f->ralign = s->round * s->mix.bpf;
1014: }
1015: if (f->rtodo > f->rmax) {
1016: #ifdef DEBUG
1017: if (log_level >= 1) {
1018: sock_log(f);
1019: log_puts(": unexpected data, size = ");
1020: log_putu(size);
1021: log_puts(", rmax = ");
1022: log_putu(f->rmax);
1023: log_puts("\n");
1024: }
1025: #endif
1026: sock_close(f);
1027: return 0;
1028: }
1029: f->rmax -= f->rtodo;
1030: if (f->rtodo == 0) {
1031: #ifdef DEBUG
1032: if (log_level >= 1) {
1033: sock_log(f);
1034: log_puts(": zero-length data chunk\n");
1035: }
1036: #endif
1037: sock_close(f);
1038: return 0;
1039: }
1040: break;
1041: case AMSG_START:
1042: #ifdef DEBUG
1043: if (log_level >= 3) {
1044: sock_log(f);
1045: log_puts(": START message\n");
1046: }
1047: #endif
1048: if (f->pstate != SOCK_INIT) {
1049: #ifdef DEBUG
1050: if (log_level >= 1) {
1051: sock_log(f);
1052: log_puts(": START, wrong state\n");
1053: }
1054: #endif
1055: sock_close(f);
1056: return 0;
1057: }
1058: f->tickpending = 0;
1059: f->stoppending = 0;
1060: slot_start(s);
1061: if (s->mode & MODE_PLAY) {
1062: f->fillpending = s->appbufsz;
1063: f->ralign = s->round * s->mix.bpf;
1064: f->rmax = 0;
1065: }
1066: if (s->mode & MODE_RECMASK) {
1067: f->walign = s->round * s->sub.bpf;
1068: f->wmax = 0;
1069: }
1070: f->pstate = SOCK_START;
1071: f->rstate = SOCK_RMSG;
1072: f->rtodo = sizeof(struct amsg);
1073: if (log_level >= 2) {
1074: slot_log(f->slot);
1075: log_puts(": ");
1076: log_putu(s->rate);
1077: log_puts("Hz, ");
1078: aparams_log(&s->par);
1079: if (s->mode & MODE_PLAY) {
1080: log_puts(", play ");
1081: log_puti(s->mix.slot_cmin);
1082: log_puts(":");
1083: log_puti(s->mix.slot_cmax);
1084: }
1085: if (s->mode & MODE_RECMASK) {
1086: log_puts(", rec ");
1087: log_puti(s->sub.slot_cmin);
1088: log_puts(":");
1089: log_puti(s->sub.slot_cmax);
1090: }
1091: log_puts(", ");
1092: log_putu(s->appbufsz / s->round);
1093: log_puts(" blocks of ");
1094: log_putu(s->round);
1095: log_puts(" frames\n");
1096: }
1097: break;
1098: case AMSG_STOP:
1099: #ifdef DEBUG
1100: if (log_level >= 3) {
1101: sock_log(f);
1102: log_puts(": STOP message\n");
1103: }
1104: #endif
1105: if (f->pstate != SOCK_START) {
1106: #ifdef DEBUG
1107: if (log_level >= 1) {
1108: sock_log(f);
1109: log_puts(": STOP, wrong state\n");
1110: }
1111: #endif
1112: sock_close(f);
1113: return 0;
1114: }
1115: f->rmax = 0;
1116: if (!(s->mode & MODE_PLAY))
1117: f->stoppending = 1;
1118: f->pstate = SOCK_STOP;
1119: f->rstate = SOCK_RMSG;
1120: f->rtodo = sizeof(struct amsg);
1121: if (s->mode & MODE_PLAY) {
1122: if (f->ralign < s->round * s->mix.bpf) {
1123: data = abuf_wgetblk(&s->mix.buf, &size);
1124: #ifdef DEBUG
1125: if (size < f->ralign) {
1126: sock_log(f);
1127: log_puts(": unaligned stop, size = ");
1128: log_putu(size);
1129: log_puts(", ralign = ");
1130: log_putu(f->ralign);
1131: log_puts("\n");
1132: panic();
1133: }
1134: #endif
1135: memset(data, 0, f->ralign);
1136: abuf_wcommit(&s->mix.buf, f->ralign);
1137: f->ralign = s->round * s->mix.bpf;
1138: }
1139: }
1140: slot_stop(s);
1141: break;
1142: case AMSG_SETPAR:
1143: #ifdef DEBUG
1144: if (log_level >= 3) {
1145: sock_log(f);
1146: log_puts(": SETPAR message\n");
1147: }
1148: #endif
1149: if (f->pstate != SOCK_INIT) {
1150: #ifdef DEBUG
1151: if (log_level >= 1) {
1152: sock_log(f);
1153: log_puts(": SETPAR, wrong state\n");
1154: }
1155: #endif
1156: sock_close(f);
1157: return 0;
1158: }
1159: if (!sock_setpar(f)) {
1160: sock_close(f);
1161: return 0;
1162: }
1163: f->rtodo = sizeof(struct amsg);
1164: f->rstate = SOCK_RMSG;
1165: break;
1166: case AMSG_GETPAR:
1167: #ifdef DEBUG
1168: if (log_level >= 3) {
1169: sock_log(f);
1170: log_puts(": GETPAR message\n");
1171: }
1172: #endif
1173: if (f->pstate != SOCK_INIT) {
1174: #ifdef DEBUG
1175: if (log_level >= 1) {
1176: sock_log(f);
1177: log_puts(": GETPAR, wrong state\n");
1178: }
1179: #endif
1180: sock_close(f);
1181: return 0;
1182: }
1183: AMSG_INIT(m);
1184: m->cmd = htonl(AMSG_GETPAR);
1185: m->u.par.legacy_mode = s->mode;
1186: m->u.par.bits = s->par.bits;
1187: m->u.par.bps = s->par.bps;
1188: m->u.par.sig = s->par.sig;
1189: m->u.par.le = s->par.le;
1190: m->u.par.msb = s->par.msb;
1191: if (s->mode & MODE_PLAY) {
1192: m->u.par.pchan = htons(s->mix.slot_cmax -
1193: s->mix.slot_cmin + 1);
1194: }
1195: if (s->mode & MODE_RECMASK) {
1196: m->u.par.rchan = htons(s->sub.slot_cmax -
1197: s->sub.slot_cmin + 1);
1198: }
1199: m->u.par.rate = htonl(s->rate);
1200: m->u.par.appbufsz = htonl(s->appbufsz);
1201: m->u.par.bufsz = htonl(SLOT_BUFSZ(s));
1202: m->u.par.round = htonl(s->round);
1203: f->rstate = SOCK_RRET;
1204: f->rtodo = sizeof(struct amsg);
1205: break;
1206: case AMSG_SETVOL:
1207: #ifdef DEBUG
1208: if (log_level >= 3) {
1209: sock_log(f);
1210: log_puts(": SETVOL message\n");
1211: }
1212: #endif
1213: if (f->pstate < SOCK_INIT) {
1214: #ifdef DEBUG
1215: if (log_level >= 1) {
1216: sock_log(f);
1217: log_puts(": SETVOL, wrong state\n");
1218: }
1219: #endif
1220: sock_close(f);
1221: return 0;
1222: }
1223: ctl = ntohl(m->u.vol.ctl);
1224: if (ctl > MIDI_MAXCTL) {
1225: #ifdef DEBUG
1226: if (log_level >= 1) {
1227: sock_log(f);
1228: log_puts(": SETVOL, volume out of range\n");
1229: }
1230: #endif
1231: sock_close(f);
1232: return 0;
1233: }
1234: f->rtodo = sizeof(struct amsg);
1235: f->rstate = SOCK_RMSG;
1236: f->lastvol = ctl; /* dont trigger feedback message */
1237: dev_midi_vol(s->dev, s);
1238: slot_setvol(s, ctl);
1239: break;
1240: case AMSG_AUTH:
1241: #ifdef DEBUG
1242: if (log_level >= 3) {
1243: sock_log(f);
1244: log_puts(": AUTH message\n");
1245: }
1246: #endif
1247: if (f->pstate != SOCK_AUTH) {
1248: #ifdef DEBUG
1249: if (log_level >= 1) {
1250: sock_log(f);
1251: log_puts(": AUTH, wrong state\n");
1252: }
1253: #endif
1254: sock_close(f);
1255: return 0;
1256: }
1257: if (!sock_auth(f)) {
1258: sock_close(f);
1259: return 0;
1260: }
1261: f->rstate = SOCK_RMSG;
1262: f->rtodo = sizeof(struct amsg);
1263: break;
1264: case AMSG_HELLO:
1265: #ifdef DEBUG
1266: if (log_level >= 3) {
1267: sock_log(f);
1268: log_puts(": HELLO message\n");
1269: }
1270: #endif
1271: if (f->pstate != SOCK_HELLO) {
1272: #ifdef DEBUG
1273: if (log_level >= 1) {
1274: sock_log(f);
1275: log_puts(": HELLO, wrong state\n");
1276: }
1277: #endif
1278: sock_close(f);
1279: return 0;
1280: }
1281: if (!sock_hello(f)) {
1282: sock_close(f);
1283: return 0;
1284: }
1285: AMSG_INIT(m);
1286: m->cmd = htonl(AMSG_ACK);
1287: f->rstate = SOCK_RRET;
1288: f->rtodo = sizeof(struct amsg);
1289: break;
1290: case AMSG_BYE:
1291: #ifdef DEBUG
1292: if (log_level >= 3) {
1293: sock_log(f);
1294: log_puts(": BYE message\n");
1295: }
1296: #endif
1297: if (s != NULL && f->pstate != SOCK_INIT) {
1298: #ifdef DEBUG
1299: if (log_level >= 1) {
1300: sock_log(f);
1301: log_puts(": BYE, wrong state\n");
1302: }
1303: #endif
1304: }
1305: sock_close(f);
1306: return 0;
1307: default:
1308: #ifdef DEBUG
1309: if (log_level >= 1) {
1310: sock_log(f);
1311: log_puts(": unknown command in message\n");
1312: }
1313: #endif
1314: sock_close(f);
1315: return 0;
1316: }
1317: return 1;
1318: }
1319:
1320: /*
1321: * build a message in f->wmsg, return 1 on success and 0 if
1322: * there's nothing to do. Assume f->wstate is SOCK_WIDLE
1323: */
1324: int
1325: sock_buildmsg(struct sock *f)
1326: {
1327: unsigned int size;
1328:
1329: /*
1330: * If pos changed (or initial tick), build a MOVE message.
1331: */
1332: if (f->tickpending) {
1333: #ifdef DEBUG
1334: if (log_level >= 4) {
1335: sock_log(f);
1336: log_puts(": building MOVE message, delta = ");
1337: log_puti(f->slot->delta);
1338: log_puts("\n");
1339: }
1340: #endif
1341: AMSG_INIT(&f->wmsg);
1342: f->wmsg.cmd = htonl(AMSG_MOVE);
1343: f->wmsg.u.ts.delta = htonl(f->slot->delta);
1344: f->wtodo = sizeof(struct amsg);
1345: f->wstate = SOCK_WMSG;
1346: f->tickpending = 0;
1347: /*
1348: * XXX: use tickpending as accumulator rather than
1349: * slot->delta
1350: */
1351: f->slot->delta = 0;
1352: return 1;
1353: }
1354:
1355: if (f->fillpending > 0) {
1356: AMSG_INIT(&f->wmsg);
1357: f->wmsg.cmd = htonl(AMSG_FLOWCTL);
1358: f->wmsg.u.ts.delta = htonl(f->fillpending);
1359: size = f->fillpending;
1360: if (f->slot)
1361: size *= f->slot->mix.bpf;
1362: f->rmax += size;
1363: #ifdef DEBUG
1364: if (log_level >= 4) {
1365: sock_log(f);
1366: log_puts(": building FLOWCTL message, count = ");
1367: log_puti(f->fillpending);
1368: log_puts(", rmax -> ");
1369: log_puti(f->rmax);
1370: log_puts("\n");
1371: }
1372: #endif
1373: f->wtodo = sizeof(struct amsg);
1374: f->wstate = SOCK_WMSG;
1375: f->fillpending = 0;
1376: return 1;
1377: }
1378:
1379: /*
1380: * if volume changed build a SETVOL message
1381: */
1382: if (f->pstate >= SOCK_START && f->slot->vol != f->lastvol) {
1383: #ifdef DEBUG
1384: if (log_level >= 3) {
1385: sock_log(f);
1386: log_puts(": building SETVOL message, vol = ");
1387: log_puti(f->slot->vol);
1388: log_puts("\n");
1389: }
1390: #endif
1391: AMSG_INIT(&f->wmsg);
1392: f->wmsg.cmd = htonl(AMSG_SETVOL);
1393: f->wmsg.u.vol.ctl = htonl(f->slot->vol);
1394: f->wtodo = sizeof(struct amsg);
1395: f->wstate = SOCK_WMSG;
1396: f->lastvol = f->slot->vol;
1397: return 1;
1398: }
1399:
1400: if (f->midi != NULL && f->midi->obuf.used > 0) {
1401: /* XXX: use tickets */
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: */
1416: if (f->slot != NULL && f->slot->sub.buf.used > 0 && f->wmax > 0) {
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: /* XXX: call sock_wmsg() ? */
1522: #ifdef DEBUG
1523: if (log_level >= 4) {
1524: sock_log(f);
1525: log_puts(": copied RRET message\n");
1526: }
1527: #endif
1528: }
1529: return 1;
1530: }
1531:
1532: /*
1533: * iteration of the socket writer loop, return 1 on success
1534: */
1535: int
1536: sock_write(struct sock *f)
1537: {
1538: #ifdef DEBUG
1539: if (log_level >= 4) {
1540: sock_log(f);
1541: log_puts(": writing");
1542: if (f->wstate != SOCK_WIDLE) {
1543: log_puts(" todo = ");
1544: log_putu(f->wtodo);
1545: }
1546: log_puts("\n");
1547: }
1548: #endif
1549: switch (f->wstate) {
1550: case SOCK_WMSG:
1551: if (!sock_wmsg(f))
1552: return 0;
1553: if (ntohl(f->wmsg.cmd) != AMSG_DATA) {
1554: f->wstate = SOCK_WIDLE;
1555: f->wtodo = 0xdeadbeef;
1556: break;
1557: }
1558: /*
1559: * XXX: why not set f->wtodo in sock_wmsg() ?
1560: */
1561: f->wstate = SOCK_WDATA;
1562: f->wsize = f->wtodo = ntohl(f->wmsg.u.data.size);
1563: /* PASSTHROUGH */
1564: case SOCK_WDATA:
1565: if (!sock_wdata(f))
1566: return 0;
1567: if (f->wtodo > 0)
1568: break;
1569: f->wstate = SOCK_WIDLE;
1570: f->wtodo = 0xdeadbeef;
1571: if (f->pstate == SOCK_STOP) {
1572: f->pstate = SOCK_INIT;
1573: f->wmax = 0;
1574: #ifdef DEBUG
1575: if (log_level >= 4) {
1576: sock_log(f);
1577: log_puts(": drained, moved to INIT state\n");
1578: }
1579: #endif
1580: }
1581: /* PASSTHROUGH */
1582: case SOCK_WIDLE:
1583: if (f->rstate == SOCK_RRET) {
1584: f->wmsg = f->rmsg;
1585: f->wstate = SOCK_WMSG;
1586: f->wtodo = sizeof(struct amsg);
1587: f->rstate = SOCK_RMSG;
1588: f->rtodo = sizeof(struct amsg);
1589: #ifdef DEBUG
1590: if (log_level >= 4) {
1591: sock_log(f);
1592: log_puts(": copied RRET message\n");
1593: }
1594: #endif
1595: } else {
1596: if (!sock_buildmsg(f))
1597: return 0;
1598: }
1599: break;
1600: #ifdef DEBUG
1601: default:
1602: sock_log(f);
1603: log_puts(": bad writing end state\n");
1604: panic();
1605: #endif
1606: }
1607: return 1;
1608: }
1609:
1610: int
1611: sock_pollfd(void *arg, struct pollfd *pfd)
1612: {
1613: struct sock *f = arg;
1614: int events = 0;
1615:
1616: /*
1617: * feedback counters, clock ticks and alike may have changed,
1618: * prepare a message to trigger writes
1619: *
1620: * XXX: doing this at the beginning of the cycle is not optimal,
1621: * because state is changed at the end of the read cycle, and
1622: * thus counters, ret message and alike are generated then.
1623: */
1624: if (f->wstate == SOCK_WIDLE && f->rstate != SOCK_RRET)
1625: sock_buildmsg(f);
1626:
1627: if (f->rstate == SOCK_RMSG ||
1628: f->rstate == SOCK_RDATA)
1629: events |= POLLIN;
1630: if (f->rstate == SOCK_RRET ||
1631: f->wstate == SOCK_WMSG ||
1632: f->wstate == SOCK_WDATA)
1633: events |= POLLOUT;
1634: pfd->fd = f->fd;
1635: pfd->events = events;
1636: return 1;
1637: }
1638:
1639: int
1640: sock_revents(void *arg, struct pollfd *pfd)
1641: {
1642: return pfd->revents;
1643: }
1644:
1645: void
1646: sock_in(void *arg)
1647: {
1648: struct sock *f = arg;
1649:
1650: while (sock_read(f))
1651: ;
1652: }
1653:
1654: void
1655: sock_out(void *arg)
1656: {
1657: struct sock *f = arg;
1658:
1659: while (sock_write(f))
1660: ;
1661: }
1662:
1663: void
1664: sock_hup(void *arg)
1665: {
1666: struct sock *f = arg;
1667:
1668: sock_close(f);
1669: }