[BACK]Return to sock.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / aucat

Annotation of src/usr.bin/aucat/sock.c, Revision 1.47

1.47    ! ratchov     1: /*     $OpenBSD: sock.c,v 1.46 2010/05/02 11:54:27 ratchov Exp $       */
1.1       ratchov     2: /*
                      3:  * Copyright (c) 2008 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:
1.44      ratchov    18: #include <sys/types.h>
                     19: #include <sys/socket.h>
                     20: #include <unistd.h>
1.1       ratchov    21: #include <stdio.h>
                     22: #include <stdlib.h>
                     23: #include <string.h>
1.20      ratchov    24:
                     25: #include "abuf.h"
1.1       ratchov    26: #include "aproc.h"
1.20      ratchov    27: #include "conf.h"
1.1       ratchov    28: #include "dev.h"
1.19      ratchov    29: #include "midi.h"
                     30: #include "opt.h"
1.20      ratchov    31: #include "sock.h"
1.37      ratchov    32: #ifdef DEBUG
                     33: #include "dbg.h"
                     34: #endif
1.1       ratchov    35:
1.42      ratchov    36: void sock_attach(struct sock *, int);
1.1       ratchov    37: int sock_read(struct sock *);
                     38: int sock_write(struct sock *);
                     39: int sock_execmsg(struct sock *);
                     40: void sock_reset(struct sock *);
1.44      ratchov    41: void sock_close(struct file *);
1.1       ratchov    42:
                     43: struct fileops sock_ops = {
                     44:        "sock",
                     45:        sizeof(struct sock),
1.44      ratchov    46:                sock_close,
1.1       ratchov    47:        pipe_read,
                     48:        pipe_write,
                     49:        NULL, /* start */
                     50:        NULL, /* stop */
                     51:        pipe_nfds,
                     52:        pipe_pollfd,
                     53:        pipe_revents
                     54: };
1.30      ratchov    55:
1.37      ratchov    56: #ifdef DEBUG
                     57: void
                     58: sock_dbg(struct sock *f)
                     59: {
1.42      ratchov    60:        static char *pstates[] = { "hel", "ini", "sta", "rdy", "run", "mid" };
1.37      ratchov    61:        static char *rstates[] = { "rdat", "rmsg", "rret" };
                     62:        static char *wstates[] = { "widl", "wmsg", "wdat" };
                     63:
1.42      ratchov    64:        if (f->slot >= 0 && APROC_OK(dev_midi)) {
1.37      ratchov    65:                dbg_puts(dev_midi->u.ctl.slot[f->slot].name);
                     66:                dbg_putu(dev_midi->u.ctl.slot[f->slot].unit);
                     67:        } else
                     68:                dbg_puts(f->pipe.file.name);
                     69:        dbg_puts("/");
                     70:        dbg_puts(pstates[f->pstate]);
                     71:        dbg_puts("|");
                     72:        dbg_puts(rstates[f->rstate]);
                     73:        dbg_puts("|");
                     74:        dbg_puts(wstates[f->wstate]);
                     75: }
                     76: #endif
1.1       ratchov    77:
1.34      ratchov    78: void sock_setvol(void *, unsigned);
1.35      ratchov    79: void sock_startreq(void *);
1.42      ratchov    80: void sock_stopreq(void *);
                     81: void sock_locreq(void *, unsigned);
1.34      ratchov    82:
                     83: struct ctl_ops ctl_sockops = {
                     84:        sock_setvol,
1.42      ratchov    85:        sock_startreq,
                     86:        sock_stopreq,
                     87:        sock_locreq
1.34      ratchov    88: };
                     89:
1.44      ratchov    90: unsigned sock_sesrefs = 0;     /* connections to the session */
                     91: uid_t sock_sesuid;             /* owner of the session */
                     92:
                     93: void
                     94: sock_close(struct file *f)
                     95: {
                     96:        sock_sesrefs--;
                     97:        pipe_close(f);
1.46      ratchov    98:        dev_unref();
1.44      ratchov    99: }
                    100:
1.1       ratchov   101: void
                    102: rsock_done(struct aproc *p)
                    103: {
                    104:        struct sock *f = (struct sock *)p->u.io.file;
                    105:
1.11      ratchov   106:        if (f == NULL)
                    107:                return;
1.1       ratchov   108:        sock_reset(f);
                    109:        f->pipe.file.rproc = NULL;
                    110:        if (f->pipe.file.wproc) {
1.34      ratchov   111:                if (f->slot >= 0)
1.24      ratchov   112:                        ctl_slotdel(dev_midi, f->slot);
1.1       ratchov   113:                aproc_del(f->pipe.file.wproc);
                    114:                file_del(&f->pipe.file);
                    115:        }
1.11      ratchov   116:        p->u.io.file = NULL;
1.1       ratchov   117: }
                    118:
                    119: int
                    120: rsock_in(struct aproc *p, struct abuf *ibuf_dummy)
                    121: {
                    122:        struct sock *f = (struct sock *)p->u.io.file;
                    123:        struct abuf *obuf;
                    124:
                    125:        if (!sock_read(f))
                    126:                return 0;
1.45      ratchov   127:        obuf = LIST_FIRST(&p->outs);
1.34      ratchov   128:        if (obuf && f->pstate >= SOCK_RUN) {
1.1       ratchov   129:                if (!abuf_flush(obuf))
                    130:                        return 0;
                    131:        }
                    132:        return 1;
                    133: }
                    134:
                    135: int
                    136: rsock_out(struct aproc *p, struct abuf *obuf)
                    137: {
                    138:        struct sock *f = (struct sock *)p->u.io.file;
                    139:
1.19      ratchov   140:        if (f->pipe.file.state & FILE_RINUSE)
1.1       ratchov   141:                return 0;
                    142:
1.12      ratchov   143:        /*
1.20      ratchov   144:         * When calling sock_read(), we may receive a ``STOP'' command,
1.1       ratchov   145:         * and detach ``obuf''. In this case, there's no more caller and
1.20      ratchov   146:         * we'll stop processing further messages, resulting in a deadlock.
1.1       ratchov   147:         * The solution is to iterate over sock_read() in order to
                    148:         * consume all messages().
                    149:         */
                    150:        for (;;) {
                    151:                if (!sock_read(f))
1.12      ratchov   152:                        return 0;
1.1       ratchov   153:        }
                    154:        return 1;
                    155: }
                    156:
                    157: void
                    158: rsock_eof(struct aproc *p, struct abuf *ibuf_dummy)
                    159: {
                    160:        aproc_del(p);
                    161: }
                    162:
                    163: void
                    164: rsock_hup(struct aproc *p, struct abuf *ibuf)
                    165: {
                    166:        aproc_del(p);
                    167: }
                    168:
                    169: void
                    170: rsock_opos(struct aproc *p, struct abuf *obuf, int delta)
                    171: {
                    172:        struct sock *f = (struct sock *)p->u.io.file;
                    173:
1.42      ratchov   174:        if (f->mode & AMSG_RECMASK)
1.14      ratchov   175:                return;
                    176:
                    177:        f->delta += delta;
1.37      ratchov   178: #ifdef DEBUG
                    179:        if (debug_level >= 4) {
                    180:                aproc_dbg(p);
                    181:                dbg_puts(": moved to delta = ");
                    182:                dbg_puti(f->delta);
                    183:                dbg_puts("\n");
                    184:        }
                    185: #endif
1.14      ratchov   186:        f->tickpending++;
1.1       ratchov   187:        for (;;) {
                    188:                if (!sock_write(f))
                    189:                        break;
                    190:        }
                    191: }
                    192:
                    193: struct aproc_ops rsock_ops = {
                    194:        "rsock",
                    195:        rsock_in,
                    196:        rsock_out,
                    197:        rsock_eof,
                    198:        rsock_hup,
                    199:        NULL, /* newin */
                    200:        NULL, /* newout */
                    201:        NULL, /* ipos */
                    202:        rsock_opos,
                    203:        rsock_done
                    204: };
                    205:
                    206: void
                    207: wsock_done(struct aproc *p)
                    208: {
                    209:        struct sock *f = (struct sock *)p->u.io.file;
                    210:
1.11      ratchov   211:        if (f == NULL)
                    212:                return;
1.1       ratchov   213:        sock_reset(f);
                    214:        f->pipe.file.wproc = NULL;
                    215:        if (f->pipe.file.rproc) {
1.34      ratchov   216:                if (f->slot >= 0)
1.24      ratchov   217:                        ctl_slotdel(dev_midi, f->slot);
1.1       ratchov   218:                aproc_del(f->pipe.file.rproc);
                    219:                file_del(&f->pipe.file);
                    220:        }
1.11      ratchov   221:        p->u.io.file = NULL;
1.1       ratchov   222: }
                    223:
                    224: int
                    225: wsock_in(struct aproc *p, struct abuf *ibuf)
                    226: {
                    227:        struct sock *f = (struct sock *)p->u.io.file;
                    228:
1.19      ratchov   229:        if (f->pipe.file.state & FILE_WINUSE)
1.1       ratchov   230:                return 0;
                    231:        /*
1.20      ratchov   232:         * See remark in rsock_out().
1.1       ratchov   233:         */
                    234:        for (;;) {
                    235:                if (!sock_write(f))
                    236:                        return 0;
                    237:        }
                    238:        return 1;
                    239: }
                    240:
                    241: int
                    242: wsock_out(struct aproc *p, struct abuf *obuf_dummy)
                    243: {
1.45      ratchov   244:        struct abuf *ibuf = LIST_FIRST(&p->ins);
1.1       ratchov   245:        struct sock *f = (struct sock *)p->u.io.file;
                    246:
                    247:        if (ibuf) {
                    248:                if (!abuf_fill(ibuf))
                    249:                        return 0;
                    250:        }
                    251:        if (!sock_write(f))
                    252:                return 0;
                    253:        return 1;
                    254: }
                    255:
                    256: void
                    257: wsock_eof(struct aproc *p, struct abuf *obuf)
                    258: {
                    259:        aproc_del(p);
                    260: }
                    261:
                    262: void
                    263: wsock_hup(struct aproc *p, struct abuf *obuf_dummy)
                    264: {
                    265:        aproc_del(p);
                    266: }
                    267:
                    268: void
                    269: wsock_ipos(struct aproc *p, struct abuf *obuf, int delta)
                    270: {
                    271:        struct sock *f = (struct sock *)p->u.io.file;
                    272:
1.42      ratchov   273:        if (!(f->mode & AMSG_RECMASK))
1.14      ratchov   274:                return;
1.1       ratchov   275:
1.14      ratchov   276:        f->delta += delta;
1.37      ratchov   277: #ifdef DEBUG
                    278:        if (debug_level >= 4) {
                    279:                aproc_dbg(p);
                    280:                dbg_puts(": moved to delta = ");
                    281:                dbg_puti(f->delta);
                    282:                dbg_puts("\n");
                    283:        }
                    284: #endif
1.33      ratchov   285:        f->tickpending++;
1.1       ratchov   286:        for (;;) {
                    287:                if (!sock_write(f))
                    288:                        break;
                    289:        }
                    290: }
                    291:
                    292: struct aproc_ops wsock_ops = {
                    293:        "wsock",
                    294:        wsock_in,
                    295:        wsock_out,
                    296:        wsock_eof,
                    297:        wsock_hup,
                    298:        NULL, /* newin */
                    299:        NULL, /* newout */
                    300:        wsock_ipos,
                    301:        NULL, /* opos */
                    302:        wsock_done
                    303: };
                    304:
                    305: /*
1.20      ratchov   306:  * Initialise socket in the SOCK_HELLO state with default
                    307:  * parameters.
1.1       ratchov   308:  */
                    309: struct sock *
