LwHttp: handle 'Connection: close' header
This commit is contained in:
parent
3409f5ff3c
commit
27153c8093
@ -44,6 +44,8 @@ public class LwHttp {
|
|||||||
private final static byte[] HEADER_HTTP_OK = "200 OK".getBytes();
|
private final static byte[] HEADER_HTTP_OK = "200 OK".getBytes();
|
||||||
//private final static byte[] HEADER_CONTENT_TYPE = "Content-Type".getBytes();
|
//private final static byte[] HEADER_CONTENT_TYPE = "Content-Type".getBytes();
|
||||||
private final static byte[] HEADER_CONTENT_LENGTH = "Content-Length".getBytes();
|
private final static byte[] HEADER_CONTENT_LENGTH = "Content-Length".getBytes();
|
||||||
|
private final static byte[] HEADER_CONNECTION_CLOSE = "Connection: close".getBytes();
|
||||||
|
|
||||||
private final static int RESPONSE_EXPECTED_LIVES = 100;
|
private final static int RESPONSE_EXPECTED_LIVES = 100;
|
||||||
private final static long RESPONSE_TIMEOUT = (long) 10E9; // 10 second in nanosecond
|
private final static long RESPONSE_TIMEOUT = (long) 10E9; // 10 second in nanosecond
|
||||||
|
|
||||||
@ -60,6 +62,9 @@ public class LwHttp {
|
|||||||
private long mLastRequest = 0;
|
private long mLastRequest = 0;
|
||||||
private SocketAddress mSockAddr;
|
private SocketAddress mSockAddr;
|
||||||
|
|
||||||
|
/** Server requested to close the connection */
|
||||||
|
private boolean mMustClose;
|
||||||
|
|
||||||
private final byte[] REQUEST_GET_START;
|
private final byte[] REQUEST_GET_START;
|
||||||
private final byte[] REQUEST_GET_END;
|
private final byte[] REQUEST_GET_END;
|
||||||
private final byte[] mRequestBuffer;
|
private final byte[] mRequestBuffer;
|
||||||
@ -119,20 +124,29 @@ public class LwHttp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean finishedReading() {
|
public boolean finishedReading() {
|
||||||
|
try {
|
||||||
|
while (bytesRead < contentLength && read() >= 0);
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.debug(e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
return bytesRead == contentLength;
|
return bytesRead == contentLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void mark(int readlimit) {
|
public synchronized void mark(int readlimit) {
|
||||||
|
if (dbg)
|
||||||
|
log.debug("mark {}", readlimit);
|
||||||
|
|
||||||
marked = bytesRead;
|
marked = bytesRead;
|
||||||
super.mark(readlimit);
|
super.mark(readlimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized long skip(long n) throws IOException {
|
public synchronized long skip(long n) throws IOException {
|
||||||
// Android(4.1.2) image decoder *requires* skip to
|
/* Android(4.1.2) image decoder *requires* skip to
|
||||||
// actually skip the requested amount.
|
* actually skip the requested amount.
|
||||||
// https://code.google.com/p/android/issues/detail?id=6066
|
* https://code.google.com/p/android/issues/detail?id=6066 */
|
||||||
long sumSkipped = 0L;
|
long sumSkipped = 0L;
|
||||||
while (sumSkipped < n) {
|
while (sumSkipped < n) {
|
||||||
long skipped = super.skip(n - sumSkipped);
|
long skipped = super.skip(n - sumSkipped);
|
||||||
@ -144,18 +158,25 @@ public class LwHttp {
|
|||||||
break; // EOF
|
break; // EOF
|
||||||
|
|
||||||
sumSkipped += 1;
|
sumSkipped += 1;
|
||||||
// was incremented by read()
|
/* was incremented by read() */
|
||||||
bytesRead -= 1;
|
bytesRead -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dbg)
|
||||||
|
log.debug("skip:{}/{} pos:{}", n, sumSkipped, bytesRead);
|
||||||
|
|
||||||
bytesRead += sumSkipped;
|
bytesRead += sumSkipped;
|
||||||
return sumSkipped;
|
return sumSkipped;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void reset() throws IOException {
|
public synchronized void reset() throws IOException {
|
||||||
|
if (dbg)
|
||||||
|
log.debug("reset");
|
||||||
|
|
||||||
if (marked >= 0)
|
if (marked >= 0)
|
||||||
bytesRead = marked;
|
bytesRead = marked;
|
||||||
// TODO could check if the mark is already invalid
|
/* TODO could check if the mark is already invalid */
|
||||||
super.reset();
|
super.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,6 +187,7 @@ public class LwHttp {
|
|||||||
|
|
||||||
int data = super.read();
|
int data = super.read();
|
||||||
|
|
||||||
|
if (data >= 0)
|
||||||
bytesRead += 1;
|
bytesRead += 1;
|
||||||
|
|
||||||
if (dbg)
|
if (dbg)
|
||||||
@ -223,12 +245,12 @@ public class LwHttp {
|
|||||||
|
|
||||||
int contentLength = -1;
|
int contentLength = -1;
|
||||||
|
|
||||||
// header may not be larger than BUFFER_SIZE for this to work
|
/* header may not be larger than BUFFER_SIZE for this to work */
|
||||||
for (; (pos < read) || ((read < BUFFER_SIZE) &&
|
for (; (pos < read) || ((read < BUFFER_SIZE) &&
|
||||||
(len = is.read(buf, read, BUFFER_SIZE - read)) >= 0); len = 0) {
|
(len = is.read(buf, read, BUFFER_SIZE - read)) >= 0); len = 0) {
|
||||||
|
|
||||||
read += len;
|
read += len;
|
||||||
// end of header lines
|
/* end of header lines */
|
||||||
while (end < read && (buf[end] != '\n'))
|
while (end < read && (buf[end] != '\n'))
|
||||||
end++;
|
end++;
|
||||||
|
|
||||||
@ -239,24 +261,26 @@ public class LwHttp {
|
|||||||
if (buf[end] != '\n')
|
if (buf[end] != '\n')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// empty line (header end)
|
/* empty line (header end) */
|
||||||
if (end - pos == 1) {
|
if (end - pos == 1) {
|
||||||
end += 1;
|
end += 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
// ignore until end of header
|
/* ignore until end of header */
|
||||||
} else if (first) {
|
} else if (first) {
|
||||||
first = false;
|
first = false;
|
||||||
// check only for OK ("HTTP/1.? ".length == 9)
|
/* check only for OK ("HTTP/1.? ".length == 9) */
|
||||||
if (!check(HEADER_HTTP_OK, buf, pos + 9, end))
|
if (!check(HEADER_HTTP_OK, buf, pos + 9, end))
|
||||||
ok = false;
|
ok = false;
|
||||||
|
|
||||||
} else if (check(HEADER_CONTENT_LENGTH, buf, pos, end)) {
|
} else if (check(HEADER_CONTENT_LENGTH, buf, pos, end)) {
|
||||||
// parse Content-Length
|
/* parse Content-Length */
|
||||||
contentLength = parseInt(buf, pos +
|
contentLength = parseInt(buf, pos +
|
||||||
HEADER_CONTENT_LENGTH.length + 2, end - 1);
|
HEADER_CONTENT_LENGTH.length + 2, end - 1);
|
||||||
|
} else if (check(HEADER_CONNECTION_CLOSE, buf, pos, end)) {
|
||||||
|
mMustClose = true;
|
||||||
}
|
}
|
||||||
//} else if (check(HEADER_CONTENT_TYPE, buf, pos, end)) {
|
//} else if (check(HEADER_CONTENT_TYPE, buf, pos, end)) {
|
||||||
// check that response contains the expected
|
// check that response contains the expected
|
||||||
@ -277,7 +301,7 @@ public class LwHttp {
|
|||||||
if (!ok)
|
if (!ok)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
// back to start of content
|
/* back to start of content */
|
||||||
is.reset();
|
is.reset();
|
||||||
is.mark(0);
|
is.mark(0);
|
||||||
is.skip(end);
|
is.skip(end);
|
||||||
@ -298,10 +322,10 @@ public class LwHttp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mSocket == null) {
|
if (mSocket == null) {
|
||||||
// might throw IOException
|
/* might throw IOException */
|
||||||
lwHttpConnect();
|
lwHttpConnect();
|
||||||
|
|
||||||
// TODO parse from header
|
/* TODO parse from header */
|
||||||
mMaxReq = RESPONSE_EXPECTED_LIVES;
|
mMaxReq = RESPONSE_EXPECTED_LIVES;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -324,7 +348,7 @@ public class LwHttp {
|
|||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.debug("recreate connection");
|
log.debug("recreate connection");
|
||||||
close();
|
close();
|
||||||
// might throw IOException
|
/* might throw IOException */
|
||||||
lwHttpConnect();
|
lwHttpConnect();
|
||||||
|
|
||||||
mCommandStream.write(request, 0, len);
|
mCommandStream.write(request, 0, len);
|
||||||
@ -348,6 +372,7 @@ public class LwHttp {
|
|||||||
close();
|
close();
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
mMustClose = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -379,18 +404,34 @@ public class LwHttp {
|
|||||||
mResponseStream.setCache(null);
|
mResponseStream.setCache(null);
|
||||||
|
|
||||||
if (!mResponseStream.finishedReading()) {
|
if (!mResponseStream.finishedReading()) {
|
||||||
|
// StringBuffer sb = new StringBuffer();
|
||||||
|
// try {
|
||||||
|
// int val;
|
||||||
|
// while ((val = mResponseStream.read()) >= 0)
|
||||||
|
// sb.append((char) val);
|
||||||
|
// } catch (IOException e) {
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
//log.debug("invalid buffer position {}", sb.toString());
|
||||||
log.debug("invalid buffer position");
|
log.debug("invalid buffer position");
|
||||||
close();
|
close();
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
close();
|
close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mMustClose) {
|
||||||
|
close();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// write (positive) integer to byte array
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** write (positive) integer to byte array */
|
||||||
public static int writeInt(int val, int pos, byte[] buf) {
|
public static int writeInt(int val, int pos, byte[] buf) {
|
||||||
if (val == 0) {
|
if (val == 0) {
|
||||||
buf[pos] = '0';
|
buf[pos] = '0';
|
||||||
@ -406,7 +447,7 @@ public class LwHttp {
|
|||||||
return pos + i;
|
return pos + i;
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse (positive) integer from byte array
|
/** parse (positive) integer from byte array */
|
||||||
protected static int parseInt(byte[] buf, int pos, int end) {
|
protected static int parseInt(byte[] buf, int pos, int end) {
|
||||||
int val = 0;
|
int val = 0;
|
||||||
for (; pos < end; pos++)
|
for (; pos < end; pos++)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user