Merge remote-tracking branch 'origin/master' into bug-359329

This commit is contained in:
Jan Bartel 2011-12-19 15:01:29 +11:00
commit 397aa79a50
28 changed files with 872 additions and 439 deletions

View File

@ -355,9 +355,8 @@ public abstract class AbstractHttpConnection extends AbstractConnection implemen
@Override
public String toString()
{
return String.format("%s@%x//%s,g=%s,p=%s",
getClass().getSimpleName(),
hashCode(),
return String.format("%s %s g=%s p=%s",
super.toString(),
_destination == null ? "?.?.?.?:??" : _destination.getAddress(),
_generator,
_parser);

View File

@ -1,7 +1,6 @@
package org.eclipse.jetty.client;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.lessThan;
import static org.hamcrest.Matchers.*;
import java.io.BufferedReader;
import java.io.File;
@ -100,6 +99,7 @@ public class SslBytesServerTest extends SslBytesTest
};
}
};
connector.setMaxIdleTime(2000);
// connector.setPort(5870);
connector.setPort(0);
@ -1181,6 +1181,54 @@ public class SslBytesServerTest extends SslBytesTest
closeClient(client);
}
@Ignore
@Test
public void testServerCloseClientDoesNotClose() throws Exception
{
final SSLSocket client = newClient();
final OutputStream clientOutput = client.getOutputStream();
SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow();
client.startHandshake();
Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS));
byte[] data = new byte[3 * 1024];
Arrays.fill(data, (byte)'Y');
String content = new String(data, "UTF-8");
automaticProxyFlow = proxy.startAutomaticFlow();
clientOutput.write(("" +
"POST / HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"Content-Type: text/plain\r\n" +
"Content-Length: " + content.length() + "\r\n" +
"Connection: close\r\n" +
"\r\n" +
content).getBytes("UTF-8"));
clientOutput.flush();
Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS));
BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream(), "UTF-8"));
String line = reader.readLine();
Assert.assertNotNull(line);
Assert.assertTrue(line.startsWith("HTTP/1.1 200 "));
while ((line = reader.readLine()) != null)
{
if (line.trim().length() == 0)
break;
}
// Check that we did not spin
Assert.assertThat(sslHandles.get(), lessThan(20));
Assert.assertThat(httpParses.get(), lessThan(50));
// TODO: instead of sleeping, we should expect the connection being closed by the idle timeout
// TODO: mechanism; unfortunately this now is not working, and this test fails because the idle
// TODO: timeout will not trigger.
TimeUnit.SECONDS.sleep(100);
closeClient(client);
}
private void assumeJavaVersionSupportsTLSRenegotiations()
{
// Due to a security bug, TLS renegotiations were disabled in JDK 1.6.0_19-21

View File

@ -0,0 +1,212 @@
package org.eclipse.jetty.client;
import static org.hamcrest.Matchers.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.channels.SocketChannel;
import java.util.Arrays;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpParser;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.Buffers;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.nio.AsyncConnection;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.toolchain.test.IO;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
public class TimeoutTest
{
private static final Logger logger = Log.getLogger(TimeoutTest.class);
private final AtomicInteger httpParses = new AtomicInteger();
private ExecutorService threadPool;
private Server server;
private int serverPort;
@Before
public void init() throws Exception
{
threadPool = Executors.newCachedThreadPool();
server = new Server();
SelectChannelConnector connector = new SelectChannelConnector()
{
@Override
protected AsyncConnection newConnection(SocketChannel channel, final AsyncEndPoint endPoint)
{
return new org.eclipse.jetty.server.AsyncHttpConnection(this,endPoint,getServer())
{
@Override
protected HttpParser newHttpParser(Buffers requestBuffers, EndPoint endPoint, HttpParser.EventHandler requestHandler)
{
return new HttpParser(requestBuffers,endPoint,requestHandler)
{
@Override
public int parseNext() throws IOException
{
System.out.print(".");
httpParses.incrementAndGet();
return super.parseNext();
}
};
}
};
}
};
connector.setMaxIdleTime(2000);
// connector.setPort(5870);
connector.setPort(0);
server.addConnector(connector);
server.setHandler(new AbstractHandler()
{
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException,
ServletException
{
request.setHandled(true);
String contentLength = request.getHeader("Content-Length");
if (contentLength != null)
{
int length = Integer.parseInt(contentLength);
ServletInputStream input = request.getInputStream();
for (int i = 0; i < length; ++i)
input.read();
}
}
});
server.start();
serverPort = connector.getLocalPort();
logger.debug(" => :{}",serverPort);
}
@After
public void destroy() throws Exception
{
if (server != null)
server.stop();
if (threadPool != null)
threadPool.shutdownNow();
}
private Socket newClient() throws IOException, InterruptedException
{
Socket client = new Socket("localhost",serverPort);
return client;
}
/**
* Test that performs a seemingly normal http POST request, but with
* a client that issues "connection: close", waits 100 seconds to
* do anything with the connection (at all), and then attempts to
* write a second POST request.
* <p>
* The connection should be closed by the server, and/or be closed
* due to a timeout on the socket.
*/
@Ignore
@Test
public void testServerCloseClientDoesNotClose() throws Exception
{
// Log.getLogger("").setDebugEnabled(true);
final Socket client = newClient();
final OutputStream clientOutput = client.getOutputStream();
byte[] data = new byte[3 * 1024];
Arrays.fill(data,(byte)'Y');
String content = new String(data,"UTF-8");
// The request section
StringBuilder req = new StringBuilder();
req.append("POST / HTTP/1.1\r\n");
req.append("Host: localhost\r\n");
req.append("Content-Type: text/plain\r\n");
req.append("Content-Length: ").append(content.length()).append("\r\n");
req.append("Connection: close\r\n");
req.append("\r\n");
// and now, the POST content section.
req.append(content);
// Send request to server
clientOutput.write(req.toString().getBytes("UTF-8"));
clientOutput.flush();
System.out.println("Client request #1 flushed");
InputStream in = null;
InputStreamReader isr = null;
BufferedReader reader = null;
try
{
in = client.getInputStream();
isr = new InputStreamReader(in);
reader = new BufferedReader(isr);
// Read the response header
String line = reader.readLine();
Assert.assertNotNull(line);
Assert.assertThat(line,startsWith("HTTP/1.1 200 "));
while ((line = reader.readLine()) != null)
{
if (line.trim().length() == 0)
{
break;
}
}
System.out.println("Got response header");
// Check that we did not spin
int httpParseCount = httpParses.get();
System.out.printf("Got %d http parses%n",httpParseCount);
Assert.assertThat(httpParseCount,lessThan(50));
// TODO: instead of sleeping, we should expect the connection being closed by the idle timeout
// TODO: mechanism; unfortunately this now is not working, and this test fails because the idle
// TODO: timeout will not trigger.
TimeUnit.SECONDS.sleep(100);
// Try to write another request (to prove that stream is closed)
clientOutput.write(req.toString().getBytes("UTF-8"));
clientOutput.flush();
Assert.fail("Should not have been able to send a second POST request (connection: close)");
}
finally
{
IO.close(reader);
IO.close(isr);
IO.close(in);
closeClient(client);
}
}
private void closeClient(Socket client) throws IOException
{
client.close();
}
}

View File

@ -62,12 +62,6 @@ public abstract class AbstractConnection implements Connection
public String toString()
{
return String.format("%s@%x//%s:%d<->%s:%d",
getClass().getSimpleName(),
hashCode(),
_endp.getLocalAddr(),
_endp.getLocalPort(),
_endp.getRemoteAddr(),
_endp.getRemotePort());
return String.format("%s@%x", getClass().getSimpleName(), hashCode());
}
}

View File

