[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.44

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