Mercurial > hg > Members > nobuyasu > tightVNCProxy
comparison src/myVncProxy/MyRfbProto.java @ 87:a8c33757ac99
refactoring zip/unzip
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Wed, 03 Aug 2011 08:33:55 +0900 |
parents | b7225991184b |
children | 9b3b1e3e7db5 |
comparison
equal
deleted
inserted
replaced
86:b7225991184b | 87:a8c33757ac99 |
---|---|
485 changeStatusFlag(); | 485 changeStatusFlag(); |
486 } else { | 486 } else { |
487 changeStatusFlag(); | 487 changeStatusFlag(); |
488 } | 488 } |
489 } | 489 } |
490 | 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 } | |
541 | |
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 } | |
577 | |
578 void newClient(AcceptThread acceptThread, final Socket newCli, | |
579 final OutputStream os, final InputStream is) throws IOException { | |
580 // createBimgFlag = true; | |
581 // rfb.addSockTmp(newCli); | |
582 // addSock(newCli); | |
583 final Client <LinkedList<byte[]>> c = multicastqueue.newClient(); | |
584 Runnable sender = new Runnable() { | |
585 public void run() { | |
586 | |
587 Deflater deflater = new Deflater(); | |
588 try { | |
589 /** | |
590 * initial connection of RFB protocol | |
591 */ | |
592 sendRfbVersion(os); | |
593 readVersionMsg(is); | |
594 sendSecurityType(os); | |
595 readSecType(is); | |
596 sendSecResult(os); | |
597 readClientInit(is); | |
598 sendInitData(os); | |
599 | |
600 for (;;) { | |
601 LinkedList<byte[]> bufs = c.poll(); | |
602 byte[] b = bufs.poll(); | |
603 if (b[0]==RfbProto.FramebufferUpdate) { | |
604 int encoding = u32(b,12); | |
605 if (encoding==RfbProto.EncodingZlib||encoding==RfbProto.EncodingZRLE) { | |
606 LinkedList<byte[]> outs = new LinkedList<byte[]>(); | |
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 | |
613 os.write(out); | |
614 } | |
615 } | |
616 } else { | |
617 os.write(b, 0, b.length); | |
618 } | |
619 os.flush(); | |
620 } | |
621 } catch (IOException e) { | |
622 /** | |
623 * if socket closed | |
624 */ | |
625 // cliList.remove(newCli); | |
626 } | |
627 | |
628 } | |
629 | |
630 | |
631 | |
632 }; | |
633 clients++; | |
634 new Thread(sender).start(); | |
635 | |
636 } | |
637 | |
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 } | |
646 void speedCheckMillis() { | 491 void speedCheckMillis() { |
647 | 492 Runnable stdin = new Runnable() { |
648 Runnable stdin = new Runnable() { | |
649 public void run() { | 493 public void run() { |
650 int c; | 494 int c; |
651 try { | 495 try { |
652 while( (c = System.in.read()) != -1 ) { | 496 while( (c = System.in.read()) != -1 ) { |
653 switch(c) { | 497 switch(c) { |
665 }; | 509 }; |
666 | 510 |
667 new Thread(stdin).start(); | 511 new Thread(stdin).start(); |
668 } | 512 } |
669 | 513 |
514 /** | |
515 * gzip byte arrays | |
516 * @param deflater | |
517 * @param inputs | |
518 * byte len[4] total byte length | |
519 * byte data[] | |
520 * @param outputs | |
521 * byte len[4] total byte length | |
522 * byte data[] | |
523 * @return byte length in last byte array | |
524 * @throws IOException | |
525 */ | |
526 public int zip(Deflater deflater,LinkedList<byte[]> inputs, LinkedList<byte[]> outputs) throws IOException { | |
527 int clen = u32(inputs.poll(),0); | |
528 int len = 0, count = 0; | |
529 int len2=0; | |
530 deflater.reset(); | |
531 do { | |
532 byte[] b1 = inputs.poll(); | |
533 if (inputs.size()==0) { | |
534 deflater.setInput(b1,0,clen); | |
535 deflater.finish(); | |
536 } else { | |
537 deflater.setInput(b1); | |
538 clen -= b1.length; | |
539 } | |
540 int len1=0; | |
541 do { | |
542 byte[] c1 = new byte[INFLATE_BUFSIZE]; | |
543 len2 = len1; | |
544 len1 = deflater.deflate(c1); | |
545 if (len1>0) { | |
546 outputs.addLast(c1); | |
547 count ++; | |
548 len += len1; | |
549 } | |
550 } while (len1 > 0); | |
551 } while(inputs.size()>0); | |
552 byte[] blen = castIntByte(len); | |
553 outputs.addFirst(blen); | |
554 return len2; | |
555 } | |
556 | |
557 /** | |
558 * gunzip byte arrays | |
559 * @param inflater | |
560 * @param inputs | |
561 * byte len[4] total byte length | |
562 * byte data[] | |
563 * @param outputs | |
564 * byte len[4] total byte length | |
565 * byte data[] | |
566 * @throws IOException | |
567 */ | |
568 public void unzip(Inflater inflater, byte[] input, LinkedList<byte[]> outputs) | |
569 throws DataFormatException { | |
570 int len=0,len0; | |
571 inflater.setInput(input); | |
572 do { | |
573 byte buf[] = new byte[INFLATE_BUFSIZE]; | |
574 len0 = inflater.inflate(buf); | |
575 len += len0; | |
576 outputs.addLast(buf); | |
577 } while (len0 ==INFLATE_BUFSIZE); | |
578 byte [] blen = castIntByte(len); | |
579 outputs.addFirst(blen); | |
580 } | |
581 | |
582 void readSendData(int dataLen) throws IOException, DataFormatException { | |
583 LinkedList<byte[]>bufs = new LinkedList<byte[]>(); | |
584 byte header[] = new byte[16]; | |
585 readFully(header,0,16); | |
586 if (header[0]==RfbProto.FramebufferUpdate) { | |
587 int encoding = u32(header,12); | |
588 if (encoding==RfbProto.EncodingZlib||encoding==RfbProto.EncodingZRLE) { | |
589 byte[] len = new byte[4]; | |
590 readFully(len,0,4); | |
591 byte inputData[] = new byte[dataLen-20]; | |
592 readFully(inputData); | |
593 unzip(inflater, inputData, bufs); | |
594 bufs.addFirst(header); | |
595 multicastqueue.put(bufs); | |
596 is.reset(); | |
597 return ; | |
598 } | |
599 } | |
600 bufs.add(header); | |
601 if (dataLen>16) { | |
602 byte b[] = new byte[dataLen-16]; | |
603 readFully(b); | |
604 bufs.add(b); | |
605 } | |
606 multicastqueue.put(bufs); | |
607 is.reset(); | |
608 | |
609 // It may be compressed. We can inflate here to avoid repeating clients decompressing here, | |
610 // but it may generate too many large data. It is better to do it in each client. | |
611 // But we have do inflation for all input data, so we have to do it here. | |
612 } | |
613 | |
614 void newClient(AcceptThread acceptThread, final Socket newCli, | |
615 final OutputStream os, final InputStream is) throws IOException { | |
616 // createBimgFlag = true; | |
617 // rfb.addSockTmp(newCli); | |
618 // addSock(newCli); | |
619 final Client <LinkedList<byte[]>> c = multicastqueue.newClient(); | |
620 Runnable sender = new Runnable() { | |
621 public void run() { | |
622 | |
623 Deflater deflater = new Deflater(); | |
624 try { | |
625 /** | |
626 * initial connection of RFB protocol | |
627 */ | |
628 sendRfbVersion(os); | |
629 readVersionMsg(is); | |
630 sendSecurityType(os); | |
631 readSecType(is); | |
632 sendSecResult(os); | |
633 readClientInit(is); | |
634 sendInitData(os); | |
635 | |
636 for (;;) { | |
637 LinkedList<byte[]> bufs = c.poll(); | |
638 byte[] header = bufs.poll(); | |
639 if (header[0]==RfbProto.FramebufferUpdate) { | |
640 int encoding = u32(header,12); | |
641 if (encoding==RfbProto.EncodingZlib||encoding==RfbProto.EncodingZRLE) { | |
642 LinkedList<byte[]> outs = new LinkedList<byte[]>(); | |
643 int len2 = zip(deflater, bufs, outs); | |
644 outs.addFirst(header); | |
645 while(!outs.isEmpty()) { | |
646 byte [] out= outs.poll(); | |
647 if (outs.isEmpty()) | |
648 os.write(out,0,len2); | |
649 else | |
650 os.write(out); | |
651 } | |
652 } | |
653 os.flush(); | |
654 return; | |
655 } | |
656 os.write(header); | |
657 for(byte [] b : bufs) { | |
658 os.write(b, 0, b.length); | |
659 } | |
660 os.flush(); | |
661 } | |
662 } catch (IOException e) { | |
663 /* if socket closed cliList.remove(newCli); */ | |
664 } | |
665 } | |
666 }; | |
667 clients++; | |
668 new Thread(sender).start(); | |
669 | |
670 } | |
671 | |
672 private int u32(byte[] b, int i) { | |
673 int ret = 0; | |
674 for(int j = 0;j<4;j++) { | |
675 ret *= 256; | |
676 ret += b[i+j] & 0xff; | |
677 } | |
678 return ret; | |
679 } | |
680 | |
670 } | 681 } |
671 | 682 |
672 | 683 |