@ -280,7 +280,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
public void checkIdleTimestamp(long now)
{
long idleTimestamp=_idleTimestamp;
if (idleTimestamp!=0 && _maxIdleTime>0)
{
long idleForMs=now-idleTimestamp;
@ -709,24 +709,43 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
@Override
public String toString()
{
synchronized(this)
// Do NOT use synchronized (this)
// because it's very easy to deadlock when debugging is enabled.
// We do a best effort to print the right toString() and that's it.
SelectionKey key = _key;
String keyString = "";
if (key != null)
{
return String.format("SCEP@%x{%s->%s,d=%b,open=%b,ishut=%b,oshut=%b,rb=%b,wb=%b,w=%b,i=%d%s%s%s}",
hashCode(),
_socket.getRemoteSocketAddress(),
_socket.getLocalSocketAddress(),
_dispatched,
isOpen(),
isInputShutdown(),
isOutputShutdown(),
_readBlocked,
_writeBlocked,
_writable,
_interestOps,
_key != null && _key.isValid() ? "" : "!",
_key != null && _key.isValid() && _key.isReadable() ? "r" : "",
_key != null && _key.isValid() && _key.isWritable() ? "w" : "");
if (key.isValid())
{
if (key.isReadable())
keyString += "r";
if (key.isWritable())
keyString += "w";
}
else
{
keyString += "!";
}
}
else
{
keyString += "-";
}
return String.format("SCEP@%x{l(%s)<->r(%s),d=%b,open=%b,ishut=%b,oshut=%b,rb=%b,wb=%b,w=%b,i=%d%s}-{%s}",
hashCode(),
_socket.getRemoteSocketAddress(),
_socket.getLocalSocketAddress(),
_dispatched,
isOpen(),
isInputShutdown(),
isOutputShutdown(),
_readBlocked,
_writeBlocked,
_writable,
_interestOps,
keyString,
_connection);
}
/* ------------------------------------------------------------ */

View File

@ -190,9 +190,10 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
_connection=next;
progress=true;
}
// TODO: consider moving here hasProgressed() - it's only used in SSL
}
LOG.debug("{} handle {} progress=",_session,this, progress);
LOG.debug("{} handle {} progress={}", _session, this, progress);
}
}
finally
@ -322,13 +323,13 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
case NOT_HANDSHAKING:
{
// Try wrapping some application data
if (toFlush.hasContent() && _outbound.space()>0 && wrap(toFlush))
progress=true;
// Try unwrapping some application data
if (toFill.space()>0 && _inbound.hasContent() && unwrap(toFill))
progress=true;
// Try wrapping some application data
if (toFlush.hasContent() && _outbound.space()>0 && wrap(toFlush))
progress=true;
}
break;
@ -389,6 +390,9 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
some_progress|=progress;
}
if (toFill.hasContent())
_aEndp.asyncDispatch();
}
finally
{
@ -571,7 +575,7 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
public String toString()
{
return String.format("%s | %s", super.toString(), _sslEndPoint);
return String.format("%s %s", super.toString(), _sslEndPoint);
}
/* ------------------------------------------------------------ */
@ -628,7 +632,7 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
public int fill(Buffer buffer) throws IOException
{
int size=buffer.length();
process(buffer,null);
process(buffer, null);
int filled=buffer.length()-size;
@ -688,7 +692,7 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
public void flush() throws IOException
{
process(null,null);
process(null, null);
}
public void asyncDispatch()
@ -793,20 +797,20 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
public String toString()
{
int i;
int o;
int u;
synchronized(SslConnection.this)
{
i=_inbound==null?-1:_inbound.length();
o=_outbound==null?-1:_outbound.length();
u=_unwrapBuf==null?-1:_unwrapBuf.length();
}
return String.format("SSL:%s %s i/u/o=%d/%d/%d ishut=%b oshut=%b",
_endp,
// Do NOT use synchronized (SslConnection.this)
// because it's very easy to deadlock when debugging is enabled.
// We do a best effort to print the right toString() and that's it.
Buffer inbound = _inbound;
Buffer outbound = _outbound;
Buffer unwrap = _unwrapBuf;
int i = inbound == null? -1 : inbound.length();
int o = outbound == null ? -1 : outbound.length();
int u = unwrap == null ? -1 : unwrap.length();
return String.format("SSL %s i/o/u=%d/%d/%d ishut=%b oshut=%b {%s}",
_engine.getHandshakeStatus(),
i, u, o,
_ishut, _oshut);
i, o, u,
_ishut, _oshut,
_connection);
}
}
}

View File

@ -16,7 +16,6 @@ package org.eclipse.jetty.server;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

View File

