blob: 952dc8df2f97c0aa8ec1d0a3a6ad098dc23b41b9 [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
wimba.comc23aeb02004-09-16 00:00:00 +000027package com.HorizonLive.RfbPlayer;
28
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000029import java.io.*;
30import java.awt.*;
31import java.awt.event.*;
Constantin Kaplinsky37cc43e2002-05-30 17:30:11 +000032import java.net.*;
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000033
34class RfbProto {
35
36 final String versionMsg = "RFB 003.003\n";
Constantin Kaplinsky72e47ef2008-04-18 17:48:16 +000037 final static int ConnFailed = 0, NoAuth = 1, VncAuth = 2;
38 final static int VncAuthOK = 0, VncAuthFailed = 1, VncAuthTooMany = 2;
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000039
Constantin Kaplinsky72e47ef2008-04-18 17:48:16 +000040 final static int FramebufferUpdate = 0, SetColourMapEntries = 1, Bell = 2, ServerCutText =
41 3;
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000042
Constantin Kaplinsky72e47ef2008-04-18 17:48:16 +000043 final int SetPixelFormat = 0, FixColourMapEntries = 1, SetEncodings = 2, FramebufferUpdateRequest =
44 3, KeyboardEvent = 4, PointerEvent = 5, ClientCutText = 6;
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000045
Constantin Kaplinsky72e47ef2008-04-18 17:48:16 +000046 final static int EncodingRaw = 0, EncodingCopyRect = 1, EncodingRRE = 2, EncodingCoRRE =
47 4, EncodingHextile = 5, EncodingZlib = 6, EncodingTight = 7, EncodingCompressLevel0 =
48 0xFFFFFF00, EncodingQualityLevel0 = 0xFFFFFFE0, EncodingXCursor =
wimba.coma27098c2004-09-21 15:22:02 +000049 0xFFFFFF10, EncodingRichCursor = 0xFFFFFF11, EncodingPointerPos =
50 0xFFFFFF18, EncodingLastRect = 0xFFFFFF20, EncodingNewFBSize =
51 0xFFFFFF21;
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000052
wimba.com93cc0db2004-10-13 16:19:45 +000053 final static int MaxNormalEncoding = 7;
54
Constantin Kaplinsky72e47ef2008-04-18 17:48:16 +000055 final int HextileRaw = (1 << 0);
56 final int HextileBackgroundSpecified = (1 << 1);
57 final int HextileForegroundSpecified = (1 << 2);
58 final int HextileAnySubrects = (1 << 3);
59 final int HextileSubrectsColoured = (1 << 4);
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000060
Constantin Kaplinsky72e47ef2008-04-18 17:48:16 +000061 final static int TightExplicitFilter = 0x04;
62 final static int TightFill = 0x08;
63 final static int TightJpeg = 0x09;
64 final static int TightMaxSubencoding = 0x09;
65 final static int TightFilterCopy = 0x00;
66 final static int TightFilterPalette = 0x01;
67 final static int TightFilterGradient = 0x02;
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000068
Constantin Kaplinsky72e47ef2008-04-18 17:48:16 +000069 final static int TightMinToCompress = 12;
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000070
Constantin Kaplinsky37cc43e2002-05-30 17:30:11 +000071 FbsInputStream fbs;
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000072 DataInputStream is;
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000073
74
75 //
Constantin Kaplinsky903009e2002-05-20 10:55:47 +000076 // Constructor.
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000077 //
Constantin Kaplinsky37cc43e2002-05-30 17:30:11 +000078 RfbProto(URL url) throws Exception {
79 fbs = null;
80 newSession(url);
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000081 }
82
Constantin Kaplinskyc833e012002-05-30 17:59:22 +000083 //
84 // Open new session URL.
85 //
Constantin Kaplinsky37cc43e2002-05-30 17:30:11 +000086 public void newSession(URL url) throws Exception {
87 if (fbs != null)
88 fbs.close();
89 fbs = new FbsInputStream(url.openStream());
90 is = new DataInputStream(fbs);
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000091
Constantin Kaplinsky903009e2002-05-20 10:55:47 +000092 readVersionMsg();
93 if (readAuthScheme() != NoAuth) {
Constantin Kaplinskyf392f442002-05-20 13:05:42 +000094 throw new Exception("Wrong authentication type in the session file");
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000095 }
Constantin Kaplinsky903009e2002-05-20 10:55:47 +000096 readServerInit();
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000097 }
98
99 //
Constantin Kaplinskyc833e012002-05-30 17:59:22 +0000100 // Read server's protocol version message.
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000101 //
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000102 int serverMajor, serverMinor;
103
104 void readVersionMsg() throws IOException {
105
106 byte[] b = new byte[12];
107
wimba.comc23aeb02004-09-16 00:00:00 +0000108 for (int i = 0; i < b.length; i++)
109 b[i] = (byte)'0';
110
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000111 is.readFully(b);
112
Constantin Kaplinsky72e47ef2008-04-18 17:48:16 +0000113 if ((b[0] != 'R') || (b[1] != 'F') || (b[2] != 'B') || (b[3] != ' ') ||
114 (b[4] < '0') || (b[4] > '9') || (b[5] < '0') || (b[5] > '9') || (b[6] <
115 '0') || (b[6] > '9') || (b[7] != '.') || (b[8] < '0') || (b[8] > '9') ||
116 (b[9] < '0') || (b[9] > '9') || (b[10] < '0') || (b[10] > '9') ||
117 (b[11] != '\n')) {
Constantin Kaplinsky903009e2002-05-20 10:55:47 +0000118 throw new IOException("Incorrect protocol version");
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000119 }
120
121 serverMajor = (b[4] - '0') * 100 + (b[5] - '0') * 10 + (b[6] - '0');
122 serverMinor = (b[8] - '0') * 100 + (b[9] - '0') * 10 + (b[10] - '0');
123 }
124
125
126 //
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000127 // Find out the authentication scheme.
128 //
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000129 int readAuthScheme() throws IOException {
130 int authScheme = is.readInt();
131
132 switch (authScheme) {
133
134 case ConnFailed:
135 int reasonLen = is.readInt();
136 byte[] reason = new byte[reasonLen];
137 is.readFully(reason);
138 throw new IOException(new String(reason));
139
140 case NoAuth:
141 case VncAuth:
142 return authScheme;
143
144 default:
Constantin Kaplinsky903009e2002-05-20 10:55:47 +0000145 throw new IOException("Unknown authentication scheme " + authScheme);
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000146
147 }
148 }
149
150
151 //
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000152 // Read the server initialisation message
153 //
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000154 String desktopName;
155 int framebufferWidth, framebufferHeight;
156 int bitsPerPixel, depth;
157 boolean bigEndian, trueColour;
158 int redMax, greenMax, blueMax, redShift, greenShift, blueShift;
159
Constantin Kaplinskyf392f442002-05-20 13:05:42 +0000160 void readServerInit() throws Exception {
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000161 framebufferWidth = is.readUnsignedShort();
162 framebufferHeight = is.readUnsignedShort();
163 bitsPerPixel = is.readUnsignedByte();
164 depth = is.readUnsignedByte();
165 bigEndian = (is.readUnsignedByte() != 0);
166 trueColour = (is.readUnsignedByte() != 0);
167 redMax = is.readUnsignedShort();
168 greenMax = is.readUnsignedShort();
169 blueMax = is.readUnsignedShort();
170 redShift = is.readUnsignedByte();
171 greenShift = is.readUnsignedByte();
172 blueShift = is.readUnsignedByte();
173 byte[] pad = new byte[3];
174 is.readFully(pad);
175 int nameLength = is.readInt();
176 byte[] name = new byte[nameLength];
177 is.readFully(name);
178 desktopName = new String(name);
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000179 }
180
181
182 //
183 // Set new framebuffer size
184 //
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000185 void setFramebufferSize(int width, int height) {
186 framebufferWidth = width;
187 framebufferHeight = height;
188 }
189
190
191 //
192 // Read the server message type
193 //
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000194 int readServerMessageType() throws IOException {
195 return is.readUnsignedByte();
196 }
197
198
199 //
200 // Read a FramebufferUpdate message
201 //
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000202 int updateNRects;
203
204 void readFramebufferUpdate() throws IOException {
205 is.readByte();
206 updateNRects = is.readUnsignedShort();
207 }
208
209 // Read a FramebufferUpdate rectangle header
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000210 int updateRectX, updateRectY, updateRectW, updateRectH, updateRectEncoding;
211
212 void readFramebufferUpdateRectHdr() throws IOException {
213 updateRectX = is.readUnsignedShort();
214 updateRectY = is.readUnsignedShort();
215 updateRectW = is.readUnsignedShort();
216 updateRectH = is.readUnsignedShort();
217 updateRectEncoding = is.readInt();
218
wimba.com93cc0db2004-10-13 16:19:45 +0000219 if (updateRectEncoding < 0 || updateRectEncoding > MaxNormalEncoding)
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000220 return;
221
222 if ((updateRectX + updateRectW > framebufferWidth) ||
Constantin Kaplinsky72e47ef2008-04-18 17:48:16 +0000223 (updateRectY + updateRectH > framebufferHeight)) {
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000224 throw new IOException("Framebuffer update rectangle too large: " +
Constantin Kaplinsky72e47ef2008-04-18 17:48:16 +0000225 updateRectW + "x" + updateRectH + " at (" +
226 updateRectX + "," + updateRectY + ")");
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000227 }
228 }
229
230 // Read CopyRect source X and Y.
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000231 int copyRectSrcX, copyRectSrcY;
232
233 void readCopyRect() throws IOException {
234 copyRectSrcX = is.readUnsignedShort();
235 copyRectSrcY = is.readUnsignedShort();
236 }
237
238
239 //
240 // Read a ServerCutText message
241 //
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000242 String readServerCutText() throws IOException {
243 byte[] pad = new byte[3];
244 is.readFully(pad);
245 int len = is.readInt();
246 byte[] text = new byte[len];
247 is.readFully(text);
248 return new String(text);
249 }
250
251
252 //
253 // Read integer in compact representation
254 //
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000255 int readCompactLen() throws IOException {
256 int portion = is.readUnsignedByte();
257 int len = portion & 0x7F;
258 if ((portion & 0x80) != 0) {
259 portion = is.readUnsignedByte();
260 len |= (portion & 0x7F) << 7;
261 if ((portion & 0x80) != 0) {
Constantin Kaplinsky72e47ef2008-04-18 17:48:16 +0000262 portion = is.readUnsignedByte();
263 len |= (portion & 0xFF) << 14;
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000264 }
265 }
266 return len;
267 }
268
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000269}