blob: 58140120fe435882e7e85c0ec2828549d6240434 [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";
35 final static int ConnFailed = 0, NoAuth = 1, VncAuth = 2;
36 final static int VncAuthOK = 0, VncAuthFailed = 1, VncAuthTooMany = 2;
37
38 final static int FramebufferUpdate = 0, SetColourMapEntries = 1, Bell = 2,
39 ServerCutText = 3;
40
41 final int SetPixelFormat = 0, FixColourMapEntries = 1, SetEncodings = 2,
42 FramebufferUpdateRequest = 3, KeyboardEvent = 4, PointerEvent = 5,
43 ClientCutText = 6;
44
45 final static int
46 EncodingRaw = 0,
47 EncodingCopyRect = 1,
48 EncodingRRE = 2,
49 EncodingCoRRE = 4,
50 EncodingHextile = 5,
51 EncodingZlib = 6,
52 EncodingTight = 7,
53 EncodingCompressLevel0 = 0xFFFFFF00,
54 EncodingQualityLevel0 = 0xFFFFFFE0,
55 EncodingXCursor = 0xFFFFFF10,
56 EncodingRichCursor = 0xFFFFFF11,
57 EncodingLastRect = 0xFFFFFF20,
58 EncodingNewFBSize = 0xFFFFFF21;
59
60 final int HextileRaw = (1 << 0);
61 final int HextileBackgroundSpecified = (1 << 1);
62 final int HextileForegroundSpecified = (1 << 2);
63 final int HextileAnySubrects = (1 << 3);
64 final int HextileSubrectsColoured = (1 << 4);
65
66 final static int TightExplicitFilter = 0x04;
67 final static int TightFill = 0x08;
68 final static int TightJpeg = 0x09;
69 final static int TightMaxSubencoding = 0x09;
70 final static int TightFilterCopy = 0x00;
71 final static int TightFilterPalette = 0x01;
72 final static int TightFilterGradient = 0x02;
73
74 final static int TightMinToCompress = 12;
75
Constantin Kaplinsky37cc43e2002-05-30 17:30:11 +000076 FbsInputStream fbs;
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000077 DataInputStream is;
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000078
79
80 //
Constantin Kaplinsky903009e2002-05-20 10:55:47 +000081 // Constructor.
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000082 //
83
Constantin Kaplinsky37cc43e2002-05-30 17:30:11 +000084 RfbProto(URL url) throws Exception {
85 fbs = null;
86 newSession(url);
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000087 }
88
Constantin Kaplinskyc833e012002-05-30 17:59:22 +000089 //
90 // Open new session URL.
91 //
92
Constantin Kaplinsky37cc43e2002-05-30 17:30:11 +000093 public void newSession(URL url) throws Exception {
94 if (fbs != null)
95 fbs.close();
96 fbs = new FbsInputStream(url.openStream());
97 is = new DataInputStream(fbs);
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000098
Constantin Kaplinsky903009e2002-05-20 10:55:47 +000099 readVersionMsg();
100 if (readAuthScheme() != NoAuth) {
Constantin Kaplinskyf392f442002-05-20 13:05:42 +0000101 throw new Exception("Wrong authentication type in the session file");
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000102 }
Constantin Kaplinsky903009e2002-05-20 10:55:47 +0000103 readServerInit();
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000104 }
105
106 //
Constantin Kaplinskyc833e012002-05-30 17:59:22 +0000107 // Read server's protocol version message.
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000108 //
109
110 int serverMajor, serverMinor;
111
112 void readVersionMsg() throws IOException {
113
114 byte[] b = new byte[12];
115
116 is.readFully(b);
117
118 if ((b[0] != 'R') || (b[1] != 'F') || (b[2] != 'B') || (b[3] != ' ')
119 || (b[4] < '0') || (b[4] > '9') || (b[5] < '0') || (b[5] > '9')
120 || (b[6] < '0') || (b[6] > '9') || (b[7] != '.')
121 || (b[8] < '0') || (b[8] > '9') || (b[9] < '0') || (b[9] > '9')
122 || (b[10] < '0') || (b[10] > '9') || (b[11] != '\n'))
123 {
Constantin Kaplinsky903009e2002-05-20 10:55:47 +0000124 throw new IOException("Incorrect protocol version");
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000125 }
126
127 serverMajor = (b[4] - '0') * 100 + (b[5] - '0') * 10 + (b[6] - '0');
128 serverMinor = (b[8] - '0') * 100 + (b[9] - '0') * 10 + (b[10] - '0');
129 }
130
131
132 //
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000133 // 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));
146
147 case NoAuth:
148 case VncAuth:
149 return authScheme;
150
151 default:
Constantin Kaplinsky903009e2002-05-20 10:55:47 +0000152 throw new IOException("Unknown authentication scheme " + authScheme);
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000153
154 }
155 }
156
157
158 //
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000159 // Read the server initialisation message
160 //
161
162 String desktopName;
163 int framebufferWidth, framebufferHeight;
164 int bitsPerPixel, depth;
165 boolean bigEndian, trueColour;
166 int redMax, greenMax, blueMax, redShift, greenShift, blueShift;
167
Constantin Kaplinskyf392f442002-05-20 13:05:42 +0000168 void readServerInit() throws Exception {
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000169 framebufferWidth = is.readUnsignedShort();
170 framebufferHeight = is.readUnsignedShort();
171 bitsPerPixel = is.readUnsignedByte();
172 depth = is.readUnsignedByte();
173 bigEndian = (is.readUnsignedByte() != 0);
174 trueColour = (is.readUnsignedByte() != 0);
175 redMax = is.readUnsignedShort();
176 greenMax = is.readUnsignedShort();
177 blueMax = is.readUnsignedShort();
178 redShift = is.readUnsignedByte();
179 greenShift = is.readUnsignedByte();
180 blueShift = is.readUnsignedByte();
181 byte[] pad = new byte[3];
182 is.readFully(pad);
183 int nameLength = is.readInt();
184 byte[] name = new byte[nameLength];
185 is.readFully(name);
186 desktopName = new String(name);
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000187 }
188
189
190 //
191 // Set new framebuffer size
192 //
193
194 void setFramebufferSize(int width, int height) {
195 framebufferWidth = width;
196 framebufferHeight = height;
197 }
198
199
200 //
201 // Read the server message type
202 //
203
204 int readServerMessageType() throws IOException {
205 return is.readUnsignedByte();
206 }
207
208
209 //
210 // Read a FramebufferUpdate message
211 //
212
213 int updateNRects;
214
215 void readFramebufferUpdate() throws IOException {
216 is.readByte();
217 updateNRects = is.readUnsignedShort();
218 }
219
220 // Read a FramebufferUpdate rectangle header
221
222 int updateRectX, updateRectY, updateRectW, updateRectH, updateRectEncoding;
223
224 void readFramebufferUpdateRectHdr() throws IOException {
225 updateRectX = is.readUnsignedShort();
226 updateRectY = is.readUnsignedShort();
227 updateRectW = is.readUnsignedShort();
228 updateRectH = is.readUnsignedShort();
229 updateRectEncoding = is.readInt();
230
231 if ((updateRectEncoding == EncodingLastRect) ||
232 (updateRectEncoding == EncodingNewFBSize))
233 return;
234
235 if ((updateRectX + updateRectW > framebufferWidth) ||
236 (updateRectY + updateRectH > framebufferHeight)) {
237 throw new IOException("Framebuffer update rectangle too large: " +
238 updateRectW + "x" + updateRectH + " at (" +
239 updateRectX + "," + updateRectY + ")");
240 }
241 }
242
243 // Read CopyRect source X and Y.
244
245 int copyRectSrcX, copyRectSrcY;
246
247 void readCopyRect() throws IOException {
248 copyRectSrcX = is.readUnsignedShort();
249 copyRectSrcY = is.readUnsignedShort();
250 }
251
252
253 //
254 // Read a ServerCutText message
255 //
256
257 String readServerCutText() throws IOException {
258 byte[] pad = new byte[3];
259 is.readFully(pad);
260 int len = is.readInt();
261 byte[] text = new byte[len];
262 is.readFully(text);
263 return new String(text);
264 }
265
266
267 //
268 // Read integer in compact representation
269 //
270
271 int readCompactLen() throws IOException {
272 int portion = is.readUnsignedByte();
273 int len = portion & 0x7F;
274 if ((portion & 0x80) != 0) {
275 portion = is.readUnsignedByte();
276 len |= (portion & 0x7F) << 7;
277 if ((portion & 0x80) != 0) {
278 portion = is.readUnsignedByte();
279 len |= (portion & 0xFF) << 14;
280 }
281 }
282 return len;
283 }
284
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000285}