code: drawterm

Download patch

ref: 673e3de9a2f59dbac9a845b2f28363b2bb9f0041
parent: b52598178143b1c4a154caec87037c3a717c3ddd
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Mon Mar 7 16:01:28 EST 2016

implement aan support for rcpu

--- a/Makefile
+++ b/Makefile
@@ -5,6 +5,7 @@
 OFILES=\
 	main.$O\
 	cpu.$O\
+	aan.$O\
 	readcons.$O\
 	secstore.$O\
 	latin1.$O\
--- /dev/null
+++ b/aan.c
@@ -1,0 +1,204 @@
+#include <u.h>
+#include <libc.h>
+#include <fcall.h>
+#include "drawterm.h"
+
+enum {
+	Hdrsz = 3*4,
+	Bufsize = 8*1024,
+};
+
+typedef struct Hdr Hdr;
+typedef struct Buf Buf;
+typedef struct Client Client;
+
+struct Hdr {
+	uchar	nb[4];		// Number of data bytes in this message
+	uchar	msg[4];		// Message number
+	uchar	acked[4];	// Number of messages acked
+};
+
+struct Buf {
+	Hdr	hdr;
+	uchar	buf[Bufsize];
+
+	Buf	*next;
+};
+
+struct Client {
+	QLock	lk;
+
+	char	*addr;
+	int	netfd;
+	int	pipefd;
+
+	int	reader;
+	int	writer;
+	int	syncer;
+
+	long	inmsg;
+	long	outmsg;
+
+	Buf	*unackedhead;
+	Buf	**unackedtail;
+};
+
+static void
+reconnect(Client *c)
+{
+	Buf *b;
+	int n;
+
+	qlock(&c->lk);
+Again:
+	for(;;){
+		if(c->netfd >= 0){
+			close(c->netfd);
+			c->netfd = -1;
+		}
+		if((c->netfd = dial(c->addr,nil,nil,nil)) >= 0)
+			break;
+		sleep(1000);
+	}
+	for(b = c->unackedhead; b != nil; b = b->next){
+		n = GBIT32(b->hdr.nb);
+		PBIT32(b->hdr.acked, c->inmsg);
+		if(write(c->netfd, &b->hdr, Hdrsz) != Hdrsz
+		|| write(c->netfd, b->buf, n) != n){
+			print("write error: %r\n");
+			goto Again;
+		}
+	}
+	qunlock(&c->lk);
+}
+
+static void
+aanwriter(void *arg)
+{
+	Client *c = (Client*)arg;
+	Buf *b;
+	int n;
+	long m;
+
+	for(;;){
+		b = malloc(sizeof(Buf));
+		if(b == nil)
+			break;
+		if((n = read(c->pipefd, b->buf, Bufsize)) < 0){
+			free(b);
+			break;
+		}
+
+		qlock(&c->lk);
+		m = c->outmsg++;
+		PBIT32(b->hdr.nb, n);
+		PBIT32(b->hdr.msg, m);
+		PBIT32(b->hdr.acked, c->inmsg);
+
+		b->next = nil;
+		if(c->unackedhead == nil)
+			c->unackedtail = &c->unackedhead;
+		*c->unackedtail = b;
+		c->unackedtail = &b->next;
+
+		if(c->netfd < 0
+		|| write(c->netfd, &b->hdr, Hdrsz) != Hdrsz
+		|| write(c->netfd, b->buf, n) != n){
+			qunlock(&c->lk);
+			break;
+		}
+		qunlock(&c->lk);
+
+		if(n == 0)
+			break;
+	}
+	close(c->pipefd);
+	c->pipefd = -1;
+}
+
+static void
+aansyncer(void *arg)
+{
+	Client *c = (Client*)arg;
+	Hdr hdr;
+
+	for(;;){
+		sleep(4000);
+		qlock(&c->lk);
+		if(c->netfd >= 0){
+			PBIT32(hdr.nb, 0);
+			PBIT32(hdr.acked, c->inmsg);
+			PBIT32(hdr.msg, -1);
+			write(c->netfd, &hdr, Hdrsz);
+		}
+		qunlock(&c->lk);
+	}
+}
+
+static void
+aanreader(void *arg)
+{
+	Client *c = (Client*)arg;
+	Buf *b, *x, **l;
+	long a, m;
+	int n;
+
+Restart:
+	b = mallocz(sizeof(Buf), 1);
+	for(;;){
+		if(readn(c->netfd, &b->hdr, Hdrsz) != Hdrsz)
+			break;
+		a = GBIT32(b->hdr.acked);
+		m = GBIT32(b->hdr.msg);
+		n = GBIT32(b->hdr.nb);
+		if(n > Bufsize)
+			break;
+
+		qlock(&c->lk);
+		l = &c->unackedhead;
+		for(x = c->unackedhead; x != nil; x = *l){
+			if(a >= GBIT32(x->hdr.msg)){
+				if((*l = x->next) == nil)
+					c->unackedtail = l;
+				free(x);
+			} else {
+				l = &x->next;
+			}
+		}
+		qunlock(&c->lk);
+
+		if(readn(c->netfd, b->buf, n) != n)
+			break;
+		if(m < c->inmsg)
+			continue;
+		c->inmsg++;
+		if(c->pipefd < 0)
+			return;
+		write(c->pipefd, b->buf, n);
+	}
+	free(b);
+	reconnect(c);
+	goto Restart;
+}
+
+int
+aanclient(char *addr)
+{
+	Client *c;
+	int pfd[2];
+
+	if(pipe(pfd) < 0)
+		sysfatal("pipe: %r");
+
+	c = mallocz(sizeof(Client), 1);
+	c->addr = addr;
+	c->netfd = -1;
+	c->pipefd = pfd[1];
+	c->inmsg = 0;
+	c->outmsg = 0;
+	reconnect(c);
+	c->writer = kproc("aanwriter", aanwriter, c);
+	c->reader = kproc("aanreader", aanreader, c);
+	c->syncer = kproc("aansyncer", aansyncer, c);
+	return pfd[0];
+}
--- a/cpu.c
+++ b/cpu.c
@@ -40,6 +40,7 @@
 static int	p9auth(int);
 
 char *authserver;
