Mercurial > hg > Members > nobuyasu > tightVNCProxy
annotate src/myVncProxy/MyRfbProto.java @ 54:796f2b3b8665
modify MyRfbProto.java
author | e085711 |
---|---|
date | Fri, 08 Jul 2011 12:38:14 +0900 |
parents | 089bd4510538 |
children | 39741f18b4f2 a240b19b66f0 |
rev | line source |
---|---|
24 | 1 package myVncProxy; |
54 | 2 |
25 | 3 import java.awt.Graphics; |
4 import java.awt.Image; | |
5 import java.awt.image.BufferedImage; | |
6 import java.io.BufferedOutputStream; | |
15 | 7 import java.io.BufferedReader; |
25 | 8 import java.io.ByteArrayInputStream; |
9 import java.io.ByteArrayOutputStream; | |
10 | 10 import java.io.IOException; |
43 | 11 import java.io.InputStream; |
15 | 12 import java.io.InputStreamReader; |
23 | 13 import java.net.BindException; |
10 | 14 import java.net.ServerSocket; |
15 import java.net.Socket; | |
16 import java.util.LinkedList; | |
17 | |
25 | 18 import javax.imageio.ImageIO; |
19 | |
54 | 20 import myVncProxy.MulticastQueue.Client; |
21 | |
40 | 22 import java.util.concurrent.ExecutorService; |
23 import java.util.concurrent.Executors; | |
24 import java.io.OutputStream; | |
10 | 25 |
26 class MyRfbProto extends RfbProto { | |
27 | |
43 | 28 final static String versionMsg_3_998 = "RFB 003.998\n"; |
54 | 29 |
18 | 30 private int messageType; |
31 private int rectangles; | |
23 | 32 private int rectX; |
33 private int rectY; | |
34 private int rectW; | |
35 private int rectH; | |
18 | 36 private int encoding; |
27 | 37 private int zLen; |
54 | 38 private int dataLen; |
18 | 39 |
23 | 40 private ServerSocket servSock; |
41 private int acceptPort; | |
10 | 42 private byte initData[]; |
54 | 43 private LinkedList<Socket> cliListTmp; |
44 private LinkedList<Socket> cliList; | |
45 private LinkedList<Thread> sendThreads; | |
27 | 46 boolean createBimgFlag; |
54 | 47 |
40 | 48 ExecutorService executor; |
54 | 49 |
25 | 50 byte[] pngBytes; |
54 | 51 |
52 private MulticastQueue<byte[]> multicastqueue = new MulticastQueue<byte[]>(); | |
53 | |
54 MyRfbProto(String h, int p, VncViewer v) throws IOException { | |
10 | 55 super(h, p, v); |
54 | 56 cliList = new LinkedList<Socket>(); |
57 cliListTmp = new LinkedList<Socket>(); | |
27 | 58 createBimgFlag = false; |
54 | 59 sendThreads = new LinkedList<Thread>(); |
60 // executor = Executors.newCachedThreadPool(); | |
61 // executor = Executors.newSingleThreadExecutor(); | |
10 | 62 } |
63 | |
13 | 64 MyRfbProto(String h, int p) throws IOException { |
65 super(h, p); | |
54 | 66 cliList = new LinkedList<Socket>(); |
67 cliListTmp = new LinkedList<Socket>(); | |
27 | 68 createBimgFlag = false; |
54 | 69 sendThreads = new LinkedList<Thread>(); |
70 // executor = Executors.newCachedThreadPool(); | |
71 // executor = Executors.newSingleThreadExecutor(); | |
13 | 72 } |
24 | 73 |
44 | 74 // over write |
43 | 75 void writeVersionMsg() throws IOException { |
76 clientMajor = 3; | |
77 if (serverMinor >= 9) { | |
54 | 78 clientMinor = 9; |
79 os.write(versionMsg_3_998.getBytes()); | |
43 | 80 } else if (serverMajor > 3 || serverMinor >= 8) { |
81 clientMinor = 8; | |
82 os.write(versionMsg_3_8.getBytes()); | |
83 } else if (serverMinor >= 9) { | |
84 clientMinor = 9; | |
85 os.write(versionMsg_3_998.getBytes()); | |
86 } else if (serverMinor >= 7) { | |
87 clientMinor = 7; | |
88 os.write(versionMsg_3_7.getBytes()); | |
89 } else { | |
90 clientMinor = 3; | |
91 os.write(versionMsg_3_3.getBytes()); | |
92 } | |
93 protocolTightVNC = false; | |
94 initCapabilities(); | |
95 } | |
96 | |
54 | 97 void initServSock(int port) throws IOException { |
10 | 98 servSock = new ServerSocket(port); |
23 | 99 acceptPort = port; |
10 | 100 } |
54 | 101 |
102 // 5550を開けるが、開いてないなら+1のポートを開ける。 | |
103 void selectPort() { | |
23 | 104 int i = 5550; |
54 | 105 while (true) { |
106 try { | |
23 | 107 initServSock(i); |
108 break; | |
54 | 109 } catch (BindException e) { |
23 | 110 i++; |
111 continue; | |
54 | 112 } catch (IOException e) { |
10 | 113 |
23 | 114 } |
115 } | |
54 | 116 System.out.println("accept port = " + i); |
23 | 117 } |
54 | 118 |
119 int getAcceptPort() { | |
23 | 120 return acceptPort; |
121 } | |
54 | 122 |
10 | 123 void setSoTimeout(int num) throws IOException { |
124 servSock.setSoTimeout(num); | |
125 } | |
54 | 126 |
10 | 127 Socket accept() throws IOException { |
128 return servSock.accept(); | |
129 } | |
130 | |
54 | 131 void addSock(Socket sock) { |
10 | 132 cliList.add(sock); |
133 } | |
54 | 134 |
135 void addSockTmp(Socket sock) { | |
136 System.out.println("connected " + sock.getInetAddress()); | |
27 | 137 cliListTmp.add(sock); |
138 } | |
54 | 139 |
10 | 140 void mark(int len) throws IOException { |
141 is.mark(len); | |
142 } | |
143 | |
144 void reset() throws IOException { | |
145 is.reset(); | |
54 | 146 } |
10 | 147 |
148 boolean markSupported() { | |
149 return is.markSupported(); | |
150 } | |
54 | 151 |
10 | 152 void readServerInit() throws IOException { |
54 | 153 |
10 | 154 mark(255); |
155 skipBytes(20); | |
156 int nlen = readU32(); | |
54 | 157 int blen = 20 + 4 + nlen; |
10 | 158 initData = new byte[blen]; |
159 reset(); | |
160 | |
161 mark(blen); | |
162 readFully(initData); | |
163 reset(); | |
54 | 164 |
10 | 165 framebufferWidth = readU16(); |
166 framebufferHeight = readU16(); | |
167 bitsPerPixel = readU8(); | |
168 depth = readU8(); | |
169 bigEndian = (readU8() != 0); | |
170 trueColour = (readU8() != 0); | |
171 redMax = readU16(); | |
172 greenMax = readU16(); | |
173 blueMax = readU16(); | |
174 redShift = readU8(); | |
175 greenShift = readU8(); | |
176 blueShift = readU8(); | |
177 byte[] pad = new byte[3]; | |
178 readFully(pad); | |
179 int nameLength = readU32(); | |
180 byte[] name = new byte[nameLength]; | |
181 readFully(name); | |
182 desktopName = new String(name); | |
183 | |
184 // Read interaction capabilities (TightVNC protocol extensions) | |
185 if (protocolTightVNC) { | |
186 int nServerMessageTypes = readU16(); | |
187 int nClientMessageTypes = readU16(); | |
188 int nEncodingTypes = readU16(); | |
189 readU16(); | |
190 readCapabilityList(serverMsgCaps, nServerMessageTypes); | |
191 readCapabilityList(clientMsgCaps, nClientMessageTypes); | |
192 readCapabilityList(encodingCaps, nEncodingTypes); | |
193 } | |
194 | |
195 inNormalProtocol = true; | |
196 } | |
197 | |
54 | 198 void sendRfbVersion(OutputStream os) throws IOException { |
199 os.write(versionMsg_3_998.getBytes()); | |
43 | 200 } |
54 | 201 |
45 | 202 void readVersionMsg(InputStream is) throws IOException { |
203 | |
204 byte[] b = new byte[12]; | |
205 | |
206 is.read(b); | |
207 | |
208 if ((b[0] != 'R') || (b[1] != 'F') || (b[2] != 'B') || (b[3] != ' ') | |
209 || (b[4] < '0') || (b[4] > '9') || (b[5] < '0') || (b[5] > '9') | |
210 || (b[6] < '0') || (b[6] > '9') || (b[7] != '.') | |
211 || (b[8] < '0') || (b[8] > '9') || (b[9] < '0') || (b[9] > '9') | |
212 || (b[10] < '0') || (b[10] > '9') || (b[11] != '\n')) { | |
213 throw new IOException("Host " + host + " port " + port | |
214 + " is not an RFB server"); | |
215 } | |
216 | |
217 serverMajor = (b[4] - '0') * 100 + (b[5] - '0') * 10 + (b[6] - '0'); | |
218 serverMinor = (b[8] - '0') * 100 + (b[9] - '0') * 10 + (b[10] - '0'); | |
219 | |
220 if (serverMajor < 3) { | |
221 throw new IOException( | |
222 "RFB server does not support protocol version 3"); | |
54 | 223 } |
224 | |
225 } | |
226 | |
43 | 227 void sendSecurityType(OutputStream os) throws IOException { |
228 // number-of-security-types | |
229 os.write(1); | |
54 | 230 // security-types |
43 | 231 // 1:None |
232 os.write(1); | |
233 } | |
54 | 234 |
46
11da7dacbc1a
modify MyRfbProto.java and acceptThread.java add readSecType
e085711
parents:
45
diff
changeset
|
235 void readSecType(InputStream is) throws IOException { |
11da7dacbc1a
modify MyRfbProto.java and acceptThread.java add readSecType
e085711
parents:
45
diff
changeset
|
236 byte[] b = new byte[1]; |
11da7dacbc1a
modify MyRfbProto.java and acceptThread.java add readSecType
e085711
parents:
45
diff
changeset
|
237 is.read(b); |
11da7dacbc1a
modify MyRfbProto.java and acceptThread.java add readSecType
e085711
parents:
45
diff
changeset
|
238 |
11da7dacbc1a
modify MyRfbProto.java and acceptThread.java add readSecType
e085711
parents:
45
diff
changeset
|
239 } |
54 | 240 |
47
b2bf4e44504a
modify MyRfbProto.java and acceptThread.java , add sendSecResult
e085711
parents:
46
diff
changeset
|
241 void sendSecResult(OutputStream os) throws IOException { |
b2bf4e44504a
modify MyRfbProto.java and acceptThread.java , add sendSecResult
e085711
parents:
46
diff
changeset
|
242 byte[] b = castIntByte(0); |
b2bf4e44504a
modify MyRfbProto.java and acceptThread.java , add sendSecResult
e085711
parents:
46
diff
changeset
|
243 os.write(b); |
b2bf4e44504a
modify MyRfbProto.java and acceptThread.java , add sendSecResult
e085711
parents:
46
diff
changeset
|
244 } |
54 | 245 |
43 | 246 void readClientInit(InputStream in) throws IOException { |
247 byte[] b = new byte[0]; | |
248 in.read(b); | |
249 } | |
54 | 250 |
251 void sendInitData(OutputStream os) throws IOException { | |
252 os.write(initData); | |
10 | 253 } |
254 | |
54 | 255 void sendData(byte b[]) { |
256 try { | |
257 multicastqueue.put(b); | |
258 | |
259 /* | |
260 * // for(Socket cli : cliList){ // try{ // | |
261 * cli.getOutputStream().write(b, 0, b.length); // | |
262 * }catch(IOException e){ // // if socket closed // | |
263 * cliList.remove(cli); // } // } | |
264 */ | |
265 // System.out.println("cliSize="+cliSize()); | |
266 } catch (Exception e) { | |
17 | 267 } |
27 | 268 } |
54 | 269 |
270 void sendPngImage() { | |
271 try { | |
272 for (Socket cli : cliListTmp) { | |
273 try { | |
27 | 274 sendPngData(cli); |
275 addSock(cli); | |
54 | 276 } catch (IOException e) { |
27 | 277 // if socket closed |
278 cliListTmp.remove(cli); | |
279 } | |
280 } | |
54 | 281 // System.out.println("cliSize="+cliSize()); |
282 } catch (Exception e) { | |
27 | 283 } |
284 cliListTmp.clear(); | |
285 } | |
286 | |
15 | 287 boolean ready() throws IOException { |
288 BufferedReader br = new BufferedReader(new InputStreamReader(is)); | |
289 return br.ready(); | |
54 | 290 } |
10 | 291 |
54 | 292 int cliSize() { |
10 | 293 return cliList.size(); |
54 | 294 } |
295 | |
296 void printNumBytesRead() { | |
297 System.out.println("numBytesRead=" + numBytesRead); | |
298 } | |
299 | |
15 | 300 void bufResetSend(int size) throws IOException { |
301 reset(); | |
302 int len = size; | |
54 | 303 if (available() < size) |
15 | 304 len = available(); |
305 byte buffer[] = new byte[len]; | |
306 readFully(buffer); | |
307 sendData(buffer); | |
308 } | |
54 | 309 |
310 void readSendData() throws IOException { | |
39 | 311 byte buffer[] = new byte[dataLen]; |
312 readFully(buffer); | |
313 reset(); | |
314 | |
54 | 315 for (Socket cli : cliList) { |
316 try { | |
40 | 317 OutputStream out = cli.getOutputStream(); |
318 executor.execute(new SendThread(out, buffer)); | |
54 | 319 } catch (IOException e) { |
40 | 320 // if client socket closed |
39 | 321 cliListTmp.remove(cli); |
54 | 322 } catch (Exception e) { |
323 | |
39 | 324 } |
40 | 325 |
39 | 326 } |
327 } | |
54 | 328 |
329 void regiFramebufferUpdate() throws IOException { | |
27 | 330 mark(20); |
18 | 331 messageType = readU8(); |
332 skipBytes(1); | |
333 rectangles = readU16(); | |
23 | 334 rectX = readU16(); |
335 rectY = readU16(); | |
336 rectW = readU16(); | |
337 rectH = readU16(); | |
27 | 338 encoding = readU32(); |
54 | 339 if (encoding == 16) |
27 | 340 zLen = readU32(); |
23 | 341 reset(); |
15 | 342 } |
54 | 343 |
344 void checkAndMark() throws IOException { | |
345 switch (encoding) { | |
23 | 346 case RfbProto.EncodingRaw: |
39 | 347 dataLen = rectW * rectH * 4 + 16; |
348 mark(dataLen); | |
23 | 349 break; |
27 | 350 case RfbProto.EncodingZRLE: |
54 | 351 dataLen = zLen + 20; |
39 | 352 mark(dataLen); |
27 | 353 break; |
23 | 354 default: |
38 | 355 mark(1000000); |
54 | 356 } |
23 | 357 } |
54 | 358 |
359 BufferedImage createBufferedImage(Image img) { | |
360 BufferedImage bimg = new BufferedImage(img.getWidth(null), | |
361 img.getHeight(null), BufferedImage.TYPE_INT_RGB); | |
27 | 362 |
25 | 363 Graphics g = bimg.getGraphics(); |
364 g.drawImage(img, 0, 0, null); | |
365 g.dispose(); | |
366 return bimg; | |
367 } | |
368 | |
54 | 369 void createPngBytes(BufferedImage bimg) throws IOException { |
370 pngBytes = getImageBytes(bimg, "png"); | |
25 | 371 } |
54 | 372 |
373 byte[] getBytes(BufferedImage img) throws IOException { | |
25 | 374 byte[] b = getImageBytes(img, "png"); |
375 return b; | |
376 } | |
54 | 377 |
378 byte[] getImageBytes(BufferedImage image, String imageFormat) | |
379 throws IOException { | |
25 | 380 ByteArrayOutputStream bos = new ByteArrayOutputStream(); |
381 BufferedOutputStream os = new BufferedOutputStream(bos); | |
382 image.flush(); | |
383 ImageIO.write(image, imageFormat, os); | |
384 os.flush(); | |
385 os.close(); | |
386 return bos.toByteArray(); | |
387 } | |
388 | |
54 | 389 void sendPngData(Socket sock) throws IOException { |
26 | 390 byte[] dataLength = castIntByte(pngBytes.length); |
391 sock.getOutputStream().write(dataLength); | |
25 | 392 sock.getOutputStream().write(pngBytes); |
393 } | |
54 | 394 |
395 byte[] castIntByte(int len) { | |
26 | 396 byte[] b = new byte[4]; |
54 | 397 b[0] = (byte) ((len >>> 24) & 0xFF); |
398 b[1] = (byte) ((len >>> 16) & 0xFF); | |
399 b[2] = (byte) ((len >>> 8) & 0xFF); | |
400 b[3] = (byte) ((len >>> 0) & 0xFF); | |
26 | 401 return b; |
402 } | |
54 | 403 |
404 BufferedImage createBimg() throws IOException { | |
25 | 405 BufferedImage bimg = ImageIO.read(new ByteArrayInputStream(pngBytes)); |
406 return bimg; | |
407 } | |
54 | 408 |
409 void readPngData() throws IOException { | |
25 | 410 pngBytes = new byte[is.available()]; |
411 readFully(pngBytes); | |
412 } | |
54 | 413 |
414 void printFramebufferUpdate() { | |
415 | |
18 | 416 System.out.println("messageType=" + messageType); |
54 | 417 System.out.println("rectangles=" + rectangles); |
18 | 418 System.out.println("encoding=" + encoding); |
54 | 419 switch (encoding) { |
23 | 420 case RfbProto.EncodingRaw: |
54 | 421 System.out.println("rectW * rectH * 4 + 16 =" + rectW * rectH * 4 |
422 + 16); | |
23 | 423 break; |
424 default: | |
425 } | |
18 | 426 } |
43 | 427 |
54 | 428 void newClient(acceptThread acceptThread, final Socket newCli, |
429 final OutputStream os, final InputStream is) throws IOException { | |
430 // createBimgFlag = true; | |
431 // rfb.addSockTmp(newCli); | |
432 // addSock(newCli); | |
433 final Client<byte[]> c = multicastqueue.newClient(); | |
434 Runnable sender = new Runnable() { | |
435 @Override | |
436 public void run() { | |
437 try { | |
438 // 初期接続確立の部分 | |
439 sendRfbVersion(os); | |
440 readVersionMsg(is); | |
441 sendSecurityType(os); | |
442 readSecType(is); | |
443 sendSecResult(os); | |
444 readClientInit(is); | |
445 sendInitData(os); | |
43 | 446 |
54 | 447 for (;;) { |
448 byte[] b = c.poll(); | |
449 os.write(b, 0, b.length); | |
450 } | |
451 } catch (IOException e) { | |
452 //接続が切れた処理 | |
453 //lockしないと駄目 | |
454 // cliList.remove(newCli); | |
455 } | |
456 | |
457 } | |
458 | |
459 }; | |
460 new Thread(sender).start(); | |
461 | |
462 } | |
463 } |