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