1 /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. 2 * Copyright (C) 2011-2019 Brian P. Hinz 3 * 4 * This is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This software is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this software; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 17 * USA. 18 */ 19 20 // 21 // A ZlibInStream reads from a zlib.io.InputStream 22 // 23 24 package com.tigervnc.rdr; 25 import com.jcraft.jzlib.*; 26 27 public class ZlibInStream extends InStream { 28 29 static final int defaultBufSize = 16384; 30 ZlibInStream(int bufSize_)31 public ZlibInStream(int bufSize_) 32 { 33 bufSize = bufSize_; 34 b = new byte[bufSize]; 35 bytesIn = offset = 0; 36 ptr = end = start = 0; 37 init(); 38 } 39 ZlibInStream()40 public ZlibInStream() { this(defaultBufSize); } 41 setUnderlying(InStream is, int bytesIn_)42 public void setUnderlying(InStream is, int bytesIn_) 43 { 44 underlying = is; 45 bytesIn = bytesIn_; 46 ptr = end = start; 47 } 48 pos()49 public int pos() 50 { 51 return offset + ptr - start; 52 } 53 flushUnderlying()54 public void flushUnderlying() 55 { 56 ptr = end = start; 57 58 while (bytesIn > 0) { 59 decompress(true); 60 end = start; // throw away any data 61 } 62 63 setUnderlying(null, 0); 64 } 65 reset()66 public void reset() 67 { 68 deinit(); 69 init(); 70 } 71 init()72 public void init() 73 { 74 assert(zs == null); 75 76 zs = new ZStream(); 77 zs.next_in = null; 78 zs.next_in_index = 0; 79 zs.avail_in = 0; 80 if (zs.inflateInit() != JZlib.Z_OK) { 81 zs = null; 82 throw new Exception("ZlinInStream: inflateInit failed"); 83 } 84 } 85 deinit()86 public void deinit() 87 { 88 assert(zs != null); 89 setUnderlying(null, 0); 90 zs.inflateEnd(); 91 zs = null; 92 } 93 overrun(int itemSize, int nItems, boolean wait)94 protected int overrun(int itemSize, int nItems, boolean wait) 95 { 96 if (itemSize > bufSize) 97 throw new Exception("ZlibInStream overrun: max itemSize exceeded"); 98 99 if (end - ptr != 0) 100 System.arraycopy(b, ptr, b, start, end - ptr); 101 102 offset += ptr - start; 103 end -= ptr - start; 104 ptr = start; 105 106 while (end - ptr < itemSize) { 107 if (!decompress(wait)) 108 return 0; 109 } 110 111 int nAvail; 112 nAvail = (end - ptr) / itemSize; 113 if (nAvail < nItems) 114 return nAvail; 115 116 return nItems; 117 } 118 119 // decompress() calls the decompressor once. Note that this won't 120 // necessarily generate any output data - it may just consume some input 121 // data. Returns false if wait is false and we would block on the underlying 122 // stream. 123 decompress(boolean wait)124 private boolean decompress(boolean wait) 125 { 126 if (underlying == null) 127 throw new Exception("ZlibInStream overrun: no underlying stream"); 128 129 zs.next_out = b; 130 zs.next_out_index = end; 131 zs.avail_out = start + bufSize - end; 132 133 int n = underlying.check(1, 1, wait); 134 if (n == 0) return false; 135 zs.next_in = underlying.getbuf(); 136 zs.next_in_index = underlying.getptr(); 137 zs.avail_in = underlying.getend() - underlying.getptr(); 138 if (zs.avail_in > bytesIn) 139 zs.avail_in = bytesIn; 140 141 int rc = zs.inflate(JZlib.Z_SYNC_FLUSH); 142 if (rc != JZlib.Z_OK) { 143 throw new Exception("ZlibInStream: inflate failed"); 144 } 145 146 bytesIn -= zs.next_in_index - underlying.getptr(); 147 end = zs.next_out_index; 148 underlying.setptr(zs.next_in_index); 149 return true; 150 } 151 152 private InStream underlying; 153 private int bufSize; 154 private int offset; 155 private com.jcraft.jzlib.ZStream zs; 156 private int bytesIn; 157 private int start; 158 } 159