diff options
-rw-r--r-- | sys/src/libc/9sys/dial.c | 356 | ||||
-rw-r--r-- | sys/src/libthread/dial.c | 221 | ||||
-rw-r--r-- | sys/src/libthread/main.c | 4 | ||||
-rw-r--r-- | sys/src/libthread/mkfile | 1 |
4 files changed, 41 insertions, 541 deletions
diff --git a/sys/src/libc/9sys/dial.c b/sys/src/libc/9sys/dial.c index 74fc6e6ae..41a1e329e 100644 --- a/sys/src/libc/9sys/dial.c +++ b/sys/src/libc/9sys/dial.c @@ -1,24 +1,16 @@ -/* - * dial - connect to a service (parallel version) - */ #include <u.h> #include <libc.h> -typedef struct Conn Conn; -typedef struct Dest Dest; typedef struct DS DS; +static int call(char*, char*, DS*); +static int csdial(DS*); +static void _dial_string_parse(char*, DS*); + enum { Maxstring = 128, Maxpath = 256, - - Maxcsreply = 64*80, /* this is probably overly generous */ - /* - * this should be a plausible slight overestimate for non-interactive - * use even if it's ridiculously long for interactive use. - */ - Maxconnms = 20*60*1000, /* 20 minutes */ }; struct DS { @@ -34,42 +26,12 @@ struct DS { int *cfdp; }; -/* - * malloc these; they need to be writable by this proc & all children. - * the stack is private to each proc, and static allocation in the data - * segment would not permit concurrent dials within a multi-process program. - */ -struct Conn { - int pid; - int dead; - - int dfd; - int cfd; - char dir[NETPATHLEN]; - char err[ERRMAX]; -}; -struct Dest { - Conn *conn; /* allocated array */ - Conn *connend; - int nkid; - - QLock winlck; - int winner; /* index into conn[] */ - - char *nextaddr; - char addrlist[Maxcsreply]; -}; - -static int call(char*, char*, DS*, Dest*, Conn*); -static int csdial(DS*); -static void _dial_string_parse(char*, DS*); - /* * the dialstring is of the form '[/net/]proto!dest' */ -static int -dialimpl(char *dest, char *local, char *dir, int *cfdp) +int +dial(char *dest, char *local, char *dir, int *cfdp) { DS ds; int rv; @@ -107,224 +69,11 @@ dialimpl(char *dest, char *local, char *dir, int *cfdp) return rv; } -/* - * the thread library can't cope with rfork(RFMEM|RFPROC), - * so it must override this with a private version of dial. - */ -int (*_dial)(char *, char *, char *, int *) = dialimpl; - -int -dial(char *dest, char *local, char *dir, int *cfdp) -{ - return (*_dial)(dest, local, dir, cfdp); -} - -static int -connsalloc(Dest *dp, int addrs) -{ - free(dp->conn); - dp->connend = nil; - assert(addrs > 0); - - dp->conn = mallocz(addrs * sizeof *dp->conn, 1); - if(dp->conn == nil) - return -1; - dp->connend = dp->conn + addrs; - return 0; -} - -static void -freedest(Dest *dp) -{ - if (dp != nil) { - free(dp->conn); - free(dp); - } -} - -static void -closeopenfd(int *fdp) -{ - if (*fdp > 0) { - close(*fdp); - *fdp = -1; - } -} - -static void -notedeath(Dest *dp, char *exitsts) -{ - int i, n, pid; - char *fields[5]; /* pid + 3 times + error */ - Conn *conn; - - for (i = 0; i < nelem(fields); i++) - fields[i] = ""; - n = tokenize(exitsts, fields, nelem(fields)); - if (n < 4) - return; - pid = atoi(fields[0]); - if (pid <= 0) - return; - for (conn = dp->conn; conn < dp->connend; conn++) - if (conn->pid == pid && !conn->dead) { /* it's one we know? */ - if (conn - dp->conn != dp->winner) { - closeopenfd(&conn->dfd); - closeopenfd(&conn->cfd); - } - strncpy(conn->err, fields[4], sizeof conn->err); - conn->dead = 1; - return; - } - /* not a proc that we forked */ -} - -static int -outstandingprocs(Dest *dp) -{ - Conn *conn; - - for (conn = dp->conn; conn < dp->connend; conn++) - if (!conn->dead) - return 1; - return 0; -} - -static int -reap(Dest *dp) -{ - char exitsts[2*ERRMAX]; - - if (outstandingprocs(dp) && await(exitsts, sizeof exitsts) >= 0) { - notedeath(dp, exitsts); - return 0; - } - return -1; -} - -static int -fillinds(DS *ds, Dest *dp) -{ - Conn *conn; - - if (dp->winner < 0) - return -1; - conn = &dp->conn[dp->winner]; - if (ds->cfdp) - *ds->cfdp = conn->cfd; - if (ds->dir) - strncpy(ds->dir, conn->dir, NETPATHLEN); - return conn->dfd; -} - -static int -connectwait(Dest *dp, char *besterr) -{ - Conn *conn; - - /* wait for a winner or all attempts to time out */ - while (dp->winner < 0 && reap(dp) >= 0) - ; - - /* kill all of our still-live kids & reap them */ - for (conn = dp->conn; conn < dp->connend; conn++) - if (!conn->dead) - postnote(PNPROC, conn->pid, "die"); - while (reap(dp) >= 0) - ; - - /* rummage about and report some error string */ - for (conn = dp->conn; conn < dp->connend; conn++) - if (conn - dp->conn != dp->winner && conn->dead && - conn->err[0]) { - strncpy(besterr, conn->err, ERRMAX); - break; - } - return dp->winner; -} - -static int -parsecs(Dest *dp, char **clonep, char **destp) -{ - char *dest, *p; - - dest = strchr(dp->nextaddr, ' '); - if(dest == nil) - return -1; - *dest++ = '\0'; - p = strchr(dest, '\n'); - if(p == nil) - return -1; - *p++ = '\0'; - *clonep = dp->nextaddr; - *destp = dest; - dp->nextaddr = p; /* advance to next line */ - return 0; -} - -static void -pickuperr(char *besterr, char *err) -{ - err[0] = '\0'; - errstr(err, ERRMAX); - if(strstr(err, "does not exist") == 0) - strcpy(besterr, err); -} - -/* - * try all addresses in parallel and take the first one that answers; - * this helps when systems have ip v4 and v6 addresses but are - * only reachable from here on one (or some) of them. - */ -static int -dialmulti(DS *ds, Dest *dp) -{ - int rv, kid, kidme; - char *clone, *dest; - char err[ERRMAX], besterr[ERRMAX]; - - dp->winner = -1; - dp->nkid = 0; - while(dp->winner < 0 && *dp->nextaddr != '\0' && - parsecs(dp, &clone, &dest) >= 0) { - kidme = dp->nkid++; /* make private copy on stack */ - kid = rfork(RFPROC|RFMEM); /* spin off a call attempt */ - if (kid < 0) - --dp->nkid; - else if (kid == 0) { - alarm(Maxconnms); - *besterr = '\0'; - rv = call(clone, dest, ds, dp, &dp->conn[kidme]); - if(rv < 0) - pickuperr(besterr, err); - _exits(besterr); /* avoid atexit callbacks */ - } - } - rv = connectwait(dp, besterr); - if(rv < 0 && *besterr) - werrstr("%s", besterr); - else - werrstr("%s", err); - return rv; -} - static int csdial(DS *ds) { - int n, fd, rv, addrs, bleft; - char c; - char *addrp, *clone2, *dest; - char buf[Maxstring], clone[Maxpath], err[ERRMAX], besterr[ERRMAX]; - Dest *dp; - - dp = mallocz(sizeof *dp, 1); - if(dp == nil) - return -1; - dp->winner = -1; - if (connsalloc(dp, 1) < 0) { /* room for a single conn. */ - freedest(dp); - return -1; - } + int n, fd, rv; + char *p, buf[Maxstring], clone[Maxpath], err[ERRMAX], besterr[ERRMAX]; /* * open connection server @@ -334,10 +83,7 @@ csdial(DS *ds) if(fd < 0){ /* no connection server, don't translate */ snprint(clone, sizeof(clone), "%s/%s/clone", ds->netdir, ds->proto); - rv = call(clone, ds->rem, ds, dp, &dp->conn[0]); - fillinds(ds, dp); - freedest(dp); - return rv; + return call(clone, ds->rem, ds); } /* @@ -346,57 +92,41 @@ csdial(DS *ds) snprint(buf, sizeof(buf), "%s!%s", ds->proto, ds->rem); if(write(fd, buf, strlen(buf)) < 0){ close(fd); - freedest(dp); return -1; } /* - * read all addresses from the connection server. + * loop through each address from the connection server till + * we get one that works. */ + *besterr = 0; + rv = -1; seek(fd, 0, 0); - addrs = 0; - addrp = dp->nextaddr = dp->addrlist; - bleft = sizeof dp->addrlist - 2; /* 2 is room for \n\0 */ - while(bleft > 0 && (n = read(fd, addrp, bleft)) > 0) { - if (addrp[n-1] != '\n') - addrp[n++] = '\n'; - addrs++; - addrp += n; - bleft -= n; + while((n = read(fd, buf, sizeof(buf) - 1)) > 0){ + buf[n] = 0; + p = strchr(buf, ' '); + if(p == 0) + continue; + *p++ = 0; + rv = call(buf, p, ds); + if(rv >= 0) + break; + err[0] = '\0'; + errstr(err, sizeof err); + if(strstr(err, "does not exist") == 0) + strcpy(besterr, err); } - /* - * if we haven't read all of cs's output, assume the last line might - * have been truncated and ignore it. we really don't expect this - * to happen. - */ - if (addrs > 0 && bleft <= 0 && read(fd, &c, 1) == 1) - addrs--; close(fd); - *besterr = 0; - rv = -1; /* pessimistic default */ - if (addrs == 0) - werrstr("no address to dial"); - else if (addrs == 1) { - /* common case: dial one address without forking */ - if (parsecs(dp, &clone2, &dest) >= 0 && - (rv = call(clone2, dest, ds, dp, &dp->conn[0])) < 0) { - pickuperr(besterr, err); - werrstr("%s", besterr); - } - } else if (connsalloc(dp, addrs) >= 0) - rv = dialmulti(ds, dp); - - /* fill in results */ - if (rv >= 0 && dp->winner >= 0) - rv = fillinds(ds, dp); - - freedest(dp); + if(rv < 0 && *besterr) + werrstr("%s", besterr); + else + werrstr("%s", err); return rv; } static int -call(char *clone, char *dest, DS *ds, Dest *dp, Conn *conn) +call(char *clone, char *dest, DS *ds) { int fd, cfd, n; char cname[Maxpath], name[Maxpath], data[Maxpath], *p; @@ -412,15 +142,14 @@ call(char *clone, char *dest, DS *ds, Dest *dp, Conn *conn) p = clone; snprint(cname, sizeof cname, "%s/%s", ds->netdir, p); - conn->pid = getpid(); - conn->cfd = cfd = open(cname, ORDWR); + cfd = open(cname, ORDWR); if(cfd < 0) return -1; /* get directory name */ n = read(cfd, name, sizeof(name)-1); if(n < 0){ - closeopenfd(&conn->cfd); + close(cfd); return -1; } name[n] = 0; @@ -430,7 +159,7 @@ call(char *clone, char *dest, DS *ds, Dest *dp, Conn *conn) p = strrchr(cname, '/'); *p = 0; if(ds->dir) - snprint(conn->dir, NETPATHLEN, "%s/%s", cname, name); + snprint(ds->dir, NETPATHLEN, "%s/%s", cname, name); snprint(data, sizeof(data), "%s/%s/data", cname, name); /* connect */ @@ -439,23 +168,20 @@ call(char *clone, char *dest, DS *ds, Dest *dp, Conn *conn) else snprint(name, sizeof(name), "connect %s", dest); if(write(cfd, name, strlen(name)) < 0){ - closeopenfd(&conn->cfd); + close(cfd); return -1; } /* open data connection */ - conn->dfd = fd = open(data, ORDWR); + fd = open(data, ORDWR); if(fd < 0){ - closeopenfd(&conn->cfd); + close(cfd); return -1; } - if(ds->cfdp == nil) - closeopenfd(&conn->cfd); - - qlock(&dp->winlck); - if (dp->winner < 0 && conn < dp->connend) - dp->winner = conn - dp->conn; - qunlock(&dp->winlck); + if(ds->cfdp) + *ds->cfdp = cfd; + else + close(cfd); return fd; } diff --git a/sys/src/libthread/dial.c b/sys/src/libthread/dial.c deleted file mode 100644 index d2ca013da..000000000 --- a/sys/src/libthread/dial.c +++ /dev/null @@ -1,221 +0,0 @@ -/* - * old single-process version of dial that libthread can cope with - */ -#include <u.h> -#include <libc.h> - -typedef struct DS DS; - -static int call(char*, char*, DS*); -static int csdial(DS*); -static void _dial_string_parse(char*, DS*); - -enum -{ - Maxstring = 128, - Maxpath = 256, -}; - -struct DS { - /* dist string */ - char buf[Maxstring]; - char *netdir; - char *proto; - char *rem; - - /* other args */ - char *local; - char *dir; - int *cfdp; -}; - - -/* - * the dialstring is of the form '[/net/]proto!dest' - */ -int -_threaddial(char *dest, char *local, char *dir, int *cfdp) -{ - DS ds; - int rv; - char err[ERRMAX], alterr[ERRMAX]; - - ds.local = local; - ds.dir = dir; - ds.cfdp = cfdp; - - _dial_string_parse(dest, &ds); - if(ds.netdir) - return csdial(&ds); - - ds.netdir = "/net"; - rv = csdial(&ds); - if(rv >= 0) - return rv; - err[0] = '\0'; - errstr(err, sizeof err); - if(strstr(err, "refused") != 0){ - werrstr("%s", err); - return rv; - } - ds.netdir = "/net.alt"; - rv = csdial(&ds); - if(rv >= 0) - return rv; - - alterr[0] = 0; - errstr(alterr, sizeof alterr); - if(strstr(alterr, "translate") || strstr(alterr, "does not exist")) - werrstr("%s", err); - else - werrstr("%s", alterr); - return rv; -} - -static int -csdial(DS *ds) -{ - int n, fd, rv; - char *p, buf[Maxstring], clone[Maxpath], err[ERRMAX], besterr[ERRMAX]; - - /* - * open connection server - */ - snprint(buf, sizeof(buf), "%s/cs", ds->netdir); - fd = open(buf, ORDWR); - if(fd < 0){ - /* no connection server, don't translate */ - snprint(clone, sizeof(clone), "%s/%s/clone", ds->netdir, ds->proto); - return call(clone, ds->rem, ds); - } - - /* - * ask connection server to translate - */ - snprint(buf, sizeof(buf), "%s!%s", ds->proto, ds->rem); - if(write(fd, buf, strlen(buf)) < 0){ - close(fd); - return -1; - } - - /* - * loop through each address from the connection server till - * we get one that works. - */ - *besterr = 0; - rv = -1; - seek(fd, 0, 0); - while((n = read(fd, buf, sizeof(buf) - 1)) > 0){ - buf[n] = 0; - p = strchr(buf, ' '); - if(p == 0) - continue; - *p++ = 0; - rv = call(buf, p, ds); - if(rv >= 0) - break; - err[0] = '\0'; - errstr(err, sizeof err); - if(strstr(err, "does not exist") == 0) - strcpy(besterr, err); - } - close(fd); - - if(rv < 0 && *besterr) - werrstr("%s", besterr); - else - werrstr("%s", err); - return rv; -} - -static int -call(char *clone, char *dest, DS *ds) -{ - int fd, cfd, n; - char cname[Maxpath], name[Maxpath], data[Maxpath], *p; - - /* because cs is in a different name space, replace the mount point */ - if(*clone == '/'){ - p = strchr(clone+1, '/'); - if(p == nil) - p = clone; - else - p++; - } else - p = clone; - snprint(cname, sizeof cname, "%s/%s", ds->netdir, p); - - cfd = open(cname, ORDWR); - if(cfd < 0) - return -1; - - /* get directory name */ - n = read(cfd, name, sizeof(name)-1); - if(n < 0){ - close(cfd); - return -1; - } - name[n] = 0; - for(p = name; *p == ' '; p++) - ; - snprint(name, sizeof(name), "%ld", strtoul(p, 0, 0)); - p = strrchr(cname, '/'); - *p = 0; - if(ds->dir) - snprint(ds->dir, NETPATHLEN, "%s/%s", cname, name); - snprint(data, sizeof(data), "%s/%s/data", cname, name); - - /* connect */ - if(ds->local) - snprint(name, sizeof(name), "connect %s %s", dest, ds->local); - else - snprint(name, sizeof(name), "connect %s", dest); - if(write(cfd, name, strlen(name)) < 0){ - close(cfd); - return -1; - } - - /* open data connection */ - fd = open(data, ORDWR); - if(fd < 0){ - close(cfd); - return -1; - } - if(ds->cfdp) - *ds->cfdp = cfd; - else - close(cfd); - return fd; -} - -/* - * parse a dial string - */ -static void -_dial_string_parse(char *str, DS *ds) -{ - char *p, *p2; - - strncpy(ds->buf, str, Maxstring); - ds->buf[Maxstring-1] = 0; - - p = strchr(ds->buf, '!'); - if(p == 0) { - ds->netdir = 0; - ds->proto = "net"; - ds->rem = ds->buf; - } else { - if(*ds->buf != '/' && *ds->buf != '#'){ - ds->netdir = 0; - ds->proto = ds->buf; - } else { - for(p2 = p; *p2 != '/'; p2--) - ; - *p2++ = 0; - ds->netdir = ds->buf; - ds->proto = p2; - } - *p = 0; - ds->rem = p + 1; - } -} diff --git a/sys/src/libthread/main.c b/sys/src/libthread/main.c index 72e3a8701..1dcd9c319 100644 --- a/sys/src/libthread/main.c +++ b/sys/src/libthread/main.c @@ -17,9 +17,6 @@ static jmp_buf _mainjmp; static void mainlauncher(void*); extern void (*_sysfatal)(char*, va_list); extern void (*__assert)(char*); -extern int (*_dial)(char*, char*, char*, int*); - -extern int _threaddial(char*, char*, char*, int*); static Proc **mainp; @@ -38,7 +35,6 @@ main(int argc, char **argv) _systhreadinit(); _qlockinit(_threadrendezvous); _sysfatal = _threadsysfatal; - _dial = _threaddial; __assert = _threadassert; notify(_threadnote); if(mainstacksize == 0) diff --git a/sys/src/libthread/mkfile b/sys/src/libthread/mkfile index 9fe44cd50..2869eedbe 100644 --- a/sys/src/libthread/mkfile +++ b/sys/src/libthread/mkfile @@ -8,7 +8,6 @@ OFILES=\ chanprint.$O\ create.$O\ debug.$O\ - dial.$O\ exec.$O\ exit.$O\ id.$O\ |