123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274 |
- #include <u.h>
- #include <libc.h>
- #include <ctype.h>
- static int nettrans(char*, char*, int na, char*, int);
- enum
- {
- Maxpath= 256,
- };
- /*
- * announce a network service.
- */
- int
- announce(char *addr, char *dir)
- {
- int ctl, n, m;
- char buf[Maxpath];
- char buf2[Maxpath];
- char netdir[Maxpath];
- char naddr[Maxpath];
- char *cp;
- /*
- * translate the address
- */
- if(nettrans(addr, naddr, sizeof(naddr), netdir, sizeof(netdir)) < 0)
- return -1;
- /*
- * get a control channel
- */
- ctl = open(netdir, ORDWR);
- if(ctl<0){
- werrstr("announce opening %s: %r", netdir);
- return -1;
- }
- cp = strrchr(netdir, '/');
- if(cp == nil){
- werrstr("announce arg format %s", netdir);
- close(ctl);
- return -1;
- }
- *cp = 0;
- /*
- * find out which line we have
- */
- n = snprint(buf, sizeof(buf), "%s/", netdir);
- m = read(ctl, &buf[n], sizeof(buf)-n-1);
- if(m <= 0){
- werrstr("announce reading %s: %r", netdir);
- close(ctl);
- return -1;
- }
- buf[n+m] = 0;
- /*
- * make the call
- */
- n = snprint(buf2, sizeof(buf2), "announce %s", naddr);
- if(write(ctl, buf2, n)!=n){
- werrstr("announce writing %s: %r", netdir);
- close(ctl);
- return -1;
- }
- /*
- * return directory etc.
- */
- if(dir){
- strncpy(dir, buf, NETPATHLEN);
- dir[NETPATHLEN-1] = 0;
- }
- return ctl;
- }
- /*
- * listen for an incoming call
- */
- int
- listen(char *dir, char *newdir)
- {
- int ctl, n, m;
- char buf[Maxpath];
- char *cp;
- /*
- * open listen, wait for a call
- */
- snprint(buf, sizeof(buf), "%s/listen", dir);
- ctl = open(buf, ORDWR);
- if(ctl < 0){
- werrstr("listen opening %s: %r", buf);
- return -1;
- }
- /*
- * find out which line we have
- */
- strncpy(buf, dir, sizeof(buf) - 1);
- buf[sizeof(buf) - 1] = 0;
- cp = strrchr(buf, '/');
- if(cp == nil){
- close(ctl);
- werrstr("listen arg format %s", dir);
- return -1;
- }
- *++cp = 0;
- n = cp-buf;
- m = read(ctl, cp, sizeof(buf) - n - 1);
- if(m <= 0){
- close(ctl);
- werrstr("listen reading %s/listen: %r", dir);
- return -1;
- }
- buf[n+m] = 0;
- /*
- * return directory etc.
- */
- if(newdir){
- strncpy(newdir, buf, NETPATHLEN);
- newdir[NETPATHLEN-1] = 0;
- }
- return ctl;
- }
- /*
- * accept a call, return an fd to the open data file
- */
- int
- accept(int ctl, char *dir)
- {
- char buf[Maxpath];
- char *num;
- long n;
- num = strrchr(dir, '/');
- if(num == nil)
- num = dir;
- else
- num++;
- n = snprint(buf, sizeof(buf), "accept %s", num);
- write(ctl, buf, n); /* ignore return value, network might not need accepts */
- snprint(buf, sizeof(buf), "%s/data", dir);
- return open(buf, ORDWR);
- }
- /*
- * reject a call, tell device the reason for the rejection
- */
- int
- reject(int ctl, char *dir, char *cause)
- {
- char buf[Maxpath];
- char *num;
- long n;
- num = strrchr(dir, '/');
- if(num == 0)
- num = dir;
- else
- num++;
- snprint(buf, sizeof(buf), "reject %s %s", num, cause);
- n = strlen(buf);
- if(write(ctl, buf, n) != n)
- return -1;
- return 0;
- }
- /*
- * perform the identity translation (in case we can't reach cs)
- */
- static int
- identtrans(char *netdir, char *addr, char *naddr, int na, char *file, int nf)
- {
- char proto[Maxpath];
- char *p;
- USED(nf);
- /* parse the protocol */
- strncpy(proto, addr, sizeof(proto));
- proto[sizeof(proto)-1] = 0;
- p = strchr(proto, '!');
- if(p)
- *p++ = 0;
- snprint(file, nf, "%s/%s/clone", netdir, proto);
- strncpy(naddr, p, na);
- naddr[na-1] = 0;
- return 1;
- }
- /*
- * call up the connection server and get a translation
- */
- static int
- nettrans(char *addr, char *naddr, int na, char *file, int nf)
- {
- int i, fd;
- char buf[Maxpath];
- char netdir[Maxpath];
- char *p, *p2;
- long n;
- /*
- * parse, get network directory
- */
- p = strchr(addr, '!');
- if(p == 0){
- werrstr("bad dial string: %s", addr);
- return -1;
- }
- if(*addr != '/'){
- strncpy(netdir, "/net", sizeof(netdir));
- netdir[sizeof(netdir) - 1] = 0;
- } else {
- for(p2 = p; *p2 != '/'; p2--)
- ;
- i = p2 - addr;
- if(i == 0 || i >= sizeof(netdir)){
- werrstr("bad dial string: %s", addr);
- return -1;
- }
- strncpy(netdir, addr, i);
- netdir[i] = 0;
- addr = p2 + 1;
- }
- /*
- * ask the connection server
- */
- snprint(buf, sizeof(buf), "%s/cs", netdir);
- fd = open(buf, ORDWR);
- if(fd < 0)
- return identtrans(netdir, addr, naddr, na, file, nf);
- if(write(fd, addr, strlen(addr)) < 0){
- close(fd);
- return -1;
- }
- seek(fd, 0, 0);
- n = read(fd, buf, sizeof(buf)-1);
- close(fd);
- if(n <= 0)
- return -1;
- buf[n] = 0;
- /*
- * parse the reply
- */
- p = strchr(buf, ' ');
- if(p == 0)
- return -1;
- *p++ = 0;
- strncpy(naddr, p, na);
- naddr[na-1] = 0;
- if(buf[0] == '/'){
- p = strchr(buf+1, '/');
- if(p == nil)
- p = buf;
- else
- p++;
- }
- snprint(file, nf, "%s/%s", netdir, p);
- return 0;
- }
|