@ -4,11 +4,11 @@
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
// The Eclipse Public License is available at
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
// You may elect to redistribute this code under either of these licenses.
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.server;
@ -16,7 +16,6 @@ package org.eclipse.jetty.server;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.Enumeration;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -56,14 +55,14 @@ public class Server extends HandlerWrapper implements Attributes
private static final String __version;
static
{
if (Server.class.getPackage()!=null &&
if (Server.class.getPackage()!=null &&
"Eclipse.org - Jetty".equals(Server.class.getPackage().getImplementationVendor()) &&
Server.class.getPackage().getImplementationVersion()!=null)
__version=Server.class.getPackage().getImplementationVersion();
else
__version=System.getProperty("jetty.version","7.x.y-SNAPSHOT");
}
private final Container _container=new Container();
private final AttributesMap _attributes = new AttributesMap();
private ThreadPool _threadPool;
@ -77,14 +76,14 @@ public class Server extends HandlerWrapper implements Attributes
private boolean _dumpAfterStart=false;
private boolean _dumpBeforeStop=false;
private boolean _uncheckedPrintWriter=false;
/* ------------------------------------------------------------ */
public Server()
{
setServer(this);
setServer(this);
}
/* ------------------------------------------------------------ */
/** Convenience constructor
* Creates server and a {@link SelectChannelConnector} at the passed port.
@ -97,7 +96,7 @@ public class Server extends HandlerWrapper implements Attributes
connector.setPort(port);
setConnectors(new Connector[]{connector});
}
/* ------------------------------------------------------------ */
/** Convenience constructor
* Creates server and a {@link SelectChannelConnector} at the passed address.
@ -118,7 +117,7 @@ public class Server extends HandlerWrapper implements Attributes
{
return __version;
}
/* ------------------------------------------------------------ */
/**
* @return Returns the container.
@ -133,7 +132,7 @@ public class Server extends HandlerWrapper implements Attributes
{
return _stopAtShutdown;
}
/* ------------------------------------------------------------ */
public void setStopAtShutdown(boolean stop)
{
@ -143,7 +142,7 @@ public class Server extends HandlerWrapper implements Attributes
else
ShutdownThread.deregister(this);
}
/* ------------------------------------------------------------ */
/**
* @return Returns the connectors.
@ -161,7 +160,7 @@ public class Server extends HandlerWrapper implements Attributes
/* ------------------------------------------------------------ */
/**
* Conveniance method which calls {@link #getConnectors()} and {@link #setConnectors(Connector[])} to
* Conveniance method which calls {@link #getConnectors()} and {@link #setConnectors(Connector[])} to
* remove a connector.
* @param connector The connector to remove.
*/
@ -181,7 +180,7 @@ public class Server extends HandlerWrapper implements Attributes
for (int i=0;i<connectors.length;i++)
connectors[i].setServer(this);
}
_container.update(this, _connectors, connectors, "connector");
_connectors = connectors;
}
@ -194,7 +193,7 @@ public class Server extends HandlerWrapper implements Attributes
{
return _threadPool;
}
/* ------------------------------------------------------------ */
/**
* @param threadPool The threadPool to set.
@ -240,32 +239,32 @@ public class Server extends HandlerWrapper implements Attributes
{
_dumpBeforeStop = dumpBeforeStop;
}
/* ------------------------------------------------------------ */
@Override
protected void doStart() throws Exception
{
if (getStopAtShutdown())
ShutdownThread.register(this);
LOG.info("jetty-"+__version);
HttpGenerator.setServerVersion(__version);
MultiException mex=new MultiException();
if (_threadPool==null)
setThreadPool(new QueuedThreadPool());
try
{
super.doStart();
}
catch(Throwable e)
{
try
{
super.doStart();
}
catch(Throwable e)
{
mex.add(e);
}
if (_connectors!=null)
{
for (int i=0;i<_connectors.length;i++)
@ -277,10 +276,10 @@ public class Server extends HandlerWrapper implements Attributes
}
}
}
if (isDumpAfterStart())
dumpStdErr();
mex.ifExceptionThrow();
}
@ -290,9 +289,9 @@ public class Server extends HandlerWrapper implements Attributes
{
if (isDumpBeforeStop())
dumpStdErr();
MultiException mex=new MultiException();
if (_graceful>0)
{
if (_connectors!=null)
@ -303,7 +302,7 @@ public class Server extends HandlerWrapper implements Attributes
try{_connectors[i].close();}catch(Throwable e){mex.add(e);}
}
}
Handler[] contexts = getChildHandlersByClass(Graceful.class);
for (int c=0;c<contexts.length;c++)
{
@ -313,7 +312,7 @@ public class Server extends HandlerWrapper implements Attributes
}
Thread.sleep(_graceful);
}
if (_connectors!=null)
{
for (int i=_connectors.length;i-->0;)
@ -321,7 +320,7 @@ public class Server extends HandlerWrapper implements Attributes
}
try {super.doStop(); } catch(Throwable e) { mex.add(e);}
mex.ifExceptionThrow();
if (getStopAtShutdown())
@ -339,7 +338,7 @@ public class Server extends HandlerWrapper implements Attributes
final String target=connection.getRequest().getPathInfo();
final Request request=connection.getRequest();
final Response response=connection.getResponse();
if (LOG.isDebugEnabled())
{
LOG.debug("REQUEST "+target+" on "+connection);
@ -349,7 +348,7 @@ public class Server extends HandlerWrapper implements Attributes
else
handle(target, request, request, response);
}
/* ------------------------------------------------------------ */
/* Handle a request from a connection.
* Called to handle a request on the connection when either the header has been received,
@ -378,7 +377,7 @@ public class Server extends HandlerWrapper implements Attributes
baseRequest.setRequestURI(null);
baseRequest.setPathInfo(baseRequest.getRequestURI());
if (uri.getQuery()!=null)
baseRequest.mergeQueryString(uri.getQuery());
baseRequest.mergeQueryString(uri.getQuery());
}
final String target=baseRequest.getPathInfo();
@ -395,10 +394,10 @@ public class Server extends HandlerWrapper implements Attributes
handle(target, baseRequest, request, response);
}
/* ------------------------------------------------------------ */
public void join() throws InterruptedException
public void join() throws InterruptedException
{
getThreadPool().join();
}
@ -490,8 +489,8 @@ public class Server extends HandlerWrapper implements Attributes
/**
* Add an associated bean.
* The bean will be added to the servers {@link Container}
* and if it is a {@link LifeCycle} instance, it will be
* started/stopped along with the Server. Any beans that are also
* and if it is a {@link LifeCycle} instance, it will be
* started/stopped along with the Server. Any beans that are also
* {@link Destroyable}, will be destroyed with the server.
* @param o the bean object to add
*/
@ -507,7 +506,7 @@ public class Server extends HandlerWrapper implements Attributes
}
/**
* Remove a LifeCycle object to be started/stopped
* Remove a LifeCycle object to be started/stopped
* along with the Server
* @deprecated Use {@link #removeBean(Object)}
*/
@ -516,7 +515,7 @@ public class Server extends HandlerWrapper implements Attributes
{
removeBean(c);
}
/* ------------------------------------------------------------ */
/**
* Remove an associated bean.
@ -533,7 +532,7 @@ public class Server extends HandlerWrapper implements Attributes
}
/* ------------------------------------------------------------ */
/*
/*
* @see org.eclipse.util.AttributesMap#clearAttributes()
*/
public void clearAttributes()
@ -542,7 +541,7 @@ public class Server extends HandlerWrapper implements Attributes
}
/* ------------------------------------------------------------ */
/*
/*
* @see org.eclipse.util.AttributesMap#getAttribute(java.lang.String)
*/
public Object getAttribute(String name)
@ -551,7 +550,7 @@ public class Server extends HandlerWrapper implements Attributes
}
/* ------------------------------------------------------------ */
/*
/*
* @see org.eclipse.util.AttributesMap#getAttributeNames()
*/
public Enumeration getAttributeNames()
@ -560,7 +559,7 @@ public class Server extends HandlerWrapper implements Attributes
}
/* ------------------------------------------------------------ */
/*
/*
* @see org.eclipse.util.AttributesMap#removeAttribute(java.lang.String)
*/
public void removeAttribute(String name)
@ -569,7 +568,7 @@ public class Server extends HandlerWrapper implements Attributes
}
/* ------------------------------------------------------------ */
/*
/*
* @see org.eclipse.util.AttributesMap#setAttribute(java.lang.String, java.lang.Object)
*/
public void setAttribute(String name, Object attribute)
@ -588,13 +587,13 @@ public class Server extends HandlerWrapper implements Attributes
/* ------------------------------------------------------------ */
/**
* Set graceful shutdown timeout. If set, the internal <code>doStop()</code> method will not immediately stop the
* Set graceful shutdown timeout. If set, the internal <code>doStop()</code> method will not immediately stop the
* server. Instead, all {@link Connector}s will be closed so that new connections will not be accepted
* and all handlers that implement {@link Graceful} will be put into the shutdown mode so that no new requests
* will be accepted, but existing requests can complete. The server will then wait the configured timeout
* will be accepted, but existing requests can complete. The server will then wait the configured timeout
* before stopping.
* @param timeoutMS the milliseconds to wait for existing request to complete before stopping the server.
*
*
*/
public void setGracefulShutdown(int timeoutMS)
{
@ -613,7 +612,7 @@ public class Server extends HandlerWrapper implements Attributes
public void dump(Appendable out,String indent) throws IOException
{
dumpThis(out);
dump(out,indent,TypeUtil.asList(getHandlers()),getBeans(),TypeUtil.asList(_connectors));
dump(out,indent,TypeUtil.asList(getHandlers()),getBeans(),TypeUtil.asList(_connectors));
}
@ -629,7 +628,7 @@ public class Server extends HandlerWrapper implements Attributes
_uncheckedPrintWriter=unchecked;
}
/* ------------------------------------------------------------ */
/* A handler that can be gracefully shutdown.
* Called by doStop if a {@link #setGracefulShutdown} period is set.

View File

@ -13,10 +13,6 @@
package org.eclipse.jetty.server;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertTrue;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@ -29,14 +25,12 @@ import java.net.URL;
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.Exchanger;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import junit.framework.Assert;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.util.IO;
@ -44,6 +38,10 @@ import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.StdErrLog;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertTrue;
/**
*
*/
@ -222,7 +220,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
// Read the response
String response=readResponse(client);
// Check the response
assertEquals("response "+i,RESPONSE2,response);
}
@ -378,7 +376,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
try
{
URL url=new URL(_scheme+"://"+HOST+":"+_connector.getLocalPort()+"/?writes="+w+"&block="+b+ (e==0?"":("&encoding="+encoding[e]))+(c==0?"&chars=true":""));
InputStream in = (InputStream)url.getContent();
String response=IO.toString(in,e==0?null:encoding[e]);
@ -453,7 +451,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
client.close();
}
}
@Test
public void testBlockingWhileWritingResponseContent() throws Exception
{
@ -521,7 +519,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
"\r\n"
).getBytes());
os.flush();
// read the chunked response header
boolean chunked=false;
boolean closed=false;
@ -530,13 +528,13 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
String line=in.readLine();
if (line==null || line.length()==0)
break;
chunked|="Transfer-Encoding: chunked".equals(line);
closed|="Connection: close".equals(line);
}
Assert.assertTrue(chunked);
Assert.assertFalse(closed);
// Read the chunks
int max=Integer.MIN_VALUE;
while(true)
@ -550,22 +548,22 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
if (max<len)
max=len;
}
// Check that a direct content buffer was used as a chunk
Assert.assertEquals(128*1024,max);
// read and check the times are < 999ms
String[] times=in.readLine().split(",");
for (String t: times)
Assert.assertTrue(Integer.valueOf(t).intValue()<999);
// read the EOF chunk
String end=in.readLine();
Assert.assertEquals("0",end);
end=in.readLine();
Assert.assertEquals(0,end.length());
// read the non-chunked response header
chunked=false;
@ -575,13 +573,13 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
String line=in.readLine();
if (line==null || line.length()==0)
break;
chunked|="Transfer-Encoding: chunked".equals(line);
closed|="Connection: close".equals(line);
}
Assert.assertFalse(chunked);
Assert.assertTrue(closed);
String bigline = in.readLine();
Assert.assertEquals(10*128*1024,bigline.length());
@ -589,7 +587,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
times=in.readLine().split(",");
for (String t: times)
Assert.assertTrue(t,Integer.valueOf(t).intValue()<999);
// check close
Assert.assertTrue(in.readLine()==null);
}
@ -607,7 +605,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
byte[] buf = new byte[128*1024];
for (int i=0;i<buf.length;i++)
buf[i]=(byte)("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_".charAt(i%63));
baseRequest.setHandled(true);
response.setStatus(200);
response.setContentType("text/plain");
@ -631,7 +629,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
out.close();
}
}
@Test
public void testPipeline() throws Exception
@ -796,14 +794,14 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
"content-length: 10\r\n"+
"\015\012"+
"123456789\n" +
"HEAD /R1 HTTP/1.1\015\012"+
"Host: "+HOST+":"+_connector.getLocalPort()+"\015\012"+
"content-type: text/plain; charset=utf-8\r\n"+
"content-length: 10\r\n"+
"\015\012"+
"123456789\n"+
"POST /R1 HTTP/1.1\015\012"+
"Host: "+HOST+":"+_connector.getLocalPort()+"\015\012"+
"content-type: text/plain; charset=utf-8\r\n"+
@ -811,25 +809,25 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
"Connection: close\015\012"+
"\015\012"+
"123456789\n"
).getBytes("iso-8859-1"));
String in = IO.toString(is);
int index=in.indexOf("123456789");
assertTrue(index>0);
index=in.indexOf("123456789",index+1);
assertTrue(index>0);
index=in.indexOf("123456789",index+1);
assertTrue(index==-1);
}
finally
{
client.close();
}
}
@Test
public void testRecycledReaders() throws Exception
{
@ -909,27 +907,27 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
"Connection: Keep-Alive\r\n"+
"\r\n"
).getBytes());
// Never send a body.
// HelloWorldHandler does not read content, so 100 is not sent.
// So close will have to happen anyway, without reset!
os.flush();
client.setSoTimeout(2000);
long start=System.currentTimeMillis();
String in = IO.toString(is);
assertTrue(System.currentTimeMillis()-start<1000);
assertTrue(in.indexOf("Connection: close")>0);
assertTrue(in.indexOf("Hello world")>0);
}
finally
{
client.close();
}
}
@Test
public void testCommittedError() throws Exception
{
@ -950,25 +948,25 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
"\r\n"
).getBytes());
os.flush();
client.setSoTimeout(2000);
String in = IO.toString(is);
assertEquals(-1,is.read()); // Closed by error!
assertTrue(in.indexOf("HTTP/1.1 200 OK")>=0);
assertTrue(in.indexOf("Transfer-Encoding: chunked")>0);
assertTrue(in.indexOf("Now is the time for all good men to come to the aid of the party")>0);
assertTrue(in.indexOf("\r\n0\r\n")==-1); // chunking is interrupted by error close
client.close();
Thread.sleep(100);
Thread.sleep(100);
assertTrue(!handler._endp.isOpen());
}
finally
{
((StdErrLog)Log.getLogger(AbstractHttpConnection.class)).setHideStacks(false);
if (!client.isClosed())
client.close();
}
@ -977,7 +975,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
protected static class CommittedErrorHandler extends AbstractHandler
{
public EndPoint _endp;
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
_endp=baseRequest.getConnection().getEndPoint();
@ -987,15 +985,15 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
response.getWriter().println("Now is the time for all good men to come to the aid of the party");
response.getWriter().flush();
response.flushBuffer();
throw new ServletException(new Exception("exception after commit"));
}
}
protected static class AvailableHandler extends AbstractHandler
{
public Exchanger<Object> _ex = new Exchanger<Object>();
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
baseRequest.setHandled(true);
@ -1003,31 +1001,31 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
response.setContentType("text/plain");
InputStream in = request.getInputStream();
ServletOutputStream out=response.getOutputStream();
// should always be some input available, because of deferred dispatch.
int avail=in.available();
out.println(avail);
String buf="";
for (int i=0;i<avail;i++)
buf+=(char)in.read();
avail=in.available();
out.println(avail);
try
{
_ex.exchange(null);
_ex.exchange(null);
_ex.exchange(null);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
avail=in.available();
if (avail==0)
{
// handle blocking channel connectors
@ -1047,15 +1045,15 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
for (int i=0;i<avail;i++)
buf+=(char)in.read();
avail=in.available();
out.println(avail);
out.println(buf);
out.close();
}
}
@Test
public void testAvailable() throws Exception
{
@ -1082,7 +1080,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
"1234567890"
).getBytes());
os.flush();
ah._ex.exchange(null);
os.write((
@ -1091,7 +1089,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
os.flush();
Thread.sleep(500);
ah._ex.exchange(null);
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
// skip header
while(reader.readLine().length()>0);
@ -1100,7 +1098,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
assertEquals(20,Integer.parseInt(reader.readLine()));
assertEquals(0,Integer.parseInt(reader.readLine()));
assertEquals("1234567890abcdefghijklmnopqrst",reader.readLine());
}
finally
{
@ -1108,7 +1106,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
}
}
@Test
public void testDualRequest1() throws Exception
{
@ -1206,5 +1204,5 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
}
}

