summaryrefslogtreecommitdiff
path: root/sys/src/cmd/vnc/proto.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/vnc/proto.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/vnc/proto.c')
-rwxr-xr-xsys/src/cmd/vnc/proto.c294
1 files changed, 294 insertions, 0 deletions
diff --git a/sys/src/cmd/vnc/proto.c b/sys/src/cmd/vnc/proto.c
new file mode 100755
index 000000000..277525034
--- /dev/null
+++ b/sys/src/cmd/vnc/proto.c
@@ -0,0 +1,294 @@
+#include "vnc.h"
+
+#define SHORT(p) (((p)[0]<<8)|((p)[1]))
+#define LONG(p) ((SHORT(p)<<16)|SHORT(p+2))
+
+uchar zero[64];
+
+Vnc*
+vncinit(int fd, int cfd, Vnc *v)
+{
+ if(v == nil)
+ v = mallocz(sizeof(*v), 1);
+ Binit(&v->in, fd, OREAD);
+ Binit(&v->out, fd, OWRITE);
+ v->datafd = fd;
+ v->ctlfd = cfd;
+ return v;
+}
+
+void
+vncterm(Vnc *v)
+{
+ Bterm(&v->out);
+ Bterm(&v->in);
+}
+
+void
+vncflush(Vnc *v)
+{
+ if(Bflush(&v->out) < 0){
+ if(verbose > 1)
+ fprint(2, "hungup while sending flush: %r\n");
+ vnchungup(v);
+ }
+}
+
+uchar
+vncrdchar(Vnc *v)
+{
+ uchar buf[1];
+
+ vncrdbytes(v, buf, 1);
+ return buf[0];
+}
+
+ushort
+vncrdshort(Vnc *v)
+{
+ uchar buf[2];
+
+ vncrdbytes(v, buf, 2);
+ return SHORT(buf);
+}
+
+ulong
+vncrdlong(Vnc *v)
+{
+ uchar buf[4];
+
+ vncrdbytes(v, buf, 4);
+ return LONG(buf);
+}
+
+Point
+vncrdpoint(Vnc *v)
+{
+ Point p;
+
+ p.x = vncrdshort(v);
+ p.y = vncrdshort(v);
+ return p;
+}
+
+Rectangle
+vncrdrect(Vnc *v)
+{
+ Rectangle r;
+
+ r.min.x = vncrdshort(v);
+ r.min.y = vncrdshort(v);
+ r.max.x = r.min.x + vncrdshort(v);
+ r.max.y = r.min.y + vncrdshort(v);
+ return r;
+}
+
+Rectangle
+vncrdcorect(Vnc *v)
+{
+ Rectangle r;
+
+ r.min.x = vncrdchar(v);
+ r.min.y = vncrdchar(v);
+ r.max.x = r.min.x + vncrdchar(v);
+ r.max.y = r.min.y + vncrdchar(v);
+ return r;
+}
+
+void
+vncrdbytes(Vnc *v, void *a, int n)
+{
+ if(Bread(&v->in, a, n) != n){
+ if(verbose > 1)
+ fprint(2, "hungup while reading\n");
+ vnchungup(v);
+ }
+}
+
+Pixfmt
+vncrdpixfmt(Vnc *v)
+{
+ Pixfmt fmt;
+ uchar pad[3];
+
+ fmt.bpp = vncrdchar(v);
+ fmt.depth = vncrdchar(v);
+ fmt.bigendian = vncrdchar(v);
+ fmt.truecolor = vncrdchar(v);
+ fmt.red.max = vncrdshort(v);
+ fmt.green.max = vncrdshort(v);
+ fmt.blue.max = vncrdshort(v);
+ fmt.red.shift = vncrdchar(v);
+ fmt.green.shift = vncrdchar(v);
+ fmt.blue.shift = vncrdchar(v);
+ vncrdbytes(v, pad, 3);
+ return fmt;
+}
+
+char*
+vncrdstring(Vnc *v)
+{
+ ulong len;
+ char *s;
+
+ len = vncrdlong(v);
+ s = malloc(len+1);
+ assert(s != nil);
+
+ vncrdbytes(v, s, len);
+ s[len] = '\0';
+ return s;
+}
+
+/*
+ * on the server side of the negotiation protocol, we read
+ * the client response and then run the negotiated function.
+ * in some cases (e.g., TLS) the negotiated function needs to
+ * use v->datafd directly and be sure that no data has been
+ * buffered away in the Bio. since we know the client is waiting
+ * for our response, it won't have sent any until we respond.
+ * thus we read the response with vncrdstringx, which goes
+ * behind bio's back.
+ */
+char*
+vncrdstringx(Vnc *v)
+{
+ char tmp[4];
+ char *s;
+ ulong len;
+
+ assert(Bbuffered(&v->in) == 0);
+ if(readn(v->datafd, tmp, 4) != 4){
+ fprint(2, "cannot rdstringx: %r");
+ vnchungup(v);
+ }
+ len = LONG(tmp);
+ s = malloc(len+1);
+ assert(s != nil);
+ if(readn(v->datafd, s, len) != len){
+ fprint(2, "cannot rdstringx len %lud: %r", len);
+ vnchungup(v);
+ }
+ s[len] = '\0';
+ return s;
+}
+
+void
+vncwrstring(Vnc *v, char *s)
+{
+ ulong len;
+
+ len = strlen(s);
+ vncwrlong(v, len);
+ vncwrbytes(v, s, len);
+}
+
+void
+vncwrbytes(Vnc *v, void *a, int n)
+{
+ if(Bwrite(&v->out, a, n) < 0){
+ if(verbose > 1)
+ fprint(2, "hungup while writing bytes\n");
+ vnchungup(v);
+ }
+}
+
+void
+vncwrlong(Vnc *v, ulong u)
+{
+ uchar buf[4];
+
+ buf[0] = u>>24;
+ buf[1] = u>>16;
+ buf[2] = u>>8;
+ buf[3] = u;
+ vncwrbytes(v, buf, 4);
+}
+
+void
+vncwrshort(Vnc *v, ushort u)
+{
+ uchar buf[2];
+
+ buf[0] = u>>8;
+ buf[1] = u;
+ vncwrbytes(v, buf, 2);
+}
+
+void
+vncwrchar(Vnc *v, uchar c)
+{
+ vncwrbytes(v, &c, 1);
+}
+
+void
+vncwrpixfmt(Vnc *v, Pixfmt *fmt)
+{
+ vncwrchar(v, fmt->bpp);
+ vncwrchar(v, fmt->depth);
+ vncwrchar(v, fmt->bigendian);
+ vncwrchar(v, fmt->truecolor);
+ vncwrshort(v, fmt->red.max);
+ vncwrshort(v, fmt->green.max);
+ vncwrshort(v, fmt->blue.max);
+ vncwrchar(v, fmt->red.shift);
+ vncwrchar(v, fmt->green.shift);
+ vncwrchar(v, fmt->blue.shift);
+ vncwrbytes(v, zero, 3);
+}
+
+void
+vncwrrect(Vnc *v, Rectangle r)
+{
+ vncwrshort(v, r.min.x);
+ vncwrshort(v, r.min.y);
+ vncwrshort(v, r.max.x-r.min.x);
+ vncwrshort(v, r.max.y-r.min.y);
+}
+
+void
+vncwrpoint(Vnc *v, Point p)
+{
+ vncwrshort(v, p.x);
+ vncwrshort(v, p.y);
+}
+
+void
+vnclock(Vnc *v)
+{
+ qlock(v);
+}
+
+void
+vncunlock(Vnc *v)
+{
+ qunlock(v);
+}
+
+void
+hexdump(void *a, int n)
+{
+ uchar *p, *ep;
+
+ p = a;
+ ep = p+n;
+
+ for(; p<ep; p++)
+ print("%.2ux ", *p);
+ print("\n");
+}
+
+void
+vncgobble(Vnc *v, long n)
+{
+ uchar buf[8192];
+ long m;
+
+ while(n > 0){
+ m = n;
+ if(m > sizeof(buf))
+ m = sizeof(buf);
+ vncrdbytes(v, buf, m);
+ n -= m;
+ }
+}