Merge remote-tracking branch 'origin/master' into jetty-9.1
Conflicts: jetty-io/src/main/java/org/eclipse/jetty/io/AbstractConnection.java jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java jetty-spdy/spdy-http-server/src/main/java/org/eclipse/jetty/spdy/server/proxy/ProxyHTTPSPDYConnection.java
This commit is contained in:
commit
2e444d2f17
|
@ -531,15 +531,22 @@ public abstract class AbstractConnection implements Connection
|
|||
}
|
||||
|
||||
@Override
|
||||
public void failed(Throwable x)
|
||||
public void failed(final Throwable x)
|
||||
{
|
||||
_executor.execute(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
State state=_state.get();
|
||||
if (next(state,state.onFailed()))
|
||||
break;
|
||||
}
|
||||
onFillInterestedFailed(x);
|
||||
onFillInterestedFailed(x);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -291,12 +291,12 @@ public class SslConnection extends AbstractConnection
|
|||
}
|
||||
|
||||
@Override
|
||||
public void failed(Throwable x)
|
||||
public void failed(final Throwable x)
|
||||
{
|
||||
// This means that a write of data has failed. Writes are done
|
||||
// only if there is an active writeflusher or a read needed to write
|
||||
// data. In either case the appropriate callback is passed on.
|
||||
boolean failFiller = false;
|
||||
boolean fail_filler = false;
|
||||
synchronized (DecryptedEndPoint.this)
|
||||
{
|
||||
if (DEBUG)
|
||||
|
@ -309,12 +309,23 @@ public class SslConnection extends AbstractConnection
|
|||
if (_fillRequiresFlushToProgress)
|
||||
{
|
||||
_fillRequiresFlushToProgress = false;
|
||||
failFiller = true;
|
||||
fail_filler = true;
|
||||
}
|
||||
}
|
||||
if (failFiller)
|
||||
getFillInterest().onFail(x);
|
||||
getWriteFlusher().onFail(x);
|
||||
|
||||
final boolean filler_failed=fail_filler;
|
||||
|
||||
getExecutor().execute(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
|
||||
if (filler_failed)
|
||||
getFillInterest().onFail(x);
|
||||
getWriteFlusher().onFail(x);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -761,8 +761,8 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable
|
|||
if (x instanceof EofException)
|
||||
{
|
||||
LOG.debug(x);
|
||||
_response.getHttpOutput().closed();
|
||||
_callback.failed(x);
|
||||
_response.getHttpOutput().closed();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -772,16 +772,16 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable
|
|||
@Override
|
||||
public void succeeded()
|
||||
{
|
||||
_response.getHttpOutput().closed();
|
||||
_callback.failed(x);
|
||||
_response.getHttpOutput().closed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void failed(Throwable th)
|
||||
{
|
||||
LOG.ignore(th);
|
||||
_response.getHttpOutput().closed();
|
||||
_callback.failed(x);
|
||||
_response.getHttpOutput().closed();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -143,6 +143,26 @@ public class ServerConnector extends AbstractNetworkConnector
|
|||
this(server,null,null,null,0,0,AbstractConnectionFactory.getFactories(sslContextFactory,new HttpConnectionFactory()));
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** HTTP Server Connection.
|
||||
* <p>Construct a ServerConnector with a private instance of {@link HttpConnectionFactory} as the primary protocol</p>.
|
||||
* @param server The {@link Server} this connector will accept connection for.
|
||||
* @param sslContextFactory If non null, then a {@link SslConnectionFactory} is instantiated and prepended to the
|
||||
* list of HTTP Connection Factory.
|
||||
* @param acceptors
|
||||
* the number of acceptor threads to use, or 0 for a default value. Acceptors accept new TCP/IP connections.
|
||||
* @param selectors
|
||||
* the number of selector threads, or 0 for a default value. Selectors notice and schedule established connection that can make IO progress.
|
||||
*/
|
||||
public ServerConnector(
|
||||
@Name("server") Server server,
|
||||
@Name("acceptors") int acceptors,
|
||||
@Name("selectors") int selectors,
|
||||
@Name("sslContextFactory") SslContextFactory sslContextFactory)
|
||||
{
|
||||
this(server,null,null,null,acceptors,selectors,AbstractConnectionFactory.getFactories(sslContextFactory,new HttpConnectionFactory()));
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Generic SSL Server Connection.
|
||||
* @param server The {@link Server} this connector will accept connection for.
|
||||
|
|
|
@ -22,6 +22,7 @@ import static org.hamcrest.Matchers.containsString;
|
|||
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
@ -35,9 +36,12 @@ import java.io.InputStreamReader;
|
|||
import java.io.LineNumberReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.Exchanger;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
|
@ -660,6 +664,57 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCloseWhileWriteBlocked() throws Exception
|
||||
{
|
||||
configureServer(new DataHandler());
|
||||
|
||||
try (Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort()))
|
||||
{
|
||||
OutputStream os = client.getOutputStream();
|
||||
InputStream is = client.getInputStream();
|
||||
|
||||
os.write((
|
||||
"GET /data?encoding=iso-8859-1&writes=100&block=100000 HTTP/1.1\r\n" +
|
||||
"host: " + _serverURI.getHost() + ":" + _serverURI.getPort() + "\r\n" +
|
||||
"connection: close\r\n" +
|
||||
"content-type: unknown\r\n" +
|
||||
"\r\n"
|
||||
).getBytes());
|
||||
os.flush();
|
||||
|
||||
// Read the first part of the response
|
||||
byte[] buf = new byte[1024 * 8];
|
||||
is.read(buf);
|
||||
|
||||
// sleep to ensure server is blocking
|
||||
Thread.sleep(500);
|
||||
|
||||
// Close the client
|
||||
client.close();
|
||||
}
|
||||
|
||||
Thread.sleep(200);
|
||||
// check server is still handling requests quickly
|
||||
try (Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort()))
|
||||
{
|
||||
client.setSoTimeout(500);
|
||||
OutputStream os = client.getOutputStream();
|
||||
InputStream is = client.getInputStream();
|
||||
|
||||
os.write(("GET /data?writes=1&block=1024 HTTP/1.1\r\n" +
|
||||
"host: " + _serverURI.getHost() + ":" + _serverURI.getPort() + "\r\n" +
|
||||
"connection: close\r\n" +
|
||||
"content-type: unknown\r\n" +
|
||||
"\r\n"
|
||||
).getBytes());
|
||||
os.flush();
|
||||
|
||||
String response = IO.toString(is);
|
||||
assertThat(response,startsWith("HTTP/1.1 200 OK"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBigBlocks() throws Exception
|
||||
{
|
||||
|
@ -1432,7 +1487,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
os.flush();
|
||||
|
||||
String response = readResponse(client);
|
||||
assertThat(response, JUnitMatchers.containsString("RESUMEDHTTP/1.1 200 OK"));
|
||||
assertThat(response, containsString("RESUMEDHTTP/1.1 200 OK"));
|
||||
assertThat((System.currentTimeMillis() - start), greaterThanOrEqualTo(1999L));
|
||||
|
||||
// TODO This test should also check that that the CPU did not spin during the suspend.
|
||||
|
|
|
@ -151,6 +151,7 @@ public class HttpServerTestFixture
|
|||
|
||||
protected static class HelloWorldHandler extends AbstractHandler
|
||||
{
|
||||
@Override
|
||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
baseRequest.setHandled(true);
|
||||
|
@ -195,20 +196,24 @@ public class HttpServerTestFixture
|
|||
else if ("true".equals(chars))
|
||||
{
|
||||
response.setCharacterEncoding(encoding);
|
||||
Writer out=response.getWriter();
|
||||
PrintWriter out=response.getWriter();
|
||||
char[] c=chunk.toCharArray();
|
||||
for (int i=0;i<writes;i++)
|
||||
{
|
||||
out.write(c);
|
||||
if (out.checkError())
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
response.setCharacterEncoding(encoding);
|
||||
Writer out=response.getWriter();
|
||||
PrintWriter out=response.getWriter();
|
||||
for (int i=0;i<writes;i++)
|
||||
{
|
||||
out.write(chunk);
|
||||
if (out.checkError())
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,6 @@ public class SelectChannelServerTest extends HttpServerTestBase
|
|||
@Before
|
||||
public void init() throws Exception
|
||||
{
|
||||
startServer(new ServerConnector(_server));
|
||||
startServer(new ServerConnector(_server,1,1));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ public class SelectChannelTimeoutTest extends ConnectorTimeoutTest
|
|||
@Before
|
||||
public void init() throws Exception
|
||||
{
|
||||
ServerConnector connector = new ServerConnector(_server);
|
||||
ServerConnector connector = new ServerConnector(_server,1,1);
|
||||
connector.setIdleTimeout(MAX_IDLE_TIME); // 250 msec max idle
|
||||
startServer(connector);
|
||||
}
|
||||
|
|
|
@ -106,7 +106,7 @@ public class SelectChannelServerSslTest extends HttpServerTestBase
|
|||
sslContextFactory.setKeyManagerPassword("keypwd");
|
||||
sslContextFactory.setTrustStorePath(keystorePath);
|
||||
sslContextFactory.setTrustStorePassword("storepwd");
|
||||
ServerConnector connector = new ServerConnector(_server, sslContextFactory);
|
||||
ServerConnector connector = new ServerConnector(_server, 1, 1, sslContextFactory);
|
||||
|
||||
startServer(connector);
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ public class SslSelectChannelTimeoutTest extends ConnectorTimeoutTest
|
|||
sslContextFactory.setKeyManagerPassword("keypwd");
|
||||
sslContextFactory.setTrustStorePath(keystorePath);
|
||||
sslContextFactory.setTrustStorePassword("storepwd");
|
||||
ServerConnector connector = new ServerConnector(_server, sslContextFactory);
|
||||
ServerConnector connector = new ServerConnector(_server, 1, 1, sslContextFactory);
|
||||
connector.setIdleTimeout(MAX_IDLE_TIME); //250 msec max idle
|
||||
startServer(connector);
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ public class ProxyHTTPSPDYConnection extends HttpConnection implements HttpParse
|
|||
|
||||
public ProxyHTTPSPDYConnection(Connector connector, HttpConfiguration config, EndPoint endPoint, short version, ProxyEngineSelector proxyEngineSelector)
|
||||
{
|
||||
super(config,connector,endPoint);
|
||||
super(config, connector, endPoint);
|
||||
this.version = version;
|
||||
this.proxyEngineSelector = proxyEngineSelector;
|
||||
this.session = new HTTPSession(version, connector);
|
||||
|
@ -95,7 +95,7 @@ public class ProxyHTTPSPDYConnection extends HttpConnection implements HttpParse
|
|||
@Override
|
||||
public boolean parsedHeader(HttpField field)
|
||||
{
|
||||
if (field.getHeader()==HttpHeader.HOST)
|
||||
if (field.getHeader() == HttpHeader.HOST)
|
||||
headers.put(HTTPSPDYHeader.HOST.name(version), field.getValue());
|
||||
else
|
||||
headers.put(field.getName(), field.getValue());
|
||||
|
@ -243,7 +243,7 @@ public class ProxyHTTPSPDYConnection extends HttpConnection implements HttpParse
|
|||
{
|
||||
Fields headers = new Fields(replyInfo.getHeaders(), false);
|
||||
|
||||
addPersistenceHeader(headers);
|
||||
addPersistenceHeader(headers);
|
||||
|
||||
headers.remove(HTTPSPDYHeader.SCHEME.name(version));
|
||||
|
||||
|
|
Loading…
Reference in New Issue