1.19      ratchov   310: sock_new(struct fileops *ops, int fd)
1.1       ratchov   311: {
                    312:        struct aproc *rproc, *wproc;
                    313:        struct sock *f;
1.44      ratchov   314:        uid_t uid, gid;
                    315:
                    316:        /*
                    317:         * ensure that all connections belong to the same user,
                    318:         * for privacy reasons.
                    319:         *
                    320:         * XXX: is there a portable way of doing this ?
                    321:         */
                    322:        if (getpeereid(fd, &uid, &gid) < 0) {
                    323:                close(fd);
                    324:                return NULL;
                    325:        }
                    326:        if (sock_sesrefs == 0) {
                    327:                /* start a new session */
                    328:                sock_sesuid = uid;
                    329:        } else if (uid != sock_sesuid) {
                    330:                /* session owned by another user, drop connection */
                    331:                close(fd);
                    332:                return NULL;
                    333:        }
                    334:        sock_sesrefs++;
1.1       ratchov   335:
1.19      ratchov   336:        f = (struct sock *)pipe_new(ops, fd, "sock");
1.46      ratchov   337:        if (f == NULL) {
                    338:                close(fd);
                    339:                return NULL;
                    340:        }
                    341:        if (!dev_ref()) {
                    342:                close(fd);
1.13      ratchov   343:                return NULL;
1.46      ratchov   344:        }
1.18      ratchov   345:        f->pstate = SOCK_HELLO;
1.1       ratchov   346:        f->mode = 0;
1.19      ratchov   347:        f->opt = opt_byname("default");
                    348:        if (f->opt) {
1.42      ratchov   349:                if (f->opt->mode & MODE_RECMASK)
1.19      ratchov   350:                        f->wpar = f->opt->wpar;
1.42      ratchov   351:                if (f->opt->mode & MODE_PLAY)
1.19      ratchov   352:                        f->rpar = f->opt->rpar;
1.1       ratchov   353:        }
                    354:        f->xrun = AMSG_IGNORE;
1.10      ratchov   355:        f->bufsz = dev_bufsz;
1.1       ratchov   356:        f->round = dev_round;
1.14      ratchov   357:        f->delta = 0;
                    358:        f->tickpending = 0;
1.42      ratchov   359:        f->startpending = 0;
1.25      ratchov   360:        f->vol = f->lastvol = MIDI_MAXCTL;
1.24      ratchov   361:        f->slot = -1;
1.1       ratchov   362:
1.19      ratchov   363:        wproc = aproc_new(&wsock_ops, f->pipe.file.name);
1.1       ratchov   364:        wproc->u.io.file = &f->pipe.file;
1.42      ratchov   365:        wproc->u.io.partial = 0;
1.1       ratchov   366:        f->pipe.file.wproc = wproc;
                    367:        f->wstate = SOCK_WIDLE;
                    368:        f->wtodo = 0xdeadbeef;
                    369:
1.19      ratchov   370:        rproc = aproc_new(&rsock_ops, f->pipe.file.name);
1.1       ratchov   371:        rproc->u.io.file = &f->pipe.file;
1.42      ratchov   372:        rproc->u.io.partial = 0;
1.1       ratchov   373:        f->pipe.file.rproc = rproc;
                    374:        f->rstate = SOCK_RMSG;
                    375:        f->rtodo = sizeof(struct amsg);
                    376:        return f;
                    377: }
                    378:
                    379: /*
1.20      ratchov   380:  * Free buffers.
1.1       ratchov   381:  */
                    382: void
                    383: sock_freebuf(struct sock *f)
                    384: {
                    385:        struct abuf *rbuf, *wbuf;
1.12      ratchov   386:
1.1       ratchov   387:        f->pstate = SOCK_INIT;
1.37      ratchov   388: #ifdef DEBUG
                    389:        if (debug_level >= 3) {
                    390:                sock_dbg(f);
                    391:                dbg_puts(": freeing buffers\n");
                    392:        }
                    393: #endif
1.45      ratchov   394:        wbuf = LIST_FIRST(&f->pipe.file.wproc->ins);
                    395:        rbuf = LIST_FIRST(&f->pipe.file.rproc->outs);
1.35      ratchov   396:        if (rbuf || wbuf)
                    397:                ctl_slotstop(dev_midi, f->slot);
1.1       ratchov   398:        if (rbuf)
                    399:                abuf_eof(rbuf);
                    400:        if (wbuf)
                    401:                abuf_hup(wbuf);
1.32      ratchov   402:        f->tickpending = 0;
1.42      ratchov   403:        f->startpending = 0;
1.1       ratchov   404: }
                    405:
                    406: /*
1.20      ratchov   407:  * Allocate buffers, so client can start filling write-end.
1.1       ratchov   408:  */
                    409: void
                    410: sock_allocbuf(struct sock *f)
                    411: {
                    412:        struct abuf *rbuf = NULL, *wbuf = NULL;
                    413:
1.42      ratchov   414:        f->pstate = SOCK_START;
1.1       ratchov   415:        if (f->mode & AMSG_PLAY) {
1.10      ratchov   416:                rbuf = abuf_new(f->bufsz, &f->rpar);
1.1       ratchov   417:                aproc_setout(f->pipe.file.rproc, rbuf);
1.42      ratchov   418:                if (!ABUF_WOK(rbuf) || (f->pipe.file.state & FILE_EOF))
                    419:                        f->pstate = SOCK_READY;
1.1       ratchov   420:        }
1.42      ratchov   421:        if (f->mode & AMSG_RECMASK) {
1.10      ratchov   422:                wbuf = abuf_new(f->bufsz, &f->wpar);
1.1       ratchov   423:                aproc_setin(f->pipe.file.wproc, wbuf);
1.42      ratchov   424:                f->walign = f->round;
1.1       ratchov   425:        }
1.14      ratchov   426:        f->delta = 0;
1.42      ratchov   427:        f->wmax = 0;
                    428:        f->rmax = f->bufsz;
1.14      ratchov   429:        f->tickpending = 0;
1.42      ratchov   430:        f->startpending = 0;
1.37      ratchov   431: #ifdef DEBUG
                    432:        if (debug_level >= 3) {
                    433:                sock_dbg(f);
                    434:                dbg_puts(": allocating ");
                    435:                dbg_putu(f->bufsz);
1.42      ratchov   436:                dbg_puts(" fr buffers, rmax = ");
                    437:                dbg_putu(f->rmax);
                    438:                dbg_puts("\n");
1.37      ratchov   439:        }
                    440: #endif
1.42      ratchov   441:        if (f->mode & AMSG_PLAY) {
                    442:                f->pstate = SOCK_START;
                    443:        } else {
                    444:                f->pstate = SOCK_READY;
                    445:                if (ctl_slotstart(dev_midi, f->slot))
                    446:                        (void)sock_attach(f, 0);
                    447:        }
1.1       ratchov   448: }
                    449:
                    450: /*
1.25      ratchov   451:  * Set volume. Callback invoked when volume is modified externally
1.3       ratchov   452:  */
                    453: void
