gt:       sock = new Socket(host, port);
context: //
  //  Copyright (C) 2001-2004 HorizonLive.com, Inc.  All Rights Reserved.
  //  Copyright (C) 2001-2006 Constantin Kaplinsky.  All Rights Reserved.
  //  Copyright (C) 2000 Tridia Corporation.  All Rights Reserved.
  //  Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.
  //
  //  This is free software; you can redistribute it and/or modify
  //  it under the terms of the GNU General Public License as published by
  //  the Free Software Foundation; either version 2 of the License, or
  //  (at your option) any later version.
  //
  //  This software is distributed in the hope that it will be useful,
  //  but WITHOUT ANY WARRANTY; without even the implied warranty of
  //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  //  GNU General Public License for more details.
  //
  //  You should have received a copy of the GNU General Public License
  //  along with this software; if not, write to the Free Software
  //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
  //  USA.
  //
  
  //
  // Extensions to support mouse wheel, UnicodeToX11, and XVP server
  // Copyright (C) 2009-2011 Colin Dean. 
  //
  
  //
  // RfbProto.java
  //
  
  import java.io.*;
  import java.awt.*;
  import java.awt.event.*;
  import java.net.Socket;
  import java.util.zip.*;
  
  class RfbProto {
  
    final static String
      versionMsg_3_3 = "RFB 003.003\n",
      versionMsg_3_7 = "RFB 003.007\n",
      versionMsg_3_8 = "RFB 003.008\n";
  
    // Vendor signatures: standard VNC/RealVNC, TridiaVNC, and TightVNC
    final static String
      StandardVendor  = "STDV",
      TridiaVncVendor = "TRDV",
      TightVncVendor  = "TGHT";
  
    // Security types
    final static int
      SecTypeInvalid = 0,
      SecTypeNone    = 1,
      SecTypeVncAuth = 2,
      SecTypeTight   = 16,
      SecTypeXvpAuth = 22;
  
    // Supported tunneling types
    final static int
      NoTunneling = 0;
    final static String
      SigNoTunneling = "NOTUNNEL";
  
    // Supported authentication types
    final static int
      AuthNone      = 1,
      AuthVNC       = 2,
      AuthXVP       = 22,
      AuthUnixLogin = 129;
    final static String
      SigAuthNone      = "NOAUTH__",
      SigAuthVNC       = "VNCAUTH_",
      SigAuthXVP       = "XVPAUTH_",
      SigAuthUnixLogin = "ULGNAUTH";
  
    // VNC authentication results
    final static int
      VncAuthOK      = 0,
      VncAuthFailed  = 1,
      VncAuthTooMany = 2;
  
    // Standard server-to-client messages
    final static int
      FramebufferUpdate   = 0,
      SetColourMapEntries = 1,
      Bell                = 2,
      ServerCutText       = 3;
  
    // Non-standard server-to-client messages
    final static int
      EndOfContinuousUpdates = 150,
      ServerXVPCode          = 250; // officially allocated for XVP
  
    final static String
      SigEndOfContinuousUpdates = "CUS_EOCU",
      SigServerXVPCode          = "CUS_XVPC";
  
    // Standard client-to-server messages
    final static int
      SetPixelFormat           = 0,
      FixColourMapEntries      = 1,
      SetEncodings             = 2,
      FramebufferUpdateRequest = 3,
      KeyboardEvent            = 4,
      PointerEvent             = 5,
      ClientCutText            = 6;
  
    // Non-standard client-to-server messages
    final static int
      EnableContinuousUpdates = 150,
      ClientXVPCode           = 250; // officially allocated for XVP
    final static String
      SigEnableContinuousUpdates = "CUC_ENCU",
      SigClientXVPCode           = "CUC_XVPC";
  
    // Supported encodings and pseudo-encodings
    final static int
      EncodingRaw            = 0,
      EncodingCopyRect       = 1,
      EncodingRRE            = 2,
      EncodingCoRRE          = 4,
      EncodingHextile        = 5,
      EncodingZlib           = 6,
      EncodingTight          = 7,
      EncodingZRLE           = 16,
      EncodingCompressLevel0 = 0xFFFFFF00,
      EncodingQualityLevel0  = 0xFFFFFFE0,
      EncodingXCursor        = 0xFFFFFF10,
      EncodingRichCursor     = 0xFFFFFF11,
      EncodingPointerPos     = 0xFFFFFF18,
      EncodingLastRect       = 0xFFFFFF20,
      EncodingNewFBSize      = 0xFFFFFF21,
      EncodingXVP            = 0xFFFFFECB; // officially allocated for XVP
  
    final static String
      SigEncodingRaw            = "RAW_____",
      SigEncodingCopyRect       = "COPYRECT",
      SigEncodingRRE            = "RRE_____",
      SigEncodingCoRRE          = "CORRE___",
      SigEncodingHextile        = "HEXTILE_",
      SigEncodingZlib           = "ZLIB____",
      SigEncodingTight          = "TIGHT___",
      SigEncodingZRLE           = "ZRLE____",
      SigEncodingCompressLevel0 = "COMPRLVL",
      SigEncodingQualityLevel0  = "JPEGQLVL",
      SigEncodingXCursor        = "X11CURSR",
      SigEncodingRichCursor     = "RCHCURSR",
      SigEncodingPointerPos     = "POINTPOS",
      SigEncodingLastRect       = "LASTRECT",
      SigEncodingNewFBSize      = "NEWFBSIZ",
      SigEncodingXVP            = "XVP_____";
  
    final static int MaxNormalEncoding = 255;
  
    // Contstants used in the Hextile decoder
    final static int
      HextileRaw                 = 1,
      HextileBackgroundSpecified = 2,
      HextileForegroundSpecified = 4,
      HextileAnySubrects         = 8,
      HextileSubrectsColoured    = 16;
  
    // Contstants used in the Tight decoder
    final static int TightMinToCompress = 12;
    final static int
      TightExplicitFilter = 0x04,
      TightFill           = 0x08,
      TightJpeg           = 0x09,
      TightMaxSubencoding = 0x09,
      TightFilterCopy     = 0x00,
      TightFilterPalette  = 0x01,
      TightFilterGradient = 0x02;
  
    // Constants used by XVP extension messages
    final static int
      XVPMessageVersion = 1,
      XVPCodeFail       = 0,
      XVPCodeInit       = 1,
      XVPCodeShutdown   = 2,
      XVPCodeReboot     = 3,
      XVPCodeReset      = 4;
  
    String host;
    int port;
    Socket sock;
    OutputStream os;
    SessionRecorder rec;
    boolean inNormalProtocol = false;
    VncViewer viewer;
  
    // Input stream is declared private to make sure it can be accessed
    // only via RfbProto methods. We have to do this because we want to
    // count how many bytes were read.
    private DataInputStream is;
    private long numBytesRead = 0;
    public long getNumBytesRead() { return numBytesRead; }
  
    // Java on UNIX does not call keyPressed() on some keys, for example
    // swedish keys To prevent our workaround to produce duplicate
    // keypresses on JVMs that actually works, keep track of if
    // keyPressed() for a "broken" key was called or not. 
    boolean brokenKeyPressed = false;
  
    // This will be set to true on the first framebuffer update
    // containing Zlib-, ZRLE- or Tight-encoded data.
    boolean wereZlibUpdates = false;
  
    // This will be set to false if the startSession() was called after
    // we have received at least one Zlib-, ZRLE- or Tight-encoded
    // framebuffer update.
    boolean recordFromBeginning = true;
  
    // This fields are needed to show warnings about inefficiently saved
    // sessions only once per each saved session file.
    boolean zlibWarningShown;
    boolean tightWarningShown;
  
    // Before starting to record each saved session, we set this field
    // to 0, and increment on each framebuffer update. We don't flush
    // the SessionRecorder data into the file before the second update. 
    // This allows us to write initial framebuffer update with zero
    // timestamp, to let the player show initial desktop before
    // playback.
    int numUpdatesInSession;
  
    // Measuring network throughput.
    boolean timing;
    long timeWaitedIn100us;
    long timedKbits;
  
    // Protocol version and TightVNC-specific protocol options.
    int serverMajor, serverMinor;
    int clientMajor, clientMinor;
    boolean protocolTightVNC;
    CapsContainer tunnelCaps, authCaps;
    CapsContainer serverMsgCaps, clientMsgCaps;
    CapsContainer encodingCaps;
  
    // If true, informs that the RFB socket was closed.
    private boolean closed;
  
    //
    // Constructor. Make TCP connection to RFB server.
    //
  
    RfbProto(String h, int p, VncViewer v) throws IOException {
      viewer = v;
      host = h;
      port = p;
  
      if (viewer.socketFactory == null) {
  