2005-09-26 jrandom

* Reworded the SSU introductions config section (thanks duck!)
    * Force identity content encoding for I2PTunnel httpserver requests
      (thanks redzara!)
    * Further x-i2p-gzip bugfixes for the end of streams
    * Reduce the minimum bandwidth limits to 3KBps steady and burst (though
      I2P's performance at 3KBps is another issue)
    * Cleaned up some streaming lib structures
This commit is contained in:
jrandom
2005-09-26 23:45:52 +00:00
committed by zzz
parent 56ecdcce82
commit aef33548b3
20 changed files with 193 additions and 179 deletions

View File

@@ -37,6 +37,7 @@ class HTTPResponseOutputStream extends FilterOutputStream {
private byte _buf1[];
protected boolean _gzip;
private long _dataWritten;
private InternalGZIPInputStream _in;
private static final int CACHE_SIZE = 8*1024;
public HTTPResponseOutputStream(OutputStream raw) {
@@ -199,7 +200,7 @@ class HTTPResponseOutputStream extends FilterOutputStream {
}
protected void beginProcessing() throws IOException {
out.flush();
//out.flush();
PipedInputStream pi = new PipedInputStream();
PipedOutputStream po = new PipedOutputStream(pi);
new I2PThread(new Pusher(pi, out), "HTTP decompresser").start();
@@ -207,22 +208,22 @@ class HTTPResponseOutputStream extends FilterOutputStream {
}
private class Pusher implements Runnable {
private InputStream _in;
private InputStream _inRaw;
private OutputStream _out;
public Pusher(InputStream in, OutputStream out) {
_in = in;
_inRaw = in;
_out = out;
}
public void run() {
OutputStream to = null;
InternalGZIPInputStream in = null;
_in = null;
long start = System.currentTimeMillis();
long written = 0;
try {
in = new InternalGZIPInputStream(_in);
_in = new InternalGZIPInputStream(_inRaw);
byte buf[] = new byte[8192];
int read = -1;
while ( (read = in.read(buf)) != -1) {
while ( (read = _in.read(buf)) != -1) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Read " + read + " and writing it to the browser/streams");
_out.write(buf, 0, read);
@@ -230,16 +231,22 @@ class HTTPResponseOutputStream extends FilterOutputStream {
written += read;
}
if (_log.shouldLog(Log.INFO))
_log.info("Decompressed: " + written + ", " + in.getTotalRead() + "/" + in.getTotalExpanded());
_log.info("Decompressed: " + written + ", " + _in.getTotalRead() + "/" + _in.getTotalExpanded());
} catch (IOException ioe) {
if (_log.shouldLog(Log.WARN))
_log.warn("Error decompressing: " + written + ", " + in.getTotalRead() + "/" + in.getTotalExpanded(), ioe);
_log.warn("Error decompressing: " + written + ", " + _in.getTotalRead() + "/" + _in.getTotalExpanded(), ioe);
} finally {
if (_out != null) try { _out.close(); } catch (IOException ioe) {}
if (_log.shouldLog(Log.WARN))
_log.warn("After decompression, written=" + written + " read=" + _in.getTotalRead()
+ ", expanded=" + _in.getTotalExpanded() + ", remaining=" + _in.getRemaining()
+ ", finished=" + _in.getFinished());
if (_out != null) try {
_out.close();
} catch (IOException ioe) {}
}
long end = System.currentTimeMillis();
double compressed = in.getTotalRead();
double expanded = in.getTotalExpanded();
double compressed = _in.getTotalRead();
double expanded = _in.getTotalExpanded();
double ratio = 0;
if (expanded > 0)
ratio = compressed/expanded;
@@ -255,6 +262,15 @@ class HTTPResponseOutputStream extends FilterOutputStream {
}
public long getTotalRead() { return super.inf.getTotalIn(); }
public long getTotalExpanded() { return super.inf.getTotalOut(); }
public long getRemaining() { return super.inf.getRemaining(); }
public boolean getFinished() { return super.inf.finished(); }
public String toString() {
return "Read: " + getTotalRead() + " expanded: " + getTotalExpanded() + " remaining: " + getRemaining() + " finished: " + getFinished();
}
}
public String toString() {
return super.toString() + ": " + _in;
}
public static void main(String args[]) {

View File

@@ -3,16 +3,13 @@
*/
package net.i2p.i2ptunnel;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.FilterOutputStream;
import java.io.*;
import java.net.Socket;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import net.i2p.I2PAppContext;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.data.ByteArray;
import net.i2p.data.DataHelper;
@@ -30,12 +27,38 @@ import net.i2p.util.Log;
*
*/
public class I2PTunnelHTTPClientRunner extends I2PTunnelRunner {
private Log _log;
public I2PTunnelHTTPClientRunner(Socket s, I2PSocket i2ps, Object slock, byte[] initialI2PData, List sockList, Runnable onTimeout) {
super(s, i2ps, slock, initialI2PData, sockList, onTimeout);
_log = I2PAppContext.getGlobalContext().logManager().getLog(I2PTunnelHTTPClientRunner.class);
}
protected OutputStream getSocketOut() throws IOException {
OutputStream raw = super.getSocketOut();
return new HTTPResponseOutputStream(raw);
}
protected void close(OutputStream out, InputStream in, OutputStream i2pout, InputStream i2pin, Socket s, I2PSocket i2ps, Thread t1, Thread t2) throws InterruptedException, IOException {
try {
i2pin.close();
i2pout.close();
} catch (IOException ioe) {
// ignore
if (_log.shouldLog(Log.DEBUG))
_log.debug("Unable to close the i2p socket output stream: " + i2pout, ioe);
}
try {
in.close();
out.close();
} catch (IOException ioe) {
// ignore
if (_log.shouldLog(Log.DEBUG))
_log.debug("Unable to close the browser output stream: " + out, ioe);
}
i2ps.close();
s.close();
t1.join(30*1000);
t2.join(30*1000);
}
}

View File

@@ -71,6 +71,10 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
if ( (_spoofHost != null) && (_spoofHost.trim().length() > 0) )
headers.setProperty("Host", _spoofHost);
headers.setProperty("Connection", "close");
// we keep the enc sent by the browser before clobbering it, since it may have
// been x-i2p-gzip
String enc = headers.getProperty("Accept-encoding");
headers.setProperty("Accept-encoding", "identity;q=1, *;q=0");
String modifiedHeader = formatHeaders(headers, command);
//String modifiedHeader = getModifiedHeader(socket);
@@ -91,7 +95,6 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
if ( (val != null) && (!Boolean.valueOf(val).booleanValue()) )
allowGZIP = false;
}
String enc = headers.getProperty("Accept-encoding");
if (_log.shouldLog(Log.INFO))
_log.info("HTTP server encoding header: " + enc);
if ( allowGZIP && (enc != null) && (enc.indexOf("x-i2p-gzip") >= 0) ) {

View File

@@ -153,11 +153,8 @@ public class I2PTunnelRunner extends I2PThread implements I2PSocket.SocketErrorL
onTimeout.run();
}
// now one connection is dead - kill the other as well.
s.close();
i2ps.close();
t1.join(30*1000);
t2.join(30*1000);
// now one connection is dead - kill the other as well, after making sure we flush
close(out, in, i2pout, i2pin, s, i2ps, t1, t2);
} catch (InterruptedException ex) {
if (_log.shouldLog(Log.ERROR))
_log.error("Interrupted", ex);
@@ -188,6 +185,27 @@ public class I2PTunnelRunner extends I2PThread implements I2PSocket.SocketErrorL
}
}
protected void close(OutputStream out, InputStream in, OutputStream i2pout, InputStream i2pin, Socket s, I2PSocket i2ps, Thread t1, Thread t2) throws InterruptedException, IOException {
try {
out.flush();
} catch (IOException ioe) {
// ignore
}
try {
i2pout.flush();
} catch (IOException ioe) {
// ignore
}
in.close();
i2pin.close();
// ok, yeah, there's a race here in theory, if data comes in after flushing and before
// closing, but its better than before...
s.close();
i2ps.close();
t1.join(30*1000);
t2.join(30*1000);
}
public void errorOccurred() {
synchronized (finishLock) {
finished = true;