You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2017/05/09 20:03:51 UTC

[03/22] httpcomponents-core git commit: Backported HTTPCORE-193, HTTPCORE-197 to 4.0.x branch

Backported HTTPCORE-193, HTTPCORE-197 to 4.0.x branch


git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpcore/branches/4.0.x@777111 13f79535-47bb-0310-9956-ffa450edef68


Project: http://git-wip-us.apache.org/repos/asf/httpcomponents-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/httpcomponents-core/commit/91ad309e
Tree: http://git-wip-us.apache.org/repos/asf/httpcomponents-core/tree/91ad309e
Diff: http://git-wip-us.apache.org/repos/asf/httpcomponents-core/diff/91ad309e

Branch: refs/heads/4.0.x
Commit: 91ad309e6c1dddac6be49475f5a00b414bd0d42b
Parents: 9043655
Author: Oleg Kalnichevski <ol...@apache.org>
Authored: Thu May 21 13:22:39 2009 +0000
Committer: Oleg Kalnichevski <ol...@apache.org>
Committed: Thu May 21 13:22:39 2009 +0000

----------------------------------------------------------------------
 RELEASE_NOTES.txt                               | 14 +++++++++
 .../http/impl/nio/codecs/ChunkDecoder.java      | 15 ++++++---
 .../http/impl/nio/reactor/SSLIOSession.java     | 22 +++++++++----
 .../http/impl/nio/codecs/TestChunkDecoder.java  | 33 ++++++++++++++++++++
 4 files changed, 74 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/91ad309e/RELEASE_NOTES.txt
----------------------------------------------------------------------
diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt
index 8403df0..88115e1 100644
--- a/RELEASE_NOTES.txt
+++ b/RELEASE_NOTES.txt
@@ -1,3 +1,17 @@
+Changes since 4.0
+-------------------
+
+* [HTTPCORE-197] Fixed bug causing the non-blocking ChunkDecoder to report some data stream as 
+  truncated under special conditions.
+  Contributed by Denis Rogov <denrogov at gmail.com> and Oleg Kalnichevski <olegk at apache.org> 
+
+* SSLIOSession#isAppOutputReady and SSLIOSession#isAppInputReady no longer ignore the application 
+  event mask causing I/O event notifications for unrequested type of events.  
+  Contributed by Oleg Kalnichevski <olegk at apache.org> 
+
+* [HTTPCORE-193] Fixed problem with SSLIOSession incorrectly handling of end-of-stream condition.  
+  Contributed by Asankha C. Perera <asankha at apache.org> and Oleg Kalnichevski <olegk at apache.org> 
+
 Release 4.0
 -------------------
 

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/91ad309e/httpcore-nio/src/main/java/org/apache/http/impl/nio/codecs/ChunkDecoder.java
----------------------------------------------------------------------
diff --git a/httpcore-nio/src/main/java/org/apache/http/impl/nio/codecs/ChunkDecoder.java b/httpcore-nio/src/main/java/org/apache/http/impl/nio/codecs/ChunkDecoder.java
index 9958d91..825e655 100644
--- a/httpcore-nio/src/main/java/org/apache/http/impl/nio/codecs/ChunkDecoder.java
+++ b/httpcore-nio/src/main/java/org/apache/http/impl/nio/codecs/ChunkDecoder.java
@@ -199,11 +199,18 @@ public class ChunkDecoder extends AbstractContentDecoder {
                 }
                 int maxLen = this.chunkSize - this.pos;
                 int len = this.buffer.read(dst, maxLen);
