Mercurial > hg > Members > nobuyasu > tightVNCProxy
annotate src/myVncProxy/MyRfbProto.java @ 75:6e703f1000e7
merge
author | Yu Taninari <e085734@ie.u-ryukyu.ac.jp> |
---|---|
date | Thu, 28 Jul 2011 17:52:48 +0900 |
parents | 6fc4272db7e2 f695bc56eb4f |
children | 347c153f74c7 |
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 { | |
43 | 27 final static String versionMsg_3_998 = "RFB 003.998\n"; |
65 | 28 /** |
29 * CheckMillis is one of new msgType for RFB 3.998. | |
30 */ | |
31 final static int CheckMillis = 4; | |
32 boolean printStatusFlag = false; | |
33 long startCheckTime; | |
54 | 34 |
18 | 35 private int messageType; |
36 private int rectangles; | |
23 | 37 private int rectX; |
38 private int rectY; | |
39 private int rectW; | |
40 private int rectH; | |
18 | 41 private int encoding; |
27 | 42 private int zLen; |
18 | 43 |
23 | 44 private ServerSocket servSock; |
45 private int acceptPort; | |
10 | 46 private byte initData[]; |
54 | 47 private LinkedList<Socket> cliListTmp; |
48 private LinkedList<Socket> cliList; | |
49 private LinkedList<Thread> sendThreads; | |
27 | 50 boolean createBimgFlag; |
54 | 51 |
40 | 52 ExecutorService executor; |
54 | 53 |
25 | 54 byte[] pngBytes; |
54 | 55 |
56 private MulticastQueue<byte[]> multicastqueue = new MulticastQueue<byte[]>(); | |
57 | |
58 MyRfbProto(String h, int p, VncViewer v) throws IOException { | |
10 | 59 super(h, p, v); |
54 | 60 cliList = new LinkedList<Socket>(); |
61 cliListTmp = new LinkedList<Socket>(); | |
27 | 62 createBimgFlag = false; |
61 | 63 // sendThreads = new LinkedList<Thread>(); |
54 | 64 // executor = Executors.newCachedThreadPool(); |
65 // executor = Executors.newSingleThreadExecutor(); | |
10 | 66 } |
67 | |
13 | 68 MyRfbProto(String h, int p) throws IOException { |
69 super(h, p); | |
54 | 70 cliList = new LinkedList<Socket>(); |
71 cliListTmp = new LinkedList<Socket>(); | |
27 | 72 createBimgFlag = false; |
61 | 73 // sendThreads = new LinkedList<Thread>(); |
54 | 74 // executor = Executors.newCachedThreadPool(); |
75 // executor = Executors.newSingleThreadExecutor(); | |
13 | 76 } |
24 | 77 |
44 | 78 // over write |
43 | 79 void writeVersionMsg() throws IOException { |
80 clientMajor = 3; | |
81 if (serverMinor >= 9) { | |
54 | 82 clientMinor = 9; |
83 os.write(versionMsg_3_998.getBytes()); | |
43 | 84 } else if (serverMajor > 3 || serverMinor >= 8) { |
85 clientMinor = 8; | |
86 os.write(versionMsg_3_8.getBytes()); | |
87 } else if (serverMinor >= 9) { | |
88 clientMinor = 9; | |
89 os.write(versionMsg_3_998.getBytes()); | |
90 } else if (serverMinor >= 7) { | |
91 clientMinor = 7; | |
92 os.write(versionMsg_3_7.getBytes()); | |
93 } else { | |
94 clientMinor = 3; | |
95 os.write(versionMsg_3_3.getBytes()); | |
96 } | |
97 protocolTightVNC = false; | |
98 initCapabilities(); | |
99 } | |
100 | |
54 | 101 void initServSock(int port) throws IOException { |
10 | 102 servSock = new ServerSocket(port); |
23 | 103 acceptPort = port; |
10 | 104 } |
54 | 105 |
106 // 5550を開けるが、開いてないなら+1のポートを開ける。 | |
107 void selectPort() { | |
23 | 108 int i = 5550; |
54 | 109 while (true) { |
110 try { | |
23 | 111 initServSock(i); |
112 break; | |
54 | 113 } catch (BindException e) { |
23 | 114 i++; |
115 continue; | |
54 | 116 } catch (IOException e) { |
10 | 117 |
23 | 118 } |
119 } | |
54 | 120 System.out.println("accept port = " + i); |
23 | 121 } |
54 | 122 |
123 int getAcceptPort() { | |
23 | 124 return acceptPort; |
125 } | |
54 | 126 |
10 | 127 void setSoTimeout(int num) throws IOException { |
128 servSock.setSoTimeout(num); | |
129 } | |
54 | 130 |
10 | 131 Socket accept() throws IOException { |
132 return servSock.accept(); | |
133 } | |
134 | |
54 | 135 void addSock(Socket sock) { |
10 | 136 cliList.add(sock); |
137 } | |
54 | 138 |
139 void addSockTmp(Socket sock) { | |
140 System.out.println("connected " + sock.getInetAddress()); | |
27 | 141 cliListTmp.add(sock); |
142 } | |
54 | 143 |
10 | 144 void mark(int len) throws IOException { |
145 is.mark(len); | |
146 } | |
147 | |
148 void reset() throws IOException { | |
149 is.reset(); | |
54 | 150 } |
10 | 151 |
152 boolean markSupported() { | |
153 return is.markSupported(); | |
154 } | |
54 | 155 |
10 | 156 void readServerInit() throws IOException { |
54 | 157 |
10 | 158 mark(255); |
159 skipBytes(20); | |
160 int nlen = readU32(); | |
54 | 161 int blen = 20 + 4 + nlen; |
10 | 162 initData = new byte[blen]; |
163 reset(); | |
164 | |
165 mark(blen); | |
166 readFully(initData); | |
167 reset(); | |
54 | 168 |
10 | 169 framebufferWidth = readU16(); |
170 framebufferHeight = readU16(); | |
171 bitsPerPixel = readU8(); | |
172 depth = readU8(); | |
173 bigEndian = (readU8() != 0); | |
174 trueColour = (readU8() != 0); | |
175 redMax = readU16(); | |
176 greenMax = readU16(); | |
177 blueMax = readU16(); | |
178 redShift = readU8(); | |
179 greenShift = readU8(); | |
180 blueShift = readU8(); | |
181 byte[] pad = new byte[3]; | |
182 readFully(pad); | |
183 int nameLength = readU32(); | |
184 byte[] name = new byte[nameLength]; | |
185 readFully(name); | |
186 desktopName = new String(name); | |
187 | |
188 // Read interaction capabilities (TightVNC protocol extensions) | |
189 if (protocolTightVNC) { | |
190 int nServerMessageTypes = readU16(); | |
191 int nClientMessageTypes = readU16(); | |
192 int nEncodingTypes = readU16(); | |
193 readU16(); | |
194 readCapabilityList(serverMsgCaps, nServerMessageTypes); | |
195 readCapabilityList(clientMsgCaps, nClientMessageTypes); | |
196 readCapabilityList(encodingCaps, nEncodingTypes); | |
197 } | |
198 | |
199 inNormalProtocol = true; | |
200 } | |
201 | |
54 | 202 void sendRfbVersion(OutputStream os) throws IOException { |
203 os.write(versionMsg_3_998.getBytes()); | |
43 | 204 } |
54 | 205 |
45 | 206 void readVersionMsg(InputStream is) throws IOException { |
207 | |
208 byte[] b = new byte[12]; | |
209 | |
210 is.read(b); | |
211 | |
212 if ((b[0] != 'R') || (b[1] != 'F') || (b[2] != 'B') || (b[3] != ' ') | |
213 || (b[4] < '0') || (b[4] > '9') || (b[5] < '0') || (b[5] > '9') | |
214 || (b[6] < '0') || (b[6] > '9') || (b[7] != '.') | |
215 || (b[8] < '0') || (b[8] > '9') || (b[9] < '0') || (b[9] > '9') | |
216 || (b[10] < '0') || (b[10] > '9') || (b[11] != '\n')) { | |
217 throw new IOException("Host " + host + " port " + port | |
218 + " is not an RFB server"); | |
219 } | |
220 | |
221 serverMajor = (b[4] - '0') * 100 + (b[5] - '0') * 10 + (b[6] - '0'); | |
222 serverMinor = (b[8] - '0') * 100 + (b[9] - '0') * 10 + (b[10] - '0'); | |
223 | |
224 if (serverMajor < 3) { | |
225 throw new IOException( | |
226 "RFB server does not support protocol version 3"); | |
54 | 227 } |
228 | |
229 } | |
230 | |
43 | 231 void sendSecurityType(OutputStream os) throws IOException { |
232 // number-of-security-types | |
233 os.write(1); | |
54 | 234 // security-types |
43 | 235 // 1:None |
236 os.write(1); | |
237 } | |
54 | 238 |
46
11da7dacbc1a
modify MyRfbProto.java and acceptThread.java add readSecType
e085711
parents:
45
diff
changeset
|
239 void readSecType(InputStream is) throws IOException { |
11da7dacbc1a
modify MyRfbProto.java and acceptThread.java add readSecType
e085711
parents:
45
diff
changeset
|
240 byte[] b = new byte[1]; |
11da7dacbc1a
modify MyRfbProto.java and acceptThread.java add readSecType
e085711
parents:
45
diff
changeset
|
241 is.read(b); |
11da7dacbc1a
modify MyRfbProto.java and acceptThread.java add readSecType
e085711
parents:
45
diff
changeset
|
242 |
11da7dacbc1a
modify MyRfbProto.java and acceptThread.java add readSecType
e085711
parents:
45
diff
changeset
|
243 } |
54 | 244 |
47
b2bf4e44504a
modify MyRfbProto.java and acceptThread.java , add sendSecResult
e085711
parents:
46
diff
changeset
|
245 void sendSecResult(OutputStream os) throws IOException { |
b2bf4e44504a
modify MyRfbProto.java and acceptThread.java , add sendSecResult
e085711
parents:
46
diff
changeset
|
246 byte[] b = castIntByte(0); |
b2bf4e44504a
modify MyRfbProto.java and acceptThread.java , add sendSecResult
e085711
parents:
46
diff
changeset
|
247 os.write(b); |
b2bf4e44504a
modify MyRfbProto.java and acceptThread.java , add sendSecResult
e085711
parents:
46
diff
changeset
|
248 } |
54 | 249 |
43 | 250 void readClientInit(InputStream in) throws IOException { |
251 byte[] b = new byte[0]; | |
252 in.read(b); | |
253 } | |
54 | 254 |
255 void sendInitData(OutputStream os) throws IOException { | |
256 os.write(initData); | |
10 | 257 } |
258 | |
54 | 259 void sendData(byte b[]) { |
260 try { | |
261 multicastqueue.put(b); | |
262 | |
263 /* | |
264 * // for(Socket cli : cliList){ // try{ // | |
265 * cli.getOutputStream().write(b, 0, b.length); // | |
266 * }catch(IOException e){ // // if socket closed // | |
267 * cliList.remove(cli); // } // } | |
268 */ | |
269 // System.out.println("cliSize="+cliSize()); | |
270 } catch (Exception e) { | |
17 | 271 } |
27 | 272 } |
54 | 273 |
274 void sendPngImage() { | |
275 try { | |
276 for (Socket cli : cliListTmp) { | |
277 try { | |
27 | 278 sendPngData(cli); |
279 addSock(cli); | |
54 | 280 } catch (IOException e) { |
27 | 281 // if socket closed |
282 cliListTmp.remove(cli); | |
283 } | |
284 } | |
54 | 285 // System.out.println("cliSize="+cliSize()); |
286 } catch (Exception e) { | |
27 | 287 } |
288 cliListTmp.clear(); | |
289 } | |
290 | |
15 | 291 boolean ready() throws IOException { |
292 BufferedReader br = new BufferedReader(new InputStreamReader(is)); | |
293 return br.ready(); | |
54 | 294 } |
10 | 295 |
54 | 296 int cliSize() { |
10 | 297 return cliList.size(); |
54 | 298 } |
299 | |
300 void printNumBytesRead() { | |
301 System.out.println("numBytesRead=" + numBytesRead); | |
302 } | |
303 | |
15 | 304 void bufResetSend(int size) throws IOException { |
305 reset(); | |
306 int len = size; | |
54 | 307 if (available() < size) |
15 | 308 len = available(); |
309 byte buffer[] = new byte[len]; | |
310 readFully(buffer); | |
311 sendData(buffer); | |
312 } | |
54 | 313 |
61 | 314 |
54 | 315 void regiFramebufferUpdate() throws IOException { |
27 | 316 mark(20); |
18 | 317 messageType = readU8(); |
318 skipBytes(1); | |
319 rectangles = readU16(); | |
23 | 320 rectX = readU16(); |
321 rectY = readU16(); | |
322 rectW = readU16(); | |
323 rectH = readU16(); | |
27 | 324 encoding = readU32(); |
54 | 325 if (encoding == 16) |
27 | 326 zLen = readU32(); |
23 | 327 reset(); |
67 | 328 /* |
329 int dataLen; | |
330 switch (encoding) { | |
331 case RfbProto.EncodingRaw: | |
332 dataLen = rectW * rectH * 4 + 16; | |
333 mark(dataLen); | |
334 break; | |
335 case RfbProto.EncodingCopyRect: | |
336 dataLen = 16 + 4; | |
337 mark(dataLen); | |
338 break; | |
339 case RfbProto.EncodingRRE: | |
340 case RfbProto.EncodingCoRRE: | |
341 case RfbProto.EncodingHextile: | |
342 | |
343 case RfbProto.EncodingZlib: | |
344 case RfbProto.EncodingTight: | |
345 case RfbProto.EncodingZRLE: | |
346 dataLen = zLen + 20; | |
347 mark(dataLen); | |
348 break; | |
349 default: | |
350 dataLen = 1000000; | |
351 mark(dataLen); | |
352 } | |
353 | |
354 */ | |
355 | |
15 | 356 } |
54 | 357 |
61 | 358 int checkAndMark() throws IOException { |
359 int dataLen; | |
54 | 360 switch (encoding) { |
23 | 361 case RfbProto.EncodingRaw: |
39 | 362 dataLen = rectW * rectH * 4 + 16; |
363 mark(dataLen); | |
23 | 364 break; |
67 | 365 case RfbProto.EncodingCopyRect: |
366 dataLen = 16 + 4; | |
367 mark(dataLen); | |
368 break; | |
369 case RfbProto.EncodingRRE: | |
370 case RfbProto.EncodingCoRRE: | |
371 case RfbProto.EncodingHextile: | |
372 case RfbProto.EncodingZlib: | |
373 case RfbProto.EncodingTight: | |
27 | 374 case RfbProto.EncodingZRLE: |
54 | 375 dataLen = zLen + 20; |
39 | 376 mark(dataLen); |
27 | 377 break; |
23 | 378 default: |
61 | 379 dataLen = 1000000; |
62 | 380 mark(dataLen); |
54 | 381 } |
61 | 382 return dataLen; |
383 } | |
65 | 384 |
61 | 385 void readSendData(int dataLen) throws IOException { |
386 byte buffer[] = new byte[dataLen]; | |
387 readFully(buffer); | |
388 multicastqueue.put(buffer); | |
389 reset(); | |
65 | 390 |
61 | 391 /* |
392 for (Socket cli : cliList) { | |
393 try { | |
394 OutputStream out = cli.getOutputStream(); | |
395 executor.execute(new SendThread(out, buffer)); | |
396 } catch (IOException e) { | |
397 // if client socket closed | |
398 cliListTmp.remove(cli); | |
399 } catch (Exception e) { | |
400 | |
401 } | |
402 | |
403 } | |
404 */ | |
405 } | |
406 void sendDataToClient() throws IOException { | |
407 regiFramebufferUpdate(); | |
408 int dataLen = checkAndMark(); | |
409 readSendData(dataLen); | |
23 | 410 } |
54 | 411 |
412 BufferedImage createBufferedImage(Image img) { | |
413 BufferedImage bimg = new BufferedImage(img.getWidth(null), | |
414 img.getHeight(null), BufferedImage.TYPE_INT_RGB); | |
27 | 415 |
25 | 416 Graphics g = bimg.getGraphics(); |
417 g.drawImage(img, 0, 0, null); | |
418 g.dispose(); | |
419 return bimg; | |
420 } | |
421 | |
54 | 422 void createPngBytes(BufferedImage bimg) throws IOException { |
423 pngBytes = getImageBytes(bimg, "png"); | |
25 | 424 } |
54 | 425 |
426 byte[] getBytes(BufferedImage img) throws IOException { | |
25 | 427 byte[] b = getImageBytes(img, "png"); |
428 return b; | |
429 } | |
54 | 430 |
431 byte[] getImageBytes(BufferedImage image, String imageFormat) | |
432 throws IOException { | |
25 | 433 ByteArrayOutputStream bos = new ByteArrayOutputStream(); |
434 BufferedOutputStream os = new BufferedOutputStream(bos); | |
435 image.flush(); | |
436 ImageIO.write(image, imageFormat, os); | |
437 os.flush(); | |
438 os.close(); | |
439 return bos.toByteArray(); | |
440 } | |
441 | |
54 | 442 void sendPngData(Socket sock) throws IOException { |
26 | 443 byte[] dataLength = castIntByte(pngBytes.length); |
444 sock.getOutputStream().write(dataLength); | |
25 | 445 sock.getOutputStream().write(pngBytes); |
446 } | |
54 | 447 |
448 byte[] castIntByte(int len) { | |
26 | 449 byte[] b = new byte[4]; |
54 | 450 b[0] = (byte) ((len >>> 24) & 0xFF); |
451 b[1] = (byte) ((len >>> 16) & 0xFF); | |
452 b[2] = (byte) ((len >>> 8) & 0xFF); | |
453 b[3] = (byte) ((len >>> 0) & 0xFF); | |
26 | 454 return b; |
455 } | |
54 | 456 |
457 BufferedImage createBimg() throws IOException { | |
25 | 458 BufferedImage bimg = ImageIO.read(new ByteArrayInputStream(pngBytes)); |
459 return bimg; | |
460 } | |
65 | 461 /* |
54 | 462 void readPngData() throws IOException { |
25 | 463 pngBytes = new byte[is.available()]; |
464 readFully(pngBytes); | |
465 } | |
65 | 466 */ |
54 | 467 void printFramebufferUpdate() { |
468 | |
18 | 469 System.out.println("messageType=" + messageType); |
54 | 470 System.out.println("rectangles=" + rectangles); |
18 | 471 System.out.println("encoding=" + encoding); |
54 | 472 switch (encoding) { |
23 | 473 case RfbProto.EncodingRaw: |
54 | 474 System.out.println("rectW * rectH * 4 + 16 =" + rectW * rectH * 4 |
475 + 16); | |
23 | 476 break; |
477 default: | |
478 } | |
18 | 479 } |
65 | 480 |
481 void readCheckMillis() throws IOException { | |
66 | 482 byte[] b = new byte[2]; |
65 | 483 readFully(b); |
484 } | |
485 | |
66 | 486 void startCheckMillis() { |
487 byte[] b = new byte[2]; | |
488 b[0] = (byte) CheckMillis; | |
489 b[1] = (byte) 0; | |
490 startCheckTime = System.currentTimeMillis(); | |
491 System.out.println("startChckTime = "+ startCheckTime); | |
65 | 492 multicastqueue.put(b); |
493 } | |
494 | |
495 void endCheckMills() { | |
496 long accTime = System.currentTimeMillis(); | |
497 long time = accTime - startCheckTime; | |
498 System.out.println("checkMillis: " + time); | |
499 } | |
500 | |
501 void printStatus() { | |
502 System.out.println(); | |
503 } | |
504 | |
505 synchronized void changeStatusFlag() { | |
506 printStatusFlag = true; | |
507 } | |
508 | |
509 void printMills() { | |
510 if(printStatusFlag) { | |
511 | |
512 changeStatusFlag(); | |
513 } else { | |
514 changeStatusFlag(); | |
515 } | |
516 } | |
517 | |
43 | 518 |
73 | 519 void newClient(AcceptThread acceptThread, final Socket newCli, |
54 | 520 final OutputStream os, final InputStream is) throws IOException { |
521 // createBimgFlag = true; | |
522 // rfb.addSockTmp(newCli); | |
523 // addSock(newCli); | |
524 final Client<byte[]> c = multicastqueue.newClient(); | |
525 Runnable sender = new Runnable() { | |
526 public void run() { | |
527 try { | |
65 | 528 /** |
529 * initial connection of RFB protocol | |
530 */ | |
54 | 531 sendRfbVersion(os); |
532 readVersionMsg(is); | |
533 sendSecurityType(os); | |
534 readSecType(is); | |
535 sendSecResult(os); | |
536 readClientInit(is); | |
537 sendInitData(os); | |
43 | 538 |
54 | 539 for (;;) { |
540 byte[] b = c.poll(); | |
541 os.write(b, 0, b.length); | |
542 } | |
543 } catch (IOException e) { | |
65 | 544 /** |
545 * if socket closed | |
546 */ | |
54 | 547 // cliList.remove(newCli); |
548 } | |
549 | |
550 } | |
551 | |
552 }; | |
553 new Thread(sender).start(); | |
554 | |
555 } | |
66 | 556 |
557 void sendCheckMillis() { | |
558 | |
559 Runnable stdin = new Runnable() { | |
560 public void run() { | |
561 int c; | |
562 try { | |
563 while( (c = System.in.read()) != -1 ) { | |
564 switch(c) { | |
565 case 's': | |
566 break; | |
567 default: | |
568 startCheckMillis(); | |
569 break; | |
570 } | |
571 } | |
572 }catch(IOException e){ | |
573 System.out.println(e); | |
574 } | |
575 } | |
576 }; | |
577 | |
578 new Thread(stdin).start(); | |
579 } | |
580 | |
54 | 581 } |
66 | 582 |
583 |