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