use LwHttp.Buffer to set limit on InputStream

This commit is contained in:
Hannes Janetzek 2014-01-20 22:43:57 +01:00
parent 9ed4bb6ec5
commit 402cbe7e57
10 changed files with 79 additions and 81 deletions

View File

@ -116,9 +116,9 @@ public class LwHttp {
if (status == 200) {
Uint8Array buf = Uint8ArrayNative.create(xhr.getResponseArrayBuffer());
mDataSource.process(new Buffer(buf), buf.byteLength());
mDataSource.process(new Buffer(buf));
} else {
mDataSource.process(null, -1);
mDataSource.process(null);
}
}
}

View File

@ -57,12 +57,12 @@ public abstract class UrlTileDataSource implements ITileDataSource {
return result;
}
public void process(InputStream is, int length) {
public void process(InputStream is) {
boolean win = false;
if (length >= 0) {
if (is != null) {
try {
win = mTileDecoder.decode(mTile, mSink, is, length);
win = mTileDecoder.decode(mTile, mSink, is);
} catch (IOException e) {
e.printStackTrace();
}

View File

@ -7,6 +7,6 @@ import org.oscim.core.Tile;
public interface ITileDecoder {
boolean decode(Tile tile, ITileDataSink sink, InputStream is, int contentLength)
boolean decode(Tile tile, ITileDataSink sink, InputStream is)
throws IOException;
}

View File

@ -39,6 +39,7 @@ import org.slf4j.LoggerFactory;
*/
public class LwHttp {
static final Logger log = LoggerFactory.getLogger(LwHttp.class);
static final boolean DBG = false;
private final static byte[] HEADER_HTTP_OK = "200 OK".getBytes();
private final static byte[] HEADER_CONTENT_TYPE = "Content-Type".getBytes();
@ -46,7 +47,7 @@ public class LwHttp {
private final static int RESPONSE_EXPECTED_LIVES = 100;
private final static long RESPONSE_TIMEOUT = (long) 10E9; // 10 second in nanosecond
private final static int BUFFER_SIZE = 1024;
private final static int BUFFER_SIZE = 4096;
private final byte[] buffer = new byte[BUFFER_SIZE];
private final String mHost;
@ -55,7 +56,7 @@ public class LwHttp {
private int mMaxReq = 0;
private Socket mSocket;
private OutputStream mCommandStream;
private InputStream mResponseStream;
private Buffer mResponseStream;
private OutputStream mCacheOutputStream;
private long mLastRequest = 0;
private SocketAddress mSockAddr;
@ -67,8 +68,6 @@ public class LwHttp {
private final boolean mInflateContent;
private final byte[] mContentType;
private int mContentLength = -1;
/**
* @param url
* Base url for tiles
@ -106,18 +105,40 @@ public class LwHttp {
mRequestBuffer, 0, REQUEST_GET_START.length);
}
// TODO:
// to avoid a copy in PbfDecoder one could manage the buffer
// array directly and provide access to it.
static class Buffer extends BufferedInputStream {
final OutputStream mCacheOutputstream;
OutputStream mCacheOutputstream;
int sumRead = 0;
int mContentLength;
public Buffer(InputStream is, OutputStream cache) {
super(is, 4096);
public Buffer(InputStream is) {
super(is, BUFFER_SIZE);
}
public void setCache(OutputStream cache) {
mCacheOutputstream = cache;
}
public void start(int length) {
sumRead = 0;
mContentLength = length;
}
@Override
public int read() throws IOException {
if (sumRead >= mContentLength)
return -1;
int data = super.read();
if (data >= 0)
sumRead += 1;
if (DBG)
log.debug("read {} {}", sumRead, mContentLength);
if (mCacheOutputstream != null)
mCacheOutputstream.write(data);
return data;
@ -126,10 +147,18 @@ public class LwHttp {
@Override
public int read(byte[] buffer, int offset, int byteCount)
throws IOException {
int len = super.read(buffer, offset, byteCount);
if (len >= 0)
mCacheOutputstream.write(buffer, offset, len);
if (sumRead >= mContentLength)
return -1;
int len = super.read(buffer, offset, byteCount);
sumRead += len;
if (DBG)
log.debug("read {} {} {}", len, sumRead, mContentLength);
if (mCacheOutputstream != null)
mCacheOutputstream.write(buffer, offset, byteCount);
return len;
}
@ -149,8 +178,9 @@ public class LwHttp {
public InputStream readHeader() throws IOException {
InputStream is = mResponseStream;
is.mark(4096);
Buffer is = mResponseStream;
is.mark(BUFFER_SIZE);
is.start(BUFFER_SIZE);
byte[] buf = buffer;
boolean first = true;
@ -161,7 +191,7 @@ public class LwHttp {
int end = 0;
int len = 0;
mContentLength = -1;
int contentLength = -1;
// header may not be larger than BUFFER_SIZE for this to work
for (; (pos < read) || ((read < BUFFER_SIZE) &&
@ -202,11 +232,11 @@ public class LwHttp {
} else if (check(HEADER_CONTENT_LENGTH, buf, pos, end)) {
// parse Content-Length
mContentLength = parseInt(buf, pos +
contentLength = parseInt(buf, pos +
HEADER_CONTENT_LENGTH.length + 2, end - 1);
}
if (!ok) {
if (!ok || DBG) {
String line = new String(buf, pos, end - pos - 1);
log.debug("> {} <", line);
}
@ -223,9 +253,8 @@ public class LwHttp {
is.mark(0);
is.skip(end);
if (mCacheOutputStream != null) {
is = new Buffer(is, mCacheOutputStream);
}
is.setCache(mCacheOutputStream);
is.start(contentLength);
if (mInflateContent)
return new InflaterInputStream(is);
@ -238,14 +267,10 @@ public class LwHttp {
if (mSocket != null && ((mMaxReq-- <= 0)
|| (System.nanoTime() - mLastRequest > RESPONSE_TIMEOUT))) {
try {
mSocket.close();
} catch (IOException e) {
log.debug(e.getMessage());
}
close();
// log.debug("not alive - recreate connection " + mMaxReq);
mSocket = null;
if (DBG)
log.debug("not alive - recreate connection " + mMaxReq);
}
if (mSocket == null) {
@ -284,6 +309,9 @@ public class LwHttp {
System.arraycopy(REQUEST_GET_END, 0, request, pos, len);
len += pos;
if (DBG)
log.debug("request: {}", new String(request, 0, len));
try {
mCommandStream.write(request, 0, len);
mCommandStream.flush();
@ -309,7 +337,7 @@ public class LwHttp {
mSocket.setTcpNoDelay(true);
mCommandStream = mSocket.getOutputStream();
mResponseStream = new BufferedInputStream(mSocket.getInputStream());
mResponseStream = new Buffer(mSocket.getInputStream());
return true;
}
@ -366,10 +394,6 @@ public class LwHttp {
close();
}
public int getContentLength() {
return mContentLength;
}
/**
* Write custom tile url
*

View File

@ -72,9 +72,6 @@ public abstract class PbfDecoder implements ITileDecoder {
// offset of buffer in message
private int mBufferOffset;
// max bytes to read: message = header + content
private int mMsgEnd;
// overall bytes of message read
private int mMsgPos;
@ -86,7 +83,7 @@ public abstract class PbfDecoder implements ITileDecoder {
mStringDecoder = new UTF8Decoder();
}
public void setInputStream(InputStream is, int contentLength) {
public void setInputStream(InputStream is) {
mInputStream = is;
bufferFill = 0;
@ -94,7 +91,6 @@ public abstract class PbfDecoder implements ITileDecoder {
mBufferOffset = 0;
mMsgPos = 0;
mMsgEnd = contentLength;
}
protected int decodeVarint32() throws IOException {
@ -397,8 +393,8 @@ public abstract class PbfDecoder implements ITileDecoder {
}
public boolean hasData() throws IOException {
if (mBufferOffset + bufferPos >= mMsgEnd)
return false;
//if (mBufferOffset + bufferPos >= mMsgEnd)
// return false;
return fillBuffer(1) > 0;
}
@ -414,10 +410,6 @@ public abstract class PbfDecoder implements ITileDecoder {
if (bytesLeft >= size)
return bytesLeft;
// check if inputstream is read to the end
if (mMsgPos >= mMsgEnd)
return bytesLeft;
int maxSize = buffer.length;
if (size > maxSize) {
@ -454,10 +446,7 @@ public abstract class PbfDecoder implements ITileDecoder {
}
while ((bufferFill - bufferPos) < size) {
int max = maxSize - bufferFill;
if (max > mMsgEnd - mMsgPos)
max = mMsgEnd - mMsgPos;
if (max <= 0) {
// should not be possible
@ -468,9 +457,8 @@ public abstract class PbfDecoder implements ITileDecoder {
int len = mInputStream.read(buffer, bufferFill, max);
if (len < 0) {
mMsgEnd = mMsgPos;
if (debug)
log.debug(" finished reading " + mMsgPos);
log.debug("finished reading {}", mMsgPos);
// finished reading, mark end
buffer[bufferFill] = 0;
@ -479,10 +467,6 @@ public abstract class PbfDecoder implements ITileDecoder {
mMsgPos += len;
bufferFill += len;
if (mMsgPos == mMsgEnd)
break;
}
return bufferFill - bufferPos;
}

View File

@ -55,7 +55,7 @@ public abstract class UrlTileDataSource implements ITileDataSource {
} else {
InputStream is = c.getInputStream();
try {
if (mTileDecoder.decode(tile, sink, is, c.getBytes())) {
if (mTileDecoder.decode(tile, sink, is)) {
return QueryResult.SUCCESS;
}
} catch (IOException e) {
@ -77,15 +77,14 @@ public abstract class UrlTileDataSource implements ITileDataSource {
} else if ((is = mConn.readHeader()) == null) {
log.debug("{} Network Error", tile);
} else {
int bytes = mConn.getContentLength();
success = mTileDecoder.decode(tile, sink, is, bytes);
success = mTileDecoder.decode(tile, sink, is);
}
} catch (SocketException e) {
log.debug("{} Socket exception: {}", tile, e.getMessage());
} catch (SocketTimeoutException e) {
log.debug("{} Socket Timeout", tile);
} catch (UnknownHostException e) {
log.debug("{} No Network", tile);
log.debug("{} Unknown host: {}", tile, e.getMessage());
} catch (IOException e) {
e.printStackTrace();
} finally {

View File

@ -71,13 +71,13 @@ public class TileDecoder extends PbfDecoder {
private float mScale;
@Override
public boolean decode(Tile tile, ITileDataSink mapDataCallback, InputStream is,
int contentLength)
public boolean decode(Tile tile, ITileDataSink mapDataCallback, InputStream is)
throws IOException {
if (debug)
log.debug(tile + " decode");
setInputStream(is, Integer.MAX_VALUE);
setInputStream(is);
mTile = tile;
mMapDataCallback = mapDataCallback;
mScale = REF_TILE_SIZE / Tile.SIZE;

View File

@ -68,10 +68,10 @@ public class TileDecoder extends PbfDecoder {
}
@Override
public boolean decode(Tile tile, ITileDataSink sink, InputStream is, int contentLength)
public boolean decode(Tile tile, ITileDataSink sink, InputStream is)
throws IOException {
setInputStream(is, contentLength);
setInputStream(is);
mTile = tile;
mSink = sink;

View File

@ -92,17 +92,12 @@ public class OSciMap2TileSource extends UrlTileSource {
}
@Override
public boolean decode(Tile tile, ITileDataSink sink, InputStream is, int contentLength)
public boolean decode(Tile tile, ITileDataSink sink, InputStream is)
throws IOException {
int byteCount = readUnsignedInt(is, buffer);
//log.debug(tile + " contentLength:" + byteCount);
if (byteCount < 0) {
log.debug(tile + " invalid content length: " + byteCount);
return false;
}
readUnsignedInt(is, buffer);
setInputStream(is, byteCount);
setInputStream(is);
mTile = tile;
mMapDataSink = sink;

View File

@ -76,17 +76,13 @@ public class TileDecoder extends PbfDecoder {
}
@Override
public boolean decode(Tile tile, ITileDataSink sink, InputStream is, int contentLength)
public boolean decode(Tile tile, ITileDataSink sink, InputStream is)
throws IOException {
int byteCount = readUnsignedInt(is, buffer);
readUnsignedInt(is, buffer);
//log.debug(tile + " contentLength:" + byteCount);
if (byteCount < 0) {
log.debug("invalid contentLength: " + byteCount);
return false;
}
setInputStream(is, byteCount);
setInputStream(is);
mTile = tile;
mMapDataSink = sink;