357240 work in progress

This commit is contained in:
Greg Wilkins 2011-09-28 16:21:57 +10:00
parent c20ce1fc4e
commit 6eaa1364e3
9 changed files with 130 additions and 71 deletions

View File

@ -355,6 +355,7 @@ public class HttpConnection extends AbstractConnection implements Dumpable
} }
} }
/* TODO - is this needed ?
if (_generator.isComplete() && !_parser.isComplete()) if (_generator.isComplete() && !_parser.isComplete())
{ {
if (!_endp.isOpen() || _endp.isInputShutdown()) if (!_endp.isOpen() || _endp.isInputShutdown())
@ -364,6 +365,7 @@ public class HttpConnection extends AbstractConnection implements Dumpable
close(); close();
} }
} }
*/
if (complete || failed) if (complete || failed)
{ {
@ -669,6 +671,9 @@ public class HttpConnection extends AbstractConnection implements Dumpable
case HttpExchange.STATUS_EXCEPTED: case HttpExchange.STATUS_EXCEPTED:
case HttpExchange.STATUS_EXPIRED: case HttpExchange.STATUS_EXPIRED:
break; break;
case HttpExchange.STATUS_PARSING_CONTENT:
if (_endp.isInputShutdown() && _parser.isState(HttpParser.STATE_EOF_CONTENT))
break;
default: default:
String exch= exchange.toString(); String exch= exchange.toString();
String reason = _endp.isOpen()?(_endp.isInputShutdown()?"half closed: ":"local close: "):"closed: "; String reason = _endp.isOpen()?(_endp.isInputShutdown()?"half closed: ":"local close: "):"closed: ";

View File

@ -107,8 +107,10 @@ public class HttpExchange
private long _timeout = -1; private long _timeout = -1;
private volatile Timeout.Task _timeoutTask; private volatile Timeout.Task _timeoutTask;
private long _lastStateChange=-1; private long _lastStateChange=System.currentTimeMillis();
private long _sent=-1; private long _sent=-1;
private int _lastState=-1;
private int _lastStatePeriod=-1;
boolean _onRequestCompleteDone; boolean _onRequestCompleteDone;
boolean _onResponseCompleteDone; boolean _onResponseCompleteDone;
@ -188,7 +190,10 @@ public class HttpExchange
boolean set = false; boolean set = false;
if (oldStatus!=newStatus) if (oldStatus!=newStatus)
{ {
_lastStateChange=System.currentTimeMillis(); long now = System.currentTimeMillis();
_lastStatePeriod=(int)(now-_lastStateChange);
_lastState=oldStatus;
_lastStateChange=now;
if (newStatus==STATUS_SENDING_REQUEST) if (newStatus==STATUS_SENDING_REQUEST)
_sent=_lastStateChange; _sent=_lastStateChange;
} }
@ -816,8 +821,10 @@ public class HttpExchange
String state=toState(getStatus()); String state=toState(getStatus());
long now=System.currentTimeMillis(); long now=System.currentTimeMillis();
long forMs = now -_lastStateChange; long forMs = now -_lastStateChange;
String s= String.format("%s@%x=%s//%s%s#%s(%dms)",getClass().getSimpleName(),hashCode(),_method,_address,_uri,state,forMs); String s= _lastState>=0
if (getStatus()>=STATUS_SENDING_REQUEST) ?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"; s+="sent="+(now-_sent)+"ms";
return s; return s;
} }

View File

@ -16,6 +16,7 @@ package org.eclipse.jetty.client;
import org.eclipse.jetty.client.helperClasses.AsyncSslServerAndClientCreator; import org.eclipse.jetty.client.helperClasses.AsyncSslServerAndClientCreator;
import org.eclipse.jetty.client.helperClasses.ServerAndClientCreator; import org.eclipse.jetty.client.helperClasses.ServerAndClientCreator;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test;
public class AsyncSslHttpExchangeTest extends SslHttpExchangeTest public class AsyncSslHttpExchangeTest extends SslHttpExchangeTest
{ {
@ -36,5 +37,11 @@ public class AsyncSslHttpExchangeTest extends SslHttpExchangeTest
super.testPerf(); super.testPerf();
} }
@Test
public void testPerf1() throws Exception
{
sender(1,true);
}
} }

