Preliminary version of RFB Session Player converted from TightVNC Java
viewer sources.

git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@2500 3789f03b-4d11-0410-bbf8-ca57d06f2519
diff --git a/java/src/com/tightvnc/rfbplayer/RfbProto.java b/java/src/com/tightvnc/rfbplayer/RfbProto.java
index a86aac5..daff66c 100644
--- a/java/src/com/tightvnc/rfbplayer/RfbProto.java
+++ b/java/src/com/tightvnc/rfbplayer/RfbProto.java
@@ -73,36 +73,25 @@
 
   final static int TightMinToCompress   = 12;
 
-  String host;
-  int port;
-  Socket sock;
   DataInputStream is;
-  OutputStream os;
-  boolean inNormalProtocol = false;
-  VncViewer viewer;
 
 
   //
-  // Constructor.  Just make TCP connection to RFB server.
+  // Constructor.
   //
 
-  RfbProto(String h, int p, VncViewer v) throws IOException {
-    viewer = v;
-    host = h;
-    port = p;
-    sock = new Socket(host, port);
-    is = new DataInputStream(new BufferedInputStream(sock.getInputStream(),
-						     16384));
-    os = sock.getOutputStream();
+  RfbProto(InputStream is) throws IOException {
+    newInputStream(is);
   }
 
+  public void newInputStream(InputStream is) throws IOException {
+    this.is = new DataInputStream(is);
 
-  void close() {
-    try {
-      sock.close();
-    } catch (Exception e) {
-      e.printStackTrace();
+    readVersionMsg();
+    if (readAuthScheme() != NoAuth) {
+      throw new IOException("Wrong authentication type in the session file");
     }
+    readServerInit();
   }
 
   //
@@ -123,8 +112,7 @@
 	|| (b[8] < '0') || (b[8] > '9') || (b[9] < '0') || (b[9] > '9')
 	|| (b[10] < '0') || (b[10] > '9') || (b[11] != '\n'))
     {
-      throw new IOException("Host " + host + " port " + port +
-			    " is not an RFB server");
+      throw new IOException("Incorrect protocol version");
     }
 
     serverMajor = (b[4] - '0') * 100 + (b[5] - '0') * 10 + (b[6] - '0');
@@ -133,15 +121,6 @@
 
 
   //
-  // Write our protocol version message
-  //
-
-  void writeVersionMsg() throws IOException {
-    os.write(versionMsg.getBytes());
-  }
-
-
-  //
   // Find out the authentication scheme.
   //
 
@@ -161,28 +140,13 @@
       return authScheme;
 
     default:
-      throw new IOException("Unknown authentication scheme from RFB " +
-			    "server " + authScheme);
+      throw new IOException("Unknown authentication scheme " + authScheme);
 
     }
   }
 
 
   //
-  // Write the client initialisation message
-  //
-
-  void writeClientInit() throws IOException {
-    if (viewer.options.shareDesktop) {
-      os.write(1);
-    } else {
-      os.write(0);
-    }
-    viewer.options.disableShareDesktop();
-  }
-
-
-  //
   // Read the server initialisation message
   //
 
@@ -211,8 +175,6 @@
     byte[] name = new byte[nameLength];
     is.readFully(name);
     desktopName = new String(name);
-
-    inNormalProtocol = true;
   }
 
 
@@ -311,368 +273,4 @@
     return len;
   }
 
