From 6eaa1364e39fcc57a20d46dbfa89bcaea8811b99 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Wed, 28 Sep 2011 16:21:57 +1000 Subject: [PATCH] 357240 work in progress --- .../eclipse/jetty/client/HttpConnection.java | 5 ++ .../eclipse/jetty/client/HttpExchange.java | 15 +++- .../client/AsyncSslHttpExchangeTest.java | 9 ++- .../jetty/client/HttpExchangeTest.java | 73 ++++++++++++++++-- .../org/eclipse/jetty/http/HttpParser.java | 2 +- .../jetty/io/nio/SelectChannelEndPoint.java | 6 +- .../io/nio/SslSelectChannelEndPoint.java | 76 ++++++++----------- .../jetty/server/HttpServerTestBase.java | 4 +- .../server/ssl/SslTruncationAttackTest.java | 11 --- 9 files changed, 130 insertions(+), 71 deletions(-) diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConnection.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConnection.java index 7dbd756f07f..7fad3b9dcca 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConnection.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConnection.java @@ -355,6 +355,7 @@ public class HttpConnection extends AbstractConnection implements Dumpable } } + /* TODO - is this needed ? if (_generator.isComplete() && !_parser.isComplete()) { if (!_endp.isOpen() || _endp.isInputShutdown()) @@ -364,6 +365,7 @@ public class HttpConnection extends AbstractConnection implements Dumpable close(); } } + */ if (complete || failed) { @@ -669,6 +671,9 @@ public class HttpConnection extends AbstractConnection implements Dumpable case HttpExchange.STATUS_EXCEPTED: case HttpExchange.STATUS_EXPIRED: break; + case HttpExchange.STATUS_PARSING_CONTENT: + if (_endp.isInputShutdown() && _parser.isState(HttpParser.STATE_EOF_CONTENT)) + break; default: String exch= exchange.toString(); String reason = _endp.isOpen()?(_endp.isInputShutdown()?"half closed: ":"local close: "):"closed: "; diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpExchange.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpExchange.java index a7f1197b340..f3fca478122 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpExchange.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpExchange.java @@ -107,8 +107,10 @@ public class HttpExchange private long _timeout = -1; private volatile Timeout.Task _timeoutTask; - private long _lastStateChange=-1; + private long _lastStateChange=System.currentTimeMillis(); private long _sent=-1; + private int _lastState=-1; + private int _lastStatePeriod=-1; boolean _onRequestCompleteDone; boolean _onResponseCompleteDone; @@ -188,7 +190,10 @@ public class HttpExchange boolean set = false; if (oldStatus!=newStatus) { - _lastStateChange=System.currentTimeMillis(); + long now = System.currentTimeMillis(); + _lastStatePeriod=(int)(now-_lastStateChange); + _lastState=oldStatus; + _lastStateChange=now; if (newStatus==STATUS_SENDING_REQUEST) _sent=_lastStateChange; } @@ -816,8 +821,10 @@ public class HttpExchange String state=toState(getStatus()); long now=System.currentTimeMillis(); long forMs = now -_lastStateChange; - String s= String.format("%s@%x=%s//%s%s#%s(%dms)",getClass().getSimpleName(),hashCode(),_method,_address,_uri,state,forMs); - if (getStatus()>=STATUS_SENDING_REQUEST) + String s= _lastState>=0 + ?String.format("%s@%x=%s//%s%s#%s(%dms)->%s(%dms)",getClass().getSimpleName(),hashCode(),_method,_address,_uri,toState(_lastState),_lastStatePeriod,state,forMs) + :String.format("%s@%x=%s//%s%s#%s(%dms)",getClass().getSimpleName(),hashCode(),_method,_address,_uri,state,forMs); + if (getStatus()>=STATUS_SENDING_REQUEST && _sent>0) s+="sent="+(now-_sent)+"ms"; return s; } diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/AsyncSslHttpExchangeTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/AsyncSslHttpExchangeTest.java index e8c2accd48d..068d497dad6 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/AsyncSslHttpExchangeTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/AsyncSslHttpExchangeTest.java @@ -16,6 +16,7 @@ package org.eclipse.jetty.client; import org.eclipse.jetty.client.helperClasses.AsyncSslServerAndClientCreator; import org.eclipse.jetty.client.helperClasses.ServerAndClientCreator; import org.junit.BeforeClass; +import org.junit.Test; public class AsyncSslHttpExchangeTest extends SslHttpExchangeTest { @@ -35,6 +36,12 @@ public class AsyncSslHttpExchangeTest extends SslHttpExchangeTest { super.testPerf(); } - + + @Test + public void testPerf1() throws Exception + { + sender(1,true); + } + } diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpExchangeTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpExchangeTest.java index 77b353a0420..0e0efc3d5a9 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpExchangeTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpExchangeTest.java @@ -129,6 +129,7 @@ public class HttpExchangeTest final CountDownLatch latch = new CountDownLatch(nb); HttpExchange[] httpExchange = new HttpExchange[nb]; long start = System.currentTimeMillis(); + final boolean verbose=false; for (int i = 0; i < nb; i++) { final int n = i; @@ -142,6 +143,8 @@ public class HttpExchangeTest @Override protected void onRequestCommitted() { + if (verbose) + System.err.println("[ "); result = "committed"; } @@ -149,6 +152,8 @@ public class HttpExchangeTest @Override protected void onRequestComplete() throws IOException { + if (verbose) + System.err.println("[ =="); result = "sent"; } @@ -156,6 +161,8 @@ public class HttpExchangeTest /* ------------------------------------------------------------ */ protected void onResponseStatus(Buffer version, int status, Buffer reason) { + if (verbose) + System.err.println("] "+version+" "+status+" "+reason); result = "status"; } @@ -163,12 +170,16 @@ public class HttpExchangeTest @Override protected void onResponseHeader(Buffer name, Buffer value) { + if (verbose) + System.err.println("] "+name+": "+value); } /* ------------------------------------------------------------ */ @Override protected void onResponseHeaderComplete() throws IOException { + if (verbose) + System.err.println("] -"); result = "content"; super.onResponseHeaderComplete(); } @@ -178,18 +189,22 @@ public class HttpExchangeTest protected void onResponseContent(Buffer content) { len += content.length(); + if (verbose) + System.err.println("] "+content.length()+" -> "+len); } /* ------------------------------------------------------------ */ @Override protected void onResponseComplete() { + if (verbose) + System.err.println("] =="); result = "complete"; if (len == 2009) latch.countDown(); else { - System.err.println(n + " ONLY " + len); + System.err.println(n + " ONLY " + len+ "/2009"); } complete.countDown(); } @@ -198,6 +213,8 @@ public class HttpExchangeTest @Override protected void onConnectionFailed(Throwable ex) { + if (verbose) + System.err.println("] "+ex); complete.countDown(); result = "failed"; System.err.println(n + " FAILED " + ex); @@ -208,6 +225,8 @@ public class HttpExchangeTest @Override protected void onException(Throwable ex) { + if (verbose) + System.err.println("] "+ex); complete.countDown(); result = "excepted"; System.err.println(n + " EXCEPTED " + ex); @@ -218,6 +237,8 @@ public class HttpExchangeTest @Override protected void onExpire() { + if (verbose) + System.err.println("] expired"); complete.countDown(); result = "expired"; System.err.println(n + " EXPIRED " + len); @@ -228,7 +249,7 @@ public class HttpExchangeTest @Override public String toString() { - return n+" "+result+" "+len; + return n+"/"+result+"/"+len+"/"+super.toString(); } }; @@ -374,7 +395,50 @@ public class HttpExchangeTest public void testBigPostWithContentExchange() throws Exception { int size =32; - ContentExchange httpExchange=new ContentExchange(); + ContentExchange httpExchange=new ContentExchange() + { + + @Override + protected synchronized void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException + { + System.err.println("] "+version+" "+status+" "+reason); + // TODO Auto-generated method stub + super.onResponseStatus(version,status,reason); + } + + @Override + protected synchronized void onResponseHeader(Buffer name, Buffer value) throws IOException + { + System.err.println("] "+name+": "+value); + // TODO Auto-generated method stub + super.onResponseHeader(name,value); + } + + @Override + protected synchronized void onResponseContent(Buffer content) throws IOException + { + System.err.println("] "+content.length()); + // TODO Auto-generated method stub + super.onResponseContent(content); + } + + @Override + protected void onRequestComplete() throws IOException + { + System.err.println("] =="); + // TODO Auto-generated method stub + super.onRequestComplete(); + } + + @Override + protected void onResponseHeaderComplete() throws IOException + { + System.err.println("] --"); + // TODO Auto-generated method stub + super.onResponseHeaderComplete(); + } + + }; Buffer babuf = new ByteArrayBuffer(size*36*1024); Buffer niobuf = new DirectNIOBuffer(size*36*1024); @@ -394,7 +458,6 @@ public class HttpExchangeTest _httpClient.send(httpExchange); int status = httpExchange.waitForDone(); - assertEquals(HttpExchange.STATUS_COMPLETED,status); String result=httpExchange.getResponseContent(); assertEquals(babuf.length(),result.length()); @@ -406,9 +469,9 @@ public class HttpExchangeTest httpExchange.setRequestContent(niobuf); _httpClient.send(httpExchange); status = httpExchange.waitForDone(); + assertEquals(HttpExchange.STATUS_COMPLETED, status); result=httpExchange.getResponseContent(); assertEquals(niobuf.length(),result.length()); - assertEquals(HttpExchange.STATUS_COMPLETED, status); } /* ------------------------------------------------------------ */ diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java index aecc18b069c..9194d6b1242 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java @@ -268,7 +268,7 @@ public class HttpParser implements Parser { long filled=fill(); - if (filled < 0) + if (filled < 0 || _endp.isInputShutdown()) { if (_headResponse && _state>STATE_END) { diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectChannelEndPoint.java b/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectChannelEndPoint.java index 5a8ed7842b6..0d15cc52041 100644 --- a/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectChannelEndPoint.java +++ b/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectChannelEndPoint.java @@ -569,20 +569,20 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo catch (EofException e) { __log.debug("EOF", e); - try{close();} + try{getChannel().close();} catch(IOException e2){__log.ignore(e2);} } catch (IOException e) { __log.warn(e.toString()); __log.debug(e); - try{close();} + try{getChannel().close();} catch(IOException e2){__log.ignore(e2);} } catch (Throwable e) { __log.warn("handle failed", e); - try{close();} + try{getChannel().close();} catch(IOException e2){__log.ignore(e2);} } dispatched=!undispatch(); diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SslSelectChannelEndPoint.java b/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SslSelectChannelEndPoint.java index 68167db4296..d60adbf6cb5 100644 --- a/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SslSelectChannelEndPoint.java +++ b/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SslSelectChannelEndPoint.java @@ -330,6 +330,8 @@ public class SslSelectChannelEndPoint extends SelectChannelEndPoint } if (_debug) LOG.debug("{} received {} sent {}",_session,received,sent); + + freeInBuffer(); return (received<0||sent<0)?-1:(received+sent); } @@ -383,13 +385,15 @@ public class SslSelectChannelEndPoint extends SelectChannelEndPoint buffer.setPutIndex(bbuf.position()); bbuf.position(0); } - - // return the number of unencrypted bytes filled. - int filled=buffer.length()-size; - if (filled>0) - _handshook=true; - return filled; } + // return the number of unencrypted bytes filled. + int filled=buffer.length()-size; + if (filled>0) + _handshook=true; + else if (filled==0 && isInputShutdown()) + return -1; + + return filled; } /* ------------------------------------------------------------ */ @@ -433,18 +437,30 @@ public class SslSelectChannelEndPoint extends SelectChannelEndPoint public void flush() throws IOException { LOG.debug(_session+" flush"); + if (!isOpen()) + throw new EofException(); + if (isBufferingOutput()) { int flushed=super.flush(_outNIOBuffer); if (_debug) LOG.debug(_session+" flushed "+flushed+" left="+_outNIOBuffer.length()); } - else if (_engine.isOutboundDone() && !super.isOutputShutdown()) + else if (_engine.isOutboundDone() && super.isOpen()) { if (_debug) LOG.debug(_session+" flush shutdownOutput"); - super.shutdownOutput(); + try + { + super.shutdownOutput(); + } + catch(IOException e) + { + LOG.ignore(e); + } } + + freeOutBuffer(); } /* ------------------------------------------------------------ */ @@ -466,41 +482,21 @@ public class SslSelectChannelEndPoint extends SelectChannelEndPoint needInBuffer(); ByteBuffer in_buffer=_inNIOBuffer.getByteBuffer(); - if (_inNIOBuffer.hasContent()) - _inNIOBuffer.compact(); - else - _inNIOBuffer.clear(); + _inNIOBuffer.compact(); int total_filled=0; boolean remoteClosed = false; // loop filling as much encrypted data as we can into the buffer while (_inNIOBuffer.space()>0 && super.isOpen()) { - try - { - int filled=super.fill(_inNIOBuffer); - if (_debug) LOG.debug(_session+" filled "+filled); - if (filled < 0) - remoteClosed = true; - // break the loop if no progress is made (we have read everything there is to read) - if (filled<=0) - break; - total_filled+=filled; - } - catch(IOException e) - { - if (_inNIOBuffer.length()==0) - { - freeInBuffer(); - if (_outNIOBuffer!=null) - { - _outNIOBuffer.clear(); - freeOutBuffer(); - } - throw e; - } + int filled=super.fill(_inNIOBuffer); + if (_debug) LOG.debug(_session+" filled "+filled); + if (filled < 0) + remoteClosed = true; + // break the loop if no progress is made (we have read everything there is to read) + if (filled<=0) break; - } + total_filled+=filled; } // If we have no progress and no data @@ -521,9 +517,6 @@ public class SslSelectChannelEndPoint extends SelectChannelEndPoint } } - freeInBuffer(); - freeOutBuffer(); - if (!isOpen()) throw new EofException(); @@ -548,7 +541,6 @@ public class SslSelectChannelEndPoint extends SelectChannelEndPoint catch(SSLException e) { LOG.warn(getRemoteAddr() + ":" + getRemotePort() + " " + e); - freeOutBuffer(); super.close(); throw e; } @@ -557,7 +549,6 @@ public class SslSelectChannelEndPoint extends SelectChannelEndPoint // reset the buffer so it can be managed by the _inNIOBuffer again. in_buffer.position(0); in_buffer.limit(in_buffer.capacity()); - freeInBuffer(); } // handle the unwrap results @@ -650,9 +641,6 @@ public class SslSelectChannelEndPoint extends SelectChannelEndPoint buffer.skip(len); consumed-=len; } - assert consumed==0; - - freeOutBuffer(); } } } diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java index aa75b07c2b4..5d84335a060 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java @@ -600,12 +600,12 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture long[] times=new long[10]; for (int i=0;i