View File

@ -129,6 +129,7 @@ public class HttpExchangeTest
final CountDownLatch latch = new CountDownLatch(nb); final CountDownLatch latch = new CountDownLatch(nb);
HttpExchange[] httpExchange = new HttpExchange[nb]; HttpExchange[] httpExchange = new HttpExchange[nb];
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
final boolean verbose=false;
for (int i = 0; i < nb; i++) for (int i = 0; i < nb; i++)
{ {
final int n = i; final int n = i;
@ -142,6 +143,8 @@ public class HttpExchangeTest
@Override @Override
protected void onRequestCommitted() protected void onRequestCommitted()
{ {
if (verbose)
System.err.println("[ ");
result = "committed"; result = "committed";
} }
@ -149,6 +152,8 @@ public class HttpExchangeTest
@Override @Override
protected void onRequestComplete() throws IOException protected void onRequestComplete() throws IOException
{ {
if (verbose)
System.err.println("[ ==");
result = "sent"; result = "sent";
} }
@ -156,6 +161,8 @@ public class HttpExchangeTest
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
protected void onResponseStatus(Buffer version, int status, Buffer reason) protected void onResponseStatus(Buffer version, int status, Buffer reason)
{ {
if (verbose)
System.err.println("] "+version+" "+status+" "+reason);
result = "status"; result = "status";
} }
@ -163,12 +170,16 @@ public class HttpExchangeTest
@Override @Override
protected void onResponseHeader(Buffer name, Buffer value) protected void onResponseHeader(Buffer name, Buffer value)
{ {
if (verbose)
System.err.println("] "+name+": "+value);
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@Override @Override
protected void onResponseHeaderComplete() throws IOException protected void onResponseHeaderComplete() throws IOException
{ {
if (verbose)
System.err.println("] -");
result = "content"; result = "content";
super.onResponseHeaderComplete(); super.onResponseHeaderComplete();
} }
@ -178,18 +189,22 @@ public class HttpExchangeTest
protected void onResponseContent(Buffer content) protected void onResponseContent(Buffer content)
{ {
len += content.length(); len += content.length();
if (verbose)
System.err.println("] "+content.length()+" -> "+len);
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@Override @Override
protected void onResponseComplete() protected void onResponseComplete()
{ {
if (verbose)
System.err.println("] ==");
result = "complete"; result = "complete";
if (len == 2009) if (len == 2009)
latch.countDown(); latch.countDown();
else else
{ {
System.err.println(n + " ONLY " + len); System.err.println(n + " ONLY " + len+ "/2009");
} }
complete.countDown(); complete.countDown();
} }
@ -198,6 +213,8 @@ public class HttpExchangeTest
@Override @Override
protected void onConnectionFailed(Throwable ex) protected void onConnectionFailed(Throwable ex)
{ {
if (verbose)
System.err.println("] "+ex);
complete.countDown(); complete.countDown();
result = "failed"; result = "failed";
System.err.println(n + " FAILED " + ex); System.err.println(n + " FAILED " + ex);
@ -208,6 +225,8 @@ public class HttpExchangeTest
@Override @Override
protected void onException(Throwable ex) protected void onException(Throwable ex)
{ {
if (verbose)
System.err.println("] "+ex);
complete.countDown(); complete.countDown();
result = "excepted"; result = "excepted";
System.err.println(n + " EXCEPTED " + ex); System.err.println(n + " EXCEPTED " + ex);
@ -218,6 +237,8 @@ public class HttpExchangeTest
@Override @Override
protected void onExpire() protected void onExpire()
{ {
if (verbose)
System.err.println("] expired");
complete.countDown(); complete.countDown();
result = "expired"; result = "expired";
System.err.println(n + " EXPIRED " + len); System.err.println(n + " EXPIRED " + len);
@ -228,7 +249,7 @@ public class HttpExchangeTest
@Override @Override
public String toString() 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 public void testBigPostWithContentExchange() throws Exception
{ {
int size =32; 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 babuf = new ByteArrayBuffer(size*36*1024);
Buffer niobuf = new DirectNIOBuffer(size*36*1024); Buffer niobuf = new DirectNIOBuffer(size*36*1024);
@ -394,7 +458,6 @@ public class HttpExchangeTest
_httpClient.send(httpExchange); _httpClient.send(httpExchange);
int status = httpExchange.waitForDone(); int status = httpExchange.waitForDone();
assertEquals(HttpExchange.STATUS_COMPLETED,status); assertEquals(HttpExchange.STATUS_COMPLETED,status);
String result=httpExchange.getResponseContent(); String result=httpExchange.getResponseContent();
assertEquals(babuf.length(),result.length()); assertEquals(babuf.length(),result.length());
@ -406,9 +469,9 @@ public class HttpExchangeTest
httpExchange.setRequestContent(niobuf); httpExchange.setRequestContent(niobuf);
_httpClient.send(httpExchange); _httpClient.send(httpExchange);
status = httpExchange.waitForDone(); status = httpExchange.waitForDone();
assertEquals(HttpExchange.STATUS_COMPLETED, status);
result=httpExchange.getResponseContent(); result=httpExchange.getResponseContent();
assertEquals(niobuf.length(),result.length()); assertEquals(niobuf.length(),result.length());
assertEquals(HttpExchange.STATUS_COMPLETED, status);
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */

View File

@ -268,7 +268,7 @@ public class HttpParser implements Parser
{ {
long filled=fill(); long filled=fill();
if (filled < 0) if (filled < 0 || _endp.isInputShutdown())
{ {
if (_headResponse && _state>STATE_END) if (_headResponse && _state>STATE_END)
{ {

View File

@ -569,20 +569,20 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
catch (EofException e) catch (EofException e)
{ {
__log.debug("EOF", e); __log.debug("EOF", e);
try{close();} try{getChannel().close();}
catch(IOException e2){__log.ignore(e2);} catch(IOException e2){__log.ignore(e2);}
} }
catch (IOException e) catch (IOException e)
{ {
__log.warn(e.toString()); __log.warn(e.toString());
__log.debug(e); __log.debug(e);
try{close();} try{getChannel().close();}
catch(IOException e2){__log.ignore(e2);} catch(IOException e2){__log.ignore(e2);}
} }
catch (Throwable e) catch (Throwable e)
{ {
__log.warn("handle failed", e); __log.warn("handle failed", e);
try{close();} try{getChannel().close();}
catch(IOException e2){__log.ignore(e2);} catch(IOException e2){__log.ignore(e2);}
} }
dispatched=!undispatch(); dispatched=!undispatch();

View File

@ -330,6 +330,8 @@ public class SslSelectChannelEndPoint extends SelectChannelEndPoint
} }
if (_debug) LOG.debug("{} received {} sent {}",_session,received,sent); if (_debug) LOG.debug("{} received {} sent {}",_session,received,sent);
freeInBuffer();
return (received<0||sent<0)?-1:(received+sent); return (received<0||sent<0)?-1:(received+sent);
} }
@ -383,13 +385,15 @@ public class SslSelectChannelEndPoint extends SelectChannelEndPoint
buffer.setPutIndex(bbuf.position()); buffer.setPutIndex(bbuf.position());
bbuf.position(0); 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 public void flush() throws IOException
{ {
LOG.debug(_session+" flush"); LOG.debug(_session+" flush");
if (!isOpen())
throw new EofException();
if (isBufferingOutput()) if (isBufferingOutput())
{ {
int flushed=super.flush(_outNIOBuffer); int flushed=super.flush(_outNIOBuffer);
if (_debug) if (_debug)
LOG.debug(_session+" flushed "+flushed+" left="+_outNIOBuffer.length()); LOG.debug(_session+" flushed "+flushed+" left="+_outNIOBuffer.length());
} }
else if (_engine.isOutboundDone() && !super.isOutputShutdown()) else if (_engine.isOutboundDone() && super.isOpen())
{ {
if (_debug) if (_debug)
LOG.debug(_session+" flush shutdownOutput"); 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(); needInBuffer();
ByteBuffer in_buffer=_inNIOBuffer.getByteBuffer(); ByteBuffer in_buffer=_inNIOBuffer.getByteBuffer();
if (_inNIOBuffer.hasContent()) _inNIOBuffer.compact();
_inNIOBuffer.compact();
else
_inNIOBuffer.clear();
int total_filled=0; int total_filled=0;
boolean remoteClosed = false; boolean remoteClosed = false;
// loop filling as much encrypted data as we can into the buffer // loop filling as much encrypted data as we can into the buffer
while (_inNIOBuffer.space()>0 && super.isOpen()) while (_inNIOBuffer.space()>0 && super.isOpen())
{ {
try int filled=super.fill(_inNIOBuffer);
{ if (_debug) LOG.debug(_session+" filled "+filled);
int filled=super.fill(_inNIOBuffer); if (filled < 0)
if (_debug) LOG.debug(_session+" filled "+filled); remoteClosed = true;
if (filled < 0) // break the loop if no progress is made (we have read everything there is to read)
remoteClosed = true; if (filled<=0)
// 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;
}
break; break;
} total_filled+=filled;
} }
// If we have no progress and no data // If we have no progress and no data
@ -521,9 +517,6 @@ public class SslSelectChannelEndPoint extends SelectChannelEndPoint
} }
} }
freeInBuffer();
freeOutBuffer();
if (!isOpen()) if (!isOpen())
throw new EofException(); throw new EofException();
@ -548,7 +541,6 @@ public class SslSelectChannelEndPoint extends SelectChannelEndPoint
catch(SSLException e) catch(SSLException e)
{ {
LOG.warn(getRemoteAddr() + ":" + getRemotePort() + " " + e); LOG.warn(getRemoteAddr() + ":" + getRemotePort() + " " + e);
freeOutBuffer();
super.close(); super.close();
throw e; throw e;
} }
@ -557,7 +549,6 @@ public class SslSelectChannelEndPoint extends SelectChannelEndPoint
// reset the buffer so it can be managed by the _inNIOBuffer again. // reset the buffer so it can be managed by the _inNIOBuffer again.
in_buffer.position(0); in_buffer.position(0);
in_buffer.limit(in_buffer.capacity()); in_buffer.limit(in_buffer.capacity());
freeInBuffer();
} }
// handle the unwrap results // handle the unwrap results
@ -650,9 +641,6 @@ public class SslSelectChannelEndPoint extends SelectChannelEndPoint
buffer.skip(len); buffer.skip(len);
consumed-=len; consumed-=len;
} }
assert consumed==0;
freeOutBuffer();
} }
} }
} }

View File

@ -600,12 +600,12 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
long[] times=new long[10]; long[] times=new long[10];
for (int i=0;i<times.length;i++) for (int i=0;i<times.length;i++)
{ {
System.err.println("\nBLOCK "+request.getRequestURI()+" "+i); // System.err.println("\nBLOCK "+request.getRequestURI()+" "+i);
long start=System.currentTimeMillis(); long start=System.currentTimeMillis();
out.write(buf); out.write(buf);
long end=System.currentTimeMillis(); long end=System.currentTimeMillis();
times[i]=end-start; times[i]=end-start;
System.err.println("Block "+request.getRequestURI()+" "+i+" "+times[i]); // System.err.println("Block "+request.getRequestURI()+" "+i+" "+times[i]);
} }
out.println(); out.println();
for (long t : times) for (long t : times)

View File

@ -159,17 +159,6 @@ public class SslTruncationAttackTest
Assert.assertTrue("endpoint not closed", endPointClosed.get()); Assert.assertTrue("endpoint not closed", endPointClosed.get());
} }
/**
* This test is currently failing because we are looping on SslSCEP.unwrap()
* to fill the buffer, so there is a case where we loop once, read some data
* loop again and read -1, but we can't close the connection yet as we have
* to notify the application (not sure that this is necessary... must assume
* the data is truncated, so it's not that safe to pass it to the application).
* This case needs to be revisited, and it also requires a review of the
* Connection:close case, especially on the client side.
* @throws Exception if the test fails
*/
@Ignore
@Test @Test
public void testTruncationAttackBeforeReading() throws Exception public void testTruncationAttackBeforeReading() throws Exception
{ {