View File

@ -1,12 +1,10 @@
package org.eclipse.jetty.server.handler;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.BufferedReader;
import java.io.EOFException;
import java.io.IOException;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.regex.Matcher;
@ -18,6 +16,9 @@ import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.junit.AfterClass;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* @version $Revision$ $Date$
*/
@ -91,11 +92,21 @@ public abstract class AbstractConnectHandlerTest
StringBuilder body = new StringBuilder();
if (headers.containsKey("content-length"))
{
int readLen = 0;
int length = Integer.parseInt(headers.get("content-length"));
for (int i = 0; i < length; ++i)
try
{
char c = (char)reader.read();
body.append(c);
for (int i = 0; i < length; ++i)
{
char c = (char)reader.read();
body.append(c);
readLen++;
}
}
catch (SocketTimeoutException e)
{
System.err.printf("Read %,d bytes (out of an expected %,d bytes)%n",readLen,length);
throw e;
}
}
else if ("chunked".equals(headers.get("transfer-encoding")))
@ -126,7 +137,7 @@ public abstract class AbstractConnectHandlerTest
protected Socket newSocket() throws IOException
{
Socket socket = new Socket("localhost", proxyConnector.getLocalPort());
socket.setSoTimeout(5000);
socket.setSoTimeout(10000);
return socket;
}

View File

