Mercurial > hg > Members > nobuyasu > tightVNCProxy
annotate src/myVncProxy/MyRfbProto.java @ 85:b384db76c28a
a little progress...
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Wed, 03 Aug 2011 07:39:43 +0900 |
parents | 704e01d2390c |
children | b7225991184b |
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 |
81
9109273b96dc
consume too much memory
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
80
diff
changeset
|
374 void readSendData(int dataLen) throws IOException, DataFormatException { |
9109273b96dc
consume too much memory
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
80
diff
changeset
|
375 byte b[] = new byte[dataLen]; |
9109273b96dc
consume too much memory
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
80
diff
changeset
|
376 readFully(b); |
84 | 377 LinkedList<byte[]>bufs = new LinkedList<byte[]>(); |
81
9109273b96dc
consume too much memory
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
80
diff
changeset
|
378 if (b[0]==RfbProto.FramebufferUpdate) { |
84 | 379 int encoding = u32(b,12); |
81
9109273b96dc
consume too much memory
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
80
diff
changeset
|
380 if (encoding==RfbProto.EncodingZlib||encoding==RfbProto.EncodingZRLE) { |
84 | 381 int len=0,len0; |
81
9109273b96dc
consume too much memory
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
80
diff
changeset
|
382 inflater.setInput(b, 20, b.length-20); |
82
0cbe556e2c54
remove item to reduce memory
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
81
diff
changeset
|
383 do { |
84 | 384 byte buf[] = new byte[INFLATE_BUFSIZE]; |
385 len0 = inflater.inflate(buf); | |
386 len += len0; | |
387 bufs.addLast(buf); | |
388 } while (len0 ==INFLATE_BUFSIZE); | |
389 byte [] blen = castIntByte(len0); | |
390 bufs.addFirst(blen); | |
391 byte inf[] = new byte[16]; | |
392 for(int i = 0;i<16;i++) inf[i] = b[i]; | |
393 bufs.addFirst(inf); | |
394 multicastqueue.put(bufs); | |
81
9109273b96dc
consume too much memory
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
80
diff
changeset
|
395 is.reset(); |
84 | 396 return ; |
81
9109273b96dc
consume too much memory
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
80
diff
changeset
|
397 } |
9109273b96dc
consume too much memory
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
80
diff
changeset
|
398 } |
84 | 399 bufs.add(b); |
400 multicastqueue.put(bufs); | |
78 | 401 is.reset(); |
65 | 402 |
80 | 403 // It may be compressed. We can inflate here to avoid repeating clients decompressing here, |
404 // but it may generate too many large data. It is better to do it in each client. | |
81
9109273b96dc
consume too much memory
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
80
diff
changeset
|
405 // But we have do inflation for all input data, so we have to do it here. |
61 | 406 /* |
407 for (Socket cli : cliList) { | |
408 try { | |
409 OutputStream out = cli.getOutputStream(); | |
410 executor.execute(new SendThread(out, buffer)); | |
411 } catch (IOException e) { | |
412 // if client socket closed | |
413 cliListTmp.remove(cli); | |
414 } catch (Exception e) { | |
415 | |
416 } | |
417 | |
418 } | |
419 */ | |
420 } | |
81
9109273b96dc
consume too much memory
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
80
diff
changeset
|
421 void sendDataToClient() throws Exception { |
61 | 422 regiFramebufferUpdate(); |
423 int dataLen = checkAndMark(); | |
424 readSendData(dataLen); | |
23 | 425 } |
54 | 426 |
427 BufferedImage createBufferedImage(Image img) { | |
428 BufferedImage bimg = new BufferedImage(img.getWidth(null), | |
429 img.getHeight(null), BufferedImage.TYPE_INT_RGB); | |
27 | 430 |
25 | 431 Graphics g = bimg.getGraphics(); |
432 g.drawImage(img, 0, 0, null); | |
433 g.dispose(); | |
434 return bimg; | |
435 } | |
436 | |
54 | 437 void createPngBytes(BufferedImage bimg) throws IOException { |
438 pngBytes = getImageBytes(bimg, "png"); | |
25 | 439 } |
54 | 440 |
441 byte[] getBytes(BufferedImage img) throws IOException { | |
25 | 442 byte[] b = getImageBytes(img, "png"); |
443 return b; | |
444 } | |
54 | 445 |
446 byte[] getImageBytes(BufferedImage image, String imageFormat) | |
447 throws IOException { | |
25 | 448 ByteArrayOutputStream bos = new ByteArrayOutputStream(); |
449 BufferedOutputStream os = new BufferedOutputStream(bos); | |
450 image.flush(); | |
451 ImageIO.write(image, imageFormat, os); | |
452 os.flush(); | |
453 os.close(); | |
454 return bos.toByteArray(); | |
455 } | |
456 | |
54 | 457 void sendPngData(Socket sock) throws IOException { |
26 | 458 byte[] dataLength = castIntByte(pngBytes.length); |
459 sock.getOutputStream().write(dataLength); | |
25 | 460 sock.getOutputStream().write(pngBytes); |
461 } | |
54 | 462 |
463 byte[] castIntByte(int len) { | |
26 | 464 byte[] b = new byte[4]; |
54 | 465 b[0] = (byte) ((len >>> 24) & 0xFF); |
466 b[1] = (byte) ((len >>> 16) & 0xFF); | |
467 b[2] = (byte) ((len >>> 8) & 0xFF); | |
468 b[3] = (byte) ((len >>> 0) & 0xFF); | |
26 | 469 return b; |
470 } | |
54 | 471 |
472 BufferedImage createBimg() throws IOException { | |
25 | 473 BufferedImage bimg = ImageIO.read(new ByteArrayInputStream(pngBytes)); |
474 return bimg; | |
475 } | |
65 | 476 /* |
54 | 477 void readPngData() throws IOException { |
25 | 478 pngBytes = new byte[is.available()]; |
479 readFully(pngBytes); | |
480 } | |
65 | 481 */ |
54 | 482 void printFramebufferUpdate() { |
483 | |
18 | 484 System.out.println("messageType=" + messageType); |
54 | 485 System.out.println("rectangles=" + rectangles); |
18 | 486 System.out.println("encoding=" + encoding); |
78 | 487 System.out.println("rectX = "+rectX+": rectY = "+rectY); |
488 System.out.println("rectW = "+rectW+": rectH = "+rectH); | |
54 | 489 switch (encoding) { |
23 | 490 case RfbProto.EncodingRaw: |
54 | 491 System.out.println("rectW * rectH * 4 + 16 =" + rectW * rectH * 4 |
492 + 16); | |
23 | 493 break; |
494 default: | |
495 } | |
18 | 496 } |
65 | 497 |
77 | 498 void readSpeedCheck() throws IOException { |
499 byte[] b = new byte[1]; | |
65 | 500 readFully(b); |
501 } | |
502 | |
77 | 503 void startSpeedCheck() { |
66 | 504 byte[] b = new byte[2]; |
77 | 505 b[0] = (byte) SpeedCheckMillis; |
66 | 506 b[1] = (byte) 0; |
507 startCheckTime = System.currentTimeMillis(); | |
508 System.out.println("startChckTime = "+ startCheckTime); | |
84 | 509 LinkedList<byte[]>bufs = new LinkedList<byte[]>(); |
510 bufs.add(b); | |
511 multicastqueue.put(bufs); | |
65 | 512 } |
513 | |
77 | 514 void endSpeedCheck() { |
65 | 515 long accTime = System.currentTimeMillis(); |
516 long time = accTime - startCheckTime; | |
517 System.out.println("checkMillis: " + time); | |
518 } | |
519 | |
520 void printStatus() { | |
521 System.out.println(); | |
522 } | |
523 | |
524 synchronized void changeStatusFlag() { | |
525 printStatusFlag = true; | |
526 } | |
527 | |
528 void printMills() { | |
529 if(printStatusFlag) { | |
530 | |
531 changeStatusFlag(); | |
532 } else { | |
533 changeStatusFlag(); | |
534 } | |
535 } | |
536 | |
43 | 537 |
71 | 538 void newClient(AcceptThread acceptThread, final Socket newCli, |
54 | 539 final OutputStream os, final InputStream is) throws IOException { |
540 // createBimgFlag = true; | |
541 // rfb.addSockTmp(newCli); | |
542 // addSock(newCli); | |
84 | 543 final Client <LinkedList<byte[]>> c = multicastqueue.newClient(); |
54 | 544 Runnable sender = new Runnable() { |
545 public void run() { | |
80 | 546 |
547 Deflater deflater = new Deflater(); | |
54 | 548 try { |
65 | 549 /** |
550 * initial connection of RFB protocol | |
551 */ | |
54 | 552 sendRfbVersion(os); |
553 readVersionMsg(is); | |
554 sendSecurityType(os); | |
555 readSecType(is); | |
556 sendSecResult(os); | |
557 readClientInit(is); | |
558 sendInitData(os); | |
43 | 559 |
54 | 560 for (;;) { |
84 | 561 LinkedList<byte[]> bufs = c.poll(); |
562 byte[] b = bufs.poll(); | |
80 | 563 if (b[0]==RfbProto.FramebufferUpdate) { |
84 | 564 int encoding = u32(b,12); |
80 | 565 if (encoding==RfbProto.EncodingZlib||encoding==RfbProto.EncodingZRLE) { |
85 | 566 int clen = u32(bufs.poll(),0); |
84 | 567 LinkedList<byte[]> outs = new LinkedList<byte[]>(); |
568 int len = 0, count = 0; | |
569 int len2=0; | |
85 | 570 //int bufSize = bufs.size(); |
571 //int bufCount = 0; | |
572 deflater.reset(); | |
573 do { | |
574 byte[] b1 = bufs.poll(); | |
575 if (bufs.size()==0) { | |
84 | 576 deflater.setInput(b1,0,clen); |
85 | 577 deflater.finish(); |
578 } else | |
84 | 579 deflater.setInput(b1); |
580 int len1=0; | |
581 do { | |
582 byte[] c1 = new byte[INFLATE_BUFSIZE]; | |
583 len2 = len1; | |
584 len1 = deflater.deflate(c1); | |
585 if (len1>0) { | |
586 outs.addLast(c1); | |
587 count ++; | |
588 len += len1; | |
589 } | |
590 } while (len1 > 0); | |
85 | 591 } while(bufs.size()>0); |
80 | 592 byte[] blen = castIntByte(len); |
84 | 593 outs.addFirst(blen); |
594 outs.addFirst(b); | |
595 int i = 0; | |
596 for(byte [] out: outs) { | |
597 if (i++ <count+2-1) | |
598 os.write(out); | |
599 else | |
600 os.write(out,0,len2); | |
601 } | |
80 | 602 } |
84 | 603 } else { |
80 | 604 os.write(b, 0, b.length); |
84 | 605 } |
85 | 606 os.flush(); |
54 | 607 } |
608 } catch (IOException e) { | |
65 | 609 /** |
610 * if socket closed | |
611 */ | |
54 | 612 // cliList.remove(newCli); |
613 } | |
614 | |
615 } | |
616 | |
84 | 617 |
54 | 618 }; |
80 | 619 clients++; |
54 | 620 new Thread(sender).start(); |
621 | |
622 } | |
66 | 623 |
84 | 624 private int u32(byte[] b, int i) { |
625 int ret = 0; | |
626 for(int j = 0;j<4;j++) { | |
627 ret *= 256; | |
628 ret += b[i+j] & 0xff; | |
629 } | |
630 return ret; | |
631 } | |
77 | 632 void speedCheckMillis() { |
66 | 633 |
634 Runnable stdin = new Runnable() { | |
635 public void run() { | |
636 int c; | |
637 try { | |
638 while( (c = System.in.read()) != -1 ) { | |
639 switch(c) { | |
640 case 's': | |
641 break; | |
642 default: | |
77 | 643 startSpeedCheck(); |
66 | 644 break; |
645 } | |
646 } | |
647 }catch(IOException e){ | |
648 System.out.println(e); | |
649 } | |
650 } | |
651 }; | |
652 | |
653 new Thread(stdin).start(); | |
654 } | |
655 | |
54 | 656 } |
66 | 657 |
658 |