-                if (maxLen > 0 && len == 0 && this.endOfStream) {
-                    throw new MalformedChunkCodingException("Truncated chunk");
+                if (len > 0) {
+                    this.pos += len;
+                    totalRead += len;
+                } else {
+                    if (!this.buffer.hasData() && this.endOfStream) {
+                        this.state = COMPLETED;
+                        this.completed = true;
+                        throw new MalformedChunkCodingException("Truncated chunk "
+                                + "( expected size: " + this.chunkSize 
+                                + "; actual size: " + this.pos + ")");
+                    }
                 }
-                this.pos += len;
-                totalRead += len;
                 
                 if (this.pos == this.chunkSize) {
                     // At the end of the chunk

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/91ad309e/httpcore-nio/src/main/java/org/apache/http/impl/nio/reactor/SSLIOSession.java
----------------------------------------------------------------------
diff --git a/httpcore-nio/src/main/java/org/apache/http/impl/nio/reactor/SSLIOSession.java b/httpcore-nio/src/main/java/org/apache/http/impl/nio/reactor/SSLIOSession.java
index b4a42a7..35f4f52 100644
--- a/httpcore-nio/src/main/java/org/apache/http/impl/nio/reactor/SSLIOSession.java
+++ b/httpcore-nio/src/main/java/org/apache/http/impl/nio/reactor/SSLIOSession.java
@@ -36,6 +36,7 @@ import java.net.InetSocketAddress;
 import java.net.SocketAddress;
 import java.nio.ByteBuffer;
 import java.nio.channels.ByteChannel;
+import java.nio.channels.SelectionKey;
 
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLEngine;
@@ -72,6 +73,7 @@ public class SSLIOSession implements IOSession, SessionBufferStatus {
     private int appEventMask;
     private SessionBufferStatus appBufferStatus;
     
+    private boolean endOfStream;
     private volatile int status;
     
     public SSLIOSession(
@@ -163,6 +165,9 @@ public class SSLIOSession implements IOSession, SessionBufferStatus {
                 if (result.getStatus() == Status.CLOSED) {
                     this.status = CLOSED;
                 }
+                if (result.getStatus() == Status.BUFFER_UNDERFLOW && this.endOfStream) {
+                    this.status = CLOSED;
+                }
                 break;
             case NEED_TASK:
                 Runnable r = this.sslEngine.getDelegatedTask();
@@ -246,6 +251,9 @@ public class SSLIOSession implements IOSession, SessionBufferStatus {
             if (result.getStatus() == Status.CLOSED) {
                 this.status = CLOSED;
             }
+            if (result.getStatus() == Status.BUFFER_UNDERFLOW && this.endOfStream) {
+                this.status = CLOSED;
+            }
             if (result.getStatus() == Status.OK) {
                 decrypted = true;
             }
@@ -256,19 +264,21 @@ public class SSLIOSession implements IOSession, SessionBufferStatus {
     public synchronized boolean isAppInputReady() throws IOException {
         int bytesRead = receiveEncryptedData();
         if (bytesRead == -1) {
-            this.status = CLOSED;
+            this.endOfStream = true;
         }
         doHandshake();
         decryptData();
         // Some decrypted data is available or at the end of stream
-        return this.inPlain.position() > 0 || this.status != ACTIVE;
+        return (this.appEventMask & SelectionKey.OP_READ) > 0 
+            && (this.inPlain.position() > 0 || (this.endOfStream && this.status == ACTIVE));
     }
     
     /**
      * @throws IOException - not thrown currently
      */
     public synchronized boolean isAppOutputReady() throws IOException {
-        return this.status == ACTIVE
+        return (this.appEventMask & SelectionKey.OP_WRITE) > 0
+            && this.status == ACTIVE
             && this.sslEngine.getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING;
     }
 
@@ -324,10 +334,10 @@ public class SSLIOSession implements IOSession, SessionBufferStatus {
             this.inPlain.compact();
             return n; 
         } else {
-            if (this.status == ACTIVE) {
-                return 0;
-            } else {
+            if (this.endOfStream) {
                 return -1;
+            } else {
+                return 0;
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/91ad309e/httpcore-nio/src/test/java/org/apache/http/impl/nio/codecs/TestChunkDecoder.java
----------------------------------------------------------------------
diff --git a/httpcore-nio/src/test/java/org/apache/http/impl/nio/codecs/TestChunkDecoder.java b/httpcore-nio/src/test/java/org/apache/http/impl/nio/codecs/TestChunkDecoder.java
index 6301219..dedc9df 100644
--- a/httpcore-nio/src/test/java/org/apache/http/impl/nio/codecs/TestChunkDecoder.java
+++ b/httpcore-nio/src/test/java/org/apache/http/impl/nio/codecs/TestChunkDecoder.java
@@ -354,6 +354,39 @@ public class TestChunkDecoder extends TestCase {
         assertTrue(decoder.isCompleted());
     }
 
+    public void testReadingWitSmallBuffer() throws Exception {
+        String s = "10\r\n1234567890123456\r\n" +
+                "40\r\n12345678901234561234567890123456" +
+                "12345678901234561234567890123456\r\n0\r\n";
+        ReadableByteChannel channel = new ReadableByteChannelMockup(
+                new String[] {s}, "US-ASCII"); 
+        HttpParams params = new BasicHttpParams();
+    
+        SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, params); 
+        HttpTransportMetricsImpl metrics = new HttpTransportMetricsImpl();
+        ChunkDecoder decoder = new ChunkDecoder(channel, inbuf, metrics);
+        
+        ByteBuffer dst = ByteBuffer.allocate(1024); 
+        ByteBuffer tmp = ByteBuffer.allocate(10); 
+
+        int bytesRead = 0;
+        while (dst.hasRemaining() && !decoder.isCompleted()) {
+            int i = decoder.read(tmp);
+            if (i > 0) {
+                bytesRead += i;
+                tmp.flip();
+                dst.put(tmp);
+                tmp.compact();
+            }
+        }
+        
+        assertEquals(80, bytesRead);
+        assertEquals("12345678901234561234567890123456" +
+        		"12345678901234561234567890123456" +
+        		"1234567890123456", convert(dst));
+        assertTrue(decoder.isCompleted());
+    }
+
     public void testEndOfStreamConditionReadingFooters() throws Exception {
         String s = "10\r\n1234567890123456\r\n" +
                 "5\r\n12345\r\n5\r\n12345\r\n0\r\n";