/* * execute the next message, return 0 if blocked */ static int mio_aucat_runmsg(struct mio_aucat_hdl *hdl) { int delta; if (!_aucat_rmsg(&hdl->aucat, &hdl->mio.eof)) return 0; switch (ntohl(hdl->aucat.rmsg.cmd)) { case AMSG_DATA: return 1; case AMSG_FLOWCTL: delta = ntohl(hdl->aucat.rmsg.u.ts.delta); hdl->aucat.maxwrite += delta; DPRINTF("aucat: flowctl = %d, maxwrite = %d\n", delta, hdl->aucat.maxwrite); break; default: DPRINTF("mio_aucat_runmsg: unhandled message %u\n", hdl->aucat.rmsg.cmd); hdl->mio.eof = 1; return 0; } hdl->aucat.rstate = RSTATE_MSG; hdl->aucat.rtodo = sizeof(struct amsg); return 1; }
int _aucat_open(struct aucat *hdl, const char *str, unsigned int mode, unsigned int type) { extern char *__progname; int eof; char host[NI_MAXHOST], opt[AMSG_OPTMAX]; const char *p = str; unsigned int unit, devnum; if (*p == '@') { p = parsestr(++p, host, NI_MAXHOST); if (p == NULL) return 0; } else *host = '\0'; if (*p == ',') { p = parsedev(++p, &unit); if (p == NULL) return 0; } else unit = 0; if (*p != '/' && *p != ':') { DPRINTF("%s: '/' expected\n", str); return 0; } p = parsedev(++p, &devnum); if (p == NULL) return 0; if (*p == '.') { p = parsestr(++p, opt, AMSG_OPTMAX); if (p == NULL) return 0; } else strlcpy(opt, "default", AMSG_OPTMAX); if (*p != '\0') { DPRINTF("%s: junk at end of dev name\n", p); return 0; } devnum += type * 16; /* XXX */ DPRINTFN(2, "_aucat_open: host=%s unit=%u devnum=%u opt=%s\n", host, unit, devnum, opt); if (host[0] != '\0') { if (!aucat_connect_tcp(hdl, host, unit)) return 0; } else { if (!aucat_connect_un(hdl, unit)) return 0; } if (fcntl(hdl->fd, F_SETFD, FD_CLOEXEC) < 0) { DPERROR("FD_CLOEXEC"); goto bad_connect; } hdl->rstate = RSTATE_MSG; hdl->rtodo = sizeof(struct amsg); hdl->wstate = WSTATE_IDLE; hdl->wtodo = 0xdeadbeef; hdl->maxwrite = 0; /* * say hello to server */ AMSG_INIT(&hdl->wmsg); hdl->wmsg.cmd = htonl(AMSG_AUTH); if (!aucat_mkcookie(hdl->wmsg.u.auth.cookie)) goto bad_connect; hdl->wtodo = sizeof(struct amsg); if (!_aucat_wmsg(hdl, &eof)) goto bad_connect; AMSG_INIT(&hdl->wmsg); hdl->wmsg.cmd = htonl(AMSG_HELLO); hdl->wmsg.u.hello.version = AMSG_VERSION; hdl->wmsg.u.hello.mode = htons(mode); hdl->wmsg.u.hello.devnum = devnum; strlcpy(hdl->wmsg.u.hello.who, __progname, sizeof(hdl->wmsg.u.hello.who)); strlcpy(hdl->wmsg.u.hello.opt, opt, sizeof(hdl->wmsg.u.hello.opt)); hdl->wtodo = sizeof(struct amsg); if (!_aucat_wmsg(hdl, &eof)) goto bad_connect; hdl->rtodo = sizeof(struct amsg); if (!_aucat_rmsg(hdl, &eof)) { DPRINTF("aucat_init: mode refused\n"); goto bad_connect; } if (ntohl(hdl->rmsg.cmd) != AMSG_ACK) { DPRINTF("aucat_init: protocol err\n"); goto bad_connect; } return 1; bad_connect: while (close(hdl->fd) < 0 && errno == EINTR) ; /* retry */ return 0; }