-
-  //
-  // Write a FramebufferUpdateRequest message
-  //
-
-  void writeFramebufferUpdateRequest(int x, int y, int w, int h,
-				     boolean incremental)
-       throws IOException
-  {
-    byte[] b = new byte[10];
-
-    b[0] = (byte) FramebufferUpdateRequest;
-    b[1] = (byte) (incremental ? 1 : 0);
-    b[2] = (byte) ((x >> 8) & 0xff);
-    b[3] = (byte) (x & 0xff);
-    b[4] = (byte) ((y >> 8) & 0xff);
-    b[5] = (byte) (y & 0xff);
-    b[6] = (byte) ((w >> 8) & 0xff);
-    b[7] = (byte) (w & 0xff);
-    b[8] = (byte) ((h >> 8) & 0xff);
-    b[9] = (byte) (h & 0xff);
-
-    os.write(b);
-  }
-
-
-  //
-  // Write a SetPixelFormat message
-  //
-
-  void writeSetPixelFormat(int bitsPerPixel, int depth, boolean bigEndian,
-			   boolean trueColour,
-			   int redMax, int greenMax, int blueMax,
-			   int redShift, int greenShift, int blueShift)
-       throws IOException
-  {
-    byte[] b = new byte[20];
-
-    b[0]  = (byte) SetPixelFormat;
-    b[4]  = (byte) bitsPerPixel;
-    b[5]  = (byte) depth;
-    b[6]  = (byte) (bigEndian ? 1 : 0);
-    b[7]  = (byte) (trueColour ? 1 : 0);
-    b[8]  = (byte) ((redMax >> 8) & 0xff);
-    b[9]  = (byte) (redMax & 0xff);
-    b[10] = (byte) ((greenMax >> 8) & 0xff);
-    b[11] = (byte) (greenMax & 0xff);
-    b[12] = (byte) ((blueMax >> 8) & 0xff);
-    b[13] = (byte) (blueMax & 0xff);
-    b[14] = (byte) redShift;
-    b[15] = (byte) greenShift;
-    b[16] = (byte) blueShift;
-
-    os.write(b);
-  }
-
-
-  //
-  // Write a FixColourMapEntries message.  The values in the red, green and
-  // blue arrays are from 0 to 65535.
-  //
-
-  void writeFixColourMapEntries(int firstColour, int nColours,
-				int[] red, int[] green, int[] blue)
-       throws IOException
-  {
-    byte[] b = new byte[6 + nColours * 6];
-
-    b[0] = (byte) FixColourMapEntries;
-    b[2] = (byte) ((firstColour >> 8) & 0xff);
-    b[3] = (byte) (firstColour & 0xff);
-    b[4] = (byte) ((nColours >> 8) & 0xff);
-    b[5] = (byte) (nColours & 0xff);
-
-    for (int i = 0; i < nColours; i++) {
-      b[6 + i * 6]     = (byte) ((red[i] >> 8) & 0xff);
-      b[6 + i * 6 + 1] = (byte) (red[i] & 0xff);
-      b[6 + i * 6 + 2] = (byte) ((green[i] >> 8) & 0xff);
-      b[6 + i * 6 + 3] = (byte) (green[i] & 0xff);
-      b[6 + i * 6 + 4] = (byte) ((blue[i] >> 8) & 0xff);
-      b[6 + i * 6 + 5] = (byte) (blue[i] & 0xff);
-    }
- 
-    os.write(b);
-  }
-
-
-  //
-  // Write a SetEncodings message
-  //
-
-  void writeSetEncodings(int[] encs, int len) throws IOException {
-    byte[] b = new byte[4 + 4 * len];
-
-    b[0] = (byte) SetEncodings;
-    b[2] = (byte) ((len >> 8) & 0xff);
-    b[3] = (byte) (len & 0xff);
-
-    for (int i = 0; i < len; i++) {
-      b[4 + 4 * i] = (byte) ((encs[i] >> 24) & 0xff);
-      b[5 + 4 * i] = (byte) ((encs[i] >> 16) & 0xff);
-      b[6 + 4 * i] = (byte) ((encs[i] >> 8) & 0xff);
-      b[7 + 4 * i] = (byte) (encs[i] & 0xff);
-    }
-
-    os.write(b);
-  }
-
-
-  //
-  // Write a ClientCutText message
-  //
-
-  void writeClientCutText(String text) throws IOException {
-    byte[] b = new byte[8 + text.length()];
-
-    b[0] = (byte) ClientCutText;
-    b[4] = (byte) ((text.length() >> 24) & 0xff);
-    b[5] = (byte) ((text.length() >> 16) & 0xff);
-    b[6] = (byte) ((text.length() >> 8) & 0xff);
-    b[7] = (byte) (text.length() & 0xff);
-
-    System.arraycopy(text.getBytes(), 0, b, 8, text.length());
-
-    os.write(b);
-  }
-
-
-  //
-  // A buffer for putting pointer and keyboard events before being sent.  This
-  // is to ensure that multiple RFB events generated from a single Java Event 
-  // will all be sent in a single network packet.  The maximum possible
-  // length is 4 modifier down events, a single key event followed by 4
-  // modifier up events i.e. 9 key events or 72 bytes.
-  //
-
-  byte[] eventBuf = new byte[72];
-  int eventBufLen;
-
-
-  // Useful shortcuts for modifier masks.
-
-  final static int CTRL_MASK  = InputEvent.CTRL_MASK;
-  final static int SHIFT_MASK = InputEvent.SHIFT_MASK;
-  final static int META_MASK  = InputEvent.META_MASK;
-  final static int ALT_MASK   = InputEvent.ALT_MASK;
-
-
-  //
-  // Write a pointer event message.  We may need to send modifier key events
-  // around it to set the correct modifier state.
-  //
-
-  int pointerMask = 0;
-
-  void writePointerEvent(MouseEvent evt) throws IOException {
-    int modifiers = evt.getModifiers();
-
-    int mask2 = 2;
-    int mask3 = 4;
-    if (viewer.options.reverseMouseButtons2And3) {
-      mask2 = 4;
-      mask3 = 2;
-    }
-
-    // Note: For some reason, AWT does not set BUTTON1_MASK on left
-    // button presses. Here we think that it was the left button if
-    // modifiers do not include BUTTON2_MASK or BUTTON3_MASK.
-
-    if (evt.getID() == MouseEvent.MOUSE_PRESSED) {
-      if ((modifiers & InputEvent.BUTTON2_MASK) != 0) {
-        pointerMask = mask2;
-        modifiers &= ~ALT_MASK;
-      } else if ((modifiers & InputEvent.BUTTON3_MASK) != 0) {
-        pointerMask = mask3;
-        modifiers &= ~META_MASK;
-      } else {
-        pointerMask = 1;
-      }
-    } else if (evt.getID() == MouseEvent.MOUSE_RELEASED) {
-      pointerMask = 0;
-      if ((modifiers & InputEvent.BUTTON2_MASK) != 0) {
-        modifiers &= ~ALT_MASK;
-      } else if ((modifiers & InputEvent.BUTTON3_MASK) != 0) {
-        modifiers &= ~META_MASK;
-      }
-    }
-
-    eventBufLen = 0;
-    writeModifierKeyEvents(modifiers);
-
-    int x = evt.getX();
-    int y = evt.getY();
-
-    if (x < 0) x = 0;
-    if (y < 0) y = 0;
-
-    eventBuf[eventBufLen++] = (byte) PointerEvent;
-    eventBuf[eventBufLen++] = (byte) pointerMask;
-    eventBuf[eventBufLen++] = (byte) ((x >> 8) & 0xff);
-    eventBuf[eventBufLen++] = (byte) (x & 0xff);
-    eventBuf[eventBufLen++] = (byte) ((y >> 8) & 0xff);
-    eventBuf[eventBufLen++] = (byte) (y & 0xff);
-
-    //
-    // Always release all modifiers after an "up" event
-    //
-
-    if (pointerMask == 0) {
-      writeModifierKeyEvents(0);
-    }
-
-    os.write(eventBuf, 0, eventBufLen);
-  }
-
-
-  //
-  // Write a key event message.  We may need to send modifier key events
-  // around it to set the correct modifier state.  Also we need to translate
-  // from the Java key values to the X keysym values used by the RFB protocol.
-  //
-
-  void writeKeyEvent(KeyEvent evt) throws IOException {
-
-    int keyChar = evt.getKeyChar();
-
-    //
-    // Ignore event if only modifiers were pressed.
-    //
-
-    // Some JVMs return 0 instead of CHAR_UNDEFINED in getKeyChar().
-    if (keyChar == 0)
-      keyChar = KeyEvent.CHAR_UNDEFINED;
-
-    if (keyChar == KeyEvent.CHAR_UNDEFINED) {
-      int code = evt.getKeyCode();
-      if (code == KeyEvent.VK_CONTROL || code == KeyEvent.VK_SHIFT ||
-          code == KeyEvent.VK_META || code == KeyEvent.VK_ALT)
-        return;
-    }
-
-    //
-    // Key press or key release?
-    //
-
-    boolean down = (evt.getID() == KeyEvent.KEY_PRESSED);
-
-    int key;
-    if (evt.isActionKey()) {
-
-      //
-      // An action key should be one of the following.
-      // If not then just ignore the event.
-      //
-
-      switch(evt.getKeyCode()) {
-      case KeyEvent.VK_HOME:      key = 0xff50; break;
-      case KeyEvent.VK_LEFT:      key = 0xff51; break;
-      case KeyEvent.VK_UP:        key = 0xff52; break;
-      case KeyEvent.VK_RIGHT:     key = 0xff53; break;
-      case KeyEvent.VK_DOWN:      key = 0xff54; break;
-      case KeyEvent.VK_PAGE_UP:   key = 0xff55; break;
-      case KeyEvent.VK_PAGE_DOWN: key = 0xff56; break;
-      case KeyEvent.VK_END:       key = 0xff57; break;
-      case KeyEvent.VK_INSERT:    key = 0xff63; break;
-      case KeyEvent.VK_F1:        key = 0xffbe; break;
-      case KeyEvent.VK_F2:        key = 0xffbf; break;
-      case KeyEvent.VK_F3:        key = 0xffc0; break;
-      case KeyEvent.VK_F4:        key = 0xffc1; break;
-      case KeyEvent.VK_F5:        key = 0xffc2; break;
-      case KeyEvent.VK_F6:        key = 0xffc3; break;
-      case KeyEvent.VK_F7:        key = 0xffc4; break;
-      case KeyEvent.VK_F8:        key = 0xffc5; break;
-      case KeyEvent.VK_F9:        key = 0xffc6; break;
-      case KeyEvent.VK_F10:       key = 0xffc7; break;
-      case KeyEvent.VK_F11:       key = 0xffc8; break;
-      case KeyEvent.VK_F12:       key = 0xffc9; break;
-      default:
-        return;
-      }
-
-    } else {
-
-      //
-      // A "normal" key press.  Ordinary ASCII characters go straight through.
-      // For CTRL-<letter>, CTRL is sent separately so just send <letter>.
-      // Backspace, tab, return, escape and delete have special keysyms.
-      // Anything else we ignore.
-      //
-
-      key = keyChar;
-
-      if (key < 32) {
-        if (evt.isControlDown()) {
-          key += 96;
-        } else {
-          switch(key) {
-          case KeyEvent.VK_BACK_SPACE: key = 0xff08; break;
-          case KeyEvent.VK_TAB:        key = 0xff09; break;
-          case KeyEvent.VK_ENTER:      key = 0xff0d; break;
-          case KeyEvent.VK_ESCAPE:     key = 0xff1b; break;
-          }
-        }
-      } else if (key >= 127) {
-        if (key == 127) {
-          key = 0xffff;
-        } else {
-          // JDK1.1 on X incorrectly passes some keysyms straight through,
-          // so we do too.  JDK1.1.4 seems to have fixed this.
-          if ((key < 0xff00) || (key > 0xffff))
-            return;
-        }
-      }
-    }
-
-    eventBufLen = 0;
-    writeModifierKeyEvents(evt.getModifiers());
-    writeKeyEvent(key, down);
-
-    // Always release all modifiers after an "up" event
-    if (!down)
-      writeModifierKeyEvents(0);
-
-    os.write(eventBuf, 0, eventBufLen);
-  }
-
-
-  //
-  // Add a raw key event with the given X keysym to eventBuf.
-  //
-
-  void writeKeyEvent(int keysym, boolean down) {
-    eventBuf[eventBufLen++] = (byte) KeyboardEvent;
-    eventBuf[eventBufLen++] = (byte) (down ? 1 : 0);
-    eventBuf[eventBufLen++] = (byte) 0;
-    eventBuf[eventBufLen++] = (byte) 0;
-    eventBuf[eventBufLen++] = (byte) ((keysym >> 24) & 0xff);
-    eventBuf[eventBufLen++] = (byte) ((keysym >> 16) & 0xff);
-    eventBuf[eventBufLen++] = (byte) ((keysym >> 8) & 0xff);
-    eventBuf[eventBufLen++] = (byte) (keysym & 0xff);
-  }
-
-
-  //
-  // Write key events to set the correct modifier state.
-  //
-
-  int oldModifiers = 0;
-
-  void writeModifierKeyEvents(int newModifiers) {
-    if ((newModifiers & CTRL_MASK) != (oldModifiers & CTRL_MASK))
-      writeKeyEvent(0xffe3, (newModifiers & CTRL_MASK) != 0);
-
-    if ((newModifiers & SHIFT_MASK) != (oldModifiers & SHIFT_MASK))
-      writeKeyEvent(0xffe1, (newModifiers & SHIFT_MASK) != 0);
-
-    if ((newModifiers & META_MASK) != (oldModifiers & META_MASK))
-      writeKeyEvent(0xffe7, (newModifiers & META_MASK) != 0);
-
-    if ((newModifiers & ALT_MASK) != (oldModifiers & ALT_MASK))
-      writeKeyEvent(0xffe9, (newModifiers & ALT_MASK) != 0);
-
-    oldModifiers = newModifiers;
-  }
 }