]>
Commit | Line | Data |
---|---|---|
3f615518 | 1 | diff -Nru directvnc-0.7.5/src/caps.c directvnc-0.7.5.new/src/caps.c |
2 | --- directvnc-0.7.5/src/caps.c 1970-01-01 01:00:00.000000000 +0100 | |
3 | +++ directvnc-0.7.5.new/src/caps.c 2007-01-15 14:48:51.000000000 +0100 | |
4 | @@ -0,0 +1,246 @@ | |
5 | +/* | |
6 | + * Copyright (C) 2003 Constantin Kaplinsky. All Rights Reserved. | |
7 | + * | |
8 | + * This is free software; you can redistribute it and/or modify | |
9 | + * it under the terms of the GNU General Public License as published by | |
10 | + * the Free Software Foundation; either version 2 of the License, or | |
11 | + * (at your option) any later version. | |
12 | + * | |
13 | + * This software is distributed in the hope that it will be useful, | |
14 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | + * GNU General Public License for more details. | |
17 | + * | |
18 | + * You should have received a copy of the GNU General Public License | |
19 | + * along with this software; if not, write to the Free Software | |
20 | + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |
21 | + * USA. | |
22 | + */ | |
23 | + | |
24 | +/* | |
25 | + * caps.c | |
26 | + */ | |
27 | + | |
28 | +#include "caps.h" | |
29 | +#include "rfbproto.h" | |
30 | + | |
31 | +static int CapsIndex(CapsContainer *pcaps, CARD32 code); | |
32 | + | |
33 | +/* | |
34 | + * The constructor. | |
35 | + */ | |
36 | + | |
37 | +CapsContainer * | |
38 | +CapsNewContainer(void) | |
39 | +{ | |
40 | + CapsContainer *pcaps; | |
41 | + | |
42 | + pcaps = malloc(sizeof(CapsContainer)); | |
43 | + if (pcaps != NULL) { | |
44 | + pcaps->known_count = 0; | |
45 | + pcaps->enabled_count = 0; | |
46 | + } | |
47 | + | |
48 | + return pcaps; | |
49 | +} | |
50 | + | |
51 | +/* | |
52 | + * The destructor. | |
53 | + */ | |
54 | + | |
55 | +void | |
56 | +CapsDeleteContainer(CapsContainer *pcaps) | |
57 | +{ | |
58 | + int i; | |
59 | + | |
60 | + for (i = 0; i < pcaps->known_count; i++) { | |
61 | + if (pcaps->descriptions[i] != NULL) | |
62 | + free(pcaps->descriptions[i]); | |
63 | + } | |
64 | + | |
65 | + free(pcaps); | |
66 | +} | |
67 | + | |
68 | +/* | |
69 | + * Add information about a particular capability into the object. There are | |
70 | + * two functions to perform this task. These functions overwrite capability | |
71 | + * records with the same code. | |
72 | + */ | |
73 | + | |
74 | +void | |
75 | +CapsAdd(CapsContainer *pcaps, | |
76 | + CARD32 code, char *vendor, char *name, char *desc) | |
77 | +{ | |
78 | + /* Fill in an rfbCapabilityInfo structure and pass it to CapsAddInfo(). */ | |
79 | + rfbCapabilityInfo capinfo; | |
80 | + capinfo.code = code; | |
81 | + memcpy(capinfo.vendorSignature, vendor, sz_rfbCapabilityInfoVendor); | |
82 | + memcpy(capinfo.nameSignature, name, sz_rfbCapabilityInfoName); | |
83 | + CapsAddInfo(pcaps, &capinfo, desc); | |
84 | +} | |
85 | + | |
86 | +void | |
87 | +CapsAddInfo(CapsContainer *pcaps, | |
88 | + rfbCapabilityInfo *capinfo, char *desc) | |
89 | +{ | |
90 | + int i; | |
91 | + char *desc_copy; | |
92 | + | |
93 | + i = CapsIndex(pcaps, capinfo->code); | |
94 | + if (i == -1) { | |
95 | + if (pcaps->known_count >= TIGHTVNC_MAX_CAPS) { | |
96 | + return; /* container full */ | |
97 | + } | |
98 | + i = pcaps->known_count++; | |
99 | + pcaps->known_list[i] = capinfo->code; | |
100 | + pcaps->descriptions[i] = NULL; | |
101 | + } | |
102 | + | |
103 | + pcaps->known_info[i] = *capinfo; | |
104 | + pcaps->enable_flags[i] = (char)0; | |
105 | + if (pcaps->descriptions[i] != NULL) { | |
106 | + free(pcaps->descriptions[i]); | |
107 | + } | |
108 | + | |
109 | + desc_copy = NULL; | |
110 | + if (desc != NULL) { | |
111 | + desc_copy = strdup(desc); | |
112 | + } | |
113 | + pcaps->descriptions[i] = desc_copy; | |
114 | +} | |
115 | + | |
116 | +/* | |
117 | + * Check if a capability with the specified code was added earlier. | |
118 | + */ | |
119 | + | |
120 | +static int | |
121 | +CapsIndex(CapsContainer *pcaps, CARD32 code) | |
122 | +{ | |
123 | + int i; | |
124 | + | |
125 | + for (i = 0; i < pcaps->known_count; i++) { | |
126 | + if (pcaps->known_list[i] == code) | |
127 | + return i; | |
128 | + } | |
129 | + | |
130 | + return -1; | |
131 | +} | |
132 | + | |
133 | +int | |
134 | +CapsIsKnown(CapsContainer *pcaps, CARD32 code) | |
135 | +{ | |
136 | + return (CapsIndex(pcaps, code) != -1); | |
137 | +} | |
138 | + | |
139 | +/* | |
140 | + * Fill in a rfbCapabilityInfo structure with contents corresponding to the | |
141 | + * specified code. Returns True on success, False if the specified code is | |
142 | + * not known. | |
143 | + */ | |
144 | + | |
145 | +int | |
146 | +CapsGetInfo(CapsContainer *pcaps, CARD32 code, rfbCapabilityInfo *capinfo) | |
147 | +{ | |
148 | + int i; | |
149 | + | |
150 | + i = CapsIndex(pcaps, code); | |
151 | + if (i != -1) { | |
152 | + *capinfo = pcaps->known_info[i]; | |
153 | + return 1; | |
154 | + } | |
155 | + | |
156 | + return 0; | |
157 | +} | |
158 | + | |
159 | +/* | |
160 | + * Get a description string for the specified capability code. Returns NULL | |
161 | + * either if the code is not known, or if there is no description for this | |
162 | + * capability. | |
163 | + */ | |
164 | + | |
165 | +char * | |
166 | +CapsGetDescription(CapsContainer *pcaps, CARD32 code) | |
167 | +{ | |
168 | + int i; | |
169 | + | |
170 | + i = CapsIndex(pcaps, code); | |
171 | + if (i != -1) { | |
172 | + return pcaps->descriptions[i]; | |
173 | + } | |
174 | + | |
175 | + return NULL; | |
176 | +} | |
177 | + | |
178 | +/* | |
179 | + * Mark the specified capability as "enabled". This function checks "vendor" | |
180 | + * and "name" signatures in the existing record and in the argument structure | |
181 | + * and enables the capability only if both records are the same. | |
182 | + */ | |
183 | + | |
184 | +int | |
185 | +CapsEnable(CapsContainer *pcaps, rfbCapabilityInfo *capinfo) | |
186 | +{ | |
187 | + int i; | |
188 | + rfbCapabilityInfo *known; | |
189 | + | |
190 | + i = CapsIndex(pcaps, capinfo->code); | |
191 | + if (i == -1) | |
192 | + return 0; | |
193 | + | |
194 | + known = &pcaps->known_info[i]; | |
195 | + if ( memcmp(known->vendorSignature, capinfo->vendorSignature, | |
196 | + sz_rfbCapabilityInfoVendor) != 0 || | |
197 | + memcmp(known->nameSignature, capinfo->nameSignature, | |
198 | + sz_rfbCapabilityInfoName) != 0 ) { | |
199 | + pcaps->enable_flags[i] = (char)0; | |
200 | + return 0; | |
201 | + } | |
202 | + | |
203 | + /* Cannot happen, but just in case. */ | |
204 | + if (pcaps->enabled_count >= TIGHTVNC_MAX_CAPS) { | |
205 | + pcaps->enable_flags[i] = (char)0; | |
206 | + return 0; | |
207 | + } | |
208 | + | |
209 | + pcaps->enable_flags[i] = (char)1; | |
210 | + pcaps->enabled_list[pcaps->enabled_count++] = capinfo->code; | |
211 | + return 1; | |
212 | +} | |
213 | + | |
214 | +/* | |
215 | + * Check if the specified capability is known and enabled. | |
216 | + */ | |
217 | + | |
218 | +int | |
219 | +CapsIsEnabled(CapsContainer *pcaps, CARD32 code) | |
220 | +{ | |
221 | + int i; | |
222 | + | |
223 | + i = CapsIndex(pcaps, code); | |
224 | + if (i != -1) { | |
225 | + return (pcaps->enable_flags[i] != (char)0); | |
226 | + } | |
227 | + | |
228 | + return 0; | |
229 | +} | |
230 | + | |
231 | +/* | |
232 | + * Return the number of enabled capabilities. | |
233 | + */ | |
234 | + | |
235 | +int CapsNumEnabled(CapsContainer *pcaps) | |
236 | +{ | |
237 | + return pcaps->enabled_count; | |
238 | +} | |
239 | + | |
240 | +/* | |
241 | + * Return the capability code at the specified index. | |
242 | + * If the index is not valid, return 0. | |
243 | + */ | |
244 | + | |
245 | +CARD32 | |
246 | +CapsGetByOrder(CapsContainer *pcaps, int idx) | |
247 | +{ | |
248 | + return (idx < pcaps->enabled_count) ? pcaps->enabled_list[idx] : 0; | |
249 | +} | |
250 | + | |
251 | diff -Nru directvnc-0.7.5/src/caps.h directvnc-0.7.5.new/src/caps.h | |
252 | --- directvnc-0.7.5/src/caps.h 1970-01-01 01:00:00.000000000 +0100 | |
253 | +++ directvnc-0.7.5.new/src/caps.h 2007-01-15 14:46:50.000000000 +0100 | |
254 | @@ -0,0 +1,64 @@ | |
255 | +/* | |
256 | + * Copyright (C) 2003 Constantin Kaplinsky. All Rights Reserved. | |
257 | + * | |
258 | + * This is free software; you can redistribute it and/or modify | |
259 | + * it under the terms of the GNU General Public License as published by | |
260 | + * the Free Software Foundation; either version 2 of the License, or | |
261 | + * (at your option) any later version. | |
262 | + * | |
263 | + * This software is distributed in the hope that it will be useful, | |
264 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
265 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
266 | + * GNU General Public License for more details. | |
267 | + * | |
268 | + * You should have received a copy of the GNU General Public License | |
269 | + * along with this software; if not, write to the Free Software | |
270 | + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |
271 | + * USA. | |
272 | + */ | |
273 | + | |
274 | +/* | |
275 | + * caps.h | |
276 | + */ | |
277 | + | |
278 | +#ifndef _VNC_CAPSCONTAINER | |
279 | +#define _VNC_CAPSCONTAINER | |
280 | + | |
281 | +#include "directvnc.h" | |
282 | +/* FIXME: Don't limit the number of capabilities. */ | |
283 | +#define TIGHTVNC_MAX_CAPS 64 | |
284 | + | |
285 | +typedef struct _CapsContainer | |
286 | +{ | |
287 | + int known_count; | |
288 | + CARD32 known_list[TIGHTVNC_MAX_CAPS]; | |
289 | + rfbCapabilityInfo known_info[TIGHTVNC_MAX_CAPS]; | |
290 | + char *descriptions[TIGHTVNC_MAX_CAPS]; | |
291 | + char enable_flags[TIGHTVNC_MAX_CAPS]; | |
292 | + | |
293 | + /* These are redundant, but improve the performance. */ | |
294 | + int enabled_count; | |
295 | + CARD32 enabled_list[TIGHTVNC_MAX_CAPS]; | |
296 | + | |
297 | +} CapsContainer; | |
298 | + | |
299 | +CapsContainer *CapsNewContainer(void); | |
300 | +void CapsDeleteContainer(CapsContainer *pcaps); | |
301 | + | |
302 | +void CapsAdd(CapsContainer *pcaps, | |
303 | + CARD32 code, char *vendor, char *name, char *desc); | |
304 | +void CapsAddInfo(CapsContainer *pcaps, | |
305 | + rfbCapabilityInfo *capinfo, char *desc); | |
306 | + | |
307 | +int CapsIsKnown(CapsContainer *pcaps, CARD32 code); | |
308 | +int CapsGetInfo(CapsContainer *pcaps, CARD32 code, | |
309 | + rfbCapabilityInfo *capinfo); | |
310 | +char *CapsGetDescription(CapsContainer *pcaps, CARD32 code); | |
311 | + | |
312 | +int CapsEnable(CapsContainer *pcaps, rfbCapabilityInfo *capinfo); | |
313 | +int CapsIsEnabled(CapsContainer *pcaps, CARD32 code); | |
314 | +int CapsNumEnabled(CapsContainer *pcaps); | |
315 | +CARD32 CapsGetByOrder(CapsContainer *pcaps, int idx); | |
316 | + | |
317 | +#endif /* _VNC_CAPSCONTAINER */ | |
318 | + | |
319 | diff -Nru directvnc-0.7.5/src/cursor.c directvnc-0.7.5.new/src/cursor.c | |
320 | --- directvnc-0.7.5/src/cursor.c 2003-01-26 19:47:54.000000000 +0100 | |
321 | +++ directvnc-0.7.5.new/src/cursor.c 2007-01-15 19:59:32.000000000 +0100 | |
322 | @@ -31,6 +31,15 @@ | |
323 | #define True 1 | |
324 | #define False 0 | |
325 | ||
326 | +#define RGB24_TO_PIXEL(bpp,r,g,b) \ | |
327 | + ((((CARD##bpp)(r) & 0xFF) * opt.client.redmax + 127) / 255 \ | |
328 | + << opt.client.redshift | \ | |
329 | + (((CARD##bpp)(g) & 0xFF) * opt.client.greenmax + 127) / 255 \ | |
330 | + << opt.client.greenshift | \ | |
331 | + (((CARD##bpp)(b) & 0xFF) * opt.client.bluemax + 127) / 255 \ | |
332 | + << opt.client.blueshift) | |
333 | + | |
334 | + | |
335 | ||
336 | /* Data kept for RichCursor encoding support. */ | |
337 | static Bool prevRichCursorSet = False; | |
338 | @@ -46,7 +55,6 @@ | |
339 | static void SoftCursorDraw(void); | |
340 | static void FreeCursors(Bool setDotCursor); | |
341 | ||
342 | - | |
343 | /********************************************************************* | |
344 | * HandleRichCursor(). RichCursor shape updates support. This | |
345 | * variation of cursor shape updates cannot be supported directly via | |
346 | @@ -54,13 +62,17 @@ | |
347 | * buffer (that is why we call it "software cursor"). | |
348 | ********************************************************************/ | |
349 | ||
350 | -Bool HandleRichCursor(int xhot, int yhot, int width, int height) | |
351 | +Bool HandleCursorShape(int xhot, int yhot, int width, int height, CARD32 enc) | |
352 | { | |
353 | + int bytesPerPixel; | |
354 | size_t bytesPerRow, bytesMaskData; | |
355 | + rfbXCursorColors rgb; | |
356 | + CARD32 colors[2]; | |
357 | char *buf; | |
358 | CARD8 *ptr; | |
359 | int x, y, b; | |
360 | ||
361 | + bytesPerPixel = opt.server.bpp / 8; | |
362 | bytesPerRow = (width + 7) / 8; | |
363 | bytesMaskData = bytesPerRow * height; | |
364 | ||
365 | @@ -75,11 +87,6 @@ | |
366 | if (rcSource == NULL) | |
367 | return False; | |
368 | ||
369 | - if (!read_from_rfb_server(sock, (char *)rcSource, | |
370 | - width * height * (opt.client.bpp / 8))) { | |
371 | - free(rcSource); | |
372 | - return False; | |
373 | - } | |
374 | ||
375 | /* Read and decode mask data. */ | |
376 | ||
377 | @@ -89,6 +96,64 @@ | |
378 | return False; | |
379 | } | |
380 | ||
381 | + /* Read and decode cursor pixel data, depending on the encoding type. */ | |
382 | + | |
383 | + if (enc == rfbEncodingXCursor) { | |
384 | + | |
385 | + /* Read and convert background and foreground colors. */ | |
386 | + if (!read_from_rfb_server(sock, (char *)&rgb, sz_rfbXCursorColors)) { | |
387 | + free(rcSource); | |
388 | + free(buf); | |
389 | + return False; | |
390 | + } | |
391 | + colors[0] = RGB24_TO_PIXEL(32, rgb.backRed, rgb.backGreen, rgb.backBlue); | |
392 | + colors[1] = RGB24_TO_PIXEL(32, rgb.foreRed, rgb.foreGreen, rgb.foreBlue); | |
393 | + | |
394 | + /* Read 1bpp pixel data into a temporary buffer. */ | |
395 | + if (!read_from_rfb_server(sock, buf, bytesMaskData)) { | |
396 | + free(rcSource); | |
397 | + free(buf); | |
398 | + return False; | |
399 | + } | |
400 | + | |
401 | + /* Convert 1bpp data to byte-wide color indices. */ | |
402 | + ptr = rcSource; | |
403 | + for (y = 0; y < height; y++) { | |
404 | + for (x = 0; x < width / 8; x++) { | |
405 | + for (b = 7; b >= 0; b--) { | |
406 | + *ptr = buf[y * bytesPerRow + x] >> b & 1; | |
407 | + ptr += bytesPerPixel; | |
408 | + } | |
409 | + } | |
410 | + for (b = 7; b > 7 - width % 8; b--) { | |
411 | + *ptr = buf[y * bytesPerRow + x] >> b & 1; | |
412 | + ptr += bytesPerPixel; | |
413 | + } | |
414 | + } | |
415 | + | |
416 | + /* Convert indices into the actual pixel values. */ | |
417 | + switch (bytesPerPixel) { | |
418 | + case 1: | |
419 | + for (x = 0; x < width * height; x++) | |
420 | + rcSource[x] = (CARD8)colors[rcSource[x]]; | |
421 | + break; | |
422 | + case 2: | |
423 | + for (x = 0; x < width * height; x++) | |
424 | + ((CARD16 *)rcSource)[x] = (CARD16)colors[rcSource[x * 2]]; | |
425 | + break; | |
426 | + case 4: | |
427 | + for (x = 0; x < width * height; x++) | |
428 | + ((CARD32 *)rcSource)[x] = colors[rcSource[x * 4]]; | |
429 | + break; | |
430 | + } | |
431 | + } else { /* rfbEncodingRichCursor */ | |
432 | + if (!read_from_rfb_server(sock, (char *)rcSource, | |
433 | + width * height * (opt.client.bpp / 8))) { | |
434 | + free(rcSource); | |
435 | + return False; | |
436 | + } | |
437 | + } | |
438 | + | |
439 | if (!read_from_rfb_server(sock, buf, bytesMaskData)) { | |
440 | free(rcSource); | |
441 | free(buf); | |
442 | @@ -201,7 +266,8 @@ | |
443 | * SoftCursorUnlock() functions is called. | |
444 | ********************************************************************/ | |
445 | ||
446 | -void SoftCursorMove(int x, int y) | |
447 | +void | |
448 | +SoftCursorMove(int x, int y) | |
449 | { | |
450 | if (prevRichCursorSet && !rcCursorHidden) { | |
451 | SoftCursorCopyArea(OPER_RESTORE); | |
452 | @@ -303,3 +369,20 @@ | |
453 | } | |
454 | } | |
455 | ||
456 | +/********************************************************************* | |
457 | + * HandleCursorPos(). Support for the PointerPos pseudo-encoding used | |
458 | + * to transmit changes in pointer position from server to clients. | |
459 | + * PointerPos encoding is used together with cursor shape updates. | |
460 | + ********************************************************************/ | |
461 | + | |
462 | +int | |
463 | +HandleCursorPos(int x, int y) | |
464 | +{ | |
465 | + if (x >= opt.server.width) | |
466 | + x = opt.server.width - 1; | |
467 | + if (y >= opt.server.height) | |
468 | + y = opt.server.height - 1; | |
469 | + | |
470 | + SoftCursorMove(x, y); | |
471 | + return 1; | |
472 | +} | |
473 | diff -Nru directvnc-0.7.5/src/directvnc.h directvnc-0.7.5.new/src/directvnc.h | |
474 | --- directvnc-0.7.5/src/directvnc.h 2007-01-15 22:06:18.000000000 +0100 | |
475 | +++ directvnc-0.7.5.new/src/directvnc.h 2007-01-15 20:02:12.000000000 +0100 | |
476 | @@ -117,6 +117,7 @@ | |
477 | { | |
478 | char *servername; | |
479 | int port; | |
480 | + char *user; | |
481 | char *password; | |
482 | char *encodings; | |
483 | struct serversettings server; | |
484 | @@ -142,6 +143,7 @@ | |
485 | int read_from_rfb_server(int sock, char *out, unsigned int n); | |
486 | int write_exact(int sock, char *buf, unsigned int n); | |
487 | int set_non_blocking(int sock); | |
488 | +int SameMachine(int sock); | |
489 | ||
490 | /* dfb.c */ | |
491 | void dfb_init(int argc, char *argv[]); | |
492 | @@ -157,12 +159,11 @@ | |
493 | void dfb_restore_cursor_rect( IDirectFBSurface *surf, int x, int y, int width, int heigth); | |
494 | ||
495 | /* cursor.c */ | |
496 | -int HandleRichCursor(int x, int y, int w, int h); | |
497 | +int HandleCursorShape(int x, int y, int w, int h, CARD32 enc); | |
498 | void SoftCursorLockArea(int x, int y, int w, int h); | |
499 | void SoftCursorUnlockScreen(void); | |
500 | void SoftCursorMove(int x, int y); | |
501 | ||
502 | - | |
503 | /* macro for a safe call to DirectFB functions */ | |
504 | #define DFBCHECK(x...) \ | |
505 | { \ | |
506 | @@ -174,5 +175,3 @@ | |
507 | } | |
508 | ||
509 | #endif | |
510 | - | |
511 | - | |
512 | diff -Nru directvnc-0.7.5/src/Makefile.am directvnc-0.7.5.new/src/Makefile.am | |
513 | --- directvnc-0.7.5/src/Makefile.am 2003-01-31 10:20:35.000000000 +0100 | |
514 | +++ directvnc-0.7.5.new/src/Makefile.am 2007-01-15 14:07:50.000000000 +0100 | |
515 | @@ -9,7 +9,7 @@ | |
516 | LIBOBJS = @LIBOBJS@ | |
517 | ||
518 | bin_PROGRAMS = directvnc | |
519 | -directvnc_SOURCES = main.c debug.h dfb.c directvnc.h sockets.c args.c\ | |
520 | +directvnc_SOURCES = caps.c caps.h main.c debug.h dfb.c directvnc.h sockets.c args.c\ | |
521 | rfb.c getopt.c getopt1.c getopt.h\ | |
522 | d3des.c d3des.h vncauth.c vncauth.h jpeg.c jpeg.h\ | |
523 | tight.c tight.h rfbproto.h keysym.h keysymdef.h \ | |
524 | diff -Nru directvnc-0.7.5/src/rfb.c directvnc-0.7.5.new/src/rfb.c | |
525 | --- directvnc-0.7.5/src/rfb.c 2003-01-31 09:41:03.000000000 +0100 | |
526 | +++ directvnc-0.7.5.new/src/rfb.c 2007-01-15 21:49:58.000000000 +0100 | |
527 | @@ -17,7 +17,8 @@ | |
528 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
529 | */ | |
530 | ||
531 | - | |
532 | +#include <pwd.h> | |
533 | +#include <sys/types.h> | |
534 | #include <unistd.h> | |
535 | #include <sys/socket.h> | |
536 | #include <errno.h> | |
537 | @@ -28,15 +29,25 @@ | |
538 | #include <math.h> | |
539 | #include <zlib.h> | |
540 | ||
541 | +#include "caps.h" | |
542 | #include "directvnc.h" | |
543 | #include "tight.h" | |
544 | ||
545 | +static void InitCapabilities(void); | |
546 | +static int SetupTunneling(void); | |
547 | +static int ReadSecurityType(void); | |
548 | +static int SelectSecurityType(void); | |
549 | +static int PerformAuthenticationTight(void); | |
550 | +static int AuthenticateVNC(void); | |
551 | +static int AuthenticateUnixLogin(void); | |
552 | +static int ReadInteractionCaps(void); | |
553 | +static int ReadCapabilityList(CapsContainer *caps, int count); | |
554 | + | |
555 | int _rfb_negotiate_protocol (); | |
556 | int _rfb_authenticate (); | |
557 | int _rfb_initialise_client (); | |
558 | int _rfb_initialise_server (); | |
559 | ||
560 | - | |
561 | static int _handle_raw_encoded_message(rfbFramebufferUpdateRectHeader rectheader); | |
562 | static int _handle_copyrect_encoded_message(rfbFramebufferUpdateRectHeader rectheader); | |
563 | static int _handle_rre_encoded_message(rfbFramebufferUpdateRectHeader rectheader); | |
564 | @@ -44,6 +55,63 @@ | |
565 | static int _handle_hextile_encoded_message(rfbFramebufferUpdateRectHeader rectheader); | |
566 | static int _handle_richcursor_message(rfbFramebufferUpdateRectHeader rectheader); | |
567 | ||
568 | +static int tightVncProtocol = 0; | |
569 | +static CapsContainer *tunnelCaps; /* known tunneling/encryption methods */ | |
570 | +static CapsContainer *authCaps; /* known authentication schemes */ | |
571 | +static CapsContainer *serverMsgCaps; /* known non-standard server messages */ | |
572 | +static CapsContainer *clientMsgCaps; /* known non-standard client messages */ | |
573 | +static CapsContainer *encodingCaps; /* known encodings besides Raw */ | |
574 | +static int tunnelSpecified = 0; | |
575 | + | |
576 | +/* | |
577 | + * InitCapabilities. | |
578 | + */ | |
579 | + | |
580 | +static void | |
581 | +InitCapabilities(void) | |
582 | +{ | |
583 | + tunnelCaps = CapsNewContainer(); | |
584 | + authCaps = CapsNewContainer(); | |
585 | + serverMsgCaps = CapsNewContainer(); | |
586 | + clientMsgCaps = CapsNewContainer(); | |
587 | + encodingCaps = CapsNewContainer(); | |
588 | + | |
589 | + /* Supported authentication methods */ | |
590 | + CapsAdd(authCaps, rfbAuthVNC, rfbStandardVendor, sig_rfbAuthVNC, | |
591 | + "Standard VNC password authentication"); | |
592 | + CapsAdd(authCaps, rfbAuthUnixLogin, rfbTightVncVendor, sig_rfbAuthUnixLogin, | |
593 | + "Login-style Unix authentication"); | |
594 | + | |
595 | + /* Supported encoding types */ | |
596 | + CapsAdd(encodingCaps, rfbEncodingCopyRect, rfbStandardVendor, | |
597 | + sig_rfbEncodingCopyRect, "Standard CopyRect encoding"); | |
598 | + CapsAdd(encodingCaps, rfbEncodingRRE, rfbStandardVendor, | |
599 | + sig_rfbEncodingRRE, "Standard RRE encoding"); | |
600 | + CapsAdd(encodingCaps, rfbEncodingCoRRE, rfbStandardVendor, | |
601 | + sig_rfbEncodingCoRRE, "Standard CoRRE encoding"); | |
602 | + CapsAdd(encodingCaps, rfbEncodingHextile, rfbStandardVendor, | |
603 | + sig_rfbEncodingHextile, "Standard Hextile encoding"); | |
604 | + CapsAdd(encodingCaps, rfbEncodingZlib, rfbTridiaVncVendor, | |
605 | + sig_rfbEncodingZlib, "Zlib encoding from TridiaVNC"); | |
606 | + CapsAdd(encodingCaps, rfbEncodingTight, rfbTightVncVendor, | |
607 | + sig_rfbEncodingTight, "Tight encoding by Constantin Kaplinsky"); | |
608 | + | |
609 | + /* Supported "fake" encoding types */ | |
610 | + CapsAdd(encodingCaps, rfbEncodingCompressLevel0, rfbTightVncVendor, | |
611 | + sig_rfbEncodingCompressLevel0, "Compression level"); | |
612 | + CapsAdd(encodingCaps, rfbEncodingQualityLevel0, rfbTightVncVendor, | |
613 | + sig_rfbEncodingQualityLevel0, "JPEG quality level"); | |
614 | + CapsAdd(encodingCaps, rfbEncodingXCursor, rfbTightVncVendor, | |
615 | + sig_rfbEncodingXCursor, "X-style cursor shape update"); | |
616 | + CapsAdd(encodingCaps, rfbEncodingRichCursor, rfbTightVncVendor, | |
617 | + sig_rfbEncodingRichCursor, "Rich-color cursor shape update"); | |
618 | + CapsAdd(encodingCaps, rfbEncodingPointerPos, rfbTightVncVendor, | |
619 | + sig_rfbEncodingPointerPos, "Pointer position update"); | |
620 | + CapsAdd(encodingCaps, rfbEncodingLastRect, rfbTightVncVendor, | |
621 | + sig_rfbEncodingLastRect, "LastRect protocol extension"); | |
622 | +} | |
623 | + | |
624 | + | |
625 | /* | |
626 | * ConnectToRFBServer. | |
627 | */ | |
628 | @@ -100,89 +168,393 @@ | |
629 | int | |
630 | rfb_initialise_connection () | |
631 | { | |
632 | - if (!_rfb_negotiate_protocol()) return 0; | |
633 | - if (!_rfb_authenticate()) return 0; | |
634 | - if (!_rfb_initialise_client()) return 0; | |
635 | - if (!_rfb_initialise_server()) return 0; | |
636 | - | |
637 | - return(1); | |
638 | + if (!_rfb_negotiate_protocol()) return 0; | |
639 | + if (!_rfb_initialise_client()) return 0; | |
640 | + if (!_rfb_initialise_server()) return 0; | |
641 | + return 1; | |
642 | } | |
643 | ||
644 | int | |
645 | _rfb_negotiate_protocol() | |
646 | { | |
647 | rfbProtocolVersionMsg msg; | |
648 | + int server_major, server_minor; | |
649 | + int viewer_major, viewer_minor; | |
650 | + int secType; | |
651 | ||
652 | /* read the protocol version the server uses */ | |
653 | if (!read_from_rfb_server(sock, (char*)&msg, sz_rfbProtocolVersionMsg)) | |
654 | return 0; | |
655 | - /* FIXME actually do something with that information ;) */ | |
656 | ||
657 | + msg[sz_rfbProtocolVersionMsg] = 0; | |
658 | + | |
659 | + if (sscanf(msg, rfbProtocolVersionFormat, &server_major, &server_minor) != 2) { | |
660 | + return 0; | |
661 | + } | |
662 | + viewer_major = rfbProtocolMajorVersion; | |
663 | + if (server_major == 3 && server_minor >= rfbProtocolMinorVersion) { | |
664 | + /* the server supports at least the standard protocol 3.7 */ | |
665 | + viewer_minor = rfbProtocolMinorVersion; | |
666 | + } else { | |
667 | + /* any other server version, request the standard 3.3 */ | |
668 | + viewer_minor = rfbProtocolFallbackMinorVersion; | |
669 | + } | |
670 | /* send the protocol version we want to use */ | |
671 | - sprintf(msg, rfbProtocolVersionFormat, | |
672 | - rfbProtocolMajorVersion, | |
673 | - rfbProtocolMinorVersion); | |
674 | + sprintf(msg, rfbProtocolVersionFormat, | |
675 | + viewer_major, | |
676 | + viewer_minor); | |
677 | if (!write_exact (sock, msg, sz_rfbProtocolVersionMsg)) | |
678 | return 0; | |
679 | ||
680 | - return 1; | |
681 | + /* Read or select the security type. */ | |
682 | + if (viewer_minor == rfbProtocolMinorVersion) { | |
683 | + secType = SelectSecurityType(); | |
684 | + } else { | |
685 | + secType = ReadSecurityType(); | |
686 | + } | |
687 | + if (secType == rfbConnFailed) | |
688 | + return 0; | |
689 | + | |
690 | + return _rfb_authenticate(secType); | |
691 | } | |
692 | ||
693 | +static int | |
694 | +ReadSecurityType(void) | |
695 | +{ | |
696 | + CARD32 secType; | |
697 | + if (!read_from_rfb_server(sock, (char *)&secType, sizeof(secType))) { | |
698 | + return rfbConnFailed; | |
699 | + } | |
700 | + return Swap32IfLE(secType); | |
701 | +} | |
702 | ||
703 | -int | |
704 | -_rfb_authenticate() | |
705 | +static int | |
706 | +SelectSecurityType(void) | |
707 | { | |
708 | - CARD32 authscheme; | |
709 | - | |
710 | - read_from_rfb_server(sock, (char *)&authscheme, 4); | |
711 | - authscheme = Swap32IfLE(authscheme); | |
712 | - switch (authscheme) | |
713 | - { | |
714 | - CARD32 reason_length; | |
715 | - CARD8 *reason_string; | |
716 | - CARD8 challenge_and_response[CHALLENGESIZE]; | |
717 | - CARD32 auth_result; | |
718 | - | |
719 | - case rfbConnFailed: | |
720 | - fprintf(stderr, "DIRECTVNC: Connection to VNC server failed\n"); | |
721 | - read_from_rfb_server(sock, (char *)&reason_length, 4); | |
722 | - reason_length = Swap32IfLE(reason_length); | |
723 | - reason_string = malloc(sizeof(CARD8) * reason_length); | |
724 | - read_from_rfb_server(sock, (char *)reason_string, reason_length); | |
725 | - fprintf(stderr, "Errormessage: %s\n", reason_string); | |
726 | - return (0); | |
727 | - case rfbVncAuth: | |
728 | + CARD8 nSecTypes; | |
729 | + char *secTypeNames[] = {"None", "VncAuth"}; | |
730 | + CARD8 knownSecTypes[] = {rfbNoAuth, rfbVncAuth}; | |
731 | + int nKnownSecTypes = sizeof(knownSecTypes); | |
732 | + CARD8 *secTypes; | |
733 | + CARD8 secType = rfbConnFailed; | |
734 | + int i, j; | |
735 | + | |
736 | + /* Read the list of security types. */ | |
737 | + if (!read_from_rfb_server(sock, (char *)&nSecTypes, sizeof(nSecTypes))) | |
738 | + return rfbConnFailed; | |
739 | + if (nSecTypes == 0) { | |
740 | + return rfbConnFailed; | |
741 | + } | |
742 | + | |
743 | + secTypes = malloc(nSecTypes); | |
744 | + if (!read_from_rfb_server(sock, (char *)secTypes, nSecTypes)) | |
745 | + return rfbConnFailed; | |
746 | + | |
747 | + /* Find out if the server supports TightVNC protocol extensions */ | |
748 | + for (j = 0; j < (int)nSecTypes; j++) { | |
749 | + if (secTypes[j] == rfbSecTypeTight) { | |
750 | + free(secTypes); | |
751 | + secType = rfbSecTypeTight; | |
752 | + if (!write_exact(sock, (char *)&secType, sizeof(secType))) | |
753 | + return rfbConnFailed; | |
754 | + fprintf(stderr, "Enabling TightVNC protocol extensions\n"); | |
755 | + return rfbSecTypeTight; | |
756 | + } | |
757 | + } | |
758 | + /* Find first supported security type */ | |
759 | + for (j = 0; j < (int)nSecTypes; j++) { | |
760 | + for (i = 0; i < nKnownSecTypes; i++) { | |
761 | + if (secTypes[j] == knownSecTypes[i]) { | |
762 | + secType = secTypes[j]; | |
763 | + if (!write_exact(sock, (char *)&secType, sizeof(secType))) { | |
764 | + free(secTypes); | |
765 | + return rfbConnFailed; | |
766 | + } | |
767 | + break; | |
768 | + } | |
769 | + } | |
770 | + if (secType != rfbConnFailed) break; | |
771 | + } | |
772 | + free(secTypes); | |
773 | + if (secType == rfbConnFailed) | |
774 | + fprintf(stderr, "Server did not offer supported security type\n"); | |
775 | + return (int)secType; | |
776 | ||
777 | - /* we didnt get a password on the command line, so go get one */ | |
778 | - if (!opt.password) opt.password = getpass("Password: "); | |
779 | +} | |
780 | ||
781 | - if (!read_from_rfb_server(sock, challenge_and_response, CHALLENGESIZE)) | |
782 | - return 0; | |
783 | - vncEncryptBytes(challenge_and_response, opt.password); | |
784 | - if (!write_exact(sock, challenge_and_response, CHALLENGESIZE)) | |
785 | - return 0; | |
786 | - if (!read_from_rfb_server(sock, (char*)&auth_result, 4)) | |
787 | +/* | |
788 | + * Standard VNC authentication. | |
789 | + */ | |
790 | + | |
791 | +static int | |
792 | +AuthenticateVNC(void) | |
793 | +{ | |
794 | + CARD32 authScheme, auth_result; | |
795 | + CARD8 challenge[CHALLENGESIZE]; | |
796 | + char *passwd; | |
797 | + char buffer[64]; | |
798 | + char* cstatus; | |
799 | + int len; | |
800 | + | |
801 | + fprintf(stderr, "Performing standard VNC authentication\n"); | |
802 | + | |
803 | + if (!read_from_rfb_server(sock, (char *)challenge, CHALLENGESIZE)) | |
804 | + return 0; | |
805 | + | |
806 | + | |
807 | + /* we get a password on the command line, so go get one */ | |
808 | + if (!opt.password) opt.password = getpass("Password: "); | |
809 | + if (strlen(opt.password) > 8) { | |
810 | + opt.password[8] = '\0'; | |
811 | + } | |
812 | + | |
813 | + vncEncryptBytes(challenge, opt.password); | |
814 | + /* Lose the password from memory */ | |
815 | + memset(opt.password, '\0', strlen(opt.password)); | |
816 | + | |
817 | + if (!write_exact(sock, challenge, CHALLENGESIZE)) | |
818 | + return 0; | |
819 | + if (!read_from_rfb_server(sock, (char*)&auth_result, 4)) | |
820 | return 0; | |
821 | - auth_result = Swap32IfLE(auth_result); | |
822 | - switch (auth_result) | |
823 | - { | |
824 | - case rfbVncAuthFailed: | |
825 | - fprintf(stderr, "Authentication Failed\n"); | |
826 | - return (0); | |
827 | - case rfbVncAuthTooMany: | |
828 | - fprintf(stderr, "Too many connections\n"); | |
829 | - return (0); | |
830 | - case rfbVncAuthOK: | |
831 | - fprintf(stderr, "Authentication OK\n"); | |
832 | - break; | |
833 | - } | |
834 | - break; | |
835 | - case rfbNoAuth: | |
836 | - break; | |
837 | + auth_result = Swap32IfLE(auth_result); | |
838 | + switch (auth_result) { | |
839 | + case rfbVncAuthFailed: | |
840 | + fprintf(stderr, "Authentication Failed\n"); | |
841 | + return 0; | |
842 | + case rfbVncAuthTooMany: | |
843 | + fprintf(stderr, "Too many connections\n"); | |
844 | + return 0; | |
845 | + case rfbVncAuthOK: | |
846 | + fprintf(stderr, "Authentication OK\n"); | |
847 | + break; | |
848 | + } | |
849 | + return 1; | |
850 | +} | |
851 | + | |
852 | + | |
853 | +/* | |
854 | + * Read the list of rfbCapabilityInfo structures and enable corresponding | |
855 | + * capabilities in the specified container. The count argument specifies how | |
856 | + * many records to read from the socket. | |
857 | + */ | |
858 | + | |
859 | +static int | |
860 | +ReadCapabilityList(CapsContainer *caps, int count) | |
861 | +{ | |
862 | + rfbCapabilityInfo msginfo; | |
863 | + int i; | |
864 | + | |
865 | + for (i = 0; i < count; i++) { | |
866 | + if (!read_from_rfb_server(sock, (char *)&msginfo, sz_rfbCapabilityInfo)) | |
867 | + return 0; | |
868 | + msginfo.code = Swap32IfLE(msginfo.code); | |
869 | + CapsEnable(caps, &msginfo); | |
870 | + } | |
871 | + | |
872 | + return 1; | |
873 | +} | |
874 | + | |
875 | +/* | |
876 | + * Unix login-style authentication. | |
877 | + */ | |
878 | + | |
879 | +static int | |
880 | +AuthenticateUnixLogin(void) | |
881 | +{ | |
882 | + CARD32 loginLen, passwdLen, authResult; | |
883 | + char *login; | |
884 | + char *passwd; | |
885 | + struct passwd *ps; | |
886 | + | |
887 | + fprintf(stderr, "Performing Unix login-style authentication\n"); | |
888 | + | |
889 | + if (opt.user) { | |
890 | + login = opt.user; | |
891 | + } else { | |
892 | + ps = getpwuid(getuid()); | |
893 | + login = ps->pw_name; | |
894 | + } | |
895 | + | |
896 | + fprintf(stderr, "Using user name \"%s\"\n", login); | |
897 | + | |
898 | + passwd = getpass("Password: "); | |
899 | + | |
900 | + if (!passwd || strlen(passwd) == 0) { | |
901 | + fprintf(stderr, "Reading password failed\n"); | |
902 | + return 0; | |
903 | + } | |
904 | + | |
905 | + loginLen = Swap32IfLE((CARD32)strlen(login)); | |
906 | + passwdLen = Swap32IfLE((CARD32)strlen(passwd)); | |
907 | + | |
908 | + if (!write_exact(sock, (char *)&loginLen, sizeof(loginLen)) || | |
909 | + !write_exact(sock, (char *)&passwdLen, sizeof(passwdLen))) | |
910 | + return 0; | |
911 | + | |
912 | + if (!write_exact(sock, login, strlen(login)) || | |
913 | + !write_exact(sock, passwd, strlen(passwd))) | |
914 | + return 0; | |
915 | + | |
916 | + /* Lose the password from memory */ | |
917 | + memset(passwd, '\0', strlen(passwd)); | |
918 | + | |
919 | + if (!read_from_rfb_server(sock, (char *)&authResult, sizeof(authResult))) | |
920 | + return 0; | |
921 | + | |
922 | + authResult = Swap32IfLE(authResult); | |
923 | + | |
924 | + switch (authResult) { | |
925 | + case rfbVncAuthOK: | |
926 | + fprintf(stderr, "Authentication succeeded\n"); | |
927 | + break; | |
928 | + case rfbVncAuthFailed: | |
929 | + fprintf(stderr, "Authentication failed\n"); | |
930 | + return 0; | |
931 | + case rfbVncAuthTooMany: | |
932 | + fprintf(stderr, "Authentication failed - too many tries\n"); | |
933 | + return 0; | |
934 | + default: | |
935 | + fprintf(stderr, "Unknown authentication result: %d\n", | |
936 | + (int)authResult); | |
937 | + return 0; | |
938 | + } | |
939 | + | |
940 | + return 1; | |
941 | +} | |
942 | + | |
943 | + | |
944 | +int | |
945 | +_rfb_authenticate(CARD32 authscheme) | |
946 | +{ | |
947 | + switch (authscheme) { | |
948 | + CARD32 reason_length; | |
949 | + CARD8 *reason_string; | |
950 | + CARD8 challenge_and_response[CHALLENGESIZE]; | |
951 | + CARD32 auth_result; | |
952 | + | |
953 | + case rfbConnFailed: | |
954 | + fprintf(stderr, "DIRECTVNC: Connection to VNC server failed\n"); | |
955 | + read_from_rfb_server(sock, (char *)&reason_length, 4); | |
956 | + reason_length = Swap32IfLE(reason_length); | |
957 | + reason_string = malloc(sizeof(CARD8) * reason_length); | |
958 | + read_from_rfb_server(sock, (char *)reason_string, reason_length); | |
959 | + fprintf(stderr, "Errormessage: %s\n", reason_string); | |
960 | + return 0; | |
961 | + case rfbVncAuth: | |
962 | + return AuthenticateVNC(); | |
963 | + case rfbNoAuth: | |
964 | + break; | |
965 | + case rfbSecTypeTight: | |
966 | + tightVncProtocol = 1; | |
967 | + InitCapabilities(); | |
968 | + if (!SetupTunneling()) return 0; | |
969 | + if (!PerformAuthenticationTight()) return 0; | |
970 | + break; | |
971 | + default: | |
972 | + fprintf(stderr, "Internal error: Invalid security type\n"); | |
973 | + return 0; | |
974 | } | |
975 | return 1; | |
976 | } | |
977 | ||
978 | +static int | |
979 | +SetupTunneling(void) | |
980 | +{ | |
981 | + rfbTunnelingCapsMsg caps; | |
982 | + CARD32 tunnelType; | |
983 | + | |
984 | + /* In the protocol version 3.7t, the server informs us about | |
985 | + supported tunneling methods. Here we read this information. */ | |
986 | + | |
987 | + if (!read_from_rfb_server(sock, (char *)&caps, sz_rfbTunnelingCapsMsg)) return 0; | |
988 | + caps.nTunnelTypes = Swap32IfLE(caps.nTunnelTypes); | |
989 | + | |
990 | + if (caps.nTunnelTypes) { | |
991 | + if (!ReadCapabilityList(tunnelCaps, caps.nTunnelTypes)) return 0; | |
992 | + | |
993 | + /* We cannot do tunneling anyway yet. */ | |
994 | + tunnelType = Swap32IfLE(rfbNoTunneling); | |
995 | + if (!write_exact(sock, (char *)&tunnelType, sizeof(tunnelType))) return 0; | |
996 | + } | |
997 | + return 1; | |
998 | +} | |
999 | + | |
1000 | +/* Negotiate authentication scheme (protocol version 3.7t) */ | |
1001 | +static int | |
1002 | +PerformAuthenticationTight(void) | |
1003 | +{ | |
1004 | + rfbAuthenticationCapsMsg caps; | |
1005 | + CARD32 authScheme; | |
1006 | + int i; | |
1007 | + | |
1008 | + /* In the protocol version 3.7t, the server informs us about supported | |
1009 | + authentication schemes. Here we read this infomation. */ | |
1010 | + | |
1011 | + if (!read_from_rfb_server(sock, (char *)&caps, sz_rfbAuthenticationCapsMsg)) return 0; | |
1012 | + | |
1013 | + caps.nAuthTypes = Swap32IfLE(caps.nAuthTypes); | |
1014 | + | |
1015 | + if (!caps.nAuthTypes) { | |
1016 | + fprintf(stderr, "No authentication needed\n"); | |
1017 | + return 1; | |
1018 | + } | |
1019 | + | |
1020 | + if (!ReadCapabilityList(authCaps, caps.nAuthTypes)) return 0; | |
1021 | + | |
1022 | + /* Prefer Unix login authentication if a user name was given. */ | |
1023 | + if (opt.user && CapsIsEnabled(authCaps, rfbAuthUnixLogin)) { | |
1024 | + authScheme = Swap32IfLE(rfbAuthUnixLogin); | |
1025 | + if (!write_exact(sock, (char *)&authScheme, sizeof(authScheme))) return 0; | |
1026 | + return AuthenticateUnixLogin(); | |
1027 | + } | |
1028 | + | |
1029 | + /* Otherwise, try server's preferred authentication scheme. */ | |
1030 | + for (i = 0; i < CapsNumEnabled(authCaps); i++) { | |
1031 | + authScheme = CapsGetByOrder(authCaps, i); | |
1032 | + if (authScheme != rfbAuthUnixLogin && authScheme != rfbAuthVNC) continue; /* unknown scheme - cannot use it */ | |
1033 | + authScheme = Swap32IfLE(authScheme); | |
1034 | + if (!write_exact(sock, (char *)&authScheme, sizeof(authScheme))) return 0; | |
1035 | + authScheme = Swap32IfLE(authScheme); /* convert it back */ | |
1036 | + | |
1037 | + if (authScheme == rfbAuthUnixLogin) { | |
1038 | + return AuthenticateUnixLogin(); | |
1039 | + } else if (authScheme == rfbAuthVNC) { | |
1040 | + return AuthenticateVNC(); | |
1041 | + } else { | |
1042 | + fprintf(stderr, "Should never happen\n"); | |
1043 | + /* Should never happen. */ | |
1044 | + return 0; | |
1045 | + } | |
1046 | + } | |
1047 | + | |
1048 | + fprintf(stderr, "No suitable authentication schemes offered by server\n"); | |
1049 | + return 0; | |
1050 | +} | |
1051 | + | |
1052 | +/* | |
1053 | + * In the protocol version 3.7t, the server informs us about supported | |
1054 | + * protocol messages and encodings. Here we read this information. | |
1055 | + */ | |
1056 | + | |
1057 | +static int | |
1058 | +ReadInteractionCaps(void) | |
1059 | +{ | |
1060 | + rfbInteractionCapsMsg intr_caps; | |
1061 | + | |
1062 | + /* Read the counts of list items following */ | |
1063 | + if (!read_from_rfb_server(sock, (char *)&intr_caps, sz_rfbInteractionCapsMsg)) | |
1064 | + return 0; | |
1065 | + intr_caps.nServerMessageTypes = Swap16IfLE(intr_caps.nServerMessageTypes); | |
1066 | + intr_caps.nClientMessageTypes = Swap16IfLE(intr_caps.nClientMessageTypes); | |
1067 | + intr_caps.nEncodingTypes = Swap16IfLE(intr_caps.nEncodingTypes); | |
1068 | + | |
1069 | + /* Read the lists of server- and client-initiated messages */ | |
1070 | + return (ReadCapabilityList(serverMsgCaps, intr_caps.nServerMessageTypes) && | |
1071 | + ReadCapabilityList(clientMsgCaps, intr_caps.nClientMessageTypes) && | |
1072 | + ReadCapabilityList(encodingCaps, intr_caps.nEncodingTypes)); | |
1073 | +} | |
1074 | + | |
1075 | + | |
1076 | int | |
1077 | _rfb_initialise_client() | |
1078 | { | |
1079 | @@ -220,10 +592,166 @@ | |
1080 | ||
1081 | if (!read_from_rfb_server(sock, opt.server.name, len)) | |
1082 | return 0; | |
1083 | - | |
1084 | + if (tightVncProtocol) { | |
1085 | + /* Read interaction capabilities (protocol 3.7t) */ | |
1086 | + if (!ReadInteractionCaps()) | |
1087 | + return 0; | |
1088 | + } | |
1089 | return 1; | |
1090 | } | |
1091 | ||
1092 | +/* | |
1093 | + * SetFormatAndEncodings. | |
1094 | + */ | |
1095 | + | |
1096 | +int | |
1097 | +rfb_set_format_and_encodings() | |
1098 | +{ | |
1099 | + rfbSetPixelFormatMsg spf; | |
1100 | + char buf[sz_rfbSetEncodingsMsg + MAX_ENCODINGS * 4]; | |
1101 | + rfbSetEncodingsMsg *se = (rfbSetEncodingsMsg *)buf; | |
1102 | + CARD32 *encs = (CARD32 *)(&buf[sz_rfbSetEncodingsMsg]); | |
1103 | + int len = 0; | |
1104 | + int requestCompressLevel = 0; | |
1105 | + int requestQualityLevel = 0; | |
1106 | + int requestLastRectEncoding = 0; | |
1107 | + | |
1108 | + spf.type = 0; | |
1109 | + spf.format.bitsPerPixel = opt.client.bpp; | |
1110 | + spf.format.depth = opt.client.depth; | |
1111 | + spf.format.bigEndian = opt.client.bigendian; | |
1112 | + spf.format.trueColour = opt.client.truecolour; | |
1113 | + spf.format.redMax = Swap16IfLE(opt.client.redmax); | |
1114 | + spf.format.greenMax = Swap16IfLE(opt.client.greenmax); | |
1115 | + spf.format.blueMax = Swap16IfLE(opt.client.bluemax); | |
1116 | + spf.format.redShift =opt.client.redshift; | |
1117 | + spf.format.greenShift = opt.client.greenshift; | |
1118 | + spf.format.blueShift = opt.client.blueshift; | |
1119 | + | |
1120 | + if (!write_exact(sock, (char *)&spf, sz_rfbSetPixelFormatMsg)) | |
1121 | + return 0; | |
1122 | + | |
1123 | + se->type = rfbSetEncodings; | |
1124 | + se->nEncodings = 0; | |
1125 | + | |
1126 | + if (opt.encodings) { | |
1127 | + char *encStr = opt.encodings; | |
1128 | + int encStrLen; | |
1129 | + do { | |
1130 | + char *nextEncStr = strchr(encStr, ' '); | |
1131 | + if (nextEncStr) { | |
1132 | + encStrLen = nextEncStr - encStr; | |
1133 | + nextEncStr++; | |
1134 | + } else { | |
1135 | + encStrLen = strlen(encStr); | |
1136 | + } | |
1137 | + | |
1138 | + if (strncasecmp(encStr,"raw",encStrLen) == 0) { | |
1139 | + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRaw); | |
1140 | + } else if (strncasecmp(encStr,"copyrect",encStrLen) == 0) { | |
1141 | + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCopyRect); | |
1142 | + } else if (strncasecmp(encStr,"tight",encStrLen) == 0) { | |
1143 | + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingTight); | |
1144 | + requestLastRectEncoding = 1; | |
1145 | + if (opt.client.compresslevel >= 0 && opt.client.compresslevel <= 9) | |
1146 | + requestCompressLevel = 1; | |
1147 | + requestQualityLevel = 1; | |
1148 | + } else if (strncasecmp(encStr,"hextile",encStrLen) == 0) { | |
1149 | + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingHextile); | |
1150 | + } else if (strncasecmp(encStr,"zlib",encStrLen) == 0) { | |
1151 | + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZlib); | |
1152 | + if (opt.client.compresslevel >= 0 && opt.client.compresslevel <= 9) | |
1153 | + requestCompressLevel = 1; | |
1154 | + } else if (strncasecmp(encStr,"corre",encStrLen) == 0) { | |
1155 | + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCoRRE); | |
1156 | + } else if (strncasecmp(encStr,"rre",encStrLen) == 0) { | |
1157 | + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRRE); | |
1158 | + } else { | |
1159 | + fprintf(stderr,"Unknown encoding '%.*s'\n",encStrLen,encStr); | |
1160 | + } | |
1161 | + | |
1162 | + encStr = nextEncStr; | |
1163 | + } while (encStr && se->nEncodings < MAX_ENCODINGS); | |
1164 | + | |
1165 | + if (se->nEncodings < MAX_ENCODINGS && requestCompressLevel) { | |
1166 | + encs[se->nEncodings++] = Swap32IfLE(opt.client.compresslevel + | |
1167 | + rfbEncodingCompressLevel0); | |
1168 | + } | |
1169 | + | |
1170 | + if (se->nEncodings < MAX_ENCODINGS && requestQualityLevel) { | |
1171 | + if (opt.client.quality < 0 || opt.client.quality > 9) | |
1172 | + opt.client.quality = 5; | |
1173 | + encs[se->nEncodings++] = Swap32IfLE(opt.client.quality + | |
1174 | + rfbEncodingQualityLevel0); | |
1175 | + } | |
1176 | + | |
1177 | + if (opt.localcursor) { | |
1178 | + if (se->nEncodings < MAX_ENCODINGS) | |
1179 | + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingXCursor); | |
1180 | + if (se->nEncodings < MAX_ENCODINGS) | |
1181 | + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRichCursor); | |
1182 | + if (se->nEncodings < MAX_ENCODINGS) | |
1183 | + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingPointerPos); | |
1184 | + } | |
1185 | + | |
1186 | + if (se->nEncodings < MAX_ENCODINGS && requestLastRectEncoding) { | |
1187 | + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingLastRect); | |
1188 | + } | |
1189 | + } else { | |
1190 | + if (SameMachine(sock)) { | |
1191 | + if (!tunnelSpecified) { | |
1192 | + fprintf(stderr,"Same machine: preferring raw encoding\n"); | |
1193 | + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRaw); | |
1194 | + } else { | |
1195 | + fprintf(stderr,"Tunneling active: preferring tight encoding\n"); | |
1196 | + } | |
1197 | + } | |
1198 | + | |
1199 | + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCopyRect); | |
1200 | + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingTight); | |
1201 | + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingHextile); | |
1202 | + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZlib); | |
1203 | + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCoRRE); | |
1204 | + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRRE); | |
1205 | + | |
1206 | + if (opt.client.compresslevel >= 0 && opt.client.compresslevel <= 9) { | |
1207 | + encs[se->nEncodings++] = Swap32IfLE(opt.client.compresslevel + | |
1208 | + rfbEncodingCompressLevel0); | |
1209 | + } else if (!tunnelSpecified) { | |
1210 | + /* If -tunnel option was provided, we assume that server machine is | |
1211 | + not in the local network so we use default compression level for | |
1212 | + tight encoding instead of fast compression. Thus we are | |
1213 | + requesting level 1 compression only if tunneling is not used. */ | |
1214 | + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCompressLevel1); | |
1215 | + } | |
1216 | +#if 0 | |
1217 | + if (appData.enableJPEG) { | |
1218 | + if (appData.qualityLevel < 0 || appData.qualityLevel > 9) | |
1219 | + appData.qualityLevel = 5; | |
1220 | + encs[se->nEncodings++] = Swap32IfLE(appData.qualityLevel + | |
1221 | + rfbEncodingQualityLevel0); | |
1222 | + } | |
1223 | +#endif | |
1224 | + | |
1225 | + if (opt.localcursor) { | |
1226 | + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingXCursor); | |
1227 | + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRichCursor); | |
1228 | + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingPointerPos); | |
1229 | + } | |
1230 | + | |
1231 | + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingLastRect); | |
1232 | + } | |
1233 | + | |
1234 | + len = sz_rfbSetEncodingsMsg + se->nEncodings * 4; | |
1235 | + | |
1236 | + se->nEncodings = Swap16IfLE(se->nEncodings); | |
1237 | + | |
1238 | + if (!write_exact(sock, buf, len)) return 0; | |
1239 | + | |
1240 | + return 1; | |
1241 | +} | |
1242 | + | |
1243 | +#if 0 | |
1244 | int | |
1245 | rfb_set_format_and_encodings() | |
1246 | { | |
1247 | @@ -312,7 +840,7 @@ | |
1248 | ||
1249 | return(1); | |
1250 | } | |
1251 | - | |
1252 | +#endif | |
1253 | ||
1254 | int | |
1255 | rfb_send_update_request(int incremental) | |
1256 | @@ -347,84 +875,93 @@ | |
1257 | rfbFramebufferUpdateRectHeader rectheader; | |
1258 | ||
1259 | if (!read_from_rfb_server(sock, (char*)&msg, 1)) return 0; | |
1260 | - switch (msg.type) | |
1261 | - { | |
1262 | - int i; | |
1263 | - case rfbFramebufferUpdate: | |
1264 | - read_from_rfb_server(sock, ((char*)&msg.fu)+1, sz_rfbFramebufferUpdateMsg-1); | |
1265 | - msg.fu.nRects = Swap16IfLE(msg.fu.nRects); | |
1266 | - for (i=0;i< msg.fu.nRects;i++) | |
1267 | - { | |
1268 | - read_from_rfb_server(sock, (char*)&rectheader, | |
1269 | - sz_rfbFramebufferUpdateRectHeader); | |
1270 | - rectheader.r.x = Swap16IfLE(rectheader.r.x); | |
1271 | - rectheader.r.y = Swap16IfLE(rectheader.r.y); | |
1272 | - rectheader.r.w = Swap16IfLE(rectheader.r.w); | |
1273 | - rectheader.r.h = Swap16IfLE(rectheader.r.h); | |
1274 | - rectheader.encoding = Swap32IfLE(rectheader.encoding); | |
1275 | - SoftCursorLockArea(rectheader.r.x, rectheader.r.y, rectheader.r.w, rectheader.r.h); | |
1276 | - switch (rectheader.encoding) | |
1277 | - { | |
1278 | - case rfbEncodingRaw: | |
1279 | - _handle_raw_encoded_message(rectheader); | |
1280 | - break; | |
1281 | - case rfbEncodingCopyRect: | |
1282 | - _handle_copyrect_encoded_message(rectheader); | |
1283 | - break; | |
1284 | - case rfbEncodingRRE: | |
1285 | - _handle_rre_encoded_message(rectheader); | |
1286 | - break; | |
1287 | - case rfbEncodingCoRRE: | |
1288 | - _handle_corre_encoded_message(rectheader); | |
1289 | - break; | |
1290 | - case rfbEncodingHextile: | |
1291 | - _handle_hextile_encoded_message(rectheader); | |
1292 | - break; | |
1293 | - case rfbEncodingTight: | |
1294 | - _handle_tight_encoded_message(rectheader); | |
1295 | - break; | |
1296 | - case rfbEncodingZlib: | |
1297 | - _handle_zlib_encoded_message(rectheader); | |
1298 | - break; | |
1299 | - case rfbEncodingRichCursor: | |
1300 | - _handle_richcursor_message(rectheader); | |
1301 | - break; | |
1302 | + switch (msg.type) { | |
1303 | + int i; | |
1304 | + case rfbFramebufferUpdate: | |
1305 | + read_from_rfb_server(sock, ((char*)&msg.fu)+1, sz_rfbFramebufferUpdateMsg-1); | |
1306 | + msg.fu.nRects = Swap16IfLE(msg.fu.nRects); | |
1307 | + | |
1308 | + for (i=0;i< msg.fu.nRects;i++) { | |
1309 | + read_from_rfb_server(sock, (char*)&rectheader, sz_rfbFramebufferUpdateRectHeader); | |
1310 | + rectheader.r.x = Swap16IfLE(rectheader.r.x); | |
1311 | + rectheader.r.y = Swap16IfLE(rectheader.r.y); | |
1312 | + rectheader.r.w = Swap16IfLE(rectheader.r.w); | |
1313 | + rectheader.r.h = Swap16IfLE(rectheader.r.h); | |
1314 | + rectheader.encoding = Swap32IfLE(rectheader.encoding); | |
1315 | + if (rectheader.encoding == rfbEncodingLastRect) break; | |
1316 | + | |
1317 | + if (rectheader.encoding == rfbEncodingPointerPos) { | |
1318 | + if (!HandleCursorPos(rectheader.r.x, rectheader.r.y)) { | |
1319 | + return 0; | |
1320 | + } | |
1321 | + continue; | |
1322 | + } | |
1323 | + SoftCursorLockArea(rectheader.r.x, rectheader.r.y, rectheader.r.w, rectheader.r.h); | |
1324 | + | |
1325 | + switch (rectheader.encoding) { | |
1326 | + case rfbEncodingRaw: | |
1327 | + _handle_raw_encoded_message(rectheader); | |
1328 | + break; | |
1329 | + case rfbEncodingCopyRect: | |
1330 | + _handle_copyrect_encoded_message(rectheader); | |
1331 | + break; | |
1332 | + case rfbEncodingRRE: | |
1333 | + _handle_rre_encoded_message(rectheader); | |
1334 | + break; | |
1335 | + case rfbEncodingCoRRE: | |
1336 | + _handle_corre_encoded_message(rectheader); | |
1337 | + break; | |
1338 | + case rfbEncodingHextile: | |
1339 | + _handle_hextile_encoded_message(rectheader); | |
1340 | + break; | |
1341 | + case rfbEncodingTight: | |
1342 | + _handle_tight_encoded_message(rectheader); | |
1343 | + break; | |
1344 | + case rfbEncodingZlib: | |
1345 | + _handle_zlib_encoded_message(rectheader); | |
1346 | + break; | |
1347 | + case rfbEncodingRichCursor: | |
1348 | + case rfbEncodingXCursor: | |
1349 | + _handle_richcursor_message(rectheader); | |
1350 | + break; | |
1351 | +#if 0 | |
1352 | case rfbEncodingLastRect: | |
1353 | - printf("LAST\n"); | |
1354 | + fprintf(stderr, "LAST\n"); | |
1355 | break; | |
1356 | - | |
1357 | - default: | |
1358 | - printf("Unknown encoding\n"); | |
1359 | - return 0; | |
1360 | - break; | |
1361 | - } | |
1362 | - /* Now we may discard "soft cursor locks". */ | |
1363 | - SoftCursorUnlockScreen(); | |
1364 | +#endif | |
1365 | + default: | |
1366 | + fprintf(stderr, "Unknown encoding: %x\n", rectheader.encoding); | |
1367 | + return 0; | |
1368 | + break; | |
1369 | + } | |
1370 | + /* Now we may discard "soft cursor locks". */ | |
1371 | + SoftCursorUnlockScreen(); | |
1372 | + } | |
1373 | + if (!rfb_send_update_request(1)) return 0; | |
1374 | ||
1375 | - } | |
1376 | - break; | |
1377 | - case rfbSetColourMapEntries: | |
1378 | - fprintf(stderr, "SetColourMapEntries\n"); | |
1379 | - read_from_rfb_server(sock, ((char*)&msg.scme)+1, sz_rfbSetColourMapEntriesMsg-1); | |
1380 | - break; | |
1381 | - case rfbBell: | |
1382 | - fprintf(stderr, "Bell message. Unimplemented.\n"); | |
1383 | - break; | |
1384 | - case rfbServerCutText: | |
1385 | - fprintf(stderr, "ServerCutText. Unimplemented.\n"); | |
1386 | - read_from_rfb_server(sock, ((char*)&msg.sct)+1, | |
1387 | - sz_rfbServerCutTextMsg-1); | |
1388 | - size = Swap32IfLE(msg.sct.length); | |
1389 | - buf = malloc(sizeof(char) * size); | |
1390 | - read_from_rfb_server(sock, buf, size); | |
1391 | - buf[size]=0; | |
1392 | - printf("%s\n", buf); | |
1393 | - free(buf); | |
1394 | - break; | |
1395 | - default: | |
1396 | - printf("Unknown server message. Type: %i\n", msg.type); | |
1397 | - return 0; | |
1398 | - break; | |
1399 | + break; | |
1400 | + | |
1401 | + case rfbSetColourMapEntries: | |
1402 | + fprintf(stderr, "SetColourMapEntries\n"); | |
1403 | + read_from_rfb_server(sock, ((char*)&msg.scme)+1, sz_rfbSetColourMapEntriesMsg-1); | |
1404 | + break; | |
1405 | + case rfbBell: | |
1406 | + fprintf(stderr, "Bell message. Unimplemented.\n"); | |
1407 | + break; | |
1408 | + case rfbServerCutText: | |
1409 | + fprintf(stderr, "ServerCutText. Unimplemented.\n"); | |
1410 | + read_from_rfb_server(sock, ((char*)&msg.sct)+1, sz_rfbServerCutTextMsg-1); | |
1411 | + size = Swap32IfLE(msg.sct.length); | |
1412 | + buf = malloc(sizeof(char) * size); | |
1413 | + read_from_rfb_server(sock, buf, size); | |
1414 | + buf[size]=0; | |
1415 | + printf("%s\n", buf); | |
1416 | + free(buf); | |
1417 | + break; | |
1418 | + default: | |
1419 | + printf("Unknown server message. Type: %i\n", msg.type); | |
1420 | + return 0; | |
1421 | + break; | |
1422 | } | |
1423 | return(1); | |
1424 | } | |
1425 | @@ -688,7 +1225,7 @@ | |
1426 | static int | |
1427 | _handle_richcursor_message(rfbFramebufferUpdateRectHeader rectheader) | |
1428 | { | |
1429 | - return HandleRichCursor(rectheader.r.x, rectheader.r.y, rectheader.r.w, rectheader.r.h); | |
1430 | + return HandleCursorShape(rectheader.r.x, rectheader.r.y, rectheader.r.w, rectheader.r.h, rectheader.encoding); | |
1431 | } | |
1432 | ||
1433 | void | |
1434 | diff -Nru directvnc-0.7.5/src/rfbproto.h directvnc-0.7.5.new/src/rfbproto.h | |
1435 | --- directvnc-0.7.5/src/rfbproto.h 2002-07-07 18:50:02.000000000 +0200 | |
1436 | +++ directvnc-0.7.5.new/src/rfbproto.h 2007-01-15 16:42:12.000000000 +0100 | |
1437 | @@ -1,3 +1,5 @@ | |
1438 | +#ifndef VNC_RFBPROTO_H | |
1439 | +#define VNC_RFBPROTO_H | |
1440 | /* | |
1441 | * Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved. | |
1442 | * Copyright (C) 2000 Tridia Corporation. All Rights Reserved. | |
1443 | @@ -20,7 +22,7 @@ | |
1444 | */ | |
1445 | ||
1446 | /* | |
1447 | - * rfbproto.h - header file for the RFB protocol version 3.3 | |
1448 | + * rfbproto.h - header file for the RFB protocol version 3.7 | |
1449 | * | |
1450 | * Uses types CARD<n> for an n-bit unsigned integer, INT<n> for an n-bit signed | |
1451 | * integer (for n = 8, 16 and 32). | |
1452 | @@ -155,7 +157,8 @@ | |
1453 | ||
1454 | #define rfbProtocolVersionFormat "RFB %03d.%03d\n" | |
1455 | #define rfbProtocolMajorVersion 3 | |
1456 | -#define rfbProtocolMinorVersion 3 | |
1457 | +#define rfbProtocolMinorVersion 7 | |
1458 | +#define rfbProtocolFallbackMinorVersion 3 | |
1459 | ||
1460 | typedef char rfbProtocolVersionMsg[13]; /* allow extra byte for null */ | |
1461 | ||
1462 | @@ -163,6 +166,31 @@ | |
1463 | ||
1464 | ||
1465 | /*----------------------------------------------------------------------------- | |
1466 | + * Structure used to describe protocol options such as tunneling methods, | |
1467 | + * authentication schemes and message types (protocol version 3.7t). | |
1468 | + */ | |
1469 | + | |
1470 | +typedef struct _rfbCapabilityInfo { | |
1471 | + | |
1472 | + CARD32 code; /* numeric identifier */ | |
1473 | + CARD8 vendorSignature[4]; /* vendor identification */ | |
1474 | + CARD8 nameSignature[8]; /* abbreviated option name */ | |
1475 | + | |
1476 | +} rfbCapabilityInfo; | |
1477 | + | |
1478 | +#define sz_rfbCapabilityInfoVendor 4 | |
1479 | +#define sz_rfbCapabilityInfoName 8 | |
1480 | +#define sz_rfbCapabilityInfo 16 | |
1481 | + | |
1482 | +/* | |
1483 | + * Vendors known by TightVNC: standard VNC/RealVNC, TridiaVNC, and TightVNC. | |
1484 | + */ | |
1485 | + | |
1486 | +#define rfbStandardVendor "STDV" | |
1487 | +#define rfbTridiaVncVendor "TRDV" | |
1488 | +#define rfbTightVncVendor "TGHT" | |
1489 | + | |
1490 | +/*----------------------------------------------------------------------------- | |
1491 | * Authentication | |
1492 | * | |
1493 | * Once the protocol version has been decided, the server then sends a 32-bit | |
1494 | @@ -174,6 +202,7 @@ | |
1495 | #define rfbConnFailed 0 | |
1496 | #define rfbNoAuth 1 | |
1497 | #define rfbVncAuth 2 | |
1498 | +#define rfbSecTypeTight 16 | |
1499 | ||
1500 | /* | |
1501 | * rfbConnFailed: For some reason the connection failed (e.g. the server | |
1502 | @@ -201,6 +230,160 @@ | |
1503 | #define rfbVncAuthFailed 1 | |
1504 | #define rfbVncAuthTooMany 2 | |
1505 | ||
1506 | +/*----------------------------------------------------------------------------- | |
1507 | + * Negotiation of Tunneling Capabilities (protocol version 3.7t) | |
1508 | + * | |
1509 | + * If the chosen security type is rfbSecTypeTight, the server sends a list of | |
1510 | + * supported tunneling methods ("tunneling" refers to any additional layer of | |
1511 | + * data transformation, such as encryption or external compression.) | |
1512 | + * | |
1513 | + * nTunnelTypes specifies the number of following rfbCapabilityInfo structures | |
1514 | + * that list all supported tunneling methods in the order of preference. | |
1515 | + * | |
1516 | + * NOTE: If nTunnelTypes is 0, that tells the client that no tunneling can be | |
1517 | + * used, and the client should not send a response requesting a tunneling | |
1518 | + * method. | |
1519 | + */ | |
1520 | + | |
1521 | +typedef struct _rfbTunnelingCapsMsg { | |
1522 | + CARD32 nTunnelTypes; | |
1523 | + /* followed by nTunnelTypes * rfbCapabilityInfo structures */ | |
1524 | +} rfbTunnelingCapsMsg; | |
1525 | + | |
1526 | +#define sz_rfbTunnelingCapsMsg 4 | |
1527 | + | |
1528 | +/*----------------------------------------------------------------------------- | |
1529 | + * Tunneling Method Request (protocol version 3.7t) | |
1530 | + * | |
1531 | + * If the list of tunneling capabilities sent by the server was not empty, the | |
1532 | + * client should reply with a 32-bit code specifying a particular tunneling | |
1533 | + * method. The following code should be used for no tunneling. | |
1534 | + */ | |
1535 | + | |
1536 | +#define rfbNoTunneling 0 | |
1537 | +#define sig_rfbNoTunneling "NOTUNNEL" | |
1538 | + | |
1539 | +/*----------------------------------------------------------------------------- | |
1540 | + * Negotiation of Authentication Capabilities (protocol version 3.7t) | |
1541 | + * | |
1542 | + * After setting up tunneling, the server sends a list of supported | |
1543 | + * authentication schemes. | |
1544 | + * | |
1545 | + * nAuthTypes specifies the number of following rfbCapabilityInfo structures | |
1546 | + * that list all supported authentication schemes in the order of preference. | |
1547 | + * | |
1548 | + * NOTE: If nAuthTypes is 0, that tells the client that no authentication is | |
1549 | + * necessary, and the client should not send a response requesting an | |
1550 | + * authentication scheme. | |
1551 | + */ | |
1552 | + | |
1553 | +typedef struct _rfbAuthenticationCapsMsg { | |
1554 | + CARD32 nAuthTypes; | |
1555 | + /* followed by nAuthTypes * rfbCapabilityInfo structures */ | |
1556 | +} rfbAuthenticationCapsMsg; | |
1557 | + | |
1558 | +#define sz_rfbAuthenticationCapsMsg 4 | |
1559 | + | |
1560 | +/*----------------------------------------------------------------------------- | |
1561 | + * Authentication Scheme Request (protocol version 3.7t) | |
1562 | + * | |
1563 | + * If the list of authentication capabilities sent by the server was not empty, | |
1564 | + * the client should reply with a 32-bit code specifying a particular | |
1565 | + * authentication scheme. The following codes are supported. | |
1566 | + */ | |
1567 | + | |
1568 | +#define rfbAuthNone 1 | |
1569 | +#define rfbAuthVNC 2 | |
1570 | +#define rfbAuthUnixLogin 129 | |
1571 | +#define rfbAuthExternal 130 | |
1572 | + | |
1573 | +#define sig_rfbAuthNone "NOAUTH__" | |
1574 | +#define sig_rfbAuthVNC "VNCAUTH_" | |
1575 | +#define sig_rfbAuthUnixLogin "ULGNAUTH" | |
1576 | +#define sig_rfbAuthExternal "XTRNAUTH" | |
1577 | + | |
1578 | +/* signatures for basic encoding types */ | |
1579 | +#define sig_rfbEncodingRaw "RAW_____" | |
1580 | +#define sig_rfbEncodingCopyRect "COPYRECT" | |
1581 | +#define sig_rfbEncodingRRE "RRE_____" | |
1582 | +#define sig_rfbEncodingCoRRE "CORRE___" | |
1583 | +#define sig_rfbEncodingHextile "HEXTILE_" | |
1584 | +#define sig_rfbEncodingZlib "ZLIB____" | |
1585 | +#define sig_rfbEncodingTight "TIGHT___" | |
1586 | +#define sig_rfbEncodingZlibHex "ZLIBHEX_" | |
1587 | + | |
1588 | +/* | |
1589 | + * Special encoding numbers: | |
1590 | + * 0xFFFFFF00 .. 0xFFFFFF0F -- encoding-specific compression levels; | |
1591 | + * 0xFFFFFF10 .. 0xFFFFFF1F -- mouse cursor shape data; | |
1592 | + * 0xFFFFFF20 .. 0xFFFFFF2F -- various protocol extensions; | |
1593 | + * 0xFFFFFF30 .. 0xFFFFFFDF -- not allocated yet; | |
1594 | + * 0xFFFFFFE0 .. 0xFFFFFFEF -- quality level for JPEG compressor; | |
1595 | + * 0xFFFFFFF0 .. 0xFFFFFFFF -- not allocated yet. | |
1596 | + */ | |
1597 | + | |
1598 | +#define rfbEncodingCompressLevel0 0xFFFFFF00 | |
1599 | +#define rfbEncodingCompressLevel1 0xFFFFFF01 | |
1600 | +#define rfbEncodingCompressLevel2 0xFFFFFF02 | |
1601 | +#define rfbEncodingCompressLevel3 0xFFFFFF03 | |
1602 | +#define rfbEncodingCompressLevel4 0xFFFFFF04 | |
1603 | +#define rfbEncodingCompressLevel5 0xFFFFFF05 | |
1604 | +#define rfbEncodingCompressLevel6 0xFFFFFF06 | |
1605 | +#define rfbEncodingCompressLevel7 0xFFFFFF07 | |
1606 | +#define rfbEncodingCompressLevel8 0xFFFFFF08 | |
1607 | +#define rfbEncodingCompressLevel9 0xFFFFFF09 | |
1608 | + | |
1609 | +#define rfbEncodingXCursor 0xFFFFFF10 | |
1610 | +#define rfbEncodingRichCursor 0xFFFFFF11 | |
1611 | +#define rfbEncodingPointerPos 0xFFFFFF18 | |
1612 | + | |
1613 | +#define rfbEncodingLastRect 0xFFFFFF20 | |
1614 | +#define rfbEncodingNewFBSize 0xFFFFFF21 | |
1615 | + | |
1616 | +#define rfbEncodingQualityLevel0 0xFFFFFFE0 | |
1617 | +#define rfbEncodingQualityLevel1 0xFFFFFFE1 | |
1618 | +#define rfbEncodingQualityLevel2 0xFFFFFFE2 | |
1619 | +#define rfbEncodingQualityLevel3 0xFFFFFFE3 | |
1620 | +#define rfbEncodingQualityLevel4 0xFFFFFFE4 | |
1621 | +#define rfbEncodingQualityLevel5 0xFFFFFFE5 | |
1622 | +#define rfbEncodingQualityLevel6 0xFFFFFFE6 | |
1623 | +#define rfbEncodingQualityLevel7 0xFFFFFFE7 | |
1624 | +#define rfbEncodingQualityLevel8 0xFFFFFFE8 | |
1625 | +#define rfbEncodingQualityLevel9 0xFFFFFFE9 | |
1626 | + | |
1627 | +/* signatures for "fake" encoding types */ | |
1628 | +#define sig_rfbEncodingCompressLevel0 "COMPRLVL" | |
1629 | +#define sig_rfbEncodingXCursor "X11CURSR" | |
1630 | +#define sig_rfbEncodingRichCursor "RCHCURSR" | |
1631 | +#define sig_rfbEncodingPointerPos "POINTPOS" | |
1632 | +#define sig_rfbEncodingLastRect "LASTRECT" | |
1633 | +#define sig_rfbEncodingNewFBSize "NEWFBSIZ" | |
1634 | +#define sig_rfbEncodingQualityLevel0 "JPEGQLVL" | |
1635 | + | |
1636 | +/*----------------------------------------------------------------------------- | |
1637 | + * Server Interaction Capabilities Message (protocol version 3.7t) | |
1638 | + * | |
1639 | + * In the protocol version 3.7t, the server informs the client what message | |
1640 | + * types it supports in addition to ones defined in the protocol version 3.7. | |
1641 | + * Also, the server sends the list of all supported encodings (note that it's | |
1642 | + * not necessary to advertise the "raw" encoding sinse it MUST be supported in | |
1643 | + * RFB 3.x protocols). | |
1644 | + * | |
1645 | + * This data immediately follows the server initialisation message. | |
1646 | + */ | |
1647 | + | |
1648 | +typedef struct _rfbInteractionCapsMsg { | |
1649 | + CARD16 nServerMessageTypes; | |
1650 | + CARD16 nClientMessageTypes; | |
1651 | + CARD16 nEncodingTypes; | |
1652 | + CARD16 pad; /* reserved, must be 0 */ | |
1653 | + /* followed by nServerMessageTypes * rfbCapabilityInfo structures */ | |
1654 | + /* followed by nClientMessageTypes * rfbCapabilityInfo structures */ | |
1655 | +} rfbInteractionCapsMsg; | |
1656 | + | |
1657 | +#define sz_rfbInteractionCapsMsg 8 | |
1658 | + | |
1659 | + | |
1660 | ||
1661 | /*----------------------------------------------------------------------------- | |
1662 | * Client Initialisation Message | |
1663 | @@ -783,3 +966,5 @@ | |
1664 | rfbPointerEventMsg pe; | |
1665 | rfbClientCutTextMsg cct; | |
1666 | } rfbClientToServerMsg; | |
1667 | + | |
1668 | +#endif /* VNC_RFBPROTO_H */ | |
1669 | diff -Nru directvnc-0.7.5/src/sockets.c directvnc-0.7.5.new/src/sockets.c | |
1670 | --- directvnc-0.7.5/src/sockets.c 2003-01-31 08:33:02.000000000 +0100 | |
1671 | +++ directvnc-0.7.5.new/src/sockets.c 2007-01-15 17:22:15.000000000 +0100 | |
1672 | @@ -273,3 +273,19 @@ | |
1673 | ||
1674 | fflush(stderr); | |
1675 | } | |
1676 | + | |
1677 | +/* | |
1678 | + * Test if the other end of a socket is on the same machine. | |
1679 | + */ | |
1680 | + | |
1681 | +int | |
1682 | +SameMachine(int sock) | |
1683 | +{ | |
1684 | + struct sockaddr_in peeraddr, myaddr; | |
1685 | + int addrlen = sizeof(struct sockaddr_in); | |
1686 | + | |
1687 | + getpeername(sock, (struct sockaddr *)&peeraddr, &addrlen); | |
1688 | + getsockname(sock, (struct sockaddr *)&myaddr, &addrlen); | |
1689 | + | |
1690 | + return (peeraddr.sin_addr.s_addr == myaddr.sin_addr.s_addr); | |
1691 | +} |