This commit is contained in:
Thomas Becker 2013-01-28 15:27:03 +01:00
commit 80b44f9940
133 changed files with 2460 additions and 5202 deletions

View File

@ -1,18 +1,34 @@
jetty-9.0.0-SNAPSHOT jetty-9.0.0-SNAPSHOT
jetty-9.0.0.M5 - 26 December 2012 jetty-9.0.0.M5 - 19 January 2013
+ 367638 throw exception for excess form keys + 367638 throw exception for excess form keys
+ 381521 Only set Vary header when content could be compressed
+ 391623 Making --stop with STOP.WAIT perform graceful shutdown + 391623 Making --stop with STOP.WAIT perform graceful shutdown
+ 393158 java.lang.IllegalStateException when sending an empty InputStream + 393158 java.lang.IllegalStateException when sending an empty InputStream
+ 393220 remove dead code from ServletHandler and log ServletExceptions in + 393220 remove dead code from ServletHandler and log ServletExceptions in
warn instead of debug warn instead of debug
+ 393733 WebSocketClient interface should support multiple connections
+ 395885 ResourceCache should honor useFileMappedBuffer if set
+ 396253 FilterRegistration wrong order
+ 396459 Log specific message for empty request body for multipart mime + 396459 Log specific message for empty request body for multipart mime
requests requests
+ 396500 HttpClient Exchange takes forever to complete when less content sent
than Content-Length
+ 396886 MultiPartFilter strips bad escaping on filename="..." + 396886 MultiPartFilter strips bad escaping on filename="..."
+ 397110 Accept %uXXXX encodings in URIs + 397110 Accept %uXXXX encodings in URIs
+ 397111 Allow multipart bodies with leading blank lines + 397111 Tolerate empty or excessive whitespace preceeding MultiParts
+ 397112 Requests with byte-range throws NPE if requested file has no mimetype + 397112 Requests with byte-range throws NPE if requested file has no mimetype
(eg no file extension) (eg no file extension)
+ 397114 run-forked with waitForChild=false can lock up
+ 397130 maxFormContentSize set in jetty.xml is ignored
+ 397190 improve ValidUrlRule to iterate on codepoints
+ 397321 Wrong condition in default start.config for annotations
+ 397535 Support pluggable alias checking to support symbolic links
+ 397769 TimerScheduler does not relinquish cancelled tasks.
+ 398105 Clean up WebSocketPolicy
+ 398285 ProxyServlet mixes cookies from different clients.
+ 398337 UTF-16 percent encoding in UTF-16 form content
+ 398582 Move lib/jta jar into lib/jndi
+ JETTY-1533 handle URL with no path + JETTY-1533 handle URL with no path
jetty-9.0.0.M4 - 21 December 2012 jetty-9.0.0.M4 - 21 December 2012

View File

@ -14,6 +14,8 @@
<Item>org.eclipse.jetty.webapp.WebXmlConfiguration</Item> <Item>org.eclipse.jetty.webapp.WebXmlConfiguration</Item>
<Item>org.eclipse.jetty.webapp.MetaInfConfiguration</Item> <Item>org.eclipse.jetty.webapp.MetaInfConfiguration</Item>
<Item>org.eclipse.jetty.webapp.FragmentConfiguration</Item> <Item>org.eclipse.jetty.webapp.FragmentConfiguration</Item>
<Item>org.eclipse.jetty.plus.webapp.EnvConfiguration</Item>
<Item>org.eclipse.jetty.plus.webapp.PlusConfiguration</Item>
<Item>org.eclipse.jetty.annotations.AnnotationConfiguration</Item> <Item>org.eclipse.jetty.annotations.AnnotationConfiguration</Item>
<Item>org.eclipse.jetty.webapp.JettyWebXmlConfiguration</Item> <Item>org.eclipse.jetty.webapp.JettyWebXmlConfiguration</Item>
</Array> </Array>

View File

@ -481,10 +481,6 @@ public class HttpClient extends ContainerLifeCycle
if (!Arrays.asList("http", "https").contains(scheme)) if (!Arrays.asList("http", "https").contains(scheme))
throw new IllegalArgumentException("Invalid protocol " + scheme); throw new IllegalArgumentException("Invalid protocol " + scheme);
for (Response.ResponseListener listener : listeners)
if (listener instanceof Schedulable)
((Schedulable)listener).schedule(scheduler);
HttpDestination destination = provideDestination(scheme, request.getHost(), request.getPort()); HttpDestination destination = provideDestination(scheme, request.getHost(), request.getPort());
destination.send(request, listeners); destination.send(request, listeners);
} }
@ -875,6 +871,16 @@ public class HttpClient extends ContainerLifeCycle
return encodingField; return encodingField;
} }
protected HttpConnection newHttpConnection(HttpClient httpClient, EndPoint endPoint, HttpDestination destination)
{
return new HttpConnection(httpClient, endPoint, destination);
}
protected SslConnection newSslConnection(HttpClient httpClient, EndPoint endPoint, SSLEngine engine)
{
return new SslConnection(httpClient.getByteBufferPool(), httpClient.getExecutor(), endPoint, engine);
}
@Override @Override
public void dump(Appendable out, String indent) throws IOException public void dump(Appendable out, String indent) throws IOException
{ {
@ -920,12 +926,9 @@ public class HttpClient extends ContainerLifeCycle
SSLEngine engine = sslContextFactory.newSSLEngine(endPoint.getRemoteAddress()); SSLEngine engine = sslContextFactory.newSSLEngine(endPoint.getRemoteAddress());
engine.setUseClientMode(true); engine.setUseClientMode(true);
SslConnection sslConnection = new SslConnection(getByteBufferPool(), getExecutor(), endPoint, engine); SslConnection sslConnection = newSslConnection(HttpClient.this, endPoint, engine);
// TODO: configureConnection => implies we should use SslConnectionFactory to do it
EndPoint appEndPoint = sslConnection.getDecryptedEndPoint(); EndPoint appEndPoint = sslConnection.getDecryptedEndPoint();
HttpConnection connection = new HttpConnection(HttpClient.this, appEndPoint, destination); HttpConnection connection = newHttpConnection(HttpClient.this, appEndPoint, destination);
// TODO: configureConnection, see above
appEndPoint.setConnection(connection); appEndPoint.setConnection(connection);
callback.promise.succeeded(connection); callback.promise.succeeded(connection);
@ -935,8 +938,7 @@ public class HttpClient extends ContainerLifeCycle
} }
else else
{ {
HttpConnection connection = new HttpConnection(HttpClient.this, endPoint, destination); HttpConnection connection = newHttpConnection(HttpClient.this, endPoint, destination);
// TODO: configureConnection, see above
callback.promise.succeeded(connection); callback.promise.succeeded(connection);
return connection; return connection;
} }

View File

@ -22,7 +22,7 @@ import java.io.UnsupportedEncodingException;
import java.net.HttpCookie; import java.net.HttpCookie;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.nio.charset.UnsupportedCharsetException; import java.nio.charset.UnsupportedCharsetException;
import java.util.Collections; import java.util.ArrayList;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
@ -108,7 +108,16 @@ public class HttpConnection extends AbstractConnection implements Connection
@Override @Override
public void send(Request request, Response.CompleteListener listener) public void send(Request request, Response.CompleteListener listener)
{ {
send(request, Collections.<Response.ResponseListener>singletonList(listener)); ArrayList<Response.ResponseListener> listeners = new ArrayList<>(2);
if (request.getTimeout() > 0)
{
TimeoutCompleteListener timeoutListener = new TimeoutCompleteListener(request);
timeoutListener.schedule(client.getScheduler());
listeners.add(timeoutListener);
}
if (listener != null)
listeners.add(listener);
send(request, listeners);
} }
public void send(Request request, List<Response.ResponseListener> listeners) public void send(Request request, List<Response.ResponseListener> listeners)
@ -125,10 +134,6 @@ public class HttpConnection extends AbstractConnection implements Connection
setExchange(exchange); setExchange(exchange);
conversation.getExchanges().offer(exchange); conversation.getExchanges().offer(exchange);
for (Response.ResponseListener listener : listeners)
if (listener instanceof Schedulable)
((Schedulable)listener).schedule(client.getScheduler());
sender.send(exchange); sender.send(exchange);
} }

View File

@ -36,7 +36,6 @@ import org.eclipse.jetty.client.api.ProxyConfiguration;
import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.client.api.Response; import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.client.api.Result; import org.eclipse.jetty.client.api.Result;
import org.eclipse.jetty.client.util.TimedResponseListener;
import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpMethod;
@ -509,8 +508,9 @@ public class HttpDestination implements Destination, AutoCloseable, Dumpable
.scheme(HttpScheme.HTTP.asString()) .scheme(HttpScheme.HTTP.asString())
.method(HttpMethod.CONNECT) .method(HttpMethod.CONNECT)
.path(target) .path(target)
.header(HttpHeader.HOST.asString(), target); .header(HttpHeader.HOST.asString(), target)
connection.send(connect, new TimedResponseListener(client.getConnectTimeout(), TimeUnit.MILLISECONDS, connect, new Response.CompleteListener() .timeout(client.getConnectTimeout(), TimeUnit.MILLISECONDS);
connection.send(connect, new Response.CompleteListener()
{ {
@Override @Override
public void onComplete(Result result) public void onComplete(Result result)
@ -534,7 +534,7 @@ public class HttpDestination implements Destination, AutoCloseable, Dumpable
} }
} }
} }
})); });
} }
} }
} }

View File

@ -178,14 +178,7 @@ public class HttpExchange
// Request and response completed // Request and response completed
LOG.debug("{} complete", this); LOG.debug("{} complete", this);
if (isLast()) if (isLast())
{
HttpExchange first = conversation.getExchanges().peekFirst();
List<Response.ResponseListener> listeners = first.getResponseListeners();
for (Response.ResponseListener listener : listeners)
if (listener instanceof Schedulable)
((Schedulable)listener).cancel();
conversation.complete(); conversation.complete();
}
} }
result = new Result(getRequest(), getRequestFailure(), getResponse(), getResponseFailure()); result = new Result(getRequest(), getRequestFailure(), getResponse(), getResponseFailure());
} }

View File

