Mercurial > hg > Members > nobuyasu > tightVNCProxy
comparison src/myVncProxy/MyRfbProto.java @ 90:462bca4c8cec
ByteBuffer
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Wed, 03 Aug 2011 10:30:45 +0900 |
parents | 9b3b1e3e7db5 |
children | 4116c19cd76e |
comparison
equal
deleted
inserted
replaced
89:43822a70978c | 90:462bca4c8cec |
---|---|
13 import java.io.InputStream; | 13 import java.io.InputStream; |
14 import java.io.InputStreamReader; | 14 import java.io.InputStreamReader; |
15 import java.net.BindException; | 15 import java.net.BindException; |
16 import java.net.ServerSocket; | 16 import java.net.ServerSocket; |
17 import java.net.Socket; | 17 import java.net.Socket; |
18 import java.nio.ByteBuffer; | |
18 import java.util.LinkedList; | 19 import java.util.LinkedList; |
19 | 20 |
20 import javax.imageio.ImageIO; | 21 import javax.imageio.ImageIO; |
21 | 22 |
22 import org.junit.Test; | 23 import org.junit.Test; |
34 class MyRfbProto extends RfbProto { | 35 class MyRfbProto extends RfbProto { |
35 final static String versionMsg_3_998 = "RFB 003.998\n"; | 36 final static String versionMsg_3_998 = "RFB 003.998\n"; |
36 /** | 37 /** |
37 * CheckMillis is one of new msgType for RFB 3.998. | 38 * CheckMillis is one of new msgType for RFB 3.998. |
38 */ | 39 */ |
39 final static int SpeedCheckMillis = 4; | 40 final static byte SpeedCheckMillis = 4; |
40 private static final int INFLATE_BUFSIZE = 1024*100; | 41 private static final int INFLATE_BUFSIZE = 1024*100; |
41 boolean printStatusFlag = false; | 42 boolean printStatusFlag = false; |
42 long startCheckTime; | 43 long startCheckTime; |
43 | 44 |
44 private int messageType; | 45 private int messageType; |
60 | 61 |
61 ExecutorService executor; | 62 ExecutorService executor; |
62 | 63 |
63 byte[] pngBytes; | 64 byte[] pngBytes; |
64 | 65 |
65 private MulticastQueue<LinkedList<byte[]>> multicastqueue = new MostRecentMultiCast<LinkedList<byte[]>>(10); | 66 private MulticastQueue<LinkedList<ByteBuffer>> multicastqueue = new MostRecentMultiCast<LinkedList<ByteBuffer>>(10); |
66 private int clients = 0; | 67 private int clients = 0; |
67 private Inflater inflater = new Inflater(); | 68 private Inflater inflater = new Inflater(); |
68 | 69 |
69 public | 70 public |
70 MyRfbProto() throws IOException { | 71 MyRfbProto() throws IOException { |
462 byte[] b = new byte[1]; | 463 byte[] b = new byte[1]; |
463 readFully(b); | 464 readFully(b); |
464 } | 465 } |
465 | 466 |
466 void startSpeedCheck() { | 467 void startSpeedCheck() { |
467 byte[] b = new byte[2]; | 468 ByteBuffer b = ByteBuffer.allocate(10); |
468 b[0] = (byte) SpeedCheckMillis; | 469 b.put((byte)SpeedCheckMillis); |
469 b[1] = (byte) 0; | 470 b.flip(); |
470 startCheckTime = System.currentTimeMillis(); | 471 startCheckTime = System.currentTimeMillis(); |
471 System.out.println("startChckTime = "+ startCheckTime); | 472 System.out.println("startChckTime = "+ startCheckTime); |
472 LinkedList<byte[]>bufs = new LinkedList<byte[]>(); | 473 LinkedList<ByteBuffer>bufs = new LinkedList<ByteBuffer>(); |
473 bufs.add(b); | 474 bufs.add(b); |
474 multicastqueue.put(bufs); | 475 multicastqueue.put(bufs); |
475 } | 476 } |
476 | 477 |
477 void endSpeedCheck() { | 478 void endSpeedCheck() { |
530 * byte len[4] total byte length | 531 * byte len[4] total byte length |
531 * byte data[] | 532 * byte data[] |
532 * @return byte length in last byte array | 533 * @return byte length in last byte array |
533 * @throws IOException | 534 * @throws IOException |
534 */ | 535 */ |
535 public int zip(Deflater deflater,LinkedList<byte[]> inputs, LinkedList<byte[]> outputs) throws IOException { | 536 public int zip(Deflater deflater,LinkedList<ByteBuffer> inputs, LinkedList<ByteBuffer> outputs) throws IOException { |
536 int clen = u32(inputs.poll(),0); | 537 int len1=0,len = 0; |
537 int len = 0, count = 0; | |
538 int len2=0; | |
539 deflater.reset(); | 538 deflater.reset(); |
540 do { | 539 do { |
541 byte[] b1 = inputs.poll(); | 540 ByteBuffer b1 = inputs.poll(); |
541 deflater.setInput(b1.array(),b1.position(),b1.limit()); | |
542 if (inputs.size()==0) { | 542 if (inputs.size()==0) { |
543 deflater.setInput(b1,0,clen); | |
544 deflater.finish(); | 543 deflater.finish(); |
545 } else { | 544 } |
546 deflater.setInput(b1); | |
547 clen -= b1.length; | |
548 } | |
549 int len1=0; | |
550 do { | 545 do { |
551 byte[] c1 = new byte[INFLATE_BUFSIZE]; | 546 ByteBuffer c1 = ByteBuffer.allocate(INFLATE_BUFSIZE); |
552 len2 = len1; | 547 len1 = deflater.deflate(c1.array(),c1.position(),c1.capacity()); |
553 len1 = deflater.deflate(c1); | 548 c1.limit(len1); |
554 if (len1>0) { | 549 if (len1>0) { |
555 outputs.addLast(c1); | 550 outputs.addLast(c1); |
556 count ++; | |
557 len += len1; | 551 len += len1; |
558 } | 552 } |
559 } while (len1 > 0); | 553 } while (len1 > 0); |
560 } while(inputs.size()>0); | 554 } while(inputs.size()>0); |
561 byte[] blen = castIntByte(len); | 555 ByteBuffer blen = ByteBuffer.wrap(castIntByte(len)); |
562 outputs.addFirst(blen); | 556 outputs.addFirst(blen); |
563 return len2; | 557 return len; |
564 } | 558 } |
565 | 559 |
566 /** | 560 /** |
567 * gunzip byte arrays | 561 * gunzip byte arrays |
568 * @param inflater | 562 * @param inflater |
572 * @param outputs | 566 * @param outputs |
573 * byte len[4] total byte length | 567 * byte len[4] total byte length |
574 * byte data[] | 568 * byte data[] |
575 * @throws IOException | 569 * @throws IOException |
576 */ | 570 */ |
577 public void unzip(Inflater inflater, LinkedList<byte[]> inputs, LinkedList<byte[]> outputs) | 571 public int unzip(Inflater inflater, LinkedList<ByteBuffer> inputs, LinkedList<ByteBuffer> outputs) |
578 throws DataFormatException { | 572 throws DataFormatException { |
579 int len=0,len0; | 573 int len=0,len0; |
580 inputs.poll(); | 574 do { |
581 for(byte [] input:inputs) { | 575 ByteBuffer input = inputs.poll(); |
582 inflater.setInput(input); | 576 inflater.setInput(input.array(),0,input.limit()); |
583 do { | 577 do { |
584 byte buf[] = new byte[INFLATE_BUFSIZE]; | 578 ByteBuffer buf = ByteBuffer.allocate(INFLATE_BUFSIZE); |
585 len0 = inflater.inflate(buf); | 579 len0 = inflater.inflate(buf.array(),0,buf.capacity()); |
580 buf.limit(len0); | |
586 len += len0; | 581 len += len0; |
587 outputs.addLast(buf); | 582 outputs.addLast(buf); |
588 } while (len0 ==INFLATE_BUFSIZE); | 583 } while (len0 ==INFLATE_BUFSIZE); |
589 } | 584 } while (!inputs.isEmpty()); |
590 byte [] blen = castIntByte(len); | 585 return len; |
591 outputs.addFirst(blen); | |
592 } | 586 } |
593 | 587 |
594 void readSendData(int dataLen) throws IOException, DataFormatException { | 588 void readSendData(int dataLen) throws IOException, DataFormatException { |
595 LinkedList<byte[]>bufs = new LinkedList<byte[]>(); | 589 LinkedList<ByteBuffer>bufs = new LinkedList<ByteBuffer>(); |
596 byte header[] = new byte[16]; | 590 ByteBuffer header = ByteBuffer.allocate(16); |
597 readFully(header,0,16); | 591 readFully(header.array(),0,16); |
598 if (header[0]==RfbProto.FramebufferUpdate) { | 592 header.limit(16); |
599 int encoding = u32(header,12); | 593 if (header.get(0)==RfbProto.FramebufferUpdate) { |
594 int encoding = header.getInt(12); | |
600 if (encoding==RfbProto.EncodingZlib||encoding==RfbProto.EncodingZRLE) { | 595 if (encoding==RfbProto.EncodingZlib||encoding==RfbProto.EncodingZRLE) { |
601 byte[] len = new byte[4]; | 596 ByteBuffer len = ByteBuffer.allocate(4); |
602 readFully(len,0,4); | 597 readFully(len.array(),0,4); len.limit(4); |
603 byte inputData[] = new byte[dataLen-20]; | 598 ByteBuffer inputData = ByteBuffer.allocate(dataLen-20); |
604 readFully(inputData); | 599 readFully(inputData.array(),0,inputData.capacity()); inputData.limit(dataLen-20); |
605 LinkedList<byte[]>inputs = new LinkedList<byte[]>(); | 600 LinkedList<ByteBuffer>inputs = new LinkedList<ByteBuffer>(); |
606 inputs.add(len); | |
607 inputs.add(inputData); | 601 inputs.add(inputData); |
608 unzip(inflater, inputs, bufs); | 602 unzip(inflater, inputs, bufs); |
609 bufs.addFirst(header); | 603 bufs.addFirst(header); |
610 multicastqueue.put(bufs); | 604 multicastqueue.put(bufs); |
611 is.reset(); | 605 is.reset(); |
612 return ; | 606 return ; |
613 } | 607 } |
614 } | 608 } |
615 bufs.add(header); | 609 bufs.add(header); |
616 if (dataLen>16) { | 610 if (dataLen>16) { |
617 byte b[] = new byte[dataLen-16]; | 611 ByteBuffer b = ByteBuffer.allocate(dataLen-16); |
618 readFully(b); | 612 readFully(b.array(),0,dataLen-16); b.limit(dataLen-16); |
619 bufs.add(b); | 613 bufs.add(b); |
620 } | 614 } |
621 multicastqueue.put(bufs); | 615 multicastqueue.put(bufs); |
622 is.reset(); | 616 is.reset(); |
623 | 617 |
629 void newClient(AcceptThread acceptThread, final Socket newCli, | 623 void newClient(AcceptThread acceptThread, final Socket newCli, |
630 final OutputStream os, final InputStream is) throws IOException { | 624 final OutputStream os, final InputStream is) throws IOException { |
631 // createBimgFlag = true; | 625 // createBimgFlag = true; |
632 // rfb.addSockTmp(newCli); | 626 // rfb.addSockTmp(newCli); |
633 // addSock(newCli); | 627 // addSock(newCli); |
634 final Client <LinkedList<byte[]>> c = multicastqueue.newClient(); | 628 final Client <LinkedList<ByteBuffer>> c = multicastqueue.newClient(); |
635 Runnable sender = new Runnable() { | 629 Runnable sender = new Runnable() { |
636 public void run() { | 630 public void run() { |
637 | 631 |
638 Deflater deflater = new Deflater(); | 632 Deflater deflater = new Deflater(); |
639 try { | 633 try { |
647 sendSecResult(os); | 641 sendSecResult(os); |
648 readClientInit(is); | 642 readClientInit(is); |
649 sendInitData(os); | 643 sendInitData(os); |
650 | 644 |
651 for (;;) { | 645 for (;;) { |
652 LinkedList<byte[]> bufs = c.poll(); | 646 LinkedList<ByteBuffer> bufs = c.poll(); |
653 byte[] header = bufs.poll(); | 647 ByteBuffer header = bufs.poll(); |
654 if (header[0]==RfbProto.FramebufferUpdate) { | 648 if (header.get(0)==RfbProto.FramebufferUpdate) { |
655 int encoding = u32(header,12); | 649 int encoding = header.getInt(12); |
656 if (encoding==RfbProto.EncodingZlib||encoding==RfbProto.EncodingZRLE) { | 650 if (encoding==RfbProto.EncodingZlib||encoding==RfbProto.EncodingZRLE) { |
657 LinkedList<byte[]> outs = new LinkedList<byte[]>(); | 651 LinkedList<ByteBuffer> outs = new LinkedList<ByteBuffer>(); |
658 int len2 = zip(deflater, bufs, outs); | 652 int len2 = zip(deflater, bufs, outs); |
653 ByteBuffer blen = ByteBuffer.allocate(4); blen.putInt(len2); blen.flip(); | |
654 outs.addFirst(blen); | |
659 outs.addFirst(header); | 655 outs.addFirst(header); |
660 while(!outs.isEmpty()) { | 656 while(!outs.isEmpty()) { |
661 byte [] out= outs.poll(); | 657 ByteBuffer out= outs.poll(); |
662 if (outs.isEmpty()) | 658 os.write(out.array(),out.position(),out.limit()); |
663 os.write(out,0,len2); | |
664 else | |
665 os.write(out); | |
666 } | 659 } |
667 } | 660 } |
668 os.flush(); | 661 os.flush(); |
669 return; | 662 return; |
670 } | 663 } |
671 os.write(header); | 664 os.write(header.array(),header.position(),header.limit()); |
672 for(byte [] b : bufs) { | 665 for(ByteBuffer b : bufs) { |
673 os.write(b, 0, b.length); | 666 os.write(b.array(), b.position(), b.limit()); |
674 } | 667 } |
675 os.flush(); | 668 os.flush(); |
676 } | 669 } |
677 } catch (IOException e) { | 670 } catch (IOException e) { |
678 /* if socket closed cliList.remove(newCli); */ | 671 /* if socket closed cliList.remove(newCli); */ |
682 clients++; | 675 clients++; |
683 new Thread(sender).start(); | 676 new Thread(sender).start(); |
684 | 677 |
685 } | 678 } |
686 | 679 |
687 private int u32(byte[] b, int i) { | |
688 int ret = 0; | |
689 for(int j = 0;j<4;j++) { | |
690 ret *= 256; | |
691 ret += b[i+j] & 0xff; | |
692 } | |
693 return ret; | |
694 } | |
695 | 680 |
696 | 681 |
697 @Test | 682 @Test |
698 public void test1() { | 683 public void test1() { |
699 try { | 684 try { |
700 LinkedList<byte[]> in = new LinkedList<byte[]>(); | 685 LinkedList<ByteBuffer> in = new LinkedList<ByteBuffer>(); |
701 LinkedList<byte[]> out = new LinkedList<byte[]>(); | 686 LinkedList<ByteBuffer> out = new LinkedList<ByteBuffer>(); |
702 LinkedList<byte[]> out2 = new LinkedList<byte[]>(); | 687 LinkedList<ByteBuffer> out2 = new LinkedList<ByteBuffer>(); |
703 for(int i=0;i<10;i++) { | 688 for(int i=0;i<10;i++) { |
704 in.add("test1".getBytes()); | 689 in.add(ByteBuffer.wrap("test1".getBytes())); |
705 in.add("test1".getBytes()); | 690 in.add(ByteBuffer.wrap("test2".getBytes())); |
706 in.add("test1".getBytes()); | 691 in.add(ByteBuffer.wrap("test3".getBytes())); |
707 in.add("test1".getBytes()); | 692 in.add(ByteBuffer.wrap("test4".getBytes())); |
708 } | 693 } |
709 int len = 0; | 694 |
710 for(byte[] b: in) len += b.length; | |
711 in.addFirst(castIntByte(len)); | |
712 | |
713 Deflater deflater = new Deflater(); | 695 Deflater deflater = new Deflater(); |
714 zip(deflater, in,out); | 696 zip(deflater, in,out); |
715 unzip(inflater, out, out2); | 697 unzip(inflater, out, out2); |
716 for(byte[] b:out) { | 698 for(ByteBuffer b:out) { |
717 byte []c = out2.poll(); | 699 ByteBuffer c = out2.poll(); |
718 assertEquals(b,c); | 700 assertEquals(b,c); |
719 } | 701 } |
720 System.out.println("Test Ok."); | 702 System.out.println("Test Ok."); |
721 } catch (Exception e) { | 703 } catch (Exception e) { |
722 assertEquals(0,1); | 704 assertEquals(0,1); |