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