1.25      ratchov   454: sock_setvol(void *arg, unsigned vol)
1.3       ratchov   455: {
1.25      ratchov   456:        struct sock *f = (struct sock *)arg;
1.3       ratchov   457:        struct abuf *rbuf;
1.12      ratchov   458:
1.3       ratchov   459:        f->vol = vol;
1.45      ratchov   460:        rbuf = LIST_FIRST(&f->pipe.file.rproc->outs);
1.3       ratchov   461:        if (!rbuf) {
1.37      ratchov   462: #ifdef DEBUG
                    463:                if (debug_level >= 3) {
                    464:                        sock_dbg(f);
                    465:                        dbg_puts(": no read buffer to set volume yet\n");
                    466:                }
                    467: #endif
1.3       ratchov   468:                return;
                    469:        }
1.25      ratchov   470:        dev_setvol(rbuf, MIDI_TO_ADATA(vol));
1.3       ratchov   471: }
                    472:
                    473: /*
1.35      ratchov   474:  * Attach the stream. Callback invoked when MMC start
                    475:  */
                    476: void
                    477: sock_startreq(void *arg)
                    478: {
                    479:        struct sock *f = (struct sock *)arg;
                    480:
1.37      ratchov   481: #ifdef DEBUG
1.42      ratchov   482:        if (f->pstate != SOCK_READY) {
1.37      ratchov   483:                sock_dbg(f);
1.42      ratchov   484:                dbg_puts(": not in READY state\n");
1.37      ratchov   485:                dbg_panic();
                    486:        }
                    487: #endif
1.35      ratchov   488:        (void)sock_attach(f, 0);
                    489: }
                    490:
                    491: /*
1.42      ratchov   492:  * Callback invoked by MMC stop
                    493:  */
                    494: void
                    495: sock_stopreq(void *arg)
                    496: {
                    497: #ifdef DEBUG
                    498:        struct sock *f = (struct sock *)arg;
                    499:
                    500:        if (debug_level >= 3) {
                    501:                sock_dbg(f);
                    502:                dbg_puts(": ignored STOP signal\n");
                    503:        }
                    504: #endif
                    505: }
                    506:
                    507: /*
                    508:  * Callback invoked by MMC relocate, ignored
                    509:  */
                    510: void
                    511: sock_locreq(void *arg, unsigned mmcpos)
                    512: {
                    513: #ifdef DEBUG
                    514:        struct sock *f = (struct sock *)arg;
                    515:
                    516:        if (debug_level >= 3) {
                    517:                sock_dbg(f);
                    518:                dbg_puts(": ignored RELOCATE signal\n");
                    519:        }
                    520: #endif
                    521: }
                    522:
                    523: /*
1.20      ratchov   524:  * Attach play and/or record buffers to dev_mix and/or dev_sub.
1.1       ratchov   525:  */
1.42      ratchov   526: void
1.1       ratchov   527: sock_attach(struct sock *f, int force)
                    528: {
                    529:        struct abuf *rbuf, *wbuf;
                    530:
1.45      ratchov   531:        rbuf = LIST_FIRST(&f->pipe.file.rproc->outs);
                    532:        wbuf = LIST_FIRST(&f->pipe.file.wproc->ins);
1.1       ratchov   533:
                    534:        /*
1.20      ratchov   535:         * If in SOCK_START state, dont attach until
                    536:         * the buffer isn't completely filled.
1.1       ratchov   537:         */
                    538:        if (!force && rbuf && ABUF_WOK(rbuf))
1.42      ratchov   539:                return;
1.12      ratchov   540:
1.42      ratchov   541:        /*
1.46      ratchov   542:         * start the device (dev_getpos() and dev_attach() must
                    543:         * be called on a started device
                    544:         */
1.47    ! ratchov   545:        dev_wakeup();
1.46      ratchov   546:
                    547:        /*
1.42      ratchov   548:         * get the current position, the origin is when
                    549:         * the first sample is played/recorded
                    550:         */
                    551:        f->delta = dev_getpos() * (int)f->round / (int)dev_round;
                    552:        f->startpending = 1;
                    553:        f->pstate = SOCK_RUN;
1.37      ratchov   554: #ifdef DEBUG
                    555:        if (debug_level >= 3) {
                    556:                sock_dbg(f);
1.42      ratchov   557:                dbg_puts(": attaching at ");
                    558:                dbg_puti(f->delta);
                    559:                dbg_puts("\n");
1.37      ratchov   560:        }
                    561: #endif
1.1       ratchov   562:        /*
1.42      ratchov   563:         * We dont check whether the device is dying,
                    564:         * because dev_xxx() functions are supposed to
                    565:         * work (i.e., not to crash)
1.1       ratchov   566:         */
1.42      ratchov   567:        dev_attach(f->pipe.file.name, f->mode,
1.43      ratchov   568:            rbuf, &f->rpar,
                    569:            f->opt->join ? f->opt->rpar.cmax - f->opt->rpar.cmin + 1 : 0,
                    570:            wbuf, &f->wpar,
                    571:            f->opt->join ? f->opt->wpar.cmax - f->opt->wpar.cmin + 1 : 0,
                    572:            f->xrun, f->opt->maxweight);
1.3       ratchov   573:        if (f->mode & AMSG_PLAY)
1.25      ratchov   574:                dev_setvol(rbuf, MIDI_TO_ADATA(f->vol));
1.3       ratchov   575:
1.1       ratchov   576:        /*
1.20      ratchov   577:         * Send the initial position, if needed.
1.1       ratchov   578:         */
                    579:        for (;;) {
                    580:                if (!sock_write(f))
                    581:                        break;
                    582:        }
                    583: }
                    584:
                    585: void
                    586: sock_reset(struct sock *f)
                    587: {
                    588:        switch (f->pstate) {
                    589:        case SOCK_START:
1.42      ratchov   590:        case SOCK_READY:
1.35      ratchov   591:                if (ctl_slotstart(dev_midi, f->slot)) {
                    592:                        (void)sock_attach(f, 1);
                    593:                        f->pstate = SOCK_RUN;
                    594:                }
1.1       ratchov   595:                /* PASSTHROUGH */
                    596:        case SOCK_RUN:
                    597:                sock_freebuf(f);
                    598:                f->pstate = SOCK_INIT;
                    599:                /* PASSTHROUGH */
                    600:        case SOCK_INIT:
                    601:                /* nothing yet */
                    602:                break;
                    603:        }
                    604: }
                    605:
                    606: /*
1.20      ratchov   607:  * Read a message from the file descriptor, return 1 if done, 0
                    608:  * otherwise. The message is stored in f->rmsg.
1.1       ratchov   609:  */
                    610: int
                    611: sock_rmsg(struct sock *f)
                    612: {
                    613:        unsigned count;
                    614:        unsigned char *data;
                    615:
                    616:        while (f->rtodo > 0) {
                    617:                if (!(f->pipe.file.state & FILE_ROK)) {
1.37      ratchov   618: #ifdef DEBUG
                    619:                        if (debug_level >= 4) {
                    620:                                sock_dbg(f);
                    621:                                dbg_puts(": reading message blocked, ");
                    622:                                dbg_putu(f->rtodo);
                    623:                                dbg_puts(" bytes remaining\n");
                    624:                        }
                    625: #endif
1.1       ratchov   626:                        return 0;
                    627:                }
                    628:                data = (unsigned char *)&f->rmsg;
                    629:                data += sizeof(struct amsg) - f->rtodo;
                    630:                count = file_read(&f->pipe.file, data, f->rtodo);
                    631:                if (count == 0)
                    632:                        return 0;
                    633:                f->rtodo -= count;
                    634:        }
1.37      ratchov   635: #ifdef DEBUG
                    636:        if (debug_level >= 4) {
                    637:                sock_dbg(f);
                    638:                dbg_puts(": read full message\n");
                    639:        }
                    640: #endif
1.1       ratchov   641:        return 1;
                    642: }
                    643:
                    644: /*
1.20      ratchov   645:  * Write a message to the file descriptor, return 1 if done, 0
1.1       ratchov   646:  * otherwise.  The "m" argument is f->rmsg or f->wmsg, and the "ptodo"
                    647:  * points to the f->rtodo or f->wtodo respectively.
                    648:  */
                    649: int
                    650: sock_wmsg(struct sock *f, struct amsg *m, unsigned *ptodo)
                    651: {
                    652:        unsigned count;
                    653:        unsigned char *data;
                    654:
                    655:        while (*ptodo > 0) {
                    656:                if (!(f->pipe.file.state & FILE_WOK)) {
1.37      ratchov   657: #ifdef DEBUG
                    658:                        if (debug_level >= 4) {
                    659:                                sock_dbg(f);
                    660:                                dbg_puts(": writing message blocked, ");
                    661:                                dbg_putu(*ptodo);
                    662:                                dbg_puts(" bytes remaining\n");
                    663:                        }
                    664: #endif
1.1       ratchov   665:                        return 0;
                    666:                }
                    667:                data = (unsigned char *)m;
                    668:                data += sizeof(struct amsg) - *ptodo;
                    669:                count = file_write(&f->pipe.file, data, *ptodo);
                    670:                if (count == 0)
                    671:                        return 0;
                    672:                *ptodo -= count;
                    673:        }
1.37      ratchov   674: #ifdef DEBUG
                    675:        if (debug_level >= 4) {
                    676:                sock_dbg(f);
                    677:                dbg_puts(": wrote full message\n");
                    678:        }
                    679: #endif
1.1       ratchov   680:        return 1;
                    681: }
                    682:
                    683: /*
1.20      ratchov   684:  * Read data chunk from the file descriptor, return 1 if at least one
1.1       ratchov   685:  * byte was read, 0 if the file blocked.
                    686:  */
                    687: int
                    688: sock_rdata(struct sock *f)
                    689: {
                    690:        struct aproc *p;
                    691:        struct abuf *obuf;
1.42      ratchov   692:        unsigned n;
1.1       ratchov   693:
1.37      ratchov   694: #ifdef DEBUG
                    695:        if (f->pstate != SOCK_MIDI && f->rtodo == 0) {
                    696:                sock_dbg(f);
                    697:                dbg_puts(": data block already read\n");
                    698:                dbg_panic();
                    699:        }
                    700: #endif
1.1       ratchov   701:        p = f->pipe.file.rproc;
1.45      ratchov   702:        obuf = LIST_FIRST(&p->outs);
1.19      ratchov   703:        if (obuf == NULL)
                    704:                return 0;
1.42      ratchov   705:        if (!ABUF_WOK(obuf) || !(f->pipe.file.state & FILE_ROK))
1.41      ratchov   706:                return 0;
1.42      ratchov   707:        if (f->pstate == SOCK_MIDI) {
                    708:                if (!rfile_do(p, obuf->len, NULL))
                    709:                        return 0;
                    710:        } else {
                    711:                if (!rfile_do(p, f->rtodo, &n))
                    712:                        return 0;
1.19      ratchov   713:                f->rtodo -= n;
1.42      ratchov   714:                if (f->pstate == SOCK_START) {
                    715:                        if (!ABUF_WOK(obuf) || (f->pipe.file.state & FILE_EOF))
                    716:                                f->pstate = SOCK_READY;
                    717:                }
                    718:        }
1.1       ratchov   719:        return 1;
                    720: }
                    721:
                    722: /*
1.20      ratchov   723:  * Write data chunk to the file descriptor, return 1 if at least one
1.1       ratchov   724:  * byte was written, 0 if the file blocked.
                    725:  */
                    726: int
                    727: sock_wdata(struct sock *f)
                    728: {
                    729:        struct aproc *p;
                    730:        struct abuf *ibuf;
1.42      ratchov   731:        unsigned n;
1.1       ratchov   732:
1.37      ratchov   733: #ifdef DEBUG
                    734:        if (f->pstate != SOCK_MIDI && f->wtodo == 0) {
                    735:                sock_dbg(f);
                    736:                dbg_puts(": attempted to write zero-sized data block\n");
                    737:                dbg_panic();
                    738:        }
                    739: #endif
1.1       ratchov   740:        if (!(f->pipe.file.state & FILE_WOK))
                    741:                return 0;
                    742:        p = f->pipe.file.wproc;
1.45      ratchov   743:        ibuf = LIST_FIRST(&p->ins);
1.42      ratchov   744: #ifdef DEBUG
                    745:        if (f->pstate != SOCK_MIDI && ibuf == NULL) {
                    746:                sock_dbg(f);
                    747:                dbg_puts(": attempted to write on detached buffer\n");
                    748:                dbg_panic();
                    749:        }
                    750: #endif
                    751:        if (ibuf == NULL)
                    752:                return 0;
                    753:        if (!ABUF_ROK(ibuf))
                    754:                return 0;
                    755:        if (f->pstate == SOCK_MIDI) {
                    756:                if (!wfile_do(p, ibuf->len, NULL))
1.1       ratchov   757:                        return 0;
                    758:        } else {
1.42      ratchov   759:                if (!wfile_do(p, f->wtodo, &n))
1.1       ratchov   760:                        return 0;
                    761:                f->wtodo -= n;
1.12      ratchov   762:        }
1.1       ratchov   763:        return 1;
                    764: }
                    765:
                    766: int
                    767: sock_setpar(struct sock *f)
                    768: {
                    769:        struct amsg_par *p = &f->rmsg.u.par;
1.9       ratchov   770:        unsigned min, max, rate;
1.12      ratchov   771:
1.1       ratchov   772:        if (AMSG_ISSET(p->bits)) {
                    773:                if (p->bits < BITS_MIN || p->bits > BITS_MAX) {
1.37      ratchov   774: #ifdef DEBUG
                    775:                        if (debug_level >= 1) {
                    776:                                sock_dbg(f);
                    777:                                dbg_puts(": ");
                    778:                                dbg_putu(p->bits);
                    779:                                dbg_puts(": bits out of bounds\n");
                    780:                        }
                    781: #endif
1.1       ratchov   782:                        return 0;
                    783:                }
                    784:                if (AMSG_ISSET(p->bps)) {
                    785:                        if (p->bps < ((p->bits + 7) / 8) || p->bps > 4) {
1.37      ratchov   786: #ifdef DEBUG
                    787:                                if (debug_level >= 1) {
                    788:                                        sock_dbg(f);
                    789:                                        dbg_puts(": ");
                    790:                                        dbg_putu(p->bps);
                    791:                                        dbg_puts(": wrong bytes per sample\n");
                    792:                                }
                    793: #endif
1.1       ratchov   794:                                return 0;
                    795:                        }
                    796:                } else
                    797:                        p->bps = APARAMS_BPS(p->bits);
                    798:                f->rpar.bits = f->wpar.bits = p->bits;
                    799:                f->rpar.bps = f->wpar.bps = p->bps;
1.37      ratchov   800: #ifdef DEBUG
                    801:                if (debug_level >= 3) {
                    802:                        sock_dbg(f);
                    803:                        dbg_puts(": using ");
                    804:                        dbg_putu(p->bits);
                    805:                        dbg_puts("bits, ");
                    806:                        dbg_putu(p->bps);
                    807:                        dbg_puts(" bytes per sample\n");
                    808:                }
                    809: #endif
1.1       ratchov   810:        }
                    811:        if (AMSG_ISSET(p->sig))
                    812:                f->rpar.sig = f->wpar.sig = p->sig ? 1 : 0;
                    813:        if (AMSG_ISSET(p->le))
                    814:                f->rpar.le = f->wpar.le = p->le ? 1 : 0;
                    815:        if (AMSG_ISSET(p->msb))
                    816:                f->rpar.msb = f->wpar.msb = p->msb ? 1 : 0;
1.42      ratchov   817:        if (AMSG_ISSET(p->rchan) && (f->mode & AMSG_RECMASK)) {
1.1       ratchov   818:                if (p->rchan < 1)
                    819:                        p->rchan = 1;
1.6       ratchov   820:                if (p->rchan > NCHAN_MAX)
                    821:                        p->rchan = NCHAN_MAX;
1.19      ratchov   822:                f->wpar.cmin = f->opt->wpar.cmin;
                    823:                f->wpar.cmax = f->opt->wpar.cmin + p->rchan - 1;
                    824:                if (f->wpar.cmax > f->opt->wpar.cmax)
                    825:                        f->wpar.cmax = f->opt->wpar.cmax;
1.37      ratchov   826: #ifdef DEBUG
                    827:                if (debug_level >= 3) {
                    828:                        sock_dbg(f);
                    829:                        dbg_puts(": using recording channels ");
                    830:                        dbg_putu(f->wpar.cmin);
                    831:                        dbg_puts("..");
                    832:                        dbg_putu(f->wpar.cmax);
                    833:                        dbg_puts("\n");
                    834:                }
                    835: #endif
1.1       ratchov   836:        }
                    837:        if (AMSG_ISSET(p->pchan) && (f->mode & AMSG_PLAY)) {
                    838:                if (p->pchan < 1)
                    839:                        p->pchan = 1;
1.6       ratchov   840:                if (p->pchan > NCHAN_MAX)
                    841:                        p->pchan = NCHAN_MAX;
1.19      ratchov   842:                f->rpar.cmin = f->opt->rpar.cmin;
                    843:                f->rpar.cmax = f->opt->rpar.cmin + p->pchan - 1;
                    844:                if (f->rpar.cmax > f->opt->rpar.cmax)
                    845:                        f->rpar.cmax = f->opt->rpar.cmax;
1.37      ratchov   846: #ifdef DEBUG
                    847:                if (debug_level >= 3) {
                    848:                        sock_dbg(f);
                    849:                        dbg_puts(": using playback channels ");
                    850:                        dbg_putu(f->rpar.cmin);
                    851:                        dbg_puts("..");
                    852:                        dbg_putu(f->rpar.cmax);
                    853:                        dbg_puts("\n");
                    854:                }
                    855: #endif
1.1       ratchov   856:        }
                    857:        if (AMSG_ISSET(p->rate)) {
                    858:                if (p->rate < RATE_MIN)
                    859:                        p->rate = RATE_MIN;
                    860:                if (p->rate > RATE_MAX)
                    861:                        p->rate = RATE_MAX;
1.9       ratchov   862:                f->round = dev_roundof(p->rate);
1.1       ratchov   863:                f->rpar.rate = f->wpar.rate = p->rate;
1.10      ratchov   864:                if (!AMSG_ISSET(p->appbufsz)) {
                    865:                        p->appbufsz = dev_bufsz / dev_round * f->round;
1.37      ratchov   866: #ifdef DEBUG
                    867:                        if (debug_level >= 3) {
                    868:                                sock_dbg(f);
                    869:                                dbg_puts(": using ");
                    870:                                dbg_putu(p->appbufsz);
                    871:                                dbg_puts(" fr app buffer size\n");
                    872:                        }
                    873: #endif
                    874:                }
                    875: #ifdef DEBUG
                    876:                if (debug_level >= 3) {
                    877:                        sock_dbg(f);
                    878:                        dbg_puts(": using ");
                    879:                        dbg_putu(p->rate);
                    880:                        dbg_puts("Hz sample rate, ");
                    881:                        dbg_putu(f->round);
                    882:                        dbg_puts(" fr block size\n");
1.10      ratchov   883:                }
1.37      ratchov   884: #endif
1.1       ratchov   885:        }
                    886:        if (AMSG_ISSET(p->xrun)) {
                    887:                if (p->xrun != AMSG_IGNORE &&
                    888:                    p->xrun != AMSG_SYNC &&
                    889:                    p->xrun != AMSG_ERROR) {
1.37      ratchov   890: #ifdef DEBUG
                    891:                        if (debug_level >= 1) {
                    892:                                sock_dbg(f);
                    893:                                dbg_puts(": ");
                    894:                                dbg_putx(p->xrun);
                    895:                                dbg_puts(": bad xrun policy\n");
                    896:                        }
                    897: #endif
1.1       ratchov   898:                        return 0;
                    899:                }
                    900:                f->xrun = p->xrun;
1.35      ratchov   901:                if (f->opt->mmc && f->xrun == AMSG_IGNORE)
                    902:                        f->xrun = AMSG_SYNC;
1.37      ratchov   903: #ifdef DEBUG
                    904:                if (debug_level >= 3) {
                    905:                        sock_dbg(f);
                    906:                        dbg_puts(": using 0x");
                    907:                        dbg_putx(f->xrun);
                    908:                        dbg_puts(" xrun policy\n");
                    909:                }
                    910: #endif
1.1       ratchov   911:        }
                    912:        if (AMSG_ISSET(p->bufsz)) {
1.10      ratchov   913:                /*
                    914:                 * XXX: bufsz will become read-only, but for now
                    915:                 *      allow old library to properly work
                    916:                 */
1.37      ratchov   917: #ifdef DEBUG
                    918:                if (debug_level >= 1) {
                    919:                        sock_dbg(f);
                    920:                        dbg_puts(": legacy client using ");
                    921:                        dbg_putx(p->bufsz);
                    922:                        dbg_puts("fr total buffer size\n");
                    923:                }
                    924: #endif
1.10      ratchov   925:                min = (dev_bufsz / dev_round) * f->round;
                    926:                if (p->bufsz < min)
                    927:                        p->bufsz = min;
                    928:                p->appbufsz = p->bufsz - min;
                    929:        }
                    930:        if (AMSG_ISSET(p->appbufsz)) {
1.9       ratchov   931:                rate = (f->mode & AMSG_PLAY) ? f->rpar.rate : f->wpar.rate;
1.42      ratchov   932:                min = 1;
                    933:                max = 1 + rate / dev_round;
1.9       ratchov   934:                min *= f->round;
                    935:                max *= f->round;
1.10      ratchov   936:                p->appbufsz += f->round - 1;
                    937:                p->appbufsz -= p->appbufsz % f->round;
                    938:                if (p->appbufsz < min)
                    939:                        p->appbufsz = min;
                    940:                if (p->appbufsz > max)
                    941:                        p->appbufsz = max;
                    942:                f->bufsz = p->appbufsz;
1.37      ratchov   943: #ifdef DEBUG
                    944:                if (debug_level >= 3) {
                    945:                        sock_dbg(f);
                    946:                        dbg_puts(": using ");
                    947:                        dbg_putu(f->bufsz);
                    948:                        dbg_puts(" buffer size\n");
                    949:                }
                    950: #endif
                    951:        }
                    952: #ifdef DEBUG
                    953:        if (debug_level >= 2) {
1.42      ratchov   954:                if (f->slot >= 0 && dev_midi) {
1.37      ratchov   955:                        dbg_puts(dev_midi->u.ctl.slot[f->slot].name);
                    956:                        dbg_putu(dev_midi->u.ctl.slot[f->slot].unit);
                    957:                } else
                    958:                        dbg_puts(f->pipe.file.name);
                    959:                dbg_puts(": buffer size = ");
                    960:                dbg_putu(f->bufsz);
                    961:                if (f->mode & AMSG_PLAY) {
                    962:                        dbg_puts(", play = ");
                    963:                        aparams_dbg(&f->rpar);
                    964:                }
1.42      ratchov   965:                if (f->mode & AMSG_RECMASK) {
1.37      ratchov   966:                        dbg_puts(", rec:");
                    967:                        aparams_dbg(&f->wpar);
                    968:                }
                    969:                dbg_puts("\n");
1.1       ratchov   970:        }
1.37      ratchov   971: #endif
1.1       ratchov   972:        return 1;
                    973: }
                    974:
