blob: 5c35036953a840dabe0baefc50cd77069bd2faa8 [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];
Brian Hinzb898b882011-10-02 02:40:37 +000034 ptr = end = offset = 0;
DRCc5dc0382011-05-13 21:42:14 +000035 timeWaitedIn100us = 5;
36 timedKbits = 0;
37 }
38
39 public JavaInStream(java.io.InputStream jis_) { this(jis_, defaultBufSize); }
40
Brian Hinzb898b882011-10-02 02:40:37 +000041 public void readBytes(byte[] data, int dataPtr, int length) {
DRCc5dc0382011-05-13 21:42:14 +000042 if (length < minBulkSize) {
Brian Hinzb898b882011-10-02 02:40:37 +000043 super.readBytes(data, dataPtr, length);
DRCc5dc0382011-05-13 21:42:14 +000044 return;
45 }
46
47 int n = end - ptr;
48 if (n > length) n = length;
49
Brian Hinzb898b882011-10-02 02:40:37 +000050 System.arraycopy(b, ptr, data, dataPtr, n);
51 dataPtr += n;
DRCc5dc0382011-05-13 21:42:14 +000052 length -= n;
53 ptr += n;
54
55 while (length > 0) {
Brian Hinzb898b882011-10-02 02:40:37 +000056 n = read(data, dataPtr, length);
57 dataPtr += n;
DRCc5dc0382011-05-13 21:42:14 +000058 length -= n;
Brian Hinzb898b882011-10-02 02:40:37 +000059 offset += n;
DRCc5dc0382011-05-13 21:42:14 +000060 }
61 }
62
Brian Hinzb898b882011-10-02 02:40:37 +000063 public int pos() { return offset + ptr; }
DRCc5dc0382011-05-13 21:42:14 +000064
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
Brian Hinz2c5b44c2011-06-17 13:00:58 +000088 protected int overrun(int itemSize, int nItems, boolean wait) {
DRCc5dc0382011-05-13 21:42:14 +000089 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
Brian Hinzb898b882011-10-02 02:40:37 +000095 offset += ptr;
DRCc5dc0382011-05-13 21:42:14 +000096 end -= ptr;
97 ptr = 0;
98
99 while (end < itemSize) {
Brian Hinzb898b882011-10-02 02:40:37 +0000100 int n = read(b, end, bufSize - end, wait);
DRCc5dc0382011-05-13 21:42:14 +0000101 end += n;
102 }
103
104 if (itemSize * nItems > end)
105 nItems = end / itemSize;
106
107 return nItems;
108 }
109
Brian Hinzb898b882011-10-02 02:40:37 +0000110 private int read(byte[] buf, int bufPtr, int len, boolean wait) {
DRCc5dc0382011-05-13 21:42:14 +0000111 try {
112 long before = 0;
113 if (timing)
Brian Hinza5f0fc82011-10-24 02:14:55 +0000114 before = System.nanoTime();
DRCc5dc0382011-05-13 21:42:14 +0000115
Brian Hinzb898b882011-10-02 02:40:37 +0000116 int n = jis.read(buf, bufPtr, len);
DRCc5dc0382011-05-13 21:42:14 +0000117 if (n < 0) throw new EndOfStream();
118
119 if (timing) {
Brian Hinza5f0fc82011-10-24 02:14:55 +0000120 long after = System.nanoTime();
121 long newTimeWaited = (after - before) / 100000;
DRCc5dc0382011-05-13 21:42:14 +0000122 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 }
Brian Hinzb898b882011-10-02 02:40:37 +0000139 private int read(byte[] buf, int bufPtr, int len) { return read(buf, bufPtr, len, true); }
DRCc5dc0382011-05-13 21:42:14 +0000140
141 private java.io.InputStream jis;
Brian Hinzb898b882011-10-02 02:40:37 +0000142 private int offset;
DRCc5dc0382011-05-13 21:42:14 +0000143 private int bufSize;
144
145 boolean timing;
146 long timeWaitedIn100us;
147 long timedKbits;
148}