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