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

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