Unified · Split
| @@ -0,0 +1,384 @@ | |||
| 1 | implement Dial; | ||
| 2 | |||
| 3 | include "sys.m"; | ||
| 4 | sys: Sys; | ||
| 5 | |||
| 6 | include "dial.m"; | ||
| 7 | |||
| 8 | # | ||
| 9 | # the dialstring is of the form '[/net/]proto!dest' | ||
| 10 | # | ||
| 11 | dial(addr: string, local: string): ref Connection | ||
| 12 | { | ||
| 13 | if(sys == nil) | ||
| 14 | sys = load Sys Sys->PATH; | ||
| 15 | (netdir, proto, rem) := dialparse(addr); | ||
| 16 | if(netdir != nil) | ||
| 17 | return csdial(netdir, proto, rem, local); | ||
| 18 | |||
| 19 | c := csdial("/net", proto, rem, local); | ||
| 20 | if(c != nil) | ||
| 21 | return c; | ||
| 22 | err := sys->sprint("%r"); | ||
| 23 | if(lookstr(err, "refused") >= 0) | ||
| 24 | return nil; | ||
| 25 | c = csdial("/net.alt", proto, rem, local); | ||
| 26 | if(c != nil) | ||
| 27 | return c; | ||
| 28 | # ignore the least precise one | ||
| 29 | alterr := sys->sprint("%r"); | ||
| 30 | if(lookstr(alterr, "translate")>=0 || lookstr(alterr, "does not exist")>=0) | ||
| 31 | sys->werrstr(err); | ||
| 32 | else | ||
| 33 | sys->werrstr(alterr); | ||
| 34 | return nil; | ||
| 35 | } | ||
| 36 | |||
| 37 | # | ||
| 38 | # ask the connection server to translate | ||
| 39 | # | ||
| 40 | csdial(netdir: string, proto: string, rem: string, local: string): ref Connection | ||
| 41 | { | ||
| 42 | fd := sys->open(netdir+"/cs", Sys->ORDWR); | ||
| 43 | if(fd == nil){ | ||
| 44 | # no connection server, don't translate | ||
| 45 | return call(netdir+"/"+proto+"/clone", rem, local); | ||
| 46 | } | ||
| 47 | |||
| 48 | if(sys->fprint(fd, "%s!%s", proto, rem) < 0) | ||
| 49 | return nil; | ||
| 50 | |||
| 51 | # try each recipe until we get one that works | ||
| 52 | besterr, err: string; | ||
| 53 | sys->seek(fd, big 0, 0); | ||
| 54 | for(;;){ | ||
| 55 | (clonefile, addr) := csread(fd); | ||
| 56 | if(clone == nil) | ||
| 57 | break; | ||
| 58 | c := call(redir(clonefile, netdir), addr, local); | ||
| 59 | if(c != nil) | ||
| 60 | return c; | ||
| 61 | err = sys->sprint("%r"); | ||
| 62 | if(lookstr(err, "does not exist") < 0) | ||
| 63 | besterr = err; | ||
| 64 | } | ||
| 65 | if(besterr != nil) | ||
| 66 | sys->werrstr(besterr); | ||
| 67 | else | ||
| 68 | sys->werrstr(err); | ||
| 69 | return nil; | ||
| 70 | } | ||
| 71 | |||
| 72 | call(clonefile: string, dest: string, local: string): ref Connection | ||
| 73 | { | ||
| 74 | (cfd, convdir) := clone(clonefile); | ||
| 75 | if(cfd == nil) | ||
| 76 | return nil; | ||
| 77 | |||
| 78 | if(local != nil) | ||
| 79 | rv := sys->fprint(cfd, "connect %s %s", dest, local); | ||
| 80 | else | ||
| 81 | rv = sys->fprint(cfd, "connect %s", dest); | ||
| 82 | if(rv < 0) | ||
| 83 | return nil; | ||
| 84 | |||
| 85 | fd := sys->open(convdir+"/data", Sys->ORDWR); | ||
| 86 | if(fd == nil) | ||
| 87 | return nil; | ||
| 88 | return ref Connection(fd, cfd, convdir); | ||
| 89 | } | ||
| 90 | |||
| 91 | clone(clonefile: string): (ref Sys->FD, string) | ||
| 92 | { | ||
| 93 | pdir := parent(clonefile); | ||
| 94 | if(pdir == nil){ | ||
| 95 | sys->werrstr(sys->sprint("bad clone file name: %q", clonefile)); | ||
| 96 | return (nil, nil); | ||
| 97 | } | ||
| 98 | cfd := sys->open(clonefile, Sys->ORDWR); | ||
| 99 | if(cfd == nil) | ||
| 100 | return (nil, nil); | ||
| 101 | lno := readchan(cfd); | ||
| 102 | if(lno == nil) | ||
| 103 | return (nil, nil); | ||
| 104 | return (cfd, pdir+"/"+lno); | ||
| 105 | } | ||
| 106 | |||
| 107 | readchan(cfd: ref Sys->FD): string | ||
| 108 | { | ||
| 109 | buf := array[Sys->NAMEMAX] of byte; | ||
| 110 | n := sys->read(cfd, buf, len buf); | ||
| 111 | if(n < 0) | ||
| 112 | return nil; | ||
| 113 | if(n == 0){ | ||
| 114 | sys->werrstr("empty clone file"); | ||
| 115 | return nil; | ||
| 116 | } | ||
| 117 | return string int string buf[0: n]; | ||
| 118 | } | ||
| 119 | |||
| 120 | redir(old: string, newdir: string): string | ||
| 121 | { | ||
| 122 | # because cs is in a different name space, replace the mount point | ||
| 123 | # assumes the mount point is directory in root (eg, /net/proto/clone) | ||
| 124 | if(len old > 1 && old[0] == '/'){ | ||
| 125 | p := lookc(old[1:], '/'); | ||
| 126 | if(p >= 0) | ||
| 127 | return newdir+"/"+old[1+p+1:]; | ||
| 128 | } | ||
| 129 | return newdir+"/"+old; | ||
| 130 | } | ||
| 131 | |||
| 132 | lookc(s: string, c: int): int | ||
| 133 | { | ||
| 134 | for(i := 0; i < len s; i++) | ||
| 135 | if(s[i] == c) | ||
| 136 | return i; | ||
| 137 | return -1; | ||
| 138 | } | ||
| 139 | |||
| 140 | backc(s: string, i: int, c: int): int | ||
| 141 | { | ||
| 142 | if(i >= len s) | ||
| 143 | return -1; | ||
| 144 | while(i >= 0 && s[i] != c) | ||
| 145 | i--; | ||
| 146 | return i; | ||
| 147 | } | ||
| 148 | |||
| 149 | lookstr(s: string, t: string): int | ||
| 150 | { | ||
| 151 | lt := len t; # we know it's not zero | ||
| 152 | Search: | ||
| 153 | for(i := 0; i <= len s - lt; i++){ | ||
| 154 | for(j := 0; j < lt; j++) | ||
| 155 | if(s[i+j] != t[j]) | ||
| 156 | continue Search; | ||
| 157 | return i; | ||
| 158 | } | ||
| 159 | return -1; | ||
| 160 | } | ||
| 161 | |||
| 162 | # | ||
| 163 | # [[/netdir/]proto!]remainder | ||
| 164 | # | ||
| 165 | dialparse(addr: string): (string, string, string) | ||
| 166 | { | ||
| 167 | p := lookc(addr, '!'); | ||
| 168 | if(p < 0) | ||
| 169 | return (nil, "net", addr); | ||
| 170 | if(addr[0] != '/' && addr[0] != '#') | ||
| 171 | return (nil, addr[0: p], addr[p+1:]); | ||
| 172 | p2 := backc(addr, p, '/'); | ||
| 173 | if(p2 <= 0) | ||
| 174 | return (addr[0: p], "net", addr[p+1:]); # plan 9 returns proto "" | ||
| 175 | return (addr[0: p2], addr[p2+1: p], addr[p+1:]); | ||
| 176 | } | ||
| 177 | |||
| 178 | # | ||
| 179 | # announce a network service | ||
| 180 | # | ||
| 181 | announce(addr: string): ref Connection | ||
| 182 | { | ||
| 183 | if(sys == nil) | ||
| 184 | sys = load Sys Sys->PATH; | ||
| 185 | |||
| 186 | (naddr, clonefile) := nettrans(addr); | ||
| 187 | if(naddr == nil) | ||
| 188 | return nil; | ||
| 189 | |||
| 190 | (ctl, convdir) := clone(clonefile); | ||
| 191 | if(ctl == nil){ | ||
| 192 | sys->werrstr(sys->sprint("announce %r")); | ||
| 193 | return nil; | ||
| 194 | } | ||
| 195 | |||
| 196 | if(sys->fprint(ctl, "announce %s", naddr) < 0){ | ||
| 197 | sys->werrstr(sys->sprint("announce writing %s: %r", clonefile)); | ||
| 198 | return nil; | ||
| 199 | } | ||
| 200 | |||
| 201 | return ref Connection(nil, ctl, convdir); | ||
| 202 | } | ||
| 203 | |||
| 204 | # | ||
| 205 | # listen for an incoming call on announced connection | ||
| 206 | # | ||
| 207 | listen(ac: ref Connection): ref Connection | ||
| 208 | { | ||
| 209 | if(sys == nil) | ||
| 210 | sys = load Sys Sys->PATH; | ||
| 211 | |||
| 212 | pdir := parent(ac.dir); # ac.dir should be /netdir/N | ||
| 213 | if(pdir == nil){ | ||
| 214 | sys->werrstr(sys->sprint("listen directory format: %q", ac.dir)); | ||
| 215 | return nil; | ||
| 216 | } | ||
| 217 | |||
| 218 | ctl := sys->open(ac.dir+"/listen", Sys->ORDWR); | ||
| 219 | if(ctl == nil){ | ||
| 220 | sys->werrstr(sys->sprint("listen opening %s: %r", ac.dir+"/listen")); | ||
| 221 | return nil; | ||
| 222 | } | ||
| 223 | |||
| 224 | lno := readchan(ctl); | ||
| 225 | if(lno == nil){ | ||
| 226 | sys->werrstr(sys->sprint("listen reading %s/listen: %r", ac.dir)); | ||
| 227 | return nil; | ||
| 228 | } | ||
| 229 | return ref Connection(nil, ctl, pdir+"/"+lno); | ||
| 230 | |||
| 231 | } | ||
| 232 | |||
| 233 | # | ||
| 234 | # translate an address [[/netdir/]proto!rem] using /netdir/cs | ||
| 235 | # returning (newaddress, clonefile) | ||
| 236 | # | ||
| 237 | nettrans(addr: string): (string, string) | ||
| 238 | { | ||
| 239 | (netdir, proto, rem) := dialparse(addr); | ||
| 240 | if(proto == nil || proto == "net"){ | ||
| 241 | sys->werrstr(sys->sprint("bad dial string: %s", addr)); | ||
| 242 | return (nil, nil); | ||
| 243 | } | ||
| 244 | if(netdir == nil) | ||
| 245 | netdir = "/net"; | ||
| 246 | |||
| 247 | # try to translate using connection server | ||
| 248 | fd := sys->open(netdir+"/cs", Sys->ORDWR); | ||
| 249 | if(fd == nil){ | ||
| 250 | # use it untranslated | ||
| 251 | if(rem == nil){ | ||
| 252 | sys->werrstr(sys->sprint("bad dial string: %s", addr)); | ||
| 253 | return (nil, nil); | ||
| 254 | } | ||
| 255 | return (rem, netdir+"/"+proto+"/clone"); | ||
| 256 | } | ||
| 257 | if(sys->fprint(fd, "%s!%s", proto, rem) < 0) | ||
| 258 | return (nil, nil); | ||
| 259 | sys->seek(fd, big 0, 0); | ||
| 260 | (clonefile, naddr) := csread(fd); | ||
| 261 | if(clonefile == nil) | ||
| 262 | return (nil, nil); | ||
| 263 | |||
| 264 | return (naddr, redir(clonefile, netdir)); | ||
| 265 | } | ||
| 266 | |||
| 267 | csread(fd: ref Sys->FD): (string, string) | ||
| 268 | { | ||
| 269 | buf := array[Sys->NAMEMAX] of byte; | ||
| 270 | n := sys->read(fd, buf, len buf); | ||
| 271 | if(n < 0) | ||
| 272 | return (nil, nil); | ||
| 273 | line := string buf[0: n]; | ||
| 274 | p := lookc(line, ' '); | ||
| 275 | if(p < 0) | ||
| 276 | return (nil, nil); | ||
| 277 | if(p == 0){ | ||
| 278 | sys->werrstr("cs: no translation"); | ||
| 279 | return (nil, nil); | ||
| 280 | } | ||
| 281 | return (line[0:p], line[p+1:]); | ||
| 282 | } | ||
| 283 | |||
| 284 | # | ||
| 285 | # accept a call, return an fd to the open data file | ||
| 286 | # | ||
| 287 | accept(c: ref Connection): ref Sys->FD | ||
| 288 | { | ||
| 289 | if(sys == nil) | ||
| 290 | sys = load Sys Sys->PATH; | ||
| 291 | sys->fprint(c.cfd, "accept %s", lastname(c.dir)); # ignore return value, network might not need accepts | ||
| 292 | return sys->open(c.dir+"/data", Sys->ORDWR); | ||
| 293 | } | ||
| 294 | |||
| 295 | # | ||
| 296 | # reject a call, tell device the reason for the rejection | ||
| 297 | # | ||
| 298 | reject(c: ref Connection, why: string): int | ||
| 299 | { | ||
| 300 | if(sys == nil) | ||
| 301 | sys = load Sys Sys->PATH; | ||
| 302 | if(sys->fprint(c.cfd, "reject %s %q", lastname(c.dir), why) < 0) | ||
| 303 | return -1; | ||
| 304 | return 0; | ||
| 305 | } | ||
| 306 | |||
| 307 | lastname(dir: string): string | ||
| 308 | { | ||
| 309 | p := backc(dir, len dir-1, '/'); | ||
| 310 | if(p < 0) | ||
| 311 | return dir; | ||
| 312 | return dir[p+1:]; # N in /net/N | ||
| 313 | } | ||
| 314 | |||
| 315 | parent(dir: string): string | ||
| 316 | { | ||
| 317 | p := backc(dir, len dir-1, '/'); | ||
| 318 | if(p < 0) | ||
| 319 | return nil; | ||
| 320 | return dir[0: p]; | ||
| 321 | } | ||
| 322 | |||
| 323 | netmkaddr(addr, net, svc: string): string | ||
| 324 | { | ||
| 325 | if(sys == nil) | ||
| 326 | sys = load Sys Sys->PATH; | ||
| 327 | if(net == nil) | ||
| 328 | net = "net"; | ||
| 329 | (n, nil) := sys->tokenize(addr, "!"); | ||
| 330 | if(n <= 1){ | ||
| 331 | if(svc== nil) | ||
| 332 | return sys->sprint("%s!%s", net, addr); | ||
| 333 | return sys->sprint("%s!%s!%s", net, addr, svc); | ||
| 334 | } | ||
| 335 | if(svc == nil || n > 2) | ||
| 336 | return addr; | ||
| 337 | return sys->sprint("%s!%s", addr, svc); | ||
| 338 | } | ||
| 339 | |||
| 340 | netinfo(c: ref Connection): ref Conninfo | ||
| 341 | { | ||
| 342 | if(sys == nil) | ||
| 343 | sys = load Sys Sys->PATH; | ||
| 344 | if((dir := c.dir) == nil){ | ||
| 345 | if(c.dfd == nil) | ||
| 346 | return nil; | ||
| 347 | dir = parent(sys->fd2path(c.dfd)); | ||
| 348 | if(dir == nil) | ||
| 349 | return nil; | ||
| 350 | } | ||
| 351 | ci := ref Conninfo; | ||
| 352 | ci.dir = dir; | ||
| 353 | ci.root = parent(dir); | ||
| 354 | while((p := parent(ci.root)) != nil && p != "/") | ||
| 355 | ci.root = p; | ||
| 356 | (ok, d) := sys->stat(ci.dir); | ||
| 357 | if(ok >= 0) | ||
| 358 | ci.spec = sys->sprint("#%c%d", d.dtype, d.dev); | ||
| 359 | (ci.lsys, ci.lserv) = getendpoint(ci.dir, "local"); | ||
| 360 | (ci.rsys, ci.rserv) = getendpoint(ci.dir, "remote"); | ||
| 361 | p = parent(ci.dir); | ||
| 362 | if(p == nil) | ||
| 363 | return nil; | ||
| 364 | if(len p >= 5 && p[0:5] == "/net/") | ||
| 365 | p = p[5:]; | ||
| 366 | ci.laddr = sys->sprint("%s!%s!%s", p, ci.lsys, ci.lserv); | ||
| 367 | ci.raddr = sys->sprint("%s!%s!%s", p, ci.rsys, ci.rserv); | ||
| 368 | return ci; | ||
| 369 | } | ||
| 370 | |||
| 371 | getendpoint(dir: string, file: string): (string, string) | ||
| 372 | { | ||
| 373 | fd := sys->open(dir+"/"+file, Sys->OREAD); | ||
| 374 | buf := array[128] of byte; | ||
| 375 | if(fd == nil || (n := sys->read(fd, buf, len buf)) <= 0) | ||
| 376 | return ("???", "???"); # compatible, but probably poor defaults | ||
| 377 | if(n > 0 && buf[n-1] == byte '\n') | ||
| 378 | n--; | ||
| 379 | s := string buf[0: n]; | ||
| 380 | p := lookc(s, '!'); | ||
| 381 | if(p < 0) | ||
| 382 | return (s, "???"); | ||
| 383 | return (s[0:p], s[p+1:]); | ||
| 384 | } | ||
| @@ -113,6 +113,7 @@ TARG=\ · 112 unmodified lines | |||
| 113 | string.dis\ | 113 | string.dis\ |
| 114 | strinttab.dis\ | 114 | strinttab.dis\ |
| 115 | styx.dis\ | 115 | styx.dis\ |
| 116 | styxflush.dis\ | ||
| 116 | styxlib.dis\ | 117 | styxlib.dis\ |
| 117 | styxpersist.dis\ | 118 | styxpersist.dis\ |
| 118 | styxservers.dis\ | 119 | styxservers.dis\ |
| @@ -234,3 +235,4 @@ csv.dis: $ROOT/module/csv.m · 115 unmodified lines | |||
| 234 | json.dis: $ROOT/module/json.m | 235 | json.dis: $ROOT/module/json.m |
| 235 | lists.dis: $ROOT/module/lists.m | 236 | lists.dis: $ROOT/module/lists.m |
| 236 | vac.dis: $ROOT/module/vac.m $ROOT/module/venti.m | 237 | vac.dis: $ROOT/module/vac.m $ROOT/module/venti.m |
| 238 | dial.dis: $ROOT/module/dial.m | ||
Binary file not shown.
| @@ -706,7 +706,9 @@ appl · 705 unmodified lines | |||
| 706 | echo.b | 706 | echo.b |
| 707 | expr.b | 707 | expr.b |
| 708 | file2chan.b | 708 | file2chan.b |
| 709 | mload.b | ||
| 709 | mkfile | 710 | mkfile |
| 711 | mpexpr.b | ||
| 710 | regex.b | 712 | regex.b |
| 711 | sexprs.b | 713 | sexprs.b |
| 712 | sh.b | 714 | sh.b |
| @@ -963,6 +965,7 @@ appl · 250 unmodified lines | |||
| 963 | deflate.b | 965 | deflate.b |
| 964 | devpointer.b | 966 | devpointer.b |
| 965 | dhcpclient.b | 967 | dhcpclient.b |
| 968 | dial.b | ||
| 966 | dialog.b | 969 | dialog.b |
| 967 | dict.b | 970 | dict.b |
| 968 | dis.b | 971 | dis.b |
| @@ -1091,6 +1094,7 @@ appl · 122 unmodified lines | |||
| 1091 | string.b | 1094 | string.b |
| 1092 | strinttab.b | 1095 | strinttab.b |
| 1093 | styx.b | 1096 | styx.b |
| 1097 | styxflush.b | ||
| 1094 | styxlib.b | 1098 | styxlib.b |
| 1095 | styxservers.b | 1099 | styxservers.b |
| 1096 | tables.b | 1100 | tables.b |
| @@ -1588,6 +1592,7 @@ dis · 491 unmodified lines | |||
| 1588 | deflate.dis | 1592 | deflate.dis |
| 1589 | devpointer.dis | 1593 | devpointer.dis |
| 1590 | dhcpclient.dis | 1594 | dhcpclient.dis |
| 1595 | dial.dis | ||
| 1591 | dialog.dis | 1596 | dialog.dis |
| 1592 | dict.dis | 1597 | dict.dis |
| 1593 | dis.dis | 1598 | dis.dis |
| @@ -1686,6 +1691,7 @@ dis · 92 unmodified lines | |||
| 1686 | styx.dis | 1691 | styx.dis |
| 1687 | styxconv | 1692 | styxconv |
| 1688 | + | 1693 | + |
| 1694 | styxflush.dis | ||
| 1689 | styxlib.dis | 1695 | styxlib.dis |
| 1690 | styxpersist.dis | 1696 | styxpersist.dis |
| 1691 | styxservers.dis | 1697 | styxservers.dis |
| @@ -2191,6 +2197,8 @@ mkfiles · 499 unmodified lines | |||
| 2191 | * | 2197 | * |
| 2192 | mnt | 2198 | mnt |
| 2193 | * | 2199 | * |
| 2200 | spki | ||
| 2201 | keys | ||
| 2194 | module | 2202 | module |
| 2195 | NOTICE | 2203 | NOTICE |
| 2196 | alphabet.m | 2204 | alphabet.m |
| @@ -2221,6 +2229,7 @@ module · 24 unmodified lines | |||
| 2221 | debug.m | 2229 | debug.m |
| 2222 | devpointer.m | 2230 | devpointer.m |
| 2223 | dhcp.m | 2231 | dhcp.m |
| 2232 | dial.m | ||
| 2224 | dialog.m | 2233 | dialog.m |
| 2225 | dict.m | 2234 | dict.m |
| 2226 | dis.m | 2235 | dis.m |
| @@ -2326,6 +2335,7 @@ module · 99 unmodified lines | |||
| 2326 | strinttab.m | 2335 | strinttab.m |
| 2327 | styx.m | 2336 | styx.m |
| 2328 | styxconv.m | 2337 | styxconv.m |
| 2338 | styxflush.m | ||
| 2329 | styxlib.m | 2339 | styxlib.m |
| 2330 | styxpersist.m | 2340 | styxpersist.m |
| 2331 | styxservers.m | 2341 | styxservers.m |
| @@ -183,6 +183,7 @@ csv sh-csv · 182 unmodified lines | |||
| 183 | getcsv sh-csv | 183 | getcsv sh-csv |
| 184 | sh-csv sh-csv | 184 | sh-csv sh-csv |
| 185 | expr sh-expr | 185 | expr sh-expr |
| 186 | mpexpr sh-expr | ||
| 186 | ntest sh-expr | 187 | ntest sh-expr |
| 187 | sh-expr sh-expr | 188 | sh-expr sh-expr |
| 188 | file2chan sh-file2chan | 189 | file2chan sh-file2chan |
| @@ -194,6 +195,9 @@ rread sh-file2chan · 5 unmodified lines | |||
| 194 | rreadone sh-file2chan | 195 | rreadone sh-file2chan |
| 195 | rwrite sh-file2chan | 196 | rwrite sh-file2chan |
| 196 | sh-file2chan sh-file2chan | 197 | sh-file2chan sh-file2chan |
| 198 | mload sh-mload | ||
| 199 | munload sh-mload | ||
| 200 | sh-mload sh-mload | ||
| 197 | match sh-regex | 201 | match sh-regex |
| 198 | re sh-regex | 202 | re sh-regex |
| 199 | sh-regex sh-regex | 203 | sh-regex sh-regex |
| @@ -44,6 +44,13 @@ dhcp dhcpclient · 43 unmodified lines | |||
| 44 | dhcpclient dhcpclient | 44 | dhcpclient dhcpclient |
| 45 | lease dhcpclient | 45 | lease dhcpclient |
| 46 | removecfg dhcpclient | 46 | removecfg dhcpclient |
| 47 | accept dial | ||
| 48 | announce dial | ||
| 49 | dial dial | ||
| 50 | listen dial | ||
| 51 | netinfo dial | ||
| 52 | netmkaddr dial | ||
| 53 | reject dial | ||
| 47 | dialog dialog | 54 | dialog dialog |
| 48 | getstring dialog | 55 | getstring dialog |
| 49 | prompt dialog | 56 | prompt dialog |
| @@ -387,6 +394,7 @@ styx styx · 337 unmodified lines | |||
| 387 | tmsg styx | 394 | tmsg styx |
| 388 | unpackdir styx | 395 | unpackdir styx |
| 389 | styxconv styxconv | 396 | styxconv styxconv |
| 397 | styxflush styxflush | ||
| 390 | styxpersist styxpersist | 398 | styxpersist styxpersist |
| 391 | styxservers styxservers | 399 | styxservers styxservers |
| 392 | nametree styxservers-nametree | 400 | nametree styxservers-nametree |
| @@ -0,0 +1,312 @@ | |||
| 1 | .TH DIAL 2 | ||
| 2 | .SH NAME | ||
| 3 | Dial: accept, announce, dial, listen, netinfo, netmkaddr, reject \- make network connections | ||
| 4 | .SH SYNOPSIS | ||
| 5 | .EX | ||
| 6 | include "sys.m"; | ||
| 7 | dial := load Dial Dial->PATH; | ||
| 8 | |||
| 9 | Connection: adt | ||
| 10 | { | ||
| 11 | dfd: ref FD; # data file | ||
| 12 | cfd: ref FD; # control file | ||
| 13 | dir: string; # pathname of line directory | ||
| 14 | }; | ||
| 15 | |||
| 16 | announce: fn(addr: string): ref Connection; | ||
| 17 | dial: fn(addr, local: string): ref Connection; | ||
| 18 | listen: fn(c: ref Connection): ref Connection; | ||
| 19 | accept: fn(c: ref Connection): ref Sys->FD; | ||
| 20 | reject: fn(c: ref Connection, why: string); | ||
| 21 | |||
| 22 | netmkaddr: fn(net, host, svc: string): string; | ||
| 23 | |||
| 24 | Conninfo: adt | ||
| 25 | { | ||
| 26 | dir: string; # connection directory | ||
| 27 | root: string; # network mount point | ||
| 28 | spec: string; # its binding spec | ||
| 29 | lsys: string; # local host address | ||
| 30 | lserv: string; # local service | ||
| 31 | rsys: string; # remote host address | ||
| 32 | rserv: string; # remote service | ||
| 33 | laddr: string; # local address in dial form | ||
| 34 | raddr: string; # remote address in dial form | ||
| 35 | }; | ||
| 36 | |||
| 37 | netinfo: fn(c: ref Connection): ref Conninfo; | ||
| 38 | .EE | ||
| 39 | .SH DESCRIPTION | ||
| 40 | .B Dial | ||
| 41 | establishes network connections. | ||
| 42 | The description below uses the following definitions: | ||
| 43 | .TF network | ||
| 44 | .PD | ||
| 45 | .TP | ||
| 46 | .I addr | ||
| 47 | is a network address in one of the following forms: | ||
| 48 | .br | ||
| 49 | .IP | ||
| 50 | .IB network ! netaddr ! service\f1 | ||
| 51 | .br | ||
| 52 | .IB network ! netaddr\f1 | ||
| 53 | .br | ||
| 54 | .IR netaddr | ||
| 55 | .TP | ||
| 56 | .I network | ||
| 57 | Any directory listed in | ||
| 58 | .B /net | ||
| 59 | (eg, | ||
| 60 | .BR tcp ), | ||
| 61 | or the special token, | ||
| 62 | .BR net . | ||
| 63 | The special name | ||
| 64 | .B net | ||
| 65 | stands for any network that connects | ||
| 66 | the current host and | ||
| 67 | .IR netaddr . | ||
| 68 | A network name can be preceded by the full path name of a directory | ||
| 69 | of networks, using the form | ||
| 70 | .I /dir/network | ||
| 71 | (eg, | ||
| 72 | .BR /net.alt/tcp ). | ||
| 73 | .TP | ||
| 74 | .I netaddr | ||
| 75 | A host name, a domain name, a network address, | ||
| 76 | or a meta-name of the form | ||
| 77 | .BI $ attribute\f1, | ||
| 78 | which | ||
| 79 | is replaced by | ||
| 80 | .I value | ||
| 81 | from the corresponding attribute-value pair | ||
| 82 | in the connection server data base (see | ||
| 83 | .IR db (6)). | ||
| 84 | .PP | ||
| 85 | The functions | ||
| 86 | .B dial | ||
| 87 | and | ||
| 88 | .B announce | ||
| 89 | translate a given | ||
| 90 | .I addr | ||
| 91 | to an actual network address using | ||
| 92 | the connection server | ||
| 93 | .IR cs (8). | ||
| 94 | If a logical name | ||
| 95 | .I addr | ||
| 96 | corresponds to several network addresses, | ||
| 97 | for instance if a destination machine has several interfaces, | ||
| 98 | .I cs | ||
| 99 | will return them all; | ||
| 100 | .B dial | ||
| 101 | or | ||
| 102 | .B announce | ||
| 103 | will try each in turn until one works. | ||
| 104 | In particular, if | ||
| 105 | .I addr | ||
| 106 | is | ||
| 107 | .BR net , | ||
| 108 | .I cs | ||
| 109 | will return addresses on | ||
| 110 | all networks that are common to source and destination. | ||
| 111 | The translation procedure accesses | ||
| 112 | .I cs | ||
| 113 | using its interface file | ||
| 114 | .BR cs , | ||
| 115 | which is sought as follows: | ||
| 116 | first, in an explicit directory | ||
| 117 | .BI / dir | ||
| 118 | if one was given in | ||
| 119 | .IR network ; | ||
| 120 | second, in the standard directory | ||
| 121 | .BR /net ; | ||
| 122 | and finally in the directory | ||
| 123 | .BR /net.alt | ||
| 124 | .RB ( dial | ||
| 125 | only). | ||
| 126 | If the connection server cannot be found, | ||
| 127 | the | ||
| 128 | .I addr | ||
| 129 | is used as-is. | ||
| 130 | .PP | ||
| 131 | If a connection attempt is successful, the | ||
| 132 | .B dir | ||
| 133 | member of the resulting | ||
| 134 | .B Connection | ||
| 135 | will be | ||
| 136 | the path name of a | ||
| 137 | .I line directory | ||
| 138 | that has files for accessing the connection. | ||
| 139 | One line directory exists for each possible connection. | ||
| 140 | The | ||
| 141 | .B data | ||
| 142 | file in the line directory is opened to | ||
| 143 | make a connection, and read and written to communicate with the destination. | ||
| 144 | The | ||
| 145 | .B ctl | ||
| 146 | file in the line directory can be used to send commands to the line. | ||
| 147 | See | ||
| 148 | .IR ip (3) | ||
| 149 | for messages that can be written to the | ||
| 150 | .B ctl | ||
| 151 | file. | ||
| 152 | The last close of both | ||
| 153 | .B data | ||
| 154 | and | ||
| 155 | .B ctl | ||
| 156 | file will close the connection. | ||
| 157 | The | ||
| 158 | .B remote | ||
| 159 | file in the line directory contains the address called; the file | ||
| 160 | .B local | ||
| 161 | contains the local address assigned. | ||
| 162 | .PP | ||
| 163 | The function | ||
| 164 | .B dial | ||
| 165 | calls destination | ||
| 166 | .I addr | ||
| 167 | on a multiplexed network. | ||
| 168 | If the connection server returns several possible locations for | ||
| 169 | .IR addr , | ||
| 170 | .B dial | ||
| 171 | tries each in turn, until a connection is made, | ||
| 172 | or no address remains to be tried. | ||
| 173 | .B Dial | ||
| 174 | returns a reference to a | ||
| 175 | .B Connection | ||
| 176 | value containing a string | ||
| 177 | .B dir | ||
| 178 | that names the conversation directory for the connection, | ||
| 179 | a file descriptor | ||
| 180 | .B dfd | ||
| 181 | open for reading and writing the | ||
| 182 | .B data | ||
| 183 | file in that directory, and | ||
| 184 | a file descriptor | ||
| 185 | .B cfd | ||
| 186 | open for reading and writing the directory's | ||
| 187 | .B ctl | ||
| 188 | file. | ||
| 189 | If | ||
| 190 | .IR local | ||
| 191 | is non-empty, and the network allows the local address to be set, | ||
| 192 | as is the case with UDP and TCP port numbers, | ||
| 193 | the local address will be set to | ||
| 194 | .IR local . | ||
| 195 | .PP | ||
| 196 | .B Announce | ||
| 197 | and | ||
| 198 | .B listen | ||
| 199 | are the complements of | ||
| 200 | .BR dial . | ||
| 201 | .B Announce | ||
| 202 | establishes a network name to which incoming calls can be made. | ||
| 203 | In | ||
| 204 | .IR addr , | ||
| 205 | .I netaddr | ||
| 206 | gives the name or address of one of the local host's interfaces on which to listen for | ||
| 207 | calls to the given | ||
| 208 | .IR service ; | ||
| 209 | it can be | ||
| 210 | .B * | ||
| 211 | to listen for calls on any interface on | ||
| 212 | .IR network . | ||
| 213 | .B Announce | ||
| 214 | returns a reference to a | ||
| 215 | .B Connection | ||
| 216 | value in which only the | ||
| 217 | .B cfd | ||
| 218 | descriptor is open, on the control file representing the announcement. | ||
| 219 | .B Listen | ||
| 220 | takes as its only argument a reference to the | ||
| 221 | .B Connection | ||
| 222 | returned by a successful call to | ||
| 223 | .BR announce . | ||
| 224 | When a call is received, | ||
| 225 | .B listen | ||
| 226 | returns a reference to a new | ||
| 227 | .B Connection | ||
| 228 | value that refers to the conversation directory for the incoming call; | ||
| 229 | only the | ||
| 230 | .B cfd | ||
| 231 | descriptor is open. | ||
| 232 | That call can be accepted or rejected. | ||
| 233 | Use | ||
| 234 | .B accept | ||
| 235 | to obtain a file descriptor for the data file for the conversation. | ||
| 236 | Use | ||
| 237 | .B reject | ||
| 238 | to reject the incoming call; some networks will also tell the caller the reason | ||
| 239 | .IR why . | ||
| 240 | .PP | ||
| 241 | Given a | ||
| 242 | .BR Connection , | ||
| 243 | .B netinfo | ||
| 244 | returns a reference to a | ||
| 245 | .B Conninfo | ||
| 246 | value that gives details about the connection and its network. | ||
| 247 | .SH EXAMPLES | ||
| 248 | .PP | ||
| 249 | Make a call and return an open file descriptor to | ||
| 250 | use for communications: | ||
| 251 | .IP | ||
| 252 | .EX | ||
| 253 | callkremvax(): ref Sys->FD | ||
| 254 | { | ||
| 255 | c := dial->dial("tcp!kremvax!80", nil); | ||
| 256 | if(c == nil) | ||
| 257 | return nil; | ||
| 258 | return c.dfd; | ||
| 259 | } | ||
| 260 | .EE | ||
| 261 | .PP | ||
| 262 | Call the local certificate signer: | ||
| 263 | .IP | ||
| 264 | .EX | ||
| 265 | dialsigner(service: string): ref Sys->FD | ||
| 266 | { | ||
| 267 | c := dial->dial("net!$SIGNER!inflogin", nil); | ||
| 268 | if(c == nil) | ||
| 269 | return nil; | ||
| 270 | return c.dfd; | ||
| 271 | } | ||
| 272 | .EE | ||
| 273 | .PP | ||
| 274 | Listen for incoming calls. | ||
| 275 | .IP | ||
| 276 | .EX | ||
| 277 | listener() | ||
| 278 | { | ||
| 279 | ac := dial->announce("tcp!*!9995"); | ||
| 280 | if(ac == nil){ | ||
| 281 | sys->print("can't announce: %r\n"); | ||
| 282 | exit; | ||
| 283 | } | ||
| 284 | for(;;){ | ||
| 285 | lc := dial->listen(ac); | ||
| 286 | if(lc == nil){ | ||
| 287 | sys->print("listen: %r\n"); | ||
| 288 | exit; | ||
| 289 | } | ||
| 290 | sys->print("incoming: %s\n", hd ctext(lc)); | ||
| 291 | spawn client(lc); | ||
| 292 | } | ||
| 293 | } | ||
| 294 | |||
| 295 | client(c: ref Connection) | ||
| 296 | { | ||
| 297 | dfd := dial->accept(c); | ||
| 298 | if(dfd == nil){ | ||
| 299 | sys->print("%s: can't accept: %r\n", c.dir); | ||
| 300 | exit; | ||
| 301 | } | ||
| 302 | buf := array[Sys->ATOMICIO] of byte; | ||
| 303 | while((n := sys->read(dfd, buf, len buf)) > 0) | ||
| 304 | sys->write(dfd, buf, n); | ||
| 305 | } | ||
| 306 | .EE | ||
| 307 | .SH SOURCE | ||
| 308 | .B /appl/lib/dial.b | ||
| 309 | .SH DIAGNOSTICS | ||
| 310 | The integer valued functions return 0 on success and -1 on error; | ||
| 311 | functions returning a reference return nil on error. | ||
| 312 | In those cases the system error string is set. | ||
| @@ -0,0 +1,34 @@ | |||
| 1 | Dial: module | ||
| 2 | { | ||
| 3 | PATH: con "/dis/lib/dial.dis"; | ||
| 4 | |||
| 5 | Connection: adt | ||
| 6 | { | ||
| 7 | dfd: ref Sys->FD; | ||
| 8 | cfd: ref Sys->FD; | ||
| 9 | dir: string; | ||
| 10 | }; | ||
| 11 | |||
| 12 | Conninfo: adt | ||
| 13 | { | ||
| 14 | dir: string; | ||
| 15 | root: string; | ||
| 16 | spec: string; | ||
| 17 | lsys: string; | ||
| 18 | lserv: string; | ||
| 19 | rsys: string; | ||
| 20 | rserv: string; | ||
| 21 | laddr: string; | ||
| 22 | raddr: string; | ||
| 23 | }; | ||
| 24 | |||
| 25 | announce: fn(addr: string): ref Connection; | ||
| 26 | dial: fn(addr, local: string): ref Connection; | ||
| 27 | listen: fn(c: ref Connection): ref Connection; | ||
| 28 | accept: fn(c: ref Connection): ref Sys->FD; | ||
| 29 | reject: fn(c: ref Connection, why: string): int; | ||
| 30 | # parse: fn(addr: string): (string, string, string); | ||
| 31 | |||
| 32 | netmkaddr: fn(addr, net, svc: string): string; | ||
| 33 | netinfo: fn(c: ref Connection): ref Conninfo; | ||
| 34 | }; | ||