]> git.pld-linux.org Git - packages/directvnc.git/blob - directvnc-3.3.7-tight.patch
- added the 3.3.7-tight patch
[packages/directvnc.git] / directvnc-3.3.7-tight.patch
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 +}
This page took 0.446986 seconds and 3 git commands to generate.