xref: /plan9/sys/src/cmd/vnc/proto.c (revision f8e525ac91e3a7fae3f104837a69862dc348aa81)
1*9a747e4fSDavid du Colombier #include "vnc.h"
2*9a747e4fSDavid du Colombier 
3*9a747e4fSDavid du Colombier #define SHORT(p) (((p)[0]<<8)|((p)[1]))
4*9a747e4fSDavid du Colombier #define LONG(p) ((SHORT(p)<<16)|SHORT(p+2))
5*9a747e4fSDavid du Colombier 
6*9a747e4fSDavid du Colombier uchar zero[64];
7*9a747e4fSDavid du Colombier 
8*9a747e4fSDavid du Colombier Vnc*
vncinit(int fd,int cfd,Vnc * v)9*9a747e4fSDavid du Colombier vncinit(int fd, int cfd, Vnc *v)
10*9a747e4fSDavid du Colombier {
11*9a747e4fSDavid du Colombier         if(v == nil)
12*9a747e4fSDavid du Colombier 		v = mallocz(sizeof(*v), 1);
13*9a747e4fSDavid du Colombier 	Binit(&v->in, fd, OREAD);
14*9a747e4fSDavid du Colombier 	Binit(&v->out, fd, OWRITE);
15*9a747e4fSDavid du Colombier 	v->datafd = fd;
16*9a747e4fSDavid du Colombier 	v->ctlfd = cfd;
17*9a747e4fSDavid du Colombier 	return v;
18*9a747e4fSDavid du Colombier }
19*9a747e4fSDavid du Colombier 
20*9a747e4fSDavid du Colombier void
vncterm(Vnc * v)21*9a747e4fSDavid du Colombier vncterm(Vnc *v)
22*9a747e4fSDavid du Colombier {
23*9a747e4fSDavid du Colombier 	Bterm(&v->out);
24*9a747e4fSDavid du Colombier 	Bterm(&v->in);
25*9a747e4fSDavid du Colombier }
26*9a747e4fSDavid du Colombier 
27*9a747e4fSDavid du Colombier void
vncflush(Vnc * v)28*9a747e4fSDavid du Colombier vncflush(Vnc *v)
29*9a747e4fSDavid du Colombier {
30*9a747e4fSDavid du Colombier 	if(Bflush(&v->out) < 0){
31*9a747e4fSDavid du Colombier 		if(verbose > 1)
32*9a747e4fSDavid du Colombier 			fprint(2, "hungup while sending flush: %r\n");
33*9a747e4fSDavid du Colombier 		vnchungup(v);
34*9a747e4fSDavid du Colombier 	}
35*9a747e4fSDavid du Colombier }
36*9a747e4fSDavid du Colombier 
37*9a747e4fSDavid du Colombier uchar
vncrdchar(Vnc * v)38*9a747e4fSDavid du Colombier vncrdchar(Vnc *v)
39*9a747e4fSDavid du Colombier {
40*9a747e4fSDavid du Colombier 	uchar buf[1];
41*9a747e4fSDavid du Colombier 
42*9a747e4fSDavid du Colombier 	vncrdbytes(v, buf, 1);
43*9a747e4fSDavid du Colombier 	return buf[0];
44*9a747e4fSDavid du Colombier }
45*9a747e4fSDavid du Colombier 
46*9a747e4fSDavid du Colombier ushort
vncrdshort(Vnc * v)47*9a747e4fSDavid du Colombier vncrdshort(Vnc *v)
48*9a747e4fSDavid du Colombier {
49*9a747e4fSDavid du Colombier 	uchar buf[2];
50*9a747e4fSDavid du Colombier 
51*9a747e4fSDavid du Colombier 	vncrdbytes(v, buf, 2);
52*9a747e4fSDavid du Colombier 	return SHORT(buf);
53*9a747e4fSDavid du Colombier }
54*9a747e4fSDavid du Colombier 
55*9a747e4fSDavid du Colombier ulong
vncrdlong(Vnc * v)56*9a747e4fSDavid du Colombier vncrdlong(Vnc *v)
57*9a747e4fSDavid du Colombier {
58*9a747e4fSDavid du Colombier 	uchar buf[4];
59*9a747e4fSDavid du Colombier 
60*9a747e4fSDavid du Colombier 	vncrdbytes(v, buf, 4);
61*9a747e4fSDavid du Colombier 	return LONG(buf);
62*9a747e4fSDavid du Colombier }
63*9a747e4fSDavid du Colombier 
64*9a747e4fSDavid du Colombier Point
vncrdpoint(Vnc * v)65*9a747e4fSDavid du Colombier vncrdpoint(Vnc *v)
66*9a747e4fSDavid du Colombier {
67*9a747e4fSDavid du Colombier 	Point p;
68*9a747e4fSDavid du Colombier 
69*9a747e4fSDavid du Colombier 	p.x = vncrdshort(v);
70*9a747e4fSDavid du Colombier 	p.y = vncrdshort(v);
71*9a747e4fSDavid du Colombier 	return p;
72*9a747e4fSDavid du Colombier }
73*9a747e4fSDavid du Colombier 
74*9a747e4fSDavid du Colombier Rectangle
vncrdrect(Vnc * v)75*9a747e4fSDavid du Colombier vncrdrect(Vnc *v)
76*9a747e4fSDavid du Colombier {
77*9a747e4fSDavid du Colombier 	Rectangle r;
78*9a747e4fSDavid du Colombier 
79*9a747e4fSDavid du Colombier 	r.min.x = vncrdshort(v);
80*9a747e4fSDavid du Colombier 	r.min.y = vncrdshort(v);
81*9a747e4fSDavid du Colombier 	r.max.x = r.min.x + vncrdshort(v);
82*9a747e4fSDavid du Colombier 	r.max.y = r.min.y + vncrdshort(v);
83*9a747e4fSDavid du Colombier 	return r;
84*9a747e4fSDavid du Colombier }
85*9a747e4fSDavid du Colombier 
86*9a747e4fSDavid du Colombier Rectangle
vncrdcorect(Vnc * v)87*9a747e4fSDavid du Colombier vncrdcorect(Vnc *v)
88*9a747e4fSDavid du Colombier {
89*9a747e4fSDavid du Colombier 	Rectangle r;
90*9a747e4fSDavid du Colombier 
91*9a747e4fSDavid du Colombier 	r.min.x = vncrdchar(v);
92*9a747e4fSDavid du Colombier 	r.min.y = vncrdchar(v);
93*9a747e4fSDavid du Colombier 	r.max.x = r.min.x + vncrdchar(v);
94*9a747e4fSDavid du Colombier 	r.max.y = r.min.y + vncrdchar(v);
95*9a747e4fSDavid du Colombier 	return r;
96*9a747e4fSDavid du Colombier }
97*9a747e4fSDavid du Colombier 
98*9a747e4fSDavid du Colombier void
vncrdbytes(Vnc * v,void * a,int n)99*9a747e4fSDavid du Colombier vncrdbytes(Vnc *v, void *a, int n)
100*9a747e4fSDavid du Colombier {
101*9a747e4fSDavid du Colombier 	if(Bread(&v->in, a, n) != n){
102*9a747e4fSDavid du Colombier 		if(verbose > 1)
103*9a747e4fSDavid du Colombier 			fprint(2, "hungup while reading\n");
104*9a747e4fSDavid du Colombier 		vnchungup(v);
105*9a747e4fSDavid du Colombier 	}
106*9a747e4fSDavid du Colombier }
107*9a747e4fSDavid du Colombier 
108*9a747e4fSDavid du Colombier Pixfmt
vncrdpixfmt(Vnc * v)109*9a747e4fSDavid du Colombier vncrdpixfmt(Vnc *v)
110*9a747e4fSDavid du Colombier {
111*9a747e4fSDavid du Colombier 	Pixfmt fmt;
112*9a747e4fSDavid du Colombier 	uchar pad[3];
113*9a747e4fSDavid du Colombier 
114*9a747e4fSDavid du Colombier 	fmt.bpp = vncrdchar(v);
115*9a747e4fSDavid du Colombier 	fmt.depth = vncrdchar(v);
116*9a747e4fSDavid du Colombier 	fmt.bigendian = vncrdchar(v);
117*9a747e4fSDavid du Colombier 	fmt.truecolor = vncrdchar(v);
118*9a747e4fSDavid du Colombier 	fmt.red.max = vncrdshort(v);
119*9a747e4fSDavid du Colombier 	fmt.green.max = vncrdshort(v);
120*9a747e4fSDavid du Colombier 	fmt.blue.max = vncrdshort(v);
121*9a747e4fSDavid du Colombier 	fmt.red.shift = vncrdchar(v);
122*9a747e4fSDavid du Colombier 	fmt.green.shift = vncrdchar(v);
123*9a747e4fSDavid du Colombier 	fmt.blue.shift = vncrdchar(v);
124*9a747e4fSDavid du Colombier 	vncrdbytes(v, pad, 3);
125*9a747e4fSDavid du Colombier 	return fmt;
126*9a747e4fSDavid du Colombier }
127*9a747e4fSDavid du Colombier 
128*9a747e4fSDavid du Colombier char*
vncrdstring(Vnc * v)129*9a747e4fSDavid du Colombier vncrdstring(Vnc *v)
130*9a747e4fSDavid du Colombier {
131*9a747e4fSDavid du Colombier 	ulong len;
132*9a747e4fSDavid du Colombier 	char *s;
133*9a747e4fSDavid du Colombier 
134*9a747e4fSDavid du Colombier 	len = vncrdlong(v);
135*9a747e4fSDavid du Colombier 	s = malloc(len+1);
136*9a747e4fSDavid du Colombier 	assert(s != nil);
137*9a747e4fSDavid du Colombier 
138*9a747e4fSDavid du Colombier 	vncrdbytes(v, s, len);
139*9a747e4fSDavid du Colombier 	s[len] = '\0';
140*9a747e4fSDavid du Colombier 	return s;
141*9a747e4fSDavid du Colombier }
142*9a747e4fSDavid du Colombier 
143*9a747e4fSDavid du Colombier /*
144*9a747e4fSDavid du Colombier  * on the server side of the negotiation protocol, we read
145*9a747e4fSDavid du Colombier  * the client response and then run the negotiated function.
146*9a747e4fSDavid du Colombier  * in some cases (e.g., TLS) the negotiated function needs to
147*9a747e4fSDavid du Colombier  * use v->datafd directly and be sure that no data has been
148*9a747e4fSDavid du Colombier  * buffered away in the Bio.  since we know the client is waiting
149*9a747e4fSDavid du Colombier  * for our response, it won't have sent any until we respond.
150*9a747e4fSDavid du Colombier  * thus we read the response with vncrdstringx, which goes
151*9a747e4fSDavid du Colombier  * behind bio's back.
152*9a747e4fSDavid du Colombier  */
153*9a747e4fSDavid du Colombier char*
vncrdstringx(Vnc * v)154*9a747e4fSDavid du Colombier vncrdstringx(Vnc *v)
155*9a747e4fSDavid du Colombier {
156*9a747e4fSDavid du Colombier 	char tmp[4];
157*9a747e4fSDavid du Colombier 	char *s;
158*9a747e4fSDavid du Colombier 	ulong len;
159*9a747e4fSDavid du Colombier 
160*9a747e4fSDavid du Colombier 	assert(Bbuffered(&v->in) == 0);
161*9a747e4fSDavid du Colombier 	if(readn(v->datafd, tmp, 4) != 4){
162*9a747e4fSDavid du Colombier 		fprint(2, "cannot rdstringx: %r");
163*9a747e4fSDavid du Colombier 		vnchungup(v);
164*9a747e4fSDavid du Colombier 	}
165*9a747e4fSDavid du Colombier 	len = LONG(tmp);
166*9a747e4fSDavid du Colombier 	s = malloc(len+1);
167*9a747e4fSDavid du Colombier 	assert(s != nil);
168*9a747e4fSDavid du Colombier 	if(readn(v->datafd, s, len) != len){
169*9a747e4fSDavid du Colombier 		fprint(2, "cannot rdstringx len %lud: %r", len);
170*9a747e4fSDavid du Colombier 		vnchungup(v);
171*9a747e4fSDavid du Colombier 	}
172*9a747e4fSDavid du Colombier 	s[len] = '\0';
173*9a747e4fSDavid du Colombier 	return s;
174*9a747e4fSDavid du Colombier }
175*9a747e4fSDavid du Colombier 
176*9a747e4fSDavid du Colombier void
vncwrstring(Vnc * v,char * s)177*9a747e4fSDavid du Colombier vncwrstring(Vnc *v, char *s)
178*9a747e4fSDavid du Colombier {
179*9a747e4fSDavid du Colombier 	ulong len;
180*9a747e4fSDavid du Colombier 
181*9a747e4fSDavid du Colombier 	len = strlen(s);
182*9a747e4fSDavid du Colombier 	vncwrlong(v, len);
183*9a747e4fSDavid du Colombier 	vncwrbytes(v, s, len);
184*9a747e4fSDavid du Colombier }
185*9a747e4fSDavid du Colombier 
186*9a747e4fSDavid du Colombier void
vncwrbytes(Vnc * v,void * a,int n)187*9a747e4fSDavid du Colombier vncwrbytes(Vnc *v, void *a, int n)
188*9a747e4fSDavid du Colombier {
189*9a747e4fSDavid du Colombier 	if(Bwrite(&v->out, a, n) < 0){
190*9a747e4fSDavid du Colombier 		if(verbose > 1)
191*9a747e4fSDavid du Colombier 			fprint(2, "hungup while writing bytes\n");
192*9a747e4fSDavid du Colombier 		vnchungup(v);
193*9a747e4fSDavid du Colombier 	}
194*9a747e4fSDavid du Colombier }
195*9a747e4fSDavid du Colombier 
196*9a747e4fSDavid du Colombier void
vncwrlong(Vnc * v,ulong u)197*9a747e4fSDavid du Colombier vncwrlong(Vnc *v, ulong u)
198*9a747e4fSDavid du Colombier {
199*9a747e4fSDavid du Colombier 	uchar buf[4];
200*9a747e4fSDavid du Colombier 
201*9a747e4fSDavid du Colombier 	buf[0] = u>>24;
202*9a747e4fSDavid du Colombier 	buf[1] = u>>16;
203*9a747e4fSDavid du Colombier 	buf[2] = u>>8;
204*9a747e4fSDavid du Colombier 	buf[3] = u;
205*9a747e4fSDavid du Colombier 	vncwrbytes(v, buf, 4);
206*9a747e4fSDavid du Colombier }
207*9a747e4fSDavid du Colombier 
208*9a747e4fSDavid du Colombier void
vncwrshort(Vnc * v,ushort u)209*9a747e4fSDavid du Colombier vncwrshort(Vnc *v, ushort u)
210*9a747e4fSDavid du Colombier {
211*9a747e4fSDavid du Colombier 	uchar buf[2];
212*9a747e4fSDavid du Colombier 
213*9a747e4fSDavid du Colombier 	buf[0] = u>>8;
214*9a747e4fSDavid du Colombier 	buf[1] = u;
215*9a747e4fSDavid du Colombier 	vncwrbytes(v, buf, 2);
216*9a747e4fSDavid du Colombier }
217*9a747e4fSDavid du Colombier 
218*9a747e4fSDavid du Colombier void
vncwrchar(Vnc * v,uchar c)219*9a747e4fSDavid du Colombier vncwrchar(Vnc *v, uchar c)
220*9a747e4fSDavid du Colombier {
221*9a747e4fSDavid du Colombier 	vncwrbytes(v, &c, 1);
222*9a747e4fSDavid du Colombier }
223*9a747e4fSDavid du Colombier 
224*9a747e4fSDavid du Colombier void
vncwrpixfmt(Vnc * v,Pixfmt * fmt)225*9a747e4fSDavid du Colombier vncwrpixfmt(Vnc *v, Pixfmt *fmt)
226*9a747e4fSDavid du Colombier {
227*9a747e4fSDavid du Colombier 	vncwrchar(v, fmt->bpp);
228*9a747e4fSDavid du Colombier 	vncwrchar(v, fmt->depth);
229*9a747e4fSDavid du Colombier 	vncwrchar(v, fmt->bigendian);
230*9a747e4fSDavid du Colombier 	vncwrchar(v, fmt->truecolor);
231*9a747e4fSDavid du Colombier 	vncwrshort(v, fmt->red.max);
232*9a747e4fSDavid du Colombier 	vncwrshort(v, fmt->green.max);
233*9a747e4fSDavid du Colombier 	vncwrshort(v, fmt->blue.max);
234*9a747e4fSDavid du Colombier 	vncwrchar(v, fmt->red.shift);
235*9a747e4fSDavid du Colombier 	vncwrchar(v, fmt->green.shift);
236*9a747e4fSDavid du Colombier 	vncwrchar(v, fmt->blue.shift);
237*9a747e4fSDavid du Colombier 	vncwrbytes(v, zero, 3);
238*9a747e4fSDavid du Colombier }
239*9a747e4fSDavid du Colombier 
240*9a747e4fSDavid du Colombier void
vncwrrect(Vnc * v,Rectangle r)241*9a747e4fSDavid du Colombier vncwrrect(Vnc *v, Rectangle r)
242*9a747e4fSDavid du Colombier {
243*9a747e4fSDavid du Colombier 	vncwrshort(v, r.min.x);
244*9a747e4fSDavid du Colombier 	vncwrshort(v, r.min.y);
245*9a747e4fSDavid du Colombier 	vncwrshort(v, r.max.x-r.min.x);
246*9a747e4fSDavid du Colombier 	vncwrshort(v, r.max.y-r.min.y);
247*9a747e4fSDavid du Colombier }
248*9a747e4fSDavid du Colombier 
249*9a747e4fSDavid du Colombier void
vncwrpoint(Vnc * v,Point p)250*9a747e4fSDavid du Colombier vncwrpoint(Vnc *v, Point p)
251*9a747e4fSDavid du Colombier {
252*9a747e4fSDavid du Colombier 	vncwrshort(v, p.x);
253*9a747e4fSDavid du Colombier 	vncwrshort(v, p.y);
254*9a747e4fSDavid du Colombier }
255*9a747e4fSDavid du Colombier 
256*9a747e4fSDavid du Colombier void
vnclock(Vnc * v)257*9a747e4fSDavid du Colombier vnclock(Vnc *v)
258*9a747e4fSDavid du Colombier {
259*9a747e4fSDavid du Colombier 	qlock(v);
260*9a747e4fSDavid du Colombier }
261*9a747e4fSDavid du Colombier 
262*9a747e4fSDavid du Colombier void
vncunlock(Vnc * v)263*9a747e4fSDavid du Colombier vncunlock(Vnc *v)
264*9a747e4fSDavid du Colombier {
265*9a747e4fSDavid du Colombier 	qunlock(v);
266*9a747e4fSDavid du Colombier }
267*9a747e4fSDavid du Colombier 
268*9a747e4fSDavid du Colombier void
hexdump(void * a,int n)269*9a747e4fSDavid du Colombier hexdump(void *a, int n)
270*9a747e4fSDavid du Colombier {
271*9a747e4fSDavid du Colombier 	uchar *p, *ep;
272*9a747e4fSDavid du Colombier 
273*9a747e4fSDavid du Colombier 	p = a;
274*9a747e4fSDavid du Colombier 	ep = p+n;
275*9a747e4fSDavid du Colombier 
276*9a747e4fSDavid du Colombier 	for(; p<ep; p++)
277*9a747e4fSDavid du Colombier 		print("%.2ux ", *p);
278*9a747e4fSDavid du Colombier 	print("\n");
279*9a747e4fSDavid du Colombier }
280*9a747e4fSDavid du Colombier 
281*9a747e4fSDavid du Colombier void
vncgobble(Vnc * v,long n)282*9a747e4fSDavid du Colombier vncgobble(Vnc *v, long n)
283*9a747e4fSDavid du Colombier {
284*9a747e4fSDavid du Colombier 	uchar buf[8192];
285*9a747e4fSDavid du Colombier 	long m;
286*9a747e4fSDavid du Colombier 
287*9a747e4fSDavid du Colombier 	while(n > 0){
288*9a747e4fSDavid du Colombier 		m = n;
289*9a747e4fSDavid du Colombier 		if(m > sizeof(buf))
290*9a747e4fSDavid du Colombier 			m = sizeof(buf);
291*9a747e4fSDavid du Colombier 		vncrdbytes(v, buf, m);
292*9a747e4fSDavid du Colombier 		n -= m;
293*9a747e4fSDavid du Colombier 	}
294*9a747e4fSDavid du Colombier }
295