home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1998 September / PCO_0998.ISO / filesbbs / frei / vnc-java.arj / VNC-JAVA.ZIP / rfbProto.java < prev    next >
Encoding:
Java Source  |  1998-07-03  |  15.6 KB  |  607 lines

  1. //
  2. //  Copyright (C) 1997, 1998 Olivetti & Oracle Research Laboratory
  3. //
  4. //  This is free software; you can redistribute it and/or modify
  5. //  it under the terms of the GNU General Public License as published by
  6. //  the Free Software Foundation; either version 2 of the License, or
  7. //  (at your option) any later version.
  8. //
  9. //  This software is distributed in the hope that it will be useful,
  10. //  but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. //  GNU General Public License for more details.
  13. //
  14. //  You should have received a copy of the GNU General Public License
  15. //  along with this software; if not, write to the Free Software
  16. //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
  17. //  USA.
  18. //
  19.  
  20. //
  21. // rfbProto.java
  22. //
  23.  
  24. import java.io.*;
  25. import java.awt.*;
  26. import java.net.Socket;
  27.  
  28. /*
  29. class myInputStream extends FilterInputStream {
  30.   public myInputStream(InputStream in) {
  31.     super(in);
  32.   }
  33.   public int read(byte[] b, int off, int len) throws IOException {
  34.     System.out.println("read(byte[] b, int off, int len) called");
  35.     return super.read(b, off, len);
  36.   }
  37. }
  38. */
  39.  
  40. class rfbProto {
  41.  
  42.   final String versionMsg = "RFB 003.003\n";
  43.   final int ConnFailed = 0, NoAuth = 1, VncAuth = 2;
  44.   final int VncAuthOK = 0, VncAuthFailed = 1, VncAuthTooMany = 2;
  45.  
  46.   final int FramebufferUpdate = 0, SetColourMapEntries = 1, Bell = 2,
  47.     ServerCutText = 3;
  48.  
  49.   final int SetPixelFormat = 0, FixColourMapEntries = 1, SetEncodings = 2,
  50.     FramebufferUpdateRequest = 3, KeyEvent = 4, PointerEvent = 5,
  51.     ClientCutText = 6;
  52.  
  53.   final static int EncodingRaw = 0, EncodingCopyRect = 1, EncodingRRE = 2,
  54.     EncodingCoRRE = 4, EncodingHextile = 5;
  55.  
  56.   final int HextileRaw            = (1 << 0);
  57.   final int HextileBackgroundSpecified    = (1 << 1);
  58.   final int HextileForegroundSpecified    = (1 << 2);
  59.   final int HextileAnySubrects        = (1 << 3);
  60.   final int HextileSubrectsColoured    = (1 << 4);
  61.  
  62.   String host;
  63.   int port;
  64.   Socket sock;
  65.   DataInputStream is;
  66.   OutputStream os;
  67.   boolean inNormalProtocol = false;
  68.   vncviewer v;
  69.  
  70.  
  71.   //
  72.   // Constructor.  Just make TCP connection to RFB server.
  73.   //
  74.  
  75.   rfbProto(String h, int p, vncviewer v1) throws IOException {
  76.     v = v1;
  77.     host = h;
  78.     port = p;
  79.     sock = new Socket(host, port);
  80.     is = new DataInputStream(new BufferedInputStream(sock.getInputStream(),
  81.                              16384));
  82.     os = sock.getOutputStream();
  83.   }
  84.  
  85.  
  86.   void close() {
  87.     try {
  88.       sock.close();
  89.     } catch (Exception e) {
  90.       e.printStackTrace();
  91.     }
  92.   }
  93.  
  94.   //
  95.   // Read server's protocol version message
  96.   //
  97.  
  98.   int serverMajor, serverMinor;
  99.  
  100.   void readVersionMsg() throws IOException {
  101.  
  102.     byte[] b = new byte[12];
  103.  
  104.     is.readFully(b);
  105.  
  106.     if ((b[0] != 'R') || (b[1] != 'F') || (b[2] != 'B') || (b[3] != ' ')
  107.     || (b[4] < '0') || (b[4] > '9') || (b[5] < '0') || (b[5] > '9')
  108.     || (b[6] < '0') || (b[6] > '9') || (b[7] != '.')
  109.     || (b[8] < '0') || (b[8] > '9') || (b[9] < '0') || (b[9] > '9')
  110.     || (b[10] < '0') || (b[10] > '9') || (b[11] != '\n'))
  111.     {
  112.       throw new IOException("Host " + host + " port " + port +
  113.                 " is not an RFB server");
  114.     }
  115.  
  116.     serverMajor = (b[4] - '0') * 100 + (b[5] - '0') * 10 + (b[6] - '0');
  117.     serverMinor = (b[8] - '0') * 100 + (b[9] - '0') * 10 + (b[10] - '0');
  118.   }
  119.  
  120.  
  121.   //
  122.   // Write our protocol version message
  123.   //
  124.  
  125.   void writeVersionMsg() throws IOException {
  126.     byte[] b = new byte[12];
  127.     versionMsg.getBytes(0, 12, b, 0);
  128.     os.write(b);
  129.   }
  130.  
  131.  
  132.   //
  133.   // Find out the authentication scheme.
  134.   //
  135.  
  136.   int readAuthScheme() throws IOException {
  137.     int authScheme = is.readInt();
  138.  
  139.     switch (authScheme) {
  140.  
  141.     case ConnFailed:
  142.       int reasonLen = is.readInt();
  143.       byte[] reason = new byte[reasonLen];
  144.       is.readFully(reason);
  145.       throw new IOException(new String(reason, 0));
  146.  
  147.     case NoAuth:
  148.     case VncAuth:
  149.       return authScheme;
  150.  
  151.     default:
  152.       throw new IOException("Unknown authentication scheme from RFB " +
  153.                 "server " + authScheme);
  154.  
  155.     }
  156.   }
  157.  
  158.  
  159.   //
  160.   // Write the client initialisation message
  161.   //
  162.  
  163.   void writeClientInit() throws IOException {
  164.     if (v.options.shareDesktop) {
  165.       os.write(1);
  166.     } else {
  167.       os.write(0);
  168.     }
  169.     v.options.disableShareDesktop();
  170.   }
  171.  
  172.  
  173.   //
  174.   // Read the server initialisation message
  175.   //
  176.  
  177.   String desktopName;
  178.   int framebufferWidth, framebufferHeight;
  179.   int bitsPerPixel, depth;
  180.   boolean bigEndian, trueColour;
  181.   int redMax, greenMax, blueMax, redShift, greenShift, blueShift;
  182.  
  183.   void readServerInit() throws IOException {
  184.     framebufferWidth = is.readUnsignedShort();
  185.     framebufferHeight = is.readUnsignedShort();
  186.     bitsPerPixel = is.readUnsignedByte();
  187.     depth = is.readUnsignedByte();
  188.     bigEndian = (is.readUnsignedByte() != 0);
  189.     trueColour = (is.readUnsignedByte() != 0);
  190.     redMax = is.readUnsignedShort();
  191.     greenMax = is.readUnsignedShort();
  192.     blueMax = is.readUnsignedShort();
  193.     redShift = is.readUnsignedByte();
  194.     greenShift = is.readUnsignedByte();
  195.     blueShift = is.readUnsignedByte();
  196.     byte[] pad = new byte[3];
  197.     is.read(pad);
  198.     int nameLength = is.readInt();
  199.     byte[] name = new byte[nameLength];
  200.     is.readFully(name);
  201.     desktopName = new String(name, 0);
  202.  
  203.     inNormalProtocol = true;
  204.   }
  205.  
  206.  
  207.   //
  208.   // Read the server message type
  209.   //
  210.  
  211.   int readServerMessageType() throws IOException {
  212.     return is.read();
  213.   }
  214.  
  215.  
  216.   //
  217.   // Read a FramebufferUpdate message
  218.   //
  219.  
  220.   int updateNRects;
  221.  
  222.   void readFramebufferUpdate() throws IOException {
  223.     is.readByte();
  224.     updateNRects = is.readUnsignedShort();
  225.   }
  226.  
  227.   // Read a FramebufferUpdate rectangle header
  228.  
  229.   int updateRectX, updateRectY, updateRectW, updateRectH, updateRectEncoding;
  230.  
  231.   void readFramebufferUpdateRectHdr() throws IOException {
  232.     updateRectX = is.readUnsignedShort();
  233.     updateRectY = is.readUnsignedShort();
  234.     updateRectW = is.readUnsignedShort();
  235.     updateRectH = is.readUnsignedShort();
  236.     updateRectEncoding = is.readInt();
  237.  
  238.     if ((updateRectX + updateRectW > framebufferWidth) ||
  239.     (updateRectY + updateRectH > framebufferHeight)) {
  240.       throw new IOException("Framebuffer update rectangle too large: " +
  241.                 updateRectW + "x" + updateRectH + " at (" +
  242.                 updateRectX + "," + updateRectY + ")");
  243.     }
  244.   }
  245.  
  246.   // Read CopyRect source X and Y.
  247.  
  248.   int copyRectSrcX, copyRectSrcY;
  249.  
  250.   void readCopyRect() throws IOException {
  251.     copyRectSrcX = is.readUnsignedShort();
  252.     copyRectSrcY = is.readUnsignedShort();
  253.   }
  254.  
  255.  
  256.   //
  257.   // Read a ServerCutText message
  258.   //
  259.  
  260.   String readServerCutText() throws IOException {
  261.     byte[] pad = new byte[3];
  262.     is.read(pad);
  263.     int len = is.readInt();
  264.     byte[] text = new byte[len];
  265.     is.readFully(text);
  266.     return new String(text, 0);
  267.   }
  268.  
  269.  
  270.   //
  271.   // Write a FramebufferUpdateRequest message
  272.   //
  273.  
  274.   void writeFramebufferUpdateRequest(int x, int y, int w, int h,
  275.                      boolean incremental)
  276.        throws IOException
  277.   {
  278.     byte[] b = new byte[10];
  279.  
  280.     b[0] = (byte) FramebufferUpdateRequest;
  281.     b[1] = (byte) (incremental ? 1 : 0);
  282.     b[2] = (byte) ((x >> 8) & 0xff);
  283.     b[3] = (byte) (x & 0xff);
  284.     b[4] = (byte) ((y >> 8) & 0xff);
  285.     b[5] = (byte) (y & 0xff);
  286.     b[6] = (byte) ((w >> 8) & 0xff);
  287.     b[7] = (byte) (w & 0xff);
  288.     b[8] = (byte) ((h >> 8) & 0xff);
  289.     b[9] = (byte) (h & 0xff);
  290.  
  291.     os.write(b);
  292.   }
  293.  
  294.  
  295.   //
  296.   // Write a SetPixelFormat message
  297.   //
  298.  
  299.   void writeSetPixelFormat(int bitsPerPixel, int depth, boolean bigEndian,
  300.                boolean trueColour,
  301.                int redMax, int greenMax, int blueMax,
  302.                int redShift, int greenShift, int blueShift)
  303.        throws IOException
  304.   {
  305.     byte[] b = new byte[20];
  306.  
  307.     b[0]  = (byte) SetPixelFormat;
  308.     b[4]  = (byte) bitsPerPixel;
  309.     b[5]  = (byte) depth;
  310.     b[6]  = (byte) (bigEndian ? 1 : 0);
  311.     b[7]  = (byte) (trueColour ? 1 : 0);
  312.     b[8]  = (byte) ((redMax >> 8) & 0xff);
  313.     b[9]  = (byte) (redMax & 0xff);
  314.     b[10] = (byte) ((greenMax >> 8) & 0xff);
  315.     b[11] = (byte) (greenMax & 0xff);
  316.     b[12] = (byte) ((blueMax >> 8) & 0xff);
  317.     b[13] = (byte) (blueMax & 0xff);
  318.     b[14] = (byte) redShift;
  319.     b[15] = (byte) greenShift;
  320.     b[16] = (byte) blueShift;
  321.  
  322.     os.write(b);
  323.   }
  324.  
  325.  
  326.   //
  327.   // Write a FixColourMapEntries message.  The values in the red, green and
  328.   // blue arrays are from 0 to 65535.
  329.   //
  330.  
  331.   void writeFixColourMapEntries(int firstColour, int nColours,
  332.                 int[] red, int[] green, int[] blue)
  333.        throws IOException
  334.   {
  335.     byte[] b = new byte[6 + nColours * 6];
  336.  
  337.     b[0] = (byte) FixColourMapEntries;
  338.     b[2] = (byte) ((firstColour >> 8) & 0xff);
  339.     b[3] = (byte) (firstColour & 0xff);
  340.     b[4] = (byte) ((nColours >> 8) & 0xff);
  341.     b[5] = (byte) (nColours & 0xff);
  342.  
  343.     for (int i = 0; i < nColours; i++) {
  344.       b[6 + i * 6]     = (byte) ((red[i] >> 8) & 0xff);
  345.       b[6 + i * 6 + 1] = (byte) (red[i] & 0xff);
  346.       b[6 + i * 6 + 2] = (byte) ((green[i] >> 8) & 0xff);
  347.       b[6 + i * 6 + 3] = (byte) (green[i] & 0xff);
  348.       b[6 + i * 6 + 4] = (byte) ((blue[i] >> 8) & 0xff);
  349.       b[6 + i * 6 + 5] = (byte) (blue[i] & 0xff);
  350.     }
  351.  
  352.     os.write(b);
  353.   }
  354.  
  355.  
  356.   //
  357.   // Write a SetEncodings message
  358.   //
  359.  
  360.   void writeSetEncodings(int[] encs, int len) throws IOException {
  361.     byte[] b = new byte[4 + 4 * len];
  362.  
  363.     b[0] = (byte) SetEncodings;
  364.     b[2] = (byte) ((len >> 8) & 0xff);
  365.     b[3] = (byte) (len & 0xff);
  366.  
  367.     for (int i = 0; i < len; i++) {
  368.       b[4 + 4 * i] = (byte) ((encs[i] >> 24) & 0xff);
  369.       b[5 + 4 * i] = (byte) ((encs[i] >> 16) & 0xff);
  370.       b[6 + 4 * i] = (byte) ((encs[i] >> 8) & 0xff);
  371.       b[7 + 4 * i] = (byte) (encs[i] & 0xff);
  372.     }
  373.  
  374.     os.write(b);
  375.   }
  376.  
  377.  
  378.   //
  379.   // Write a ClientCutText message
  380.   //
  381.  
  382.   void writeClientCutText(String text) throws IOException {
  383.     byte[] b = new byte[8 + text.length()];
  384.  
  385.     b[0] = (byte) ClientCutText;
  386.     b[4] = (byte) ((text.length() >> 24) & 0xff);
  387.     b[5] = (byte) ((text.length() >> 16) & 0xff);
  388.     b[6] = (byte) ((text.length() >> 8) & 0xff);
  389.     b[7] = (byte) (text.length() & 0xff);
  390.  
  391.     text.getBytes(0, text.length(), b, 8);
  392.  
  393.     os.write(b);
  394.   }
  395.  
  396.  
  397.   //
  398.   // A buffer for putting pointer and keyboard events before being sent.  This
  399.   // is to ensure that multiple RFB events generated from a single Java Event 
  400.   // will all be sent in a single network packet.  The maximum possible
  401.   // length is 4 modifier down events, a single key event followed by 4
  402.   // modifier up events i.e. 9 key events or 72 bytes.
  403.   //
  404.  
  405.   byte[] eventBuf = new byte[72];
  406.   int eventBufLen;
  407.  
  408.  
  409.   //
  410.   // Write a pointer event message.  We may need to send modifier key events
  411.   // around it to set the correct modifier state.  Also buttons 2 and 3 are
  412.   // represented as having ALT and META modifiers respectively.
  413.   //
  414.  
  415.   int pointerMask = 0;
  416.  
  417.   void writePointerEvent(Event evt)
  418.        throws IOException
  419.   {
  420.     byte[] b = new byte[6];
  421.  
  422.     if (evt.id == Event.MOUSE_DOWN) {
  423.       pointerMask = 1;
  424.       if ((evt.modifiers & Event.ALT_MASK) != 0) {
  425.     if (v.options.reverseMouseButtons2And3)
  426.       pointerMask = 4;
  427.     else
  428.       pointerMask = 2;
  429.       }
  430.       if ((evt.modifiers & Event.META_MASK) != 0) {
  431.     if (v.options.reverseMouseButtons2And3)
  432.       pointerMask = 2;
  433.     else
  434.       pointerMask = 4;
  435.       }
  436.     } else if (evt.id == Event.MOUSE_UP) {
  437.       pointerMask = 0;
  438.     }
  439.  
  440.     evt.modifiers &= ~(Event.ALT_MASK|Event.META_MASK);
  441.  
  442.     eventBufLen = 0;
  443.  
  444.     writeModifierKeyEvents(evt.modifiers);
  445.  
  446.     if (evt.x < 0) evt.x = 0;
  447.     if (evt.y < 0) evt.y = 0;
  448.  
  449.     eventBuf[eventBufLen++] = (byte) PointerEvent;
  450.     eventBuf[eventBufLen++] = (byte) pointerMask;
  451.     eventBuf[eventBufLen++] = (byte) ((evt.x >> 8) & 0xff);
  452.     eventBuf[eventBufLen++] = (byte) (evt.x & 0xff);
  453.     eventBuf[eventBufLen++] = (byte) ((evt.y >> 8) & 0xff);
  454.     eventBuf[eventBufLen++] = (byte) (evt.y & 0xff);
  455.  
  456.     //
  457.     // Always release all modifiers after an "up" event
  458.     //
  459.  
  460.     if (pointerMask == 0) {
  461.       writeModifierKeyEvents(0);
  462.     }
  463.  
  464.     os.write(eventBuf, 0, eventBufLen);
  465.   }
  466.  
  467.  
  468.   //
  469.   // Write a key event message.  We may need to send modifier key events
  470.   // around it to set the correct modifier state.  Also we need to translate
  471.   // from the Java key values to the X keysym values used by the RFB protocol.
  472.   //
  473.  
  474.   void writeKeyEvent(Event evt)
  475.        throws IOException
  476.   {
  477.     int key = evt.key;
  478.     boolean down = false;
  479.  
  480.     if ((evt.id == Event.KEY_PRESS) || (evt.id == Event.KEY_ACTION))
  481.       down = true;
  482.  
  483.     if ((evt.id == Event.KEY_ACTION) || (evt.id == Event.KEY_ACTION_RELEASE)) {
  484.  
  485.       //
  486.       // A KEY_ACTION event should be one of the following.  If not then just
  487.       // ignore the event.
  488.       //
  489.  
  490.       switch(key) {
  491.       case Event.HOME:    key = 0xff50; break;
  492.       case Event.LEFT:    key = 0xff51; break;
  493.       case Event.UP:    key = 0xff52; break;
  494.       case Event.RIGHT:    key = 0xff53; break;
  495.       case Event.DOWN:    key = 0xff54; break;
  496.       case Event.PGUP:    key = 0xff55; break;
  497.       case Event.PGDN:    key = 0xff56; break;
  498.       case Event.END:    key = 0xff57; break;
  499.       case Event.F1:    key = 0xffbe; break;
  500.       case Event.F2:    key = 0xffbf; break;
  501.       case Event.F3:    key = 0xffc0; break;
  502.       case Event.F4:    key = 0xffc1; break;
  503.       case Event.F5:    key = 0xffc2; break;
  504.       case Event.F6:    key = 0xffc3; break;
  505.       case Event.F7:    key = 0xffc4; break;
  506.       case Event.F8:    key = 0xffc5; break;
  507.       case Event.F9:    key = 0xffc6; break;
  508.       case Event.F10:    key = 0xffc7; break;
  509.       case Event.F11:    key = 0xffc8; break;
  510.       case Event.F12:    key = 0xffc9; break;
  511.       default:
  512.         return;
  513.       }
  514.  
  515.     } else {
  516.  
  517.       //
  518.       // A "normal" key press.  Ordinary ASCII characters go straight through.
  519.       // For CTRL-<letter>, CTRL is sent separately so just send <letter>.
  520.       // Backspace, tab, return, escape and delete have special keysyms.
  521.       // Anything else we ignore.
  522.       //
  523.  
  524.       if (key < 32) {
  525.     if ((evt.modifiers & Event.CTRL_MASK) != 0) {
  526.       key += 96;
  527.     } else {
  528.       switch(key) {
  529.       case 8:  key = 0xff08; break;
  530.       case 9:  key = 0xff09; break;
  531.       case 10: key = 0xff0d; break;
  532.       case 27: key = 0xff1b; break;
  533.       }
  534.     }
  535.       } else if (key >= 127) {
  536.     if (key == 127) {
  537.       key = 0xffff;
  538.     } else {
  539.       // JDK1.1 on X incorrectly passes some keysyms straight through, so
  540.       // we do too.  JDK1.1.4 seems to have fixed this.
  541.       if ((key < 0xff00) || (key > 0xffff))
  542.         return;
  543.     }
  544.       }
  545.     }
  546.  
  547.     eventBufLen = 0;
  548.  
  549.     writeModifierKeyEvents(evt.modifiers);
  550.  
  551.     writeKeyEvent(key, down);
  552.  
  553.     //
  554.     // Always release all modifiers after an "up" event
  555.     //
  556.  
  557.     if (!down) {
  558.       writeModifierKeyEvents(0);
  559.     }
  560.  
  561.     os.write(eventBuf, 0, eventBufLen);
  562.   }
  563.  
  564.  
  565.   //
  566.   // Add a raw key event with the given X keysym to eventBuf.
  567.   //
  568.  
  569.   void writeKeyEvent(int keysym, boolean down)
  570.        throws IOException
  571.   {
  572.     eventBuf[eventBufLen++] = (byte) KeyEvent;
  573.     eventBuf[eventBufLen++] = (byte) (down ? 1 : 0);
  574.     eventBuf[eventBufLen++] = (byte) 0;
  575.     eventBuf[eventBufLen++] = (byte) 0;
  576.     eventBuf[eventBufLen++] = (byte) ((keysym >> 24) & 0xff);
  577.     eventBuf[eventBufLen++] = (byte) ((keysym >> 16) & 0xff);
  578.     eventBuf[eventBufLen++] = (byte) ((keysym >> 8) & 0xff);
  579.     eventBuf[eventBufLen++] = (byte) (keysym & 0xff);
  580.   }
  581.  
  582.  
  583.   //
  584.   // Write key events to set the correct modifier state.
  585.   //
  586.  
  587.   int oldModifiers;
  588.  
  589.   void writeModifierKeyEvents(int newModifiers)
  590.        throws IOException
  591.   {
  592.     if ((newModifiers & Event.CTRL_MASK) != (oldModifiers & Event.CTRL_MASK))
  593.       writeKeyEvent(0xffe3, (newModifiers & Event.CTRL_MASK) != 0);
  594.  
  595.     if ((newModifiers & Event.SHIFT_MASK) != (oldModifiers & Event.SHIFT_MASK))
  596.       writeKeyEvent(0xffe1, (newModifiers & Event.SHIFT_MASK) != 0);
  597.  
  598.     if ((newModifiers & Event.META_MASK) != (oldModifiers & Event.META_MASK))
  599.       writeKeyEvent(0xffe7, (newModifiers & Event.META_MASK) != 0);
  600.  
  601.     if ((newModifiers & Event.ALT_MASK) != (oldModifiers & Event.ALT_MASK))
  602.       writeKeyEvent(0xffe9, (newModifiers & Event.ALT_MASK) != 0);
  603.  
  604.     oldModifiers = newModifiers;
  605.   }
  606. }
  607.