@ -14,23 +14,17 @@
package org.eclipse.jetty.server.handler;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import junit.framework.Assert;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.LocalConnector;
import org.eclipse.jetty.server.Request;
@ -38,6 +32,10 @@ import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.resource.Resource;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
* @version $Revision$
*/
@ -122,22 +120,22 @@ public class ContextHandlerTest
server.setConnectors(new Connector[] { connector });
ContextHandlerCollection contexts = new ContextHandlerCollection();
server.setHandler(contexts);
ContextHandler rootA = new ContextHandler(contexts,"/");
ContextHandler fooA = new ContextHandler(contexts,"/foo");
ContextHandler foobarA = new ContextHandler(contexts,"/foo/bar");
server.start();
// System.err.println(server.dump());
Assert.assertEquals(rootA._scontext,rootA._scontext.getContext("/"));
Assert.assertEquals(fooA._scontext,rootA._scontext.getContext("/foo"));
Assert.assertEquals(foobarA._scontext,rootA._scontext.getContext("/foo/bar"));
Assert.assertEquals(foobarA._scontext,rootA._scontext.getContext("/foo/bar/bob.jsp"));
Assert.assertEquals(rootA._scontext,rootA._scontext.getContext("/other"));
Assert.assertEquals(fooA._scontext,rootA._scontext.getContext("/foo/other"));
Assert.assertEquals(rootA._scontext,foobarA._scontext.getContext("/"));
Assert.assertEquals(fooA._scontext,foobarA._scontext.getContext("/foo"));
Assert.assertEquals(foobarA._scontext,foobarA._scontext.getContext("/foo/bar"));
@ -145,7 +143,7 @@ public class ContextHandlerTest
Assert.assertEquals(rootA._scontext,foobarA._scontext.getContext("/other"));
Assert.assertEquals(fooA._scontext,foobarA._scontext.getContext("/foo/other"));
}
@Test
public void testContextVirtualGetContext() throws Exception
{
@ -154,45 +152,45 @@ public class ContextHandlerTest
server.setConnectors(new Connector[] { connector });
ContextHandlerCollection contexts = new ContextHandlerCollection();
server.setHandler(contexts);
ContextHandler rootA = new ContextHandler(contexts,"/");
rootA.setVirtualHosts(new String[] {"a.com"});
ContextHandler rootB = new ContextHandler(contexts,"/");
rootB.setVirtualHosts(new String[] {"b.com"});
ContextHandler rootC = new ContextHandler(contexts,"/");
rootC.setVirtualHosts(new String[] {"c.com"});
ContextHandler fooA = new ContextHandler(contexts,"/foo");
fooA.setVirtualHosts(new String[] {"a.com"});
ContextHandler fooB = new ContextHandler(contexts,"/foo");
fooB.setVirtualHosts(new String[] {"b.com"});
ContextHandler foobarA = new ContextHandler(contexts,"/foo/bar");
foobarA.setVirtualHosts(new String[] {"a.com"});
server.start();
// System.err.println(server.dump());
Assert.assertEquals(rootA._scontext,rootA._scontext.getContext("/"));
Assert.assertEquals(fooA._scontext,rootA._scontext.getContext("/foo"));
Assert.assertEquals(foobarA._scontext,rootA._scontext.getContext("/foo/bar"));
Assert.assertEquals(foobarA._scontext,rootA._scontext.getContext("/foo/bar/bob"));
Assert.assertEquals(rootA._scontext,rootA._scontext.getContext("/other"));
Assert.assertEquals(rootB._scontext,rootB._scontext.getContext("/other"));
Assert.assertEquals(rootC._scontext,rootC._scontext.getContext("/other"));
Assert.assertEquals(fooB._scontext,rootB._scontext.getContext("/foo/other"));
Assert.assertEquals(rootC._scontext,rootC._scontext.getContext("/foo/other"));
}
@Test
public void testVirtualHostWildcard() throws Exception
{
@ -238,31 +236,31 @@ public class ContextHandlerTest
ContextHandler context = new ContextHandler("/");
// test singular
context.setVirtualHosts(new String[] { "www.example.com"} );
context.setVirtualHosts(new String[] { "www.example.com"} );
Assert.assertEquals(1,context.getVirtualHosts().length);
// test adding two more
context.addVirtualHosts(new String[] { "www.example2.com", "www.example3.com"});
Assert.assertEquals(3,context.getVirtualHosts().length);
// test adding existing context
context.addVirtualHosts(new String[] { "www.example.com" });
Assert.assertEquals(3,context.getVirtualHosts().length);
// test removing existing
context.removeVirtualHosts(new String[] { "www.example3.com" });
Assert.assertEquals(2,context.getVirtualHosts().length);
// test removing non-existent
context.removeVirtualHosts(new String[] { "www.example3.com" });
Assert.assertEquals(2,context.getVirtualHosts().length);
// test removing all remaining and resets to null
context.removeVirtualHosts(new String[] { "www.example.com", "www.example2.com" });
Assert.assertEquals(null,context.getVirtualHosts());
Assert.assertEquals(null,context.getVirtualHosts());
}
@Test
public void testAttributes() throws Exception
{
@ -332,7 +330,7 @@ public class ContextHandlerTest
return root;
}
@Test
public void testUncheckedPrintWriter() throws Exception
{
@ -348,7 +346,7 @@ public class ContextHandlerTest
try
{
server.start();
String response = connector.getResponses("GET / HTTP/1.1\n" + "Host: www.example.com.\n\n");
Assert.assertTrue(response.indexOf("Goodbye")>0);
@ -401,7 +399,7 @@ public class ContextHandlerTest
handled = false;
}
}
private static final class WriterHandler extends AbstractHandler
{
boolean error;

View File

@ -1,13 +1,12 @@
package org.eclipse.jetty.servlets;
import java.io.File;
import java.util.Arrays;
import java.util.List;
import javax.servlet.Servlet;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.gzip.GzipResponseWrapper;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlets.gzip.GzipTester;
import org.eclipse.jetty.servlets.gzip.TestServletLengthStreamTypeWrite;
@ -25,7 +24,7 @@ import org.junit.runners.Parameterized.Parameters;
/**
* Test the GzipFilter support for Content-Length setting variations.
*
*
* @see <a href="Eclipse Bug 354014">http://bugs.eclipse.org/354014</a>
*/
@RunWith(Parameterized.class)
@ -39,9 +38,9 @@ public class GzipFilterContentLengthTest
* in different order so as to simulate the real world scenario
* that caused the bug in Eclipse <a href="Bug 354014">http://bugs.eclipse.org/354014</a>
* <p>
* This test case will be run with each of the entries in
* This test case will be run with each of the entries in
* the array below as setup parameters for the test case.
*
*
* @return the junit parameters
*/
@Parameters
@ -49,7 +48,6 @@ public class GzipFilterContentLengthTest
{
return Arrays.asList(new Object[][]
{
{ DefaultServlet.class },
{ TestServletLengthStreamTypeWrite.class },
{ TestServletLengthTypeStreamWrite.class },
{ TestServletStreamLengthTypeWrite.class },
@ -77,7 +75,7 @@ public class GzipFilterContentLengthTest
{
GzipTester tester = new GzipTester(testingdir);
tester.prepareServerFile(filename,filesize);
File testfile = tester.prepareServerFile(testServlet.getSimpleName() + "-" + filename,filesize);
FilterHolder holder = tester.setContentServlet(testServlet);
holder.setInitParameter("mimeTypes","text/plain");
@ -85,7 +83,7 @@ public class GzipFilterContentLengthTest
try
{
tester.start();
tester.assertIsResponseGzipCompressed(filename);
tester.assertIsResponseGzipCompressed(testfile.getName());
}
finally
{
@ -97,7 +95,7 @@ public class GzipFilterContentLengthTest
{
GzipTester tester = new GzipTester(testingdir);
tester.prepareServerFile(filename,filesize);
File testfile = tester.prepareServerFile(testServlet.getSimpleName() + "-" + filename,filesize);
FilterHolder holder = tester.setContentServlet(testServlet);
holder.setInitParameter("mimeTypes","text/plain");
@ -105,7 +103,7 @@ public class GzipFilterContentLengthTest
try
{
tester.start();
tester.assertIsResponseNotGzipCompressed(filename,filesize,HttpStatus.OK_200);
tester.assertIsResponseNotGzipCompressed(testfile.getName(),filesize,HttpStatus.OK_200);
}
finally
{
@ -119,7 +117,7 @@ public class GzipFilterContentLengthTest
@Test
public void testIsGzipCompressedSmall() throws Exception
{
assertIsGzipCompressed("file.txt",SMALL);
assertIsGzipCompressed("file-small.txt",SMALL);
}
/**
@ -128,7 +126,7 @@ public class GzipFilterContentLengthTest
@Test
public void testIsGzipCompressedMedium() throws Exception
{
assertIsGzipCompressed("file.txt",MEDIUM);
assertIsGzipCompressed("file-med.txt",MEDIUM);
}
/**
@ -137,54 +135,54 @@ public class GzipFilterContentLengthTest
@Test
public void testIsGzipCompressedLarge() throws Exception
{
assertIsGzipCompressed("file.txt",LARGE);
assertIsGzipCompressed("file-large.txt",LARGE);
}
/**
* Tests for problems with Content-Length header on small size files
* Tests for problems with Content-Length header on small size files
* that are not being compressed encountered when using GzipFilter
*
*
* @see <a href="Eclipse Bug 354014">http://bugs.eclipse.org/354014</a>
*/
@Test
public void testIsNotGzipCompressedTiny() throws Exception
{
assertIsNotGzipCompressed("file.txt",TINY);
assertIsNotGzipCompressed("file-tiny.txt",TINY);
}
/**
* Tests for problems with Content-Length header on small size files
* Tests for problems with Content-Length header on small size files
* that are not being compressed encountered when using GzipFilter
*
*
* @see <a href="Eclipse Bug 354014">http://bugs.eclipse.org/354014</a>
*/
@Test
public void testIsNotGzipCompressedSmall() throws Exception
{
assertIsNotGzipCompressed("file.mp3",SMALL);
assertIsNotGzipCompressed("file-small.mp3",SMALL);
}
/**
* Tests for problems with Content-Length header on medium size files
* Tests for problems with Content-Length header on medium size files
* that are not being compressed encountered when using GzipFilter
*
*
* @see <a href="Eclipse Bug 354014">http://bugs.eclipse.org/354014</a>
*/
@Test
public void testIsNotGzipCompressedMedium() throws Exception
{
assertIsNotGzipCompressed("file.mp3",MEDIUM);
assertIsNotGzipCompressed("file-medium.mp3",MEDIUM);
}
/**
* Tests for problems with Content-Length header on large size files
* Tests for problems with Content-Length header on large size files
* that were not being compressed encountered when using GzipFilter
*
*
* @see <a href="Eclipse Bug 354014">http://bugs.eclipse.org/354014</a>
*/
@Test
public void testIsNotGzipCompressedLarge() throws Exception
{
assertIsNotGzipCompressed("file.mp3",LARGE);
assertIsNotGzipCompressed("file-large.mp3",LARGE);
}
}

View File

@ -1,8 +1,5 @@
package org.eclipse.jetty.servlets.gzip;
import static org.hamcrest.Matchers.*;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
@ -15,7 +12,6 @@ import java.util.Enumeration;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;
import javax.servlet.Servlet;
import javax.servlet.http.HttpServletResponse;
@ -30,6 +26,12 @@ import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.toolchain.test.TestingDir;
import org.junit.Assert;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
public class GzipTester
{
private Class<? extends GzipFilter> gzipFilterClass = GzipFilter.class;
@ -41,7 +43,7 @@ public class GzipTester
{
this.testdir = testingdir;
// Make sure we start with a clean testing directory.
this.testdir.ensureEmpty();
// DOES NOT WORK IN WINDOWS - this.testdir.ensureEmpty();
}
public void assertIsResponseGzipCompressed(String filename) throws Exception
@ -106,7 +108,7 @@ public class GzipTester
* <p>
* An example is to test that it is possible to configure GzipFilter to not recompress content that shouldn't be
* compressed by the GzipFilter.
*
*
* @param requestedFilename
* the filename used to on the GET request,.
* @param testResourceSha1Sum
@ -189,7 +191,7 @@ public class GzipTester
/**
* Asserts that the requested filename results in a properly structured GzipFilter response, where the content is
* not compressed, and the content-length is returned appropriately.
*
*
* @param filename
* the filename used for the request, and also used to compare the response to the server file, assumes
* that the file is suitable for {@link Assert#assertEquals(Object, Object)} use. (in other words, the
@ -230,7 +232,7 @@ public class GzipTester
Assert.assertThat("Response.header[Content-Length]",serverLength,is(expectedFilesize));
}
Assert.assertThat("Response.header[Content-Encoding]",response.getHeader("Content-Encoding"),not(containsString("gzip")));
// Assert that the contents are what we expect.
if (filename != null)
{
@ -256,13 +258,13 @@ public class GzipTester
}
}
}
/**
* Generate string content of arbitrary length.
*
*
* @param length
* the length of the string to generate.
* @return the string content.
@ -303,37 +305,42 @@ public class GzipTester
/**
* Create a file on the server resource path of a specified filename and size.
*
*
* @param filename
* the filename to create
* @param filesize
* the file size to create (Note: this isn't suitable for creating large multi-megabyte files)
*/
public void prepareServerFile(String filename, int filesize) throws IOException
public File prepareServerFile(String filename, int filesize) throws IOException
{
File testFile = testdir.getFile(filename);
File dir = testdir.getDir();
File testFile = new File(dir,filename);
// Make sure we have a uniq filename (to work around windows File.delete bug)
int i = 0;
while (testFile.exists())
{
testFile = new File(dir,(i++) + "-" + filename);
}
FileOutputStream fos = null;
BufferedOutputStream out = null;
ByteArrayInputStream in = null;
try
{
fos = new FileOutputStream(testFile,false);
out = new BufferedOutputStream(fos);
in = new ByteArrayInputStream(generateContent(filesize).getBytes(encoding));
IO.copy(in,out);
IO.copy(in,fos);
return testFile;
}
finally
{
IO.close(in);
IO.close(out);
IO.close(fos);
}
}
/**
* Copy a src/test/resource file into the server tree for eventual serving.
*
*
* @param filename
* the filename to look for in src/test/resources
*/
@ -341,13 +348,13 @@ public class GzipTester
{
File srcFile = MavenTestingUtils.getTestResourceFile(filename);
File testFile = testdir.getFile(filename);
IO.copy(srcFile,testFile);
}
/**
* Set the servlet that provides content for the GzipFilter in being tested.
*
*
* @param servletClass
* the servlet that will provide content.
* @return the FilterHolder for configuring the GzipFilter's initParameters with

View File

@ -141,7 +141,7 @@ public class WebSocketClientFactory extends AggregateLifeCycle
/* ------------------------------------------------------------ */
/**
* @return the shared mask generator, or null if no shared mask generator is used
* @see {@link WebSocketClient#getMaskGen()}
* @see WebSocketClient#getMaskGen()
*/
public MaskGen getMaskGen()
{
@ -151,7 +151,7 @@ public class WebSocketClientFactory extends AggregateLifeCycle
/* ------------------------------------------------------------ */
/**
* @param maskGen the shared mask generator, or null if no shared mask generator is used
* @see {@link WebSocketClient#setMaskGen(MaskGen)}
* @see WebSocketClient#setMaskGen(MaskGen)
*/
public void setMaskGen(MaskGen maskGen)
{

View File

@ -1,12 +1,8 @@
package org.eclipse.jetty.websocket;
import java.io.IOException;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.io.nio.AsyncConnection;
@ -14,8 +10,6 @@ public interface WebSocketConnection extends AsyncConnection
{
void fillBuffersFrom(Buffer buffer);
void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException;
List<Extension> getExtensions();
WebSocket.Connection getConnection();

View File

@ -19,10 +19,6 @@ import java.security.NoSuchAlgorithmException;
import java.util.Collections;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpURI;
import org.eclipse.jetty.io.AbstractConnection;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.Buffer;
@ -30,7 +26,6 @@ import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.nio.IndirectNIOBuffer;
import org.eclipse.jetty.util.QuotedStringTokenizer;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ -43,13 +38,13 @@ public class WebSocketConnectionD00 extends AbstractConnection implements WebSoc
public final static byte LENGTH_FRAME=(byte)0x80;
public final static byte SENTINEL_FRAME=(byte)0x00;
final WebSocketParser _parser;
final WebSocketGenerator _generator;
final WebSocket _websocket;
final String _protocol;
String _key1;
String _key2;
ByteArrayBuffer _hixieBytes;
private final WebSocketParser _parser;
private final WebSocketGenerator _generator;
private final WebSocket _websocket;
private final String _protocol;
private String _key1;
private String _key2;
private ByteArrayBuffer _hixieBytes;
public WebSocketConnectionD00(WebSocket websocket, EndPoint endpoint, WebSocketBuffers buffers, long timestamp, int maxIdleTime, String protocol)
throws IOException
@ -340,54 +335,6 @@ public class WebSocketConnectionD00 extends AbstractConnection implements WebSoc
}
}
public void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException
{
String uri=request.getRequestURI();
String query=request.getQueryString();
if (query!=null && query.length()>0)
uri+="?"+query;
uri=new HttpURI(uri).toString();
String host=request.getHeader("Host");
String origin=request.getHeader("Sec-WebSocket-Origin");
if (origin==null)
origin=request.getHeader("Origin");
if (origin!=null)
origin= QuotedStringTokenizer.quoteIfNeeded(origin, "\r\n");
String key1 = request.getHeader("Sec-WebSocket-Key1");
if (key1!=null)
{
String key2 = request.getHeader("Sec-WebSocket-Key2");
setHixieKeys(key1,key2);
response.setHeader("Upgrade","WebSocket");
response.addHeader("Connection","Upgrade");
if (origin!=null)
response.addHeader("Sec-WebSocket-Origin",origin);
response.addHeader("Sec-WebSocket-Location",(request.isSecure()?"wss://":"ws://")+host+uri);
if (subprotocol!=null)
response.addHeader("Sec-WebSocket-Protocol",subprotocol);
response.sendError(101,"WebSocket Protocol Handshake");
}
else
{
response.setHeader("Upgrade","WebSocket");
response.addHeader("Connection","Upgrade");
response.addHeader("WebSocket-Origin",origin);
response.addHeader("WebSocket-Location",(request.isSecure()?"wss://":"ws://")+host+uri);
if (subprotocol!=null)
response.addHeader("WebSocket-Protocol",subprotocol);
response.sendError(101,"Web Socket Protocol Handshake");
response.flushBuffer();
if (_websocket instanceof OnFrame)
((OnFrame)_websocket).onHandshake(this);
_websocket.onOpen(this);
}
}
public void setMaxTextMessageSize(int size)
{
}
@ -427,6 +374,19 @@ public class WebSocketConnectionD00 extends AbstractConnection implements WebSoc
{
return _protocol;
}
protected void onFrameHandshake()
{
if (_websocket instanceof OnFrame)
{
((OnFrame)_websocket).onHandshake(this);
}
}
protected void onWebsocketOpen()
{
_websocket.onOpen(this);
}
static class FrameHandlerD00 implements WebSocketParser.FrameHandler
{

View File

@ -19,9 +19,6 @@ import java.security.MessageDigest;
import java.util.Collections;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.io.AbstractConnection;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.Buffer;
@ -73,7 +70,6 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
}
}
private final static byte[] MAGIC;
private final WebSocketParser _parser;
private final WebSocketGenerator _generator;
@ -101,10 +97,6 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
}
private final WebSocketParser.FrameHandler _frameHandler= new FrameHandlerD06();
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
private final WebSocket.FrameConnection _connection = new FrameConnectionD06();
@ -287,9 +279,20 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
{
return Collections.emptyList();
}
protected void onFrameHandshake()
{
if (_onFrame!=null)
{
_onFrame.onHandshake(_connection);
}
}
protected void onWebSocketOpen()
{
_webSocket.onOpen(_connection);
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
private class FrameConnectionD06 implements WebSocket.FrameConnection
{
@ -487,6 +490,7 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
}
/* ------------------------------------------------------------ */
@Override
public String toString()
{
return this.getClass().getSimpleName()+"@"+_endp.getLocalAddr()+":"+_endp.getLocalPort()+"<->"+_endp.getRemoteAddr()+":"+_endp.getRemotePort();
@ -693,29 +697,13 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
_connection.close(code,message);
}
@Override
public String toString()
{
return WebSocketConnectionD06.this.toString()+"FH";
}
}
/* ------------------------------------------------------------ */
public void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException
{
String key = request.getHeader("Sec-WebSocket-Key");
response.setHeader("Upgrade","WebSocket");
response.addHeader("Connection","Upgrade");
response.addHeader("Sec-WebSocket-Accept",hashKey(key));
if (subprotocol!=null)
response.addHeader("Sec-WebSocket-Protocol",subprotocol);
response.sendError(101);
if (_onFrame!=null)
_onFrame.onHandshake(_connection);
_webSocket.onOpen(_connection);
}
/* ------------------------------------------------------------ */
public static String hashKey(String key)
{

View File

@ -19,16 +19,12 @@ import java.security.MessageDigest;
import java.util.Collections;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.io.AbstractConnection;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.nio.SelectChannelEndPoint;
import org.eclipse.jetty.util.B64Code;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.Utf8StringBuilder;
@ -110,7 +106,6 @@ public class WebSocketConnectionD08 extends AbstractConnection implements WebSoc
}
private final WebSocketParser.FrameHandler _frameHandler= new WSFrameHandler();
private final WebSocket.FrameConnection _connection = new WSFrameConnection();
@ -375,8 +370,19 @@ public class WebSocketConnectionD08 extends AbstractConnection implements WebSoc
}
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
protected void onFrameHandshake()
{
if (_onFrame != null)
{
_onFrame.onHandshake(_connection);
}
}
protected void onWebSocketOpen()
{
_webSocket.onOpen(_connection);
}
/* ------------------------------------------------------------ */
private class WSFrameConnection implements WebSocket.FrameConnection
{
@ -799,27 +805,6 @@ public class WebSocketConnectionD08 extends AbstractConnection implements WebSoc
}
}
/* ------------------------------------------------------------ */
public void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException
{
String key = request.getHeader("Sec-WebSocket-Key");
response.setHeader("Upgrade", "WebSocket");
response.addHeader("Connection","Upgrade");
response.addHeader("Sec-WebSocket-Accept",hashKey(key));
if (subprotocol!=null)
response.addHeader("Sec-WebSocket-Protocol",subprotocol);
for(Extension ext : _extensions)
response.addHeader("Sec-WebSocket-Extensions",ext.getParameterizedName());
response.sendError(101);
if (_onFrame!=null)
_onFrame.onHandshake(_connection);
_webSocket.onOpen(_connection);
}
/* ------------------------------------------------------------ */
public static String hashKey(String key)
{
@ -840,6 +825,6 @@ public class WebSocketConnectionD08 extends AbstractConnection implements WebSoc
@Override
public String toString()
{
return "WS/D"+_draft+"-"+_endp;
return String.format("WS/D%d p=%s g=%s", _draft, _parser, _generator);
}
}

View File

@ -19,16 +19,12 @@ import java.security.MessageDigest;
import java.util.Collections;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.io.AbstractConnection;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.nio.SelectChannelEndPoint;
import org.eclipse.jetty.util.B64Code;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.Utf8Appendable;
@ -397,8 +393,19 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
}
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
protected void onFrameHandshake()
{
if (_onFrame != null)
{
_onFrame.onHandshake(_connection);
}
}
protected void onWebSocketOpen()
{
_webSocket.onOpen(_connection);
}
/* ------------------------------------------------------------ */
private class WSFrameConnection implements WebSocket.FrameConnection
{
@ -916,27 +923,6 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
return WebSocketConnectionD13.this.toString()+"FH";
}
}
/* ------------------------------------------------------------ */
public void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException
{
String key = request.getHeader("Sec-WebSocket-Key");
response.setHeader("Upgrade","WebSocket");
response.addHeader("Connection","Upgrade");
response.addHeader("Sec-WebSocket-Accept",hashKey(key));
if (subprotocol!=null)
response.addHeader("Sec-WebSocket-Protocol",subprotocol);
for(Extension ext : _extensions)
response.addHeader("Sec-WebSocket-Extensions",ext.getParameterizedName());
response.sendError(101);
if (_onFrame!=null)
_onFrame.onHandshake(_connection);
_webSocket.onOpen(_connection);
}
/* ------------------------------------------------------------ */
public static String hashKey(String key)
@ -958,6 +944,6 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
@Override
public String toString()
{
return "WS/D"+_draft+"-"+_endp;
return String.format("WS/D%d p=%s g=%s", _draft, _parser, _generator);
}
}

View File

@ -20,7 +20,6 @@ import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -201,40 +200,43 @@ public class WebSocketFactory
ConnectedEndPoint endp = (ConnectedEndPoint)http.getEndPoint();
List<String> extensions_requested = new ArrayList<String>();
for (Enumeration e=request.getHeaders("Sec-WebSocket-Extensions");e.hasMoreElements();)
@SuppressWarnings("unchecked")
Enumeration<String> e = request.getHeaders("Sec-WebSocket-Extensions");
while (e.hasMoreElements())
{
QuotedStringTokenizer tok = new QuotedStringTokenizer((String)e.nextElement(),",");
QuotedStringTokenizer tok = new QuotedStringTokenizer(e.nextElement(),",");
while (tok.hasMoreTokens())
{
extensions_requested.add(tok.nextToken());
}
}
final WebSocketConnection connection;
final WebSocketServletConnection connection;
final List<Extension> extensions;
switch (draft)
{
case -1:
case 0:
extensions=Collections.emptyList();
connection = new WebSocketConnectionD00(websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol);
connection = new WebSocketServletConnectionD00(websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol);
break;
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 6:
extensions=Collections.emptyList();
connection = new WebSocketConnectionD06(websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol);
connection = new WebSocketServletConnectionD06(websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol);
break;
case 7:
case 8:
extensions= initExtensions(extensions_requested,8-WebSocketConnectionD08.OP_EXT_DATA, 16-WebSocketConnectionD08.OP_EXT_CTRL,3);
connection = new WebSocketConnectionD08(websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol,extensions,draft);
connection = new WebSocketServletConnectionD08(websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol,extensions,draft);
break;
case 13:
extensions= initExtensions(extensions_requested,8-WebSocketConnectionD13.OP_EXT_DATA, 16-WebSocketConnectionD13.OP_EXT_CTRL,3);
connection = new WebSocketConnectionD13(websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol,extensions,draft);
connection = new WebSocketServletConnectionD13(websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol,extensions,draft);
break;
default:
LOG.warn("Unsupported Websocket version: "+draft);
@ -292,7 +294,8 @@ public class WebSocketFactory
// Try each requested protocol
WebSocket websocket = null;
@SuppressWarnings("unchecked")
Enumeration<String> protocols = request.getHeaders("Sec-WebSocket-Protocol");
String protocol=null;
while (protocol==null && protocols!=null && protocols.hasMoreElements())
@ -314,7 +317,7 @@ public class WebSocketFactory
{
// Try with no protocol
websocket = _acceptor.doWebSocketConnect(request, null);
if (websocket==null)
{
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);

View File

@ -65,7 +65,7 @@ public class WebSocketGeneratorD13 implements WebSocketGenerator
throw new EofException("Closed");
if (opcode==WebSocketConnectionD13.OP_CLOSE)
_closed=true;
boolean mask=_maskGen!=null;
if (_buffer==null)
@ -240,4 +240,17 @@ public class WebSocketGeneratorD13 implements WebSocketGenerator
}
}
@Override
public String toString()
{
// Do NOT use synchronized (this)
// because it's very easy to deadlock when debugging is enabled.
// We do a best effort to print the right toString() and that's it.
Buffer buffer = _buffer;
return String.format("%s@%x closed=%b buffer=%d",
getClass().getSimpleName(),
hashCode(),
_closed,
buffer == null ? -1 : buffer.length());
}
}

View File

@ -125,7 +125,7 @@ public class WebSocketParserD13 implements WebSocketParser
{
if (_buffer==null)
_buffer=_buffers.getBuffer();
boolean progress=false;
int filled=-1;
@ -189,7 +189,7 @@ public class WebSocketParserD13 implements WebSocketParser
// Did we get enough?
if (available<(_state==State.SKIP?1:_bytesNeeded))
break;
// if we are here, then we have sufficient bytes to process the current state.
// Parse the buffer byte by byte (unless it is STATE_DATA)
byte b;
@ -307,7 +307,7 @@ public class WebSocketParserD13 implements WebSocketParser
if (_bytesNeeded==0)
_state=State.START;
break;
case SEEK_EOF:
progress=true;
_buffer.skip(available);
@ -349,7 +349,7 @@ public class WebSocketParserD13 implements WebSocketParser
break;
}
}
return progress?1:filled;
}
@ -380,8 +380,10 @@ public class WebSocketParserD13 implements WebSocketParser
@Override
public String toString()
{
Buffer buffer=_buffer;
return WebSocketParserD13.class.getSimpleName()+"@"+ Integer.toHexString(hashCode())+"|"+_state+"|"+(buffer==null?"<>":buffer.toDetailString());
return String.format("%s@%x state=%s buffer=%s",
getClass().getSimpleName(),
hashCode(),
_state,
_buffer);
}
}

