blob: e8a5042be8113afb99a01a1d0656ab00ebf44929 [file] [log] [blame]
Constantin Kaplinsky1215b992008-04-18 09:51:44 +00001//
2// Copyright (C) 2001,2002 HorizonLive.com, Inc. All Rights Reserved.
3// Copyright (C) 2001 Constantin Kaplinsky. All Rights Reserved.
4// Copyright (C) 2000 Tridia Corporation. All Rights Reserved.
5// Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
6//
7// This is free software; you can redistribute it and/or modify
8// it under the terms of the GNU General Public License as published by
9// the Free Software Foundation; either version 2 of the License, or
10// (at your option) any later version.
11//
12// This software is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15// GNU General Public License for more details.
16//
17// You should have received a copy of the GNU General Public License
18// along with this software; if not, write to the Free Software
19// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20// USA.
21//
22
23//
24// RfbProto.java
25//
26
27import java.io.*;
28import java.awt.*;
29import java.awt.event.*;
Constantin Kaplinsky37cc43e2002-05-30 17:30:11 +000030import java.net.*;
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000031
32class RfbProto {
33
34 final String versionMsg = "RFB 003.003\n";
Constantin Kaplinsky72e47ef2008-04-18 17:48:16 +000035 final static int ConnFailed = 0, NoAuth = 1, VncAuth = 2;
36 final static int VncAuthOK = 0, VncAuthFailed = 1, VncAuthTooMany = 2;
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000037
Constantin Kaplinsky72e47ef2008-04-18 17:48:16 +000038 final static int FramebufferUpdate = 0, SetColourMapEntries = 1, Bell = 2, ServerCutText =
39 3;
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000040
Constantin Kaplinsky72e47ef2008-04-18 17:48:16 +000041 final int SetPixelFormat = 0, FixColourMapEntries = 1, SetEncodings = 2, FramebufferUpdateRequest =
42 3, KeyboardEvent = 4, PointerEvent = 5, ClientCutText = 6;
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000043
Constantin Kaplinsky72e47ef2008-04-18 17:48:16 +000044 final static int EncodingRaw = 0, EncodingCopyRect = 1, EncodingRRE = 2, EncodingCoRRE =
45 4, EncodingHextile = 5, EncodingZlib = 6, EncodingTight = 7, EncodingCompressLevel0 =
46 0xFFFFFF00, EncodingQualityLevel0 = 0xFFFFFFE0, EncodingXCursor =
47 0xFFFFFF10, EncodingRichCursor = 0xFFFFFF11, EncodingLastRect =
48 0xFFFFFF20, EncodingNewFBSize = 0xFFFFFF21;
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000049
Constantin Kaplinsky72e47ef2008-04-18 17:48:16 +000050 final int HextileRaw = (1 << 0);
51 final int HextileBackgroundSpecified = (1 << 1);
52 final int HextileForegroundSpecified = (1 << 2);
53 final int HextileAnySubrects = (1 << 3);
54 final int HextileSubrectsColoured = (1 << 4);
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000055
Constantin Kaplinsky72e47ef2008-04-18 17:48:16 +000056 final static int TightExplicitFilter = 0x04;
57 final static int TightFill = 0x08;
58 final static int TightJpeg = 0x09;
59 final static int TightMaxSubencoding = 0x09;
60 final static int TightFilterCopy = 0x00;
61 final static int TightFilterPalette = 0x01;
62 final static int TightFilterGradient = 0x02;
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000063
Constantin Kaplinsky72e47ef2008-04-18 17:48:16 +000064 final static int TightMinToCompress = 12;
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000065
Constantin Kaplinsky37cc43e2002-05-30 17:30:11 +000066 FbsInputStream fbs;
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000067 DataInputStream is;
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000068
69
70 //
Constantin Kaplinsky903009e2002-05-20 10:55:47 +000071 // Constructor.
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000072 //
Constantin Kaplinsky37cc43e2002-05-30 17:30:11 +000073 RfbProto(URL url) throws Exception {
74 fbs = null;
75 newSession(url);
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000076 }
77
Constantin Kaplinskyc833e012002-05-30 17:59:22 +000078 //
79 // Open new session URL.
80 //
Constantin Kaplinsky37cc43e2002-05-30 17:30:11 +000081 public void newSession(URL url) throws Exception {
82 if (fbs != null)
83 fbs.close();
84 fbs = new FbsInputStream(url.openStream());
85 is = new DataInputStream(fbs);
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000086
Constantin Kaplinsky903009e2002-05-20 10:55:47 +000087 readVersionMsg();
88 if (readAuthScheme() != NoAuth) {
Constantin Kaplinskyf392f442002-05-20 13:05:42 +000089 throw new Exception("Wrong authentication type in the session file");
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000090 }
Constantin Kaplinsky903009e2002-05-20 10:55:47 +000091 readServerInit();
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000092 }
93
94 //
Constantin Kaplinskyc833e012002-05-30 17:59:22 +000095 // Read server's protocol version message.
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000096 //
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000097 int serverMajor, serverMinor;
98
99 void readVersionMsg() throws IOException {
100
101 byte[] b = new byte[12];
102
103 is.readFully(b);
104
Constantin Kaplinsky72e47ef2008-04-18 17:48:16 +0000105 if ((b[0] != 'R') || (b[1] != 'F') || (b[2] != 'B') || (b[3] != ' ') ||
106 (b[4] < '0') || (b[4] > '9') || (b[5] < '0') || (b[5] > '9') || (b[6] <
107 '0') || (b[6] > '9') || (b[7] != '.') || (b[8] < '0') || (b[8] > '9') ||
108 (b[9] < '0') || (b[9] > '9') || (b[10] < '0') || (b[10] > '9') ||
109 (b[11] != '\n')) {
Constantin Kaplinsky903009e2002-05-20 10:55:47 +0000110 throw new IOException("Incorrect protocol version");
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000111 }
112
113 serverMajor = (b[4] - '0') * 100 + (b[5] - '0') * 10 + (b[6] - '0');
114 serverMinor = (b[8] - '0') * 100 + (b[9] - '0') * 10 + (b[10] - '0');
115 }
116
117
118 //
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000119 // Find out the authentication scheme.
120 //
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000121 int readAuthScheme() throws IOException {
122 int authScheme = is.readInt();
123
124 switch (authScheme) {
125
126 case ConnFailed:
127 int reasonLen = is.readInt();
128 byte[] reason = new byte[reasonLen];
129 is.readFully(reason);
130 throw new IOException(new String(reason));
131
132 case NoAuth:
133 case VncAuth:
134 return authScheme;
135
136 default:
Constantin Kaplinsky903009e2002-05-20 10:55:47 +0000137 throw new IOException("Unknown authentication scheme " + authScheme);
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000138
139 }
140 }
141
142
143 //
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000144 // Read the server initialisation message
145 //
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000146 String desktopName;
147 int framebufferWidth, framebufferHeight;
148 int bitsPerPixel, depth;
149 boolean bigEndian, trueColour;
150 int redMax, greenMax, blueMax, redShift, greenShift, blueShift;
151
Constantin Kaplinskyf392f442002-05-20 13:05:42 +0000152 void readServerInit() throws Exception {
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000153 framebufferWidth = is.readUnsignedShort();
154 framebufferHeight = is.readUnsignedShort();
155 bitsPerPixel = is.readUnsignedByte();
156 depth = is.readUnsignedByte();
157 bigEndian = (is.readUnsignedByte() != 0);
158 trueColour = (is.readUnsignedByte() != 0);
159 redMax = is.readUnsignedShort();
160 greenMax = is.readUnsignedShort();
161 blueMax = is.readUnsignedShort();
162 redShift = is.readUnsignedByte();
163 greenShift = is.readUnsignedByte();
164 blueShift = is.readUnsignedByte();
165 byte[] pad = new byte[3];
166 is.readFully(pad);
167 int nameLength = is.readInt();
168 byte[] name = new byte[nameLength];
169 is.readFully(name);
170 desktopName = new String(name);
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000171 }
172
173
174 //
175 // Set new framebuffer size
176 //
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000177 void setFramebufferSize(int width, int height) {
178 framebufferWidth = width;
179 framebufferHeight = height;
180 }
181
182
183 //
184 // Read the server message type
185 //
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000186 int readServerMessageType() throws IOException {
187 return is.readUnsignedByte();
188 }
189
190
191 //
192 // Read a FramebufferUpdate message
193 //
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000194 int updateNRects;
195
196 void readFramebufferUpdate() throws IOException {
197 is.readByte();
198 updateNRects = is.readUnsignedShort();
199 }
200
201 // Read a FramebufferUpdate rectangle header
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000202 int updateRectX, updateRectY, updateRectW, updateRectH, updateRectEncoding;
203
204 void readFramebufferUpdateRectHdr() throws IOException {
205 updateRectX = is.readUnsignedShort();
206 updateRectY = is.readUnsignedShort();
207 updateRectW = is.readUnsignedShort();
208 updateRectH = is.readUnsignedShort();
209 updateRectEncoding = is.readInt();
210
211 if ((updateRectEncoding == EncodingLastRect) ||
Constantin Kaplinsky72e47ef2008-04-18 17:48:16 +0000212 (updateRectEncoding == EncodingNewFBSize))
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000213 return;
214
215 if ((updateRectX + updateRectW > framebufferWidth) ||
Constantin Kaplinsky72e47ef2008-04-18 17:48:16 +0000216 (updateRectY + updateRectH > framebufferHeight)) {
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000217 throw new IOException("Framebuffer update rectangle too large: " +
Constantin Kaplinsky72e47ef2008-04-18 17:48:16 +0000218 updateRectW + "x" + updateRectH + " at (" +
219 updateRectX + "," + updateRectY + ")");
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000220 }
221 }
222
223 // Read CopyRect source X and Y.
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000224 int copyRectSrcX, copyRectSrcY;
225
226 void readCopyRect() throws IOException {
227 copyRectSrcX = is.readUnsignedShort();
228 copyRectSrcY = is.readUnsignedShort();
229 }
230
231
232 //
233 // Read a ServerCutText message
234 //
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000235 String readServerCutText() throws IOException {
236 byte[] pad = new byte[3];
237 is.readFully(pad);
238 int len = is.readInt();
239 byte[] text = new byte[len];
240 is.readFully(text);
241 return new String(text);
242 }
243
244
245 //
246 // Read integer in compact representation
247 //
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000248 int readCompactLen() throws IOException {
249 int portion = is.readUnsignedByte();
250 int len = portion & 0x7F;
251 if ((portion & 0x80) != 0) {
252 portion = is.readUnsignedByte();
253 len |= (portion & 0x7F) << 7;
254 if ((portion & 0x80) != 0) {
Constantin Kaplinsky72e47ef2008-04-18 17:48:16 +0000255 portion = is.readUnsignedByte();
256 len |= (portion & 0xFF) << 14;
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000257 }
258 }
259 return len;
260 }
261
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000262}