1.19      ratchov   975: /*
                    976:  * allocate buffers, so client can start filling write-end.
                    977:  */
                    978: void
                    979: sock_midiattach(struct sock *f, unsigned mode)
                    980: {
                    981:        struct abuf *rbuf = NULL, *wbuf = NULL;
                    982:
                    983:        if (mode & AMSG_MIDIOUT) {
1.22      ratchov   984:                rbuf = abuf_new(MIDI_BUFSZ, &aparams_none);
1.19      ratchov   985:                aproc_setout(f->pipe.file.rproc, rbuf);
                    986:        }
                    987:        if (mode & AMSG_MIDIIN) {
1.22      ratchov   988:                wbuf = abuf_new(MIDI_BUFSZ, &aparams_none);
1.19      ratchov   989:                aproc_setin(f->pipe.file.wproc, wbuf);
                    990:        }
1.23      ratchov   991:        dev_midiattach(rbuf, wbuf);
1.19      ratchov   992: }
                    993:
1.17      ratchov   994: int
                    995: sock_hello(struct sock *f)
                    996: {
                    997:        struct amsg_hello *p = &f->rmsg.u.hello;
                    998:
1.37      ratchov   999: #ifdef DEBUG
                   1000:        if (debug_level >= 3) {
                   1001:                sock_dbg(f);
                   1002:                dbg_puts(": hello from <");
                   1003:                dbg_puts(p->who);
                   1004:                dbg_puts(">, proto = ");
                   1005:                dbg_putx(p->proto);
                   1006:                dbg_puts(", ver ");
                   1007:                dbg_putu(p->version);
                   1008:                dbg_puts("\n");
                   1009:        }
                   1010: #endif
1.33      ratchov  1011:        if (p->version != AMSG_VERSION) {
1.37      ratchov  1012: #ifdef DEBUG
                   1013:                if (debug_level >= 1) {
                   1014:                        sock_dbg(f);
                   1015:                        dbg_puts(": ");
                   1016:                        dbg_putu(p->version);
                   1017:                        dbg_puts(": bad version\n");
                   1018:                }
                   1019: #endif
1.33      ratchov  1020:                return 0;
                   1021:        }
                   1022:        /*
                   1023:         * XXX : dev_midi can no longer be NULL, right ?
                   1024:         */
1.42      ratchov  1025:        if (APROC_OK(dev_midi) && (p->proto & (AMSG_MIDIIN | AMSG_MIDIOUT))) {
1.19      ratchov  1026:                if (p->proto & ~(AMSG_MIDIIN | AMSG_MIDIOUT)) {
1.37      ratchov  1027: #ifdef DEBUG
                   1028:                        if (debug_level >= 1) {
                   1029:                                sock_dbg(f);
                   1030:                                dbg_puts(": ");
                   1031:                                dbg_putx(p->proto);
                   1032:                                dbg_puts(": bad hello protocol\n");
                   1033:                        }
                   1034: #endif
1.19      ratchov  1035:                        return 0;
                   1036:                }
                   1037:                f->mode = p->proto;
                   1038:                f->pstate = SOCK_MIDI;
                   1039:                sock_midiattach(f, p->proto);
                   1040:                return 1;
                   1041:        }
                   1042:        f->opt = opt_byname(p->opt);
                   1043:        if (f->opt == NULL)
                   1044:                return 0;
1.42      ratchov  1045:        if (f->opt->mode & MODE_RECMASK)
1.19      ratchov  1046:                f->wpar = f->opt->wpar;
1.42      ratchov  1047:        if (f->opt->mode & MODE_PLAY)
1.19      ratchov  1048:                f->rpar = f->opt->rpar;
1.35      ratchov  1049:        if (f->opt->mmc)
                   1050:                f->xrun = AMSG_SYNC;
1.18      ratchov  1051:        if ((p->proto & ~(AMSG_PLAY | AMSG_REC)) != 0 ||
                   1052:            (p->proto &  (AMSG_PLAY | AMSG_REC)) == 0) {
1.37      ratchov  1053: #ifdef DEBUG
                   1054:                if (debug_level >= 1) {
                   1055:                        sock_dbg(f);
                   1056:                        dbg_puts(": ");
                   1057:                        dbg_putx(p->proto);
                   1058:                        dbg_puts(": unsupported hello protocol\n");
                   1059:                }
                   1060: #endif
1.17      ratchov  1061:                return 0;
                   1062:        }
1.18      ratchov  1063:        f->mode = 0;
                   1064:        if (p->proto & AMSG_PLAY) {
1.42      ratchov  1065:                if (!APROC_OK(dev_mix) || !(f->opt->mode & MODE_PLAY)) {
1.37      ratchov  1066: #ifdef DEBUG
                   1067:                        if (debug_level >= 1) {
                   1068:                                sock_dbg(f);
                   1069:                                dbg_puts(": playback not available\n");
                   1070:                        }
                   1071: #endif
1.18      ratchov  1072:                        return 0;
                   1073:                }
                   1074:                f->mode |= AMSG_PLAY;
1.17      ratchov  1075:        }
1.18      ratchov  1076:        if (p->proto & AMSG_REC) {
1.42      ratchov  1077:                if (!(APROC_OK(dev_sub)    && (f->opt->mode & MODE_REC)) &&
                   1078:                    !(APROC_OK(dev_submon) && (f->opt->mode & MODE_MON))) {
1.37      ratchov  1079: #ifdef DEBUG
                   1080:                        if (debug_level >= 1) {
                   1081:                                sock_dbg(f);
                   1082:                                dbg_puts(": recording not available\n");
                   1083:                        }
                   1084: #endif
1.18      ratchov  1085:                        return 0;
                   1086:                }
1.42      ratchov  1087:                f->mode |= (f->opt->mode & MODE_MON) ? AMSG_MON : AMSG_REC;
1.17      ratchov  1088:        }
1.42      ratchov  1089:        if (APROC_OK(dev_midi)) {
1.35      ratchov  1090:                f->slot = ctl_slotnew(dev_midi,
                   1091:                     p->who, &ctl_sockops, f,
                   1092:                     f->opt->mmc);
1.24      ratchov  1093:                if (f->slot < 0) {
1.37      ratchov  1094: #ifdef DEBUG
                   1095:                        if (debug_level >= 1) {
                   1096:                                sock_dbg(f);
                   1097:                                dbg_puts(": out of mixer slots\n");
                   1098:                        }
                   1099: #endif
1.24      ratchov  1100:                        return 0;
                   1101:                }
                   1102:        }
1.18      ratchov  1103:        f->pstate = SOCK_INIT;
1.17      ratchov  1104:        return 1;
                   1105: }
                   1106:
