1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
//
// A JavaInStream reads from a java.io.InputStream
//
package com.tigervnc.rdr;
public class JavaInStream extends InStream {
static final int defaultBufSize = 8192;
static final int minBulkSize = 1024;
public JavaInStream(java.io.InputStream jis_, int bufSize_) {
jis = jis_;
bufSize = bufSize_;
b = new byte[bufSize];
ptr = end = offset = 0;
timeWaitedIn100us = 5;
timedKbits = 0;
}
public JavaInStream(java.io.InputStream jis_) { this(jis_, defaultBufSize); }
public void readBytes(byte[] data, int dataPtr, int length) {
if (length < minBulkSize) {
super.readBytes(data, dataPtr, length);
return;
}
int n = end - ptr;
if (n > length) n = length;
System.arraycopy(b, ptr, data, dataPtr, n);
dataPtr += n;
length -= n;
ptr += n;
while (length > 0) {
n = read(data, dataPtr, length);
dataPtr += n;
length -= n;
offset += n;
}
}
public int pos() { return offset + ptr; }
public void startTiming() {
timing = true;
// Carry over up to 1s worth of previous rate for smoothing.
if (timeWaitedIn100us > 10000) {
timedKbits = timedKbits * 10000 / timeWaitedIn100us;
timeWaitedIn100us = 10000;
}
}
public void stopTiming() {
timing = false;
if (timeWaitedIn100us < timedKbits/2)
timeWaitedIn100us = timedKbits/2; // upper limit 20Mbit/s
}
public long kbitsPerSecond() {
return timedKbits * 10000 / timeWaitedIn100us;
}
public long timeWaited() { return timeWaitedIn100us; }
protected int overrun(int itemSize, int nItems, boolean wait) {
if (itemSize > bufSize)
throw new Exception("JavaInStream overrun: max itemSize exceeded");
if (end - ptr != 0)
System.arraycopy(b, ptr, b, 0, end - ptr);
offset += ptr;
end -= ptr;
ptr = 0;
while (end < itemSize) {
int n = read(b, end, bufSize - end, wait);
end += n;
}
if (itemSize * nItems > end)
nItems = end / itemSize;
return nItems;
}
private int read(byte[] buf, int bufPtr, int len, boolean wait) {
try {
long before = 0;
if (timing)
before = System.nanoTime();
int n = jis.read(buf, bufPtr, len);
if (n < 0) throw new EndOfStream();
if (timing) {
long after = System.nanoTime();
long newTimeWaited = (after - before) / 100000;
int newKbits = n * 8 / 1000;
// limit rate to between 10kbit/s and 40Mbit/s
if (newTimeWaited > newKbits*1000) newTimeWaited = newKbits*1000;
if (newTimeWaited < newKbits/4) newTimeWaited = newKbits/4;
timeWaitedIn100us += newTimeWaited;
timedKbits += newKbits;
}
return n;
} catch (java.io.IOException e) {
throw new IOException(e);
}
}
private int read(byte[] buf, int bufPtr, int len) { return read(buf, bufPtr, len, true); }
private java.io.InputStream jis;
private int offset;
private int bufSize;
boolean timing;
long timeWaitedIn100us;
long timedKbits;
}
|