465857 - Support HTTP/2 clear-text server-side upgrade.
Fixed and test both types of upgrade, from HTTP/1.1 via its upgrade mechanism, and direct HTTP/2.
This commit is contained in:
parent
aaaf65bf3c
commit
a6cc4ff2f5
|
@ -66,9 +66,9 @@ public class HTTP2Connection extends AbstractConnection
|
|||
return parser;
|
||||
}
|
||||
|
||||
protected void prefill(ByteBuffer buffer)
|
||||
protected void setInputBuffer(ByteBuffer buffer)
|
||||
{
|
||||
producer.buffer=buffer;
|
||||
producer.buffer = buffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -18,14 +18,28 @@
|
|||
|
||||
package org.eclipse.jetty.http2.frames;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class PrefaceFrame extends Frame
|
||||
{
|
||||
public static final byte[] PREFACE_BYTES = new byte[]
|
||||
{
|
||||
0x50, 0x52, 0x49, 0x20, 0x2a, 0x20, 0x48, 0x54,
|
||||
0x54, 0x50, 0x2f, 0x32, 0x2e, 0x30, 0x0d, 0x0a,
|
||||
0x0d, 0x0a, 0x53, 0x4d, 0x0d, 0x0a, 0x0d, 0x0a
|
||||
};
|
||||
/**
|
||||
* The bytes of the HTTP/2 preface that form a legal HTTP/1.1
|
||||
* request, used in the direct upgrade.
|
||||
*/
|
||||
public static final byte[] PREFACE_PREAMBLE_BYTES = (
|
||||
"PRI * HTTP/2.0\r\n" +
|
||||
"\r\n"
|
||||
).getBytes(StandardCharsets.US_ASCII);
|
||||
|
||||
/**
|
||||
* The HTTP/2 preface bytes.
|
||||
*/
|
||||
public static final byte[] PREFACE_BYTES = (
|
||||
"PRI * HTTP/2.0\r\n" +
|
||||
"\r\n" +
|
||||
"SM\r\n" +
|
||||
"\r\n"
|
||||
).getBytes(StandardCharsets.US_ASCII);
|
||||
|
||||
public PrefaceFrame()
|
||||
{
|
||||
|
|
|
@ -38,20 +38,19 @@ public class PrefaceParser
|
|||
this.listener = listener;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Unsafe upgrade is an unofficial upgrade from HTTP/1.0 to HTTP/2.0
|
||||
* initiated when a the <code>org.eclipse.jetty.server.HttpConnection</code> sees a PRI * HTTP/2.0 prefix
|
||||
* that indicates a HTTP/2.0 client is attempting a h2c direct connection.
|
||||
* This is not a standard HTTP/1.1 Upgrade path.
|
||||
/**
|
||||
* <p>Advances this parser after the {@link PrefaceFrame#PREFACE_PREAMBLE_BYTES}.</p>
|
||||
* <p>This allows the HTTP/1.1 parser to parse the preamble of the preface,
|
||||
* which is a legal HTTP/1.1 request, and this parser will parse the remaining
|
||||
* bytes, that are not parseable by a HTTP/1.1 parser.</p>
|
||||
*/
|
||||
public void directUpgrade()
|
||||
protected void directUpgrade()
|
||||
{
|
||||
if (cursor!=0)
|
||||
if (cursor != 0)
|
||||
throw new IllegalStateException();
|
||||
cursor=18;
|
||||
cursor = PrefaceFrame.PREFACE_PREAMBLE_BYTES.length;
|
||||
}
|
||||
|
||||
|
||||
public boolean parse(ByteBuffer buffer)
|
||||
{
|
||||
while (buffer.hasRemaining())
|
||||
|
|
|
@ -41,20 +41,25 @@ public class ServerParser extends Parser
|
|||
this.prefaceParser = new PrefaceParser(listener);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Unsafe upgrade is an unofficial upgrade from HTTP/1.0 to HTTP/2.0
|
||||
* initiated when a the <code>org.eclipse.jetty.server.HttpConnection</code> sees a PRI * HTTP/2.0 prefix
|
||||
* that indicates a HTTP/2.0 client is attempting a h2c direct connection.
|
||||
* This is not a standard HTTP/1.1 Upgrade path.
|
||||
/**
|
||||
* <p>A direct upgrade is an unofficial upgrade from HTTP/1.1 to HTTP/2.0.</p>
|
||||
* <p>A direct upgrade is initiated when {@code org.eclipse.jetty.server.HttpConnection}
|
||||
* sees a request with these bytes:</p>
|
||||
* <pre>
|
||||
* PRI * HTTP/2.0\r\n
|
||||
* \r\n
|
||||
* </pre>
|
||||
* <p>This request is part of the HTTP/2.0 preface, indicating that a
|
||||
* HTTP/2.0 client is attempting a h2c direct connection.</p>
|
||||
* <p>This is not a standard HTTP/1.1 Upgrade path.</p>
|
||||
*/
|
||||
public void directUpgrade()
|
||||
{
|
||||
if (state!=State.PREFACE)
|
||||
if (state != State.PREFACE)
|
||||
throw new IllegalStateException();
|
||||
prefaceParser.directUpgrade();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void parse(ByteBuffer buffer)
|
||||
{
|
||||
|
|
|
@ -25,7 +25,6 @@ import org.eclipse.jetty.http2.FlowControlStrategy;
|
|||
import org.eclipse.jetty.http2.HTTP2Connection;
|
||||
import org.eclipse.jetty.http2.api.server.ServerSessionListener;
|
||||
import org.eclipse.jetty.http2.generator.Generator;
|
||||
import org.eclipse.jetty.http2.parser.Parser;
|
||||
import org.eclipse.jetty.http2.parser.ServerParser;
|
||||
import org.eclipse.jetty.io.Connection;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
|
@ -43,7 +42,7 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
|
|||
|
||||
public AbstractHTTP2ServerConnectionFactory(@Name("config") HttpConfiguration httpConfiguration)
|
||||
{
|
||||
this(httpConfiguration,"h2-17","h2-16","h2-15","h2-14","h2");
|
||||
this(httpConfiguration,"h2","h2-17","h2-16","h2-15","h2-14");
|
||||
}
|
||||
|
||||
protected AbstractHTTP2ServerConnectionFactory(@Name("config") HttpConfiguration httpConfiguration, String... protocols)
|
||||
|
@ -103,7 +102,7 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
|
|||
// stream idle timeout will expire earlier that the connection's.
|
||||
session.setStreamIdleTimeout(endPoint.getIdleTimeout());
|
||||
|
||||
Parser parser = newServerParser(connector, session);
|
||||
ServerParser parser = newServerParser(connector, session);
|
||||
HTTP2Connection connection = new HTTP2ServerConnection(connector.getByteBufferPool(), connector.getExecutor(),
|
||||
endPoint, httpConfiguration, parser, session, getInputBufferSize(), listener);
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ public class HTTP2CServerConnectionFactory extends HTTP2ServerConnectionFactory
|
|||
|
||||
public HTTP2CServerConnectionFactory(@Name("config") HttpConfiguration httpConfiguration)
|
||||
{
|
||||
super(httpConfiguration,"h2c","h2c-14");
|
||||
super(httpConfiguration,"h2c","h2c-17","h2c-16","h2c-15","h2c-14");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -71,7 +71,7 @@ public class HTTP2CServerConnectionFactory extends HTTP2ServerConnectionFactory
|
|||
return null;
|
||||
|
||||
HTTP2ServerConnection connection = (HTTP2ServerConnection)newConnection(connector, endPoint);
|
||||
if (connection.upgrade(request, response101))
|
||||
if (connection.upgrade(request))
|
||||
return connection;
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ import java.util.Queue;
|
|||
import java.util.concurrent.Executor;
|
||||
|
||||
import org.eclipse.jetty.http.BadMessageException;
|
||||
import org.eclipse.jetty.http.HttpFields;
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.eclipse.jetty.http.MetaData;
|
||||
|
@ -35,7 +35,6 @@ import org.eclipse.jetty.http2.api.server.ServerSessionListener;
|
|||
import org.eclipse.jetty.http2.frames.DataFrame;
|
||||
import org.eclipse.jetty.http2.frames.HeadersFrame;
|
||||
import org.eclipse.jetty.http2.frames.SettingsFrame;
|
||||
import org.eclipse.jetty.http2.parser.Parser;
|
||||
import org.eclipse.jetty.http2.parser.ServerParser;
|
||||
import org.eclipse.jetty.http2.parser.SettingsBodyParser;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
|
@ -56,7 +55,7 @@ public class HTTP2ServerConnection extends HTTP2Connection implements Connection
|
|||
private final HttpConfiguration httpConfig;
|
||||
private HeadersFrame upgradeRequest;
|
||||
|
||||
public HTTP2ServerConnection(ByteBufferPool byteBufferPool, Executor executor, EndPoint endPoint, HttpConfiguration httpConfig, Parser parser, ISession session, int inputBufferSize, ServerSessionListener listener)
|
||||
public HTTP2ServerConnection(ByteBufferPool byteBufferPool, Executor executor, EndPoint endPoint, HttpConfiguration httpConfig, ServerParser parser, ISession session, int inputBufferSize, ServerSessionListener listener)
|
||||
{
|
||||
super(byteBufferPool, executor, endPoint, parser, session, inputBufferSize);
|
||||
this.listener = listener;
|
||||
|
@ -64,11 +63,17 @@ public class HTTP2ServerConnection extends HTTP2Connection implements Connection
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onUpgradeTo(ByteBuffer prefilled)
|
||||
protected ServerParser getParser()
|
||||
{
|
||||
return (ServerParser)super.getParser();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgradeTo(ByteBuffer buffer)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("HTTP2 onUpgradeTo {} {}", this, BufferUtil.toDetailString(prefilled));
|
||||
prefill(prefilled);
|
||||
LOG.debug("HTTP2 onUpgradeTo {} {}", this, BufferUtil.toDetailString(buffer));
|
||||
setInputBuffer(buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -143,16 +148,19 @@ public class HTTP2ServerConnection extends HTTP2Connection implements Connection
|
|||
return channel;
|
||||
}
|
||||
|
||||
public boolean upgrade(Request request, HttpFields response101)
|
||||
public boolean upgrade(Request request)
|
||||
{
|
||||
if (HttpMethod.PRI.is(request.getMethod()))
|
||||
{
|
||||
((ServerParser)getParser()).directUpgrade();
|
||||
getParser().directUpgrade();
|
||||
}
|
||||
else
|
||||
{
|
||||
String value = request.getFields().getField(HttpHeader.HTTP2_SETTINGS).getValue();
|
||||
final byte[] settings = B64Code.decodeRFC4648URL(value);
|
||||
HttpField settingsField = request.getFields().getField(HttpHeader.HTTP2_SETTINGS);
|
||||
if (settingsField == null)
|
||||
throw new BadMessageException("Missing " + HttpHeader.HTTP2_SETTINGS + " header");
|
||||
String value = settingsField.getValue();
|
||||
final byte[] settings = B64Code.decodeRFC4648URL(value == null ? "" : value);
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("{} settings {}",this,TypeUtil.toHexString(settings));
|
||||
|
|
|
@ -31,33 +31,27 @@ import org.eclipse.jetty.server.Request;
|
|||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.ServerConnector;
|
||||
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
||||
|
||||
public class HTTP2CServer extends Server
|
||||
{
|
||||
public HTTP2CServer(int port)
|
||||
{
|
||||
// HTTP connector
|
||||
HttpConfiguration config = new HttpConfiguration();
|
||||
// HTTP + HTTP/2 connector
|
||||
ServerConnector http = new ServerConnector(this,new HttpConnectionFactory(config), new HTTP2CServerConnectionFactory(config));
|
||||
http.setHost("localhost");
|
||||
http.setPort(port);
|
||||
http.setIdleTimeout(30000);
|
||||
|
||||
// Set the connector
|
||||
addConnector(http);
|
||||
|
||||
// Set a handler
|
||||
((QueuedThreadPool)getThreadPool()).setName("server");
|
||||
|
||||
setHandler(new SimpleHandler());
|
||||
}
|
||||
|
||||
public static void main(String... args ) throws Exception
|
||||
{
|
||||
// The Server
|
||||
HTTP2CServer server = new HTTP2CServer(8080);
|
||||
|
||||
// Start the server
|
||||
server.start();
|
||||
server.join();
|
||||
}
|
||||
|
||||
private static class SimpleHandler extends AbstractHandler
|
||||
|
@ -78,6 +72,5 @@ public class HTTP2CServer extends Server
|
|||
response.setContentLength(content.length());
|
||||
response.getOutputStream().print(content);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,9 +18,7 @@
|
|||
|
||||
package org.eclipse.jetty.http2.server;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
import java.nio.ByteBuffer;
|
||||
|
@ -45,22 +43,27 @@ import org.eclipse.jetty.io.MappedByteBufferPool;
|
|||
import org.eclipse.jetty.server.NetworkConnector;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.eclipse.jetty.util.Utf8StringBuilder;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class HTTP2CServerTest extends AbstractServerTest
|
||||
{
|
||||
HTTP2CServer _server;
|
||||
int _port;
|
||||
private HTTP2CServer _server;
|
||||
private int _port;
|
||||
|
||||
@Before
|
||||
public void before() throws Exception
|
||||
{
|
||||
_server=new HTTP2CServer(0);
|
||||
_server = new HTTP2CServer(0);
|
||||
_server.start();
|
||||
_port=((NetworkConnector)_server.getConnectors()[0]).getLocalPort();
|
||||
_port = ((NetworkConnector)_server.getConnectors()[0]).getLocalPort();
|
||||
}
|
||||
|
||||
@After
|
||||
|
@ -79,8 +82,8 @@ public class HTTP2CServerTest extends AbstractServerTest
|
|||
|
||||
String response = IO.toString(client.getInputStream());
|
||||
|
||||
assertThat(response,containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(response,containsString("Hello from Jetty using HTTP/1.0"));
|
||||
assertThat(response, containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(response, containsString("Hello from Jetty using HTTP/1.0"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -95,24 +98,128 @@ public class HTTP2CServerTest extends AbstractServerTest
|
|||
|
||||
String response = IO.toString(client.getInputStream());
|
||||
|
||||
assertThat(response,containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(response,containsString("Hello from Jetty using HTTP/1.1"));
|
||||
assertThat(response,containsString("uri=/one"));
|
||||
assertThat(response,containsString("uri=/two"));
|
||||
assertThat(response, containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(response, containsString("Hello from Jetty using HTTP/1.1"));
|
||||
assertThat(response, containsString("uri=/one"));
|
||||
assertThat(response, containsString("uri=/two"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHTTP_2_0_Simple() throws Exception
|
||||
public void testHTTP_1_1_Upgrade() throws Exception
|
||||
{
|
||||
try (Socket client = new Socket("localhost", _port))
|
||||
{
|
||||
OutputStream output = client.getOutputStream();
|
||||
output.write(("" +
|
||||
"GET /one HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"Connection: Upgrade, HTTP2-Settings\r\n" +
|
||||
"Upgrade: h2c\r\n" +
|
||||
"HTTP2-Settings: \r\n" +
|
||||
"\r\n").getBytes(StandardCharsets.ISO_8859_1));
|
||||
output.flush();
|
||||
|
||||
InputStream input = client.getInputStream();
|
||||
Utf8StringBuilder upgrade = new Utf8StringBuilder();
|
||||
int crlfs = 0;
|
||||
while (true)
|
||||
{
|
||||
int read = input.read();
|
||||
if (read == '\r' || read == '\n')
|
||||
++crlfs;
|
||||
else
|
||||
crlfs = 0;
|
||||
upgrade.append((byte)read);
|
||||
if (crlfs == 4)
|
||||
break;
|
||||
}
|
||||
|
||||
assertTrue(upgrade.toString().startsWith("HTTP/1.1 101 "));
|
||||
|
||||
byteBufferPool = new MappedByteBufferPool();
|
||||
generator = new Generator(byteBufferPool);
|
||||
|
||||
final AtomicReference<HeadersFrame> headersRef = new AtomicReference<>();
|
||||
final AtomicReference<DataFrame> dataRef = new AtomicReference<>();
|
||||
final AtomicReference<CountDownLatch> latchRef = new AtomicReference<>(new CountDownLatch(2));
|
||||
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onHeaders(HeadersFrame frame)
|
||||
{
|
||||
headersRef.set(frame);
|
||||
latchRef.get().countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onData(DataFrame frame)
|
||||
{
|
||||
dataRef.set(frame);
|
||||
latchRef.get().countDown();
|
||||
}
|
||||
}, 4096, 8192);
|
||||
|
||||
parseResponse(client, parser);
|
||||
|
||||
Assert.assertTrue(latchRef.get().await(5, TimeUnit.SECONDS));
|
||||
|
||||
HeadersFrame response = headersRef.get();
|
||||
Assert.assertNotNull(response);
|
||||
MetaData.Response responseMetaData = (MetaData.Response)response.getMetaData();
|
||||
Assert.assertEquals(200, responseMetaData.getStatus());
|
||||
|
||||
DataFrame responseData = dataRef.get();
|
||||
Assert.assertNotNull(responseData);
|
||||
|
||||
String content = BufferUtil.toString(responseData.getData());
|
||||
|
||||
// The upgrade request is seen as HTTP/1.1.
|
||||
assertThat(content, containsString("Hello from Jetty using HTTP/1.1"));
|
||||
assertThat(content, containsString("uri=/one"));
|
||||
|
||||
// Send a HTTP/2 request.
|
||||
headersRef.set(null);
|
||||
dataRef.set(null);
|
||||
latchRef.set(new CountDownLatch(2));
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.control(lease, new PrefaceFrame());
|
||||
MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP, new HostPortHttpField("localhost:" + _port), "/two", HttpVersion.HTTP_2, new HttpFields());
|
||||
generator.control(lease, new HeadersFrame(3, metaData, null, true));
|
||||
for (ByteBuffer buffer : lease.getByteBuffers())
|
||||
output.write(BufferUtil.toArray(buffer));
|
||||
output.flush();
|
||||
|
||||
parseResponse(client, parser);
|
||||
|
||||
Assert.assertTrue(latchRef.get().await(5, TimeUnit.SECONDS));
|
||||
|
||||
response = headersRef.get();
|
||||
Assert.assertNotNull(response);
|
||||
responseMetaData = (MetaData.Response)response.getMetaData();
|
||||
Assert.assertEquals(200, responseMetaData.getStatus());
|
||||
|
||||
responseData = dataRef.get();
|
||||
Assert.assertNotNull(responseData);
|
||||
|
||||
content = BufferUtil.toString(responseData.getData());
|
||||
|
||||
assertThat(content, containsString("Hello from Jetty using HTTP/2.0"));
|
||||
assertThat(content, containsString("uri=/two"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHTTP_2_0_Direct() throws Exception
|
||||
{
|
||||
final CountDownLatch latch = new CountDownLatch(3);
|
||||
|
||||
byteBufferPool= new MappedByteBufferPool();
|
||||
byteBufferPool = new MappedByteBufferPool();
|
||||
generator = new Generator(byteBufferPool);
|
||||
|
||||
ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
|
||||
generator.control(lease, new PrefaceFrame());
|
||||
MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP, new HostPortHttpField("localhost:"+_port), "/test", HttpVersion.HTTP_2, new HttpFields());
|
||||
MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP, new HostPortHttpField("localhost:" + _port), "/test", HttpVersion.HTTP_2, new HttpFields());
|
||||
|
||||
generator.control(lease, new HeadersFrame(1, metaData, null, true));
|
||||
|
||||
|
@ -163,8 +270,8 @@ public class HTTP2CServerTest extends AbstractServerTest
|
|||
|
||||
String s = BufferUtil.toString(responseData.getData());
|
||||
|
||||
assertThat(s,containsString("Hello from Jetty using HTTP/2.0"));
|
||||
assertThat(s,containsString("uri=/test"));
|
||||
assertThat(s, containsString("Hello from Jetty using HTTP/2.0"));
|
||||
assertThat(s, containsString("uri=/test"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,10 +29,10 @@ import org.eclipse.jetty.http.HttpGenerator;
|
|||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.HttpHeaderValue;
|
||||
import org.eclipse.jetty.http.HttpParser;
|
||||
import org.eclipse.jetty.http.HttpParser.RequestHandler;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.eclipse.jetty.http.MetaData;
|
||||
import org.eclipse.jetty.http.PreEncodedHttpField;
|
||||
import org.eclipse.jetty.http.HttpParser.RequestHandler;
|
||||
import org.eclipse.jetty.io.AbstractConnection;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.Connection;
|
||||
|
@ -245,7 +245,8 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
|
|||
// Continue or break?
|
||||
else if (filled<=0)
|
||||
{
|
||||
if (filled==0)
|
||||
// Be fill interested only if there was no connection upgrade.
|
||||
if (filled==0 && getEndPoint().getConnection()==this)
|
||||
fillInterested();
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue