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