Mercurial > hg > Applications > TightVNC_orginal
annotate src/main/java/jp/ac/u_ryukyu/treevnc/server/MyRfbProtoProxy.java @ 20:98519d16a8c3
getInitData from ProtocolContext
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Wed, 29 Aug 2012 23:22:14 +0900 |
parents | ea83f4be0cc9 |
children | bfddb801c3aa |
rev | line source |
---|---|
12 | 1 package jp.ac.u_ryukyu.treevnc.server; |
11 | 2 |
3 import static org.junit.Assert.*; | |
4 | |
5 import java.io.IOException; | |
6 import java.net.BindException; | |
7 import java.net.ServerSocket; | |
8 import java.net.Socket; | |
9 import java.nio.ByteBuffer; | |
10 import java.util.Iterator; | |
11 import java.util.LinkedList; | |
12 | |
13 | |
14 import org.junit.Test; | |
15 | |
19 | 16 import com.glavsoft.exceptions.CommonException; |
15 | 17 import com.glavsoft.exceptions.TransportException; |
18 import com.glavsoft.rfb.encoding.EncodingType; | |
20
98519d16a8c3
getInitData from ProtocolContext
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
19 import com.glavsoft.rfb.protocol.Protocol; |
98519d16a8c3
getInitData from ProtocolContext
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
20 import com.glavsoft.rfb.protocol.ProtocolContext; |
15 | 21 import com.glavsoft.transport.Reader; |
16 | 22 import com.glavsoft.transport.Writer; |
11 | 23 |
24 //import myVncProxy.MulticastQueue.Client; | |
25 | |
26 import java.util.concurrent.ExecutorService; | |
27 import java.util.concurrent.atomic.AtomicInteger; | |
28 import java.util.zip.DataFormatException; | |
29 import java.util.zip.Deflater; | |
30 import java.util.zip.Inflater; | |
31 | |
12 | 32 import jp.ac.u_ryukyu.treevnc.MulticastQueue; |
33 | |
11 | 34 public class MyRfbProtoProxy { |
35 final static String versionMsg_3_855 = "RFB 003.855\n"; | |
36 /** | |
37 * CheckMillis is one of new msgType for RFB 3.855. | |
38 */ | |
39 final static byte SpeedCheckMillis = 4; | |
15 | 40 final static int FramebufferUpdate = 0; |
41 final static int CheckDelay = 11; | |
16 | 42 final static int FramebufferUpdateRequest = 3; |
11 | 43 |
44 // Secyrity type of OS X | |
45 final static int SecTypeReqAccess = 32; | |
46 | |
47 // Supported authentication types | |
48 final static int AuthAccess = 32; | |
49 | |
50 private static final int INFLATE_BUFSIZE = 1024 * 100; | |
51 boolean printStatusFlag = false; | |
52 long startCheckTime; | |
19 | 53 |
11 | 54 |
55 private ServerSocket servSock; | |
56 protected int acceptPort; | |
57 // private byte initData[]; | |
20
98519d16a8c3
getInitData from ProtocolContext
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
58 ProtocolContext context; |
11 | 59 private LinkedList<Socket> cliListTmp; |
60 private LinkedList<Socket> cliList; | |
61 boolean createBimgFlag; | |
62 boolean proxyFlag = true; | |
19 | 63 // private Reader is; |
17 | 64 private Writer os; |
11 | 65 ExecutorService executor; |
66 | |
67 byte[] pngBytes; | |
68 | |
69 // private MulticastQueue<LinkedList<ByteBuffer>> multicastqueue = new | |
70 // MostRecentMultiCast<LinkedList<ByteBuffer>>(10); | |
71 private MulticastQueue<LinkedList<ByteBuffer>> multicastqueue = new MulticastQueue<LinkedList<ByteBuffer>>(); | |
72 private int clients = 0; | |
73 private Inflater inflater = new Inflater(); | |
74 private Deflater deflater = new Deflater(); | |
75 // private Thread requestThread; | |
76 private RequestScreenThread rThread; | |
77 private Thread requestThread; | |
78 | |
15 | 79 public MyRfbProtoProxy() { |
16 | 80 rThread = new RequestScreenThread(this); |
81 requestThread = new Thread(rThread); | |
11 | 82 } |
83 | |
19 | 84 public void setStream(Writer _writer) { |
17 | 85 os = _writer; |
15 | 86 } |
11 | 87 |
88 void initServSock(int port) throws IOException { | |
89 servSock = new ServerSocket(port); | |
90 acceptPort = port; | |
91 } | |
92 | |
93 /* | |
94 * default port number is 5999. | |
95 */ | |
96 public void selectPort(int p) { | |
97 if (servSock != null) | |
98 return; | |
99 int port = p; | |
100 while (true) { | |
101 try { | |
102 initServSock(port); | |
103 break; | |
104 } catch (BindException e) { | |
105 port++; | |
106 continue; | |
107 } catch (IOException e) { | |
108 | |
109 } | |
110 } | |
111 System.out.println("accept port = " + port); | |
112 } | |
113 | |
114 int getAcceptPort() { | |
115 return acceptPort; | |
116 } | |
117 | |
118 void setSoTimeout(int num) throws IOException { | |
119 servSock.setSoTimeout(num); | |
120 } | |
121 | |
122 public Socket accept() throws IOException { | |
123 return servSock.accept(); | |
124 } | |
125 | |
126 void addSock(Socket sock) { | |
127 cliList.add(sock); | |
128 } | |
129 | |
130 void addSockTmp(Socket sock) { | |
131 System.out.println("connected " + sock.getInetAddress()); | |
132 cliListTmp.add(sock); | |
133 } | |
134 | |
135 synchronized void changeStatusFlag() { | |
136 printStatusFlag = true; | |
137 } | |
138 | |
139 void printMills() { | |
140 if (printStatusFlag) { | |
141 | |
142 changeStatusFlag(); | |
143 } else { | |
144 changeStatusFlag(); | |
145 } | |
146 } | |
147 | |
148 void requestThreadStart() { | |
149 requestThread.start(); | |
150 } | |
151 | |
152 public synchronized void requestThreadNotify() { | |
153 rThread.reStart(); | |
154 } | |
155 | |
156 /** | |
157 * gzip byte arrays | |
158 * | |
159 * @param deflater | |
160 * @param inputs | |
161 * byte data[] | |
162 * @param inputIndex | |
163 * @param outputs | |
164 * byte data[] | |
165 * @return byte length in last byte array | |
166 * @throws IOException | |
167 */ | |
168 public int zip(Deflater deflater, LinkedList<ByteBuffer> inputs, | |
169 int inputIndex, LinkedList<ByteBuffer> outputs) throws IOException { | |
170 int len = 0; | |
171 ByteBuffer c1 = ByteBuffer.allocate(INFLATE_BUFSIZE); | |
172 while (inputIndex < inputs.size()) { | |
173 ByteBuffer b1 = inputs.get(inputIndex++); | |
174 deflater.setInput(b1.array(), b1.position(), b1.remaining()); | |
175 /** | |
176 * If we finish() stream and reset() it, Deflater start new gzip | |
177 * stream, this makes continuous zlib reader unhappy. if we remove | |
178 * finish(), Deflater.deflate() never flushes its output. The | |
179 * original zlib deflate has flush flag. I'm pretty sure this a kind | |
180 * of bug of Java library. | |
181 */ | |
182 if (inputIndex == inputs.size()) | |
183 deflater.finish(); | |
184 int len1 = 0; | |
185 do { | |
186 len1 = deflater.deflate(c1.array(), c1.position(), | |
187 c1.remaining()); | |
188 if (len1 > 0) { | |
189 len += len1; | |
190 c1.position(c1.position() + len1); | |
191 if (c1.remaining() == 0) { | |
192 c1.flip(); | |
193 outputs.addLast(c1); | |
194 c1 = ByteBuffer.allocate(INFLATE_BUFSIZE); | |
195 } | |
196 } | |
197 } while (len1 > 0 || !deflater.needsInput()); // &&!deflater.finished()); | |
198 } | |
199 if (c1.position() != 0) { | |
200 c1.flip(); | |
201 outputs.addLast(c1); | |
202 } | |
203 deflater.reset(); | |
204 return len; | |
205 } | |
206 | |
207 /** | |
208 * gunzip byte arrays | |
209 * | |
210 * @param inflater | |
211 * @param inputs | |
212 * byte data[] | |
213 * @param outputs | |
214 * byte data[] | |
215 * @return number of total bytes | |
216 * @throws IOException | |
217 */ | |
218 public int unzip(Inflater inflater, LinkedList<ByteBuffer> inputs, | |
219 int inputIndex, LinkedList<ByteBuffer> outputs, int bufSize) | |
220 throws DataFormatException { | |
221 int len = 0; | |
222 ByteBuffer buf = ByteBuffer.allocate(bufSize); | |
223 while (inputIndex < inputs.size()) { | |
224 ByteBuffer input = inputs.get(inputIndex++); | |
225 inflater.setInput(input.array(), input.position(), input.limit()); | |
226 // if (inputIndex==inputs.size()) if inflater/deflater has symmetry, | |
227 // we need this | |
228 // inflater.end(); but this won't work | |
229 do { | |
230 int len0 = inflater.inflate(buf.array(), buf.position(), | |
231 buf.remaining()); | |
232 if (len0 > 0) { | |
233 buf.position(buf.position() + len0); | |
234 len += len0; | |
235 if (buf.remaining() == 0) { | |
236 buf.flip(); | |
237 outputs.addLast(buf); | |
238 buf = ByteBuffer.allocate(bufSize); | |
239 } | |
240 } | |
241 } while (!inflater.needsInput()); | |
242 } | |
243 if (buf.position() != 0) { | |
244 buf.flip(); | |
245 outputs.addLast(buf); | |
246 } | |
247 return len; | |
248 } | |
249 | |
250 float maxMag = 1; | |
251 | |
252 /** | |
253 * send data to clients | |
254 * | |
255 * @param dataLen | |
19 | 256 * @param is |
11 | 257 * @throws IOException |
258 * @throws DataFormatException | |
259 * | |
260 * Zlibed packet is compressed in context dependent way, that | |
261 * is, it have to send from the beginning. But this is | |
262 * impossible. So we have to compress it again for each clients. | |
263 * Separate deflater for each clients is necessary. | |
264 * | |
265 * Java's deflater does not support flush. This means to get the | |
266 * result, we have to finish the compression. Reseting start new | |
267 * compression, but it is not accepted well in zlib continuous | |
268 * reading. So we need new Encoding ZRLEE which reset decoder | |
269 * for each packet. ZRLEE can be invisible from user, but it | |
270 * have to be implemented in the clients. ZRLEE compression is | |
271 * not context dependent, so no recompression is necessary. | |
16 | 272 * @throws TransportException |
11 | 273 */ |
274 | |
19 | 275 public void readSendData(int dataLen, Reader is) throws CommonException { |
11 | 276 LinkedList<ByteBuffer> bufs = new LinkedList<ByteBuffer>(); |
277 ByteBuffer header = ByteBuffer.allocate(16); | |
17 | 278 is.readBytes(header.array(), 0, 16); |
11 | 279 header.limit(16); |
16 | 280 if (header.get(0) == FramebufferUpdate) { |
11 | 281 int encoding = header.getInt(12); |
15 | 282 if (encoding == EncodingType.ZRLE.getId() |
16 | 283 || encoding == EncodingType.ZLIB.getId()) { // ZRLEE is |
284 // already | |
285 // recompressed | |
11 | 286 ByteBuffer len = ByteBuffer.allocate(4); |
17 | 287 is.readBytes(len.array(), 0, 4); |
11 | 288 len.limit(4); |
289 ByteBuffer inputData = ByteBuffer.allocate(dataLen - 20); | |
290 | |
17 | 291 is.readBytes(inputData.array(), 0, inputData.capacity()); |
16 | 292 // System.out.println(dataLen); |
11 | 293 inputData.limit(dataLen - 20); |
294 | |
295 LinkedList<ByteBuffer> inputs = new LinkedList<ByteBuffer>(); | |
296 inputs.add(inputData); | |
297 | |
16 | 298 header.putInt(12, EncodingType.ZRLEE.getId()); // means |
299 // recompress | |
300 // every time | |
11 | 301 // using new Deflecter every time is incompatible with the |
302 // protocol, clients have to be modified. | |
303 Deflater nDeflater = deflater; // new Deflater(); | |
304 LinkedList<ByteBuffer> out = new LinkedList<ByteBuffer>(); | |
19 | 305 int len2 = 0; |
306 try { | |
307 unzip(inflater, inputs, 0, out, INFLATE_BUFSIZE); | |
308 len2 = zip(nDeflater, out, 0, bufs); | |
309 } catch (DataFormatException e) { | |
310 throw new CommonException(e); | |
311 } catch (IOException e) { | |
312 throw new CommonException(e); | |
313 } | |
314 | |
11 | 315 ByteBuffer blen = ByteBuffer.allocate(4); |
316 blen.putInt(len2); | |
317 blen.flip(); | |
318 bufs.addFirst(blen); | |
319 | |
320 bufs.addFirst(header); | |
16 | 321 // if(dataLen<=64000) |
322 multicastqueue.put(bufs); | |
11 | 323 // is.reset(); |
324 | |
325 /* | |
326 * System.out.println("ZRLE = "+dataLen); | |
327 * System.out.println("ZRLEE = "+(len2+20)); float mag = | |
328 * (float)dataLen / (float)(len2 + 20); | |
329 * System.out.println("ZRLE / ZRLEE = "+ mag); if(mag > maxMag) | |
330 * maxMag = mag; System.out.println("maxMag = "+maxMag); | |
331 */ | |
332 return; | |
333 } | |
334 bufs.add(header); | |
335 if (dataLen > 16) { | |
336 ByteBuffer b = ByteBuffer.allocate(dataLen - 16); | |
17 | 337 is.readBytes(b.array(), 0, dataLen - 16); |
11 | 338 b.limit(dataLen - 16); |
339 bufs.add(b); | |
340 } | |
341 multicastqueue.put(bufs); | |
342 // is.reset(); | |
343 return; | |
344 } | |
17 | 345 is.reset(); |
11 | 346 |
347 // It may be compressed. We can inflate here to avoid repeating clients | |
348 // decompressing here, | |
349 // but it may generate too many large data. It is better to do it in | |
350 // each client. | |
351 // But we have do inflation for all input data, so we have to do it | |
352 // here. | |
353 } | |
354 | |
355 public void newClient(AcceptThread acceptThread, final Socket newCli, | |
17 | 356 final Writer os, final Reader is) throws IOException { |
11 | 357 // createBimgFlag = true; |
358 // rfb.addSockTmp(newCli); | |
359 // addSock(newCli); | |
360 final int myId = clients; | |
19 | 361 final MulticastQueue.Client<LinkedList<ByteBuffer>> c = multicastqueue.newClient(); |
11 | 362 final AtomicInteger writerRunning = new AtomicInteger(); |
363 writerRunning.set(1); | |
364 /** | |
365 * Timeout thread. If a client is suspended, it has top of queue | |
366 * indefinitely, which caused memory overflow. After the timeout, we | |
367 * poll the queue and discard it. Start long wait if writer is running. | |
368 */ | |
369 final Runnable timer = new Runnable() { | |
370 public void run() { | |
371 int count = 0; | |
372 for (;;) { | |
373 long timeout = 50000 / 8; | |
374 try { | |
375 synchronized (this) { | |
376 int state, flag; | |
377 writerRunning.set(0); | |
378 wait(timeout); | |
379 flag = 0; | |
380 while ((state = writerRunning.get()) == 0) { | |
381 c.poll(); // discard, should be timeout | |
382 count++; | |
383 if (flag == 0) { | |
384 System.out.println("Discarding " + myId | |
385 + " count=" + count); | |
386 flag = 1; | |
387 } | |
388 wait(10); // if this is too short, writer cannot | |
389 // take the poll, if this is too | |
390 // long, memory will overflow... | |
391 } | |
392 if (flag == 1) | |
393 System.out.println("Resuming " + myId | |
394 + " count=" + count); | |
395 if (state != 1) { | |
396 System.out.println("Client died " + myId); | |
397 break; | |
398 } | |
399 } | |
400 } catch (InterruptedException e) { | |
401 } | |
402 } | |
403 } | |
404 }; | |
405 new Thread(timer).start(); | |
406 /** | |
407 * discard all incoming from clients | |
408 */ | |
409 final Runnable reader = new Runnable() { | |
410 public void run() { | |
411 byte b[] = new byte[4096]; | |
412 for (;;) { | |
413 try { | |
17 | 414 int c = is.readByte(b); |
11 | 415 if (c <= 0) |
416 throw new IOException(); | |
417 // System.out.println("client read "+c); | |
418 } catch (IOException e) { | |
419 try { | |
420 writerRunning.set(2); | |
421 os.close(); | |
422 is.close(); | |
423 } catch (IOException e1) { | |
17 | 424 } catch (TransportException e1) { |
425 e1.printStackTrace(); | |
11 | 426 } |
427 return; | |
17 | 428 } catch (TransportException e) { |
429 e.printStackTrace(); | |
11 | 430 } |
431 } | |
432 } | |
433 }; | |
434 /** | |
435 * send packets to a client | |
436 */ | |
437 Runnable sender = new Runnable() { | |
438 public void run() { | |
439 writerRunning.set(1); | |
440 try { | |
441 requestThreadNotify(); | |
442 // rThread.checkDelay(); | |
443 | |
444 /** | |
445 * initial connection of RFB protocol | |
446 */ | |
447 sendRfbVersion(os); | |
448 // readVersionMsg(is); | |
19 | 449 readVersionMsg(is, os); |
11 | 450 sendSecurityType(os); |
451 readSecType(is); | |
452 sendSecResult(os); | |
453 readClientInit(is); | |
454 sendInitData(os); | |
455 new Thread(reader).start(); // discard incoming packet here | |
456 // after. | |
457 // writeFramebufferUpdateRequest(0,0, framebufferWidth, | |
458 // framebufferHeight, false ); | |
459 for (;;) { | |
460 LinkedList<ByteBuffer> bufs = c.poll(); | |
461 int inputIndex = 0; | |
462 ByteBuffer header = bufs.get(inputIndex); | |
463 if (header == null) | |
464 continue; | |
15 | 465 else if (header.get(0) == CheckDelay) { |
11 | 466 writeToClient(os, bufs, inputIndex); |
467 continue; | |
15 | 468 } else if (header.get(0) == FramebufferUpdate) { |
11 | 469 // System.out.println("client "+ myId); |
470 } | |
471 /* | |
16 | 472 * if(i%20==0){ sendDataCheckDelay(); } i++; |
473 */ | |
11 | 474 writeToClient(os, bufs, inputIndex); |
475 writerRunning.set(1); // yes my client is awaking. | |
476 } | |
477 } catch (IOException e) { | |
478 try { | |
479 writerRunning.set(2); | |
480 os.close(); | |
481 } catch (IOException e1) { | |
482 } | |
483 /* if socket closed cliList.remove(newCli); */ | |
17 | 484 } catch (TransportException e) { |
485 e.printStackTrace(); | |
11 | 486 } |
487 } | |
488 | |
17 | 489 public void writeToClient(final Writer os, |
11 | 490 LinkedList<ByteBuffer> bufs, int inputIndex) |
17 | 491 throws TransportException { |
11 | 492 while (inputIndex < bufs.size()) { |
493 ByteBuffer b = bufs.get(inputIndex++); | |
494 os.write(b.array(), b.position(), b.limit()); | |
495 } | |
496 os.flush(); | |
497 } | |
498 }; | |
499 clients++; | |
500 new Thread(sender).start(); | |
501 | |
502 } | |
503 | |
504 public void dump32(LinkedList<ByteBuffer> bufs) { | |
505 int len = 0; | |
506 for (ByteBuffer b : bufs) | |
507 len += b.remaining(); | |
508 ByteBuffer top = bufs.getFirst(); | |
509 ByteBuffer end = bufs.getLast(); | |
510 System.err.println("length: " + len); | |
511 System.err.print("head 0: "); | |
512 for (int i = 0; i < 16 && i < top.remaining(); i++) { | |
513 System.err.print(" " + top.get(i)); | |
514 } | |
515 System.err.print("tail 0: "); | |
516 for (int i = 0; i < 16 && i < end.remaining(); i++) { | |
517 System.err.print(" " + end.get(i)); | |
518 } | |
519 System.err.println(); | |
520 } | |
521 | |
522 @Test | |
523 public void test1() { | |
524 try { | |
525 LinkedList<ByteBuffer> in = new LinkedList<ByteBuffer>(); | |
526 LinkedList<ByteBuffer> out = new LinkedList<ByteBuffer>(); | |
527 LinkedList<ByteBuffer> out2 = new LinkedList<ByteBuffer>(); | |
528 // if (false) { | |
529 // for(int i=0;i<10;i++) { | |
530 // in.add(ByteBuffer.wrap("test1".getBytes())); | |
531 // in.add(ByteBuffer.wrap("test2".getBytes())); | |
532 // in.add(ByteBuffer.wrap("test3".getBytes())); | |
533 // in.add(ByteBuffer.wrap("test44".getBytes())); | |
534 // } | |
535 // } else | |
536 { | |
537 String t = ""; | |
538 for (int i = 0; i < 10; i++) { | |
539 t += "test1"; | |
540 t += "test2"; | |
541 t += "test3"; | |
542 t += "test44"; | |
543 } | |
544 in.add(ByteBuffer.wrap(t.getBytes())); | |
545 } | |
546 | |
547 LinkedList<ByteBuffer> in1 = clone(in); | |
548 | |
549 Deflater deflater = new Deflater(); | |
550 zip(deflater, in, 0, out); | |
551 // LinkedList<ByteBuffer> out3 = clone(out); zipped result is depend | |
552 // on deflator's state | |
553 unzip(inflater, out, 0, out2, INFLATE_BUFSIZE); | |
554 // inflater.reset(); | |
555 equalByteBuffers(in1, out2); | |
556 LinkedList<ByteBuffer> out4 = new LinkedList<ByteBuffer>(); | |
557 deflater = new Deflater(); | |
558 zip(deflater, out2, 0, out4); | |
559 LinkedList<ByteBuffer> out5 = new LinkedList<ByteBuffer>(); | |
560 unzip(inflater, out4, 0, out5, INFLATE_BUFSIZE); | |
561 int len = equalByteBuffers(in1, out5); | |
562 | |
563 System.out.println("Test Ok. " + len); | |
564 } catch (Exception e) { | |
565 assertEquals(0, 1); | |
566 } | |
567 } | |
568 | |
569 private LinkedList<ByteBuffer> clone(LinkedList<ByteBuffer> in) { | |
570 LinkedList<ByteBuffer> copy = new LinkedList<ByteBuffer>(); | |
571 for (ByteBuffer b : in) { | |
572 ByteBuffer c = b.duplicate(); | |
573 copy.add(c); | |
574 } | |
575 return copy; | |
576 } | |
577 | |
578 public int equalByteBuffers(LinkedList<ByteBuffer> in, | |
579 LinkedList<ByteBuffer> out2) { | |
580 int len = 0; | |
581 Iterable<Byte> i = byteBufferIterator(in); | |
582 Iterator<Byte> o = byteBufferIterator(out2).iterator(); | |
583 | |
584 for (int b : i) { | |
585 len++; | |
586 if (o.hasNext()) { | |
587 int c = o.next(); | |
588 assertEquals(b, c); | |
589 } else | |
590 assertEquals(0, 1); | |
591 } | |
592 if (o.hasNext()) | |
593 assertEquals(0, 1); | |
594 // System.out.println(); | |
595 return len; | |
596 } | |
597 | |
598 private Iterable<Byte> byteBufferIterator(final LinkedList<ByteBuffer> in) { | |
599 return new Iterable<Byte>() { | |
600 public Iterator<Byte> iterator() { | |
601 return new Iterator<Byte>() { | |
602 int bytes = 0; | |
603 int buffers = 0; | |
604 | |
605 public boolean hasNext() { | |
606 for (;;) { | |
607 if (buffers >= in.size()) | |
608 return false; | |
609 ByteBuffer b = in.get(buffers); | |
610 if (!(bytes < b.remaining())) { | |
611 buffers++; | |
612 bytes = 0; | |
613 } else | |
614 return true; | |
615 } | |
616 } | |
617 | |
618 public Byte next() { | |
619 ByteBuffer bf = in.get(buffers); | |
620 byte b = bf.get(bytes++); | |
621 if (bf.remaining() <= bytes) { | |
622 buffers++; | |
623 bytes = 0; | |
624 } | |
625 // System.out.print(b); | |
626 return b; | |
627 } | |
628 | |
629 public void remove() { | |
630 } | |
631 }; | |
632 } | |
633 }; | |
634 } | |
16 | 635 |
17 | 636 void sendRfbVersion(Writer writer) throws IOException, TransportException { |
15 | 637 // os.write(versionMsg_3_8.getBytes()); |
17 | 638 writer.write(versionMsg_3_855.getBytes()); |
15 | 639 } |
16 | 640 |
17 | 641 int readVersionMsg(Reader reader, Writer writer) throws IOException, TransportException { |
11 | 642 |
15 | 643 byte[] b = new byte[12]; |
644 | |
17 | 645 reader.readBytes(b); |
15 | 646 |
647 if ((b[0] != 'R') || (b[1] != 'F') || (b[2] != 'B') || (b[3] != ' ') | |
648 || (b[4] < '0') || (b[4] > '9') || (b[5] < '0') || (b[5] > '9') | |
649 || (b[6] < '0') || (b[6] > '9') || (b[7] != '.') | |
650 || (b[8] < '0') || (b[8] > '9') || (b[9] < '0') || (b[9] > '9') | |
651 || (b[10] < '0') || (b[10] > '9') || (b[11] != '\n')) { | |
652 throw new IOException("this is not an RFB server"); | |
653 } | |
654 | |
655 int rfbMajor = (b[4] - '0') * 100 + (b[5] - '0') * 10 + (b[6] - '0'); | |
656 int rfbMinor = (b[8] - '0') * 100 + (b[9] - '0') * 10 + (b[10] - '0'); | |
657 | |
658 if (rfbMajor < 3) { | |
659 throw new IOException( | |
660 "RFB server does not support protocol version 3"); | |
661 } | |
662 | |
663 if (rfbMinor == 855) { | |
17 | 664 sendProxyFlag(writer); |
15 | 665 if (proxyFlag) |
17 | 666 sendPortNumber(writer); |
15 | 667 } |
668 return rfbMinor; | |
669 } | |
16 | 670 |
17 | 671 void sendProxyFlag(Writer writer) throws TransportException { |
15 | 672 if (proxyFlag) |
17 | 673 writer.writeInt(1); |
15 | 674 else |
17 | 675 writer.writeInt(0); |
15 | 676 } |
16 | 677 |
17 | 678 void sendPortNumber(Writer writer) throws TransportException { |
15 | 679 byte[] b = new byte[4]; |
17 | 680 //b = castIntByte(getHost.getPort()); |
681 b = castIntByte(9999); | |
682 writer.write(b); | |
15 | 683 } |
684 | |
17 | 685 void sendSecurityType(Writer os) throws TransportException { |
15 | 686 // number-of-security-types |
17 | 687 os.writeInt(1); |
15 | 688 // security-types |
689 // 1:None | |
17 | 690 os.writeInt(1); |
15 | 691 |
692 /* | |
693 * os.write(4); os.write(30); os.write(31); os.write(32); os.write(35); | |
694 * os.flush(); | |
695 */ | |
696 } | |
697 | |
17 | 698 void readSecType(Reader reader) throws TransportException { |
15 | 699 byte[] b = new byte[1]; |
17 | 700 reader.read(b); |
15 | 701 } |
702 | |
17 | 703 void readSecType(Reader is, Writer os) throws TransportException { |
15 | 704 byte[] b = new byte[1]; |
17 | 705 is.readBytes(b); |
15 | 706 |
707 int count = 260; | |
708 int[] data = { 0, 2, 0, -128, -1, -1, -1, -1, -1, -1, -1, -1, -55, 15, | |
709 -38, -94, 33, 104, -62, 52, -60, -58, 98, -117, -128, -36, 28, | |
710 -47, 41, 2, 78, 8, -118, 103, -52, 116, 2, 11, -66, -90, 59, | |
711 19, -101, 34, 81, 74, 8, 121, -114, 52, 4, -35, -17, -107, 25, | |
712 -77, -51, 58, 67, 27, 48, 43, 10, 109, -14, 95, 20, 55, 79, | |
713 -31, 53, 109, 109, 81, -62, 69, -28, -123, -75, 118, 98, 94, | |
714 126, -58, -12, 76, 66, -23, -90, 55, -19, 107, 11, -1, 92, -74, | |
715 -12, 6, -73, -19, -18, 56, 107, -5, 90, -119, -97, -91, -82, | |
716 -97, 36, 17, 124, 75, 31, -26, 73, 40, 102, 81, -20, -26, 83, | |
717 -127, -1, -1, -1, -1, -1, -1, -1, -1, -111, 73, -29, 30, 57, | |
718 -67, -75, -77, -49, -50, -99, -76, -80, -80, 14, 65, 57, -105, | |
719 -103, -54, -102, 3, 39, -44, 39, 35, 118, -84, -64, 37, -117, | |
720 -21, 89, -31, -68, 70, 5, 122, -92, -119, 9, 121, 63, -112, | |
721 -60, 122, -46, -69, -36, 92, -103, -92, 74, 92, -73, 87, 120, | |
722 -8, 116, -47, 111, 20, -41, 110, 122, -3, -94, 14, 42, -51, | |
723 -59, 48, -54, -125, 117, 60, 77, -52, -31, 98, 32, -2, -102, | |
724 -15, -29, 58, -14, -106, -116, -32, -86, 50, -32, -16, -3, | |
725 -123, 87, 88, -118, 10, 120, -107, -37, 125, -110, 59, 87, 93, | |
726 -24, 124, -99, 18, 78, -13, -49, -34, -24, -27, 1, 114, -67, | |
727 -98, -56, -3, 85, -67, -126, 77 }; | |
728 for (int i = 0; i < count; i++) { | |
729 os.write((byte) data[i]); | |
730 os.flush(); | |
731 } | |
732 | |
733 byte[] c = new byte[256]; | |
17 | 734 is.readBytes(c); |
15 | 735 |
736 System.out.println(new String(c)); | |
737 | |
738 } | |
739 | |
17 | 740 void sendSecResult(Writer os) throws TransportException { |
15 | 741 byte[] b = castIntByte(0); |
742 os.write(b); | |
743 } | |
16 | 744 |
15 | 745 byte[] castIntByte(int len) { |
746 byte[] b = new byte[4]; | |
747 b[0] = (byte) ((len >>> 24) & 0xFF); | |
748 b[1] = (byte) ((len >>> 16) & 0xFF); | |
749 b[2] = (byte) ((len >>> 8) & 0xFF); | |
750 b[3] = (byte) ((len >>> 0) & 0xFF); | |
751 return b; | |
752 } | |
753 | |
17 | 754 void readClientInit(Reader in) throws TransportException { |
15 | 755 byte[] b = new byte[0]; |
17 | 756 in.readBytes(b); |
15 | 757 } |
758 | |
17 | 759 void sendInitData(Writer os) throws TransportException { |
20
98519d16a8c3
getInitData from ProtocolContext
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
760 os.write(context.getInitData()); |
15 | 761 } |
16 | 762 |
19 | 763 public void writeFramebufferUpdateRequest(int x, int y, int w, int h, |
17 | 764 boolean incremental) throws TransportException { |
16 | 765 byte[] b = new byte[10]; |
766 | |
767 b[0] = (byte) FramebufferUpdateRequest; | |
768 b[1] = (byte) (incremental ? 1 : 0); | |
769 b[2] = (byte) ((x >> 8) & 0xff); | |
770 b[3] = (byte) (x & 0xff); | |
771 b[4] = (byte) ((y >> 8) & 0xff); | |
772 b[5] = (byte) (y & 0xff); | |
773 b[6] = (byte) ((w >> 8) & 0xff); | |
774 b[7] = (byte) (w & 0xff); | |
775 b[8] = (byte) ((h >> 8) & 0xff); | |
776 b[9] = (byte) (h & 0xff); | |
777 | |
17 | 778 os.write(b); |
16 | 779 } |
20
98519d16a8c3
getInitData from ProtocolContext
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
780 |
98519d16a8c3
getInitData from ProtocolContext
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
781 public void setProtocolContext(Protocol workingProtocol) { |
98519d16a8c3
getInitData from ProtocolContext
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
782 context = workingProtocol; |
98519d16a8c3
getInitData from ProtocolContext
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
783 } |
18 | 784 |
11 | 785 } |