VMM: SMP guest (XCC)
[akaros.git] / user / iplib / announce.c
old mode 100755 (executable)
new mode 100644 (file)
index 53a0913..78e846e
@@ -1,4 +1,4 @@
-/* 
+/*
  * This file is part of the UCB release of Plan 9. It is subject to the license
  * terms in the LICENSE file found in the top-level directory of this
  * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  */
 #include <stdlib.h>
 
-#include <stdio.h>
 #include <fcntl.h>
+#include <iplib/iplib.h>
 #include <parlib/parlib.h>
-#include <unistd.h>
 #include <signal.h>
-#include <iplib/iplib.h>
+#include <stdio.h>
+#include <unistd.h>
 
-static int     nettrans(char*, char*, int na, char*, int);
+static int nettrans(char *, char *, int na, char *, int);
 
-enum
-{
-       Maxpath=        256,
+enum {
+       Maxpath = 256,
 };
 
-/*
- *  announce a network service.
- */
-int
-announce(char *addr, char *dir)
+/* Helper, given a net directory (translated from an addr/dialstring) by
+ * nettrans), clones a conversation, returns the ctl, and optionally fills in
+ * dir with the path of the directory (e.g. /net/tcp/1/).
+ *
+ * Returns the ctl FD, or -1 on error.  err_func is the function name to print
+ * for error output. */
+static int __clone9(char *netdir, char *dir, char *err_func, int flags)
 {
        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
-        */
+       /* get a control channel */
        ctl = open(netdir, O_RDWR);
-       if(ctl<0){
-               fprintf(stderr,"announce opening %s: %r\n", netdir);
+       if (ctl < 0) {
+               fprintf(stderr, "%s opening %s: %r\n", err_func, netdir);
                return -1;
        }
        cp = strrchr(netdir, '/');
-       if(cp == NULL){
-               fprintf(stderr,"announce arg format %s\n", netdir);
+       if (cp == NULL) {
+               fprintf(stderr, "%s arg format %s\n", err_func, netdir);
                close(ctl);
                return -1;
        }
        *cp = 0;
 
-       /*
-        *  find out which line we have
-        */
+       /* find out which line we have */
        n = snprintf(buf, sizeof(buf), "%s/", netdir);
-       m = read(ctl, &buf[n], sizeof(buf)-n-1);
-       if(m <= 0){
-               fprintf(stderr,"announce reading %s: %r\n", netdir);
+       m = read(ctl, &buf[n], sizeof(buf) - n - 1);
+       if (m <= 0) {
+               fprintf(stderr, "%s reading %s: %r\n", err_func, netdir);
                close(ctl);
                return -1;
        }
-       buf[n+m] = 0;
+       buf[n + m] = 0;
+
+       /* return directory etc. */
+       if (dir) {
+               strncpy(dir, buf, NETPATHLEN);
+               dir[NETPATHLEN - 1] = 0;
+       }
+       return ctl;
+}
+
+/* Clones a new network connection for a given dialstring (e.g. tcp!*!22). */
+int clone9(char *addr, char *dir, int flags)
+{
+       char netdir[Maxpath];
+       char naddr[Maxpath];
+
+       if (nettrans(addr, naddr, sizeof(naddr), netdir, sizeof(netdir)) < 0)
+               return -1;
+       return __clone9(addr, dir, "clone", flags);
+}
+
+/*
+ *  announce a network service.
+ */
+int announce9(char *addr, char *dir, int flags)
+{
+       int ctl, n;
+       char buf[Maxpath];
+       char netdir[Maxpath];
+       char naddr[Maxpath];
+
+       /*
+        *  translate the address
+        */
+       if (nettrans(addr, naddr, sizeof(naddr), netdir, sizeof(netdir)) < 0)
+               return -1;
+
+       ctl = __clone9(netdir, dir, "announce", flags);
+       if (ctl < 0)
+               return -1;
 
        /*
         *  make the call
         */
-       n = snprintf(buf2, sizeof(buf2), "announce %s", naddr);
-       if(write(ctl, buf2, n)!=n){
-               fprintf(stderr,"announce writing %s: %r\n", netdir);
+       n = snprintf(buf, sizeof(buf), "announce %s", naddr);
+       if (write(ctl, buf, n) != n) {
+               fprintf(stderr, "announce writing %s: %r\n", netdir);
                close(ctl);
                return -1;
        }
 
-       /*
-        *  return directory etc.
-        */
-       if(dir){
-               strncpy(dir, buf, NETPATHLEN);
-               dir[NETPATHLEN-1] = 0;
+       return ctl;
+}
+
+/* Gets a conversation and bypasses the protocol layer */
+int bypass9(char *addr, char *conv_dir, int flags)
+{
+       int ctl, n;
+       char buf[Maxpath];
+       char netdir[Maxpath];
+       char naddr[Maxpath];
+
+       if (nettrans(addr, naddr, sizeof(naddr), netdir, sizeof(netdir)) < 0)
+               return -1;
+       ctl = __clone9(netdir, conv_dir, "bypass", flags);
+       if (ctl < 0)
+               return -1;
+       n = snprintf(buf, sizeof(buf), "bypass %s", naddr);
+       if (write(ctl, buf, n) != n) {
+               fprintf(stderr, "bypass writing %s: %r\n", netdir);
+               close(ctl);
+               return -1;
        }
        return ctl;
 }
@@ -92,8 +134,7 @@ announce(char *addr, char *dir)
 /*
  *  listen for an incoming call
  */
-int
-listen(char *dir, char *newdir)
+int listen9(char *dir, char *newdir, int flags)
 {
        int ctl, n, m;
        char buf[Maxpath];
@@ -103,10 +144,10 @@ listen(char *dir, char *newdir)
         *  open listen, wait for a call
         */
        snprintf(buf, sizeof(buf), "%s/listen", dir);
-       ctl = open(buf, O_RDWR);
-       if(ctl < 0){
+       ctl = open(buf, O_RDWR | (flags & O_NONBLOCK));
+       if (ctl < 0) {
                if ((errno != EAGAIN) && (errno != EWOULDBLOCK))
-                       fprintf(stderr,"listen opening %s: %r\n", buf);
+                       fprintf(stderr, "listen opening %s: %r\n", buf);
                return -1;
        }
 
@@ -116,50 +157,49 @@ listen(char *dir, char *newdir)
        strncpy(buf, dir, sizeof(buf) - 1);
        buf[sizeof(buf) - 1] = 0;
        cp = strrchr(buf, '/');
-       if(cp == NULL){
+       if (cp == NULL) {
                close(ctl);
-               fprintf(stderr,"listen arg format %s\n", dir);
+               fprintf(stderr, "listen arg format %s\n", dir);
                return -1;
        }
        *++cp = 0;
-       n = cp-buf;
+       n = cp - buf;
        m = read(ctl, cp, sizeof(buf) - n - 1);
-       if(m <= 0){
+       if (m <= 0) {
                close(ctl);
-               fprintf(stderr,"listen reading %s/listen: %r\n", dir);
+               fprintf(stderr, "listen reading %s/listen: %r\n", dir);
                return -1;
        }
-       buf[n+m] = 0;
+       buf[n + m] = 0;
 
        /*
         *  return directory etc.
         */
-       if(newdir){
+       if (newdir) {
                strncpy(newdir, buf, NETPATHLEN);
-               newdir[NETPATHLEN-1] = 0;
+               newdir[NETPATHLEN - 1] = 0;
        }
        return ctl;
-
 }
 
 /*
  *  accept a call, return an fd to the open data file
  */
-int
-accept(int ctl, char *dir)
+int accept9(int ctl, char *dir)
 {
        char buf[Maxpath];
        char *num;
        long n;
 
        num = strrchr(dir, '/');
-       if(num == NULL)
+       if (num == NULL)
                num = dir;
        else
                num++;
 
        n = snprintf(buf, sizeof(buf), "accept %s", num);
-       write(ctl, buf, n); /* ignore return value, network might not need accepts */
+       /* ignore return value, network might not need accepts */
+       write(ctl, buf, n);
 
        snprintf(buf, sizeof(buf), "%s/data", dir);
        return open(buf, O_RDWR);
@@ -168,21 +208,20 @@ accept(int ctl, char *dir)
 /*
  *  reject a call, tell device the reason for the rejection
  */
-int
-reject(int ctl, char *dir, char *cause)
+int reject9(int ctl, char *dir, char *cause)
 {
        char buf[Maxpath];
        char *num;
        long n;
 
        num = strrchr(dir, '/');
-       if(num == 0)
+       if (num == 0)
                num = dir;
        else
                num++;
        snprintf(buf, sizeof(buf), "reject %s %s", num, cause);
        n = strlen(buf);
-       if(write(ctl, buf, n) != n)
+       if (write(ctl, buf, n) != n)
                return -1;
        return 0;
 }
@@ -190,22 +229,22 @@ reject(int ctl, char *dir, char *cause)
 /*
  *  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)
+static int identtrans(char *netdir, char *addr, char *naddr, int na, char *file,
+                      int nf)
 {
        char proto[Maxpath];
        char *p;
 
        /* parse the protocol */
        strncpy(proto, addr, sizeof(proto));
-       proto[sizeof(proto)-1] = 0;
+       proto[sizeof(proto) - 1] = 0;
        p = strchr(proto, '!');
-       if(p)
+       if (p)
                *p++ = 0;
 
        snprintf(file, nf, "%s/%s/clone", netdir, proto);
        strncpy(naddr, p, na);
-       naddr[na-1] = 0;
+       naddr[na - 1] = 0;
 
        return 1;
 }
@@ -213,8 +252,7 @@ identtrans(char *netdir, char *addr, char *naddr, int na, char *file, int nf)
 /*
  *  call up the connection server and get a translation
  */
-static int
-nettrans(char *addr, char *naddr, int na, char *file, int nf)
+static int nettrans(char *addr, char *naddr, int na, char *file, int nf)
 {
        int i, fd;
        char buf[Maxpath];
@@ -226,19 +264,19 @@ nettrans(char *addr, char *naddr, int na, char *file, int nf)
         *  parse, get network directory
         */
        p = strchr(addr, '!');
-       if(p == 0){
-               fprintf(stderr,"bad dial string: %s\n", addr);
+       if (p == 0) {
+               fprintf(stderr, "bad dial string: %s\n", addr);
                return -1;
        }
-       if(*addr != '/'){
+       if (*addr != '/') {
                strncpy(netdir, "/net", sizeof(netdir));
                netdir[sizeof(netdir) - 1] = 0;
        } else {
-               for(p2 = p; *p2 != '/'; p2--)
+               for (p2 = p; *p2 != '/'; p2--)
                        ;
                i = p2 - addr;
-               if(i == 0 || i >= sizeof(netdir)){
-                       fprintf(stderr,"bad dial string: %s\n", addr);
+               if (i == 0 || i >= sizeof(netdir)) {
+                       fprintf(stderr, "bad dial string: %s\n", addr);
                        return -1;
                }
                strncpy(netdir, addr, i);
@@ -251,16 +289,16 @@ nettrans(char *addr, char *naddr, int na, char *file, int nf)
         */
        snprintf(buf, sizeof(buf), "%s/cs", netdir);
        fd = open(buf, O_RDWR);
-       if(fd < 0)
+       if (fd < 0)
                return identtrans(netdir, addr, naddr, na, file, nf);
-       if(write(fd, addr, strlen(addr)) < 0){
+       if (write(fd, addr, strlen(addr)) < 0) {
                close(fd);
                return -1;
        }
        lseek(fd, 0, 0);
-       n = read(fd, buf, sizeof(buf)-1);
+       n = read(fd, buf, sizeof(buf) - 1);
        close(fd);
-       if(n <= 0)
+       if (n <= 0)
                return -1;
        buf[n] = 0;
 
@@ -268,19 +306,53 @@ nettrans(char *addr, char *naddr, int na, char *file, int nf)
         *  parse the reply
         */
        p = strchr(buf, ' ');
-       if(p == 0)
+       if (p == 0)
                return -1;
        *p++ = 0;
        strncpy(naddr, p, na);
-       naddr[na-1] = 0;
+       naddr[na - 1] = 0;
 
-       if(buf[0] == '/'){
-               p = strchr(buf+1, '/');
-               if(p == NULL)
+       if (buf[0] == '/') {
+               p = strchr(buf + 1, '/');
+               if (p == NULL)
                        p = buf;
-               else 
+               else
                        p++;
        }
        snprintf(file, nf, "%s/%s", netdir, p);
        return 0;
 }
+
+int open_data_fd9(char *conv_dir, int flags)
+{
+       char path_buf[MAX_PATH_LEN];
+
+       snprintf(path_buf, sizeof(path_buf), "%s/data", conv_dir);
+       return open(path_buf, O_RDWR | flags);
+}
+
+/* Given a conversation directory, return the "remote" or "local" port, passed
+ * as the string which.  Returns the port via *port and TRUE on success. */
+bool get_port9(char *conv_dir, char *which, uint16_t *port)
+{
+       /* We don't have a MAX_DIALSTRING, but MAX_PATH_LEN should be enough. */
+       char buf[MAX_PATH_LEN];
+       int local_fd;
+       int ret;
+       char *p;
+
+       snprintf(buf, sizeof(buf), "%s/%s", conv_dir, which);
+       local_fd = open(buf, O_RDONLY);
+       if (local_fd < 0)
+               return FALSE;
+       ret = read(local_fd, buf, sizeof(buf));
+       close(local_fd);
+       if (ret <= 0)
+               return FALSE;
+       p = strrchr(buf, '!');
+       if (!p)
+               return FALSE;
+       p++;
+       *port = atoi(p);
+       return TRUE;
+}