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

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