1.1       ratchov  1107: /*
1.20      ratchov  1108:  * Execute message in f->rmsg and change the state accordingly; return 1
1.1       ratchov  1109:  * on success, and 0 on failure, in which case the socket is destroyed.
                   1110:  */
                   1111: int
                   1112: sock_execmsg(struct sock *f)
                   1113: {
                   1114:        struct amsg *m = &f->rmsg;
1.42      ratchov  1115:        struct abuf *obuf;
1.1       ratchov  1116:
                   1117:        switch (m->cmd) {
                   1118:        case AMSG_DATA:
1.37      ratchov  1119: #ifdef DEBUG
                   1120:                if (debug_level >= 4) {
                   1121:                        sock_dbg(f);
                   1122:                        dbg_puts(": DATA message\n");
                   1123:                }
                   1124: #endif
1.42      ratchov  1125:                if (f->pstate != SOCK_RUN && f->pstate != SOCK_START &&
                   1126:                    f->pstate != SOCK_READY) {
1.37      ratchov  1127: #ifdef DEBUG
                   1128:                        if (debug_level >= 1) {
                   1129:                                sock_dbg(f);
                   1130:                                dbg_puts(": DATA, bad state\n");
                   1131:                        }
                   1132: #endif
1.8       ratchov  1133:                        aproc_del(f->pipe.file.rproc);
                   1134:                        return 0;
                   1135:                }
                   1136:                if (!(f->mode & AMSG_PLAY)) {
1.37      ratchov  1137: #ifdef DEBUG
                   1138:                        if (debug_level >= 1) {
                   1139:                                sock_dbg(f);
                   1140:                                dbg_puts(": DATA not allowed in record-only mode\n");
                   1141:                        }
                   1142: #endif
1.1       ratchov  1143:                        aproc_del(f->pipe.file.rproc);
                   1144:                        return 0;
                   1145:                }
1.45      ratchov  1146:                obuf = LIST_FIRST(&f->pipe.file.rproc->outs);
1.42      ratchov  1147:                if (f->pstate == SOCK_START && !ABUF_WOK(obuf)) {
1.37      ratchov  1148: #ifdef DEBUG
                   1149:                        if (debug_level >= 1) {
                   1150:                                sock_dbg(f);
                   1151:                                dbg_puts(": DATA client violates flow control\n");
                   1152:                        }
                   1153: #endif
1.34      ratchov  1154:                        aproc_del(f->pipe.file.rproc);
                   1155:                        return 0;
                   1156:                }
1.42      ratchov  1157:                if (m->u.data.size % obuf->bpf != 0) {
                   1158: #ifdef DEBUG
                   1159:                        if (debug_level >= 1) {
                   1160:                                sock_dbg(f);
                   1161:                                dbg_puts(": unaligned data chunk\n");
                   1162:                        }
                   1163: #endif
                   1164:                        aproc_del(f->pipe.file.rproc);
                   1165:                        return 0;
                   1166:                }
1.1       ratchov  1167:                f->rstate = SOCK_RDATA;
1.42      ratchov  1168:                f->rtodo = m->u.data.size / obuf->bpf;
                   1169: #ifdef DEBUG
                   1170:                if (f->rtodo > f->rmax && debug_level >= 2) {
                   1171:                        sock_dbg(f);
                   1172:                        dbg_puts(": received past current position, rtodo = ");
                   1173:                        dbg_putu(f->rtodo);
                   1174:                        dbg_puts(", rmax = ");
                   1175:                        dbg_putu(f->rmax);
                   1176:                        dbg_puts("\n");
                   1177:                        aproc_del(f->pipe.file.rproc);
                   1178:                        return 0;
                   1179:                }
                   1180: #endif
                   1181:                f->rmax -= f->rtodo;
1.1       ratchov  1182:                if (f->rtodo == 0) {
1.37      ratchov  1183: #ifdef DEBUG
                   1184:                        if (debug_level >= 1) {
                   1185:                                sock_dbg(f);
                   1186:                                dbg_puts(": zero-length data chunk\n");
                   1187:                        }
                   1188: #endif
1.1       ratchov  1189:                        aproc_del(f->pipe.file.rproc);
                   1190:                        return 0;
                   1191:                }
                   1192:                break;
                   1193:        case AMSG_START:
1.37      ratchov  1194: #ifdef DEBUG
                   1195:                if (debug_level >= 3) {
                   1196:                        sock_dbg(f);
                   1197:                        dbg_puts(": START message\n");
                   1198:                }
                   1199: #endif
1.1       ratchov  1200:                if (f->pstate != SOCK_INIT) {
1.37      ratchov  1201: #ifdef DEBUG
                   1202:                        if (debug_level >= 1) {
                   1203:                                sock_dbg(f);
                   1204:                                dbg_puts(": START, bad state\n");
                   1205:                        }
                   1206: #endif
1.1       ratchov  1207:                        aproc_del(f->pipe.file.rproc);
                   1208:                        return 0;
                   1209:                }
                   1210:                sock_allocbuf(f);
                   1211:                f->rstate = SOCK_RMSG;
                   1212:                f->rtodo = sizeof(struct amsg);
                   1213:                break;
                   1214:        case AMSG_STOP:
1.37      ratchov  1215: #ifdef DEBUG
                   1216:                if (debug_level >= 3) {
                   1217:                        sock_dbg(f);
                   1218:                        dbg_puts(": STOP message\n");
                   1219:                }
                   1220: #endif
1.42      ratchov  1221:                if (f->pstate != SOCK_RUN &&
                   1222:                    f->pstate != SOCK_START && f->pstate != SOCK_READY) {
1.37      ratchov  1223: #ifdef DEBUG
                   1224:                        if (debug_level >= 1) {
                   1225:                                sock_dbg(f);
                   1226:                                dbg_puts(": STOP, bad state\n");
                   1227:                        }
                   1228: #endif
1.1       ratchov  1229:                        aproc_del(f->pipe.file.rproc);
                   1230:                        return 0;
1.42      ratchov  1231:                /*
                   1232:                 * XXX: device could have desappeared at this point,
                   1233:                 * see how this is fixed in wav.c
                   1234:                 */
1.1       ratchov  1235:                }
1.42      ratchov  1236:                if ((f->pstate == SOCK_START || f->pstate == SOCK_READY) &&
1.35      ratchov  1237:                    ctl_slotstart(dev_midi, f->slot))
1.1       ratchov  1238:                        (void)sock_attach(f, 1);
1.42      ratchov  1239:                if (f->wstate != SOCK_WDATA || f->wtodo == 0)
                   1240:                        sock_freebuf(f);
                   1241:                else
                   1242:                        f->pstate = SOCK_STOP;
1.1       ratchov  1243:                AMSG_INIT(m);
                   1244:                m->cmd = AMSG_ACK;
                   1245:                f->rstate = SOCK_RRET;
                   1246:                f->rtodo = sizeof(struct amsg);
                   1247:                break;
                   1248:        case AMSG_SETPAR:
1.37      ratchov  1249: #ifdef DEBUG
                   1250:                if (debug_level >= 3) {
                   1251:                        sock_dbg(f);
                   1252:                        dbg_puts(": SETPAR message\n");
                   1253:                }
                   1254: #endif
1.1       ratchov  1255:                if (f->pstate != SOCK_INIT) {
1.37      ratchov  1256: #ifdef DEBUG
                   1257:                        if (debug_level >= 1) {
                   1258:                                sock_dbg(f);
                   1259:                                dbg_puts(": SETPAR, bad state\n");
                   1260:                        }
                   1261: #endif
1.1       ratchov  1262:                        aproc_del(f->pipe.file.rproc);
                   1263:                        return 0;
                   1264:                }
                   1265:                if (!sock_setpar(f)) {
                   1266:                        aproc_del(f->pipe.file.rproc);
                   1267:                        return 0;
                   1268:                }
                   1269:                f->rtodo = sizeof(struct amsg);
                   1270:                f->rstate = SOCK_RMSG;
                   1271:                break;
                   1272:        case AMSG_GETPAR:
1.37      ratchov  1273: #ifdef DEBUG
                   1274:                if (debug_level >= 3) {
                   1275:                        sock_dbg(f);
                   1276:                        dbg_puts(": GETPAR message\n");
                   1277:                }
                   1278: #endif
1.1       ratchov  1279:                if (f->pstate != SOCK_INIT) {
1.37      ratchov  1280: #ifdef DEBUG
                   1281:                        if (debug_level >= 1) {
                   1282:                                sock_dbg(f);
                   1283:                                dbg_puts(": GETPAR, bad state\n");
                   1284:                        }
                   1285: #endif
1.1       ratchov  1286:                        aproc_del(f->pipe.file.rproc);
                   1287:                        return 0;
                   1288:                }
                   1289:                AMSG_INIT(m);
                   1290:                m->cmd = AMSG_GETPAR;
1.18      ratchov  1291:                m->u.par.legacy_mode = f->mode;
1.42      ratchov  1292:                if (f->mode & AMSG_PLAY) {
                   1293:                        m->u.par.bits = f->rpar.bits;
                   1294:                        m->u.par.bps = f->rpar.bps;
                   1295:                        m->u.par.sig = f->rpar.sig;
                   1296:                        m->u.par.le = f->rpar.le;
                   1297:                        m->u.par.msb = f->rpar.msb;
                   1298:                        m->u.par.rate = f->rpar.rate;
                   1299:                        m->u.par.pchan = f->rpar.cmax - f->rpar.cmin + 1;
                   1300:                }
                   1301:                if (f->mode & AMSG_RECMASK) {
                   1302:                        m->u.par.bits = f->wpar.bits;
                   1303:                        m->u.par.bps = f->wpar.bps;
                   1304:                        m->u.par.sig = f->wpar.sig;
                   1305:                        m->u.par.le = f->wpar.le;
                   1306:                        m->u.par.msb = f->wpar.msb;
                   1307:                        m->u.par.rate = f->wpar.rate;
                   1308:                        m->u.par.rchan = f->wpar.cmax - f->wpar.cmin + 1;
                   1309:                }
1.10      ratchov  1310:                m->u.par.appbufsz = f->bufsz;
1.12      ratchov  1311:                m->u.par.bufsz =
1.10      ratchov  1312:                    f->bufsz + (dev_bufsz / dev_round) * f->round;
1.1       ratchov  1313:                m->u.par.round = f->round;
                   1314:                f->rstate = SOCK_RRET;
                   1315:                f->rtodo = sizeof(struct amsg);
                   1316:                break;
                   1317:        case AMSG_GETCAP:
1.37      ratchov  1318: #ifdef DEBUG
                   1319:                if (debug_level >= 3) {
                   1320:                        sock_dbg(f);
                   1321:                        dbg_puts(": GETCAP message\n");
                   1322:                }
                   1323: #endif
1.1       ratchov  1324:                if (f->pstate != SOCK_INIT) {
1.37      ratchov  1325: #ifdef DEBUG
                   1326:                        if (debug_level >= 1) {
                   1327:                                sock_dbg(f);
                   1328:                                dbg_puts(": GETCAP, bad state\n");
                   1329:                        }
                   1330: #endif
1.1       ratchov  1331:                        aproc_del(f->pipe.file.rproc);
                   1332:                        return 0;
                   1333:                }
                   1334:                AMSG_INIT(m);
                   1335:                m->cmd = AMSG_GETCAP;
                   1336:                m->u.cap.rate = dev_rate;
1.42      ratchov  1337:                m->u.cap.pchan = (f->opt->mode & MODE_PLAY) ?
1.19      ratchov  1338:                    (f->opt->rpar.cmax - f->opt->rpar.cmin + 1) : 0;
1.42      ratchov  1339:                m->u.cap.rchan = (f->opt->mode & (MODE_PLAY | MODE_REC)) ?
1.19      ratchov  1340:                    (f->opt->wpar.cmax - f->opt->wpar.cmin + 1) : 0;
1.1       ratchov  1341:                m->u.cap.bits = sizeof(short) * 8;
                   1342:                m->u.cap.bps = sizeof(short);
                   1343:                f->rstate = SOCK_RRET;
                   1344:                f->rtodo = sizeof(struct amsg);
1.3       ratchov  1345:                break;
                   1346:        case AMSG_SETVOL:
1.37      ratchov  1347: #ifdef DEBUG
                   1348:                if (debug_level >= 3) {
                   1349:                        sock_dbg(f);
                   1350:                        dbg_puts(": SETVOL message\n");
                   1351:                }
                   1352: #endif
1.42      ratchov  1353:                if (f->pstate != SOCK_RUN && f->pstate != SOCK_START &&
                   1354:                    f->pstate != SOCK_INIT && f->pstate != SOCK_READY) {
1.37      ratchov  1355: #ifdef DEBUG
                   1356:                        if (debug_level >= 1) {
                   1357:                                sock_dbg(f);
                   1358:                                dbg_puts(": SETVOL, bad state\n");
                   1359:                        }
                   1360: #endif
1.3       ratchov  1361:                        aproc_del(f->pipe.file.rproc);
                   1362:                        return 0;
                   1363:                }
                   1364:                if (m->u.vol.ctl > MIDI_MAXCTL) {
1.37      ratchov  1365: #ifdef DEBUG
                   1366:                        if (debug_level >= 1) {
                   1367:                                sock_dbg(f);
                   1368:                                dbg_puts(": SETVOL, volume out of range\n");
                   1369:                        }
                   1370: #endif
1.3       ratchov  1371:                        aproc_del(f->pipe.file.rproc);
                   1372:                        return 0;
                   1373:                }
1.25      ratchov  1374:                sock_setvol(f, m->u.vol.ctl);
1.34      ratchov  1375:                if (f->slot >= 0)
1.24      ratchov  1376:                        ctl_slotvol(dev_midi, f->slot, m->u.vol.ctl);
1.3       ratchov  1377:                f->rtodo = sizeof(struct amsg);
                   1378:                f->rstate = SOCK_RMSG;
1.17      ratchov  1379:                break;
                   1380:        case AMSG_HELLO:
1.37      ratchov  1381: #ifdef DEBUG
                   1382:                if (debug_level >= 3) {
                   1383:                        sock_dbg(f);
                   1384:                        dbg_puts(": HELLO message\n");
                   1385:                }
                   1386: #endif
1.18      ratchov  1387:                if (f->pstate != SOCK_HELLO) {
1.37      ratchov  1388: #ifdef DEBUG
                   1389:                        if (debug_level >= 1) {
                   1390:                                sock_dbg(f);
                   1391:                                dbg_puts(": HELLO, bad state\n");
                   1392:                        }
                   1393: #endif
1.17      ratchov  1394:                        aproc_del(f->pipe.file.rproc);
                   1395:                        return 0;
                   1396:                }
                   1397:                if (!sock_hello(f)) {
                   1398:                        aproc_del(f->pipe.file.rproc);
                   1399:                        return 0;
                   1400:                }
                   1401:                AMSG_INIT(m);
                   1402:                m->cmd = AMSG_ACK;
                   1403:                f->rstate = SOCK_RRET;
                   1404:                f->rtodo = sizeof(struct amsg);
1.1       ratchov  1405:                break;
1.28      ratchov  1406:        case AMSG_BYE:
1.37      ratchov  1407: #ifdef DEBUG
                   1408:                if (debug_level >= 3) {
                   1409:                        sock_dbg(f);
                   1410:                        dbg_puts(": BYE message\n");
                   1411:                }
                   1412: #endif
1.29      ratchov  1413:                if (f->pstate != SOCK_INIT) {
1.37      ratchov  1414: #ifdef DEBUG
                   1415:                        if (debug_level >= 1) {
                   1416:                                sock_dbg(f);
                   1417:                                dbg_puts(": BYE, bad state\n");
                   1418:                        }
                   1419: #endif
1.29      ratchov  1420:                }
1.28      ratchov  1421:                aproc_del(f->pipe.file.rproc);
                   1422:                return 0;
1.1       ratchov  1423:        default:
1.37      ratchov  1424: #ifdef DEBUG
                   1425:                if (debug_level >= 1) {
                   1426:                        sock_dbg(f);
                   1427:                        dbg_puts(": unknown command in message\n");
                   1428:                }
                   1429: #endif
1.1       ratchov  1430:                aproc_del(f->pipe.file.rproc);
                   1431:                return 0;
                   1432:        }
                   1433:        if (f->rstate == SOCK_RRET) {
                   1434:                if (f->wstate != SOCK_WIDLE ||
                   1435:                    !sock_wmsg(f, &f->rmsg, &f->rtodo))
                   1436:                        return 0;
1.37      ratchov  1437: #ifdef DEBUG
                   1438:                if (debug_level >= 3) {
                   1439:                        sock_dbg(f);
                   1440:                        dbg_puts(": RRET done\n");
                   1441:                }
                   1442: #endif
1.19      ratchov  1443:                if (f->pstate == SOCK_MIDI && (f->mode & AMSG_MIDIOUT)) {
                   1444:                        f->rstate = SOCK_RDATA;
                   1445:                        f->rtodo = 0;
                   1446:                } else {
                   1447:                        f->rstate = SOCK_RMSG;
                   1448:                        f->rtodo = sizeof(struct amsg);
                   1449:                }
1.1       ratchov  1450:        }
                   1451:        return 1;
                   1452: }
                   1453:
                   1454: /*
1.20      ratchov  1455:  * Create a new data/pos message.
1.1       ratchov  1456:  */
                   1457: int
                   1458: sock_buildmsg(struct sock *f)
                   1459: {
                   1460:        struct aproc *p;
                   1461:        struct abuf *ibuf;
1.42      ratchov  1462:        unsigned size, max;
1.12      ratchov  1463:
1.19      ratchov  1464:        if (f->pstate == SOCK_MIDI) {
1.37      ratchov  1465: #ifdef DEBUG
                   1466:                if (debug_level >= 3) {
                   1467:                        sock_dbg(f);
                   1468:                        dbg_puts(": switching to MIDI mode\n");
                   1469:                }
                   1470: #endif
1.19      ratchov  1471:                f->wstate = SOCK_WDATA;
                   1472:                f->wtodo = 0;
                   1473:                return 1;
                   1474:        }
                   1475:
1.1       ratchov  1476:        /*
1.20      ratchov  1477:         * If pos changed, build a MOVE message.
1.1       ratchov  1478:         */
1.42      ratchov  1479:        if ((f->tickpending && f->delta > 0) || f->startpending) {
1.37      ratchov  1480: #ifdef DEBUG
                   1481:                if (debug_level >= 4) {
                   1482:                        sock_dbg(f);
                   1483:                        dbg_puts(": building POS message, delta = ");
                   1484:                        dbg_puti(f->delta);
                   1485:                        dbg_puts("\n");
                   1486:                }
                   1487: #endif
1.42      ratchov  1488:                f->wmax += f->delta;
                   1489:                if (f->delta > 0)
                   1490:                        f->rmax += f->delta;
1.1       ratchov  1491:                AMSG_INIT(&f->wmsg);
                   1492:                f->wmsg.cmd = AMSG_MOVE;
1.14      ratchov  1493:                f->wmsg.u.ts.delta = f->delta;
1.1       ratchov  1494:                f->wtodo = sizeof(struct amsg);
                   1495:                f->wstate = SOCK_WMSG;
1.14      ratchov  1496:                f->delta = 0;
                   1497:                f->tickpending = 0;
1.42      ratchov  1498:                f->startpending = 0;
1.25      ratchov  1499:                return 1;
                   1500:        }
                   1501:
                   1502:        /*
                   1503:         * if volume changed build a SETVOL message
                   1504:         */
1.27      ratchov  1505:        if (f->pstate >= SOCK_START && f->vol != f->lastvol) {
1.37      ratchov  1506: #ifdef DEBUG
                   1507:                if (debug_level >= 4) {
                   1508:                        sock_dbg(f);
                   1509:                        dbg_puts(": building SETVOL message, vol = ");
                   1510:                        dbg_puti(f->vol);
                   1511:                        dbg_puts("\n");
                   1512:                }
                   1513: #endif
1.25      ratchov  1514:                AMSG_INIT(&f->wmsg);
                   1515:                f->wmsg.cmd = AMSG_SETVOL;
                   1516:                f->wmsg.u.vol.ctl = f->vol;
                   1517:                f->wtodo = sizeof(struct amsg);
                   1518:                f->wstate = SOCK_WMSG;
                   1519:                f->lastvol = f->vol;
1.1       ratchov  1520:                return 1;
                   1521:        }
                   1522:
                   1523:        /*
1.20      ratchov  1524:         * If data available, build a DATA message.
1.1       ratchov  1525:         */
                   1526:        p = f->pipe.file.wproc;
1.45      ratchov  1527:        ibuf = LIST_FIRST(&p->ins);
1.1       ratchov  1528:        if (ibuf && ABUF_ROK(ibuf)) {
1.42      ratchov  1529: #ifdef DEBUG
                   1530:                if (ibuf->used > f->wmax && debug_level >= 3) {
                   1531:                        sock_dbg(f);
1.46      ratchov  1532:                        dbg_puts(": attempt to send past current position: used = ");
                   1533:                        dbg_putu(ibuf->used);
                   1534:                        dbg_puts(" wmax = ");
                   1535:                        dbg_putu(f->wmax);
                   1536:                        dbg_puts("\n");
1.42      ratchov  1537:                }
                   1538: #endif
                   1539:                max = AMSG_DATAMAX / ibuf->bpf;
                   1540:                size = ibuf->used;
1.39      ratchov  1541:                if (size > f->walign)
                   1542:                        size = f->walign;
1.42      ratchov  1543:                if (size > f->wmax)
                   1544:                        size = f->wmax;
                   1545:                if (size > max)
                   1546:                        size = max;
                   1547:                if (size == 0)
                   1548:                        return 0;
1.39      ratchov  1549:                f->walign -= size;
1.42      ratchov  1550:                f->wmax -= size;
1.39      ratchov  1551:                if (f->walign == 0)
1.42      ratchov  1552:                        f->walign = f->round;
1.1       ratchov  1553:                AMSG_INIT(&f->wmsg);
                   1554:                f->wmsg.cmd = AMSG_DATA;
1.42      ratchov  1555:                f->wmsg.u.data.size = size * ibuf->bpf;
1.1       ratchov  1556:                f->wtodo = sizeof(struct amsg);
                   1557:                f->wstate = SOCK_WMSG;
                   1558:                return 1;
                   1559:        }
1.37      ratchov  1560: #ifdef DEBUG
                   1561:        if (debug_level >= 4) {
                   1562:                sock_dbg(f);
                   1563:                dbg_puts(": no messages to build anymore, idling...\n");
                   1564:        }
                   1565: #endif
1.1       ratchov  1566:        f->wstate = SOCK_WIDLE;
                   1567:        return 0;
                   1568: }
                   1569:
                   1570: /*
1.20      ratchov  1571:  * Read from the socket file descriptor, fill input buffer and update
1.1       ratchov  1572:  * the state. Return 1 if at least one message or 1 data byte was
                   1573:  * processed, 0 if something blocked.
                   1574:  */
                   1575: int
                   1576: sock_read(struct sock *f)
                   1577: {
1.37      ratchov  1578: #ifdef DEBUG
                   1579:        if (debug_level >= 4) {
                   1580:                sock_dbg(f);
1.39      ratchov  1581:                dbg_puts(": reading ");
1.37      ratchov  1582:                dbg_putu(f->rtodo);
1.39      ratchov  1583:                dbg_puts(" todo\n");
1.37      ratchov  1584:        }
                   1585: #endif
1.1       ratchov  1586:        switch (f->rstate) {
                   1587:        case SOCK_RMSG:
                   1588:                if (!sock_rmsg(f))
                   1589:                        return 0;
                   1590:                if (!sock_execmsg(f))
                   1591:                        return 0;
                   1592:                break;
                   1593:        case SOCK_RDATA:
                   1594:                if (!sock_rdata(f))
                   1595:                        return 0;
1.19      ratchov  1596:                if (f->pstate != SOCK_MIDI && f->rtodo == 0) {
1.1       ratchov  1597:                        f->rstate = SOCK_RMSG;
                   1598:                        f->rtodo = sizeof(struct amsg);
                   1599:                }
1.35      ratchov  1600:                /*
1.42      ratchov  1601:                 * XXX: sock_attach() may not start if there's not enough
                   1602:                 *      samples queues, if so ctl_slotstart() will trigger
                   1603:                 *      other streams, but this one won't start.
1.35      ratchov  1604:                 */
1.42      ratchov  1605:                if (f->pstate == SOCK_READY && ctl_slotstart(dev_midi, f->slot))
1.1       ratchov  1606:                        (void)sock_attach(f, 0);
                   1607:                break;
                   1608:        case SOCK_RRET:
1.37      ratchov  1609: #ifdef DEBUG
                   1610:                if (debug_level >= 4) {
                   1611:                        sock_dbg(f);
                   1612:                        dbg_puts(": blocked by pending RRET message\n");
                   1613:                }
                   1614: #endif
1.1       ratchov  1615:                return 0;
                   1616:        }
                   1617:        return 1;
                   1618: }
                   1619:
                   1620: /*
1.20      ratchov  1621:  * Process messages to return.
1.1       ratchov  1622:  */
                   1623: int
                   1624: sock_return(struct sock *f)
                   1625: {
                   1626:        struct aproc *rp;
                   1627:
                   1628:        while (f->rstate == SOCK_RRET) {
                   1629:                if (!sock_wmsg(f, &f->rmsg, &f->rtodo))
                   1630:                        return 0;
1.37      ratchov  1631: #ifdef DEBUG
                   1632:                if (debug_level >= 4) {
                   1633:                        sock_dbg(f);
                   1634:                        dbg_puts(": sent RRET message\n");
                   1635:                }
                   1636: #endif
1.19      ratchov  1637:                if (f->pstate == SOCK_MIDI && (f->mode & AMSG_MIDIOUT)) {
                   1638:                        f->rstate = SOCK_RDATA;
                   1639:                        f->rtodo = 0;
                   1640:                } else {
                   1641:                        f->rstate = SOCK_RMSG;
                   1642:                        f->rtodo = sizeof(struct amsg);
                   1643:                }
                   1644:                if (f->pipe.file.state & FILE_RINUSE)
                   1645:                        break;
                   1646:                f->pipe.file.state |= FILE_RINUSE;
1.1       ratchov  1647:                for (;;) {
                   1648:                        /*
                   1649:                         * in() may trigger rsock_done and destroy the
1.20      ratchov  1650:                         * wsock.
1.1       ratchov  1651:                         */
                   1652:                        rp = f->pipe.file.rproc;
                   1653:                        if (!rp || !rp->ops->in(rp, NULL))
                   1654:                                break;
                   1655:                }
1.19      ratchov  1656:                f->pipe.file.state &= ~FILE_RINUSE;
1.1       ratchov  1657:                if (f->pipe.file.wproc == NULL)
                   1658:                        return 0;
                   1659:        }
                   1660:        return 1;
                   1661: }
                   1662:
                   1663: /*
1.20      ratchov  1664:  * Write messages and data on the socket file descriptor. Return 1 if
1.1       ratchov  1665:  * at least one message or one data byte was processed, 0 if something
                   1666:  * blocked.
                   1667:  */
                   1668: int
                   1669: sock_write(struct sock *f)
                   1670: {
1.37      ratchov  1671: #ifdef DEBUG
                   1672:        if (debug_level >= 4) {
                   1673:                sock_dbg(f);
1.39      ratchov  1674:                dbg_puts(": writing ");
1.37      ratchov  1675:                dbg_putu(f->wtodo);
1.39      ratchov  1676:                dbg_puts(" todo\n");
1.37      ratchov  1677:        }
                   1678: #endif
1.1       ratchov  1679:        switch (f->wstate) {
                   1680:        case SOCK_WMSG:
                   1681:                if (!sock_wmsg(f, &f->wmsg, &f->wtodo))
                   1682:                        return 0;
                   1683:                if (f->wmsg.cmd != AMSG_DATA) {
                   1684:                        f->wstate = SOCK_WIDLE;
                   1685:                        f->wtodo = 0xdeadbeef;
                   1686:                        break;
                   1687:                }
1.42      ratchov  1688:                /*
                   1689:                 * XXX: why not set f->wtodo in sock_wmsg() ?
                   1690:                 */
1.1       ratchov  1691:                f->wstate = SOCK_WDATA;
1.42      ratchov  1692:                f->wtodo = f->wmsg.u.data.size /
1.45      ratchov  1693:                    LIST_FIRST(&f->pipe.file.wproc->ins)->bpf;
1.1       ratchov  1694:                /* PASSTHROUGH */
                   1695:        case SOCK_WDATA:
                   1696:                if (!sock_wdata(f))
                   1697:                        return 0;
1.19      ratchov  1698:                if (f->pstate == SOCK_MIDI || f->wtodo > 0)
1.1       ratchov  1699:                        break;
                   1700:                f->wstate = SOCK_WIDLE;
                   1701:                f->wtodo = 0xdeadbeef;
1.42      ratchov  1702:                if (f->pstate == SOCK_STOP)
                   1703:                        sock_freebuf(f);
1.1       ratchov  1704:                /* PASSTHROUGH */
                   1705:        case SOCK_WIDLE:
                   1706:                if (!sock_return(f))
                   1707:                        return 0;
                   1708:                if (!sock_buildmsg(f))
                   1709:                        return 0;
                   1710:                break;
1.37      ratchov  1711: #ifdef DEBUG
                   1712:        default:
                   1713:                sock_dbg(f);
                   1714:                dbg_puts(": bad writing end state\n");
                   1715:                dbg_panic();
                   1716: #endif
1.1       ratchov  1717:        }
                   1718:        return 1;
                   1719: }