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 // rdr::InStream marshalls data from a buffer stored in RDR (RFB Data 22 // Representation). 23 // 24 25 package com.tigervnc.rdr; 26 27 import java.nio.*; 28 29 import com.tigervnc.network.*; 30 31 abstract public class InStream { 32 33 // check() ensures there is buffer data for at least one item of size 34 // itemSize bytes. Returns the number of items in the buffer (up to a 35 // maximum of nItems). 36 check(int itemSize, int nItems, boolean wait)37 public int check(int itemSize, int nItems, boolean wait) { 38 int nAvail; 39 40 if (itemSize > (end - ptr)) 41 return overrun(itemSize, nItems, wait); 42 43 nAvail = (end - ptr) / itemSize; 44 if (nAvail < nItems) 45 return nAvail; 46 47 return nItems; 48 } 49 check(int itemSize, int nItems)50 public int check(int itemSize, int nItems) { return check(itemSize, nItems, true); } check(int itemSize)51 public int check(int itemSize) { return check(itemSize, 1); } 52 53 // checkNoWait() tries to make sure that the given number of bytes can 54 // be read without blocking. It returns true if this is the case, false 55 // otherwise. The length must be "small" (less than the buffer size). 56 checkNoWait(int length)57 public final boolean checkNoWait(int length) { return check(length, 1, false)!=0; } 58 59 // readU/SN() methods read unsigned and signed N-bit integers. 60 readS8()61 public final int readS8() { check(1); return b[ptr++]; } readS16()62 public final int readS16() { check(2); int b0 = b[ptr++]; 63 int b1 = b[ptr++] & 0xff; return b0 << 8 | b1; } readS32()64 public final int readS32() { check(4); int b0 = b[ptr++]; 65 int b1 = b[ptr++] & 0xff; 66 int b2 = b[ptr++] & 0xff; 67 int b3 = b[ptr++] & 0xff; 68 return b0 << 24 | b1 << 16 | b2 << 8 | b3; } 69 readU8()70 public final int readU8() { return readS8() & 0xff; } readU16()71 public final int readU16() { return readS16() & 0xffff; } readU32()72 public final int readU32() { return readS32() & 0xffffffff; } 73 74 // readString() reads a string - a U32 length followed by the data. 75 readString()76 public final String readString() { 77 int len = readU32(); 78 if (len > maxStringLength) 79 throw new Exception("InStream max string length exceeded"); 80 81 ByteBuffer str = ByteBuffer.allocate(len); 82 readBytes(str, len); 83 String utf8string = new String(); 84 try { 85 utf8string = new String(str.array(),"UTF8"); 86 } catch(java.io.UnsupportedEncodingException e) { 87 e.printStackTrace(); 88 } 89 return utf8string; 90 } 91 92 // maxStringLength protects against allocating a huge buffer. Set it 93 // higher if you need longer strings. 94 95 public static int maxStringLength = 65535; 96 skip(int bytes)97 public final void skip(int bytes) { 98 while (bytes > 0) { 99 int n = check(1, bytes); 100 ptr += n; 101 bytes -= n; 102 } 103 } 104 105 // readBytes() reads an exact number of bytes 106 readBytes(ByteBuffer data, int length)107 public void readBytes(ByteBuffer data, int length) { 108 while (length > 0) { 109 int n = check(1, length); 110 data.put(b, ptr, n); 111 ptr += n; 112 length -= n; 113 } 114 } 115 116 // readOpaqueN() reads a quantity "without byte-swapping". Because java has 117 // no byte-ordering, we just use big-endian. 118 readOpaque8()119 public final int readOpaque8() { return readU8(); } readOpaque16()120 public final int readOpaque16() { return readU16(); } readOpaque32()121 public final int readOpaque32() { return readU32(); } 122 123 // pos() returns the position in the stream. 124 pos()125 abstract public int pos(); 126 127 // bytesAvailable() returns true if at least one byte can be read from the 128 // stream without blocking. i.e. if false is returned then readU8() would 129 // block. 130 bytesAvailable()131 public boolean bytesAvailable() { return end != ptr; } 132 133 // getbuf(), getptr(), getend() and setptr() are "dirty" methods which allow 134 // you to manipulate the buffer directly. This is useful for a stream which 135 // is a wrapper around an underlying stream. 136 getbuf()137 public final byte[] getbuf() { return b; } getptr()138 public final int getptr() { return ptr; } getend()139 public final int getend() { return end; } setptr(int p)140 public final void setptr(int p) { ptr = p; } 141 142 // overrun() is implemented by a derived class to cope with buffer overrun. 143 // It ensures there are at least itemSize bytes of buffer data. Returns 144 // the number of items in the buffer (up to a maximum of nItems). itemSize 145 // is supposed to be "small" (a few bytes). 146 overrun(int itemSize, int nItems, boolean wait)147 abstract protected int overrun(int itemSize, int nItems, boolean wait); overrun(int itemSize, int nItems)148 protected int overrun(int itemSize, int nItems) { 149 return overrun(itemSize, nItems, true); 150 } 151 InStream()152 protected InStream() {} 153 protected byte[] b; 154 protected int ptr; 155 protected int end; 156 } 157