+int aanfilter;
 
 void
 exits(char *s)
@@ -75,6 +76,79 @@
 	return 0;
 }
 
+/*
+ * p9any authentication followed by tls-psk encryption
+ */
+static int
+p9authtls(int fd)
+{
+	AuthInfo *ai;
+	TLSconn *conn;
+
+	ai = p9any(fd);
+	if(ai == nil)
+		fatal(1, "can't authenticate");
+
+	conn = mallocz(sizeof(TLSconn), 1);
+	conn->pskID = "p9secret";
+	conn->psk = ai->secret;
+	conn->psklen = ai->nsecret;
+
+	fd = tlsClient(fd, conn);
+	if(fd < 0)
+		fatal(1, "tlsClient");
+
+	auth_freeAI(ai);
+	free(conn->sessionID);
+	free(conn);
+
+	return fd;
+}
+
+static int
+startaan(char *host, int fd)
+{
+	static char script[] =
+"~ $#netdir 1 || netdir=/net/tcp/clone\n"
+"netdir=`{basename -d $netdir} || exit\n"
+"<>$netdir/clone {\n"
+"	netdir=$netdir/`{read} || exit\n"
+"	>[3] $netdir/ctl {\n"
+"		echo -n 'announce *!0' >[1=3]\n"
+"		echo `{cat $netdir/local} || exit\n"
+"		bind '#|' /mnt/aan || exit\n"
+"		exec aan $netdir <>/mnt/aan/data1 >[1=0] >[2]/dev/null &\n"
+"	}\n"
+"}\n"
+"<>/mnt/aan/data >[1=0] >[2]/dev/null {\n"
+"	rfork n\n"
+"	fn server {\n"
+"		echo -n aanserver $netdir >/proc/$pid/args\n"
+"		. <{n=`{read} && ! ~ $#n 0 && read -c $n} >[2=1]\n"
+"	}\n"
+"	rm -f /env/^'fn#aanserver'\n"
+"	exec tlssrv -A /bin/rc -c server\n"
+"	exit\n"
+"}\n";
+	char buf[128], *p, *na;
+	int n;
+
+	if(fprint(fd, "%7ld\n%s", strlen(script), script) < 0)
+		fatal(1, "sending aan script");
+	n = read(fd, buf, sizeof(buf)-1);
+	close(fd);
+
+	while(n > 0 && buf[n-1] == '\n') n--;
+	if(n <= 0) return -1;
+	buf[n] = 0;
+	if((p = strrchr(buf, '!')) != nil)
+		na = strdup(netmkaddr(host, "tcp", p+1));
+	else
+		na = strdup(buf);
+
+	return aanclient(na);
+}
+
 void
 rcpu(char *host)
 {
@@ -84,13 +158,11 @@
 "</dev/cons >/dev/cons >[2=1] aux/kbdfs -dq -m /mnt/term/dev\n"
 "bind -q /mnt/term/dev/cons /dev/cons\n"
 "</dev/cons >/dev/cons >[2=1] service=cpu exec rc -li\n";
-	AuthInfo *ai;
-	TLSconn *conn;
 	char *na;
 	int fd;
 
 	na = netmkaddr(host, "tcp", "17019");
-	if((fd = dial(na, 0, 0, 0)) < 0)
+	if((fd = dial(na, nil, nil, nil)) < 0)
 		return;
 
 	/* provide /dev/kbd for kbdfs */
@@ -97,21 +169,15 @@
 	if(bind("#b", "/dev", MAFTER) < 0)
 		panic("bind #b: %r");
 
-	ai = p9any(fd);
-	if(ai == nil)
-		fatal(1, "can't authenticate");
+	fd = p9authtls(fd);
+	if(aanfilter){
+		fd = startaan(host, fd);
+		if(fd < 0)
+			fatal(1, "startaan");
+		fd = p9authtls(fd);
+	}
+	memset(secstorebuf, 0, sizeof(secstorebuf));	/* forget secstore secrets */
 
-	conn = mallocz(sizeof(TLSconn), 1);
-	conn->pskID = "p9secret";
-	conn->psk = ai->secret;
-	conn->psklen = ai->nsecret;
-
-	fd = tlsClient(fd, conn);
-	if(fd < 0)
-		fatal(1, "tlsClient");
-
-	auth_freeAI(ai);
-
 	if(fprint(fd, "%7ld\n%s", strlen(script), script) < 0)
 		fatal(1, "sending script");
 
@@ -140,6 +206,9 @@
 	authserver = getenv("auth");
 	system = getenv("cpu");
 	ARGBEGIN{
+	case 'p':
+		aanfilter = 1;
+		break;
 	case 'a':
 		authserver = EARGF(usage());
 		break;
@@ -353,6 +422,7 @@
 	AuthInfo *ai;
 
 	ai = p9any(fd);
+	memset(secstorebuf, 0, sizeof(secstorebuf));	/* forget secstore secrets */
 	if(ai == nil)
 		return -1;
 	if(ealgs == nil)
@@ -628,8 +698,6 @@
 
 	u = user;
 	pass = findkey(&u, tr.authdom, proto);
-	memset(secstorebuf, 0, sizeof(secstorebuf));	/* forget secstore secrets */
-
 	if(pass == nil)
 	again:
 		pass = getkey(u, tr.authdom, proto);
--- a/drawterm.h
+++ b/drawterm.h
@@ -12,3 +12,4 @@
 extern char *getuser(void);
 extern void cpumain(int, char**);
 extern char *estrdup(char*);
+extern int aanclient(char*);
--- a/kern/devpipe.c
+++ b/kern/devpipe.c
@@ -313,8 +313,6 @@
 	Pipe *p;
 
 	USED(offset);
-	if(!islo())
-		print("pipewrite hi %lux\n", getcallerpc(&c));
 
 	if(waserror()) {
 		/* avoid notes when pipe is a mounted queue */
--- a/main.c
+++ b/main.c
@@ -73,10 +73,14 @@
 char*
 getkey(char *user, char *dom, char *proto)
 {
-	char buf[1024];
+	char buf[1024], *key;
 
 	snprint(buf, sizeof buf, "%s@%s %s password", user, dom, proto);
-	return readcons(buf, nil, 1);
+	key = readcons(buf, nil, 1);
+	if(key != nil)
+		snprint(secstorebuf, sizeof(secstorebuf), "key proto=%q dom=%q user=%q !password=%q\n",
+			proto, dom, user, key);
+	return key;
 }
 
 char*