View File

@ -4,17 +4,16 @@
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
// The Eclipse Public License is available at
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
// You may elect to redistribute this code under either of these licenses.
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.websocket;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
@ -39,12 +38,13 @@ import javax.servlet.http.HttpServletResponse;
* <p>
* The initParameter "maxBinaryMessagesSize" can be used to set the size in bytes
* that a websocket may be accept before closing.
*
*
*/
@SuppressWarnings("serial")
public abstract class WebSocketServlet extends HttpServlet implements WebSocketFactory.Acceptor
{
WebSocketFactory _webSocketFactory;
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.GenericServlet#init()
@ -57,15 +57,15 @@ public abstract class WebSocketServlet extends HttpServlet implements WebSocketF
String max=getInitParameter("maxIdleTime");
if (max!=null)
_webSocketFactory.setMaxIdleTime(Integer.parseInt(max));
max=getInitParameter("maxTextMessageSize");
if (max!=null)
_webSocketFactory.setMaxTextMessageSize(Integer.parseInt(max));
max=getInitParameter("maxBinaryMessageSize");
if (max!=null)
_webSocketFactory.setMaxBinaryMessageSize(Integer.parseInt(max));
}
/* ------------------------------------------------------------ */
@ -74,7 +74,7 @@ public abstract class WebSocketServlet extends HttpServlet implements WebSocketF
*/
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
{
if (_webSocketFactory.acceptWebSocket(request,response) || response.isCommitted())
return;
super.service(request,response);
@ -85,7 +85,7 @@ public abstract class WebSocketServlet extends HttpServlet implements WebSocketF
{
return true;
}
}

