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