hc-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ol...@apache.org
Subject svn commit: r1737930 - in /httpcomponents/httpcore/trunk/httpcore5/src: main/java/org/apache/hc/core5/http/impl/io/ main/java/org/apache/hc/core5/http/impl/nio/ test/java/org/apache/hc/core5/http/impl/io/ test/java/org/apache/hc/core5/http/impl/nio/
Date Wed, 06 Apr 2016 07:21:38 GMT
Author: olegk
Date: Wed Apr  6 07:21:38 2016
New Revision: 1737930

URL: http://svn.apache.org/viewvc?rev=1737930&view=rev
Log:
Support 64-bit chunk headers

Modified:
    httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/ChunkedInputStream.java
    httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ChunkDecoder.java
    httpcomponents/httpcore/trunk/httpcore5/src/test/java/org/apache/hc/core5/http/impl/io/TestChunkCoding.java
    httpcomponents/httpcore/trunk/httpcore5/src/test/java/org/apache/hc/core5/http/impl/nio/TestChunkDecoder.java

Modified: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/ChunkedInputStream.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/ChunkedInputStream.java?rev=1737930&r1=1737929&r2=1737930&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/ChunkedInputStream.java
(original)
+++ httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/ChunkedInputStream.java
Wed Apr  6 07:21:38 2016
@@ -76,10 +76,10 @@ public class ChunkedInputStream extends
     private int state;
 
     /** The chunk size */
-    private int chunkSize;
+    private long chunkSize;
 
     /** The current position within the current chunk */
-    private int pos;
+    private long pos;
 
     /** True if we've reached the end of stream */
     private boolean eof = false;
@@ -102,7 +102,7 @@ public class ChunkedInputStream extends
         super();
         this.buffer = Args.notNull(buffer, "Session input buffer");
         this.inputStream = Args.notNull(inputStream, "Input stream");
-        this.pos = 0;
+        this.pos = 0L;
         this.lineBuffer = new CharArrayBuffer(16);
         this.constraints = constraints != null ? constraints : MessageConstraints.DEFAULT;
         this.state = CHUNK_LEN;
@@ -121,7 +121,7 @@ public class ChunkedInputStream extends
     @Override
     public int available() throws IOException {
         final int len = this.buffer.length();
-        return Math.min(len, this.chunkSize - this.pos);
+        return (int) Math.min(len, this.chunkSize - this.pos);
     }
 
     /**
@@ -186,7 +186,7 @@ public class ChunkedInputStream extends
                 return -1;
             }
         }
-        final int bytesRead = buffer.read(b, off, Math.min(len, chunkSize - pos), inputStream);
+        final int bytesRead = buffer.read(b, off, (int) Math.min(len, chunkSize - pos), inputStream);
         if (bytesRead != -1) {
             pos += bytesRead;
             if (pos >= chunkSize) {
@@ -222,12 +222,12 @@ public class ChunkedInputStream extends
         }
         try {
             chunkSize = getChunkSize();
-            if (chunkSize < 0) {
+            if (chunkSize < 0L) {
                 throw new MalformedChunkCodingException("Negative chunk size");
             }
             state = CHUNK_DATA;
-            pos = 0;
-            if (chunkSize == 0) {
+            pos = 0L;
+            if (chunkSize == 0L) {
                 eof = true;
                 parseTrailerHeaders();
             }
@@ -242,7 +242,7 @@ public class ChunkedInputStream extends
      * comments after a semicolon. The line must end with a CRLF: "a3; some
      * comment\r\n" Positions the stream at the start of the next line.
      */
