Author: violetagg Date: Fri Oct 28 11:18:05 2016 New Revision: 1767004 URL: http://svn.apache.org/viewvc?rev=1767004&view=rev Log: Introduce a new method o.a.coyote.InputBuffer.doRead(ApplicationBufferHandler)
Modified: tomcat/tc8.5.x/trunk/ (props changed) tomcat/tc8.5.x/trunk/java/org/apache/catalina/connector/InputBuffer.java tomcat/tc8.5.x/trunk/java/org/apache/coyote/InputBuffer.java tomcat/tc8.5.x/trunk/java/org/apache/coyote/Request.java tomcat/tc8.5.x/trunk/java/org/apache/coyote/ajp/AjpProcessor.java tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/Http11InputBuffer.java tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/filters/BufferedInputFilter.java tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/filters/IdentityInputFilter.java tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/filters/SavedRequestInputFilter.java tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/filters/VoidInputFilter.java tomcat/tc8.5.x/trunk/java/org/apache/coyote/http2/Stream.java tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/net/ApplicationBufferHandler.java Propchange: tomcat/tc8.5.x/trunk/ ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Fri Oct 28 11:18:05 2016 @@ -1 +1 @@ -/tomcat/trunk:1734785,1734799,1734845,1734928,1735041,1735044,1735480,1735577,1735597,1735599-1735600,1735615,1736145,1736162,1736209,1736280,1736297,1736299,1736489,1736646,1736703,1736836,1736849,1737104-1737105,1737112,1737117,1737119-1737120,1737155,1737157,1737192,1737280,1737339,1737632,1737664,1737715,1737748,1737785,1737834,1737860,1737903,1737959,1738005,1738007,1738014-1738015,1738018,1738022,1738039,1738043,1738059-1738060,1738147,1738149,1738174-1738175,1738261,1738589,1738623-1738625,1738643,1738816,1738850,1738855,1738946-1738948,1738953-1738954,1738979,1738982,1739079-1739081,1739087,1739113,1739153,1739172,1739176,1739191,1739474,1739726,1739762,1739775,1739814,1739817-1739818,1739975,1740131,1740324,1740465,1740495,1740508-1740509,1740520,1740535,1740707,1740803,1740810,1740969,1740980,1740991,1740997,1741015,1741033,1741036,1741058,1741060,1741080,1741147,1741159,1741164,1741173,1741181,1741190,1741197,1741202,1741208,1741213,1741221,1741225,1741232,1741409,1741501 ,1741677,1741892,1741896,1741984,1742023,1742042,1742071,1742090,1742093,1742101,1742105,1742111,1742139,1742146,1742148,1742166,1742181,1742184,1742187,1742246,1742248-1742251,1742263-1742264,1742268,1742276,1742369,1742387,1742448,1742509-1742512,1742917,1742919,1742933,1742975-1742976,1742984,1742986,1743019,1743115,1743117,1743124-1743125,1743134,1743425,1743554,1743679,1743696-1743698,1743700-1743701,1744058,1744064-1744065,1744125,1744194,1744229,1744270,1744323,1744432,1744684,1744697,1744705,1744713,1744760,1744786,1745083,1745142-1745143,1745145,1745177,1745179-1745180,1745227,1745248,1745254,1745337,1745467,1745473,1745576,1745735,1745744,1746304,1746306-1746307,1746319,1746327,1746338,1746340-1746341,1746344,1746427,1746441,1746473,1746490,1746492,1746495-1746496,1746499-1746501,1746503-1746507,1746509,1746549,1746551,1746554,1746556,1746558,1746584,1746620,1746649,1746724,1746939,1746989,1747014,1747028,1747035,1747210,1747225,1747234,1747253,1747404,1747506,1747536,1747 924,1747980,1747993,1748001,1748253,1748452,1748547,1748629,1748676,1748715,1749287,1749296,1749328,1749373,1749465,1749506,1749508,1749665-1749666,1749763,1749865-1749866,1749898,1749978,1749980,1750011,1750015,1750056,1750480,1750617,1750634,1750692,1750697,1750700,1750703,1750707,1750714,1750718,1750723,1750774,1750899,1750975,1750995,1751061,1751097,1751173,1751438,1751447,1751463,1751702,1752212,1752737,1752745,1753078,1753080,1753358,1753363,1754111,1754140-1754141,1754281,1754310,1754445,1754467,1754494,1754496,1754528,1754532-1754533,1754613,1754714,1754874,1754941,1754944,1754950-1754951,1755005,1755007,1755009,1755132,1755180-1755181,1755185,1755190,1755204-1755206,1755208,1755214,1755224,1755227,1755230,1755629,1755646-1755647,1755650,1755653,1755675,1755680,1755683,1755693,1755717,1755731-1755737,1755812,1755828,1755884,1755890,1755918-1755919,1755942,1755958,1755960,1755970,1755993,1756013,1756019,1756039,1756056,1756083-1756114,1756175,1756288-1756289,1756408-1756410,1 756778,1756798,1756878,1756898,1756939,1757123-1757124,1757126,1757128,1757132-1757133,1757136,1757145,1757167-1757168,1757175,1757180,1757182,1757195,1757271,1757278,1757347,1757353-1757354,1757363,1757374,1757399,1757406,1757408,1757485,1757495,1757499,1757527,1757578,1757684,1757722,1757727,1757790,1757799,1757813,1757853,1757883,1757903,1757976,1757997,1758000,1758058,1758072-1758075,1758078-1758079,1758223,1758257,1758261,1758276,1758292,1758369,1758378-1758383,1758421,1758423,1758425-1758427,1758430,1758443,1758448,1758459,1758483,1758486-1758487,1758499,1758525,1758556,1758580,1758582,1758584,1758588,1758842,1759019,1759212,1759224,1759227,1759252,1759274,1759513-1759516,1759611,1759757,1759785-1759790,1760005,1760022,1760109-1760110,1760135,1760200-1760201,1760227,1760300,1760397,1760446,1760454,1760640,1760648,1761057,1761422,1761491,1761498,1761500-1761501,1761550,1761553,1761572,1761574,1761625-1761626,1761628,1761682,1761740,1761752,1762051-1762053,1762123,1762168,176217 2,1762182,1762201-1762202,1762204,1762208,1762288,1762296,1762324,1762348,1762353,1762362,1762374,1762492,1762503,1762505,1762541,1762608,1762710,1762753,1762766,1762769,1762944,1762947,1762953,1763167,1763179,1763232,1763259,1763271-1763272,1763276-1763277,1763319-1763320,1763370,1763372,1763375,1763377,1763393,1763412,1763430,1763450,1763462,1763511-1763512,1763516,1763518,1763520,1763529,1763574,1763634-1763635,1763718,1763786,1763798-1763799,1764083,1764425,1764646,1764648-1764649,1764659,1764663,1764682,1764862,1764866-1764867,1764870,1764897,1765133,1765299,1765358,1765439,1765447,1765495,1765502,1765569-1765571,1765579,1765582,1765589-1765590,1765794,1765801,1765813,1765815,1766276,1766514,1766533,1766535,1766664,1766675,1766698 +/tomcat/trunk:1734785,1734799,1734845,1734928,1735041,1735044,1735480,1735577,1735597,1735599-1735600,1735615,1736145,1736162,1736209,1736280,1736297,1736299,1736489,1736646,1736703,1736836,1736849,1737104-1737105,1737112,1737117,1737119-1737120,1737155,1737157,1737192,1737280,1737339,1737632,1737664,1737715,1737748,1737785,1737834,1737860,1737903,1737959,1738005,1738007,1738014-1738015,1738018,1738022,1738039,1738043,1738059-1738060,1738147,1738149,1738174-1738175,1738261,1738589,1738623-1738625,1738643,1738816,1738850,1738855,1738946-1738948,1738953-1738954,1738979,1738982,1739079-1739081,1739087,1739113,1739153,1739172,1739176,1739191,1739474,1739726,1739762,1739775,1739814,1739817-1739818,1739975,1740131,1740324,1740465,1740495,1740508-1740509,1740520,1740535,1740707,1740803,1740810,1740969,1740980,1740991,1740997,1741015,1741033,1741036,1741058,1741060,1741080,1741147,1741159,1741164,1741173,1741181,1741190,1741197,1741202,1741208,1741213,1741221,1741225,1741232,1741409,1741501 ,1741677,1741892,1741896,1741984,1742023,1742042,1742071,1742090,1742093,1742101,1742105,1742111,1742139,1742146,1742148,1742166,1742181,1742184,1742187,1742246,1742248-1742251,1742263-1742264,1742268,1742276,1742369,1742387,1742448,1742509-1742512,1742917,1742919,1742933,1742975-1742976,1742984,1742986,1743019,1743115,1743117,1743124-1743125,1743134,1743425,1743554,1743679,1743696-1743698,1743700-1743701,1744058,1744064-1744065,1744125,1744194,1744229,1744270,1744323,1744432,1744684,1744697,1744705,1744713,1744760,1744786,1745083,1745142-1745143,1745145,1745177,1745179-1745180,1745227,1745248,1745254,1745337,1745467,1745473,1745576,1745735,1745744,1746304,1746306-1746307,1746319,1746327,1746338,1746340-1746341,1746344,1746427,1746441,1746473,1746490,1746492,1746495-1746496,1746499-1746501,1746503-1746507,1746509,1746549,1746551,1746554,1746556,1746558,1746584,1746620,1746649,1746724,1746939,1746989,1747014,1747028,1747035,1747210,1747225,1747234,1747253,1747404,1747506,1747536,1747 924,1747980,1747993,1748001,1748253,1748452,1748547,1748629,1748676,1748715,1749287,1749296,1749328,1749373,1749465,1749506,1749508,1749665-1749666,1749763,1749865-1749866,1749898,1749978,1749980,1750011,1750015,1750056,1750480,1750617,1750634,1750692,1750697,1750700,1750703,1750707,1750714,1750718,1750723,1750774,1750899,1750975,1750995,1751061,1751097,1751173,1751438,1751447,1751463,1751702,1752212,1752737,1752745,1753078,1753080,1753358,1753363,1754111,1754140-1754141,1754281,1754310,1754445,1754467,1754494,1754496,1754528,1754532-1754533,1754613,1754714,1754874,1754941,1754944,1754950-1754951,1755005,1755007,1755009,1755132,1755180-1755181,1755185,1755190,1755204-1755206,1755208,1755214,1755224,1755227,1755230,1755629,1755646-1755647,1755650,1755653,1755675,1755680,1755683,1755693,1755717,1755731-1755737,1755812,1755828,1755884,1755890,1755918-1755919,1755942,1755958,1755960,1755970,1755993,1756013,1756019,1756039,1756056,1756083-1756114,1756175,1756288-1756289,1756408-1756410,1 756778,1756798,1756878,1756898,1756939,1757123-1757124,1757126,1757128,1757132-1757133,1757136,1757145,1757167-1757168,1757175,1757180,1757182,1757195,1757271,1757278,1757347,1757353-1757354,1757363,1757374,1757399,1757406,1757408,1757485,1757495,1757499,1757527,1757578,1757684,1757722,1757727,1757790,1757799,1757813,1757853,1757883,1757903,1757976,1757997,1758000,1758058,1758072-1758075,1758078-1758079,1758223,1758257,1758261,1758276,1758292,1758369,1758378-1758383,1758421,1758423,1758425-1758427,1758430,1758443,1758448,1758459,1758483,1758486-1758487,1758499,1758525,1758556,1758580,1758582,1758584,1758588,1758842,1759019,1759212,1759224,1759227,1759252,1759274,1759513-1759516,1759611,1759757,1759785-1759790,1760005,1760022,1760109-1760110,1760135,1760200-1760201,1760227,1760300,1760397,1760446,1760454,1760640,1760648,1761057,1761422,1761491,1761498,1761500-1761501,1761550,1761553,1761572,1761574,1761625-1761626,1761628,1761682,1761740,1761752,1762051-1762053,1762123,1762168,176217 2,1762182,1762201-1762202,1762204,1762208,1762288,1762296,1762324,1762348,1762353,1762362,1762374,1762492,1762503,1762505,1762541,1762608,1762710,1762753,1762766,1762769,1762944,1762947,1762953,1763167,1763179,1763232,1763259,1763271-1763272,1763276-1763277,1763319-1763320,1763370,1763372,1763375,1763377,1763393,1763412,1763430,1763450,1763462,1763511-1763512,1763516,1763518,1763520,1763529,1763559,1763574,1763634-1763635,1763718,1763786,1763798-1763799,1764083,1764425,1764646,1764648-1764649,1764659,1764663,1764682,1764862,1764866-1764867,1764870,1764897,1765133,1765299,1765358,1765439,1765447,1765495,1765502,1765569-1765571,1765579,1765582,1765589-1765590,1765794,1765801,1765813,1765815,1766276,1766514,1766533,1766535,1766664,1766675,1766698 Modified: tomcat/tc8.5.x/trunk/java/org/apache/catalina/connector/InputBuffer.java URL: http://svn.apache.org/viewvc/tomcat/tc8.5.x/trunk/java/org/apache/catalina/connector/InputBuffer.java?rev=1767004&r1=1767003&r2=1767004&view=diff ============================================================================== --- tomcat/tc8.5.x/trunk/java/org/apache/catalina/connector/InputBuffer.java (original) +++ tomcat/tc8.5.x/trunk/java/org/apache/catalina/connector/InputBuffer.java Fri Oct 28 11:18:05 2016 @@ -36,6 +36,7 @@ import org.apache.tomcat.util.buf.B2CCon import org.apache.tomcat.util.buf.ByteChunk; import org.apache.tomcat.util.buf.CharChunk; import org.apache.tomcat.util.collections.SynchronizedStack; +import org.apache.tomcat.util.net.ApplicationBufferHandler; import org.apache.tomcat.util.res.StringManager; /** @@ -48,7 +49,7 @@ import org.apache.tomcat.util.res.String */ public class InputBuffer extends Reader implements ByteChunk.ByteInputChannel, CharChunk.CharInputChannel, - CharChunk.CharOutputChannel { + CharChunk.CharOutputChannel, ApplicationBufferHandler { /** * The string manager for this package. @@ -75,6 +76,7 @@ public class InputBuffer extends Reader * The byte buffer. */ private final ByteChunk bb; + private ByteBuffer tempRead; /** @@ -146,6 +148,8 @@ public class InputBuffer extends Reader public InputBuffer(int size) { this.size = size; + tempRead = ByteBuffer.allocate(size); + tempRead.flip(); bb = new ByteChunk(size); bb.setLimit(size); bb.setByteInputChannel(this); @@ -314,8 +318,10 @@ public class InputBuffer extends Reader state = BYTE_STATE; } - int result = coyoteRequest.doRead(bb); - + int result = coyoteRequest.doRead(this); + bb.setBytes(tempRead.array(), tempRead.arrayOffset() + tempRead.position(), + tempRead.remaining()); + tempRead.position(0).limit(0); return result; } @@ -594,4 +600,22 @@ public class InputBuffer extends Reader } } + + + @Override + public void setByteBuffer(ByteBuffer buffer) { + tempRead = buffer; + } + + + @Override + public ByteBuffer getByteBuffer() { + return tempRead; + } + + + @Override + public void expand(int size) { + // no-op + } } Modified: tomcat/tc8.5.x/trunk/java/org/apache/coyote/InputBuffer.java URL: http://svn.apache.org/viewvc/tomcat/tc8.5.x/trunk/java/org/apache/coyote/InputBuffer.java?rev=1767004&r1=1767003&r2=1767004&view=diff ============================================================================== --- tomcat/tc8.5.x/trunk/java/org/apache/coyote/InputBuffer.java (original) +++ tomcat/tc8.5.x/trunk/java/org/apache/coyote/InputBuffer.java Fri Oct 28 11:18:05 2016 @@ -19,6 +19,7 @@ package org.apache.coyote; import java.io.IOException; import org.apache.tomcat.util.buf.ByteChunk; +import org.apache.tomcat.util.net.ApplicationBufferHandler; /** * This class is only for internal use in the protocol implementation. All @@ -40,4 +41,20 @@ public interface InputBuffer { * @throws IOException If an I/O error occurs reading from the input stream */ public int doRead(ByteChunk chunk) throws IOException; + + /** + * Read from the input stream into the ByteBuffer provided by the + * ApplicaitonBufferHandler. + * IMPORTANT: the current model assumes that the protocol will 'own' the + * ByteBuffer and return a pointer to it. + * + * @param handler ApplicaitonBufferHandler that provides the buffer to read + * data into. + * + * @return The number of bytes that have been added to the buffer or -1 for + * end of stream + * + * @throws IOException If an I/O error occurs reading from the input stream + */ + public int doRead(ApplicationBufferHandler handler) throws IOException; } Modified: tomcat/tc8.5.x/trunk/java/org/apache/coyote/Request.java URL: http://svn.apache.org/viewvc/tomcat/tc8.5.x/trunk/java/org/apache/coyote/Request.java?rev=1767004&r1=1767003&r2=1767004&view=diff ============================================================================== --- tomcat/tc8.5.x/trunk/java/org/apache/coyote/Request.java (original) +++ tomcat/tc8.5.x/trunk/java/org/apache/coyote/Request.java Fri Oct 28 11:18:05 2016 @@ -29,6 +29,7 @@ import org.apache.tomcat.util.buf.UDecod import org.apache.tomcat.util.http.MimeHeaders; import org.apache.tomcat.util.http.Parameters; import org.apache.tomcat.util.http.ServerCookies; +import org.apache.tomcat.util.net.ApplicationBufferHandler; import org.apache.tomcat.util.res.StringManager; /** @@ -512,6 +513,31 @@ public final class Request { if (n > 0) { bytesRead+=n; } + return n; + } + + + /** + * Read data from the input buffer and put it into ApplicationBufferHandler. + * + * The buffer is owned by the protocol implementation - it will be reused on + * the next read. The Adapter must either process the data in place or copy + * it to a separate buffer if it needs to hold it. In most cases this is + * done during byte->char conversions or via InputStream. Unlike + * InputStream, this interface allows the app to process data in place, + * without copy. + * + * @param handler The destination to which to copy the data + * + * @return The number of bytes copied + * + * @throws IOException If an I/O error occurs during the copy + */ + public int doRead(ApplicationBufferHandler handler) throws IOException { + int n = inputBuffer.doRead(handler); + if (n > 0) { + bytesRead+=n; + } return n; } Modified: tomcat/tc8.5.x/trunk/java/org/apache/coyote/ajp/AjpProcessor.java URL: http://svn.apache.org/viewvc/tomcat/tc8.5.x/trunk/java/org/apache/coyote/ajp/AjpProcessor.java?rev=1767004&r1=1767003&r2=1767004&view=diff ============================================================================== --- tomcat/tc8.5.x/trunk/java/org/apache/coyote/ajp/AjpProcessor.java (original) +++ tomcat/tc8.5.x/trunk/java/org/apache/coyote/ajp/AjpProcessor.java Fri Oct 28 11:18:05 2016 @@ -43,6 +43,7 @@ import org.apache.tomcat.util.buf.Messag import org.apache.tomcat.util.http.MimeHeaders; import org.apache.tomcat.util.net.AbstractEndpoint; import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState; +import org.apache.tomcat.util.net.ApplicationBufferHandler; import org.apache.tomcat.util.net.SSLSupport; import org.apache.tomcat.util.net.SocketWrapperBase; import org.apache.tomcat.util.res.StringManager; @@ -1395,6 +1396,23 @@ public class AjpProcessor extends Abstra empty = true; return chunk.getLength(); } + + @Override + public int doRead(ApplicationBufferHandler handler) throws IOException { + + if (endOfStream) { + return -1; + } + if (empty) { + if (!refillReadBuffer(true)) { + return -1; + } + } + ByteChunk bc = bodyBytes.getByteChunk(); + handler.setByteBuffer(ByteBuffer.wrap(bc.getBuffer(), bc.getStart(), bc.getLength())); + empty = true; + return handler.getByteBuffer().remaining(); + } } Modified: tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/Http11InputBuffer.java URL: http://svn.apache.org/viewvc/tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/Http11InputBuffer.java?rev=1767004&r1=1767003&r2=1767004&view=diff ============================================================================== --- tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/Http11InputBuffer.java (original) +++ tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/Http11InputBuffer.java Fri Oct 28 11:18:05 2016 @@ -292,6 +292,16 @@ public class Http11InputBuffer implement } + @Override + public int doRead(ApplicationBufferHandler handler) throws IOException { + + if (lastActiveFilter == -1) + return inputStreamInputBuffer.doRead(handler); + else + return activeFilters[lastActiveFilter].doRead(handler); + + } + // ------------------------------------------------------- Protected Methods @@ -1073,6 +1083,29 @@ public class Http11InputBuffer implement return length; } + + @Override + public int doRead(ApplicationBufferHandler handler) throws IOException { + + if (byteBuffer.position() >= byteBuffer.limit()) { + // The application is reading the HTTP request body which is + // always a blocking operation. + if (!fill(true)) + return -1; + } + + int length = byteBuffer.remaining(); + handler.setByteBuffer(byteBuffer.duplicate()); + byteBuffer.position(byteBuffer.limit()); + + return length; + } + } + + + @Override + public void setByteBuffer(ByteBuffer buffer) { + byteBuffer = buffer; } Modified: tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/filters/BufferedInputFilter.java URL: http://svn.apache.org/viewvc/tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/filters/BufferedInputFilter.java?rev=1767004&r1=1767003&r2=1767004&view=diff ============================================================================== --- tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/filters/BufferedInputFilter.java (original) +++ tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/filters/BufferedInputFilter.java Fri Oct 28 11:18:05 2016 @@ -26,12 +26,13 @@ import org.apache.coyote.InputBuffer; import org.apache.coyote.Request; import org.apache.coyote.http11.InputFilter; import org.apache.tomcat.util.buf.ByteChunk; +import org.apache.tomcat.util.net.ApplicationBufferHandler; /** * Input filter responsible for reading and buffering the request body, so that * it does not interfere with client SSL handshake messages. */ -public class BufferedInputFilter implements InputFilter { +public class BufferedInputFilter implements InputFilter, ApplicationBufferHandler { // -------------------------------------------------------------- Constants @@ -42,7 +43,7 @@ public class BufferedInputFilter impleme // ----------------------------------------------------- Instance Variables private ByteBuffer buffered; - private final ByteChunk tempRead = new ByteChunk(1024); + private ByteBuffer tempRead; private InputBuffer buffer; private boolean hasRead = false; @@ -82,11 +83,11 @@ public class BufferedInputFilter impleme public void setRequest(Request request) { // save off the Request body try { - while (buffer.doRead(tempRead) >= 0) { + while (buffer.doRead(this) >= 0) { buffered.mark().position(buffered.limit()).limit(buffered.capacity()); - buffered.put(tempRead.getBytes(), tempRead.getStart(), tempRead.getLength()); + buffered.put(tempRead); buffered.limit(buffered.position()).reset(); - tempRead.recycle(); + tempRead = null; } } catch(IOException | BufferOverflowException ioe) { // No need for i18n - this isn't going to get logged anywhere @@ -110,6 +111,20 @@ public class BufferedInputFilter impleme return chunk.getLength(); } + /** + * Fills the given ByteBuffer with the buffered request body. + */ + @Override + public int doRead(ApplicationBufferHandler handler) throws IOException { + if (isFinished()) { + return -1; + } + + handler.setByteBuffer(buffered); + hasRead = true; + return buffered.remaining(); + } + @Override public void setBuffer(InputBuffer buffer) { this.buffer = buffer; @@ -124,7 +139,6 @@ public class BufferedInputFilter impleme buffered.position(0).limit(0); } } - tempRead.recycle(); hasRead = false; buffer = null; } @@ -149,4 +163,22 @@ public class BufferedInputFilter impleme public boolean isFinished() { return hasRead || buffered.remaining() <= 0; } + + + @Override + public void setByteBuffer(ByteBuffer buffer) { + tempRead = buffer; + } + + + @Override + public ByteBuffer getByteBuffer() { + return tempRead; + } + + + @Override + public void expand(int size) { + // no-op + } } Modified: tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java URL: http://svn.apache.org/viewvc/tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java?rev=1767004&r1=1767003&r2=1767004&view=diff ============================================================================== --- tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java (original) +++ tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java Fri Oct 28 11:18:05 2016 @@ -18,6 +18,7 @@ package org.apache.coyote.http11.filters import java.io.EOFException; import java.io.IOException; +import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.util.Locale; import java.util.Set; @@ -30,6 +31,7 @@ import org.apache.tomcat.util.buf.ByteCh import org.apache.tomcat.util.buf.HexUtils; import org.apache.tomcat.util.buf.MessageBytes; import org.apache.tomcat.util.http.MimeHeaders; +import org.apache.tomcat.util.net.ApplicationBufferHandler; import org.apache.tomcat.util.res.StringManager; /** @@ -38,7 +40,7 @@ import org.apache.tomcat.util.res.String * * @author Remy Maucherat */ -public class ChunkedInputFilter implements InputFilter { +public class ChunkedInputFilter implements InputFilter, ApplicationBufferHandler { private static final StringManager sm = StringManager.getManager( ChunkedInputFilter.class.getPackage().getName()); @@ -73,27 +75,9 @@ public class ChunkedInputFilter implemen /** - * Position in the buffer. - */ - protected int pos = 0; - - - /** - * Last valid byte in the buffer. - */ - protected int lastValid = 0; - - - /** - * Read bytes buffer. - */ - protected byte[] buf = null; - - - /** * Byte chunk used to read bytes. */ - protected final ByteChunk readChunk = new ByteChunk(); + protected ByteBuffer readChunk; /** @@ -189,24 +173,83 @@ public class ChunkedInputFilter implemen int result = 0; - if (pos >= lastValid) { + if (readChunk == null || readChunk.position() >= readChunk.limit()) { + if (readBytes() < 0) { + throwIOException(sm.getString("chunkedInputFilter.eos")); + } + } + + if (remaining > readChunk.remaining()) { + result = readChunk.remaining(); + remaining = remaining - result; + chunk.setBytes(readChunk.array(), readChunk.arrayOffset() + readChunk.position(), result); + readChunk.position(readChunk.limit()); + } else { + result = remaining; + chunk.setBytes(readChunk.array(), readChunk.arrayOffset() + readChunk.position(), remaining); + readChunk.position(readChunk.position() + remaining); + remaining = 0; + //we need a CRLF + if ((readChunk.position() + 1) >= readChunk.limit()) { + //if we call parseCRLF we overrun the buffer here + //so we defer it to the next call BZ 11117 + needCRLFParse = true; + } else { + parseCRLF(false); //parse the CRLF immediately + } + } + + return result; + } + + @Override + public int doRead(ApplicationBufferHandler handler) throws IOException { + if (endChunk) { + return -1; + } + + checkError(); + + if(needCRLFParse) { + needCRLFParse = false; + parseCRLF(false); + } + + if (remaining <= 0) { + if (!parseChunkHeader()) { + throwIOException(sm.getString("chunkedInputFilter.invalidHeader")); + } + if (endChunk) { + parseEndChunk(); + return -1; + } + } + + int result = 0; + + if (readChunk == null || readChunk.position() >= readChunk.limit()) { if (readBytes() < 0) { throwIOException(sm.getString("chunkedInputFilter.eos")); } } - if (remaining > (lastValid - pos)) { - result = lastValid - pos; + if (remaining > readChunk.remaining()) { + result = readChunk.remaining(); remaining = remaining - result; - chunk.setBytes(buf, pos, result); - pos = lastValid; + if (readChunk != handler.getByteBuffer()) { + handler.setByteBuffer(readChunk.duplicate()); + } + readChunk.position(readChunk.limit()); } else { result = remaining; - chunk.setBytes(buf, pos, remaining); - pos = pos + remaining; + if (readChunk != handler.getByteBuffer()) { + handler.setByteBuffer(readChunk.duplicate()); + handler.getByteBuffer().limit(readChunk.position() + remaining); + } + readChunk.position(readChunk.position() + remaining); remaining = 0; //we need a CRLF - if ((pos+1) >= lastValid) { + if ((readChunk.position() + 1) >= readChunk.limit()) { //if we call parseCRLF we overrun the buffer here //so we defer it to the next call BZ 11117 needCRLFParse = true; @@ -238,7 +281,7 @@ public class ChunkedInputFilter implemen long swallowed = 0; int read = 0; // Consume extra bytes : parse the stream until the end chunk is found - while ((read = doRead(readChunk)) >= 0) { + while ((read = doRead(this)) >= 0) { swallowed += read; if (maxSwallowSize > -1 && swallowed > maxSwallowSize) { throwIOException(sm.getString("inputFilter.maxSwallow")); @@ -246,7 +289,7 @@ public class ChunkedInputFilter implemen } // Return the number of extra bytes which were consumed - return lastValid - pos; + return readChunk.remaining(); } @@ -255,7 +298,7 @@ public class ChunkedInputFilter implemen */ @Override public int available() { - return lastValid - pos; + return readChunk != null ? readChunk.remaining() : 0; } @@ -274,8 +317,9 @@ public class ChunkedInputFilter implemen @Override public void recycle() { remaining = 0; - pos = 0; - lastValid = 0; + if (readChunk != null) { + readChunk.position(0).limit(0); + } endChunk = false; needCRLFParse = false; trailingHeaders.recycle(); @@ -309,13 +353,7 @@ public class ChunkedInputFilter implemen * @throws IOException Read error */ protected int readBytes() throws IOException { - - int nRead = buffer.doRead(readChunk); - pos = readChunk.getStart(); - lastValid = pos + nRead; - buf = readChunk.getBytes(); - - return nRead; + return buffer.doRead(this); } @@ -342,15 +380,16 @@ public class ChunkedInputFilter implemen while (!eol) { - if (pos >= lastValid) { + if (readChunk == null || readChunk.position() >= readChunk.limit()) { if (readBytes() <= 0) return false; } - if (buf[pos] == Constants.CR || buf[pos] == Constants.LF) { + byte chr = readChunk.get(readChunk.position()); + if (chr == Constants.CR || chr == Constants.LF) { parseCRLF(false); eol = true; - } else if (buf[pos] == Constants.SEMI_COLON && !extension) { + } else if (chr == Constants.SEMI_COLON && !extension) { // First semi-colon marks the start of the extension. Further // semi-colons may appear to separate multiple chunk-extensions. // These need to be processed as part of parsing the extensions. @@ -358,7 +397,7 @@ public class ChunkedInputFilter implemen extensionSize++; } else if (!extension) { //don't read data after the trailer - int charValue = HexUtils.getDec(buf[pos]); + int charValue = HexUtils.getDec(chr); if (charValue != -1 && readDigit < 8) { readDigit++; result = (result << 4) | charValue; @@ -379,7 +418,7 @@ public class ChunkedInputFilter implemen // Parsing the CRLF increments pos if (!eol) { - pos++; + readChunk.position(readChunk.position() + 1); } } @@ -410,18 +449,19 @@ public class ChunkedInputFilter implemen boolean crfound = false; while (!eol) { - if (pos >= lastValid) { + if (readChunk == null || readChunk.position() >= readChunk.limit()) { if (readBytes() <= 0) { throwIOException(sm.getString("chunkedInputFilter.invalidCrlfNoData")); } } - if (buf[pos] == Constants.CR) { + byte chr = readChunk.get(readChunk.position()); + if (chr == Constants.CR) { if (crfound) { throwIOException(sm.getString("chunkedInputFilter.invalidCrlfCRCR")); } crfound = true; - } else if (buf[pos] == Constants.LF) { + } else if (chr == Constants.LF) { if (!tolerant && !crfound) { throwIOException(sm.getString("chunkedInputFilter.invalidCrlfNoCR")); } @@ -430,7 +470,7 @@ public class ChunkedInputFilter implemen throwIOException(sm.getString("chunkedInputFilter.invalidCrlf")); } - pos++; + readChunk.position(readChunk.position() + 1); } } @@ -454,13 +494,13 @@ public class ChunkedInputFilter implemen byte chr = 0; // Read new bytes if needed - if (pos >= lastValid) { + if (readChunk == null || readChunk.position() >= readChunk.limit()) { if (readBytes() <0) { throwEOFException(sm.getString("chunkedInputFilter.eosTrailer")); } } - chr = buf[pos]; + chr = readChunk.get(readChunk.position()); // CRLF terminates the request if (chr == Constants.CR || chr == Constants.LF) { @@ -480,13 +520,13 @@ public class ChunkedInputFilter implemen while (!colon) { // Read new bytes if needed - if (pos >= lastValid) { + if (readChunk == null || readChunk.position() >= readChunk.limit()) { if (readBytes() <0) { throwEOFException(sm.getString("chunkedInputFilter.eosTrailer")); } } - chr = buf[pos]; + chr = readChunk.get(readChunk.position()); if ((chr >= Constants.A) && (chr <= Constants.Z)) { chr = (byte) (chr - Constants.LC_OFFSET); } @@ -497,7 +537,7 @@ public class ChunkedInputFilter implemen trailingHeaders.append(chr); } - pos++; + readChunk.position(readChunk.position() + 1); } int colonPos = trailingHeaders.getEnd(); @@ -518,15 +558,15 @@ public class ChunkedInputFilter implemen while (space) { // Read new bytes if needed - if (pos >= lastValid) { + if (readChunk == null || readChunk.position() >= readChunk.limit()) { if (readBytes() <0) { throwEOFException(sm.getString("chunkedInputFilter.eosTrailer")); } } - chr = buf[pos]; + chr = readChunk.get(readChunk.position()); if ((chr == Constants.SP) || (chr == Constants.HT)) { - pos++; + readChunk.position(readChunk.position() + 1); // If we swallow whitespace, make sure it counts towards the // limit placed on trailing header size int newlimit = trailingHeaders.getLimit() -1; @@ -544,13 +584,13 @@ public class ChunkedInputFilter implemen while (!eol) { // Read new bytes if needed - if (pos >= lastValid) { + if (readChunk == null || readChunk.position() >= readChunk.limit()) { if (readBytes() <0) { throwEOFException(sm.getString("chunkedInputFilter.eosTrailer")); } } - chr = buf[pos]; + chr = readChunk.get(readChunk.position()); if (chr == Constants.CR || chr == Constants.LF) { parseCRLF(true); eol = true; @@ -562,7 +602,7 @@ public class ChunkedInputFilter implemen } if (!eol) { - pos++; + readChunk.position(readChunk.position() + 1); } } @@ -570,13 +610,13 @@ public class ChunkedInputFilter implemen // is a LWS, then it's a multiline header // Read new bytes if needed - if (pos >= lastValid) { + if (readChunk == null || readChunk.position() >= readChunk.limit()) { if (readBytes() <0) { throwEOFException(sm.getString("chunkedInputFilter.eosTrailer")); } } - chr = buf[pos]; + chr = readChunk.get(readChunk.position()); if ((chr != Constants.SP) && (chr != Constants.HT)) { validLine = false; } else { @@ -620,4 +660,22 @@ public class ChunkedInputFilter implemen throw new IOException(sm.getString("chunkedInputFilter.error")); } } + + + @Override + public void setByteBuffer(ByteBuffer buffer) { + readChunk = buffer; + } + + + @Override + public ByteBuffer getByteBuffer() { + return readChunk; + } + + + @Override + public void expand(int size) { + // no-op + } } Modified: tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/filters/IdentityInputFilter.java URL: http://svn.apache.org/viewvc/tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/filters/IdentityInputFilter.java?rev=1767004&r1=1767003&r2=1767004&view=diff ============================================================================== --- tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/filters/IdentityInputFilter.java (original) +++ tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/filters/IdentityInputFilter.java Fri Oct 28 11:18:05 2016 @@ -24,6 +24,7 @@ import org.apache.coyote.InputBuffer; import org.apache.coyote.Request; import org.apache.coyote.http11.InputFilter; import org.apache.tomcat.util.buf.ByteChunk; +import org.apache.tomcat.util.net.ApplicationBufferHandler; import org.apache.tomcat.util.res.StringManager; /** @@ -118,6 +119,40 @@ public class IdentityInputFilter impleme result = -1; } } + + return result; + + } + + @Override + public int doRead(ApplicationBufferHandler handler) throws IOException { + + int result = -1; + + if (contentLength >= 0) { + if (remaining > 0) { + int nRead = buffer.doRead(handler); + if (nRead > remaining) { + // The chunk is longer than the number of bytes remaining + // in the body; changing the chunk length to the number + // of bytes remaining + handler.getByteBuffer().limit(handler.getByteBuffer().position() + (int) remaining); + result = (int) remaining; + } else { + result = nRead; + } + if (nRead > 0) { + remaining = remaining - nRead; + } + } else { + // No more bytes left to be read : return -1 and clear the + // buffer + if (handler.getByteBuffer() != null) { + handler.getByteBuffer().position(0).limit(0); + } + result = -1; + } + } return result; Modified: tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/filters/SavedRequestInputFilter.java URL: http://svn.apache.org/viewvc/tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/filters/SavedRequestInputFilter.java?rev=1767004&r1=1767003&r2=1767004&view=diff ============================================================================== --- tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/filters/SavedRequestInputFilter.java (original) +++ tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/filters/SavedRequestInputFilter.java Fri Oct 28 11:18:05 2016 @@ -18,10 +18,12 @@ package org.apache.coyote.http11.filters; import java.io.IOException; +import java.nio.ByteBuffer; import org.apache.coyote.InputBuffer; import org.apache.coyote.http11.InputFilter; import org.apache.tomcat.util.buf.ByteChunk; +import org.apache.tomcat.util.net.ApplicationBufferHandler; /** * Input filter responsible for replaying the request body when restoring the @@ -63,6 +65,18 @@ public class SavedRequestInputFilter imp return writeLength; } + @Override + public int doRead(ApplicationBufferHandler handler) throws IOException { + if(input.getOffset()>= input.getEnd()) + return -1; + + ByteBuffer byteBuffer = handler.getByteBuffer(); + byteBuffer.position(byteBuffer.limit()).limit(byteBuffer.capacity()); + input.substract(byteBuffer); + + return byteBuffer.remaining(); + } + /** * Set the content length on the request. */ Modified: tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/filters/VoidInputFilter.java URL: http://svn.apache.org/viewvc/tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/filters/VoidInputFilter.java?rev=1767004&r1=1767003&r2=1767004&view=diff ============================================================================== --- tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/filters/VoidInputFilter.java (original) +++ tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/filters/VoidInputFilter.java Fri Oct 28 11:18:05 2016 @@ -23,6 +23,7 @@ import org.apache.coyote.InputBuffer; import org.apache.coyote.Request; import org.apache.coyote.http11.InputFilter; import org.apache.tomcat.util.buf.ByteChunk; +import org.apache.tomcat.util.net.ApplicationBufferHandler; /** * Void input filter, which returns -1 when attempting a read. Used with a GET, @@ -54,6 +55,11 @@ public class VoidInputFilter implements return -1; } + @Override + public int doRead(ApplicationBufferHandler handler) throws IOException { + return -1; + } + // ---------------------------------------------------- InputFilter Methods Modified: tomcat/tc8.5.x/trunk/java/org/apache/coyote/http2/Stream.java URL: http://svn.apache.org/viewvc/tomcat/tc8.5.x/trunk/java/org/apache/coyote/http2/Stream.java?rev=1767004&r1=1767003&r2=1767004&view=diff ============================================================================== --- tomcat/tc8.5.x/trunk/java/org/apache/coyote/http2/Stream.java (original) +++ tomcat/tc8.5.x/trunk/java/org/apache/coyote/http2/Stream.java Fri Oct 28 11:18:05 2016 @@ -33,6 +33,7 @@ import org.apache.coyote.http2.HpackDeco import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; import org.apache.tomcat.util.buf.ByteChunk; +import org.apache.tomcat.util.net.ApplicationBufferHandler; import org.apache.tomcat.util.res.StringManager; public class Stream extends AbstractStream implements HeaderEmitter { @@ -765,6 +766,62 @@ public class Stream extends AbstractStre // Increment client-side flow control windows by the number of bytes // read + handler.writeWindowUpdate(Stream.this, written, true); + + return written; + } + + @Override + public int doRead(ApplicationBufferHandler applicationBufferHandler) throws IOException { + + ensureBuffersExist(); + + int written = -1; + + // Ensure that only one thread accesses inBuffer at a time + synchronized (inBuffer) { + while (inBuffer.position() == 0 && !isInputFinished()) { + // Need to block until some data is written + try { + if (log.isDebugEnabled()) { + log.debug(sm.getString("stream.inputBuffer.empty")); + } + inBuffer.wait(); + if (reset) { + // TODO: i18n + throw new IOException("HTTP/2 Stream reset"); + } + } catch (InterruptedException e) { + // Possible shutdown / rst or similar. Use an + // IOException to signal to the client that further I/O + // isn't possible for this Stream. + throw new IOException(e); + } + } + + if (inBuffer.position() > 0) { + // Data is available in the inBuffer. Copy it to the + // outBuffer. + inBuffer.flip(); + written = inBuffer.remaining(); + if (log.isDebugEnabled()) { + log.debug(sm.getString("stream.inputBuffer.copy", + Integer.toString(written))); + } + inBuffer.get(outBuffer, 0, written); + inBuffer.clear(); + } else if (isInputFinished()) { + return -1; + } else { + // Should never happen + throw new IllegalStateException(); + } + } + + applicationBufferHandler.setByteBuffer(ByteBuffer.wrap(outBuffer, 0, written)); + + // Increment client-side flow control windows by the number of bytes + // read handler.writeWindowUpdate(Stream.this, written, true); return written; Modified: tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/net/ApplicationBufferHandler.java URL: http://svn.apache.org/viewvc/tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/net/ApplicationBufferHandler.java?rev=1767004&r1=1767003&r2=1767004&view=diff ============================================================================== --- tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/net/ApplicationBufferHandler.java (original) +++ tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/net/ApplicationBufferHandler.java Fri Oct 28 11:18:05 2016 @@ -20,10 +20,12 @@ import java.nio.ByteBuffer; /** * Callback interface to be able to expand buffers when buffer overflow - * exceptions happen + * exceptions happen or to replace buffers */ public interface ApplicationBufferHandler { + public void setByteBuffer(ByteBuffer buffer); + public ByteBuffer getByteBuffer(); public void expand(int size); --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org