View File

@ -0,0 +1,10 @@
package org.eclipse.jetty.websocket;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public interface WebSocketServletConnection extends WebSocketConnection
{
void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException;
}

View File

@ -0,0 +1,77 @@
package org.eclipse.jetty.websocket;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpURI;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.util.QuotedStringTokenizer;
public class WebSocketServletConnectionD00 extends WebSocketConnectionD00 implements WebSocketServletConnection
{
public WebSocketServletConnectionD00(WebSocket websocket, EndPoint endpoint, WebSocketBuffers buffers, long timestamp, int maxIdleTime, String protocol)
throws IOException
{
super(websocket,endpoint,buffers,timestamp,maxIdleTime,protocol);
}
public void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException
{
String uri = request.getRequestURI();
String query = request.getQueryString();
if (query != null && query.length() > 0)
{
uri += "?" + query;
}
uri = new HttpURI(uri).toString();
String host = request.getHeader("Host");
String origin = request.getHeader("Sec-WebSocket-Origin");
if (origin == null)
{
origin = request.getHeader("Origin");
}
if (origin != null)
{
origin = QuotedStringTokenizer.quoteIfNeeded(origin,"\r\n");
}
String key1 = request.getHeader("Sec-WebSocket-Key1");
if (key1 != null)
{
String key2 = request.getHeader("Sec-WebSocket-Key2");
setHixieKeys(key1,key2);
response.setHeader("Upgrade","WebSocket");
response.addHeader("Connection","Upgrade");
if (origin != null)
{
response.addHeader("Sec-WebSocket-Origin",origin);
}
response.addHeader("Sec-WebSocket-Location",(request.isSecure()?"wss://":"ws://") + host + uri);
if (subprotocol != null)
{
response.addHeader("Sec-WebSocket-Protocol",subprotocol);
}
response.sendError(101,"WebSocket Protocol Handshake");
}
else
{
response.setHeader("Upgrade","WebSocket");
response.addHeader("Connection","Upgrade");
response.addHeader("WebSocket-Origin",origin);
response.addHeader("WebSocket-Location",(request.isSecure()?"wss://":"ws://") + host + uri);
if (subprotocol != null)
{
response.addHeader("WebSocket-Protocol",subprotocol);
}
response.sendError(101,"Web Socket Protocol Handshake");
response.flushBuffer();
onFrameHandshake();
onWebsocketOpen();
}
}
}

