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