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