View File

@ -0,0 +1,35 @@
package org.eclipse.jetty.websocket;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.io.EndPoint;
public class WebSocketServletConnectionD06 extends WebSocketConnectionD06 implements WebSocketServletConnection
{
public WebSocketServletConnectionD06(WebSocket websocket, EndPoint endpoint, WebSocketBuffers buffers, long timestamp, int maxIdleTime, String protocol)
throws IOException
{
super(websocket,endpoint,buffers,timestamp,maxIdleTime,protocol);
}
/* ------------------------------------------------------------ */
public void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException
{
String key = request.getHeader("Sec-WebSocket-Key");
response.setHeader("Upgrade","WebSocket");
response.addHeader("Connection","Upgrade");
response.addHeader("Sec-WebSocket-Accept",hashKey(key));
if (subprotocol!=null)
{
response.addHeader("Sec-WebSocket-Protocol",subprotocol);
}
response.sendError(101);
onFrameHandshake();
onWebSocketOpen();
}
}

View File

@ -0,0 +1,47 @@
package org.eclipse.jetty.websocket;
import java.io.IOException;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.io.EndPoint;
public class WebSocketServletConnectionD08 extends WebSocketConnectionD08 implements WebSocketServletConnection
{
public WebSocketServletConnectionD08(WebSocket websocket, EndPoint endpoint, WebSocketBuffers buffers, long timestamp, int maxIdleTime, String protocol,
List<Extension> extensions, int draft, MaskGen maskgen) throws IOException
{
super(websocket,endpoint,buffers,timestamp,maxIdleTime,protocol,extensions,draft,maskgen);
}
public WebSocketServletConnectionD08(WebSocket websocket, EndPoint endpoint, WebSocketBuffers buffers, long timestamp, int maxIdleTime, String protocol,
List<Extension> extensions, int draft) throws IOException
{
super(websocket,endpoint,buffers,timestamp,maxIdleTime,protocol,extensions,draft);
}
/* ------------------------------------------------------------ */
public void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException
{
String key = request.getHeader("Sec-WebSocket-Key");
response.setHeader("Upgrade","WebSocket");
response.addHeader("Connection","Upgrade");
response.addHeader("Sec-WebSocket-Accept",hashKey(key));
if (subprotocol != null)
{
response.addHeader("Sec-WebSocket-Protocol",subprotocol);
}
for (Extension ext : getExtensions())
{
response.addHeader("Sec-WebSocket-Extensions",ext.getParameterizedName());
}
response.sendError(101);
onFrameHandshake();
onWebSocketOpen();
}
}

View File

@ -0,0 +1,47 @@
package org.eclipse.jetty.websocket;
import java.io.IOException;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.io.EndPoint;
public class WebSocketServletConnectionD13 extends WebSocketConnectionD13 implements WebSocketServletConnection
{
public WebSocketServletConnectionD13(WebSocket websocket, EndPoint endpoint, WebSocketBuffers buffers, long timestamp, int maxIdleTime, String protocol,
List<Extension> extensions, int draft, MaskGen maskgen) throws IOException
{
super(websocket,endpoint,buffers,timestamp,maxIdleTime,protocol,extensions,draft,maskgen);
}
public WebSocketServletConnectionD13(WebSocket websocket, EndPoint endpoint, WebSocketBuffers buffers, long timestamp, int maxIdleTime, String protocol,
List<Extension> extensions, int draft) throws IOException
{
super(websocket,endpoint,buffers,timestamp,maxIdleTime,protocol,extensions,draft);
}
/* ------------------------------------------------------------ */
public void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException
{
String key = request.getHeader("Sec-WebSocket-Key");
response.setHeader("Upgrade","WebSocket");
response.addHeader("Connection","Upgrade");
response.addHeader("Sec-WebSocket-Accept",hashKey(key));
if (subprotocol != null)
{
response.addHeader("Sec-WebSocket-Protocol",subprotocol);
}
for (Extension ext : getExtensions())
{
response.addHeader("Sec-WebSocket-Extensions",ext.getParameterizedName());
}
response.sendError(101);
onFrameHandshake();
onWebSocketOpen();
}
}