blob: 191173ef8a5379d6d46616d4986eb86d1964ecf8 [file] [log] [blame]
Constantin Kaplinsky1215b992008-04-18 09:51:44 +00001//
Constantin Kaplinsky8920b552008-06-18 06:08:59 +00002// Copyright (C) 2008 Wimba, Inc. All Rights Reserved.
Constantin Kaplinsky1215b992008-04-18 09:51:44 +00003// Copyright (C) 2001,2002 HorizonLive.com, Inc. All Rights Reserved.
4// Copyright (C) 2001 Constantin Kaplinsky. All Rights Reserved.
5// Copyright (C) 2000 Tridia Corporation. All Rights Reserved.
6// Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
7//
8// This is free software; you can redistribute it and/or modify
9// it under the terms of the GNU General Public License as published by
10// the Free Software Foundation; either version 2 of the License, or
11// (at your option) any later version.
12//
13// This software is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU General Public License for more details.
17//
18// You should have received a copy of the GNU General Public License
19// along with this software; if not, write to the Free Software
20// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
21// USA.
22//
23
24//
25// RfbProto.java
26//
27
Constantin Kaplinskycf689b32008-04-30 12:50:34 +000028package com.tightvnc.rfbplayer;
wimba.comc23aeb02004-09-16 00:00:00 +000029
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000030import java.io.*;
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000031
32class RfbProto {
33
Constantin Kaplinsky8920b552008-06-18 06:08:59 +000034 final static String versionMsg = "RFB 003.003\n";
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000035
Constantin Kaplinsky8920b552008-06-18 06:08:59 +000036 final static int ConnFailed = 0;
37 final static int NoAuth = 1;
38 final static int VncAuth = 2;
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000039
Constantin Kaplinsky8920b552008-06-18 06:08:59 +000040 final static int VncAuthOK = 0;
41 final static int VncAuthFailed = 1;
42 final static int VncAuthTooMany = 2;
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000043
Constantin Kaplinsky8920b552008-06-18 06:08:59 +000044 final static int FramebufferUpdate = 0;
45 final static int SetColourMapEntries = 1;
46 final static int Bell = 2;
47 final static int ServerCutText = 3;
48
49 final static int SetPixelFormat = 0;
50 final static int FixColourMapEntries = 1;
51 final static int SetEncodings = 2;
52 final static int FramebufferUpdateRequest = 3;
53 final static int KeyboardEvent = 4;
54 final static int PointerEvent = 5;
55 final static int ClientCutText = 6;
56
57 final static int EncodingRaw = 0;
58 final static int EncodingCopyRect = 1;
59 final static int EncodingRRE = 2;
60 final static int EncodingCoRRE = 4;
61 final static int EncodingHextile = 5;
62 final static int EncodingZlib = 6;
63 final static int EncodingTight = 7;
64 final static int EncodingCompressLevel0 = 0xFFFFFF00;
65 final static int EncodingQualityLevel0 = 0xFFFFFFE0;
66 final static int EncodingXCursor = 0xFFFFFF10;
67 final static int EncodingRichCursor = 0xFFFFFF11;
68 final static int EncodingPointerPos = 0xFFFFFF18;
69 final static int EncodingLastRect = 0xFFFFFF20;
70 final static int EncodingNewFBSize = 0xFFFFFF21;
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000071
wimba.com93cc0db2004-10-13 16:19:45 +000072 final static int MaxNormalEncoding = 7;
73
Constantin Kaplinsky8920b552008-06-18 06:08:59 +000074 final static int HextileRaw = (1 << 0);
75 final static int HextileBackgroundSpecified = (1 << 1);
76 final static int HextileForegroundSpecified = (1 << 2);
77 final static int HextileAnySubrects = (1 << 3);
78 final static int HextileSubrectsColoured = (1 << 4);
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000079
Constantin Kaplinsky72e47ef2008-04-18 17:48:16 +000080 final static int TightExplicitFilter = 0x04;
81 final static int TightFill = 0x08;
82 final static int TightJpeg = 0x09;
83 final static int TightMaxSubencoding = 0x09;
84 final static int TightFilterCopy = 0x00;
85 final static int TightFilterPalette = 0x01;
86 final static int TightFilterGradient = 0x02;
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000087
Constantin Kaplinsky72e47ef2008-04-18 17:48:16 +000088 final static int TightMinToCompress = 12;
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000089
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000090 DataInputStream is;
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000091
Constantin Kaplinsky7b55c4f2008-06-18 09:28:30 +000092 /**
93 * Constructor. It calls <code>{@link #newSession(InputStream)}</code> to open
94 * new session.
95 *
96 * @param is the input stream from which RFB data will be read.
97 * @throws java.lang.Exception
98 * @throws java.io.IOException
99 */
100 RfbProto(InputStream is) throws Exception {
101 newSession(is);
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000102 }
103
Constantin Kaplinsky7b55c4f2008-06-18 09:28:30 +0000104 /**
105 * Open new session that can be read from the specified InputStream.
106 *
107 * @param is the input stream.
108 * @throws java.lang.Exception
109 * @throws java.io.IOException
110 */
111 public void newSession(InputStream is) throws Exception {
wimba.comd1f56df2004-11-01 16:18:54 +0000112
Constantin Kaplinsky7b55c4f2008-06-18 09:28:30 +0000113 this.is = new DataInputStream(is);
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000114
Constantin Kaplinsky903009e2002-05-20 10:55:47 +0000115 readVersionMsg();
116 if (readAuthScheme() != NoAuth) {
Constantin Kaplinskyf392f442002-05-20 13:05:42 +0000117 throw new Exception("Wrong authentication type in the session file");
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000118 }
Constantin Kaplinsky903009e2002-05-20 10:55:47 +0000119 readServerInit();
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000120 }
121
122 //
Constantin Kaplinskyc833e012002-05-30 17:59:22 +0000123 // Read server's protocol version message.
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000124 //
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000125 int serverMajor, serverMinor;
126
127 void readVersionMsg() throws IOException {
128
129 byte[] b = new byte[12];
130
wimba.comc23aeb02004-09-16 00:00:00 +0000131 for (int i = 0; i < b.length; i++)
132 b[i] = (byte)'0';
133
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000134 is.readFully(b);
135
Constantin Kaplinsky72e47ef2008-04-18 17:48:16 +0000136 if ((b[0] != 'R') || (b[1] != 'F') || (b[2] != 'B') || (b[3] != ' ') ||
137 (b[4] < '0') || (b[4] > '9') || (b[5] < '0') || (b[5] > '9') || (b[6] <
138 '0') || (b[6] > '9') || (b[7] != '.') || (b[8] < '0') || (b[8] > '9') ||
139 (b[9] < '0') || (b[9] > '9') || (b[10] < '0') || (b[10] > '9') ||
140 (b[11] != '\n')) {
Constantin Kaplinsky903009e2002-05-20 10:55:47 +0000141 throw new IOException("Incorrect protocol version");
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000142 }
143
144 serverMajor = (b[4] - '0') * 100 + (b[5] - '0') * 10 + (b[6] - '0');
145 serverMinor = (b[8] - '0') * 100 + (b[9] - '0') * 10 + (b[10] - '0');
146 }
147
148
149 //
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000150 // Find out the authentication scheme.
151 //
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000152 int readAuthScheme() throws IOException {
153 int authScheme = is.readInt();
154
155 switch (authScheme) {
156
157 case ConnFailed:
158 int reasonLen = is.readInt();
159 byte[] reason = new byte[reasonLen];
160 is.readFully(reason);
161 throw new IOException(new String(reason));
162
163 case NoAuth:
164 case VncAuth:
165 return authScheme;
166
167 default:
Constantin Kaplinsky903009e2002-05-20 10:55:47 +0000168 throw new IOException("Unknown authentication scheme " + authScheme);
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000169
170 }
171 }
172
173
174 //
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000175 // Read the server initialisation message
176 //
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000177 String desktopName;
178 int framebufferWidth, framebufferHeight;
179 int bitsPerPixel, depth;
180 boolean bigEndian, trueColour;
181 int redMax, greenMax, blueMax, redShift, greenShift, blueShift;
182
Constantin Kaplinskyf392f442002-05-20 13:05:42 +0000183 void readServerInit() throws Exception {
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000184 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.readFully(pad);
198 int nameLength = is.readInt();
199 byte[] name = new byte[nameLength];
200 is.readFully(name);
201 desktopName = new String(name);
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000202 }
203
204
205 //
206 // Set new framebuffer size
207 //
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000208 void setFramebufferSize(int width, int height) {
209 framebufferWidth = width;
210 framebufferHeight = height;
211 }
212
213
214 //
215 // Read the server message type
216 //
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000217 int readServerMessageType() throws IOException {
218 return is.readUnsignedByte();
219 }
220
221
222 //
223 // Read a FramebufferUpdate message
224 //
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000225 int updateNRects;
226
227 void readFramebufferUpdate() throws IOException {
228 is.readByte();
229 updateNRects = is.readUnsignedShort();
230 }
231
232 // Read a FramebufferUpdate rectangle header
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000233 int updateRectX, updateRectY, updateRectW, updateRectH, updateRectEncoding;
234
235 void readFramebufferUpdateRectHdr() throws IOException {
236 updateRectX = is.readUnsignedShort();
237 updateRectY = is.readUnsignedShort();
238 updateRectW = is.readUnsignedShort();
239 updateRectH = is.readUnsignedShort();
240 updateRectEncoding = is.readInt();
241
wimba.com93cc0db2004-10-13 16:19:45 +0000242 if (updateRectEncoding < 0 || updateRectEncoding > MaxNormalEncoding)
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000243 return;
244
245 if ((updateRectX + updateRectW > framebufferWidth) ||
Constantin Kaplinsky72e47ef2008-04-18 17:48:16 +0000246 (updateRectY + updateRectH > framebufferHeight)) {
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000247 throw new IOException("Framebuffer update rectangle too large: " +
Constantin Kaplinsky72e47ef2008-04-18 17:48:16 +0000248 updateRectW + "x" + updateRectH + " at (" +
249 updateRectX + "," + updateRectY + ")");
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000250 }
251 }
252
253 // Read CopyRect source X and Y.
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000254 int copyRectSrcX, copyRectSrcY;
255
256 void readCopyRect() throws IOException {
257 copyRectSrcX = is.readUnsignedShort();
258 copyRectSrcY = is.readUnsignedShort();
259 }
260
261
262 //
263 // Read a ServerCutText message
264 //
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000265 String readServerCutText() throws IOException {
266 byte[] pad = new byte[3];
267 is.readFully(pad);
268 int len = is.readInt();
269 byte[] text = new byte[len];
270 is.readFully(text);
271 return new String(text);
272 }
273
274
275 //
276 // Read integer in compact representation
277 //
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000278 int readCompactLen() throws IOException {
279 int portion = is.readUnsignedByte();
280 int len = portion & 0x7F;
281 if ((portion & 0x80) != 0) {
282 portion = is.readUnsignedByte();
283 len |= (portion & 0x7F) << 7;
284 if ((portion & 0x80) != 0) {
Constantin Kaplinsky72e47ef2008-04-18 17:48:16 +0000285 portion = is.readUnsignedByte();
286 len |= (portion & 0xFF) << 14;
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000287 }
288 }
289 return len;
290 }
291
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000292}