@ -426,7 +426,7 @@ public class HttpRequest implements Request
public ContentResponse send() throws InterruptedException, TimeoutException, ExecutionException public ContentResponse send() throws InterruptedException, TimeoutException, ExecutionException
{ {
FutureResponseListener listener = new FutureResponseListener(this); FutureResponseListener listener = new FutureResponseListener(this);
send(listener); send(this, listener);
long timeout = getTimeout(); long timeout = getTimeout();
if (timeout <= 0) if (timeout <= 0)
@ -447,10 +447,21 @@ public class HttpRequest implements Request
@Override @Override
public void send(Response.CompleteListener listener) public void send(Response.CompleteListener listener)
{
if (getTimeout() > 0)
{
TimeoutCompleteListener timeoutListener = new TimeoutCompleteListener(this);
timeoutListener.schedule(client.getScheduler());
responseListeners.add(timeoutListener);
}
send(this, listener);
}
private void send(Request request, Response.CompleteListener listener)
{ {
if (listener != null) if (listener != null)
responseListeners.add(listener); responseListeners.add(listener);
client.send(this, responseListeners); client.send(request, responseListeners);
} }
@Override @Override

View File

@ -0,0 +1,70 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// 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
// 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.
// ========================================================================
//
package org.eclipse.jetty.client;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.client.api.Result;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.thread.Scheduler;
public class TimeoutCompleteListener implements Response.CompleteListener, Runnable
{
private static final Logger LOG = Log.getLogger(TimeoutCompleteListener.class);
private final AtomicReference<Scheduler.Task> task = new AtomicReference<>();
private final Request request;
public TimeoutCompleteListener(Request request)
{
this.request = request;
}
@Override
public void onComplete(Result result)
{
Scheduler.Task task = this.task.getAndSet(null);
if (task != null)
{
boolean cancelled = task.cancel();
LOG.debug("Cancelled (successfully: {}) timeout task {}", cancelled, task);
}
}
public boolean schedule(Scheduler scheduler)
{
long timeout = request.getTimeout();
Scheduler.Task task = scheduler.schedule(this, timeout, TimeUnit.MILLISECONDS);
if (this.task.getAndSet(task) != null)
throw new IllegalStateException();
LOG.debug("Scheduled timeout task {} in {} ms", task, timeout);
return true;
}
@Override
public void run()
{
request.abort(new TimeoutException("Total timeout elapsed"));
}
}

View File

@ -1,169 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// 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
// 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.
// ========================================================================
//
package org.eclipse.jetty.client.util;
import java.nio.ByteBuffer;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.jetty.client.Schedulable;
import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.client.api.Result;
import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.thread.Scheduler;
/**
* Implementation of {@link Response.Listener} that allows to specify a timeout for asynchronous
* operations.
* <p />
* {@link TimedResponseListener} may be used to decorate a delegate {@link Response.CompleteListener}
* provided by the application. Events are forwarded by {@link TimedResponseListener} to the delegate
* listener.
* Alternatively, {@link TimedResponseListener} may be subclassed to override callbacks that are
* interesting to the application, typically {@link #onComplete(Result)}.
* <p />
* If the timeout specified at the constructor elapses, the request is {@link Request#abort(Throwable) aborted}
* with a {@link TimeoutException}.
* <p />
* Typical usage is:
* <pre>
* Request request = httpClient.newRequest(...)...;
* TimedResponseListener listener = new TimedResponseListener(5, TimeUnit.SECONDS, request, new Response.CompleteListener()
* {
* public void onComplete(Result result)
* {
* // Invoked when request/response completes or when timeout elapses
*
* // Your logic here
* }
* });
* request.send(listener); // Asynchronous send
* </pre>
*/
public class TimedResponseListener implements Response.Listener, Schedulable, Runnable
{
private static final Logger LOG = Log.getLogger(TimedResponseListener.class);
private final AtomicReference<Scheduler.Task> task = new AtomicReference<>();
private final long timeout;
private final TimeUnit unit;
private final Request request;
private final Response.CompleteListener delegate;
public TimedResponseListener(long timeout, TimeUnit unit, Request request)
{
this(timeout, unit, request, new Empty());
}
public TimedResponseListener(long timeout, TimeUnit unit, Request request, Response.CompleteListener delegate)
{
this.timeout = timeout;
this.unit = unit;
this.request = request;
this.delegate = delegate;
}
@Override
public void onBegin(Response response)
{
if (delegate instanceof Response.BeginListener)
((Response.BeginListener)delegate).onBegin(response);
}
@Override
public boolean onHeader(Response response, HttpField field)
{
if (delegate instanceof Response.HeaderListener)
return ((Response.HeaderListener)delegate).onHeader(response, field);
return true;
}
@Override
public void onHeaders(Response response)
{
if (delegate instanceof Response.HeadersListener)
((Response.HeadersListener)delegate).onHeaders(response);
}
@Override
public void onContent(Response response, ByteBuffer content)
{
if (delegate instanceof Response.ContentListener)
((Response.ContentListener)delegate).onContent(response, content);
}
@Override
public void onSuccess(Response response)
{
if (delegate instanceof Response.SuccessListener)
((Response.SuccessListener)delegate).onSuccess(response);
}
@Override
public void onFailure(Response response, Throwable failure)
{
if (delegate instanceof Response.FailureListener)
((Response.FailureListener)delegate).onFailure(response, failure);
}
@Override
public void onComplete(Result result)
{
delegate.onComplete(result);
}
public boolean schedule(Scheduler scheduler)
{
Scheduler.Task task = this.task.get();
if (task != null)
return false;
task = scheduler.schedule(this, timeout, unit);
if (this.task.compareAndSet(null, task))
{
LOG.debug("Scheduled timeout task {} in {} ms", task, unit.toMillis(timeout));
return true;
}
else
{
task.cancel();
return false;
}
}
@Override
public void run()
{
request.abort(new TimeoutException("Total timeout elapsed"));
}
public boolean cancel()
{
Scheduler.Task task = this.task.get();
if (task == null)
return false;
boolean result = task.cancel();
LOG.debug("Cancelled timeout task {}", task);
return result;
}
}

View File

@ -23,7 +23,8 @@ import java.io.IOException;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.net.ssl.SSLEngine;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@ -35,11 +36,13 @@ import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.client.api.Result; import org.eclipse.jetty.client.api.Result;
import org.eclipse.jetty.client.util.BufferingResponseListener; import org.eclipse.jetty.client.util.BufferingResponseListener;
import org.eclipse.jetty.client.util.InputStreamContentProvider; import org.eclipse.jetty.client.util.InputStreamContentProvider;
import org.eclipse.jetty.client.util.TimedResponseListener; import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.ssl.SslConnection;
import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.toolchain.test.annotation.Slow; import org.eclipse.jetty.toolchain.test.annotation.Slow;
import org.eclipse.jetty.util.IO; import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.hamcrest.Matchers;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
@ -71,8 +74,10 @@ public class HttpClientTimeoutTest extends AbstractHttpClientServerTest
start(new TimeoutHandler(2 * timeout)); start(new TimeoutHandler(2 * timeout));
final CountDownLatch latch = new CountDownLatch(1); final CountDownLatch latch = new CountDownLatch(1);
Request request = client.newRequest("localhost", connector.getLocalPort()).scheme(scheme); Request request = client.newRequest("localhost", connector.getLocalPort())
request.send(new TimedResponseListener(timeout, TimeUnit.MILLISECONDS, request) .scheme(scheme)
.timeout(timeout, TimeUnit.MILLISECONDS);
request.send(new Response.CompleteListener()
{ {
@Override @Override
public void onComplete(Result result) public void onComplete(Result result)
@ -96,8 +101,10 @@ public class HttpClientTimeoutTest extends AbstractHttpClientServerTest
// The first request has a long timeout // The first request has a long timeout
final CountDownLatch firstLatch = new CountDownLatch(1); final CountDownLatch firstLatch = new CountDownLatch(1);
Request request = client.newRequest("localhost", connector.getLocalPort()).scheme(scheme); Request request = client.newRequest("localhost", connector.getLocalPort())
request.send(new TimedResponseListener(4 * timeout, TimeUnit.MILLISECONDS, request) .scheme(scheme)
.timeout(4 * timeout, TimeUnit.MILLISECONDS);
request.send(new Response.CompleteListener()
{ {
@Override @Override
public void onComplete(Result result) public void onComplete(Result result)
@ -109,8 +116,10 @@ public class HttpClientTimeoutTest extends AbstractHttpClientServerTest
// Second request has a short timeout and should fail in the queue // Second request has a short timeout and should fail in the queue
final CountDownLatch secondLatch = new CountDownLatch(1); final CountDownLatch secondLatch = new CountDownLatch(1);
request = client.newRequest("localhost", connector.getLocalPort()).scheme(scheme); request = client.newRequest("localhost", connector.getLocalPort())
request.send(new TimedResponseListener(timeout, TimeUnit.MILLISECONDS, request) .scheme(scheme)
.timeout(timeout, TimeUnit.MILLISECONDS);
request.send(new Response.CompleteListener()
{ {
@Override @Override
public void onComplete(Result result) public void onComplete(Result result)
@ -137,8 +146,9 @@ public class HttpClientTimeoutTest extends AbstractHttpClientServerTest
final byte[] content = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; final byte[] content = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
Request request = client.newRequest("localhost", connector.getLocalPort()) Request request = client.newRequest("localhost", connector.getLocalPort())
.scheme(scheme) .scheme(scheme)
.content(new InputStreamContentProvider(new ByteArrayInputStream(content))); .content(new InputStreamContentProvider(new ByteArrayInputStream(content)))
request.send(new TimedResponseListener(2 * timeout, TimeUnit.MILLISECONDS, request, new BufferingResponseListener() .timeout(2 * timeout, TimeUnit.MILLISECONDS);
request.send(new BufferingResponseListener()
{ {
@Override @Override
public void onComplete(Result result) public void onComplete(Result result)
@ -147,7 +157,7 @@ public class HttpClientTimeoutTest extends AbstractHttpClientServerTest
Assert.assertArrayEquals(content, getContent()); Assert.assertArrayEquals(content, getContent());
latch.countDown(); latch.countDown();
} }
})); });
Assert.assertTrue(latch.await(3 * timeout, TimeUnit.MILLISECONDS)); Assert.assertTrue(latch.await(3 * timeout, TimeUnit.MILLISECONDS));
@ -167,8 +177,10 @@ public class HttpClientTimeoutTest extends AbstractHttpClientServerTest
Destination destination = client.getDestination(scheme, "localhost", connector.getLocalPort()); Destination destination = client.getDestination(scheme, "localhost", connector.getLocalPort());
try (Connection connection = destination.newConnection().get(5, TimeUnit.SECONDS)) try (Connection connection = destination.newConnection().get(5, TimeUnit.SECONDS))
{ {
Request request = client.newRequest("localhost", connector.getLocalPort()).scheme(scheme); Request request = client.newRequest("localhost", connector.getLocalPort())
connection.send(request, new TimedResponseListener(timeout, TimeUnit.MILLISECONDS, request) .scheme(scheme)
.timeout(timeout, TimeUnit.MILLISECONDS);
connection.send(request, new Response.CompleteListener()
{ {
@Override @Override
public void onComplete(Result result) public void onComplete(Result result)
@ -193,8 +205,10 @@ public class HttpClientTimeoutTest extends AbstractHttpClientServerTest
Destination destination = client.getDestination(scheme, "localhost", connector.getLocalPort()); Destination destination = client.getDestination(scheme, "localhost", connector.getLocalPort());
try (Connection connection = destination.newConnection().get(5, TimeUnit.SECONDS)) try (Connection connection = destination.newConnection().get(5, TimeUnit.SECONDS))
{ {
Request request = client.newRequest(destination.getHost(), destination.getPort()).scheme(scheme); Request request = client.newRequest(destination.getHost(), destination.getPort())
connection.send(request, new TimedResponseListener(2 * timeout, TimeUnit.MILLISECONDS, request) .scheme(scheme)
.timeout(2 * timeout, TimeUnit.MILLISECONDS);
connection.send(request, new Response.CompleteListener()
{ {
@Override @Override
public void onComplete(Result result) public void onComplete(Result result)
@ -214,6 +228,46 @@ public class HttpClientTimeoutTest extends AbstractHttpClientServerTest
} }
} }
@Test
public void testIdleTimeout() throws Throwable
{
long timeout = 1000;
start(new TimeoutHandler(2 * timeout));
client.stop();
final AtomicBoolean sslIdle = new AtomicBoolean();
client = new HttpClient(sslContextFactory)
{
@Override
protected SslConnection newSslConnection(HttpClient httpClient, EndPoint endPoint, SSLEngine engine)
{
return new SslConnection(httpClient.getByteBufferPool(), httpClient.getExecutor(), endPoint, engine)
{
@Override
protected boolean onReadTimeout()
{
sslIdle.set(true);
return super.onReadTimeout();
}
};
}
};
client.setIdleTimeout(timeout);
client.start();
try
{
client.newRequest("localhost", connector.getLocalPort())
.scheme(scheme)
.send();
Assert.fail();
}
catch (Exception x)
{
Assert.assertFalse(sslIdle.get());
Assert.assertThat(x.getCause(), Matchers.instanceOf(TimeoutException.class));
}
}
private class TimeoutHandler extends AbstractHandler private class TimeoutHandler extends AbstractHandler
{ {
private final long timeout; private final long timeout;

View File

@ -0,0 +1,77 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// 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
// 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.
// ========================================================================
//
package org.eclipse.jetty.client;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.toolchain.test.annotation.Slow;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
/**
* IdleTimeoutTest
*
* Warning - this is a slow test. Uncomment the ignore to run it.
*
*/
public class IdleTimeoutTest
{
public int _repetitions = 30;
@Slow
@Ignore
public void testIdleTimeoutOnBlockingConnector() throws Exception
{
final HttpClient client = new HttpClient();
client.setMaxConnectionsPerDestination(4);
client.setIdleTimeout(500); // very short idle timeout
client.start();
final CountDownLatch counter = new CountDownLatch(_repetitions);
Thread runner = new Thread()
{
public void run()
{
try
{
for (int i=0; i<_repetitions; i++)
{
ContentResponse response = client.GET("http://www.google.com/?i="+i);
counter.countDown();
System.err.println(counter.getCount());
Thread.sleep(1000); //wait long enough for idle timeout to expire
}
}
catch (Exception e)
{
Assert.fail(e.getMessage());
}
}
};
runner.start();
if (!counter.await(80, TimeUnit.SECONDS))
Assert.fail("Test did not complete in time");
}
}

View File

@ -289,7 +289,7 @@
<includeGroupIds>org.eclipse.jetty.orbit</includeGroupIds> <includeGroupIds>org.eclipse.jetty.orbit</includeGroupIds>
<includeArtifactIds>javax.transaction</includeArtifactIds> <includeArtifactIds>javax.transaction</includeArtifactIds>
<includeTypes>jar</includeTypes> <includeTypes>jar</includeTypes>
<outputDirectory>${assembly-directory}/lib/jta</outputDirectory> <outputDirectory>${assembly-directory}/lib/jndi</outputDirectory>
</configuration> </configuration>
</execution> </execution>
<execution> <execution>

View File

@ -127,11 +127,11 @@ OPTIONS=jsp
#=========================================================== #===========================================================
# Annotations JNDI JASS processing # Annotations JNDI JAAS processing
#----------------------------------------------------------- #-----------------------------------------------------------
# OPTIONS=annotations
# OPTIONS=plus # OPTIONS=plus
# etc/jetty-plus.xml # etc/jetty-plus.xml
# OPTIONS=annotations
# etc/jetty-annotations.xml # etc/jetty-annotations.xml
#=========================================================== #===========================================================

View File

@ -30,12 +30,12 @@ import org.eclipse.jetty.util.thread.Scheduler;
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** An Abstract implementation of an Idle Timeout. /** An Abstract implementation of an Idle Timeout.
* *
* This implementation is optimised that timeout operations are not cancelled on * This implementation is optimised that timeout operations are not cancelled on
* every operation. Rather timeout are allowed to expire and a check is then made * every operation. Rather timeout are allowed to expire and a check is then made
* to see when the last operation took place. If the idle timeout has not expired, * to see when the last operation took place. If the idle timeout has not expired,
* the timeout is rescheduled for the earliest possible time a timeout could occur. * the timeout is rescheduled for the earliest possible time a timeout could occur.
* *
*/ */
public abstract class IdleTimeout public abstract class IdleTimeout
{ {
@ -44,7 +44,7 @@ public abstract class IdleTimeout
private final AtomicReference<Scheduler.Task> _timeout = new AtomicReference<>(); private final AtomicReference<Scheduler.Task> _timeout = new AtomicReference<>();
private volatile long _idleTimeout; private volatile long _idleTimeout;
private volatile long _idleTimestamp=System.currentTimeMillis(); private volatile long _idleTimestamp=System.currentTimeMillis();
private final Runnable _idleTask = new Runnable() private final Runnable _idleTask = new Runnable()
{ {
@Override @Override
@ -63,12 +63,12 @@ public abstract class IdleTimeout
{ {
_scheduler=scheduler; _scheduler=scheduler;
} }
public long getIdleTimestamp() public long getIdleTimestamp()
{ {
return _idleTimestamp; return _idleTimestamp;
} }
public long getIdleTimeout() public long getIdleTimeout()
{ {
return _idleTimeout; return _idleTimeout;
@ -78,22 +78,22 @@ public abstract class IdleTimeout
{ {
long old=_idleTimeout; long old=_idleTimeout;
_idleTimeout = idleTimeout; _idleTimeout = idleTimeout;
// Do we have an old timeout // Do we have an old timeout
if (old>0) if (old>0)
{ {
// if the old was less than or equal to the new timeout, then nothing more to do // if the old was less than or equal to the new timeout, then nothing more to do
if (old<=_idleTimeout) if (old<=idleTimeout)
return; return;
// old timeout is too long, so cancel it. // old timeout is too long, so cancel it.
Scheduler.Task oldTimeout = _timeout.getAndSet(null); Scheduler.Task oldTimeout = _timeout.getAndSet(null);
if (oldTimeout != null) if (oldTimeout != null)
oldTimeout.cancel(); oldTimeout.cancel();
} }
// If we have a new timeout, then check and reschedule // If we have a new timeout, then check and reschedule
if (_idleTimeout>0 && isOpen()) if (idleTimeout>0 && isOpen())
_idleTask.run(); _idleTask.run();
} }
@ -103,7 +103,7 @@ public abstract class IdleTimeout
{ {
_idleTimestamp=System.currentTimeMillis(); _idleTimestamp=System.currentTimeMillis();
} }
private void scheduleIdleTimeout(long delay) private void scheduleIdleTimeout(long delay)
{ {
Scheduler.Task newTimeout = null; Scheduler.Task newTimeout = null;
@ -113,20 +113,20 @@ public abstract class IdleTimeout
if (oldTimeout != null) if (oldTimeout != null)
oldTimeout.cancel(); oldTimeout.cancel();
} }
public void onOpen() public void onOpen()
{ {
if (_idleTimeout>0) if (_idleTimeout>0)
_idleTask.run(); _idleTask.run();
} }
protected void close() protected void close()
{ {
Scheduler.Task oldTimeout = _timeout.getAndSet(null); Scheduler.Task oldTimeout = _timeout.getAndSet(null);
if (oldTimeout != null) if (oldTimeout != null)
oldTimeout.cancel(); oldTimeout.cancel();
} }
protected long checkIdleTimeout() protected long checkIdleTimeout()
{ {
if (isOpen()) if (isOpen())
@ -158,14 +158,14 @@ public abstract class IdleTimeout
} }
return -1; return -1;
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** This abstract method is called when the idle timeout has expired. /** This abstract method is called when the idle timeout has expired.
* @param timeout a TimeoutException * @param timeout a TimeoutException
*/ */
abstract protected void onIdleExpired(TimeoutException timeout); abstract protected void onIdleExpired(TimeoutException timeout);
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** This abstract method should be called to check if idle timeouts /** This abstract method should be called to check if idle timeouts
* should still be checked. * should still be checked.

View File

@ -100,7 +100,7 @@ public class SslConnection extends AbstractConnection
_decryptedEndPoint.getWriteFlusher().completeWrite(); _decryptedEndPoint.getWriteFlusher().completeWrite();
} }
}; };
public SslConnection(ByteBufferPool byteBufferPool, Executor executor, EndPoint endPoint, SSLEngine sslEngine) public SslConnection(ByteBufferPool byteBufferPool, Executor executor, EndPoint endPoint, SSLEngine sslEngine)
{ {
// This connection does not execute calls to onfillable, so they will be called by the selector thread. // This connection does not execute calls to onfillable, so they will be called by the selector thread.
@ -109,7 +109,7 @@ public class SslConnection extends AbstractConnection
this._bufferPool = byteBufferPool; this._bufferPool = byteBufferPool;
this._sslEngine = sslEngine; this._sslEngine = sslEngine;
this._decryptedEndPoint = newDecryptedEndPoint(); this._decryptedEndPoint = newDecryptedEndPoint();
if (endPoint instanceof SocketBased) if (endPoint instanceof SocketBased)
{ {
try try
@ -220,7 +220,6 @@ public class SslConnection extends AbstractConnection
// the decrypted readInterest and/or writeFlusher so that they will attempt // the decrypted readInterest and/or writeFlusher so that they will attempt
// to do the fill and/or flush again and these calls will do the actually // to do the fill and/or flush again and these calls will do the actually
// handle the cause. // handle the cause.
synchronized(_decryptedEndPoint) synchronized(_decryptedEndPoint)
{ {
_decryptedEndPoint.getFillInterest().onFail(cause); _decryptedEndPoint.getFillInterest().onFail(cause);
@ -480,13 +479,13 @@ public class SslConnection extends AbstractConnection
LOG.debug("{} filled {} encrypted bytes", SslConnection.this, net_filled); LOG.debug("{} filled {} encrypted bytes", SslConnection.this, net_filled);
if (net_filled > 0) if (net_filled > 0)
_underFlown = false; _underFlown = false;
// Let's try the SSL thang even if we have no net data because in that // Let's try the SSL thang even if we have no net data because in that
// case we want to fall through to the handshake handling // case we want to fall through to the handshake handling
int pos = BufferUtil.flipToFill(app_in); int pos = BufferUtil.flipToFill(app_in);
SSLEngineResult unwrapResult = _sslEngine.unwrap(_encryptedInput, app_in); SSLEngineResult unwrapResult = _sslEngine.unwrap(_encryptedInput, app_in);
BufferUtil.flipToFlush(app_in, pos); BufferUtil.flipToFlush(app_in, pos);
if (DEBUG) if (DEBUG)
LOG.debug("{} unwrap {}", SslConnection.this, unwrapResult); LOG.debug("{} unwrap {}", SslConnection.this, unwrapResult);
@ -661,7 +660,7 @@ public class SslConnection extends AbstractConnection
BufferUtil.flipToFlush(_encryptedOutput, pos); BufferUtil.flipToFlush(_encryptedOutput, pos);
if (wrapResult.bytesConsumed()>0) if (wrapResult.bytesConsumed()>0)
consumed+=wrapResult.bytesConsumed(); consumed+=wrapResult.bytesConsumed();
boolean all_consumed=true; boolean all_consumed=true;
// clear empty buffers to prevent position creeping up the buffer // clear empty buffers to prevent position creeping up the buffer
for (ByteBuffer b : appOuts) for (ByteBuffer b : appOuts)

View File

@ -20,11 +20,9 @@ package org.eclipse.jetty.io;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket; import java.net.Socket;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel; import java.nio.channels.SocketChannel;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLEngineResult; import javax.net.ssl.SSLEngineResult;
import javax.net.ssl.SSLEngineResult.HandshakeStatus; import javax.net.ssl.SSLEngineResult.HandshakeStatus;
@ -42,9 +40,7 @@ import org.junit.Test;
import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.greaterThan;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
public class SelectChannelEndPointSslTest extends SelectChannelEndPointTest public class SelectChannelEndPointSslTest extends SelectChannelEndPointTest
@ -226,51 +222,6 @@ public class SelectChannelEndPointSslTest extends SelectChannelEndPointTest
super.testIdle(); super.testIdle();
} }
@Override
public void testBlockedReadIdle() throws Exception
{
Socket client = newClient();
OutputStream clientOutputStream = client.getOutputStream();
client.setSoTimeout(5000);
SocketChannel server = _connector.accept();
server.configureBlocking(false);
_manager.accept(server);
// Write client to server
clientOutputStream.write("HelloWorld".getBytes("UTF-8"));
// Verify echo server to client
for (char c : "HelloWorld".toCharArray())
{
int b = client.getInputStream().read();
assertTrue(b>0);
assertEquals(c,(char)b);
}
assertTrue(_lastEndPointLatch.await(1, TimeUnit.SECONDS));
_lastEndPoint.setIdleTimeout(500);
// Write 8 and cause block waiting for 10
_blockAt=10;
clientOutputStream.write("12345678".getBytes("UTF-8"));
clientOutputStream.flush();
// read until idle shutdown received
long start=System.currentTimeMillis();
int b=client.getInputStream().read();
assertEquals(-1,b);
long idle=System.currentTimeMillis()-start;
assertTrue(idle>400);
assertTrue(idle<2000);
Thread.sleep(1000);
assertFalse(_lastEndPoint.isOpen());
}
@Test @Test
@Override @Override
@Stress("Requires a relatively idle (network wise) environment") @Stress("Requires a relatively idle (network wise) environment")

View File

@ -18,12 +18,6 @@
package org.eclipse.jetty.io; package org.eclipse.jetty.io;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.BufferedOutputStream; import java.io.BufferedOutputStream;
import java.io.IOException; import java.io.IOException;
@ -52,6 +46,12 @@ import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class SelectChannelEndPointTest public class SelectChannelEndPointTest
{ {
private static final Logger LOG = Log.getLogger(SelectChannelEndPointTest.class); private static final Logger LOG = Log.getLogger(SelectChannelEndPointTest.class);
@ -220,7 +220,7 @@ public class SelectChannelEndPointTest
{ {
Socket client = newClient(); Socket client = newClient();
client.setSoTimeout(60000); client.setSoTimeout(60000);
SocketChannel server = _connector.accept(); SocketChannel server = _connector.accept();
server.configureBlocking(false); server.configureBlocking(false);
@ -425,6 +425,7 @@ public class SelectChannelEndPointTest
public void testBlockedReadIdle() throws Exception public void testBlockedReadIdle() throws Exception
{ {
Socket client = newClient(); Socket client = newClient();
InputStream clientInputStream = client.getInputStream();
OutputStream clientOutputStream = client.getOutputStream(); OutputStream clientOutputStream = client.getOutputStream();
client.setSoTimeout(5000); client.setSoTimeout(5000);
@ -440,7 +441,7 @@ public class SelectChannelEndPointTest
// Verify echo server to client // Verify echo server to client
for (char c : "HelloWorld".toCharArray()) for (char c : "HelloWorld".toCharArray())
{ {
int b = client.getInputStream().read(); int b = clientInputStream.read();
assertTrue(b > 0); assertTrue(b > 0);
assertEquals(c, (char)b); assertEquals(c, (char)b);
} }
@ -456,7 +457,7 @@ public class SelectChannelEndPointTest
// read until idle shutdown received // read until idle shutdown received
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
int b = client.getInputStream().read(); int b = clientInputStream.read();
assertEquals('E', b); assertEquals('E', b);
long idle = System.currentTimeMillis() - start; long idle = System.currentTimeMillis() - start;
assertTrue(idle > idleTimeout / 2); assertTrue(idle > idleTimeout / 2);
@ -464,10 +465,12 @@ public class SelectChannelEndPointTest
for (char c : "E: 12345678".toCharArray()) for (char c : "E: 12345678".toCharArray())
{ {
b = client.getInputStream().read(); b = clientInputStream.read();
assertTrue(b > 0); assertTrue(b > 0);
assertEquals(c, (char)b); assertEquals(c, (char)b);
} }
b = clientInputStream.read();
assertEquals(-1,b);
// But endpoint is still open. // But endpoint is still open.
if(_lastEndPoint.isOpen()) if(_lastEndPoint.isOpen())

View File

@ -67,9 +67,7 @@
<Item>org.eclipse.jetty.webapp.FragmentConfiguration</Item> <Item>org.eclipse.jetty.webapp.FragmentConfiguration</Item>
<Item>org.eclipse.jetty.plus.webapp.EnvConfiguration</Item> <Item>org.eclipse.jetty.plus.webapp.EnvConfiguration</Item>
<Item>org.eclipse.jetty.plus.webapp.PlusConfiguration</Item> <Item>org.eclipse.jetty.plus.webapp.PlusConfiguration</Item>
<Item>org.eclipse.jetty.annotations.AnnotationConfiguration</Item>
<Item>org.eclipse.jetty.webapp.JettyWebXmlConfiguration</Item> <Item>org.eclipse.jetty.webapp.JettyWebXmlConfiguration</Item>
<Item>org.eclipse.jetty.webapp.TagLibConfiguration</Item>
</Array> </Array>
<!-- =========================================================== --> <!-- =========================================================== -->
@ -86,7 +84,6 @@
<Set name="monitoredDirName"><Property name="jetty.home" default="." />/webapps-plus</Set> <Set name="monitoredDirName"><Property name="jetty.home" default="." />/webapps-plus</Set>
<Set name="defaultsDescriptor"><Property name="jetty.home" default="."/>/etc/webdefault.xml</Set> <Set name="defaultsDescriptor"><Property name="jetty.home" default="."/>/etc/webdefault.xml</Set>
<Set name="scanInterval">5</Set> <Set name="scanInterval">5</Set>
<Set name="contextXmlDir"><Property name="jetty.home" default="." />/contexts</Set>
<Set name="parentLoaderPriority">false</Set> <Set name="parentLoaderPriority">false</Set>
<Set name="extractWars">true</Set> <Set name="extractWars">true</Set>
<Set name="configurationClasses"><Ref id="plusConfig"/></Set> <Set name="configurationClasses"><Ref id="plusConfig"/></Set>

View File

@ -43,7 +43,6 @@ import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.client.api.Response; import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.client.api.Result; import org.eclipse.jetty.client.api.Result;
import org.eclipse.jetty.client.util.InputStreamContentProvider; import org.eclipse.jetty.client.util.InputStreamContentProvider;
import org.eclipse.jetty.client.util.TimedResponseListener;
import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.HttpVersion;
@ -221,7 +220,7 @@ public class ProxyServlet extends HttpServlet
* <tr> * <tr>
* <td>timeout</td> * <td>timeout</td>
* <td>60000</td> * <td>60000</td>
* <td>The total timeout in milliseconds, see {@link TimedResponseListener}</td> * <td>The total timeout in milliseconds, see {@link Request#timeout(long, TimeUnit)}</td>
* </tr> * </tr>
* <tr> * <tr>
* <td>requestBufferSize</td> * <td>requestBufferSize</td>
@ -463,7 +462,8 @@ public class ProxyServlet extends HttpServlet
proxyRequest.getHeaders().toString().trim()); proxyRequest.getHeaders().toString().trim());
} }
proxyRequest.send(new TimedResponseListener(getTimeout(), TimeUnit.MILLISECONDS, proxyRequest, new ProxyResponseListener(request, response))); proxyRequest.timeout(getTimeout(), TimeUnit.MILLISECONDS);
proxyRequest.send(new ProxyResponseListener(request, response));
} }
protected void onResponseHeaders(HttpServletRequest request, HttpServletResponse response, Response proxyResponse) protected void onResponseHeaders(HttpServletRequest request, HttpServletResponse response, Response proxyResponse)

View File

@ -109,7 +109,7 @@ public class BalancerServletTest
private int getServerPort(Server server) private int getServerPort(Server server)
{ {
return ((NetworkConnector)server.getConnectors()[0]).getLocalPort(); return server.getURI().getPort();
} }
protected byte[] sendRequestToBalancer(String path) throws Exception protected byte[] sendRequestToBalancer(String path) throws Exception

View File

@ -172,21 +172,21 @@ public class Runner
if (error!=null) if (error!=null)
System.err.println("ERROR: "+error); System.err.println("ERROR: "+error);
System.err.println("Usage: java [-Djetty.home=dir] -jar jetty-runner.jar [--help|--version] [ server opts] [[ context opts] context ...] "); System.err.println("Usage: java [-Djetty.home=dir] -jar jetty-runner.jar [--help|--version] [ server opts] [[ context opts] context ...] ");
System.err.println("Server Options:"); System.err.println("Server opts:");
System.err.println(" --version - display version and exit"); System.err.println(" --version - display version and exit");
System.err.println(" --log file - request log filename (with optional 'yyyy_mm_dd' wildcard"); System.err.println(" --log file - request log filename (with optional 'yyyy_mm_dd' wildcard");
System.err.println(" --out file - info/warn/debug log filename (with optional 'yyyy_mm_dd' wildcard"); System.err.println(" --out file - info/warn/debug log filename (with optional 'yyyy_mm_dd' wildcard");
System.err.println(" --port n - port to listen on (default 8080)"); System.err.println(" --host name|ip - interface to listen on (default is all interfaces)");
System.err.println(" --stop-port n - port to listen for stop command"); System.err.println(" --port n - port to listen on (default 8080)");
System.err.println(" --stop-key n - security string for stop command (required if --stop-port is present)"); System.err.println(" --stop-port n - port to listen for stop command");
System.err.println(" --jar file - a jar to be added to the classloader"); System.err.println(" --stop-key n - security string for stop command (required if --stop-port is present)");
System.err.println(" --lib dir - a directory of jars to be added to the classloader"); System.err.println(" [--jar file]*n - each tuple specifies an extra jar to be added to the classloader");
System.err.println(" --classes dir - a directory of classes to be added to the classloader"); System.err.println(" [--lib dir]*n - each tuple specifies an extra directory of jars to be added to the classloader");
System.err.println(" [--classes dir]*n - each tuple specifies an extra directory of classes to be added to the classloader");
System.err.println(" --stats [unsecure|realm.properties] - enable stats gathering servlet context"); System.err.println(" --stats [unsecure|realm.properties] - enable stats gathering servlet context");
System.err.println(" [--config file]*n - each --config parameter specifies the name of a jetty xml config file to apply (in the order defined)"); System.err.println(" [--config file]*n - each tuple specifies the name of a jetty xml config file to apply (in the order defined)");
System.err.println("Context Options:"); System.err.println("Context opts:");
System.err.println(" --path /path - context path (default /)"); System.err.println(" [[--path /path] context]*n - WAR file, web app dir or context xml file, optionally with a context path");
System.err.println(" context - WAR file, web app dir or context xml file");
System.exit(1); System.exit(1);
} }
@ -246,6 +246,7 @@ public class Runner
String contextPath = __defaultContextPath; String contextPath = __defaultContextPath;
boolean contextPathSet = false; boolean contextPathSet = false;
int port = __defaultPort; int port = __defaultPort;
String host = null;
int stopPort = 0; int stopPort = 0;
String stopKey = null; String stopKey = null;
@ -255,6 +256,8 @@ public class Runner
{ {
if ("--port".equals(args[i])) if ("--port".equals(args[i]))
port=Integer.parseInt(args[++i]); port=Integer.parseInt(args[++i]);
else if ("--host".equals(args[i]))
host=args[++i];
else if ("--stop-port".equals(args[i])) else if ("--stop-port".equals(args[i]))
stopPort=Integer.parseInt(args[++i]); stopPort=Integer.parseInt(args[++i]);
else if ("--stop-key".equals(args[i])) else if ("--stop-key".equals(args[i]))
@ -393,6 +396,8 @@ public class Runner
{ {
ServerConnector connector = new ServerConnector(_server); ServerConnector connector = new ServerConnector(_server);
connector.setPort(port); connector.setPort(port);
if (host != null)
connector.setHost(host);
_server.addConnector(connector); _server.addConnector(connector);
if (_enableStats) if (_enableStats)
connector.addBean(new ConnectorStatistics()); connector.addBean(new ConnectorStatistics());

View File

@ -19,7 +19,11 @@
package org.eclipse.jetty.server; package org.eclipse.jetty.server;
import java.io.IOException; import java.io.IOException;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
@ -35,14 +39,18 @@ import javax.servlet.ServletContext;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.xml.validation.Schema;
import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpGenerator; import org.eclipse.jetty.http.HttpGenerator;
import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpScheme;
import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.http.HttpURI;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.HandlerWrapper; import org.eclipse.jetty.server.handler.HandlerWrapper;
import org.eclipse.jetty.util.Attributes; import org.eclipse.jetty.util.Attributes;
import org.eclipse.jetty.util.AttributesMap; import org.eclipse.jetty.util.AttributesMap;
@ -580,6 +588,49 @@ public class Server extends HandlerWrapper implements Attributes
_attributes.setAttribute(name, attribute); _attributes.setAttribute(name, attribute);
} }
/* ------------------------------------------------------------ */
/**
* @return The URI of the first {@link NetworkConnector} and first {@link ContextHandler}, or null
*/
public URI getURI()
{
NetworkConnector connector=null;
for (Connector c: _connectors)
{
if (c instanceof NetworkConnector)
{
connector=(NetworkConnector)c;
break;
}
}
if (connector==null)
return null;
ContextHandler context = getChildHandlerByClass(ContextHandler.class);
try
{
String scheme=connector.getDefaultConnectionFactory().getProtocol().startsWith("SSL-")?"https":"http";
String host=connector.getHost();
if (context!=null && context.getVirtualHosts()!=null && context.getVirtualHosts().length>0)
host=context.getVirtualHosts()[0];
if (host==null)
host=InetAddress.getLocalHost().getHostAddress();
String path=context==null?null:context.getContextPath();
if (path==null)
path="/";
return new URI(scheme,null,host,connector.getLocalPort(),path,null,null);
}
catch(Exception e)
{
LOG.warn(e);
return null;
}
}
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@Override @Override
public String toString() public String toString()

View File

@ -255,7 +255,7 @@ public class ShutdownMonitor extends Thread
{ {
if (isAlive()) if (isAlive())
{ {
System.out.printf("ShutdownMonitor already started"); System.err.printf("ShutdownMonitor already started");
return; // cannot start it again return; // cannot start it again
} }
startListenSocket(); startListenSocket();
@ -270,8 +270,9 @@ public class ShutdownMonitor extends Thread
private void startListenSocket() private void startListenSocket()
{ {
if (this.port < 0) if (this.port < 0)
{ {
System.out.println("ShutdownMonitor not in use (port < 0): " + port); if (DEBUG)
System.err.println("ShutdownMonitor not in use (port < 0): " + port);
return; return;
} }

View File

@ -123,23 +123,6 @@ public class HandlerWrapper extends AbstractHandlerContainer
expandHandler(_handler,list,byClass); expandHandler(_handler,list,byClass);
} }
/* ------------------------------------------------------------ */
public <H extends Handler> H getNestedHandlerByClass(Class<H> byclass)
{
HandlerWrapper h=this;
while (h!=null)
{
if (byclass.isInstance(h))
return (H)h;
Handler w = h.getHandler();
if (w instanceof HandlerWrapper)
h=(HandlerWrapper)w;
else break;
}
return null;
}
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@Override @Override
public void destroy() public void destroy()

View File

@ -24,6 +24,7 @@ import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.ObjectInputStream; import java.io.ObjectInputStream;
import java.net.URI;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
@ -466,9 +467,11 @@ public class HashSessionManager extends AbstractSessionManager
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
public void setStoreDirectory (File dir) public void setStoreDirectory (File dir) throws IOException
{ {
_storeDir=dir; // CanonicalFile is used to capture the base store directory in a way that will
// work on Windows. Case differences may through off later checks using this directory.
_storeDir=dir.getCanonicalFile();
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@ -526,8 +529,9 @@ public class HashSessionManager extends AbstractSessionManager
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
protected synchronized HashedSession restoreSession(String idInCuster) protected synchronized HashedSession restoreSession(String idInCuster)
{ {
File file = new File(_storeDir,idInCuster); File file = new File(_storeDir,idInCuster);
FileInputStream in = null; FileInputStream in = null;
Exception error = null; Exception error = null;
try try
@ -552,13 +556,15 @@ public class HashSessionManager extends AbstractSessionManager
if (error != null) if (error != null)
{ {
if (isDeleteUnrestorableSessions() && file.exists()) if (isDeleteUnrestorableSessions() && file.exists() && file.getParentFile().equals(_storeDir) )
{ {
file.delete(); file.delete();
LOG.warn("Deleting file for unrestorable session "+idInCuster, error); LOG.warn("Deleting file for unrestorable session "+idInCuster, error);
} }
else else
LOG.warn("Problem restoring session "+idInCuster, error); {
__log.warn("Problem restoring session "+idInCuster, error);
}
} }
else else
file.delete(); //delete successfully restored file file.delete(); //delete successfully restored file

View File

@ -25,6 +25,7 @@ import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.OutputStream; import java.io.OutputStream;
import java.net.Socket; import java.net.Socket;
import java.net.URI;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -59,7 +60,8 @@ public abstract class ConnectorCloseTestBase extends HttpServerTestFixture
configureServer(new HelloWorldHandler()); configureServer(new HelloWorldHandler());
Socket client = newSocket(HOST,_connector.getLocalPort()); URI uri = _server.getURI();
Socket client = newSocket(uri.getHost(),uri.getPort());
try try
{ {
OutputStream os = client.getOutputStream(); OutputStream os = client.getOutputStream();
@ -101,7 +103,7 @@ public abstract class ConnectorCloseTestBase extends HttpServerTestFixture
String request = String request =
"GET /data?writes=1&block=16&id="+pipeline+" HTTP/1.1\r\n"+ "GET /data?writes=1&block=16&id="+pipeline+" HTTP/1.1\r\n"+
"host: "+HOST+":"+_connector.getLocalPort()+"\r\n"+ "host: "+uri.getHost()+":"+uri.getPort()+"\r\n"+
"user-agent: testharness/1.0 (blah foo/bar)\r\n"+ "user-agent: testharness/1.0 (blah foo/bar)\r\n"+
"accept-encoding: nothing\r\n"+ "accept-encoding: nothing\r\n"+
"cookie: aaa=1234567890\r\n"+ "cookie: aaa=1234567890\r\n"+
@ -135,7 +137,8 @@ public abstract class ConnectorCloseTestBase extends HttpServerTestFixture
{ {
configureServer(new EchoHandler()); configureServer(new EchoHandler());
Socket client = newSocket(HOST,_connector.getLocalPort()); URI uri = _server.getURI();
Socket client = newSocket(uri.getHost(),uri.getPort());
try try
{ {
OutputStream os = client.getOutputStream(); OutputStream os = client.getOutputStream();
@ -148,7 +151,7 @@ public abstract class ConnectorCloseTestBase extends HttpServerTestFixture
os.write(( os.write((
"POST /echo?charset=utf-8 HTTP/1.1\r\n"+ "POST /echo?charset=utf-8 HTTP/1.1\r\n"+
"host: "+HOST+":"+_connector.getLocalPort()+"\r\n"+ "host: "+uri.getHost()+":"+uri.getPort()+"\r\n"+
"content-type: text/plain; charset=utf-8\r\n"+ "content-type: text/plain; charset=utf-8\r\n"+
"content-length: "+bytes.length+"\r\n"+ "content-length: "+bytes.length+"\r\n"+
"\r\n" "\r\n"

View File

@ -60,7 +60,8 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
public void testMaxIdleWithRequest10() throws Exception public void testMaxIdleWithRequest10() throws Exception
{ {
configureServer(new HelloWorldHandler()); configureServer(new HelloWorldHandler());
Socket client=newSocket(HOST,_connector.getLocalPort());
Socket client=newSocket(_serverURI.getHost(),_serverURI.getPort());
client.setSoTimeout(10000); client.setSoTimeout(10000);
assertFalse(client.isClosed()); assertFalse(client.isClosed());
@ -70,7 +71,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
os.write(( os.write((
"GET / HTTP/1.0\r\n"+ "GET / HTTP/1.0\r\n"+
"host: "+HOST+":"+_connector.getLocalPort()+"\r\n"+ "host: "+_serverURI.getHost()+":"+_serverURI.getPort()+"\r\n"+
"connection: keep-alive\r\n"+ "connection: keep-alive\r\n"+
"\r\n").getBytes("utf-8")); "\r\n").getBytes("utf-8"));
os.flush(); os.flush();
@ -89,7 +90,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
public void testMaxIdleWithRequest11() throws Exception public void testMaxIdleWithRequest11() throws Exception
{ {
configureServer(new EchoHandler()); configureServer(new EchoHandler());
Socket client=newSocket(HOST,_connector.getLocalPort()); Socket client=newSocket(_serverURI.getHost(),_serverURI.getPort());
client.setSoTimeout(10000); client.setSoTimeout(10000);
assertFalse(client.isClosed()); assertFalse(client.isClosed());
@ -101,7 +102,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
byte[] contentB=content.getBytes("utf-8"); byte[] contentB=content.getBytes("utf-8");
os.write(( os.write((
"POST /echo HTTP/1.1\r\n"+ "POST /echo HTTP/1.1\r\n"+
"host: "+HOST+":"+_connector.getLocalPort()+"\r\n"+ "host: "+_serverURI.getHost()+":"+_serverURI.getPort()+"\r\n"+
"content-type: text/plain; charset=utf-8\r\n"+ "content-type: text/plain; charset=utf-8\r\n"+
"content-length: "+contentB.length+"\r\n"+ "content-length: "+contentB.length+"\r\n"+
"\r\n").getBytes("utf-8")); "\r\n").getBytes("utf-8"));
@ -140,7 +141,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
} }
}); });
Socket client=newSocket(HOST,_connector.getLocalPort()); Socket client=newSocket(_serverURI.getHost(),_serverURI.getPort());
client.setSoTimeout(10000); client.setSoTimeout(10000);
assertFalse(client.isClosed()); assertFalse(client.isClosed());
@ -150,7 +151,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
os.write(( os.write((
"GET / HTTP/1.0\r\n"+ "GET / HTTP/1.0\r\n"+
"host: "+HOST+":"+_connector.getLocalPort()+"\r\n"+ "host: "+_serverURI.getHost()+":"+_serverURI.getPort()+"\r\n"+
"connection: close\r\n"+ "connection: close\r\n"+
"\r\n").getBytes("utf-8")); "\r\n").getBytes("utf-8"));
os.flush(); os.flush();
@ -177,7 +178,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
{ {
os.write(( os.write((
"GET / HTTP/1.0\r\n"+ "GET / HTTP/1.0\r\n"+
"host: "+HOST+":"+_connector.getLocalPort()+"\r\n"+ "host: "+_serverURI.getHost()+":"+_serverURI.getPort()+"\r\n"+
"connection: keep-alive\r\n"+ "connection: keep-alive\r\n"+
"\r\n").getBytes("utf-8")); "\r\n").getBytes("utf-8"));
os.flush(); os.flush();
@ -214,7 +215,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
} }
}); });
Socket client=newSocket(HOST,_connector.getLocalPort()); Socket client=newSocket(_serverURI.getHost(),_serverURI.getPort());
client.setSoTimeout(10000); client.setSoTimeout(10000);
assertFalse(client.isClosed()); assertFalse(client.isClosed());
@ -224,7 +225,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
os.write(( os.write((
"GET / HTTP/1.0\r\n"+ "GET / HTTP/1.0\r\n"+
"host: "+HOST+":"+_connector.getLocalPort()+"\r\n"+ "host: "+_serverURI.getHost()+":"+_serverURI.getPort()+"\r\n"+
"connection: close\r\n"+ "connection: close\r\n"+
"\r\n").getBytes("utf-8")); "\r\n").getBytes("utf-8"));
os.flush(); os.flush();
@ -290,7 +291,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
} }
}); });
Socket client=newSocket(HOST,_connector.getLocalPort()); Socket client=newSocket(_serverURI.getHost(),_serverURI.getPort());
client.setSoTimeout(10000); client.setSoTimeout(10000);
assertFalse(client.isClosed()); assertFalse(client.isClosed());
@ -302,7 +303,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
byte[] contentB=content.getBytes("utf-8"); byte[] contentB=content.getBytes("utf-8");
os.write(( os.write((
"POST /echo HTTP/1.1\r\n" + "POST /echo HTTP/1.1\r\n" +
"host: " + HOST + ":" + _connector.getLocalPort() + "\r\n" + "host: " + _serverURI.getHost() + ":" + _serverURI.getPort() + "\r\n" +
"content-type: text/plain; charset=utf-8\r\n" + "content-type: text/plain; charset=utf-8\r\n" +
"content-length: " + contentB.length + "\r\n" + "content-length: " + contentB.length + "\r\n" +
"connection: close\r\n" + "connection: close\r\n" +
@ -329,7 +330,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
{ {
os.write(( os.write((
"GET / HTTP/1.0\r\n"+ "GET / HTTP/1.0\r\n"+
"host: "+HOST+":"+_connector.getLocalPort()+"\r\n"+ "host: "+_serverURI.getHost()+":"+_serverURI.getPort()+"\r\n"+
"connection: keep-alive\r\n"+ "connection: keep-alive\r\n"+
"\r\n").getBytes("utf-8")); "\r\n").getBytes("utf-8"));
os.flush(); os.flush();
@ -349,7 +350,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
public void testMaxIdleNoRequest() throws Exception public void testMaxIdleNoRequest() throws Exception
{ {
configureServer(new EchoHandler()); configureServer(new EchoHandler());
Socket client=newSocket(HOST,_connector.getLocalPort()); Socket client=newSocket(_serverURI.getHost(),_serverURI.getPort());
client.setSoTimeout(10000); client.setSoTimeout(10000);
InputStream is=client.getInputStream(); InputStream is=client.getInputStream();
assertFalse(client.isClosed()); assertFalse(client.isClosed());
@ -377,7 +378,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
public void testMaxIdleWithSlowRequest() throws Exception public void testMaxIdleWithSlowRequest() throws Exception
{ {
configureServer(new EchoHandler()); configureServer(new EchoHandler());
Socket client=newSocket(HOST,_connector.getLocalPort()); Socket client=newSocket(_serverURI.getHost(),_serverURI.getPort());
client.setSoTimeout(10000); client.setSoTimeout(10000);
assertFalse(client.isClosed()); assertFalse(client.isClosed());
@ -389,7 +390,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
byte[] contentB=content.getBytes("utf-8"); byte[] contentB=content.getBytes("utf-8");
os.write(( os.write((
"GET / HTTP/1.0\r\n"+ "GET / HTTP/1.0\r\n"+
"host: "+HOST+":"+_connector.getLocalPort()+"\r\n"+ "host: "+_serverURI.getHost()+":"+_serverURI.getPort()+"\r\n"+
"connection: keep-alive\r\n"+ "connection: keep-alive\r\n"+
"Content-Length: "+(contentB.length*20)+"\r\n"+ "Content-Length: "+(contentB.length*20)+"\r\n"+
"Content-Type: text/plain\r\n"+ "Content-Type: text/plain\r\n"+
@ -417,7 +418,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
public void testMaxIdleWithSlowResponse() throws Exception public void testMaxIdleWithSlowResponse() throws Exception
{ {
configureServer(new SlowResponseHandler()); configureServer(new SlowResponseHandler());
Socket client=newSocket(HOST,_connector.getLocalPort()); Socket client=newSocket(_serverURI.getHost(),_serverURI.getPort());
client.setSoTimeout(10000); client.setSoTimeout(10000);
assertFalse(client.isClosed()); assertFalse(client.isClosed());
@ -427,7 +428,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
os.write(( os.write((
"GET / HTTP/1.0\r\n"+ "GET / HTTP/1.0\r\n"+
"host: "+HOST+":"+_connector.getLocalPort()+"\r\n"+ "host: "+_serverURI.getHost()+":"+_serverURI.getPort()+"\r\n"+
"connection: keep-alive\r\n"+ "connection: keep-alive\r\n"+
"Connection: close\r\n"+ "Connection: close\r\n"+
"\r\n").getBytes("utf-8")); "\r\n").getBytes("utf-8"));
@ -446,7 +447,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
public void testMaxIdleWithWait() throws Exception public void testMaxIdleWithWait() throws Exception
{ {
configureServer(new WaitHandler()); configureServer(new WaitHandler());
Socket client=newSocket(HOST,_connector.getLocalPort()); Socket client=newSocket(_serverURI.getHost(),_serverURI.getPort());
client.setSoTimeout(10000); client.setSoTimeout(10000);
assertFalse(client.isClosed()); assertFalse(client.isClosed());
@ -456,7 +457,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
os.write(( os.write((
"GET / HTTP/1.0\r\n"+ "GET / HTTP/1.0\r\n"+
"host: "+HOST+":"+_connector.getLocalPort()+"\r\n"+ "host: "+_serverURI.getHost()+":"+_serverURI.getPort()+"\r\n"+
"connection: keep-alive\r\n"+ "connection: keep-alive\r\n"+
"Connection: close\r\n"+ "Connection: close\r\n"+
"\r\n").getBytes("utf-8")); "\r\n").getBytes("utf-8"));

View File

@ -118,7 +118,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
{ {
configureServer(new HelloWorldHandler()); configureServer(new HelloWorldHandler());
try (Socket client = newSocket(HOST, _connector.getLocalPort())) try (Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort()))
{ {
((StdErrLog)Log.getLogger(HttpConnection.class)).setHideStacks(true); ((StdErrLog)Log.getLogger(HttpConnection.class)).setHideStacks(true);
((StdErrLog)Log.getLogger(HttpConnection.class)).info("expect request is too large, then ISE extra data ..."); ((StdErrLog)Log.getLogger(HttpConnection.class)).info("expect request is too large, then ISE extra data ...");
@ -149,7 +149,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
{ {
configureServer(new HelloWorldHandler()); configureServer(new HelloWorldHandler());
try (Socket client = newSocket(HOST, _connector.getLocalPort())) try (Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort()))
{ {
((StdErrLog)Log.getLogger(HttpConnection.class)).setHideStacks(true); ((StdErrLog)Log.getLogger(HttpConnection.class)).setHideStacks(true);
((StdErrLog)Log.getLogger(HttpConnection.class)).info("expect URI is too large, then ISE extra data ..."); ((StdErrLog)Log.getLogger(HttpConnection.class)).info("expect URI is too large, then ISE extra data ...");
@ -192,7 +192,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
StringBuffer request = new StringBuffer("GET / HTTP/1.0\r\n"); StringBuffer request = new StringBuffer("GET / HTTP/1.0\r\n");
request.append("Host: localhost\r\n\r\n"); request.append("Host: localhost\r\n\r\n");
Socket client = newSocket(HOST, _connector.getLocalPort()); Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort());
OutputStream os = client.getOutputStream(); OutputStream os = client.getOutputStream();
try try
@ -246,7 +246,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
request.append("Content-length: 6\n\n"); request.append("Content-length: 6\n\n");
request.append("foo"); request.append("foo");
Socket client = newSocket(HOST, _connector.getLocalPort()); Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort());
OutputStream os = client.getOutputStream(); OutputStream os = client.getOutputStream();
os.write(request.toString().getBytes()); os.write(request.toString().getBytes());
@ -269,7 +269,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
configureServer(new HelloWorldHandler()); configureServer(new HelloWorldHandler());
try (Socket client = newSocket(HOST, _connector.getLocalPort())) try (Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort()))
{ {
((StdErrLog)Log.getLogger(HttpConnection.class)).setHideStacks(true); ((StdErrLog)Log.getLogger(HttpConnection.class)).setHideStacks(true);
((StdErrLog)Log.getLogger(HttpConnection.class)).info("expect header is too large, then ISE extra data ..."); ((StdErrLog)Log.getLogger(HttpConnection.class)).info("expect header is too large, then ISE extra data ...");
@ -317,7 +317,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
{ {
configureServer(new HelloWorldHandler()); configureServer(new HelloWorldHandler());
try (Socket client = newSocket(HOST, _connector.getLocalPort())) try (Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort()))
{ {
OutputStream os = client.getOutputStream(); OutputStream os = client.getOutputStream();
@ -337,7 +337,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
{ {
configureServer(new EchoHandler()); configureServer(new EchoHandler());
try (Socket client = newSocket(HOST, _connector.getLocalPort())) try (Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort()))
{ {
OutputStream os = client.getOutputStream(); OutputStream os = client.getOutputStream();
@ -367,7 +367,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
{ {
configureServer(new EchoHandler()); configureServer(new EchoHandler());
try (Socket client = newSocket(HOST, _connector.getLocalPort())) try (Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort()))
{ {
OutputStream os = client.getOutputStream(); OutputStream os = client.getOutputStream();
@ -396,7 +396,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
{ {
configureServer(new HelloWorldHandler()); configureServer(new HelloWorldHandler());
try (Socket client = newSocket(HOST, _connector.getLocalPort())) try (Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort()))
{ {
OutputStream os = client.getOutputStream(); OutputStream os = client.getOutputStream();
@ -426,7 +426,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
byte[] bytes = REQUEST2.getBytes(); byte[] bytes = REQUEST2.getBytes();
for (int i = 0; i < LOOPS; i++) for (int i = 0; i < LOOPS; i++)
{ {
try (Socket client = newSocket(HOST, _connector.getLocalPort())) try (Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort()))
{ {
OutputStream os = client.getOutputStream(); OutputStream os = client.getOutputStream();
@ -474,7 +474,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
// Sort the list // Sort the list
Arrays.sort(points); Arrays.sort(points);
try (Socket client = newSocket(HOST, _connector.getLocalPort())) try (Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort()))
{ {
OutputStream os = client.getOutputStream(); OutputStream os = client.getOutputStream();
@ -505,7 +505,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
// Sort the list // Sort the list
Arrays.sort(points); Arrays.sort(points);
try (Socket client = newSocket(HOST, _connector.getLocalPort())) try (Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort()))
{ {
OutputStream os = client.getOutputStream(); OutputStream os = client.getOutputStream();
@ -537,7 +537,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
String test = encoding[e] + "x" + b + "x" + w + "x" + c; String test = encoding[e] + "x" + b + "x" + w + "x" + c;
try try
{ {
URL url = new URL(_scheme + "://" + HOST + ":" + _connector.getLocalPort() + "/?writes=" + w + "&block=" + b + (e == 0 ? "" : ("&encoding=" + encoding[e])) + (c == 0 ? "&chars=true" : "")); URL url = new URL(_scheme + "://" + _serverURI.getHost() + ":" + _serverURI.getPort() + "/?writes=" + w + "&block=" + b + (e == 0 ? "" : ("&encoding=" + encoding[e])) + (c == 0 ? "&chars=true" : ""));
InputStream in = (InputStream)url.getContent(); InputStream in = (InputStream)url.getContent();
String response = IO.toString(in, e == 0 ? null : encoding[e]); String response = IO.toString(in, e == 0 ? null : encoding[e]);
@ -562,14 +562,14 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
configureServer(new DataHandler()); configureServer(new DataHandler());
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
try (Socket client = newSocket(HOST, _connector.getLocalPort())) try (Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort()))
{ {
OutputStream os = client.getOutputStream(); OutputStream os = client.getOutputStream();
InputStream is = client.getInputStream(); InputStream is = client.getInputStream();
os.write(( os.write((
"GET /data?writes=1024&block=256 HTTP/1.1\r\n" + "GET /data?writes=1024&block=256 HTTP/1.1\r\n" +
"host: " + HOST + ":" + _connector.getLocalPort() + "\r\n" + "host: " + _serverURI.getHost() + ":" + _serverURI.getPort() + "\r\n" +
"connection: close\r\n" + "connection: close\r\n" +
"content-type: unknown\r\n" + "content-type: unknown\r\n" +
"content-length: 30\r\n" + "content-length: 30\r\n" +
@ -624,14 +624,14 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
int total = 0; int total = 0;
try (Socket client = newSocket(HOST, _connector.getLocalPort())) try (Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort()))
{ {
OutputStream os = client.getOutputStream(); OutputStream os = client.getOutputStream();
InputStream is = client.getInputStream(); InputStream is = client.getInputStream();
os.write(( os.write((
"GET /data?writes=256&block=1024 HTTP/1.1\r\n" + "GET /data?writes=256&block=1024 HTTP/1.1\r\n" +
"host: " + HOST + ":" + _connector.getLocalPort() + "\r\n" + "host: " + _serverURI.getHost() + ":" + _serverURI.getPort() + "\r\n" +
"connection: close\r\n" + "connection: close\r\n" +
"content-type: unknown\r\n" + "content-type: unknown\r\n" +
"\r\n" "\r\n"
@ -665,7 +665,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
{ {
configureServer(new BigBlockHandler()); configureServer(new BigBlockHandler());
try (Socket client = newSocket(HOST, _connector.getLocalPort())) try (Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort()))
{ {
client.setSoTimeout(20000); client.setSoTimeout(20000);
@ -674,10 +674,10 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
os.write(( os.write((
"GET /r1 HTTP/1.1\r\n" + "GET /r1 HTTP/1.1\r\n" +
"host: " + HOST + ":" + _connector.getLocalPort() + "\r\n" + "host: " + _serverURI.getHost() + ":" + _serverURI.getPort() + "\r\n" +
"\r\n" + "\r\n" +
"GET /r2 HTTP/1.1\r\n" + "GET /r2 HTTP/1.1\r\n" +
"host: " + HOST + ":" + _connector.getLocalPort() + "\r\n" + "host: " + _serverURI.getHost() + ":" + _serverURI.getPort() + "\r\n" +
"connection: close\r\n" + "connection: close\r\n" +
"\r\n" "\r\n"
).getBytes()); ).getBytes());
@ -797,7 +797,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
//for (int pipeline=1;pipeline<32;pipeline++) //for (int pipeline=1;pipeline<32;pipeline++)
for (int pipeline = 1; pipeline < 32; pipeline++) for (int pipeline = 1; pipeline < 32; pipeline++)
{ {
try (Socket client = newSocket(HOST, _connector.getLocalPort())) try (Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort()))
{ {
client.setSoTimeout(5000); client.setSoTimeout(5000);
OutputStream os = client.getOutputStream(); OutputStream os = client.getOutputStream();
@ -807,7 +807,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
for (int i = 1; i < pipeline; i++) for (int i = 1; i < pipeline; i++)
request += request +=
"GET /data?writes=1&block=16&id=" + i + " HTTP/1.1\r\n" + "GET /data?writes=1&block=16&id=" + i + " HTTP/1.1\r\n" +
"host: " + HOST + ":" + _connector.getLocalPort() + "\r\n" + "host: " + _serverURI.getHost() + ":" + _serverURI.getPort() + "\r\n" +
"user-agent: testharness/1.0 (blah foo/bar)\r\n" + "user-agent: testharness/1.0 (blah foo/bar)\r\n" +
"accept-encoding: nothing\r\n" + "accept-encoding: nothing\r\n" +
"cookie: aaa=1234567890\r\n" + "cookie: aaa=1234567890\r\n" +
@ -815,7 +815,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
request += request +=
"GET /data?writes=1&block=16 HTTP/1.1\r\n" + "GET /data?writes=1&block=16 HTTP/1.1\r\n" +
"host: " + HOST + ":" + _connector.getLocalPort() + "\r\n" + "host: " + _serverURI.getHost() + ":" + _serverURI.getPort() + "\r\n" +
"user-agent: testharness/1.0 (blah foo/bar)\r\n" + "user-agent: testharness/1.0 (blah foo/bar)\r\n" +
"accept-encoding: nothing\r\n" + "accept-encoding: nothing\r\n" +
"cookie: aaa=bbbbbb\r\n" + "cookie: aaa=bbbbbb\r\n" +
@ -844,14 +844,14 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
public void testRecycledWriters() throws Exception public void testRecycledWriters() throws Exception
{ {
configureServer(new EchoHandler()); configureServer(new EchoHandler());
try (Socket client = newSocket(HOST, _connector.getLocalPort())) try (Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort()))
{ {
OutputStream os = client.getOutputStream(); OutputStream os = client.getOutputStream();
InputStream is = client.getInputStream(); InputStream is = client.getInputStream();
os.write(( os.write((
"POST /echo?charset=utf-8 HTTP/1.1\r\n" + "POST /echo?charset=utf-8 HTTP/1.1\r\n" +
"host: " + HOST + ":" + _connector.getLocalPort() + "\r\n" + "host: " + _serverURI.getHost() + ":" + _serverURI.getPort() + "\r\n" +
"content-type: text/plain; charset=utf-8\r\n" + "content-type: text/plain; charset=utf-8\r\n" +
"content-length: 10\r\n" + "content-length: 10\r\n" +
"\r\n").getBytes("iso-8859-1")); "\r\n").getBytes("iso-8859-1"));
@ -862,7 +862,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
os.write(( os.write((
"POST /echo?charset=utf-8 HTTP/1.1\r\n" + "POST /echo?charset=utf-8 HTTP/1.1\r\n" +
"host: " + HOST + ":" + _connector.getLocalPort() + "\r\n" + "host: " + _serverURI.getHost() + ":" + _serverURI.getPort() + "\r\n" +
"content-type: text/plain; charset=utf-8\r\n" + "content-type: text/plain; charset=utf-8\r\n" +
"content-length: 10\r\n" + "content-length: 10\r\n" +
"\r\n" "\r\n"
@ -876,7 +876,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
byte[] contentB = content.getBytes("utf-8"); byte[] contentB = content.getBytes("utf-8");
os.write(( os.write((
"POST /echo?charset=utf-16 HTTP/1.1\r\n" + "POST /echo?charset=utf-16 HTTP/1.1\r\n" +
"host: " + HOST + ":" + _connector.getLocalPort() + "\r\n" + "host: " + _serverURI.getHost() + ":" + _serverURI.getPort() + "\r\n" +
"content-type: text/plain; charset=utf-8\r\n" + "content-type: text/plain; charset=utf-8\r\n" +
"content-length: " + contentB.length + "\r\n" + "content-length: " + contentB.length + "\r\n" +
"connection: close\r\n" + "connection: close\r\n" +
@ -928,28 +928,28 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
{ {
configureServer(new EchoHandler(false)); configureServer(new EchoHandler(false));
try (Socket client = newSocket(HOST, _connector.getLocalPort())) try (Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort()))
{ {
OutputStream os = client.getOutputStream(); OutputStream os = client.getOutputStream();
InputStream is = client.getInputStream(); InputStream is = client.getInputStream();
os.write(( os.write((
"POST /R1 HTTP/1.1\015\012" + "POST /R1 HTTP/1.1\015\012" +
"Host: " + HOST + ":" + _connector.getLocalPort() + "\r\n" + "Host: " + _serverURI.getHost() + ":" + _serverURI.getPort() + "\r\n" +
"content-type: text/plain; charset=utf-8\r\n" + "content-type: text/plain; charset=utf-8\r\n" +
"content-length: 10\r\n" + "content-length: 10\r\n" +
"\015\012" + "\015\012" +
"123456789\n" + "123456789\n" +
"HEAD /R1 HTTP/1.1\015\012" + "HEAD /R1 HTTP/1.1\015\012" +
"Host: " + HOST + ":" + _connector.getLocalPort() + "\015\012" + "Host: " + _serverURI.getHost() + ":" + _serverURI.getPort() + "\015\012" +
"content-type: text/plain; charset=utf-8\r\n" + "content-type: text/plain; charset=utf-8\r\n" +
"content-length: 10\r\n" + "content-length: 10\r\n" +
"\015\012" + "\015\012" +
"123456789\n" + "123456789\n" +
"POST /R1 HTTP/1.1\015\012" + "POST /R1 HTTP/1.1\015\012" +
"Host: " + HOST + ":" + _connector.getLocalPort() + "\015\012" + "Host: " + _serverURI.getHost() + ":" + _serverURI.getPort() + "\015\012" +
"content-type: text/plain; charset=utf-8\r\n" + "content-type: text/plain; charset=utf-8\r\n" +
"content-length: 10\r\n" + "content-length: 10\r\n" +
"Connection: close\015\012" + "Connection: close\015\012" +
@ -976,14 +976,14 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
{ {
configureServer(new EchoHandler()); configureServer(new EchoHandler());
try (Socket client = newSocket(HOST, _connector.getLocalPort())) try (Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort()))
{ {
OutputStream os = client.getOutputStream(); OutputStream os = client.getOutputStream();
InputStream is = client.getInputStream(); InputStream is = client.getInputStream();
os.write(( os.write((
"POST /echo?charset=utf-8 HTTP/1.1\r\n" + "POST /echo?charset=utf-8 HTTP/1.1\r\n" +
"host: " + HOST + ":" + _connector.getLocalPort() + "\r\n" + "host: " + _serverURI.getHost() + ":" + _serverURI.getPort() + "\r\n" +
"content-type: text/plain; charset=utf-8\r\n" + "content-type: text/plain; charset=utf-8\r\n" +
"content-length: 10\r\n" + "content-length: 10\r\n" +
"\r\n").getBytes("iso-8859-1")); "\r\n").getBytes("iso-8859-1"));
@ -994,7 +994,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
os.write(( os.write((
"POST /echo?charset=utf-8 HTTP/1.1\r\n" + "POST /echo?charset=utf-8 HTTP/1.1\r\n" +
"host: " + HOST + ":" + _connector.getLocalPort() + "\r\n" + "host: " + _serverURI.getHost() + ":" + _serverURI.getPort() + "\r\n" +
"content-type: text/plain; charset=utf-8\r\n" + "content-type: text/plain; charset=utf-8\r\n" +
"content-length: 10\r\n" + "content-length: 10\r\n" +
"\r\n" "\r\n"
@ -1008,7 +1008,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
byte[] contentB = content.getBytes("utf-16"); byte[] contentB = content.getBytes("utf-16");
os.write(( os.write((
"POST /echo?charset=utf-8 HTTP/1.1\r\n" + "POST /echo?charset=utf-8 HTTP/1.1\r\n" +
"host: " + HOST + ":" + _connector.getLocalPort() + "\r\n" + "host: " + _serverURI.getHost() + ":" + _serverURI.getPort() + "\r\n" +
"content-type: text/plain; charset=utf-16\r\n" + "content-type: text/plain; charset=utf-16\r\n" +
"content-length: " + contentB.length + "\r\n" + "content-length: " + contentB.length + "\r\n" +
"connection: close\r\n" + "connection: close\r\n" +
@ -1030,7 +1030,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
{ {
configureServer(new HelloWorldHandler()); configureServer(new HelloWorldHandler());
try (Socket client = newSocket(HOST, _connector.getLocalPort())) try (Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort()))
{ {
OutputStream os = client.getOutputStream(); OutputStream os = client.getOutputStream();
InputStream is = client.getInputStream(); InputStream is = client.getInputStream();
@ -1038,7 +1038,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
// Send a request with chunked input and expect 100 // Send a request with chunked input and expect 100
os.write(( os.write((
"GET / HTTP/1.1\r\n" + "GET / HTTP/1.1\r\n" +
"Host: " + HOST + ":" + _connector.getLocalPort() + "\r\n" + "Host: " + _serverURI.getHost() + ":" + _serverURI.getPort() + "\r\n" +
"Transfer-Encoding: chunked\r\n" + "Transfer-Encoding: chunked\r\n" +
"Expect: 100-continue\r\n" + "Expect: 100-continue\r\n" +
"Connection: Keep-Alive\r\n" + "Connection: Keep-Alive\r\n" +
@ -1066,7 +1066,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
CommittedErrorHandler handler = new CommittedErrorHandler(); CommittedErrorHandler handler = new CommittedErrorHandler();
configureServer(handler); configureServer(handler);
Socket client = newSocket(HOST, _connector.getLocalPort()); Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort());
try try
{ {
((StdErrLog)Log.getLogger(HttpChannel.class)).setHideStacks(true); ((StdErrLog)Log.getLogger(HttpChannel.class)).setHideStacks(true);
@ -1076,7 +1076,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
// Send a request // Send a request
os.write(("GET / HTTP/1.1\r\n" + os.write(("GET / HTTP/1.1\r\n" +
"Host: " + HOST + ":" + _connector.getLocalPort() + "\r\n" + "Host: " + _serverURI.getHost() + ":" + _serverURI.getPort() + "\r\n" +
"\r\n" "\r\n"
).getBytes()); ).getBytes());
os.flush(); os.flush();
@ -1206,14 +1206,14 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
AvailableHandler ah = new AvailableHandler(); AvailableHandler ah = new AvailableHandler();
configureServer(ah); configureServer(ah);
try (Socket client = newSocket(HOST, _connector.getLocalPort())) try (Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort()))
{ {
OutputStream os = client.getOutputStream(); OutputStream os = client.getOutputStream();
InputStream is = client.getInputStream(); InputStream is = client.getInputStream();
os.write(( os.write((
"GET /data?writes=1024&block=256 HTTP/1.1\r\n" + "GET /data?writes=1024&block=256 HTTP/1.1\r\n" +
"host: " + HOST + ":" + _connector.getLocalPort() + "\r\n" + "host: " + _serverURI.getHost() + ":" + _serverURI.getPort() + "\r\n" +
"connection: close\r\n" + "connection: close\r\n" +
"content-type: unknown\r\n" + "content-type: unknown\r\n" +
"content-length: 30\r\n" + "content-length: 30\r\n" +
@ -1251,7 +1251,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
{ {
configureServer(new HelloWorldHandler()); configureServer(new HelloWorldHandler());
try (Socket client1 = newSocket(HOST, _connector.getLocalPort()); Socket client2 = newSocket(HOST, _connector.getLocalPort())) try (Socket client1 = newSocket(_serverURI.getHost(), _serverURI.getPort()); Socket client2 = newSocket(_serverURI.getHost(), _serverURI.getPort()))
{ {
OutputStream os1 = client1.getOutputStream(); OutputStream os1 = client1.getOutputStream();
OutputStream os2 = client2.getOutputStream(); OutputStream os2 = client2.getOutputStream();
@ -1345,7 +1345,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
new String(fill); new String(fill);
final byte[] bytes = content.getBytes(); final byte[] bytes = content.getBytes();
Socket client = newSocket(HOST, _connector.getLocalPort()); Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort());
final OutputStream out = client.getOutputStream(); final OutputStream out = client.getOutputStream();
new Thread() new Thread()
@ -1405,7 +1405,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
configureServer(suspend); configureServer(suspend);
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
Socket client = newSocket(HOST, _connector.getLocalPort()); Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort());
client.setSoTimeout(5000); client.setSoTimeout(5000);
try try
{ {
@ -1414,7 +1414,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
// write an initial request // write an initial request
os.write(( os.write((
"GET / HTTP/1.1\r\n" + "GET / HTTP/1.1\r\n" +
"host: " + HOST + ":" + _connector.getLocalPort() + "\r\n" + "host: " + _serverURI.getHost() + ":" + _serverURI.getPort() + "\r\n" +
"\r\n" "\r\n"
).getBytes()); ).getBytes());
os.flush(); os.flush();
@ -1424,7 +1424,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
// write an pipelined request // write an pipelined request
os.write(( os.write((
"GET / HTTP/1.1\r\n" + "GET / HTTP/1.1\r\n" +
"host: " + HOST + ":" + _connector.getLocalPort() + "\r\n" + "host: " + _serverURI.getHost() + ":" + _serverURI.getPort() + "\r\n" +
"connection: close\r\n" + "connection: close\r\n" +
"\r\n" "\r\n"
).getBytes()); ).getBytes());

View File

@ -25,6 +25,7 @@ import java.io.OutputStream;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.io.Writer; import java.io.Writer;
import java.net.Socket; import java.net.Socket;
import java.net.URI;
import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSession;
@ -42,9 +43,9 @@ public class HttpServerTestFixture
{ // Useful constants { // Useful constants
protected static final long PAUSE=10L; protected static final long PAUSE=10L;
protected static final int LOOPS=50; protected static final int LOOPS=50;
protected static final String HOST="localhost";
protected Server _server; protected Server _server;
protected URI _serverURI;
protected NetworkConnector _connector; protected NetworkConnector _connector;
protected String _scheme="http"; protected String _scheme="http";
@ -69,6 +70,7 @@ public class HttpServerTestFixture
_server.addConnector(_connector); _server.addConnector(_connector);
_server.setHandler(new HandlerWrapper()); _server.setHandler(new HandlerWrapper());
_server.start(); _server.start();
_serverURI = _server.getURI();
} }
@After @After

View File

@ -0,0 +1,93 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// 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
// 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.
// ========================================================================
//
package org.eclipse.jetty.server.session;
import java.io.File;
import junit.framework.Assert;
import org.eclipse.jetty.server.SessionManager;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.StdErrLog;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class HashSessionManagerTest
{
@After
public void enableStacks()
{
enableStacks(true);
}
@Before
public void quietStacks()
{
enableStacks(false);
}
protected void enableStacks(boolean enabled)
{
StdErrLog log = (StdErrLog)Log.getLogger("org.eclipse.jetty.server.session");
log.setHideStacks(!enabled);
}
@Test
public void testDangerousSessionIdRemoval() throws Exception
{
final HashSessionManager manager = new HashSessionManager();
manager.setDeleteUnrestorableSessions(true);
manager.setLazyLoad(true);
File testDir = MavenTestingUtils.getTargetTestingDir("hashes");
testDir.mkdirs();
manager.setStoreDirectory(testDir);
MavenTestingUtils.getTargetFile("dangerFile.session").createNewFile();
Assert.assertTrue("File should exist!", MavenTestingUtils.getTargetFile("dangerFile.session").exists());
manager.getSession("../../dangerFile.session");
Assert.assertTrue("File should exist!", MavenTestingUtils.getTargetFile("dangerFile.session").exists());
}
@Test
public void testValidSessionIdRemoval() throws Exception
{
final HashSessionManager manager = new HashSessionManager();
manager.setDeleteUnrestorableSessions(true);
manager.setLazyLoad(true);
File testDir = MavenTestingUtils.getTargetTestingDir("hashes");
testDir.mkdirs();
manager.setStoreDirectory(testDir);
new File(testDir, "validFile.session").createNewFile();
Assert.assertTrue("File should exist!", new File(testDir, "validFile.session").exists());
manager.getSession("validFile.session");
Assert.assertTrue("File shouldn't exist!", !new File(testDir,"validFile.session").exists());
}
}

View File

@ -24,6 +24,7 @@ import java.io.FileInputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.net.Socket; import java.net.Socket;
import java.net.SocketException; import java.net.SocketException;
import java.net.URI;
import java.security.KeyStore; import java.security.KeyStore;
import java.util.Arrays; import java.util.Arrays;
@ -153,7 +154,8 @@ public class SelectChannelServerSslTest extends HttpServerTestBase
// Sort the list // Sort the list
Arrays.sort(points); Arrays.sort(points);
Socket client=newSocket(HOST,_connector.getLocalPort()); URI uri=_server.getURI();
Socket client=newSocket(uri.getHost(),uri.getPort());
try try
{ {
OutputStream os=client.getOutputStream(); OutputStream os=client.getOutputStream();

View File

@ -34,8 +34,10 @@ import javax.servlet.ServletContext;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.ServletRequest; import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse; import javax.servlet.ServletResponse;
import javax.servlet.ServletResponseWrapper;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import org.eclipse.jetty.continuation.Continuation; import org.eclipse.jetty.continuation.Continuation;
import org.eclipse.jetty.continuation.ContinuationListener; import org.eclipse.jetty.continuation.ContinuationListener;
@ -43,6 +45,7 @@ import org.eclipse.jetty.continuation.ContinuationSupport;
import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.servlets.gzip.AbstractCompressedStream; import org.eclipse.jetty.servlets.gzip.AbstractCompressedStream;
import org.eclipse.jetty.servlets.gzip.CompressedResponseWrapper; import org.eclipse.jetty.servlets.gzip.CompressedResponseWrapper;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
@ -101,15 +104,21 @@ import org.eclipse.jetty.util.log.Logger;
* instead. * instead.
* *
* excludePathPatterns Same as excludePath, but accepts regex patterns for more complex matching. * excludePathPatterns Same as excludePath, but accepts regex patterns for more complex matching.
*
* vary Set to the value of the Vary header sent with responses that could be compressed. By default it is
* set to 'Vary: Accept-Encoding, User-Agent' since IE6 is excluded by default from the excludedAgents.
* If user-agents are not to be excluded, then this can be set to 'Vary: Accept-Encoding'. Note also
* that shared caches may cache copies of a resource that is varied by User-Agent - one per variation of
* the User-Agent, unless the cache does some normalization of the UA string.
* </PRE> * </PRE>
*/ */
public class GzipFilter extends UserAgentFilter public class GzipFilter extends UserAgentFilter
{ {
private static final Logger LOG = Log.getLogger(GzipFilter.class); private static final Logger LOG = Log.getLogger(GzipFilter.class);
public final static String GZIP="gzip"; public final static String GZIP="gzip";
public final static String ETAG_GZIP="-gzip\""; public final static String ETAG_GZIP="--gzip\"";
public final static String DEFLATE="deflate"; public final static String DEFLATE="deflate";
public final static String ETAG_DEFLATE="-deflate\""; public final static String ETAG_DEFLATE="--deflate\"";
public final static String ETAG="o.e.j.s.GzipFilter.ETag"; public final static String ETAG="o.e.j.s.GzipFilter.ETag";
protected ServletContext _context; protected ServletContext _context;
@ -122,6 +131,7 @@ public class GzipFilter extends UserAgentFilter
protected Set<Pattern> _excludedAgentPatterns; protected Set<Pattern> _excludedAgentPatterns;
protected Set<String> _excludedPaths; protected Set<String> _excludedPaths;
protected Set<Pattern> _excludedPathPatterns; protected Set<Pattern> _excludedPathPatterns;
protected String _vary="Accept-Encoding, User-Agent";
private static final int STATE_SEPARATOR = 0; private static final int STATE_SEPARATOR = 0;
private static final int STATE_Q = 1; private static final int STATE_Q = 1;
@ -199,6 +209,10 @@ public class GzipFilter extends UserAgentFilter
while (tok.hasMoreTokens()) while (tok.hasMoreTokens())
_excludedPathPatterns.add(Pattern.compile(tok.nextToken())); _excludedPathPatterns.add(Pattern.compile(tok.nextToken()));
} }
tmp=filterConfig.getInitParameter("vary");
if (tmp!=null)
_vary=tmp;
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@ -220,9 +234,16 @@ public class GzipFilter extends UserAgentFilter
{ {
HttpServletRequest request=(HttpServletRequest)req; HttpServletRequest request=(HttpServletRequest)req;
HttpServletResponse response=(HttpServletResponse)res; HttpServletResponse response=(HttpServletResponse)res;
// If not a GET or an Excluded URI - no Vary because no matter what client, this URI is always excluded
String requestURI = request.getRequestURI();
if (!HttpMethod.GET.is(request.getMethod()) || isExcludedPath(requestURI))
{
super.doFilter(request,response,chain);
return;
}
// Exclude non compressible mime-types known from URI extension. - no Vary because no matter what client, this URI is always excluded
// Check if mime type of request can ever be compressed.
if (_mimeTypes!=null && _mimeTypes.size()>0) if (_mimeTypes!=null && _mimeTypes.size()>0)
{ {
String mimeType = _context.getMimeType(request.getRequestURI()); String mimeType = _context.getMimeType(request.getRequestURI());
@ -234,64 +255,45 @@ public class GzipFilter extends UserAgentFilter
return; return;
} }
} }
// Excluded User-Agents
String ua = getUserAgent(request);
boolean ua_excluded=ua!=null&&isExcludedAgent(ua);
// Acceptable compression type
String compressionType = ua_excluded?null:selectCompression(request.getHeader("accept-encoding"));
// Inform caches that responses may vary according to Accept-Encoding // Special handling for etags
response.setHeader("Vary","Accept-Encoding"); String etag = request.getHeader("If-None-Match");
if (etag!=null)
// Should we vary this response according to Accept-Encoding
String compressionType = selectCompression(request.getHeader("accept-encoding"));
if (compressionType!=null && !response.containsHeader("Content-Encoding") && !HttpMethod.HEAD.is(request.getMethod()))
{ {
String ua = getUserAgent(request); int dd=etag.indexOf("--");
if (isExcludedAgent(ua)) if (dd>0)
{ request.setAttribute(ETAG,etag.substring(0,dd)+(etag.endsWith("\"")?"\"":""));
super.doFilter(request,response,chain);
return;
}
String requestURI = request.getRequestURI();
if (isExcludedPath(requestURI))
{
super.doFilter(request,response,chain);
return;
}
// Special handling for etags
String etag = request.getHeader("If-None-Match");
if (etag!=null)
{
if (etag.endsWith(ETAG_GZIP))
request.setAttribute(ETAG,etag.substring(0,etag.length()-ETAG_GZIP.length())+'"');
else if (etag.endsWith(ETAG_DEFLATE))
request.setAttribute(ETAG,etag.substring(0,etag.length()-ETAG_DEFLATE.length())+'"');
}
CompressedResponseWrapper wrappedResponse = createWrappedResponse(request,response,compressionType);
boolean exceptional=true;
try
{
super.doFilter(request,wrappedResponse,chain);
exceptional=false;
}
finally
{
Continuation continuation = ContinuationSupport.getContinuation(request);
if (continuation.isSuspended() && continuation.isResponseWrapped())
{
continuation.addContinuationListener(new ContinuationListenerWaitingForWrappedResponseToFinish(wrappedResponse));
}
else if (exceptional && !response.isCommitted())
{
wrappedResponse.resetBuffer();
wrappedResponse.noCompression();
}
else
wrappedResponse.finish();
}
} }
else
CompressedResponseWrapper wrappedResponse = createWrappedResponse(request,response,compressionType);
boolean exceptional=true;
try
{ {
super.doFilter(request,response,chain); super.doFilter(request,wrappedResponse,chain);
exceptional=false;
}
finally
{
Continuation continuation = ContinuationSupport.getContinuation(request);
if (continuation.isSuspended() && continuation.isResponseWrapped())
{
continuation.addContinuationListener(new ContinuationListenerWaitingForWrappedResponseToFinish(wrappedResponse));
}
else if (exceptional && !response.isCommitted())
{
wrappedResponse.resetBuffer();
wrappedResponse.noCompression();
}
else
wrappedResponse.finish();
} }
} }
@ -387,14 +389,32 @@ public class GzipFilter extends UserAgentFilter
protected CompressedResponseWrapper createWrappedResponse(HttpServletRequest request, HttpServletResponse response, final String compressionType) protected CompressedResponseWrapper createWrappedResponse(HttpServletRequest request, HttpServletResponse response, final String compressionType)
{ {
CompressedResponseWrapper wrappedResponse = null; CompressedResponseWrapper wrappedResponse = null;
if (compressionType.equals(GZIP)) if (compressionType==null)
{ {
wrappedResponse = new CompressedResponseWrapper(request,response) wrappedResponse = new CompressedResponseWrapper(request,response)
{ {
@Override @Override
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response) throws IOException protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response) throws IOException
{ {
return new AbstractCompressedStream(compressionType,request,this) return new AbstractCompressedStream(null,request,this,_vary)
{
@Override
protected DeflaterOutputStream createStream() throws IOException
{
return null;
}
};
}
};
}
else if (compressionType.equals(GZIP))
{
wrappedResponse = new CompressedResponseWrapper(request,response)
{
@Override
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response) throws IOException
{
return new AbstractCompressedStream(compressionType,request,this,_vary)
{ {
@Override @Override
protected DeflaterOutputStream createStream() throws IOException protected DeflaterOutputStream createStream() throws IOException
@ -412,7 +432,7 @@ public class GzipFilter extends UserAgentFilter
@Override @Override
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response) throws IOException protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response) throws IOException
{ {
return new AbstractCompressedStream(compressionType,request,this) return new AbstractCompressedStream(compressionType,request,this,_vary)
{ {
@Override @Override
protected DeflaterOutputStream createStream() throws IOException protected DeflaterOutputStream createStream() throws IOException
@ -422,7 +442,7 @@ public class GzipFilter extends UserAgentFilter
}; };
} }
}; };
} }
else else
{ {
throw new IllegalStateException(compressionType + " not supported"); throw new IllegalStateException(compressionType + " not supported");
@ -438,8 +458,8 @@ public class GzipFilter extends UserAgentFilter
wrappedResponse.setMinCompressSize(_minGzipSize); wrappedResponse.setMinCompressSize(_minGzipSize);
} }
private class ContinuationListenerWaitingForWrappedResponseToFinish implements ContinuationListener{ private class ContinuationListenerWaitingForWrappedResponseToFinish implements ContinuationListener
{
private CompressedResponseWrapper wrappedResponse; private CompressedResponseWrapper wrappedResponse;
public ContinuationListenerWaitingForWrappedResponseToFinish(CompressedResponseWrapper wrappedResponse) public ContinuationListenerWaitingForWrappedResponseToFinish(CompressedResponseWrapper wrappedResponse)
@ -532,4 +552,51 @@ public class GzipFilter extends UserAgentFilter
} }
return false; return false;
} }
private class VaryResponseWrapper extends HttpServletResponseWrapper
{
public VaryResponseWrapper(HttpServletResponse response)
{
super(response);
}
@Override
public void addHeader(String name, String value)
{
if ("content-type".equalsIgnoreCase(name))
{
setContentType(value);
}
else
super.addHeader(name,value);
}
@Override
public void setHeader(String name, String value)
{
if ("content-type".equalsIgnoreCase(name))
{
setContentType(value);
}
else
super.setHeader(name,value);
}
@Override
public void setContentType(String ct)
{
super.setContentType(ct);
if (ct!=null)
{
int colon=ct.indexOf(";");
if (colon>0)
ct=ct.substring(0,colon);
}
if (_mimeTypes!=null && _mimeTypes.contains(StringUtil.asciiToLowerCase(ct)))
super.setHeader("Vary",_vary);
}
}
} }

View File

@ -70,14 +70,41 @@ public class IncludableGzipFilter extends GzipFilter
protected CompressedResponseWrapper createWrappedResponse(HttpServletRequest request, HttpServletResponse response, final String compressionType) protected CompressedResponseWrapper createWrappedResponse(HttpServletRequest request, HttpServletResponse response, final String compressionType)
{ {
CompressedResponseWrapper wrappedResponse = null; CompressedResponseWrapper wrappedResponse = null;
if (compressionType.equals(GZIP)) if (compressionType==null)
{ {
wrappedResponse = new IncludableResponseWrapper(request,response) wrappedResponse = new IncludableResponseWrapper(request,response)
{ {
@Override @Override
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response) throws IOException protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response) throws IOException
{ {
return new AbstractCompressedStream(compressionType,request,this) return new AbstractCompressedStream(null,request,this,_vary)
{
@Override
protected DeflaterOutputStream createStream() throws IOException
{
return null;
}
@Override
protected void setHeader(String name, String value)
{
super.setHeader(name, value);
HttpServletResponse response = (HttpServletResponse)getResponse();
if (!response.containsHeader(name))
response.setHeader("org.eclipse.jetty.server.include." + name, value);
}
};
}
};
}
else if (compressionType.equals(GZIP))
{
wrappedResponse = new IncludableResponseWrapper(request,response)
{
@Override
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response) throws IOException
{
return new AbstractCompressedStream(compressionType,request,this,_vary)
{ {
@Override @Override
protected DeflaterOutputStream createStream() throws IOException protected DeflaterOutputStream createStream() throws IOException
@ -104,7 +131,7 @@ public class IncludableGzipFilter extends GzipFilter
@Override @Override
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response) throws IOException protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response) throws IOException
{ {
return new AbstractCompressedStream(compressionType,request,this) return new AbstractCompressedStream(compressionType,request,this,_vary)
{ {
@Override @Override
protected DeflaterOutputStream createStream() throws IOException protected DeflaterOutputStream createStream() throws IOException

View File

@ -40,6 +40,7 @@ import org.eclipse.jetty.util.ByteArrayOutputStream2;
public abstract class AbstractCompressedStream extends ServletOutputStream public abstract class AbstractCompressedStream extends ServletOutputStream
{ {
private final String _encoding; private final String _encoding;
protected final String _vary;
protected final CompressedResponseWrapper _wrapper; protected final CompressedResponseWrapper _wrapper;
protected final HttpServletResponse _response; protected final HttpServletResponse _response;
protected OutputStream _out; protected OutputStream _out;
@ -52,12 +53,13 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
* Instantiates a new compressed stream. * Instantiates a new compressed stream.
* *
*/ */
public AbstractCompressedStream(String encoding,HttpServletRequest request, CompressedResponseWrapper wrapper) public AbstractCompressedStream(String encoding,HttpServletRequest request, CompressedResponseWrapper wrapper,String vary)
throws IOException throws IOException
{ {
_encoding=encoding; _encoding=encoding;
_wrapper = wrapper; _wrapper = wrapper;
_response = (HttpServletResponse)wrapper.getResponse(); _response = (HttpServletResponse)wrapper.getResponse();
_vary=vary;
if (_wrapper.getMinCompressSize()==0) if (_wrapper.getMinCompressSize()==0)
doCompress(); doCompress();
@ -106,7 +108,7 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
{ {
long length=_wrapper.getContentLength(); long length=_wrapper.getContentLength();
if (length > 0 && length < _wrapper.getMinCompressSize()) if (length > 0 && length < _wrapper.getMinCompressSize())
doNotCompress(); doNotCompress(false);
else else
doCompress(); doCompress();
} }
@ -137,13 +139,14 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
_wrapper.setContentLength(length); _wrapper.setContentLength(length);
} }
if (length < _wrapper.getMinCompressSize()) if (length < _wrapper.getMinCompressSize())
doNotCompress(); doNotCompress(false);
else else
doCompress(); doCompress();
} }
else if (_out == null) else if (_out == null)
{ {
doNotCompress(); // No output
doNotCompress(false);
} }
if (_compressedOutputStream != null) if (_compressedOutputStream != null)
@ -168,7 +171,7 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
{ {
long length=_wrapper.getContentLength(); long length=_wrapper.getContentLength();
if (length > 0 && length < _wrapper.getMinCompressSize()) if (length > 0 && length < _wrapper.getMinCompressSize())
doNotCompress(); doNotCompress(false);
else else
doCompress(); doCompress();
} }
@ -226,23 +229,30 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
if (_response.isCommitted()) if (_response.isCommitted())
throw new IllegalStateException(); throw new IllegalStateException();
setHeader("Content-Encoding", _encoding); if (_encoding!=null)
if (_response.containsHeader("Content-Encoding"))
{ {
_out=_compressedOutputStream=createStream(); setHeader("Content-Encoding", _encoding);
if (_response.containsHeader("Content-Encoding"))
if (_bOut!=null)
{ {
_out.write(_bOut.getBuf(),0,_bOut.getCount()); setHeader("Vary",_vary);
_bOut=null; _out=_compressedOutputStream=createStream();
if (_out!=null)
{
if (_bOut!=null)
{
_out.write(_bOut.getBuf(),0,_bOut.getCount());
_bOut=null;
}
String etag=_wrapper.getETag();
if (etag!=null)
setHeader("ETag",etag.substring(0,etag.length()-1)+'-'+_encoding+'"');
return;
}
} }
String etag=_wrapper.getETag();
if (etag!=null)
setHeader("ETag",etag.substring(0,etag.length()-1)+'-'+_encoding+'"');
} }
else
doNotCompress(); doNotCompress(true); // Send vary as it could have been compressed if encoding was present
} }
} }
@ -252,12 +262,14 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
* @throws IOException * @throws IOException
* Signals that an I/O exception has occurred. * Signals that an I/O exception has occurred.
*/ */
public void doNotCompress() throws IOException public void doNotCompress(boolean sendVary) throws IOException
{ {
if (_compressedOutputStream != null) if (_compressedOutputStream != null)
throw new IllegalStateException("Compressed output stream is already assigned."); throw new IllegalStateException("Compressed output stream is already assigned.");
if (_out == null || _bOut != null) if (_out == null || _bOut != null)
{ {
if (sendVary)
setHeader("Vary",_vary);
if (_wrapper.getETag()!=null) if (_wrapper.getETag()!=null)
setHeader("ETag",_wrapper.getETag()); setHeader("ETag",_wrapper.getETag());
@ -289,7 +301,7 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
{ {
long length=_wrapper.getContentLength(); long length=_wrapper.getContentLength();
if (_response.isCommitted() || (length >= 0 && length < _wrapper.getMinCompressSize())) if (_response.isCommitted() || (length >= 0 && length < _wrapper.getMinCompressSize()))
doNotCompress(); doNotCompress(false);
else if (lengthToWrite > _wrapper.getMinCompressSize()) else if (lengthToWrite > _wrapper.getMinCompressSize())
doCompress(); doCompress();
else else
@ -299,7 +311,7 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
{ {
long length=_wrapper.getContentLength(); long length=_wrapper.getContentLength();
if (_response.isCommitted() || (length >= 0 && length < _wrapper.getMinCompressSize())) if (_response.isCommitted() || (length >= 0 && length < _wrapper.getMinCompressSize()))
doNotCompress(); doNotCompress(false);
else if (lengthToWrite >= (_bOut.getBuf().length - _bOut.getCount())) else if (lengthToWrite >= (_bOut.getBuf().length - _bOut.getCount()))
doCompress(); doCompress();
} }

View File

@ -316,7 +316,7 @@ public abstract class CompressedResponseWrapper extends HttpServletResponseWrapp
{ {
try try
{ {
_compressedStream.doNotCompress(); _compressedStream.doNotCompress(false);
} }
catch (IOException e) catch (IOException e)
{ {

View File

@ -67,6 +67,7 @@ public class GzipHandler extends HandlerWrapper
protected Set<String> _excluded; protected Set<String> _excluded;
protected int _bufferSize = 8192; protected int _bufferSize = 8192;
protected int _minGzipSize = 256; protected int _minGzipSize = 256;
protected String _vary = "Accept-Encoding, User-Agent";
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
@ -160,6 +161,31 @@ public class GzipHandler extends HandlerWrapper
} }
} }
/* ------------------------------------------------------------ */
/**
* @return The value of the Vary header set if a response can be compressed.
*/
public String getVary()
{
return _vary;
}
/* ------------------------------------------------------------ */
/**
* Set the value of the Vary header sent with responses that could be compressed.
* <p>
* By default it is set to 'Accept-Encoding, User-Agent' since IE6 is excluded by
* default from the excludedAgents. If user-agents are not to be excluded, then
* this can be set to 'Accept-Encoding'. Note also that shared caches may cache
* many copies of a resource that is varied by User-Agent - one per variation of the
* User-Agent, unless the cache does some normalization of the UA string.
* @param vary The value of the Vary header set if a response can be compressed.
*/
public void setVary(String vary)
{
_vary = vary;
}
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* Get the buffer size. * Get the buffer size.
@ -296,7 +322,7 @@ public class GzipHandler extends HandlerWrapper
@Override @Override
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response) throws IOException protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response) throws IOException
{ {
return new AbstractCompressedStream("gzip",request,this) return new AbstractCompressedStream("gzip",request,this,_vary)
{ {
@Override @Override
protected DeflaterOutputStream createStream() throws IOException protected DeflaterOutputStream createStream() throws IOException

View File

@ -120,15 +120,7 @@ public class GzipWithPipeliningTest
// Start Server // Start Server
server.start(); server.start();
NetworkConnector conn = (NetworkConnector)server.getConnectors()[0]; serverUri = server.getURI();
String host = conn.getHost();
if (host == null)
{
host = "localhost";
}
int port = conn.getLocalPort();
serverUri = new URI(String.format("ws://%s:%d/",host,port));
// System.out.printf("Server URI: %s%n",serverUri);
} }
@After @After

View File

@ -73,7 +73,6 @@ public class MultipartFilterTest
@Override @Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{ {
System.err.println(req.getParameter("field1"));
assertNotNull(req.getParameter("fileup")); assertNotNull(req.getParameter("fileup"));
assertNotNull(req.getParameter("fileup"+MultiPartFilter.CONTENT_TYPE_SUFFIX)); assertNotNull(req.getParameter("fileup"+MultiPartFilter.CONTENT_TYPE_SUFFIX));
assertEquals(req.getParameter("fileup"+MultiPartFilter.CONTENT_TYPE_SUFFIX), "application/octet-stream"); assertEquals(req.getParameter("fileup"+MultiPartFilter.CONTENT_TYPE_SUFFIX), "application/octet-stream");

View File

@ -298,6 +298,7 @@ public class GzipTester
private void assertResponseHeaders(int expectedFilesize, int status, HttpTester.Response response) private void assertResponseHeaders(int expectedFilesize, int status, HttpTester.Response response)
{ {
Assert.assertThat("Response.status",response.getStatus(),is(status)); Assert.assertThat("Response.status",response.getStatus(),is(status));
Assert.assertThat("Response.header[Content-Encoding]",response.get("Content-Encoding"),not(containsString(compressionType)));
if (expectedFilesize != (-1)) if (expectedFilesize != (-1))
{ {
Assert.assertEquals(expectedFilesize,response.getContentBytes().length); Assert.assertEquals(expectedFilesize,response.getContentBytes().length);
@ -456,6 +457,7 @@ public class GzipTester
ServletHolder servletHolder = tester.addServlet(servletClass,"/"); ServletHolder servletHolder = tester.addServlet(servletClass,"/");
servletHolder.setInitParameter("baseDir",testdir.getDir().getAbsolutePath()); servletHolder.setInitParameter("baseDir",testdir.getDir().getAbsolutePath());
FilterHolder holder = tester.addFilter(gzipFilterClass,"/*",EnumSet.allOf(DispatcherType.class)); FilterHolder holder = tester.addFilter(gzipFilterClass,"/*",EnumSet.allOf(DispatcherType.class));
holder.setInitParameter("vary","Accept-Encoding");
return holder; return holder;
} }

View File

@ -34,7 +34,6 @@ import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.DefaultHandler; import org.eclipse.jetty.server.handler.DefaultHandler;
import org.eclipse.jetty.spdy.api.DataInfo; import org.eclipse.jetty.spdy.api.DataInfo;
import org.eclipse.jetty.spdy.api.GoAwayInfo;
import org.eclipse.jetty.spdy.api.GoAwayReceivedInfo; import org.eclipse.jetty.spdy.api.GoAwayReceivedInfo;
import org.eclipse.jetty.spdy.api.PingInfo; import org.eclipse.jetty.spdy.api.PingInfo;
import org.eclipse.jetty.spdy.api.PingResultInfo; import org.eclipse.jetty.spdy.api.PingResultInfo;
@ -49,6 +48,7 @@ import org.eclipse.jetty.spdy.api.SynInfo;
import org.eclipse.jetty.spdy.client.SPDYClient; import org.eclipse.jetty.spdy.client.SPDYClient;
import org.eclipse.jetty.spdy.server.http.HTTPSPDYHeader; import org.eclipse.jetty.spdy.server.http.HTTPSPDYHeader;
import org.eclipse.jetty.spdy.server.http.SPDYTestUtils; import org.eclipse.jetty.spdy.server.http.SPDYTestUtils;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.Fields; import org.eclipse.jetty.util.Fields;
import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.After; import org.junit.After;
@ -180,8 +180,6 @@ public class ProxySPDYToHTTPTest
}); });
assertThat("Reply is send to SPDY client", replyLatch.await(5, TimeUnit.SECONDS), is(true)); assertThat("Reply is send to SPDY client", replyLatch.await(5, TimeUnit.SECONDS), is(true));
client.goAway(new GoAwayInfo(5, TimeUnit.SECONDS));
} }
@Test @Test
@ -227,8 +225,6 @@ public class ProxySPDYToHTTPTest
assertThat("reply has been received", replyLatch.await(5, TimeUnit.SECONDS), is(true)); assertThat("reply has been received", replyLatch.await(5, TimeUnit.SECONDS), is(true));
assertThat("data has been received", dataLatch.await(5, TimeUnit.SECONDS), is(true)); assertThat("data has been received", dataLatch.await(5, TimeUnit.SECONDS), is(true));
client.goAway(new GoAwayInfo(5, TimeUnit.SECONDS));
} }
@Test @Test
@ -272,19 +268,17 @@ public class ProxySPDYToHTTPTest
} }
}); });
stream.data(new StringDataInfo(data, true)); stream.data(new StringDataInfo(data, true), new Callback.Adapter());
assertThat("reply has been received", replyLatch.await(5, TimeUnit.SECONDS), is(true)); assertThat("reply has been received", replyLatch.await(5, TimeUnit.SECONDS), is(true));
assertThat("data has been received", dataLatch.await(5, TimeUnit.SECONDS), is(true)); assertThat("data has been received", dataLatch.await(5, TimeUnit.SECONDS), is(true));
client.goAway(new GoAwayInfo(5, TimeUnit.SECONDS));
} }
@Test @Test
public void testSYNWithSplitRequestContentThenREPLYAndDATA() throws Exception public void testSYNWithSplitRequestContentThenREPLYAndDATA() throws Exception
{ {
final String data = "0123456789ABCDEF"; final String data = "0123456789ABCDEF";
final String data2 = "ABCDEF0123456789"; final String data2 = "ABCDEF";
final String header = "foo"; final String header = "foo";
InetSocketAddress proxyAddress = startProxy(startServer(new TestServerHandler(header, null)), 30000, 30000); InetSocketAddress proxyAddress = startProxy(startServer(new TestServerHandler(header, null)), 30000, 30000);
@ -316,19 +310,20 @@ public class ProxySPDYToHTTPTest
result.write(dataInfo.asBytes(true), 0, dataInfo.length()); result.write(dataInfo.asBytes(true), 0, dataInfo.length());
if (dataInfo.isClose()) if (dataInfo.isClose())
{ {
System.out.println("client received DATA: " + result);
assertThat("received data matches send data", result.toString(), is(data + data2)); assertThat("received data matches send data", result.toString(), is(data + data2));
dataLatch.countDown(); dataLatch.countDown();
} }
} }
}); });
stream.data(new StringDataInfo(data, false)); System.out.println("DATA1 sent!!!!!!!!");
stream.data(new StringDataInfo(data2, true)); stream.data(new StringDataInfo(data, false), new Callback.Adapter());
System.out.println("DATA2 sent!!!!!!!!");
stream.data(new StringDataInfo(data2, true), new Callback.Adapter());
assertThat("reply has been received", replyLatch.await(5, TimeUnit.SECONDS), is(true)); assertThat("reply has been received", replyLatch.await(5, TimeUnit.SECONDS), is(true));
assertThat("data has been received", dataLatch.await(5, TimeUnit.SECONDS), is(true)); assertThat("data has been received", dataLatch.await(5, TimeUnit.SECONDS), is(true));
client.goAway(new GoAwayInfo(5, TimeUnit.SECONDS));
} }
@Test @Test
@ -399,7 +394,7 @@ public class ProxySPDYToHTTPTest
assertThat("reply has been received", replyLatch.await(5, TimeUnit.SECONDS), is(true)); assertThat("reply has been received", replyLatch.await(5, TimeUnit.SECONDS), is(true));
client.goAway(new GoAwayInfo(5, TimeUnit.SECONDS)); // client.goAway(new GoAwayInfo(5, TimeUnit.SECONDS));
} }
@Test @Test
@ -425,7 +420,7 @@ public class ProxySPDYToHTTPTest
Assert.assertTrue(pingLatch.await(5, TimeUnit.SECONDS)); Assert.assertTrue(pingLatch.await(5, TimeUnit.SECONDS));
client.goAway(new GoAwayInfo(5, TimeUnit.SECONDS)); // client.goAway(new GoAwayInfo(5, TimeUnit.SECONDS));
} }
private class TestServerHandler extends DefaultHandler private class TestServerHandler extends DefaultHandler
@ -443,6 +438,7 @@ public class ProxySPDYToHTTPTest
public void handle(String target, Request baseRequest, HttpServletRequest request, public void handle(String target, Request baseRequest, HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException HttpServletResponse response) throws IOException, ServletException
{ {
System.out.println("HANDLER CALLED!!!");
assertThat("Via Header is set", baseRequest.getHeader("X-Forwarded-For"), is(notNullValue())); assertThat("Via Header is set", baseRequest.getHeader("X-Forwarded-For"), is(notNullValue()));
assertThat("X-Forwarded-For Header is set", baseRequest.getHeader("X-Forwarded-For"), assertThat("X-Forwarded-For Header is set", baseRequest.getHeader("X-Forwarded-For"),
is(notNullValue())); is(notNullValue()));

View File

@ -3,5 +3,5 @@ org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
#org.eclipse.jetty.server.LEVEL=DEBUG #org.eclipse.jetty.server.LEVEL=DEBUG
#org.eclipse.jetty.io.ssl.LEVEL=DEBUG #org.eclipse.jetty.io.ssl.LEVEL=DEBUG
org.eclipse.jetty.spdy.LEVEL=DEBUG org.eclipse.jetty.spdy.LEVEL=DEBUG
#org.eclipse.jetty.client.LEVEL=DEBUG org.eclipse.jetty.client.LEVEL=DEBUG
#org.mortbay.LEVEL=DEBUG #org.mortbay.LEVEL=DEBUG

View File

@ -61,10 +61,11 @@ public class PingTest extends AbstractTest
@Test @Test
public void testServerPingPong() throws Exception public void testServerPingPong() throws Exception
{ {
final CountDownLatch pingLatch = new CountDownLatch(1); final CountDownLatch pingReceived = new CountDownLatch(1);
ServerSessionFrameListener serverSessionFrameListener = new ServerSessionFrameListener.Adapter() ServerSessionFrameListener serverSessionFrameListener = new ServerSessionFrameListener.Adapter()
{ {
public volatile int pingId; private final CountDownLatch pingSent = new CountDownLatch(1);
private int pingId;
@Override @Override
public void onConnect(Session session) public void onConnect(Session session)
@ -75,6 +76,7 @@ public class PingTest extends AbstractTest
public void succeeded(PingResultInfo pingInfo) public void succeeded(PingResultInfo pingInfo)
{ {
pingId = pingInfo.getPingId(); pingId = pingInfo.getPingId();
pingSent.countDown();
} }
}); });
} }
@ -82,13 +84,23 @@ public class PingTest extends AbstractTest
@Override @Override
public void onPing(Session session, PingResultInfo pingInfo) public void onPing(Session session, PingResultInfo pingInfo)
{ {
Assert.assertEquals(0, pingInfo.getPingId() % 2); try
Assert.assertEquals(pingId, pingInfo.getPingId()); {
pingLatch.countDown(); // This callback may be notified before the promise above,
// so make sure we wait here to know the pingId
Assert.assertTrue(pingSent.await(5, TimeUnit.SECONDS));
Assert.assertEquals(0, pingInfo.getPingId() % 2);
Assert.assertEquals(pingId, pingInfo.getPingId());
pingReceived.countDown();
}
catch (InterruptedException x)
{
Assert.fail();
}
} }
}; };
startClient(startServer(serverSessionFrameListener), null); startClient(startServer(serverSessionFrameListener), null);
Assert.assertTrue(pingLatch.await(5, TimeUnit.SECONDS)); Assert.assertTrue(pingReceived.await(5, TimeUnit.SECONDS));
} }
} }

View File

@ -86,8 +86,12 @@ import org.eclipse.jetty.util.log.Logger;
* . These convertors are looked up by class, interface and super class by * . These convertors are looked up by class, interface and super class by
* {@link #getConvertor(Class)}. * {@link #getConvertor(Class)}.
* </p> * </p>
* * <p>If a JSON object has a "class" field, then a java class for that name is
* * looked up and the method {@link convertTo(Class,Map)} is used to find a
* Convertor for that class. If a JSON object has a "x-class" field then a
* direct lookup for a Convertor for that named x-class is done, so that none
* java classes may be converted.
* </p>
*/ */
public class JSON public class JSON
{ {
@ -945,6 +949,15 @@ public class JSON
next = seekTo("\"}",source); next = seekTo("\"}",source);
} }
String xclassname = (String)map.get("x-class");
if (xclassname != null)
{
Convertor c = getConvertorFor(xclassname);
if (c != null)
return c.fromJSON(map);
LOG.warn("no Convertor for xclassname '%s'", xclassname);
}
String classname = (String)map.get("class"); String classname = (String)map.get("class");
if (classname != null) if (classname != null)
{ {
@ -955,9 +968,10 @@ public class JSON
} }
catch (ClassNotFoundException e) catch (ClassNotFoundException e)
{ {
LOG.warn(e); LOG.warn("no Class for classname '%s'", classname);
} }
} }
return map; return map;
} }

View File

@ -208,7 +208,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/ */
public SslContextFactory() public SslContextFactory()
{ {
this(true); this(false);
} }
/** /**

View File

@ -27,7 +27,7 @@ import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
public class TimerScheduler extends AbstractLifeCycle implements Scheduler public class TimerScheduler extends AbstractLifeCycle implements Scheduler, Runnable
{ {
private static final Logger LOG = Log.getLogger(TimerScheduler.class); private static final Logger LOG = Log.getLogger(TimerScheduler.class);
@ -49,14 +49,15 @@ public class TimerScheduler extends AbstractLifeCycle implements Scheduler
public TimerScheduler(String name, boolean daemon) public TimerScheduler(String name, boolean daemon)
{ {
_name=name; _name = name;
_daemon=daemon; _daemon = daemon;
} }
@Override @Override
protected void doStart() throws Exception protected void doStart() throws Exception
{ {
_timer=_name==null?new Timer():new Timer(_name,_daemon); _timer = _name == null ? new Timer() : new Timer(_name, _daemon);
run();
super.doStart(); super.doStart();
} }
@ -65,18 +66,29 @@ public class TimerScheduler extends AbstractLifeCycle implements Scheduler
{ {
_timer.cancel(); _timer.cancel();
super.doStop(); super.doStop();
_timer=null; _timer = null;
} }
@Override @Override
public Task schedule(final Runnable task, final long delay, final TimeUnit units) public Task schedule(final Runnable task, final long delay, final TimeUnit units)
{ {
Timer timer=_timer; Timer timer = _timer;
if (timer==null) if (timer == null)
throw new RejectedExecutionException("STOPPED: "+this); throw new RejectedExecutionException("STOPPED: " + this);
SimpleTask t = new SimpleTask(task); SimpleTask t = new SimpleTask(task);
timer.schedule(t,units.toMillis(delay)); timer.schedule(t, units.toMillis(delay));
return t; return t;
}
@Override
public void run()
{
Timer timer = _timer;
if (timer != null)
{
timer.purge();
schedule(this, 1, TimeUnit.SECONDS);
}
} }
private static class SimpleTask extends TimerTask implements Task private static class SimpleTask extends TimerTask implements Task
@ -85,7 +97,7 @@ public class TimerScheduler extends AbstractLifeCycle implements Scheduler
private SimpleTask(Runnable runnable) private SimpleTask(Runnable runnable)
{ {
_task=runnable; _task = runnable;
} }
@Override @Override
@ -97,7 +109,7 @@ public class TimerScheduler extends AbstractLifeCycle implements Scheduler
} }
catch (Throwable x) catch (Throwable x)
{ {
LOG.debug("Exception while executing task "+_task,x); LOG.debug("Exception while executing task " + _task, x);
} }
} }

View File

@ -1,309 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// 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
// 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.
// ========================================================================
//
package org.eclipse.jetty.websocket.dummy;
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.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.URI;
import java.nio.ByteBuffer;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.WebSocketConnectionRFC6455;
import org.junit.Assert;
/**
* Simple ServerSocket server used to test oddball server scenarios encountered in the real world.
*/
public class DummyServer
{
public static class ServerConnection
{
private static final Logger LOG = Log.getLogger(ServerConnection.class);
private final Socket socket;
private InputStream in;
private OutputStream out;
public ServerConnection(Socket socket)
{
this.socket = socket;
}
public int read(ByteBuffer buf) throws IOException
{
int len = 0;
while ((in.available() > 0) && (buf.remaining() > 0))
{
buf.put((byte)in.read());
len++;
}
return len;
}
public void disconnect()
{
LOG.debug("disconnect");
IO.close(in);
IO.close(out);
if (socket != null)
{
try
{
socket.close();
}
catch (IOException ignore)
{
/* ignore */
}
}
}
public InputStream getInputStream() throws IOException
{
if (in == null)
{
in = socket.getInputStream();
}
return in;
}
public OutputStream getOutputStream() throws IOException
{
if (out == null)
{
out = socket.getOutputStream();
}
return out;
}
public void flush() throws IOException
{
LOG.debug("flush()");
getOutputStream().flush();
}
public String readRequest() throws IOException
{
LOG.debug("Reading client request");
StringBuilder request = new StringBuilder();
BufferedReader in = new BufferedReader(new InputStreamReader(getInputStream()));
for (String line = in.readLine(); line != null; line = in.readLine())
{
if (line.length() == 0)
{
break;
}
request.append(line).append("\r\n");
LOG.debug("read line: {}",line);
}
LOG.debug("Client Request:{}{}","\n",request);
return request.toString();
}
public void respond(String rawstr) throws IOException
{
LOG.debug("respond(){}{}","\n",rawstr);
getOutputStream().write(rawstr.getBytes());
flush();
}
public void setSoTimeout(int ms) throws SocketException
{
socket.setSoTimeout(ms);
}
public void upgrade(Map<String, String> extraResponseHeaders) throws IOException
{
@SuppressWarnings("unused")
Pattern patExts = Pattern.compile("^Sec-WebSocket-Extensions: (.*)$",Pattern.CASE_INSENSITIVE);
Pattern patKey = Pattern.compile("^Sec-WebSocket-Key: (.*)$",Pattern.CASE_INSENSITIVE);
LOG.debug("(Upgrade) Reading HTTP Request");
Matcher mat;
String key = "not sent";
BufferedReader in = new BufferedReader(new InputStreamReader(getInputStream()));
for (String line = in.readLine(); line != null; line = in.readLine())
{
if (line.length() == 0)
{
break;
}
// TODO: Check for extensions
// mat = patExts.matcher(line);
// if (mat.matches())
// Check for Key
mat = patKey.matcher(line);
if (mat.matches())
{
key = mat.group(1);
}
}
LOG.debug("(Upgrade) Writing HTTP Response");
// TODO: handle extensions?
// Setup Response
StringBuilder resp = new StringBuilder();
resp.append("HTTP/1.1 101 Upgrade\r\n");
resp.append("Upgrade: websocket\r\n");
resp.append("Connection: upgrade\r\n");
resp.append("Sec-WebSocket-Accept: ");
resp.append(WebSocketConnectionRFC6455.hashKey(key)).append("\r\n");
// extra response headers.
if (extraResponseHeaders != null)
{
for (Map.Entry<String,String> header : extraResponseHeaders.entrySet())
{
resp.append(header.getKey());
resp.append(": ");
resp.append(header.getValue());
resp.append("\r\n");
}
}
resp.append("\r\n");
// Write Response
getOutputStream().write(resp.toString().getBytes());
flush();
}
public void write(byte[] bytes) throws IOException
{
LOG.debug("Writing {} bytes", bytes.length);
getOutputStream().write(bytes);
}
public void write(byte[] buf, int offset, int length) throws IOException
{
LOG.debug("Writing bytes[{}], offset={}, length={}", buf.length, offset, length);
getOutputStream().write(buf,offset,length);
}
public void write(int b) throws IOException
{
LOG.debug("Writing int={}", b);
getOutputStream().write(b);
}
}
private static final Logger LOG = Log.getLogger(DummyServer.class);
private ServerSocket serverSocket;
private URI wsUri;
public ServerConnection accept() throws IOException
{
LOG.debug(".accept()");
assertIsStarted();
Socket socket = serverSocket.accept();
return new ServerConnection(socket);
}
private void assertIsStarted()
{
Assert.assertThat("ServerSocket",serverSocket,notNullValue());
Assert.assertThat("ServerSocket.isBound",serverSocket.isBound(),is(true));
Assert.assertThat("ServerSocket.isClosed",serverSocket.isClosed(),is(false));
Assert.assertThat("WsUri",wsUri,notNullValue());
}
public URI getWsUri()
{
return wsUri;
}
public void respondToClient(Socket connection, String serverResponse) throws IOException
{
InputStream in = null;
InputStreamReader isr = null;
BufferedReader buf = null;
OutputStream out = null;
try
{
in = connection.getInputStream();
isr = new InputStreamReader(in);
buf = new BufferedReader(isr);
String line;
while ((line = buf.readLine()) != null)
{
// System.err.println(line);
if (line.length() == 0)
{
// Got the "\r\n" line.
break;
}
}
// System.out.println("[Server-Out] " + serverResponse);
out = connection.getOutputStream();
out.write(serverResponse.getBytes());
out.flush();
}
finally
{
IO.close(buf);
IO.close(isr);
IO.close(in);
IO.close(out);
}
}
public void start() throws IOException
{
serverSocket = new ServerSocket();
InetAddress addr = InetAddress.getByName("localhost");
InetSocketAddress endpoint = new InetSocketAddress(addr,0);
serverSocket.bind(endpoint);
int port = serverSocket.getLocalPort();
String uri = String.format("ws://%s:%d/",addr.getHostAddress(),port);
wsUri = URI.create(uri);
LOG.debug("Server Started on {} -> {}",endpoint,wsUri);
}
public void stop()
{
LOG.debug("Stopping Server");
try
{
serverSocket.close();
}
catch (IOException ignore)
{
/* ignore */
}
}
}

View File

@ -1,3 +0,0 @@
# Setup default logging implementation for during testing
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
#org.eclipse.jetty.websocket.LEVEL=DEBUG

View File

@ -35,33 +35,26 @@ public class WebSocketPolicy
return new WebSocketPolicy(WebSocketBehavior.SERVER); return new WebSocketPolicy(WebSocketBehavior.SERVER);
} }
/**
* The maximum allowed payload size (validated in both directions)
* <p>
* Default: 65536 (64K)
*/
private int maxPayloadSize = 64 * KB;
/** /**
* The maximum size of a text message during parsing/generating. * The maximum size of a text message during parsing/generating.
* <p> * <p>
* Default: 16384 (16 K) * Default: 65536 (64 K)
*/ */
private int maxTextMessageSize = 64 * KB; private long maxMessageSize = 64 * KB;
/**
* The maximum size of a binary message during parsing/generating.
* <p>
* Default: -1 (no validation)
*/
private int maxBinaryMessageSize = 64 * KB;
/** /**
* The time in ms (milliseconds) that a websocket may be idle before closing. * The time in ms (milliseconds) that a websocket may be idle before closing.
* <p> * <p>
* Default: 300000 (ms) * Default: 300000 (ms)
*/ */
private int idleTimeout = 300000; private long idleTimeout = 300000;
/**
* The size of the input (read from network layer) buffer size.
* <p>
* Default: 4096 (4 K)
*/
private int inputBufferSize = 4 * KB;
/** /**
* Behavior of the websockets * Behavior of the websockets
@ -73,35 +66,14 @@ public class WebSocketPolicy
this.behavior = behavior; this.behavior = behavior;
} }
public void assertValidBinaryMessageSize(int requestedSize) public void assertValidMessageSize(int requestedSize)
{ {
if (maxBinaryMessageSize > 0) if (maxMessageSize > 0)
{ {
// validate it // validate it
if (requestedSize > maxBinaryMessageSize) if (requestedSize > maxMessageSize)
{ {
throw new MessageTooLargeException("Requested binary message size [" + requestedSize + "] exceeds maximum size [" + maxBinaryMessageSize + "]"); throw new MessageTooLargeException("Requested message size [" + requestedSize + "] exceeds maximum size [" + maxMessageSize + "]");
}
}
}
public void assertValidPayloadLength(int payloadLength)
{
// validate to buffer sizes
if (payloadLength > maxPayloadSize)
{
throw new MessageTooLargeException("Requested payload length [" + payloadLength + "] exceeds maximum size [" + maxPayloadSize + "]");
}
}
public void assertValidTextMessageSize(int requestedSize)
{
if (maxTextMessageSize > 0)
{
// validate it
if (requestedSize > maxTextMessageSize)
{
throw new MessageTooLargeException("Requested text message size [" + requestedSize + "] exceeds maximum size [" + maxTextMessageSize + "]");
} }
} }
} }
@ -110,9 +82,8 @@ public class WebSocketPolicy
{ {
WebSocketPolicy clone = new WebSocketPolicy(this.behavior); WebSocketPolicy clone = new WebSocketPolicy(this.behavior);
clone.idleTimeout = this.idleTimeout; clone.idleTimeout = this.idleTimeout;
clone.maxPayloadSize = this.maxPayloadSize; clone.maxMessageSize = this.maxMessageSize;
clone.maxBinaryMessageSize = this.maxBinaryMessageSize; clone.inputBufferSize = this.inputBufferSize;
clone.maxTextMessageSize = this.maxTextMessageSize;
return clone; return clone;
} }
@ -121,47 +92,33 @@ public class WebSocketPolicy
return behavior; return behavior;
} }
public int getIdleTimeout() public long getIdleTimeout()
{ {
return idleTimeout; return idleTimeout;
} }
public int getMaxBinaryMessageSize() public int getInputBufferSize()
{ {
return maxBinaryMessageSize; return inputBufferSize;
} }
public int getMaxPayloadSize() public long getMaxMessageSize()
{ {
return maxPayloadSize; return maxMessageSize;
} }
public int getMaxTextMessageSize() public void setIdleTimeout(long idleTimeout)
{
return maxTextMessageSize;
}
public void setIdleTimeout(int idleTimeout)
{ {
this.idleTimeout = idleTimeout; this.idleTimeout = idleTimeout;
} }
public void setMaxBinaryMessageSize(int maxBinaryMessageSize) public void setInputBufferSize(int inputBufferSize)
{ {
this.maxBinaryMessageSize = maxBinaryMessageSize; this.inputBufferSize = inputBufferSize;
} }
public void setMaxPayloadSize(int maxPayloadSize) public void setMaxMessageSize(long maxMessageSize)
{ {
if (maxPayloadSize < 0) this.maxMessageSize = maxMessageSize;
{
throw new IllegalStateException("Cannot have payload size be a negative number");
}
this.maxPayloadSize = maxPayloadSize;
}
public void setMaxTextMessageSize(int maxTextMessageSize)
{
this.maxTextMessageSize = maxTextMessageSize;
} }
} }

View File

@ -33,11 +33,9 @@ import java.lang.annotation.Target;
{ ElementType.TYPE }) { ElementType.TYPE })
public @interface WebSocket public @interface WebSocket
{ {
int maxBinarySize() default -2; int inputBufferSize() default -2;
int maxBufferSize() default -2;
int maxIdleTime() default -2; int maxIdleTime() default -2;
int maxTextSize() default -2; int maxMessageSize() default -2;
} }

View File

@ -16,15 +16,8 @@
// ======================================================================== // ========================================================================
// //
package org.eclipse.jetty.websocket.core.api;
/** /**
* Connection suspend token * Jetty WebSocket API : WebSocket POJO Annotations
*/ */
public interface SuspendToken package org.eclipse.jetty.websocket.api.annotations;
{
/**
* Resume a previously suspended connection.
*/
void resume();
}

View File

@ -16,13 +16,8 @@
// ======================================================================== // ========================================================================
// //
package org.eclipse.jetty.client; /**
* Jetty WebSocket API : WebSocket Extension API
*/
package org.eclipse.jetty.websocket.api.extensions;
import org.eclipse.jetty.util.thread.Scheduler;
public interface Schedulable
{
public boolean schedule(Scheduler scheduler);
public boolean cancel();
}

View File

@ -16,16 +16,8 @@
// ======================================================================== // ========================================================================
// //
package org.eclipse.jetty.websocket.client.internal.mux; /**
* Jetty WebSocket API : I/O Classes
*/
package org.eclipse.jetty.websocket.api.io;
import org.eclipse.jetty.websocket.common.extensions.mux.AbstractMuxExtension;
import org.eclipse.jetty.websocket.common.extensions.mux.Muxer;
public class MuxClientExtension extends AbstractMuxExtension
{
@Override
public void configureMuxer(Muxer muxer)
{
muxer.setAddClient(new MuxClientAddHandler());
}
}

View File

@ -16,18 +16,8 @@
// ======================================================================== // ========================================================================
// //
package org.eclipse.jetty.websocket.core.io; /**
* Jetty WebSocket API
*/
package org.eclipse.jetty.websocket.api;
import java.util.List;
import org.eclipse.jetty.websocket.core.api.Extension;
import org.eclipse.jetty.websocket.core.api.LogicalConnection;
public interface InternalConnection extends LogicalConnection
{
void configureFromExtensions(List<Extension> extensions);
void setIncoming(IncomingFrames incoming);
void setSession(WebSocketSession session);
}

View File

@ -0,0 +1,23 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// 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
// 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.
// ========================================================================
//
/**
* Jetty WebSocket API : Utility Classes
*/
package org.eclipse.jetty.websocket.api.util;

View File

@ -44,27 +44,39 @@
<artifactId>maven-enforcer-plugin</artifactId> <artifactId>maven-enforcer-plugin</artifactId>
<version>1.1</version> <version>1.1</version>
<executions> <executions>
<execution> <execution>
<id>ban-java-servlet-api</id> <id>ban-java-servlet-api</id>
<goals> <goals>
<goal>enforce</goal> <goal>enforce</goal>
</goals> </goals>
<configuration> <configuration>
<rules> <rules>
<bannedDependencies> <bannedDependencies>
<includes> <includes>
<include>javax.servlet</include> <include>javax.servlet</include>
<include>servletapi</include> <include>servletapi</include>
<include>org.eclipse.jetty.orbit:javax.servlet</include> <include>org.eclipse.jetty.orbit:javax.servlet</include>
<include>org.mortbay.jetty:servlet-api</include> <include>org.mortbay.jetty:servlet-api</include>
<include>jetty:servlet-api</include> <include>jetty:servlet-api</include>
</includes> </includes>
<searchTransitive>true</searchTransitive> <searchTransitive>true</searchTransitive>
<message>The servlet-api dependency is banned in websocket-client as it causes problems in apps that use client only.</message> <message>The servlet-api dependency is banned in websocket-client as it causes problems in apps that use client only.</message>
</bannedDependencies> </bannedDependencies>
</rules> </rules>
</configuration> </configuration>
</execution> </execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>tests-jar</id>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions> </executions>
</plugin> </plugin>
</plugins> </plugins>

View File

@ -43,8 +43,8 @@ import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.api.extensions.Extension; import org.eclipse.jetty.websocket.api.extensions.Extension;
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
import org.eclipse.jetty.websocket.api.extensions.ExtensionFactory; import org.eclipse.jetty.websocket.api.extensions.ExtensionFactory;
import org.eclipse.jetty.websocket.client.internal.ConnectPromise; import org.eclipse.jetty.websocket.client.io.ConnectPromise;
import org.eclipse.jetty.websocket.client.internal.ConnectionManager; import org.eclipse.jetty.websocket.client.io.ConnectionManager;
import org.eclipse.jetty.websocket.client.masks.Masker; import org.eclipse.jetty.websocket.client.masks.Masker;
import org.eclipse.jetty.websocket.client.masks.RandomMasker; import org.eclipse.jetty.websocket.client.masks.RandomMasker;
import org.eclipse.jetty.websocket.common.events.EventDriver; import org.eclipse.jetty.websocket.common.events.EventDriver;
@ -290,13 +290,8 @@ public class WebSocketClient extends ContainerLifeCycle
this.bufferPool = bufferPool; this.bufferPool = bufferPool;
} }
public void setConnectTimeout(int connectTimeout) public void setConnectTimeout(long connectTimeout)
{ {
if (isStarted())
{
throw new IllegalStateException("Cannot change connect timeout, WebSocketClient is already started");
}
if (connectTimeout < 0) if (connectTimeout < 0)
{ {
throw new IllegalStateException("Connect Timeout cannot be negative"); throw new IllegalStateException("Connect Timeout cannot be negative");
@ -318,4 +313,4 @@ public class WebSocketClient extends ContainerLifeCycle
{ {
this.masker = masker; this.masker = masker;
} }
} }

View File

@ -1,33 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// 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
// 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.
// ========================================================================
//
package org.eclipse.jetty.websocket.client.internal.mux;
import org.eclipse.jetty.websocket.common.WebSocketSession;
import org.eclipse.jetty.websocket.common.extensions.mux.add.MuxAddClient;
import org.eclipse.jetty.websocket.common.extensions.mux.op.MuxAddChannelResponse;
public class MuxClientAddHandler implements MuxAddClient
{
@Override
public WebSocketSession createSession(MuxAddChannelResponse response)
{
// TODO Auto-generated method stub
return null;
}
}

View File

@ -16,7 +16,7 @@
// ======================================================================== // ========================================================================
// //
package org.eclipse.jetty.websocket.client.internal; package org.eclipse.jetty.websocket.client.io;
import org.eclipse.jetty.util.FuturePromise; import org.eclipse.jetty.util.FuturePromise;
import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.api.Session;

View File

@ -16,7 +16,7 @@
// ======================================================================== // ========================================================================
// //
package org.eclipse.jetty.websocket.client.internal; package org.eclipse.jetty.websocket.client.io;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.SocketAddress; import java.net.SocketAddress;
@ -34,7 +34,6 @@ import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.api.UpgradeException; import org.eclipse.jetty.websocket.api.UpgradeException;
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest; import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
import org.eclipse.jetty.websocket.client.WebSocketClient; import org.eclipse.jetty.websocket.client.WebSocketClient;
import org.eclipse.jetty.websocket.client.internal.io.WebSocketClientSelectorManager;
import org.eclipse.jetty.websocket.common.WebSocketSession; import org.eclipse.jetty.websocket.common.WebSocketSession;
import org.eclipse.jetty.websocket.common.events.EventDriver; import org.eclipse.jetty.websocket.common.events.EventDriver;

View File

@ -16,7 +16,7 @@
// ======================================================================== // ========================================================================
// //
package org.eclipse.jetty.websocket.client.internal.io; package org.eclipse.jetty.websocket.client.io;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.regex.Matcher; import java.util.regex.Matcher;

View File

@ -16,7 +16,7 @@
// ======================================================================== // ========================================================================
// //
package org.eclipse.jetty.websocket.client.internal.io; package org.eclipse.jetty.websocket.client.io;
import java.io.IOException; import java.io.IOException;
import java.net.URI; import java.net.URI;
@ -39,7 +39,6 @@ import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest; import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
import org.eclipse.jetty.websocket.client.ClientUpgradeResponse; import org.eclipse.jetty.websocket.client.ClientUpgradeResponse;
import org.eclipse.jetty.websocket.client.internal.ConnectPromise;
import org.eclipse.jetty.websocket.common.AcceptHash; import org.eclipse.jetty.websocket.common.AcceptHash;
import org.eclipse.jetty.websocket.common.WebSocketSession; import org.eclipse.jetty.websocket.common.WebSocketSession;
import org.eclipse.jetty.websocket.common.events.EventDriver; import org.eclipse.jetty.websocket.common.events.EventDriver;

View File

@ -16,7 +16,7 @@
// ======================================================================== // ========================================================================
// //
package org.eclipse.jetty.websocket.client.internal.io; package org.eclipse.jetty.websocket.client.io;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
@ -28,8 +28,6 @@ import org.eclipse.jetty.websocket.api.ProtocolException;
import org.eclipse.jetty.websocket.api.WriteCallback; import org.eclipse.jetty.websocket.api.WriteCallback;
import org.eclipse.jetty.websocket.api.extensions.Frame; import org.eclipse.jetty.websocket.api.extensions.Frame;
import org.eclipse.jetty.websocket.api.extensions.IncomingFrames; import org.eclipse.jetty.websocket.api.extensions.IncomingFrames;
import org.eclipse.jetty.websocket.client.internal.ConnectPromise;
import org.eclipse.jetty.websocket.client.internal.ConnectionManager;
import org.eclipse.jetty.websocket.client.masks.Masker; import org.eclipse.jetty.websocket.client.masks.Masker;
import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.WebSocketFrame;
import org.eclipse.jetty.websocket.common.WebSocketSession; import org.eclipse.jetty.websocket.common.WebSocketSession;

View File

@ -16,7 +16,7 @@
// ======================================================================== // ========================================================================
// //
package org.eclipse.jetty.websocket.client.internal.io; package org.eclipse.jetty.websocket.client.io;
import java.io.IOException; import java.io.IOException;
import java.nio.channels.SelectionKey; import java.nio.channels.SelectionKey;
@ -37,7 +37,6 @@ import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.Scheduler; import org.eclipse.jetty.util.thread.Scheduler;
import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.client.WebSocketClient; import org.eclipse.jetty.websocket.client.WebSocketClient;
import org.eclipse.jetty.websocket.client.internal.ConnectPromise;
public class WebSocketClientSelectorManager extends SelectorManager public class WebSocketClientSelectorManager extends SelectorManager
{ {

View File

@ -0,0 +1,23 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// 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
// 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.
// ========================================================================
//
/**
* Jetty WebSocket Client : I/O Implementation [<em>Internal Use Only</em>]
*/
package org.eclipse.jetty.websocket.client.io;

View File

@ -20,7 +20,18 @@ package org.eclipse.jetty.websocket.client.masks;
import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.WebSocketFrame;
/**
* Interface for various Masker implementations.
*/
public interface Masker public interface Masker
{ {
/**
* Set the mask on the provided {@link WebSocketFrame}.
* <p>
* Implementations MUST set the mask on the frame.
*
* @param frame
* the frame to set the mask on.
*/
void setMask(WebSocketFrame frame); void setMask(WebSocketFrame frame);
} }

View File

@ -0,0 +1,23 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// 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
// 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.
// ========================================================================
//
/**
* Jetty WebSocket Client : Frame Masking Implementations
*/
package org.eclipse.jetty.websocket.client.masks;

View File

@ -0,0 +1,23 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// 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
// 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.
// ========================================================================
//
/**
* Jetty WebSocket Client : MUX Extension [<em>Unstable Early Draft</em>]
*/
package org.eclipse.jetty.websocket.client.mux;

View File

@ -0,0 +1,34 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// 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
// 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.
// ========================================================================
//
/**
* Jetty WebSocket Client API
* <p>
* The core class is {@link WebSocketClient}, which acts as a central configuration object (for example
* for {@link WebSocketClient#setConnectTimeout(int) connect timeouts}, {@link WebSocketClient#setCookieStore(CookieStore)
* request cookie store}, etc.) and as a factory for WebSocket {@link org.eclipse.jetty.websocket.api.Session} objects.
* <p>
* The <a href="https://tools.ietf.org/html/rfc6455">WebSocket protocol</a> is based on a framing protocol built
* around an upgraded HTTP connection. It is primarily focused on the sending of messages (text or binary), with an
* occasional control frame (close, ping, pong) that this implementation uses.
* <p />
* {@link WebSocketClient} holds a number of {@link org.eclipse.jetty.websocket.api.Session Sessions}, which in turn
* is used to manage physical vs virtual connection handling (mux extension).
*/
package org.eclipse.jetty.websocket.client;

View File

@ -16,88 +16,90 @@
// ======================================================================== // ========================================================================
// //
package org.eclipse.jetty.websocket; package org.eclipse.jetty.websocket.client;
import java.io.IOException; import java.io.IOException;
import java.net.URI; import java.net.URI;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.util.thread.QueuedThreadPool; import org.eclipse.jetty.websocket.api.WebSocketAdapter;
import org.eclipse.jetty.websocket.dummy.DummyServer; import org.eclipse.jetty.websocket.api.WebSocketConnection;
import org.eclipse.jetty.websocket.dummy.DummyServer.ServerConnection; import org.eclipse.jetty.websocket.client.blockhead.BlockheadServer;
import org.eclipse.jetty.websocket.client.blockhead.BlockheadServer.ServerConnection;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
public class TomcatServerQuirksTest public class TomcatServerQuirksTest
{ {
public static class LatchedSocket extends WebSocketAdapter
{
final CountDownLatch openLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(1);
final CountDownLatch closeLatch = new CountDownLatch(1);
@Override
public void onWebSocketClose(int statusCode, String reason)
{
closeLatch.countDown();
}
@Override
public void onWebSocketConnect(WebSocketConnection connection)
{
openLatch.countDown();
}
@Override
public void onWebSocketText(String message)
{
dataLatch.countDown();
}
}
/** /**
* Test for when encountering a "Transfer-Encoding: chunked" on a Upgrade Response header. * Test for when encountering a "Transfer-Encoding: chunked" on a Upgrade Response header.
* <ul> * <ul>
* <li><a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=393075">Eclipse Jetty Bug #393075</a></li> * <li><a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=393075">Eclipse Jetty Bug #393075</a></li>
* <li><a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=54067">Apache Tomcat Bug #54067</a></li> * <li><a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=54067">Apache Tomcat Bug #54067</a></li>
* </ul> * </ul>
* @throws IOException *
* @throws IOException
*/ */
@Test @Test
public void testTomcat7_0_32_WithTransferEncoding() throws Exception public void testTomcat7_0_32_WithTransferEncoding() throws Exception
{ {
DummyServer server = new DummyServer(); BlockheadServer server = new BlockheadServer();
int bufferSize = 512; WebSocketClient client = new WebSocketClient();
QueuedThreadPool threadPool = new QueuedThreadPool();
WebSocketClientFactory factory = new WebSocketClientFactory(threadPool, new ZeroMaskGen(), bufferSize); try
try
{ {
int bufferSize = 512;
server.start(); server.start();
// Setup Client Factory // Setup Client Factory
threadPool.start(); client.start();
factory.start();
// Create Client
WebSocketClient client = new WebSocketClient(factory);
// Create End User WebSocket Class // Create End User WebSocket Class
final CountDownLatch openLatch = new CountDownLatch(1); LatchedSocket websocket = new LatchedSocket();
final CountDownLatch dataLatch = new CountDownLatch(1);
WebSocket.OnTextMessage websocket = new WebSocket.OnTextMessage()
{
public void onOpen(Connection connection)
{
openLatch.countDown();
}
public void onMessage(String data)
{
// System.out.println("data = " + data);
dataLatch.countDown();
}
public void onClose(int closeCode, String message)
{
}
};
// Open connection // Open connection
URI wsURI = server.getWsUri(); URI wsURI = server.getWsUri();
client.open(wsURI, websocket); client.connect(websocket,wsURI);
// Accept incoming connection // Accept incoming connection
ServerConnection socket = server.accept(); ServerConnection socket = server.accept();
socket.setSoTimeout(2000); // timeout socket.setSoTimeout(2000); // timeout
// Issue upgrade // Issue upgrade
Map<String,String> extraResponseHeaders = new HashMap<String, String>(); // Add the extra problematic header that triggers bug found in jetty-io
extraResponseHeaders.put("Transfer-Encoding", "chunked"); // !! The problem !! socket.addResponseHeader("Transfer-Encoding","chunked");
socket.upgrade(extraResponseHeaders); socket.upgrade();
// Wait for proper upgrade // Wait for proper upgrade
Assert.assertTrue("Timed out waiting for Client side WebSocket open event", openLatch.await(1, TimeUnit.SECONDS)); Assert.assertTrue("Timed out waiting for Client side WebSocket open event",websocket.openLatch.await(1,TimeUnit.SECONDS));
// Have server write frame. // Have server write frame.
int length = bufferSize / 2; int length = bufferSize / 2;
@ -107,18 +109,19 @@ public class TomcatServerQuirksTest
serverFrame.put((byte)(length >> 8)); // first length byte serverFrame.put((byte)(length >> 8)); // first length byte
serverFrame.put((byte)(length & 0xFF)); // second length byte serverFrame.put((byte)(length & 0xFF)); // second length byte
for (int i = 0; i < length; ++i) for (int i = 0; i < length; ++i)
{
serverFrame.put((byte)'x'); serverFrame.put((byte)'x');
}
serverFrame.flip(); serverFrame.flip();
byte buf[] = serverFrame.array(); byte buf[] = serverFrame.array();
socket.write(buf,0,buf.length); socket.write(buf,0,buf.length);
socket.flush(); socket.flush();
Assert.assertTrue(dataLatch.await(1000, TimeUnit.SECONDS)); Assert.assertTrue(websocket.dataLatch.await(1000,TimeUnit.SECONDS));
} }
finally finally
{ {
factory.stop(); client.stop();
threadPool.stop();
server.stop(); server.stop();
} }
} }

View File

@ -33,7 +33,9 @@ import java.net.SocketException;
import java.net.URI; import java.net.URI;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
@ -87,6 +89,7 @@ public class BlockheadServer
private OutputStream out; private OutputStream out;
private InputStream in; private InputStream in;
private Map<String, String> extraResponseHeaders = new HashMap<>();
private OutgoingFrames outgoing = this; private OutgoingFrames outgoing = this;
public ServerConnection(Socket socket) public ServerConnection(Socket socket)
@ -101,6 +104,14 @@ public class BlockheadServer
this.extensionRegistry = new WebSocketExtensionFactory(policy,bufferPool); this.extensionRegistry = new WebSocketExtensionFactory(policy,bufferPool);
} }
/**
* Add an extra header for the upgrade response (from the server). No extra work is done to ensure the key and value are sane for http.
*/
public void addResponseHeader(String rawkey, String rawvalue)
{
extraResponseHeaders.put(rawkey,rawvalue);
}
public void close() throws IOException public void close() throws IOException
{ {
write(new WebSocketFrame(OpCode.CLOSE)); write(new WebSocketFrame(OpCode.CLOSE));
@ -412,6 +423,16 @@ public class BlockheadServer
} }
resp.append("\r\n"); resp.append("\r\n");
} }
if (extraResponseHeaders.size() > 0)
{
for (Map.Entry<String, String> xheader : extraResponseHeaders.entrySet())
{
resp.append(xheader.getKey());
resp.append(": ");
resp.append(xheader.getValue());
resp.append("\r\n");
}
}
resp.append("\r\n"); resp.append("\r\n");
// Write Response // Write Response

View File

@ -25,6 +25,7 @@ import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import org.eclipse.jetty.toolchain.test.TestTracker; import org.eclipse.jetty.toolchain.test.TestTracker;
import org.eclipse.jetty.websocket.client.io.ConnectionManager;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;

View File

@ -28,6 +28,7 @@ import org.eclipse.jetty.toolchain.test.TestTracker;
import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.websocket.api.UpgradeResponse; import org.eclipse.jetty.websocket.api.UpgradeResponse;
import org.eclipse.jetty.websocket.client.io.HttpResponseHeaderParser;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;

View File

@ -97,7 +97,7 @@ public class Parser
// OMG! Sanity Check! DO NOT WANT! Won't anyone think of the memory! // OMG! Sanity Check! DO NOT WANT! Won't anyone think of the memory!
throw new MessageTooLargeException("[int-sane!] cannot handle payload lengths larger than " + Integer.MAX_VALUE); throw new MessageTooLargeException("[int-sane!] cannot handle payload lengths larger than " + Integer.MAX_VALUE);
} }
policy.assertValidPayloadLength((int)len); policy.assertValidMessageSize((int)len);
switch (frame.getOpCode()) switch (frame.getOpCode())
{ {
@ -540,7 +540,6 @@ public class Parser
{ {
if (payload == null) if (payload == null)
{ {
getPolicy().assertValidPayloadLength(payloadLength);
frame.assertValid(); frame.assertValid();
payload = bufferPool.acquire(payloadLength,false); payload = bufferPool.acquire(payloadLength,false);
BufferUtil.clearToFill(payload); BufferUtil.clearToFill(payload);

View File

@ -49,13 +49,13 @@ public class AnnotatedEventDriver extends EventDriver
WebSocket anno = websocket.getClass().getAnnotation(WebSocket.class); WebSocket anno = websocket.getClass().getAnnotation(WebSocket.class);
// Setup the policy // Setup the policy
if (anno.maxBinarySize() > 0) if (anno.maxMessageSize() > 0)
{ {
this.policy.setMaxBinaryMessageSize(anno.maxBinarySize()); this.policy.setMaxMessageSize(anno.maxMessageSize());
} }
if (anno.maxTextSize() > 0) if (anno.maxMessageSize() > 0)
{ {
this.policy.setMaxTextMessageSize(anno.maxTextSize()); this.policy.setInputBufferSize(anno.inputBufferSize());
} }
if (anno.maxIdleTime() > 0) if (anno.maxIdleTime() > 0)
{ {

View File

@ -0,0 +1,23 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// 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
// 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.
// ========================================================================
//
/**
* Jetty WebSocket Common : Event Driver for WebSocket Object
*/
package org.eclipse.jetty.websocket.common.events;

View File

@ -0,0 +1,23 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// 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
// 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.
// ========================================================================
//
/**
* Jetty WebSocket Common : Frame &amp; Message Compression Extension Implementations
*/
package org.eclipse.jetty.websocket.common.extensions.compress;

View File

@ -0,0 +1,23 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// 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
// 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.
// ========================================================================
//
/**
* Jetty WebSocket Common : Auto Fragment Extension Implementation
*/
package org.eclipse.jetty.websocket.common.extensions.fragment;

View File

@ -0,0 +1,23 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// 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
// 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.
// ========================================================================
//
/**
* Jetty WebSocket Common : Identity Extension Implementation
*/
package org.eclipse.jetty.websocket.common.extensions.identity;

View File

@ -0,0 +1,23 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// 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
// 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.
// ========================================================================
//
/**
* Jetty WebSocket Common : MUX Extension Add Channel Handling [<em>Unstable Early Draft</em>]
*/
package org.eclipse.jetty.websocket.common.extensions.mux.add;

View File

@ -0,0 +1,23 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// 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
// 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.
// ========================================================================
//
/**
* Jetty WebSocket Common : MUX Extension OpCode Handling [<em>Unstable Early Draft</em>]
*/
package org.eclipse.jetty.websocket.common.extensions.mux.op;

View File

@ -0,0 +1,23 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// 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
// 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.
// ========================================================================
//
/**
* Jetty WebSocket Common : MUX Extension Core [<em>Unstable Early Draft</em>]
*/
package org.eclipse.jetty.websocket.common.extensions.mux;

View File

@ -0,0 +1,23 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// 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
// 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.
// ========================================================================
//
/**
* Jetty WebSocket Common : Extension Implementations
*/
package org.eclipse.jetty.websocket.common.extensions;

View File

@ -140,7 +140,7 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp
public AbstractWebSocketConnection(EndPoint endp, Executor executor, Scheduler scheduler, WebSocketPolicy policy, ByteBufferPool bufferPool) public AbstractWebSocketConnection(EndPoint endp, Executor executor, Scheduler scheduler, WebSocketPolicy policy, ByteBufferPool bufferPool)
{ {
super(endp,executor,EXECUTE_ONFILLABLE); // TODO review if this is best. Specially with MUX super(endp,executor,EXECUTE_ONFILLABLE); // TODO review if this is best. Specifically with MUX
this.policy = policy; this.policy = policy;
this.bufferPool = bufferPool; this.bufferPool = bufferPool;
this.generator = new Generator(policy,bufferPool); this.generator = new Generator(policy,bufferPool);
@ -151,6 +151,7 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp
this.ioState = new IOState(); this.ioState = new IOState();
this.ioState.setState(ConnectionState.CONNECTING); this.ioState.setState(ConnectionState.CONNECTING);
this.writeBytes = new WriteBytesProvider(generator,new FlushCallback()); this.writeBytes = new WriteBytesProvider(generator,new FlushCallback());
this.setInputBufferSize(policy.getInputBufferSize());
} }
@Override @Override

View File

@ -0,0 +1,23 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// 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
// 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.
// ========================================================================
//
/**
* Jetty WebSocket Common : I/O Implementation
*/
package org.eclipse.jetty.websocket.common.io;

View File

@ -0,0 +1,23 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// 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
// 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.
// ========================================================================
//
/**
* Jetty WebSocket Common : I/O : Frame Payload Handling
*/
package org.eclipse.jetty.websocket.common.io.payload;

View File

@ -67,7 +67,7 @@ public class MessageInputStream extends InputStream implements MessageAppender
return; return;
} }
driver.getPolicy().assertValidBinaryMessageSize(size + payload.remaining()); driver.getPolicy().assertValidMessageSize(size + payload.remaining());
size += payload.remaining(); size += payload.remaining();
synchronized (buf) synchronized (buf)

View File

@ -61,7 +61,7 @@ public class MessageReader extends Reader implements MessageAppender
return; return;
} }
driver.getPolicy().assertValidTextMessageSize(size + payload.remaining()); driver.getPolicy().assertValidMessageSize(size + payload.remaining());
size += payload.remaining(); size += payload.remaining();
synchronized (utf) synchronized (utf)

View File

@ -54,7 +54,7 @@ public class SimpleBinaryMessage implements MessageAppender
return; return;
} }
onEvent.getPolicy().assertValidBinaryMessageSize(size + payload.remaining()); onEvent.getPolicy().assertValidMessageSize(size + payload.remaining());
size += payload.remaining(); size += payload.remaining();
BufferUtil.writeTo(payload,out); BufferUtil.writeTo(payload,out);

View File

@ -53,7 +53,7 @@ public class SimpleTextMessage implements MessageAppender
return; return;
} }
onEvent.getPolicy().assertValidTextMessageSize(size + payload.remaining()); onEvent.getPolicy().assertValidMessageSize(size + payload.remaining());
size += payload.remaining(); size += payload.remaining();
// allow for fast fail of BAD utf (incomplete utf will trigger on messageComplete) // allow for fast fail of BAD utf (incomplete utf will trigger on messageComplete)

View File

@ -0,0 +1,23 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// 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
// 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.
// ========================================================================
//
/**
* Jetty WebSocket Common : Message Handling
*/
package org.eclipse.jetty.websocket.common.message;

View File

@ -0,0 +1,29 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// 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
// 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.
// ========================================================================
//
/**
* Jetty WebSocket Common : Implementation [<em>Internal Use Only</em>]
* <p>
* A core set of internal implementation classes for the Jetty WebSocket API.
* <p>
* Note: do not reference or use classes present in this package space in your code. <br />
* Restrict your usage to the Jetty WebSocket API classes, the Jetty WebSocket Client API,
* or the Jetty WebSocket Servlet API.
*/
package org.eclipse.jetty.websocket.common;

View File

@ -0,0 +1,434 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="645"
height="350"
id="svg2"
version="1.1"
inkscape:version="0.48.3.1 r9886"
sodipodi:docname="websocket-stack-extensions.svg"
inkscape:export-filename="/home/joakim/code/intalio/org.eclipse.jetty9.project/jetty-websocket/websocket-core/src/main/javadoc/org/eclipse/jetty/websocket/doc-files/websocket-stack-extensions.png"
inkscape:export-xdpi="111.63"
inkscape:export-ydpi="111.63">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.5972939"
inkscape:cx="332.46256"
inkscape:cy="171.52658"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:window-width="1920"
inkscape:window-height="1024"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
showguides="true"
inkscape:guide-bbox="true"
borderlayer="true">
<inkscape:grid
type="xygrid"
id="grid3006"
empspacing="5"
dotted="true"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true"
spacingx="5px"
spacingy="5px" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Background"
sodipodi:insensitive="true">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none"
id="rect3046"
width="645"
height="350"
x="9.2142858e-07"
y="5.0000006e-07" />
</g>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-702.36218)">
<rect
y="952.36218"
x="40.000004"
height="70"
width="560"
id="rect3977"
style="fill:#bdbdbd;fill-opacity:1;stroke:none" />
<rect
style="fill:#d1d1d1;fill-opacity:1;stroke:none"
id="rect3975"
width="560"
height="170"
x="40.000004"
y="782.36218" />
<path
style="fill:none;stroke:#858585;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 1;stroke-dashoffset:0"
d="m 25.000004,952.36217 594.999996,0"
id="path4004"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<rect
y="732.36218"
x="40.000004"
height="50"
width="560"
id="rect3973"
style="fill:#e7e7e7;fill-opacity:1;stroke:none" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path3999"
d="m 25.000004,782.36217 594.999996,0"
style="fill:none;stroke:#858585;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 1;stroke-dashoffset:0" />
<g
transform="translate(24.999996,-35.000005)"
id="g4031">
<rect
style="fill:#caf3f6;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-opacity:1"
id="rect3008"
width="400"
height="25.000031"
x="25"
y="1047.3622" />
<text
xml:space="preserve"
style="font-size:14px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="224.91454"
y="1063.7245"
id="text3778"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3780"
x="224.91454"
y="1063.7245">Physical Connection</tspan></text>
</g>
<rect
style="fill:#caf3f6;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-opacity:1"
id="rect3797"
width="400"
height="25"
x="49.999996"
y="987.36218" />
<text
xml:space="preserve"
style="font-size:14px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="249.91455"
y="1003.7245"
id="text3799"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3801"
x="249.91455"
y="1003.7245">Jetty I/O EndPoint</tspan></text>
<rect
y="927.36212"
x="49.999996"
height="59.999992"
width="400"
id="rect3805"
style="fill:#caf3f6;fill-opacity:1;stroke:#000000;stroke-width:0.99999988;stroke-opacity:1" />
<text
sodipodi:linespacing="125%"
id="text3807"
y="978.72449"
x="249.91455"
style="font-size:14px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
y="978.72449"
x="249.91455"
id="tspan3809"
sodipodi:role="line">Jetty WebSocketConnection</tspan></text>
<rect
style="color:#000000;fill:#000000;fill-opacity:0.12328766;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.56470588;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect3786"
width="190"
height="25"
x="60"
y="937.36218" />
<text
xml:space="preserve"
style="font-size:14px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="149.31982"
y="954.86609"
id="text3815"
sodipodi:linespacing="125%"><tspan
id="tspan3822"
sodipodi:role="line"
x="149.31982"
y="954.86609">Parser</tspan></text>
<rect
y="937.36218"
x="250"
height="25"
width="190"
id="rect3788"
style="color:#000000;fill:#000000;fill-opacity:0.12328766;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.56470588;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<text
sodipodi:linespacing="125%"
id="text3826"
y="954.95837"
x="314.03955"
style="font-size:14px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
id="tspan3830"
y="954.95837"
x="314.03955"
sodipodi:role="line">Generator</tspan></text>
<rect
style="fill:#caf3f6;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-opacity:1"
id="rect3849"
width="400"
height="59.999996"
x="50"
y="742.36218" />
<text
xml:space="preserve"
style="font-size:14px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="249.91455"
y="758.72449"
id="text3851"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3853"
x="249.91455"
y="758.72449">WebSocket Session</tspan></text>
<rect
style="fill:#caf3f6;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-opacity:1"
id="rect3865"
width="400"
height="25"
x="50"
y="717.36218" />
<text
xml:space="preserve"
style="font-size:14px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="249.91455"
y="733.72449"
id="text3867"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3869"
x="249.91455"
y="733.72449">WebSocket POJO</tspan></text>
<rect
y="767.36218"
x="60"
height="25"
width="190"
id="rect3881"
style="color:#000000;fill:#000000;fill-opacity:0.12328766;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.56470588;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<text
transform="scale(0.9746794,1.0259784)"
sodipodi:linespacing="125%"
id="text3883"
y="765.2027"
x="158.80678"
style="font-size:13.64551163px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
y="765.2027"
x="158.80678"
sodipodi:role="line"
id="tspan3885">EventDriver</tspan></text>
<rect
style="fill:#000000;fill-opacity:0.12328766;stroke:#000000;stroke-width:1;stroke-opacity:0.56470588"
id="rect3905"
width="190"
height="25"
x="250"
y="767.36218" />
<text
transform="scale(0.97467941,1.0259784)"
xml:space="preserve"
style="font-size:13.64551163px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="353.74265"
y="765.2027"
id="text3907"
sodipodi:linespacing="125%"><tspan
id="tspan3909"
sodipodi:role="line"
x="353.74265"
y="765.2027">RemoteEndpoint</tspan></text>
<rect
y="812.36218"
x="49.999996"
height="104.99999"
width="400"
id="rect4036"
style="fill:#fdff14;fill-opacity:0.37442926;stroke:#87882d;stroke-width:0.99999994;stroke-opacity:1" />
<text
sodipodi:linespacing="125%"
id="text3979"
y="970.67273"
x="470"
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
y="970.67273"
x="470"
id="tspan3981"
sodipodi:role="line">Network</tspan><tspan
id="tspan3983"
y="985.67273"
x="470"
sodipodi:role="line">(ByteBuffers)</tspan></text>
<text
sodipodi:linespacing="125%"
id="text3985"
y="802.36218"
x="470"
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
y="802.36218"
x="470"
id="tspan3987"
sodipodi:role="line">Internal</tspan><tspan
id="tspan3989"
y="817.36218"
x="470"
sodipodi:role="line">(WebSocket Frame)</tspan></text>
<text
sodipodi:linespacing="125%"
id="text3991"
y="752.98816"
x="470"
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
y="752.98816"
x="470"
id="tspan3993"
sodipodi:role="line">Message</tspan><tspan
id="tspan3995"
y="767.98816"
x="470"
sodipodi:role="line">(Text or Binary)</tspan></text>
<text
sodipodi:linespacing="125%"
id="text3867-0"
y="827.36218"
x="249.34033"
style="font-size:14px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
y="827.36218"
x="249.34033"
id="tspan3869-0"
sodipodi:role="line">ExtensionStack</tspan></text>
<g
id="g4630"
transform="translate(0,10.000122)">
<rect
y="837.36218"
x="60"
height="20.000149"
width="380"
id="rect4588"
style="fill:#fdff14;fill-opacity:0.37442926;stroke:#87882d;stroke-width:0.99999994;stroke-opacity:1" />
<text
xml:space="preserve"
style="font-size:14px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="249.91455"
y="851.22449"
id="text3867-0-6"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3869-0-8"
x="249.91455"
y="851.22449">Message Compression Extension</tspan></text>
</g>
<g
id="g4635"
transform="translate(0,29.999997)">
<rect
style="fill:#fdff14;fill-opacity:0.37442926;stroke:#87882d;stroke-width:0.99999994;stroke-opacity:1"
id="rect4637"
width="380"
height="20.000149"
x="60"
y="837.36218" />
<text
sodipodi:linespacing="125%"
id="text4639"
y="851.22449"
x="249.91455"
style="font-size:14px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
y="851.22449"
x="249.91455"
id="tspan4641"
sodipodi:role="line">Fragmentation Extension</tspan></text>
</g>
<g
id="g4648">
<path
style="fill:#f7d1d1;fill-opacity:1;stroke:#dd9191;stroke-width:1;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
d="m 95.031248,947.36218 0,-141.74193 7.656252,0 -17.656252,-18.25807 -17.6875,18.25807 7.6875,0 0,141.74193 20,0 z"
id="rect3934"
inkscape:connector-curvature="0" />
<text
xml:space="preserve"
style="font-size:14px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="-925.48132"
y="88.87793"
id="text3948"
sodipodi:linespacing="125%"
transform="matrix(0,-1,1,0,0,0)"><tspan
sodipodi:role="line"
id="tspan3950"
x="-925.48132"
y="88.87793">IncomingFrames</tspan></text>
</g>
<g
id="g4643">
<path
style="fill:#f7d1d1;fill-opacity:1;stroke:#dd9191;stroke-width:0.99999988;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
d="m 419.96875,947.3621 17.6875,-20.96294 -7.6875,0 0,-139.03698 -20,0 0,139.03698 -7.65625,0 17.65625,20.96294 z"
id="rect3954"
inkscape:connector-curvature="0" />
<text
sodipodi:linespacing="125%"
id="text3969"
y="-416.12207"
x="809.57794"
style="font-size:14px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"
transform="matrix(0,1,-1,0,0,0)"><tspan
y="-416.12207"
x="809.57794"
id="tspan3971"
sodipodi:role="line">OutgoingFrames</tspan></text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -0,0 +1,384 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="645"
height="350"
id="svg2"
version="1.1"
inkscape:version="0.48.3.1 r9886"
sodipodi:docname="websocket-stack-simple.svg"
inkscape:export-filename="/home/joakim/code/intalio/org.eclipse.jetty9.project/jetty-websocket/websocket-common/src/main/javadoc/org/eclipse/jetty/websocket/common/doc-files/websocket-stack-simple.png"
inkscape:export-xdpi="111.63"
inkscape:export-ydpi="111.63">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.6652639"
inkscape:cx="375.14499"
inkscape:cy="194.35762"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:window-width="1920"
inkscape:window-height="1024"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
showguides="true"
inkscape:guide-bbox="true"
borderlayer="true">
<inkscape:grid
type="xygrid"
id="grid3006"
empspacing="5"
dotted="true"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true"
spacingx="5px"
spacingy="5px" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Background"
sodipodi:insensitive="true">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none"
id="rect3089"
width="645"
height="350"
x="0"
y="0" />
</g>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-702.36218)">
<rect
style="fill:#bdbdbd;fill-opacity:1;stroke:none"
id="rect3977"
width="560"
height="70"
x="40.000004"
y="952.36218" />
<rect
y="782.36218"
x="40.000004"
height="170"
width="560"
id="rect3975"
style="fill:#d1d1d1;fill-opacity:1;stroke:none" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path4004"
d="m 25.000004,952.36217 594.999996,0"
style="fill:none;stroke:#858585;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 1;stroke-dashoffset:0" />
<rect
style="fill:#e7e7e7;fill-opacity:1;stroke:none"
id="rect3973"
width="560"
height="50"
x="40.000004"
y="732.36218" />
<path
style="fill:none;stroke:#858585;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 1;stroke-dashoffset:0"
d="m 25.000004,782.36217 594.999996,0"
id="path3999"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<g
id="g4031"
transform="translate(24.999996,-35.000005)">
<rect
y="1047.3622"
x="25"
height="25.000031"
width="400"
id="rect3008"
style="fill:#caf3f6;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-opacity:1" />
<text
sodipodi:linespacing="125%"
id="text3778"
y="1063.7245"
x="224.91454"
style="font-size:14px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
y="1063.7245"
x="224.91454"
id="tspan3780"
sodipodi:role="line">Physical Connection</tspan></text>
</g>
<rect
y="987.36218"
x="49.999996"
height="25"
width="400"
id="rect3797"
style="fill:#caf3f6;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-opacity:1" />
<text
sodipodi:linespacing="125%"
id="text3799"
y="1003.7245"
x="249.91455"
style="font-size:14px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
y="1003.7245"
x="249.91455"
id="tspan3801"
sodipodi:role="line">Jetty I/O EndPoint</tspan></text>
<rect
style="fill:#caf3f6;fill-opacity:1;stroke:#000000;stroke-width:0.99999988;stroke-opacity:1"
id="rect3805"
width="400"
height="59.999992"
x="49.999996"
y="927.36212" />
<text
xml:space="preserve"
style="font-size:14px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="249.91455"
y="978.72449"
id="text3807"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3809"
x="249.91455"
y="978.72449">Jetty WebSocketConnection</tspan></text>
<rect
y="937.36218"
x="60"
height="25"
width="190"
id="rect3786"
style="fill:#000000;fill-opacity:0.12328765999999999;stroke:#000000;stroke-width:1;stroke-opacity:0.56470587999999999;color:#000000;fill-rule:nonzero;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<text
sodipodi:linespacing="125%"
id="text3815"
y="954.86609"
x="149.31982"
style="font-size:14px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
y="954.86609"
x="149.31982"
sodipodi:role="line"
id="tspan3822">Parser</tspan></text>
<rect
style="fill:#000000;fill-opacity:0.12328765999999999;stroke:#000000;stroke-width:1;stroke-opacity:0.56470587999999999;color:#000000;fill-rule:nonzero;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect3788"
width="190"
height="25"
x="250"
y="937.36218" />
<text
xml:space="preserve"
style="font-size:14px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="314.03955"
y="954.95837"
id="text3826"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
x="314.03955"
y="954.95837"
id="tspan3830">Generator</tspan></text>
<rect
y="742.36218"
x="50"
height="59.999996"
width="400"
id="rect3849"
style="fill:#caf3f6;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-opacity:1" />
<text
sodipodi:linespacing="125%"
id="text3851"
y="758.72449"
x="249.91455"
style="font-size:14px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
y="758.72449"
x="249.91455"
id="tspan3853"
sodipodi:role="line">WebSocket Session</tspan></text>
<rect
y="717.36218"
x="50"
height="25"
width="400"
id="rect3865"
style="fill:#caf3f6;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-opacity:1" />
<text
sodipodi:linespacing="125%"
id="text3867"
y="733.72449"
x="249.91455"
style="font-size:14px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
y="733.72449"
x="249.91455"
id="tspan3869"
sodipodi:role="line">WebSocket POJO</tspan></text>
<rect
style="fill:#000000;fill-opacity:0.12328765999999999;stroke:#000000;stroke-width:1;stroke-opacity:0.56470587999999999;color:#000000;fill-rule:nonzero;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect3881"
width="190"
height="25"
x="60"
y="767.36218" />
<text
xml:space="preserve"
style="font-size:13.64551163px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="158.80678"
y="765.2027"
id="text3883"
sodipodi:linespacing="125%"
transform="scale(0.97467942,1.0259784)"><tspan
id="tspan3885"
sodipodi:role="line"
x="158.80678"
y="765.2027">EventDriver</tspan></text>
<rect
y="767.36218"
x="250"
height="25"
width="190"
id="rect3905"
style="fill:#000000;fill-opacity:0.12328767000000000;stroke:#000000;stroke-width:1;stroke-opacity:0.56470591" />
<text
sodipodi:linespacing="125%"
id="text3907"
y="765.2027"
x="353.74265"
style="font-size:13.64551163px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"
transform="scale(0.97467943,1.0259784)"><tspan
y="765.2027"
x="353.74265"
sodipodi:role="line"
id="tspan3909">RemoteEndpoint</tspan></text>
<rect
style="fill:#fdff14;fill-opacity:0.37442925999999999;stroke:#87882d;stroke-width:0.99999994000000003;stroke-opacity:1"
id="rect4036"
width="400"
height="104.99999"
x="49.999996"
y="812.36218" />
<path
style="fill:#f7d1d1;fill-opacity:1;stroke:#dd9191;stroke-width:1;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
d="m 95.031248,947.36218 0,-141.74193 7.656252,0 -17.656252,-18.25807 -17.6875,18.25807 7.6875,0 0,141.74193 20,0 z"
id="rect3934"
inkscape:connector-curvature="0" />
<text
xml:space="preserve"
style="font-size:14px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="-925.48132"
y="88.87793"
id="text3948"
sodipodi:linespacing="125%"
transform="matrix(0,-1,1,0,0,0)"><tspan
sodipodi:role="line"
id="tspan3950"
x="-925.48132"
y="88.87793">IncomingFrames</tspan></text>
<path
style="fill:#f7d1d1;fill-opacity:1;stroke:#dd9191;stroke-width:0.99999988;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
d="m 419.96875,947.3621 17.6875,-20.96294 -7.6875,0 0,-139.03698 -20,0 0,139.03698 -7.65625,0 17.65625,20.96294 z"
id="rect3954"
inkscape:connector-curvature="0" />
<text
sodipodi:linespacing="125%"
id="text3969"
y="-416.12207"
x="809.57794"
style="font-size:14px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"
transform="matrix(0,1,-1,0,0,0)"><tspan
y="-416.12207"
x="809.57794"
id="tspan3971"
sodipodi:role="line">OutgoingFrames</tspan></text>
<text
xml:space="preserve"
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="470"
y="970.67273"
id="text3979"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3981"
x="470"
y="970.67273">Network</tspan><tspan
sodipodi:role="line"
x="470"
y="985.67273"
id="tspan3983">(ByteBuffers)</tspan></text>
<text
xml:space="preserve"
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="470"
y="802.36218"
id="text3985"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3987"
x="470"
y="802.36218">Internal</tspan><tspan
sodipodi:role="line"
x="470"
y="817.36218"
id="tspan3989">(WebSocket Frame)</tspan></text>
<text
xml:space="preserve"
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="470"
y="752.98816"
id="text3991"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3993"
x="470"
y="752.98816">Message</tspan><tspan
sodipodi:role="line"
x="470"
y="767.98816"
id="tspan3995">(Text or Binary)</tspan></text>
<text
xml:space="preserve"
style="font-size:14px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="249.34033"
y="827.36218"
id="text3867-0"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3869-0"
x="249.34033"
y="827.36218">ExtensionStack</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -1,802 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="645"
height="350"
id="svg2"
version="1.1"
inkscape:version="0.48.3.1 r9886"
sodipodi:docname="javax.net.websocket-stack-extensions.svg"
inkscape:export-filename="/home/joakim/code/intalio/org.eclipse.jetty9.project/jetty-websocket/websocket-common/src/main/javadoc/org/eclipse/jetty/websocket/doc-files/javax.net.websocket-stack-extensions.png"
inkscape:export-xdpi="111.63"
inkscape:export-ydpi="111.63">
<defs
id="defs4">
<linearGradient
inkscape:collect="always"
id="linearGradient3965">
<stop
style="stop-color:#caf3f6;stop-opacity:1;"
offset="0"
id="stop3967" />
<stop
style="stop-color:#caf3f6;stop-opacity:0;"
offset="1"
id="stop3969" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3965"
id="linearGradient3971"
x1="250"
y1="772.36218"
x2="250"
y2="927.36218"
gradientUnits="userSpaceOnUse" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="2.1472868"
inkscape:cx="304.93654"
inkscape:cy="184.92979"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:window-width="1920"
inkscape:window-height="1024"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
showguides="true"
inkscape:guide-bbox="true"
borderlayer="true"
inkscape:snap-grids="true">
<inkscape:grid
type="xygrid"
id="grid3006"
empspacing="5"
dotted="true"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true"
spacingx="5px"
spacingy="5px" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Background"
sodipodi:insensitive="true">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none"
id="rect3089"
width="645"
height="350"
x="0"
y="0" />
</g>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-702.36218)">
<rect
style="fill:#b9b9b9;fill-opacity:1;stroke:none"
id="rect3977"
width="560"
height="70.000008"
x="40.000004"
y="957.36218" />
<rect
y="812.36218"
x="40.000004"
height="145"
width="560"
id="rect3975"
style="fill:#d1d1d1;fill-opacity:1;stroke:none" />
<rect
style="fill:#ececec;fill-opacity:1;stroke:none"
id="rect3973"
width="560"
height="75"
x="40.000004"
y="737.24573" />
<path
style="fill:none;stroke:#858585;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 1;stroke-dashoffset:0"
d="m 25.000004,812.36217 594.999996,0"
id="path3999"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<g
id="g3132"
transform="translate(0,79.999997)">
<rect
y="937.36218"
x="50"
height="25.000031"
width="400"
id="rect3008"
style="fill:#caf3f6;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-opacity:1" />
<text
sodipodi:linespacing="125%"
id="text3778"
y="953.72449"
x="249.91454"
style="font-size:14px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
y="953.72449"
x="249.91454"
id="tspan3780"
sodipodi:role="line">Physical Connection</tspan></text>
</g>
<g
id="g3137"
transform="translate(0,29.999997)">
<rect
style="fill:#caf3f6;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-opacity:1"
id="rect3797"
width="400"
height="25"
x="50"
y="962.36218" />
<text
xml:space="preserve"
style="font-size:14px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="249.91455"
y="978.72449"
id="text3799"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3801"
x="249.91455"
y="978.72449">AsyncEndPoint</tspan></text>
</g>
<g
id="g3142"
transform="translate(0,-20.000003)">
<rect
y="987.36218"
x="50"
height="24.999996"
width="400"
id="rect3805"
style="fill:#caf3f6;fill-opacity:1;stroke:#000000;stroke-width:0.99999994;stroke-opacity:1" />
<text
sodipodi:linespacing="125%"
id="text3807"
y="1003.7245"
x="249.91455"
style="font-size:14px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
y="1003.7245"
x="249.91455"
id="tspan3809"
sodipodi:role="line">WebSocketAsyncConnection</tspan></text>
</g>
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path4004"
d="m 25.000004,957.36218 594.999996,0"
style="fill:none;stroke:#858585;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 1;stroke-dashoffset:0" />
<g
id="g3152"
transform="translate(0,-70.000003)">
<rect
style="fill:#caf3f6;fill-opacity:1;stroke:#000000;stroke-width:0.99999994;stroke-opacity:1"
id="rect3786"
width="200"
height="25"
x="50"
y="1012.3622" />
<text
xml:space="preserve"
style="font-size:14px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="149.31982"
y="1029.8661"
id="text3815"
sodipodi:linespacing="125%"><tspan
id="tspan3822"
sodipodi:role="line"
x="149.31982"
y="1029.8661">Parser</tspan></text>
</g>
<g
id="g3147"
transform="translate(0,-70.000003)">
<rect
y="1012.3622"
x="250"
height="25"
width="200"
id="rect3788"
style="fill:#caf3f6;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-opacity:1" />
<text
sodipodi:linespacing="125%"
id="text3826"
y="1029.9584"
x="314.03955"
style="font-size:14px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
id="tspan3830"
y="1029.9584"
x="314.03955"
sodipodi:role="line">Generator</tspan></text>
</g>
<g
id="g3954"
transform="translate(-0.0854492,38.643061)">
<rect
style="fill:#caf3f6;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-opacity:1"
id="rect3849"
width="400"
height="25"
x="50.085449"
y="710.99988" />
<text
xml:space="preserve"
style="font-size:14px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="250"
y="727.36218"
id="text3851"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3853"
x="250"
y="727.36218">WebSocketEndPoint</tspan></text>
</g>
<g
id="g3949"
transform="translate(-0.0854492,-36.356939)">
<rect
style="fill:#caf3f6;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-opacity:1"
id="rect3865"
width="400"
height="25"
x="50.085449"
y="760.99988" />
<text
xml:space="preserve"
style="font-size:14px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="250"
y="777.36218"
id="text3867"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3869"
x="250"
y="777.36218">WebSocket Object</tspan></text>
</g>
<rect
style="fill:url(#linearGradient3971);fill-opacity:1;stroke:#000000;stroke-width:1;stroke-opacity:1"
id="rect3961"
width="400"
height="152.71928"
x="50"
y="774.64294" />
<rect
style="fill:#caf3f6;fill-opacity:1;stroke:#000000;stroke-width:0.90829504;stroke-opacity:1"
id="rect3881"
width="164.99998"
height="25"
x="60"
y="799.64294" />
<text
xml:space="preserve"
style="font-size:14px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="136.81982"
y="817.36218"
id="text3883"
sodipodi:linespacing="125%"><tspan
id="tspan3885"
sodipodi:role="line"
x="136.81982"
y="817.36218">EventDriver</tspan></text>
<rect
y="799.64294"
x="229.99998"
height="25"
width="209.99998"
id="rect3905"
style="fill:#caf3f6;fill-opacity:1;stroke:#000000;stroke-width:1.03682196;stroke-opacity:1" />
<text
sodipodi:linespacing="125%"
id="text3907"
y="817.36218"
x="334.93845"
style="font-size:14px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
y="817.36218"
x="334.93845"
sodipodi:role="line"
id="tspan3909">WebSocketRemoteEndpoint</tspan></text>
<text
xml:space="preserve"
style="font-size:14px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="249.91455"
y="791.00525"
id="text3963"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3965"
x="249.91455"
y="791.00525">WebSocketSession</tspan></text>
<text
xml:space="preserve"
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="484.2207"
y="987.36218"
id="text3979"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3981"
x="484.2207"
y="987.36218">Network</tspan><tspan
sodipodi:role="line"
x="484.2207"
y="1002.3622"
id="tspan3983">ByteBuffers</tspan></text>
<text
xml:space="preserve"
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="485"
y="847.36218"
id="text3985"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3987"
x="485"
y="847.36218">Internal</tspan><tspan
sodipodi:role="line"
x="485"
y="862.36218"
id="tspan3989">WebSocketFrame</tspan></text>
<text
xml:space="preserve"
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="485.43359"
y="762.36218"
id="text3991"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3993"
x="485.43359"
y="762.36218">Message</tspan><tspan
sodipodi:role="line"
x="485.43359"
y="777.36218"
id="tspan3995">Text or Binary</tspan></text>
<rect
style="fill:#e84400;fill-opacity:1;stroke:none"
id="rect4032"
width="65.063103"
height="11.709856"
x="414.50586"
y="757.07648"
ry="5.854928" />
<text
xml:space="preserve"
style="font-size:10.80251503px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Sans"
x="421.08868"
y="766.78979"
id="text4034"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4036"
x="421.08868"
y="766.78979"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#ffffff;fill-opacity:1;font-family:Droid Sans Mono;-inkscape-font-specification:Droid Sans Mono">EndPoint</tspan></text>
<rect
ry="5.854928"
y="781.06757"
x="418.32745"
height="11.709856"
width="59.474655"
id="rect4045"
style="fill:#e84400;fill-opacity:1;stroke:none" />
<text
sodipodi:linespacing="125%"
id="text4047"
y="790.78094"
x="425.44174"
style="font-size:10.80251503px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Sans"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#ffffff;fill-opacity:1;font-family:Droid Sans Mono;-inkscape-font-specification:Droid Sans Mono"
y="790.78094"
x="425.44174"
id="tspan4049"
sodipodi:role="line">Session</tspan></text>
<g
id="g3979"
transform="translate(-6.9855596,-6.0541516)">
<rect
ry="5.854928"
y="804.20941"
x="439.77084"
height="11.709856"
width="103.94939"
id="rect4053"
style="fill:#e84400;fill-opacity:1;stroke:none" />
<text
sodipodi:linespacing="125%"
id="text4055"
y="813.92279"
x="446.44672"
style="font-size:10.80251503px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Sans"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#ffffff;fill-opacity:1;font-family:Droid Sans Mono;-inkscape-font-specification:Droid Sans Mono"
y="813.92279"
x="446.44672"
id="tspan4057"
sodipodi:role="line">RemoteEndpoint</tspan></text>
</g>
<g
id="g4070"
transform="translate(3.6030325,-99.6839)">
<rect
ry="5.854928"
y="921.58582"
x="85.647453"
height="11.709856"
width="88.274292"
id="rect4061"
style="fill:#e84400;fill-opacity:1;stroke:none" />
<text
sodipodi:linespacing="125%"
id="text4063"
y="931.29919"
x="90.723061"
style="font-size:10.80251503px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Sans"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#ffffff;fill-opacity:1;font-family:Droid Sans Mono;-inkscape-font-specification:Droid Sans Mono"
y="931.29919"
x="90.723061"
id="tspan4065"
sodipodi:role="line">FrameHandler</tspan></text>
</g>
<g
transform="translate(228.00221,11.948808)"
id="g4075">
<rect
style="fill:#e84400;fill-opacity:1;stroke:none"
id="rect4077"
width="88.274292"
height="11.709856"
x="85.647453"
y="921.58582"
ry="5.854928" />
<text
xml:space="preserve"
style="font-size:10.80251503px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Sans"
x="90.723061"
y="931.29919"
id="text4079"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4081"
x="90.723061"
y="931.29919"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#ffffff;fill-opacity:1;font-family:Droid Sans Mono;-inkscape-font-specification:Droid Sans Mono">FrameHandler</tspan></text>
</g>
<rect
ry="5.854928"
y="780.36169"
x="59.872288"
height="11.709856"
width="107.44216"
id="rect4112"
style="fill:#e84400;fill-opacity:1;stroke:none" />
<text
sodipodi:linespacing="125%"
id="text4114"
y="790.07501"
x="66.455116"
style="font-size:10.80251503px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Sans"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#ffffff;fill-opacity:1;font-family:Droid Sans Mono;-inkscape-font-specification:Droid Sans Mono"
y="790.07501"
x="66.455116"
id="tspan4116"
sodipodi:role="line">MessageHandler</tspan></text>
<rect
style="fill:#e84400;fill-opacity:1;stroke:none"
id="rect4118"
width="63.665989"
height="11.709856"
x="328.81635"
y="780.59454"
ry="5.854928" />
<text
xml:space="preserve"
style="font-size:10.80251503px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Sans"
x="337.85223"
y="790.30786"
id="text4120"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4122"
x="337.85223"
y="790.30786"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#ffffff;fill-opacity:1;font-family:Droid Sans Mono;-inkscape-font-specification:Droid Sans Mono">Encoder</tspan></text>
<g
id="g3856"
transform="translate(-0.81398971,4.1913356)">
<rect
y="848.0545"
x="191.13927"
height="25"
width="112.82959"
id="rect3072"
style="fill:#f6f4ca;fill-opacity:1;stroke:#000000;stroke-width:0.53110641;stroke-opacity:1" />
<text
sodipodi:linespacing="125%"
id="text3074"
y="865.77374"
x="247.57115"
style="font-size:14px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
y="865.77374"
x="247.57115"
id="tspan3076"
sodipodi:role="line">Extension 2</tspan></text>
</g>
<rect
y="841.53467"
x="72.885246"
height="25"
width="129.32132"
id="rect3850"
style="fill:#f6f4ca;fill-opacity:1;stroke:#000000;stroke-width:0.56859767;stroke-opacity:1" />
<text
sodipodi:linespacing="125%"
id="text3852"
y="857.89697"
x="126.25812"
style="font-size:14px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
y="857.89697"
x="126.25812"
id="tspan3854"
sodipodi:role="line">Incoming</tspan></text>
<rect
style="fill:#f6f4ca;fill-opacity:1;stroke:#000000;stroke-width:0.56353527;stroke-opacity:1"
id="rect3861"
width="127.02879"
height="25"
x="295.69891"
y="860.62854" />
<text
xml:space="preserve"
style="font-size:14px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="370.28702"
y="876.99084"
id="text3863"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3865"
x="370.28702"
y="876.99084">Outgoing</tspan></text>
<g
transform="translate(-0.81398971,41.913358)"
id="g3877">
<rect
style="fill:#f6f4ca;fill-opacity:1;stroke:#000000;stroke-width:0.53110641;stroke-opacity:1"
id="rect3879"
width="112.82959"
height="25"
x="191.13927"
y="848.0545" />
<text
xml:space="preserve"
style="font-size:14px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="247.57115"
y="865.77374"
id="text3881"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3883"
x="247.57115"
y="865.77374">Extension 1</tspan></text>
</g>
<rect
style="fill:#f6f4ca;fill-opacity:1;stroke:#000000;stroke-width:0.56359768;stroke-opacity:1"
id="rect3887"
width="127.05691"
height="25"
x="75.149658"
y="879.25665" />
<text
xml:space="preserve"
style="font-size:14px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="126.25812"
y="895.61896"
id="text3889"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3891"
x="126.25812"
y="895.61896">Incoming</tspan></text>
<rect
y="898.35059"
x="295.69891"
height="25"
width="125.62177"
id="rect3895"
style="fill:#f6f4ca;fill-opacity:1;stroke:#000000;stroke-width:0.56040561;stroke-opacity:1" />
<text
sodipodi:linespacing="125%"
id="text3897"
y="914.71289"
x="370.28702"
style="font-size:14px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
y="914.71289"
x="370.28702"
id="tspan3899"
sodipodi:role="line">Outgoing</tspan></text>
<g
id="g3925"
transform="matrix(-1,0,0,-1,156.93219,1775.5293)">
<path
inkscape:connector-curvature="0"
id="rect3934"
d="m 75.000004,817.36217 0,137.3125 -7.65625,0 17.65625,17.6875 17.687496,-17.6875 -7.687496,0 0,-137.3125 -20,0 z"
style="fill:#f7d1d1;fill-opacity:1;stroke:#dd9191;stroke-width:1;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<text
transform="matrix(0,1,-1,0,0,0)"
sodipodi:linespacing="125%"
id="text3948"
y="-81.15332"
x="822.36218"
style="font-size:14px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
y="-81.15332"
x="822.36218"
id="tspan3950"
sodipodi:role="line">IncomingFrames</tspan></text>
</g>
<g
id="g3930"
transform="matrix(-1,0,0,-1,842.97235,1773.7812)">
<path
inkscape:connector-curvature="0"
id="rect3954"
d="m 420,817.36217 -17.6875,17.6875 7.6875,0 0,117.3125 20,0 0,-117.3125 7.65625,0 L 420,817.36217 z"
style="fill:#f7d1d1;fill-opacity:1;stroke:#dd9191;stroke-width:0.99999994;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<text
xml:space="preserve"
style="font-size:14px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="-942.64636"
y="423.84668"
id="text3969"
sodipodi:linespacing="125%"
transform="matrix(0,-1,1,0,0,0)"><tspan
sodipodi:role="line"
id="tspan3971"
x="-942.64636"
y="423.84668">OutgoingFrames</tspan></text>
</g>
<g
transform="translate(3.6030325,-60.564766)"
id="g3901">
<rect
style="fill:#e84400;fill-opacity:1;stroke:none"
id="rect3903"
width="88.274292"
height="11.709856"
x="85.647453"
y="921.58582"
ry="5.854928" />
<text
xml:space="preserve"
style="font-size:10.80251503px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Sans"
x="90.723061"
y="931.29919"
id="text3905"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3907"
x="90.723061"
y="931.29919"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#ffffff;fill-opacity:1;font-family:Droid Sans Mono;-inkscape-font-specification:Droid Sans Mono">FrameHandler</tspan></text>
</g>
<g
id="g3909"
transform="translate(3.6030325,-20.979928)">
<rect
ry="5.854928"
y="921.58582"
x="85.647453"
height="11.709856"
width="88.274292"
id="rect3911"
style="fill:#e84400;fill-opacity:1;stroke:none" />
<text
sodipodi:linespacing="125%"
id="text3913"
y="931.29919"
x="90.723061"
style="font-size:10.80251503px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Sans"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#ffffff;fill-opacity:1;font-family:Droid Sans Mono;-inkscape-font-specification:Droid Sans Mono"
y="931.29919"
x="90.723061"
id="tspan3915"
sodipodi:role="line">FrameHandler</tspan></text>
</g>
<g
id="g3917"
transform="translate(228.00221,-31.827366)">
<rect
ry="5.854928"
y="921.58582"
x="85.647453"
height="11.709856"
width="88.274292"
id="rect3919"
style="fill:#e84400;fill-opacity:1;stroke:none" />
<text
sodipodi:linespacing="125%"
id="text3921"
y="931.29919"
x="90.723061"
style="font-size:10.80251503px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Sans"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#ffffff;fill-opacity:1;font-family:Droid Sans Mono;-inkscape-font-specification:Droid Sans Mono"
y="931.29919"
x="90.723061"
id="tspan3923"
sodipodi:role="line">FrameHandler</tspan></text>
</g>
<g
transform="translate(228.00221,-69.549388)"
id="g3926">
<rect
style="fill:#e84400;fill-opacity:1;stroke:none"
id="rect3928"
width="88.274292"
height="11.709856"
x="85.647453"
y="921.58582"
ry="5.854928" />
<text
xml:space="preserve"
style="font-size:10.80251503px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Sans"
x="90.723061"
y="931.29919"
id="text3930"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3932"
x="90.723061"
y="931.29919"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#ffffff;fill-opacity:1;font-family:Droid Sans Mono;-inkscape-font-specification:Droid Sans Mono">FrameHandler</tspan></text>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 30 KiB

View File

@ -1,575 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="645"
height="350"
id="svg2"
version="1.1"
inkscape:version="0.48.3.1 r9886"
sodipodi:docname="javax.net.websocket-stack-simple.svg"
inkscape:export-filename="/home/joakim/code/intalio/org.eclipse.jetty9.project/jetty-websocket/websocket-common/src/main/javadoc/org/eclipse/jetty/websocket/doc-files/javax.net.websocket-stack-simple.png"
inkscape:export-xdpi="111.63"
inkscape:export-ydpi="111.63">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="2.1472868"
inkscape:cx="290.96542"
inkscape:cy="172.35578"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:window-width="1920"
inkscape:window-height="1024"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
showguides="true"
inkscape:guide-bbox="true"
borderlayer="true"
inkscape:snap-grids="false">
<inkscape:grid
type="xygrid"
id="grid3006"
empspacing="5"
dotted="true"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true"
spacingx="5px"
spacingy="5px" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Background"
sodipodi:insensitive="true">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none"
id="rect3089"
width="645"
height="350"
x="0"
y="0" />
</g>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-702.36218)">
<rect
style="fill:#b9b9b9;fill-opacity:1;stroke:none"
id="rect3977"
width="560"
height="70.000008"
x="40.000004"
y="957.36218" />
<rect
y="812.36218"
x="40.000004"
height="145"
width="560"
id="rect3975"
style="fill:#d1d1d1;fill-opacity:1;stroke:none" />
<rect
style="fill:#ececec;fill-opacity:1;stroke:none"
id="rect3973"
width="560"
height="75"
x="40.000004"
y="737.24573" />
<path
style="fill:none;stroke:#858585;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 1;stroke-dashoffset:0"
d="m 25.000004,812.36217 594.999996,0"
id="path3999"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<g
id="g3132"
transform="translate(0,79.999997)">
<rect
y="937.36218"
x="50"
height="25.000031"
width="400"
id="rect3008"
style="fill:#caf3f6;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-opacity:1" />
<text
sodipodi:linespacing="125%"
id="text3778"
y="953.72449"
x="249.91454"
style="font-size:14px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
y="953.72449"
x="249.91454"
id="tspan3780"
sodipodi:role="line">Physical Connection</tspan></text>
</g>
<g
id="g3137"
transform="translate(0,29.999997)">
<rect
style="fill:#caf3f6;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-opacity:1"
id="rect3797"
width="400"
height="25"
x="50"
y="962.36218" />
<text
xml:space="preserve"
style="font-size:14px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="249.91455"
y="978.72449"
id="text3799"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3801"
x="249.91455"
y="978.72449">AsyncEndPoint</tspan></text>
</g>
<g
id="g3142"
transform="translate(0,-20.000003)">
<rect
y="987.36218"
x="50"
height="24.999996"
width="400"
id="rect3805"
style="fill:#caf3f6;fill-opacity:1;stroke:#000000;stroke-width:0.99999994;stroke-opacity:1" />
<text
sodipodi:linespacing="125%"
id="text3807"
y="1003.7245"
x="249.91455"
style="font-size:14px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
y="1003.7245"
x="249.91455"
id="tspan3809"
sodipodi:role="line">WebSocketAsyncConnection</tspan></text>
</g>
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path4004"
d="m 25.000004,957.36218 594.999996,0"
style="fill:none;stroke:#858585;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 1;stroke-dashoffset:0" />
<g
id="g3152"
transform="translate(0,-70.000003)">
<rect
style="fill:#caf3f6;fill-opacity:1;stroke:#000000;stroke-width:0.99999994;stroke-opacity:1"
id="rect3786"
width="200"
height="25"
x="50"
y="1012.3622" />
<text
xml:space="preserve"
style="font-size:14px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="149.31982"
y="1029.8661"
id="text3815"
sodipodi:linespacing="125%"><tspan
id="tspan3822"
sodipodi:role="line"
x="149.31982"
y="1029.8661">Parser</tspan></text>
</g>
<g
id="g3147"
transform="translate(0,-70.000003)">
<rect
y="1012.3622"
x="250"
height="25"
width="200"
id="rect3788"
style="fill:#caf3f6;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-opacity:1" />
<text
sodipodi:linespacing="125%"
id="text3826"
y="1029.9584"
x="314.03955"
style="font-size:14px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
id="tspan3830"
y="1029.9584"
x="314.03955"
sodipodi:role="line">Generator</tspan></text>
</g>
<g
id="g3954"
transform="translate(-0.0854492,38.643061)">
<rect
style="fill:#caf3f6;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-opacity:1"
id="rect3849"
width="400"
height="25"
x="50.085449"
y="710.99988" />
<text
xml:space="preserve"
style="font-size:14px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="250"
y="727.36218"
id="text3851"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3853"
x="250"
y="727.36218">WebSocketEndPoint</tspan></text>
</g>
<g
id="g3949"
transform="translate(-0.0854492,-36.356939)">
<rect
style="fill:#caf3f6;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-opacity:1"
id="rect3865"
width="400"
height="25"
x="50.085449"
y="760.99988" />
<text
xml:space="preserve"
style="font-size:14px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="250"
y="777.36218"
id="text3867"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3869"
x="250"
y="777.36218">WebSocket Object</tspan></text>
</g>
<g
id="g3973"
transform="translate(0,17.280759)">
<rect
y="782.36218"
x="49.999996"
height="25"
width="175"
id="rect3881"
style="fill:#caf3f6;fill-opacity:1;stroke:#000000;stroke-width:0.93541425;stroke-opacity:1" />
<text
sodipodi:linespacing="125%"
id="text3883"
y="800.08142"
x="136.81982"
style="font-size:14px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
y="800.08142"
x="136.81982"
sodipodi:role="line"
id="tspan3885">EventDriver</tspan></text>
</g>
<g
id="g3978"
transform="translate(0,17.280759)">
<rect
style="fill:#caf3f6;fill-opacity:1;stroke:#000000;stroke-width:1.06066012;stroke-opacity:1"
id="rect3905"
width="225"
height="25"
x="225"
y="782.36218" />
<text
xml:space="preserve"
style="font-size:14px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="337.43848"
y="798.72449"
id="text3907"
sodipodi:linespacing="125%"><tspan
id="tspan3909"
sodipodi:role="line"
x="337.43848"
y="798.72449">WebSocketRemoteEndpoint</tspan></text>
</g>
<g
transform="translate(-0.0854492,63.643061)"
id="g3959">
<rect
y="710.99988"
x="50.085449"
height="25"
width="400"
id="rect3961"
style="fill:#caf3f6;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-opacity:1" />
<text
sodipodi:linespacing="125%"
id="text3963"
y="727.36218"
x="250"
style="font-size:14px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
y="727.36218"
x="250"
id="tspan3965"
sodipodi:role="line">WebSocketSession</tspan></text>
</g>
<g
id="g3930"
transform="matrix(-1,0,0,-1,842.97235,1773.7812)">
<path
inkscape:connector-curvature="0"
id="rect3954"
d="m 420,817.36217 -17.6875,17.6875 7.6875,0 0,117.3125 20,0 0,-117.3125 7.65625,0 L 420,817.36217 z"
style="fill:#f7d1d1;fill-opacity:1;stroke:#dd9191;stroke-width:0.99999994;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<text
xml:space="preserve"
style="font-size:14px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="-942.64636"
y="423.84668"
id="text3969"
sodipodi:linespacing="125%"
transform="matrix(0,-1,1,0,0,0)"><tspan
sodipodi:role="line"
id="tspan3971"
x="-942.64636"
y="423.84668">OutgoingFrames</tspan></text>
</g>
<text
xml:space="preserve"
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="484.2207"
y="987.36218"
id="text3979"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3981"
x="484.2207"
y="987.36218">Network</tspan><tspan
sodipodi:role="line"
x="484.2207"
y="1002.3622"
id="tspan3983">ByteBuffers</tspan></text>
<text
xml:space="preserve"
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="485"
y="847.36218"
id="text3985"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3987"
x="485"
y="847.36218">Internal</tspan><tspan
sodipodi:role="line"
x="485"
y="862.36218"
id="tspan3989">WebSocketFrame</tspan></text>
<text
xml:space="preserve"
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="485.43359"
y="762.36218"
id="text3991"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3993"
x="485.43359"
y="762.36218">Message</tspan><tspan
sodipodi:role="line"
x="485.43359"
y="777.36218"
id="tspan3995">Text or Binary</tspan></text>
<rect
style="fill:#e84400;fill-opacity:1;stroke:none"
id="rect4032"
width="65.063103"
height="11.709856"
x="414.50586"
y="757.07648"
ry="5.854928" />
<text
xml:space="preserve"
style="font-size:10.80251503px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Sans"
x="421.08868"
y="766.78979"
id="text4034"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4036"
x="421.08868"
y="766.78979"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#ffffff;fill-opacity:1;font-family:Droid Sans Mono;-inkscape-font-specification:Droid Sans Mono">EndPoint</tspan></text>
<rect
ry="5.854928"
y="781.06757"
x="418.32745"
height="11.709856"
width="59.474655"
id="rect4045"
style="fill:#e84400;fill-opacity:1;stroke:none" />
<text
sodipodi:linespacing="125%"
id="text4047"
y="790.78094"
x="425.44174"
style="font-size:10.80251503px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Sans"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#ffffff;fill-opacity:1;font-family:Droid Sans Mono;-inkscape-font-specification:Droid Sans Mono"
y="790.78094"
x="425.44174"
id="tspan4049"
sodipodi:role="line">Session</tspan></text>
<rect
style="fill:#e84400;fill-opacity:1;stroke:none"
id="rect4053"
width="103.94939"
height="11.709856"
x="439.77084"
y="804.20941"
ry="5.854928" />
<text
xml:space="preserve"
style="font-size:10.80251503px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Sans"
x="446.44672"
y="813.92279"
id="text4055"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4057"
x="446.44672"
y="813.92279"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#ffffff;fill-opacity:1;font-family:Droid Sans Mono;-inkscape-font-specification:Droid Sans Mono">RemoteEndpoint</tspan></text>
<g
id="g4070"
transform="translate(3.6030325,-99.6839)">
<rect
ry="5.854928"
y="921.58582"
x="85.647453"
height="11.709856"
width="88.274292"
id="rect4061"
style="fill:#e84400;fill-opacity:1;stroke:none" />
<text
sodipodi:linespacing="125%"
id="text4063"
y="931.29919"
x="90.723061"
style="font-size:10.80251503px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Sans"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#ffffff;fill-opacity:1;font-family:Droid Sans Mono;-inkscape-font-specification:Droid Sans Mono"
y="931.29919"
x="90.723061"
id="tspan4065"
sodipodi:role="line">FrameHandler</tspan></text>
</g>
<g
id="g3925"
transform="matrix(-1,0,0,-1,156.93219,1775.5293)">
<path
inkscape:connector-curvature="0"
id="rect3934"
d="m 75.000004,817.36217 0,137.3125 -7.65625,0 17.65625,17.6875 17.687496,-17.6875 -7.687496,0 0,-137.3125 -20,0 z"
style="fill:#f7d1d1;fill-opacity:1;stroke:#dd9191;stroke-width:1;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<text
transform="matrix(0,1,-1,0,0,0)"
sodipodi:linespacing="125%"
id="text3948"
y="-81.15332"
x="822.36218"
style="font-size:14px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
y="-81.15332"
x="822.36218"
id="tspan3950"
sodipodi:role="line">IncomingFrames</tspan></text>
</g>
<g
transform="translate(220.08524,13.811624)"
id="g4075">
<rect
style="fill:#e84400;fill-opacity:1;stroke:none"
id="rect4077"
width="88.274292"
height="11.709856"
x="85.647453"
y="921.58582"
ry="5.854928" />
<text
xml:space="preserve"
style="font-size:10.80251503px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Sans"
x="90.723061"
y="931.29919"
id="text4079"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4081"
x="90.723061"
y="931.29919"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#ffffff;fill-opacity:1;font-family:Droid Sans Mono;-inkscape-font-specification:Droid Sans Mono">FrameHandler</tspan></text>
</g>
<rect
ry="5.854928"
y="780.36169"
x="59.872288"
height="11.709856"
width="107.44216"
id="rect4112"
style="fill:#e84400;fill-opacity:1;stroke:none" />
<text
sodipodi:linespacing="125%"
id="text4114"
y="790.07501"
x="66.455116"
style="font-size:10.80251503px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Sans"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#ffffff;fill-opacity:1;font-family:Droid Sans Mono;-inkscape-font-specification:Droid Sans Mono"
y="790.07501"
x="66.455116"
id="tspan4116"
sodipodi:role="line">MessageHandler</tspan></text>
<rect
style="fill:#e84400;fill-opacity:1;stroke:none"
id="rect4118"
width="63.665989"
height="11.709856"
x="328.81635"
y="780.59454"
ry="5.854928" />
<text
xml:space="preserve"
style="font-size:10.80251503px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Sans"
x="337.85223"
y="790.30786"
id="text4120"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4122"
x="337.85223"
y="790.30786"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#ffffff;fill-opacity:1;font-family:Droid Sans Mono;-inkscape-font-specification:Droid Sans Mono">Encoder</tspan></text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 21 KiB

Some files were not shown because too many files have changed in this diff Show More