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