-    private int getChunkSize() throws IOException {
+    private long getChunkSize() throws IOException {
         final int st = this.state;
         switch (st) {
         case CHUNK_CRLF:
@@ -269,10 +269,11 @@ public class ChunkedInputStream extends
             if (separator < 0) {
                 separator = lineBuffer.length();
             }
+            final String s = this.lineBuffer.substringTrimmed(0, separator);
             try {
-                return Integer.parseInt(lineBuffer.substringTrimmed(0, separator), 16);
+                return Long.parseLong(s, 16);
             } catch (final NumberFormatException e) {
-                throw new MalformedChunkCodingException("Bad chunk header");
+                throw new MalformedChunkCodingException("Bad chunk header: " + s);
             }
         default:
             throw new IllegalStateException("Inconsistent codec state");

Modified: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ChunkDecoder.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ChunkDecoder.java?rev=1737930&r1=1737929&r2=1737930&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ChunkDecoder.java
(original)
+++ httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ChunkDecoder.java
Wed Apr  6 07:21:38 2016
@@ -65,8 +65,8 @@ public class ChunkDecoder extends Abstra
     private boolean endOfStream;
 
     private CharArrayBuffer lineBuf;
-    private int chunkSize;
-    private int pos;
+    private long chunkSize;
+    private long pos;
 
     private final MessageConstraints constraints;
     private final List<CharArrayBuffer> trailerBufs;
@@ -83,8 +83,8 @@ public class ChunkDecoder extends Abstra
             final BasicHttpTransportMetrics metrics) {
         super(channel, buffer, metrics);
         this.state = READ_CONTENT;
-        this.chunkSize = -1;
-        this.pos = 0;
+        this.chunkSize = -1L;
+        this.pos = 0L;
         this.endOfChunk = false;
         this.endOfStream = false;
         this.constraints = constraints != null ? constraints : MessageConstraints.DEFAULT;
@@ -129,13 +129,13 @@ public class ChunkDecoder extends Abstra
             if (separator < 0) {
                 separator = this.lineBuf.length();
             }
+            final String s = this.lineBuf.substringTrimmed(0, separator);
             try {
-                final String s = this.lineBuf.substringTrimmed(0, separator);
-                this.chunkSize = Integer.parseInt(s, 16);
+                this.chunkSize = Long.parseLong(s, 16);
             } catch (final NumberFormatException e) {
-                throw new MalformedChunkCodingException("Bad chunk header");
+                throw new MalformedChunkCodingException("Bad chunk header: " + s);
             }
-            this.pos = 0;
+            this.pos = 0L;
         } else if (this.endOfStream) {
             throw new ConnectionClosedException("Premature end of chunk coded message body:
" +
                     "closing chunk expected");
@@ -193,7 +193,7 @@ public class ChunkDecoder extends Abstra
         int totalRead = 0;
         while (this.state != COMPLETED) {
 
-            if (!this.buffer.hasData() || this.chunkSize == -1) {
+            if (!this.buffer.hasData() || this.chunkSize == -1L) {
                 final int bytesRead = fillBufferFromChannel();
                 if (bytesRead == -1) {
                     this.endOfStream = true;
@@ -203,21 +203,21 @@ public class ChunkDecoder extends Abstra
             switch (this.state) {
             case READ_CONTENT:
 
-                if (this.chunkSize == -1) {
+                if (this.chunkSize == -1L) {
                     readChunkHead();
-                    if (this.chunkSize == -1) {
+                    if (this.chunkSize == -1L) {
                         // Unable to read a chunk head
                         return totalRead;
                     }
-                    if (this.chunkSize == 0) {
+                    if (this.chunkSize == 0L) {
                         // Last chunk. Read footers
-                        this.chunkSize = -1;
+                        this.chunkSize = -1L;
                         this.state = READ_FOOTERS;
                         break;
                     }
                 }
-                final int maxLen = this.chunkSize - this.pos;
-                final int len = this.buffer.read(dst, maxLen);
+                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;
@@ -233,8 +233,8 @@ public class ChunkDecoder extends Abstra
 
                 if (this.pos == this.chunkSize) {
                     // At the end of the chunk
-                    this.chunkSize = -1;
-                    this.pos = 0;
+                    this.chunkSize = -1L;
+                    this.pos = 0L;
                     this.endOfChunk = true;
                     break;
                 }

Modified: httpcomponents/httpcore/trunk/httpcore5/src/test/java/org/apache/hc/core5/http/impl/io/TestChunkCoding.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5/src/test/java/org/apache/hc/core5/http/impl/io/TestChunkCoding.java?rev=1737930&r1=1737929&r2=1737930&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/test/java/org/apache/hc/core5/http/impl/io/TestChunkCoding.java
(original)
+++ httpcomponents/httpcore/trunk/httpcore5/src/test/java/org/apache/hc/core5/http/impl/io/TestChunkCoding.java
Wed Apr  6 07:21:38 2016
@@ -490,5 +490,23 @@ public class TestChunkCoding {
         in.close();
     }
 
+    // Test for when buffer is larger than chunk size
+    @Test
+    public void testHugeChunk() throws IOException {
+
+        final SessionInputBuffer inbuffer = new SessionInputBufferImpl(16);
+        final ByteArrayInputStream inputStream = new ByteArrayInputStream("1234567890abcdef\r\n01234567".getBytes(
+                StandardCharsets.ISO_8859_1));
+        final ChunkedInputStream in = new ChunkedInputStream(inbuffer, inputStream);
+
+        final ByteArrayOutputStream out = new ByteArrayOutputStream();
+        for (int i = 0; i < 8; ++i) {
+            out.write(in.read());
+        }
+
+        final String result = new String(out.toByteArray(), StandardCharsets.ISO_8859_1);
+        Assert.assertEquals("01234567", result);
+    }
+
 }
 

Modified: httpcomponents/httpcore/trunk/httpcore5/src/test/java/org/apache/hc/core5/http/impl/nio/TestChunkDecoder.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5/src/test/java/org/apache/hc/core5/http/impl/nio/TestChunkDecoder.java?rev=1737930&r1=1737929&r2=1737930&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/test/java/org/apache/hc/core5/http/impl/nio/TestChunkDecoder.java
(original)
+++ httpcomponents/httpcore/trunk/httpcore5/src/test/java/org/apache/hc/core5/http/impl/nio/TestChunkDecoder.java
Wed Apr  6 07:21:38 2016
@@ -584,4 +584,23 @@ public class TestChunkDecoder {
         decoder.read(null);
     }
 
+    @Test
+    public void testHugeChunk() throws Exception {
+        final String s = "1234567890abcdef\r\n0123456789abcdef";
+        final ReadableByteChannel channel = new ReadableByteChannelMock(new String[] {s},
StandardCharsets.US_ASCII);
+        final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, StandardCharsets.US_ASCII);
+        final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
+        final ChunkDecoder decoder = new ChunkDecoder(channel, inbuf, metrics);
+
+        final ByteBuffer dst = ByteBuffer.allocate(4);
+
+        int bytesRead = decoder.read(dst);
+        Assert.assertEquals(4, bytesRead);
+        Assert.assertEquals("0123", CodecTestUtils.convert(dst));
+        dst.clear();
+        bytesRead = decoder.read(dst);
+        Assert.assertEquals(4, bytesRead);
+        Assert.assertEquals("4567", CodecTestUtils.convert(dst));
+    }
+
 }



Mime
View raw message