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