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

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