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