in httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ChunkDecoder.java [185:270]
public int read(final ByteBuffer dst) throws IOException {
Args.notNull(dst, "Byte buffer");
if (this.state == State.COMPLETED) {
return -1;
}
int totalRead = 0;
while (this.state != State.COMPLETED) {
if (!this.buffer.hasData() || this.chunkSize == -1L) {
final int bytesRead = fillBufferFromChannel();
if (bytesRead == -1) {
this.endOfStream = true;
}
}
switch (this.state) {
case READ_CONTENT:
if (this.chunkSize == -1L) {
readChunkHead();
if (this.chunkSize == -1L) {
// Unable to read a chunk head
return totalRead;
}
if (this.chunkSize == 0L) {
// Last chunk. Read footers
this.chunkSize = -1L;
this.state = State.READ_FOOTERS;
break;
}
}
final long maxLen = this.chunkSize - this.pos;
final int len = this.buffer.read(dst, (int) Math.min(maxLen, Integer.MAX_VALUE));
if (len > 0) {
this.pos += len;
totalRead += len;
} else {
if (!this.buffer.hasData() && this.endOfStream) {
this.state = State.COMPLETED;
setCompleted();
throw new TruncatedChunkException(
"Truncated chunk (expected size: %d; actual size: %d)",
chunkSize, pos);
}
}
if (this.pos == this.chunkSize) {
// At the end of the chunk
this.chunkSize = -1L;
this.pos = 0L;
this.endOfChunk = true;
break;
}
return totalRead;
case READ_FOOTERS:
if (this.lineBuf == null) {
this.lineBuf = new CharArrayBuffer(32);
} else {
this.lineBuf.clear();
}
if (!this.buffer.readLine(this.lineBuf, this.endOfStream)) {
// Unable to read a footer
if (this.endOfStream) {
this.state = State.COMPLETED;
setCompleted();
}
return totalRead;
}
if (this.lineBuf.length() > 0) {
final int maxHeaderCount = this.http1Config.getMaxHeaderCount();
if (maxHeaderCount > 0 && trailerBufs.size() >= maxHeaderCount) {
throw new MessageConstraintException("Maximum header count exceeded");
}
parseHeader();
} else {
this.state = State.COMPLETED;
setCompleted();
processFooters();
}
break;
}
}
return totalRead;
}