Merge remote-tracking branch 'origin/master' into bug-359329
This commit is contained in:
commit
cc84c3d6a0
|
@ -1,12 +1,11 @@
|
|||
package org.eclipse.jetty.client;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.SocketException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.Arrays;
|
||||
|
@ -16,19 +15,21 @@ import java.util.concurrent.Executors;
|
|||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLEngine;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletInputStream;
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.http.HttpParser;
|
||||
import org.eclipse.jetty.io.AsyncEndPoint;
|
||||
import org.eclipse.jetty.io.Buffer;
|
||||
import org.eclipse.jetty.io.Buffers;
|
||||
import org.eclipse.jetty.io.Connection;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
|
@ -47,15 +48,22 @@ import org.junit.Before;
|
|||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
import static org.hamcrest.Matchers.lessThan;
|
||||
|
||||
public class SslBytesServerTest extends SslBytesTest
|
||||
{
|
||||
private final static int MAX_IDLE_TIME=5000;
|
||||
|
||||
private final AtomicInteger sslHandles = new AtomicInteger();
|
||||
private final AtomicInteger sslFlushes = new AtomicInteger();
|
||||
private final AtomicInteger httpParses = new AtomicInteger();
|
||||
private ExecutorService threadPool;
|
||||
private Server server;
|
||||
private SSLContext sslContext;
|
||||
private SimpleProxy proxy;
|
||||
|
||||
private final AtomicReference<SslConnection> sslConnection = new AtomicReference<SslConnection>();
|
||||
|
||||
@Before
|
||||
public void init() throws Exception
|
||||
{
|
||||
|
@ -67,7 +75,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
@Override
|
||||
protected SslConnection newSslConnection(AsyncEndPoint endPoint, SSLEngine engine)
|
||||
{
|
||||
return new SslConnection(engine, endPoint)
|
||||
SslConnection connection = new SslConnection(engine, endPoint)
|
||||
{
|
||||
@Override
|
||||
public Connection handle() throws IOException
|
||||
|
@ -75,7 +83,23 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
sslHandles.incrementAndGet();
|
||||
return super.handle();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SslEndPoint newSslEndPoint()
|
||||
{
|
||||
return new SslEndPoint()
|
||||
{
|
||||
@Override
|
||||
public int flush(Buffer buffer) throws IOException
|
||||
{
|
||||
sslFlushes.incrementAndGet();
|
||||
return super.flush(buffer);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
sslConnection.set(connection);
|
||||
return connection;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -99,7 +123,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
};
|
||||
}
|
||||
};
|
||||
connector.setMaxIdleTime(2000);
|
||||
connector.setMaxIdleTime(MAX_IDLE_TIME);
|
||||
|
||||
// connector.setPort(5870);
|
||||
connector.setPort(0);
|
||||
|
@ -119,9 +143,15 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
if (contentLength != null)
|
||||
{
|
||||
int length = Integer.parseInt(contentLength);
|
||||
ServletInputStream input = request.getInputStream();
|
||||
ServletInputStream input = httpRequest.getInputStream();
|
||||
ServletOutputStream output = httpResponse.getOutputStream();
|
||||
byte[] buffer = new byte[32 * 1024];
|
||||
for (int i = 0; i < length; ++i)
|
||||
input.read();
|
||||
{
|
||||
int read = input.read(buffer);
|
||||
if ("/echo".equals(target))
|
||||
output.write(buffer, 0, read);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -199,6 +229,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
|
||||
// Check that we did not spin
|
||||
Assert.assertThat(sslHandles.get(), lessThan(20));
|
||||
Assert.assertThat(sslFlushes.get(), lessThan(20));
|
||||
Assert.assertThat(httpParses.get(), lessThan(50));
|
||||
|
||||
closeClient(client);
|
||||
|
@ -225,10 +256,8 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
System.arraycopy(bytes, 0, chunk1, 0, chunk1.length);
|
||||
byte[] chunk2 = new byte[bytes.length - chunk1.length];
|
||||
System.arraycopy(bytes, chunk1.length, chunk2, 0, chunk2.length);
|
||||
proxy.flushToServer(chunk1);
|
||||
TimeUnit.MILLISECONDS.sleep(100);
|
||||
proxy.flushToServer(chunk2);
|
||||
TimeUnit.MILLISECONDS.sleep(100);
|
||||
proxy.flushToServer(100, chunk1);
|
||||
proxy.flushToServer(100, chunk2);
|
||||
|
||||
// Server Hello + Certificate + Server Done
|
||||
record = proxy.readFromServer();
|
||||
|
@ -241,10 +270,8 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
System.arraycopy(bytes, 0, chunk1, 0, chunk1.length);
|
||||
chunk2 = new byte[bytes.length - chunk1.length];
|
||||
System.arraycopy(bytes, chunk1.length, chunk2, 0, chunk2.length);
|
||||
proxy.flushToServer(chunk1);
|
||||
TimeUnit.MILLISECONDS.sleep(100);
|
||||
proxy.flushToServer(chunk2);
|
||||
TimeUnit.MILLISECONDS.sleep(100);
|
||||
proxy.flushToServer(100, chunk1);
|
||||
proxy.flushToServer(100, chunk2);
|
||||
|
||||
// Change Cipher Spec
|
||||
record = proxy.readFromClient();
|
||||
|
@ -253,10 +280,8 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
System.arraycopy(bytes, 0, chunk1, 0, chunk1.length);
|
||||
chunk2 = new byte[bytes.length - chunk1.length];
|
||||
System.arraycopy(bytes, chunk1.length, chunk2, 0, chunk2.length);
|
||||
proxy.flushToServer(chunk1);
|
||||
TimeUnit.MILLISECONDS.sleep(100);
|
||||
proxy.flushToServer(chunk2);
|
||||
TimeUnit.MILLISECONDS.sleep(100);
|
||||
proxy.flushToServer(100, chunk1);
|
||||
proxy.flushToServer(100, chunk2);
|
||||
|
||||
// Client Done
|
||||
record = proxy.readFromClient();
|
||||
|
@ -265,10 +290,8 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
System.arraycopy(bytes, 0, chunk1, 0, chunk1.length);
|
||||
chunk2 = new byte[bytes.length - chunk1.length];
|
||||
System.arraycopy(bytes, chunk1.length, chunk2, 0, chunk2.length);
|
||||
proxy.flushToServer(chunk1);
|
||||
TimeUnit.MILLISECONDS.sleep(100);
|
||||
proxy.flushToServer(chunk2);
|
||||
TimeUnit.MILLISECONDS.sleep(100);
|
||||
proxy.flushToServer(100, chunk1);
|
||||
proxy.flushToServer(100, chunk2);
|
||||
|
||||
// Change Cipher Spec
|
||||
record = proxy.readFromServer();
|
||||
|
@ -284,6 +307,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
|
||||
// Check that we did not spin
|
||||
Assert.assertThat(sslHandles.get(), lessThan(20));
|
||||
Assert.assertThat(sslFlushes.get(), lessThan(20));
|
||||
Assert.assertThat(httpParses.get(), lessThan(50));
|
||||
|
||||
client.close();
|
||||
|
@ -295,10 +319,8 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
System.arraycopy(bytes, 0, chunk1, 0, chunk1.length);
|
||||
chunk2 = new byte[bytes.length - chunk1.length];
|
||||
System.arraycopy(bytes, chunk1.length, chunk2, 0, chunk2.length);
|
||||
proxy.flushToServer(chunk1);
|
||||
TimeUnit.MILLISECONDS.sleep(100);
|
||||
proxy.flushToServer(chunk2);
|
||||
TimeUnit.MILLISECONDS.sleep(100);
|
||||
proxy.flushToServer(100, chunk1);
|
||||
proxy.flushToServer(100, chunk2);
|
||||
// Socket close
|
||||
record = proxy.readFromClient();
|
||||
Assert.assertNull(String.valueOf(record), record);
|
||||
|
@ -358,6 +380,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
|
||||
// Check that we did not spin
|
||||
Assert.assertThat(sslHandles.get(), lessThan(20));
|
||||
Assert.assertThat(sslFlushes.get(), lessThan(20));
|
||||
Assert.assertThat(httpParses.get(), lessThan(50));
|
||||
|
||||
closeClient(client);
|
||||
|
@ -380,10 +403,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
// Client Hello
|
||||
TLSRecord record = proxy.readFromClient();
|
||||
for (byte b : record.getBytes())
|
||||
{
|
||||
proxy.flushToServer(b);
|
||||
TimeUnit.MILLISECONDS.sleep(50);
|
||||
}
|
||||
proxy.flushToServer(50, b);
|
||||
|
||||
// Server Hello + Certificate + Server Done
|
||||
record = proxy.readFromServer();
|
||||
|
@ -392,26 +412,17 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
// Client Key Exchange
|
||||
record = proxy.readFromClient();
|
||||
for (byte b : record.getBytes())
|
||||
{
|
||||
proxy.flushToServer(b);
|
||||
TimeUnit.MILLISECONDS.sleep(50);
|
||||
}
|
||||
proxy.flushToServer(50, b);
|
||||
|
||||
// Change Cipher Spec
|
||||
record = proxy.readFromClient();
|
||||
for (byte b : record.getBytes())
|
||||
{
|
||||
proxy.flushToServer(b);
|
||||
TimeUnit.MILLISECONDS.sleep(50);
|
||||
}
|
||||
proxy.flushToServer(50, b);
|
||||
|
||||
// Client Done
|
||||
record = proxy.readFromClient();
|
||||
for (byte b : record.getBytes())
|
||||
{
|
||||
proxy.flushToServer(b);
|
||||
TimeUnit.MILLISECONDS.sleep(50);
|
||||
}
|
||||
proxy.flushToServer(50, b);
|
||||
|
||||
// Change Cipher Spec
|
||||
record = proxy.readFromServer();
|
||||
|
@ -440,10 +451,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
// Application data
|
||||
record = proxy.readFromClient();
|
||||
for (byte b : record.getBytes())
|
||||
{
|
||||
proxy.flushToServer(b);
|
||||
TimeUnit.MILLISECONDS.sleep(50);
|
||||
}
|
||||
proxy.flushToServer(50, b);
|
||||
Assert.assertNull(request.get(5, TimeUnit.SECONDS));
|
||||
|
||||
// Application data
|
||||
|
@ -463,6 +471,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
|
||||
// Check that we did not spin
|
||||
Assert.assertThat(sslHandles.get(), lessThan(750));
|
||||
Assert.assertThat(sslFlushes.get(), lessThan(750));
|
||||
Assert.assertThat(httpParses.get(), lessThan(150));
|
||||
|
||||
client.close();
|
||||
|
@ -470,10 +479,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
// Close Alert
|
||||
record = proxy.readFromClient();
|
||||
for (byte b : record.getBytes())
|
||||
{
|
||||
proxy.flushToServer(b);
|
||||
TimeUnit.MILLISECONDS.sleep(50);
|
||||
}
|
||||
proxy.flushToServer(50, b);
|
||||
// Socket close
|
||||
record = proxy.readFromClient();
|
||||
Assert.assertNull(String.valueOf(record), record);
|
||||
|
@ -587,6 +593,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
|
||||
// Application data
|
||||
TLSRecord record = proxy.readFromClient();
|
||||
Assert.assertEquals(TLSRecord.Type.APPLICATION, record.getType());
|
||||
proxy.flushToServer(record);
|
||||
Assert.assertNull(request.get(5, TimeUnit.SECONDS));
|
||||
|
||||
|
@ -594,6 +601,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
|
||||
// Close Alert
|
||||
record = proxy.readFromClient();
|
||||
Assert.assertEquals(TLSRecord.Type.ALERT, record.getType());
|
||||
proxy.flushToServer(record);
|
||||
|
||||
// Do not close the raw socket yet
|
||||
|
@ -614,6 +622,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
|
||||
// Check that we did not spin
|
||||
Assert.assertThat(sslHandles.get(), lessThan(20));
|
||||
Assert.assertThat(sslFlushes.get(), lessThan(20));
|
||||
Assert.assertThat(httpParses.get(), lessThan(50));
|
||||
|
||||
// Socket close
|
||||
|
@ -652,6 +661,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
|
||||
// Application data
|
||||
TLSRecord record = proxy.readFromClient();
|
||||
Assert.assertEquals(TLSRecord.Type.APPLICATION, record.getType());
|
||||
proxy.flushToServer(record);
|
||||
Assert.assertNull(request.get(5, TimeUnit.SECONDS));
|
||||
|
||||
|
@ -670,6 +680,64 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
|
||||
// Check that we did not spin
|
||||
Assert.assertThat(sslHandles.get(), lessThan(20));
|
||||
Assert.assertThat(sslFlushes.get(), lessThan(20));
|
||||
Assert.assertThat(httpParses.get(), lessThan(50));
|
||||
|
||||
client.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestWithBigContentWriteBlockedAndResetException() throws Exception
|
||||
{
|
||||
final SSLSocket client = newClient();
|
||||
|
||||
SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow();
|
||||
client.startHandshake();
|
||||
Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS));
|
||||
|
||||
byte[] data = new byte[128 * 1024];
|
||||
Arrays.fill(data, (byte)'X');
|
||||
final String content = new String(data, "UTF-8");
|
||||
Future<Object> request = threadPool.submit(new Callable<Object>()
|
||||
{
|
||||
public Object call() throws Exception
|
||||
{
|
||||
OutputStream clientOutput = client.getOutputStream();
|
||||
clientOutput.write(("" +
|
||||
"GET /echo HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"Content-Length: " + content.length() + "\r\n" +
|
||||
"\r\n" +
|
||||
content).getBytes("UTF-8"));
|
||||
clientOutput.flush();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
// Nine TLSRecords will be generated for the request
|
||||
for (int i = 0; i < 9; ++i)
|
||||
{
|
||||
// Application data
|
||||
TLSRecord record = proxy.readFromClient();
|
||||
Assert.assertEquals(TLSRecord.Type.APPLICATION, record.getType());
|
||||
proxy.flushToServer(record, 0);
|
||||
}
|
||||
Assert.assertNull(request.get(5, TimeUnit.SECONDS));
|
||||
|
||||
// We asked the server to echo back the data we sent
|
||||
// but we do not read it, thus causing a write interest
|
||||
// on the server.
|
||||
// However, we then simulate that the client resets the
|
||||
// connection, and this will cause an exception in the
|
||||
// server that is trying to write the data
|
||||
|
||||
proxy.resetServer();
|
||||
|
||||
// Wait a while to detect spinning
|
||||
TimeUnit.SECONDS.sleep(1);
|
||||
|
||||
Assert.assertThat(sslHandles.get(), lessThan(20));
|
||||
Assert.assertThat(sslFlushes.get(), lessThan(20));
|
||||
Assert.assertThat(httpParses.get(), lessThan(50));
|
||||
|
||||
client.close();
|
||||
|
@ -713,13 +781,11 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
byte[] bytes = new byte[dataBytes.length + closeBytes.length / 2];
|
||||
System.arraycopy(dataBytes, 0, bytes, 0, dataBytes.length);
|
||||
System.arraycopy(closeBytes, 0, bytes, dataBytes.length, closeBytes.length / 2);
|
||||
proxy.flushToServer(bytes);
|
||||
|
||||
TimeUnit.MILLISECONDS.sleep(100);
|
||||
proxy.flushToServer(100, bytes);
|
||||
|
||||
bytes = new byte[closeBytes.length - closeBytes.length / 2];
|
||||
System.arraycopy(closeBytes, closeBytes.length / 2, bytes, 0, bytes.length);
|
||||
proxy.flushToServer(bytes);
|
||||
proxy.flushToServer(100, bytes);
|
||||
|
||||
// Do not close the raw socket yet
|
||||
|
||||
|
@ -739,6 +805,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
|
||||
// Check that we did not spin
|
||||
Assert.assertThat(sslHandles.get(), lessThan(20));
|
||||
Assert.assertThat(sslFlushes.get(), lessThan(20));
|
||||
Assert.assertThat(httpParses.get(), lessThan(50));
|
||||
|
||||
// Socket close
|
||||
|
@ -785,13 +852,11 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
Assert.assertNull(request.get(5, TimeUnit.SECONDS));
|
||||
byte[] chunk1 = new byte[2 * record.getBytes().length / 3];
|
||||
System.arraycopy(record.getBytes(), 0, chunk1, 0, chunk1.length);
|
||||
proxy.flushToServer(chunk1);
|
||||
|
||||
TimeUnit.MILLISECONDS.sleep(100);
|
||||
proxy.flushToServer(100, chunk1);
|
||||
|
||||
byte[] chunk2 = new byte[record.getBytes().length - chunk1.length];
|
||||
System.arraycopy(record.getBytes(), chunk1.length, chunk2, 0, chunk2.length);
|
||||
proxy.flushToServer(chunk2);
|
||||
proxy.flushToServer(100, chunk2);
|
||||
|
||||
record = proxy.readFromServer();
|
||||
Assert.assertEquals(TLSRecord.Type.APPLICATION, record.getType());
|
||||
|
@ -809,6 +874,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
|
||||
// Check that we did not spin
|
||||
Assert.assertThat(sslHandles.get(), lessThan(20));
|
||||
Assert.assertThat(sslFlushes.get(), lessThan(20));
|
||||
Assert.assertThat(httpParses.get(), lessThan(50));
|
||||
|
||||
closeClient(client);
|
||||
|
@ -855,14 +921,13 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
System.arraycopy(bytes, 0, chunk1, 0, chunk1.length);
|
||||
byte[] chunk2 = new byte[bytes.length - chunk1.length];
|
||||
System.arraycopy(bytes, chunk1.length, chunk2, 0, chunk2.length);
|
||||
proxy.flushToServer(chunk1);
|
||||
TimeUnit.MILLISECONDS.sleep(100);
|
||||
proxy.flushToServer(chunk2);
|
||||
TimeUnit.MILLISECONDS.sleep(100);
|
||||
proxy.flushToServer(100, chunk1);
|
||||
proxy.flushToServer(100, chunk2);
|
||||
}
|
||||
|
||||
// Check that we did not spin
|
||||
Assert.assertThat(sslHandles.get(), lessThan(20));
|
||||
Assert.assertThat(sslFlushes.get(), lessThan(20));
|
||||
Assert.assertThat(httpParses.get(), lessThan(150));
|
||||
|
||||
Assert.assertNull(request.get(5, TimeUnit.SECONDS));
|
||||
|
@ -883,6 +948,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
|
||||
// Check that we did not spin
|
||||
Assert.assertThat(sslHandles.get(), lessThan(20));
|
||||
Assert.assertThat(sslFlushes.get(), lessThan(20));
|
||||
Assert.assertThat(httpParses.get(), lessThan(150));
|
||||
|
||||
closeClient(client);
|
||||
|
@ -1013,6 +1079,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
|
||||
// Check that we did not spin
|
||||
Assert.assertThat(sslHandles.get(), lessThan(20));
|
||||
Assert.assertThat(sslFlushes.get(), lessThan(20));
|
||||
Assert.assertThat(httpParses.get(), lessThan(50));
|
||||
|
||||
closeClient(client);
|
||||
|
@ -1068,10 +1135,8 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
System.arraycopy(bytes, 0, chunk1, 0, chunk1.length);
|
||||
byte[] chunk2 = new byte[bytes.length - chunk1.length];
|
||||
System.arraycopy(bytes, chunk1.length, chunk2, 0, chunk2.length);
|
||||
proxy.flushToServer(chunk1);
|
||||
TimeUnit.MILLISECONDS.sleep(100);
|
||||
proxy.flushToServer(chunk2);
|
||||
TimeUnit.MILLISECONDS.sleep(100);
|
||||
proxy.flushToServer(100, chunk1);
|
||||
proxy.flushToServer(100, chunk2);
|
||||
|
||||
// Renegotiation Handshake
|
||||
record = proxy.readFromServer();
|
||||
|
@ -1108,10 +1173,8 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
System.arraycopy(bytes, 0, chunk1, 0, chunk1.length);
|
||||
chunk2 = new byte[bytes.length - chunk1.length];
|
||||
System.arraycopy(bytes, chunk1.length, chunk2, 0, chunk2.length);
|
||||
proxy.flushToServer(chunk1);
|
||||
TimeUnit.MILLISECONDS.sleep(100);
|
||||
proxy.flushToServer(chunk2);
|
||||
TimeUnit.MILLISECONDS.sleep(100);
|
||||
proxy.flushToServer(100, chunk1);
|
||||
proxy.flushToServer(100, chunk2);
|
||||
|
||||
// Renegotiation Handshake
|
||||
record = proxy.readFromClient();
|
||||
|
@ -1121,8 +1184,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
System.arraycopy(bytes, 0, chunk1, 0, chunk1.length);
|
||||
chunk2 = new byte[bytes.length - chunk1.length];
|
||||
System.arraycopy(bytes, chunk1.length, chunk2, 0, chunk2.length);
|
||||
proxy.flushToServer(chunk1);
|
||||
TimeUnit.MILLISECONDS.sleep(100);
|
||||
proxy.flushToServer(100, chunk1);
|
||||
// Do not write the second chunk now, but merge it with content, see below
|
||||
|
||||
Assert.assertNull(renegotiation.get(5, TimeUnit.SECONDS));
|
||||
|
@ -1146,7 +1208,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
byte[] mergedBytes = new byte[chunk2.length + dataBytes.length];
|
||||
System.arraycopy(chunk2, 0, mergedBytes, 0, chunk2.length);
|
||||
System.arraycopy(dataBytes, 0, mergedBytes, chunk2.length, dataBytes.length);
|
||||
proxy.flushToServer(mergedBytes);
|
||||
proxy.flushToServer(100, mergedBytes);
|
||||
// Write the remaining 2 TLS records
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
|
@ -1176,12 +1238,12 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
|
||||
// Check that we did not spin
|
||||
Assert.assertThat(sslHandles.get(), lessThan(20));
|
||||
Assert.assertThat(sslFlushes.get(), lessThan(20));
|
||||
Assert.assertThat(httpParses.get(), lessThan(100));
|
||||
|
||||
closeClient(client);
|
||||
}
|
||||
|
||||
@Ignore
|
||||
@Test
|
||||
public void testServerCloseClientDoesNotClose() throws Exception
|
||||
{
|
||||
|
@ -1217,16 +1279,51 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
break;
|
||||
}
|
||||
|
||||
// Check client is at EOF
|
||||
Assert.assertEquals(-1,client.getInputStream().read());
|
||||
|
||||
// Client should close the socket, but let's hold it open.
|
||||
|
||||
// Check that we did not spin
|
||||
TimeUnit.MILLISECONDS.sleep(100);
|
||||
Assert.assertThat(sslHandles.get(), lessThan(20));
|
||||
Assert.assertThat(httpParses.get(), lessThan(50));
|
||||
|
||||
// TODO: instead of sleeping, we should expect the connection being closed by the idle timeout
|
||||
// TODO: mechanism; unfortunately this now is not working, and this test fails because the idle
|
||||
// TODO: timeout will not trigger.
|
||||
TimeUnit.SECONDS.sleep(100);
|
||||
|
||||
closeClient(client);
|
||||
|
||||
// Check it is still half closed on the server.
|
||||
Assert.assertTrue(((AsyncEndPoint)sslConnection.get().getEndPoint()).isOpen());
|
||||
Assert.assertTrue(((AsyncEndPoint)sslConnection.get().getEndPoint()).isOutputShutdown());
|
||||
Assert.assertFalse(((AsyncEndPoint)sslConnection.get().getEndPoint()).isInputShutdown());
|
||||
|
||||
// wait for a bit more than MAX_IDLE_TIME
|
||||
TimeUnit.MILLISECONDS.sleep(MAX_IDLE_TIME+1000);
|
||||
|
||||
// Server should have closed the endpoint
|
||||
Assert.assertFalse(((AsyncEndPoint)sslConnection.get().getEndPoint()).isOpen());
|
||||
Assert.assertTrue(((AsyncEndPoint)sslConnection.get().getEndPoint()).isOutputShutdown());
|
||||
Assert.assertTrue(((AsyncEndPoint)sslConnection.get().getEndPoint()).isInputShutdown());
|
||||
|
||||
|
||||
// writing to client will eventually get broken pipe exception or similar
|
||||
try
|
||||
{
|
||||
for (int i=0;i<100;i++)
|
||||
{
|
||||
clientOutput.write(("" +
|
||||
"POST / HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"Content-Type: text/plain\r\n" +
|
||||
"Content-Length: " + content.length() + "\r\n" +
|
||||
"Connection: close\r\n" +
|
||||
"\r\n" +
|
||||
content).getBytes("UTF-8"));
|
||||
clientOutput.flush();
|
||||
}
|
||||
Assert.fail("Client should have seen server close");
|
||||
}
|
||||
catch(SocketException e)
|
||||
{
|
||||
// this was expected.
|
||||
}
|
||||
}
|
||||
|
||||
private void assumeJavaVersionSupportsTLSRenegotiations()
|
||||
|
@ -1251,7 +1348,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
return client;
|
||||
}
|
||||
|
||||
private void closeClient(SSLSocket client) throws IOException
|
||||
private void closeClient(SSLSocket client) throws Exception
|
||||
{
|
||||
client.close();
|
||||
|
||||
|
@ -1271,5 +1368,4 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
Assert.assertNull(String.valueOf(record), record);
|
||||
proxy.flushToClient(record);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -199,7 +199,12 @@ public abstract class SslBytesTest
|
|||
return new TLSRecord(type, bytes);
|
||||
}
|
||||
|
||||
public void flushToServer(TLSRecord record) throws IOException
|
||||
public void flushToServer(TLSRecord record) throws Exception
|
||||
{
|
||||
flushToServer(record, 100);
|
||||
}
|
||||
|
||||
public void flushToServer(TLSRecord record, long sleep) throws Exception
|
||||
{
|
||||
if (record == null)
|
||||
{
|
||||
|
@ -212,20 +217,22 @@ public abstract class SslBytesTest
|
|||
}
|
||||
else
|
||||
{
|
||||
flush(server, record.getBytes());
|
||||
flush(sleep, server, record.getBytes());
|
||||
}
|
||||
}
|
||||
|
||||
public void flushToServer(byte... bytes) throws IOException
|
||||
public void flushToServer(long sleep, byte... bytes) throws Exception
|
||||
{
|
||||
flush(server, bytes);
|
||||
flush(sleep, server, bytes);
|
||||
}
|
||||
|
||||
private void flush(Socket socket, byte... bytes) throws IOException
|
||||
private void flush(long sleep, Socket socket, byte... bytes) throws Exception
|
||||
{
|
||||
OutputStream output = socket.getOutputStream();
|
||||
output.write(bytes);
|
||||
output.flush();
|
||||
if (sleep > 0)
|
||||
TimeUnit.MILLISECONDS.sleep(sleep);
|
||||
}
|
||||
|
||||
public TLSRecord readFromServer() throws IOException
|
||||
|
@ -235,7 +242,7 @@ public abstract class SslBytesTest
|
|||
return record;
|
||||
}
|
||||
|
||||
public void flushToClient(TLSRecord record) throws IOException
|
||||
public void flushToClient(TLSRecord record) throws Exception
|
||||
{
|
||||
if (record == null)
|
||||
{
|
||||
|
@ -248,7 +255,7 @@ public abstract class SslBytesTest
|
|||
}
|
||||
else
|
||||
{
|
||||
flush(client, record.getBytes());
|
||||
flush(0, client, record.getBytes());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -266,7 +273,7 @@ public abstract class SslBytesTest
|
|||
{
|
||||
while (true)
|
||||
{
|
||||
flushToServer(readFromClient());
|
||||
flushToServer(readFromClient(), 0);
|
||||
}
|
||||
}
|
||||
catch (InterruptedIOException x)
|
||||
|
@ -313,6 +320,15 @@ public abstract class SslBytesTest
|
|||
return latch.await(time, unit);
|
||||
}
|
||||
|
||||
public void resetServer() throws IOException
|
||||
{
|
||||
// Calling setSoLinger(true, 0) causes close()
|
||||
// to send a RST instead of a FIN, causing an
|
||||
// exception to be thrown on the other end
|
||||
server.setSoLinger(true, 0);
|
||||
server.close();
|
||||
}
|
||||
|
||||
public class AutomaticFlow
|
||||
{
|
||||
private final CountDownLatch stopLatch;
|
||||
|
|
|
@ -8,12 +8,14 @@ import java.io.InputStream;
|
|||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletInputStream;
|
||||
|
@ -42,9 +44,11 @@ public class TimeoutTest
|
|||
{
|
||||
private static final Logger logger = Log.getLogger(TimeoutTest.class);
|
||||
private final AtomicInteger httpParses = new AtomicInteger();
|
||||
private final AtomicInteger httpRequests = new AtomicInteger();
|
||||
private ExecutorService threadPool;
|
||||
private Server server;
|
||||
private int serverPort;
|
||||
private final AtomicReference<EndPoint> serverEndPoint = new AtomicReference<EndPoint>();
|
||||
|
||||
@Before
|
||||
public void init() throws Exception
|
||||
|
@ -57,6 +61,7 @@ public class TimeoutTest
|
|||
@Override
|
||||
protected AsyncConnection newConnection(SocketChannel channel, final AsyncEndPoint endPoint)
|
||||
{
|
||||
serverEndPoint.set(endPoint);
|
||||
return new org.eclipse.jetty.server.AsyncHttpConnection(this,endPoint,getServer())
|
||||
{
|
||||
@Override
|
||||
|
@ -67,7 +72,6 @@ public class TimeoutTest
|
|||
@Override
|
||||
public int parseNext() throws IOException
|
||||
{
|
||||
System.out.print(".");
|
||||
httpParses.incrementAndGet();
|
||||
return super.parseNext();
|
||||
}
|
||||
|
@ -87,6 +91,7 @@ public class TimeoutTest
|
|||
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException,
|
||||
ServletException
|
||||
{
|
||||
httpRequests.incrementAndGet();
|
||||
request.setHandled(true);
|
||||
String contentLength = request.getHeader("Content-Length");
|
||||
if (contentLength != null)
|
||||
|
@ -101,6 +106,7 @@ public class TimeoutTest
|
|||
server.start();
|
||||
serverPort = connector.getLocalPort();
|
||||
|
||||
httpRequests.set(0);
|
||||
logger.debug(" => :{}",serverPort);
|
||||
}
|
||||
|
||||
|
@ -119,16 +125,197 @@ public class TimeoutTest
|
|||
return client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that performs a normal http POST request, with connection:close.
|
||||
* Check that shutdownOutput is sufficient to close the server connection.
|
||||
*/
|
||||
@Test
|
||||
public void testServerCloseClientDoesClose() throws Exception
|
||||
{
|
||||
// Log.getLogger("").setDebugEnabled(true);
|
||||
final Socket client = newClient();
|
||||
final OutputStream clientOutput = client.getOutputStream();
|
||||
|
||||
byte[] data = new byte[3 * 1024];
|
||||
Arrays.fill(data,(byte)'Y');
|
||||
String content = new String(data,"UTF-8");
|
||||
|
||||
// The request section
|
||||
StringBuilder req = new StringBuilder();
|
||||
req.append("POST / HTTP/1.1\r\n");
|
||||
req.append("Host: localhost\r\n");
|
||||
req.append("Content-Type: text/plain\r\n");
|
||||
req.append("Content-Length: ").append(content.length()).append("\r\n");
|
||||
req.append("Connection: close\r\n");
|
||||
req.append("\r\n");
|
||||
// and now, the POST content section.
|
||||
req.append(content);
|
||||
|
||||
// Send request to server
|
||||
clientOutput.write(req.toString().getBytes("UTF-8"));
|
||||
clientOutput.flush();
|
||||
|
||||
InputStream in = null;
|
||||
InputStreamReader isr = null;
|
||||
BufferedReader reader = null;
|
||||
try
|
||||
{
|
||||
in = client.getInputStream();
|
||||
isr = new InputStreamReader(in);
|
||||
reader = new BufferedReader(isr);
|
||||
|
||||
// Read the response header
|
||||
String line = reader.readLine();
|
||||
Assert.assertNotNull(line);
|
||||
Assert.assertThat(line,startsWith("HTTP/1.1 200 "));
|
||||
while ((line = reader.readLine()) != null)
|
||||
{
|
||||
if (line.trim().length() == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
Assert.assertEquals("one request handled",1,httpRequests.get());
|
||||
|
||||
Assert.assertEquals("EOF received",-1,client.getInputStream().read());
|
||||
|
||||
// shutdown the output
|
||||
client.shutdownOutput();
|
||||
|
||||
// Check that we did not spin
|
||||
int httpParseCount = httpParses.get();
|
||||
Assert.assertThat(httpParseCount,lessThan(50));
|
||||
|
||||
// Try to write another request (to prove that stream is closed)
|
||||
try
|
||||
{
|
||||
clientOutput.write(req.toString().getBytes("UTF-8"));
|
||||
clientOutput.flush();
|
||||
|
||||
Assert.fail("Should not have been able to send a second POST request (connection: close)");
|
||||
}
|
||||
catch(SocketException e)
|
||||
{
|
||||
}
|
||||
|
||||
Assert.assertEquals("one request handled",1,httpRequests.get());
|
||||
}
|
||||
finally
|
||||
{
|
||||
IO.close(reader);
|
||||
IO.close(isr);
|
||||
IO.close(in);
|
||||
closeClient(client);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that performs a seemingly normal http POST request, but with
|
||||
* a client that issues "connection: close", waits 100 seconds to
|
||||
* do anything with the connection (at all), and then attempts to
|
||||
* a client that issues "connection: close", and then attempts to
|
||||
* write a second POST request.
|
||||
* <p>
|
||||
* The connection should be closed by the server, and/or be closed
|
||||
* due to a timeout on the socket.
|
||||
* The connection should be closed by the server
|
||||
*/
|
||||
@Test
|
||||
public void testServerCloseClientMoreDataSent() throws Exception
|
||||
{
|
||||
// Log.getLogger("").setDebugEnabled(true);
|
||||
final Socket client = newClient();
|
||||
final OutputStream clientOutput = client.getOutputStream();
|
||||
|
||||
byte[] data = new byte[3 * 1024];
|
||||
Arrays.fill(data,(byte)'Y');
|
||||
String content = new String(data,"UTF-8");
|
||||
|
||||
// The request section
|
||||
StringBuilder req = new StringBuilder();
|
||||
req.append("POST / HTTP/1.1\r\n");
|
||||
req.append("Host: localhost\r\n");
|
||||
req.append("Content-Type: text/plain\r\n");
|
||||
req.append("Content-Length: ").append(content.length()).append("\r\n");
|
||||
req.append("Connection: close\r\n");
|
||||
req.append("\r\n");
|
||||
// and now, the POST content section.
|
||||
req.append(content);
|
||||
|
||||
// Send request to server
|
||||
clientOutput.write(req.toString().getBytes("UTF-8"));
|
||||
clientOutput.flush();
|
||||
|
||||
InputStream in = null;
|
||||
InputStreamReader isr = null;
|
||||
BufferedReader reader = null;
|
||||
try
|
||||
{
|
||||
in = client.getInputStream();
|
||||
isr = new InputStreamReader(in);
|
||||
reader = new BufferedReader(isr);
|
||||
|
||||
// Read the response header
|
||||
String line = reader.readLine();
|
||||
Assert.assertNotNull(line);
|
||||
Assert.assertThat(line,startsWith("HTTP/1.1 200 "));
|
||||
while ((line = reader.readLine()) != null)
|
||||
{
|
||||
if (line.trim().length() == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Assert.assertEquals("EOF received",-1,client.getInputStream().read());
|
||||
Assert.assertEquals("one request handled",1,httpRequests.get());
|
||||
|
||||
// Don't shutdown the output
|
||||
// client.shutdownOutput();
|
||||
|
||||
// server side seeking EOF
|
||||
Assert.assertTrue("is open",serverEndPoint.get().isOpen());
|
||||
Assert.assertTrue("close sent",serverEndPoint.get().isOutputShutdown());
|
||||
Assert.assertFalse("close not received",serverEndPoint.get().isInputShutdown());
|
||||
|
||||
|
||||
// Check that we did not spin
|
||||
TimeUnit.SECONDS.sleep(1);
|
||||
int httpParseCount = httpParses.get();
|
||||
Assert.assertThat(httpParseCount,lessThan(50));
|
||||
|
||||
|
||||
// Write another request (which is ignored as the stream is closing), which causes real close.
|
||||
clientOutput.write(req.toString().getBytes("UTF-8"));
|
||||
clientOutput.flush();
|
||||
|
||||
// Check that we did not spin
|
||||
TimeUnit.SECONDS.sleep(1);
|
||||
httpParseCount = httpParses.get();
|
||||
Assert.assertThat(httpParseCount,lessThan(50));
|
||||
|
||||
|
||||
// server side is closed
|
||||
Assert.assertFalse("is open",serverEndPoint.get().isOpen());
|
||||
Assert.assertTrue("close sent",serverEndPoint.get().isOutputShutdown());
|
||||
Assert.assertTrue("close not received",serverEndPoint.get().isInputShutdown());
|
||||
|
||||
Assert.assertEquals("one request handled",1,httpRequests.get());
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
IO.close(reader);
|
||||
IO.close(isr);
|
||||
IO.close(in);
|
||||
closeClient(client);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test that performs a seemingly normal http POST request, but with
|
||||
* a client that issues "connection: close", and then does not close
|
||||
* the connection after reading the response.
|
||||
* <p>
|
||||
* The connection should be closed by the server after a timeout.
|
||||
*/
|
||||
@Ignore
|
||||
@Test
|
||||
public void testServerCloseClientDoesNotClose() throws Exception
|
||||
{
|
||||
|
@ -155,8 +342,6 @@ public class TimeoutTest
|
|||
clientOutput.write(req.toString().getBytes("UTF-8"));
|
||||
clientOutput.flush();
|
||||
|
||||
System.out.println("Client request #1 flushed");
|
||||
|
||||
InputStream in = null;
|
||||
InputStreamReader isr = null;
|
||||
BufferedReader reader = null;
|
||||
|
@ -178,23 +363,46 @@ public class TimeoutTest
|
|||
}
|
||||
}
|
||||
|
||||
System.out.println("Got response header");
|
||||
Assert.assertEquals("EOF received",-1,client.getInputStream().read());
|
||||
Assert.assertEquals("one request handled",1,httpRequests.get());
|
||||
|
||||
// Don't shutdown the output
|
||||
// client.shutdownOutput();
|
||||
|
||||
// server side seeking EOF
|
||||
Assert.assertTrue("is open",serverEndPoint.get().isOpen());
|
||||
Assert.assertTrue("close sent",serverEndPoint.get().isOutputShutdown());
|
||||
Assert.assertFalse("close not received",serverEndPoint.get().isInputShutdown());
|
||||
|
||||
|
||||
// Check that we did not spin
|
||||
// Wait for the server idle timeout
|
||||
TimeUnit.SECONDS.sleep(3);
|
||||
int httpParseCount = httpParses.get();
|
||||
System.out.printf("Got %d http parses%n",httpParseCount);
|
||||
Assert.assertThat(httpParseCount,lessThan(50));
|
||||
|
||||
// TODO: instead of sleeping, we should expect the connection being closed by the idle timeout
|
||||
// TODO: mechanism; unfortunately this now is not working, and this test fails because the idle
|
||||
// TODO: timeout will not trigger.
|
||||
TimeUnit.SECONDS.sleep(100);
|
||||
// server side is closed
|
||||
Assert.assertFalse("is open",serverEndPoint.get().isOpen());
|
||||
Assert.assertTrue("close sent",serverEndPoint.get().isOutputShutdown());
|
||||
Assert.assertTrue("close not received",serverEndPoint.get().isInputShutdown());
|
||||
|
||||
// Try to write another request (to prove that stream is closed)
|
||||
clientOutput.write(req.toString().getBytes("UTF-8"));
|
||||
clientOutput.flush();
|
||||
Assert.assertEquals("one request handled",1,httpRequests.get());
|
||||
|
||||
|
||||
// client will eventually get broken pipe if it keeps writing
|
||||
try
|
||||
{
|
||||
for (int i=0;i<1000;i++)
|
||||
{
|
||||
clientOutput.write(req.toString().getBytes("UTF-8"));
|
||||
clientOutput.flush();
|
||||
}
|
||||
Assert.fail("Client should have seen a broken pipe");
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
// expected broken pipe
|
||||
}
|
||||
|
||||
Assert.fail("Should not have been able to send a second POST request (connection: close)");
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
|
|
@ -968,8 +968,25 @@ public class HttpParser implements Parser
|
|||
}
|
||||
|
||||
case STATE_SEEKING_EOF:
|
||||
{
|
||||
// Skip all data
|
||||
{
|
||||
// Close if there is more data than CRLF
|
||||
if (_buffer.length()>2)
|
||||
{
|
||||
_state=STATE_END;
|
||||
_endp.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
// or if the data is not white space
|
||||
while (_buffer.length()>0)
|
||||
if (!Character.isWhitespace(_buffer.get()))
|
||||
{
|
||||
_state=STATE_END;
|
||||
_endp.close();
|
||||
_buffer.clear();
|
||||
}
|
||||
}
|
||||
|
||||
_buffer.clear();
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -510,6 +510,36 @@ public class HttpParserTest
|
|||
assertTrue(messageCompleted);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSeekEOF() throws Exception
|
||||
{
|
||||
StringEndPoint io=new StringEndPoint();
|
||||
io.setInput(
|
||||
"HTTP/1.1 200 OK\015\012"
|
||||
+ "Content-Length: 0\015\012"
|
||||
+ "Connection: close\015\012"
|
||||
+ "\015\012"
|
||||
+ "\015\012" // extra CRLF ignored
|
||||
+ "HTTP/1.1 400 OK\015\012"); // extra data causes close
|
||||
|
||||
|
||||
ByteArrayBuffer buffer= new ByteArrayBuffer(4096);
|
||||
SimpleBuffers buffers=new SimpleBuffers(buffer,null);
|
||||
|
||||
Handler handler = new Handler();
|
||||
HttpParser parser= new HttpParser(buffers,io, handler);
|
||||
|
||||
parser.parse();
|
||||
assertEquals("HTTP/1.1", f0);
|
||||
assertEquals("200", f1);
|
||||
assertEquals("OK", f2);
|
||||
assertEquals(null,_content);
|
||||
assertTrue(headerCompleted);
|
||||
assertTrue(messageCompleted);
|
||||
|
||||
|
||||
}
|
||||
|
||||
private String _content;
|
||||
private String f0;
|
||||
private String f1;
|
||||
|
|
|
@ -257,6 +257,15 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
|
|||
getSelectSet().scheduleTimeout(task,timeoutMs);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public boolean isOutputShutdown()
|
||||
{
|
||||
setCheckForIdle(true);
|
||||
return super.isOutputShutdown();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void setCheckForIdle(boolean check)
|
||||
{
|
||||
|
@ -280,7 +289,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
|
|||
public void checkIdleTimestamp(long now)
|
||||
{
|
||||
long idleTimestamp=_idleTimestamp;
|
||||
|
||||
|
||||
if (idleTimestamp!=0 && _maxIdleTime>0)
|
||||
{
|
||||
long idleForMs=now-idleTimestamp;
|
||||
|
|
|
@ -50,7 +50,7 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
private final SSLEngine _engine;
|
||||
private final SSLSession _session;
|
||||
private AsyncConnection _connection;
|
||||
private final SslEndPoint _sslEndPoint = new SslEndPoint();
|
||||
private final SslEndPoint _sslEndPoint;
|
||||
private int _allocations;
|
||||
private SslBuffers _buffers;
|
||||
private NIOBuffer _inbound;
|
||||
|
@ -93,6 +93,12 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
_engine=engine;
|
||||
_session=_engine.getSession();
|
||||
_aEndp=(AsyncEndPoint)endp;
|
||||
_sslEndPoint = newSslEndPoint();
|
||||
}
|
||||
|
||||
protected SslEndPoint newSslEndPoint()
|
||||
{
|
||||
return new SslEndPoint();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -243,7 +249,10 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
try
|
||||
{
|
||||
LOG.debug("onIdleExpired {}ms on {}",idleForMs,this);
|
||||
_sslEndPoint.shutdownOutput();
|
||||
if (_endp.isOutputShutdown())
|
||||
_sslEndPoint.close();
|
||||
else
|
||||
_sslEndPoint.shutdownOutput();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
|
@ -308,12 +317,15 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
if (_outbound.hasContent() && (flushed=_endp.flush(_outbound))>0)
|
||||
progress = true;
|
||||
}
|
||||
catch (Exception e)
|
||||
catch (IOException e)
|
||||
{
|
||||
LOG.debug(e.toString());
|
||||
LOG.ignore(e);
|
||||
_endp.close();
|
||||
throw e;
|
||||
}
|
||||
finally
|
||||
{
|
||||
LOG.debug("{} {} {} filled={}/{} flushed={}/{}",_session,this,_engine.getHandshakeStatus(),filled,_inbound.length(),flushed,_outbound.length());
|
||||
}
|
||||
LOG.debug("{} {} {} filled={}/{} flushed={}/{}",_session,this,_engine.getHandshakeStatus(),filled,_inbound.length(),flushed,_outbound.length());
|
||||
|
||||
// handle the current hand share status
|
||||
switch(_engine.getHandshakeStatus())
|
||||
|
@ -435,7 +447,7 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
}
|
||||
catch(SSLException e)
|
||||
{
|
||||
LOG.warn(_endp+":",e);
|
||||
LOG.warn(String.valueOf(_endp), e);
|
||||
_endp.close();
|
||||
throw e;
|
||||
}
|
||||
|
@ -511,10 +523,8 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
}
|
||||
catch(SSLException e)
|
||||
{
|
||||
LOG.warn(_endp+":"+e);
|
||||
LOG.debug(e);
|
||||
if (_endp.isOpen())
|
||||
_endp.close();
|
||||
LOG.warn(String.valueOf(_endp), e);
|
||||
_endp.close();
|
||||
throw e;
|
||||
}
|
||||
finally
|
||||
|
|
|
@ -20,12 +20,16 @@ import static org.junit.Assert.fail;
|
|||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.nio.channels.SocketChannel;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.eclipse.jetty.toolchain.test.OS;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -192,8 +196,87 @@ public class IOTest
|
|||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
// Dang OSX!
|
||||
System.err.println(e);
|
||||
assertTrue(OS.IS_OSX);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHalfCloseBadClient() throws Exception
|
||||
{
|
||||
ServerSocketChannel connector = ServerSocketChannel.open();
|
||||
connector.socket().bind(null);
|
||||
|
||||
Socket client = SocketChannel.open(connector.socket().getLocalSocketAddress()).socket();
|
||||
client.setSoTimeout(1000);
|
||||
client.setSoLinger(false,-1);
|
||||
Socket server = connector.accept().socket();
|
||||
server.setSoTimeout(1000);
|
||||
server.setSoLinger(false,-1);
|
||||
|
||||
// Write from client to server
|
||||
client.getOutputStream().write(1);
|
||||
|
||||
// Server reads
|
||||
assertEquals(1,server.getInputStream().read());
|
||||
|
||||
// Write from server to client with oshut
|
||||
server.getOutputStream().write(1);
|
||||
System.err.println("OSHUT "+server);
|
||||
server.shutdownOutput();
|
||||
|
||||
try
|
||||
{
|
||||
// Client reads response
|
||||
assertEquals(1,client.getInputStream().read());
|
||||
|
||||
// Client reads -1
|
||||
assertEquals(-1,client.getInputStream().read());
|
||||
assertFalse(client.isInputShutdown());
|
||||
|
||||
// Client can still write as we are half closed
|
||||
client.getOutputStream().write(1);
|
||||
|
||||
// Server can still read
|
||||
assertEquals(1,server.getInputStream().read());
|
||||
|
||||
// Server now closes
|
||||
server.close();
|
||||
|
||||
// Client still reads -1 (not broken pipe !!)
|
||||
assertEquals(-1,client.getInputStream().read());
|
||||
assertFalse(client.isInputShutdown());
|
||||
|
||||
Thread.sleep(100);
|
||||
|
||||
// Client still reads -1 (not broken pipe !!)
|
||||
assertEquals(-1,client.getInputStream().read());
|
||||
assertFalse(client.isInputShutdown());
|
||||
|
||||
// Client can still write data even though server is closed???
|
||||
client.getOutputStream().write(1);
|
||||
Thread.sleep(100);
|
||||
client.getOutputStream().write(1);
|
||||
|
||||
// Client eventually sees Broken Pipe
|
||||
int i=0;
|
||||
try
|
||||
{
|
||||
for (i=0;i<100000;i++)
|
||||
client.getOutputStream().write(1);
|
||||
|
||||
Assert.fail();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
}
|
||||
client.close();
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.err.println("PLEASE INVESTIGATE:");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -203,6 +203,25 @@ public class AsyncContinuation implements AsyncContext, Continuation
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public boolean isDispatchable()
|
||||
{
|
||||
synchronized(this)
|
||||
{
|
||||
switch(_state)
|
||||
{
|
||||
case __REDISPATCH:
|
||||
case __REDISPATCHED:
|
||||
case __REDISPATCHING:
|
||||
case __COMPLETING:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
|
|
|
@ -62,8 +62,11 @@ public class AsyncHttpConnection extends AbstractHttpConnection implements Async
|
|||
try
|
||||
{
|
||||
// Handle resumed request
|
||||
if (_request._async.isAsync() && !_request._async.isComplete())
|
||||
handleRequest();
|
||||
if (_request._async.isAsync())
|
||||
{
|
||||
if (_request._async.isDispatchable())
|
||||
handleRequest();
|
||||
}
|
||||
// else Parse more input
|
||||
else if (!_parser.isComplete() && _parser.parseAvailable())
|
||||
progress=true;
|
||||
|
|
|
@ -1,17 +1,33 @@
|
|||
package org.eclipse.jetty.server;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.io.nio.SelectChannelEndPoint;
|
||||
import org.eclipse.jetty.server.nio.SelectChannelConnector;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.junit.Test;
|
||||
|
||||
public class SelectChannelAsyncContextTest extends LocalAsyncContextTest
|
||||
{
|
||||
volatile SelectChannelEndPoint _endp;
|
||||
|
||||
@Override
|
||||
protected Connector initConnector()
|
||||
{
|
||||
return new SelectChannelConnector();
|
||||
return new SelectChannelConnector(){
|
||||
|
||||
@Override
|
||||
public void customize(EndPoint endpoint, Request request) throws IOException
|
||||
{
|
||||
super.customize(endpoint,request);
|
||||
_endp=(SelectChannelEndPoint)endpoint;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -23,4 +39,42 @@ public class SelectChannelAsyncContextTest extends LocalAsyncContextTest
|
|||
return IO.toString(socket.getInputStream());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuspendResumeWithAsyncDispatch() throws Exception
|
||||
{
|
||||
// Test that suspend/resume works in the face of spurious asyncDispatch call that may be
|
||||
// produced by the SslConnection
|
||||
final AtomicBoolean running = new AtomicBoolean(true);
|
||||
Thread thread = new Thread()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
while (running.get())
|
||||
{
|
||||
try
|
||||
{
|
||||
TimeUnit.MILLISECONDS.sleep(200);
|
||||
SelectChannelEndPoint endp=_endp;
|
||||
if (endp!=null && endp.isOpen())
|
||||
endp.asyncDispatch();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
thread.start();
|
||||
testSuspendResume();
|
||||
}
|
||||
finally
|
||||
{
|
||||
running.set(false);
|
||||
thread.join();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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;
|
||||
|
||||
import java.io.IOException;
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -87,7 +102,7 @@ public class DeflateFrameExtension extends AbstractExtension
|
|||
catch(DataFormatException e)
|
||||
{
|
||||
LOG.warn(e);
|
||||
getConnection().close(WebSocketConnectionD13.CLOSE_BAD_PAYLOAD,e.toString());
|
||||
getConnection().close(WebSocketConnectionRFC6455.CLOSE_BAD_PAYLOAD,e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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;
|
||||
|
||||
import java.util.Map;
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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;
|
||||
|
||||
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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;
|
||||
|
||||
import java.io.IOException;
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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;
|
||||
|
||||
public class IdentityExtension extends AbstractExtension
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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;
|
||||
|
||||
public interface MaskGen
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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;
|
||||
|
||||
import java.util.Random;
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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.
|
||||
*******************************************************************************/
|
||||
// ========================================================================
|
||||
// Copyright (c) 2010 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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.
|
||||
*******************************************************************************/
|
||||
// ========================================================================
|
||||
// Copyright (c) 2010 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -317,18 +332,15 @@ public class WebSocketClient
|
|||
{
|
||||
if (!_factory.isStarted())
|
||||
throw new IllegalStateException("Factory !started");
|
||||
String scheme=uri.getScheme();
|
||||
if (!("ws".equalsIgnoreCase(scheme) || "wss".equalsIgnoreCase(scheme)))
|
||||
throw new IllegalArgumentException("Bad WebSocket scheme '"+scheme+"'");
|
||||
|
||||
InetSocketAddress address = toSocketAddress(uri);
|
||||
|
||||
SocketChannel channel = SocketChannel.open();
|
||||
if (_bindAddress != null)
|
||||
channel.socket().bind(_bindAddress);
|
||||
channel.socket().setTcpNoDelay(true);
|
||||
|
||||
InetSocketAddress address=new InetSocketAddress(uri.getHost(),uri.getPort());
|
||||
|
||||
final WebSocketFuture holder=new WebSocketFuture(websocket,uri,this,channel);
|
||||
WebSocketFuture holder = new WebSocketFuture(websocket, uri, this, channel);
|
||||
|
||||
channel.configureBlocking(false);
|
||||
channel.connect(address);
|
||||
|
@ -336,6 +348,21 @@ public class WebSocketClient
|
|||
|
||||
return holder;
|
||||
}
|
||||
|
||||
public static final InetSocketAddress toSocketAddress(URI uri)
|
||||
{
|
||||
String scheme = uri.getScheme();
|
||||
if (!("ws".equalsIgnoreCase(scheme) || "wss".equalsIgnoreCase(scheme)))
|
||||
throw new IllegalArgumentException("Bad WebSocket scheme: " + scheme);
|
||||
int port = uri.getPort();
|
||||
if (port == 0)
|
||||
throw new IllegalArgumentException("Bad WebSocket port: " + port);
|
||||
if (port < 0)
|
||||
port = "ws".equals(scheme) ? 80 : 443;
|
||||
|
||||
InetSocketAddress address = new InetSocketAddress(uri.getHost(), port);
|
||||
return address;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** The Future Websocket Connection.
|
||||
|
@ -420,9 +447,9 @@ public class WebSocketClient
|
|||
if (channel!=null)
|
||||
{
|
||||
if (ex instanceof ProtocolException)
|
||||
closeChannel(channel,WebSocketConnectionD13.CLOSE_PROTOCOL,ex.getMessage());
|
||||
closeChannel(channel,WebSocketConnectionRFC6455.CLOSE_PROTOCOL,ex.getMessage());
|
||||
else
|
||||
closeChannel(channel,WebSocketConnectionD13.CLOSE_NO_CLOSE,ex.getMessage());
|
||||
closeChannel(channel,WebSocketConnectionRFC6455.CLOSE_NO_CLOSE,ex.getMessage());
|
||||
}
|
||||
}
|
||||
finally
|
||||
|
@ -466,6 +493,7 @@ public class WebSocketClient
|
|||
return _maskGen;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "[" + _uri + ","+_websocket+"]@"+hashCode();
|
||||
|
@ -487,7 +515,7 @@ public class WebSocketClient
|
|||
|
||||
if (channel!=null)
|
||||
{
|
||||
closeChannel(channel,WebSocketConnectionD13.CLOSE_NO_CLOSE,"cancelled");
|
||||
closeChannel(channel,WebSocketConnectionRFC6455.CLOSE_NO_CLOSE,"cancelled");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -547,7 +575,7 @@ public class WebSocketClient
|
|||
}
|
||||
|
||||
if (channel!=null)
|
||||
closeChannel(channel,WebSocketConnectionD13.CLOSE_NO_CLOSE,"timeout");
|
||||
closeChannel(channel,WebSocketConnectionRFC6455.CLOSE_NO_CLOSE,"timeout");
|
||||
if (exception!=null)
|
||||
throw new ExecutionException(exception);
|
||||
if (connection!=null)
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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;
|
||||
|
||||
import java.io.EOFException;
|
||||
|
@ -379,7 +394,7 @@ public class WebSocketClientFactory extends AggregateLifeCycle
|
|||
if (origin != null)
|
||||
request.append("Origin: ").append(origin).append("\r\n");
|
||||
|
||||
request.append("Sec-WebSocket-Version: ").append(WebSocketConnectionD13.VERSION).append("\r\n");
|
||||
request.append("Sec-WebSocket-Version: ").append(WebSocketConnectionRFC6455.VERSION).append("\r\n");
|
||||
|
||||
if (_future.getProtocol() != null)
|
||||
request.append("Sec-WebSocket-Protocol: ").append(_future.getProtocol()).append("\r\n");
|
||||
|
@ -436,7 +451,7 @@ public class WebSocketClientFactory extends AggregateLifeCycle
|
|||
{
|
||||
_error = "No Sec-WebSocket-Accept";
|
||||
}
|
||||
else if (!WebSocketConnectionD13.hashKey(_key).equals(_accept))
|
||||
else if (!WebSocketConnectionRFC6455.hashKey(_key).equals(_accept))
|
||||
{
|
||||
_error = "Bad Sec-WebSocket-Accept";
|
||||
}
|
||||
|
@ -444,14 +459,14 @@ public class WebSocketClientFactory extends AggregateLifeCycle
|
|||
{
|
||||
Buffer header = _parser.getHeaderBuffer();
|
||||
MaskGen maskGen = _future.getMaskGen();
|
||||
WebSocketConnectionD13 connection =
|
||||
new WebSocketConnectionD13(_future.getWebSocket(),
|
||||
WebSocketConnectionRFC6455 connection =
|
||||
new WebSocketConnectionRFC6455(_future.getWebSocket(),
|
||||
_endp,
|
||||
_buffers, System.currentTimeMillis(),
|
||||
_future.getMaxIdleTime(),
|
||||
_future.getProtocol(),
|
||||
null,
|
||||
WebSocketConnectionD13.VERSION,
|
||||
WebSocketConnectionRFC6455.VERSION,
|
||||
maskGen);
|
||||
|
||||
if (header.hasContent())
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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;
|
||||
|
||||
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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.
|
||||
*******************************************************************************/
|
||||
// ========================================================================
|
||||
// Copyright (c) 2010 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -135,11 +150,10 @@ public class WebSocketConnectionD00 extends AbstractConnection implements WebSoc
|
|||
|
||||
progress = flushed>0 || filled>0;
|
||||
|
||||
if (filled<0 || flushed<0)
|
||||
{
|
||||
_endp.close();
|
||||
break;
|
||||
}
|
||||
_endp.flush();
|
||||
|
||||
if (_endp instanceof AsyncEndPoint && ((AsyncEndPoint)_endp).hasProgressed())
|
||||
progress=true;
|
||||
}
|
||||
}
|
||||
catch(IOException e)
|
||||
|
@ -147,7 +161,8 @@ public class WebSocketConnectionD00 extends AbstractConnection implements WebSoc
|
|||
LOG.debug(e);
|
||||
try
|
||||
{
|
||||
_endp.close();
|
||||
if (_endp.isOpen())
|
||||
_endp.close();
|
||||
}
|
||||
catch(IOException e2)
|
||||
{
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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.
|
||||
*******************************************************************************/
|
||||
// ========================================================================
|
||||
// Copyright (c) 2010 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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.
|
||||
*******************************************************************************/
|
||||
// ========================================================================
|
||||
// Copyright (c) 2010 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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.
|
||||
*******************************************************************************/
|
||||
// ========================================================================
|
||||
// Copyright (c) 2010 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -60,9 +75,9 @@ import org.eclipse.jetty.websocket.WebSocket.OnTextMessage;
|
|||
* +---------------------------------------------------------------+
|
||||
* </pre>
|
||||
*/
|
||||
public class WebSocketConnectionD13 extends AbstractConnection implements WebSocketConnection
|
||||
public class WebSocketConnectionRFC6455 extends AbstractConnection implements WebSocketConnection
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(WebSocketConnectionD13.class);
|
||||
private static final Logger LOG = Log.getLogger(WebSocketConnectionRFC6455.class);
|
||||
|
||||
final static byte OP_CONTINUATION = 0x00;
|
||||
final static byte OP_TEXT = 0x01;
|
||||
|
@ -86,9 +101,12 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
final static int CLOSE_POLICY_VIOLATION=1008;
|
||||
final static int CLOSE_MESSAGE_TOO_LARGE=1009;
|
||||
final static int CLOSE_REQUIRED_EXTENSION=1010;
|
||||
final static int CLOSE_SERVER_ERROR=1011;
|
||||
final static int CLOSE_FAILED_TLS_HANDSHAKE=1015;
|
||||
|
||||
final static int FLAG_FIN=0x8;
|
||||
|
||||
// Per RFC 6455, section 1.3 - Opening Handshake - this version is "13"
|
||||
final static int VERSION=13;
|
||||
|
||||
static boolean isLastFrame(byte flags)
|
||||
|
@ -104,7 +122,7 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
private final static byte[] MAGIC;
|
||||
private final List<Extension> _extensions;
|
||||
private final WebSocketParserD13 _parser;
|
||||
private final WebSocketGeneratorD13 _generator;
|
||||
private final WebSocketGeneratorRFC6455 _generator;
|
||||
private final WebSocketGenerator _outbound;
|
||||
private final WebSocket _webSocket;
|
||||
private final OnFrame _onFrame;
|
||||
|
@ -137,14 +155,14 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public WebSocketConnectionD13(WebSocket websocket, EndPoint endpoint, WebSocketBuffers buffers, long timestamp, int maxIdleTime, String protocol, List<Extension> extensions,int draft)
|
||||
public WebSocketConnectionRFC6455(WebSocket websocket, EndPoint endpoint, WebSocketBuffers buffers, long timestamp, int maxIdleTime, String protocol, List<Extension> extensions,int draft)
|
||||
throws IOException
|
||||
{
|
||||
this(websocket,endpoint,buffers,timestamp,maxIdleTime,protocol,extensions,draft,null);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public WebSocketConnectionD13(WebSocket websocket, EndPoint endpoint, WebSocketBuffers buffers, long timestamp, int maxIdleTime, String protocol, List<Extension> extensions,int draft, MaskGen maskgen)
|
||||
public WebSocketConnectionRFC6455(WebSocket websocket, EndPoint endpoint, WebSocketBuffers buffers, long timestamp, int maxIdleTime, String protocol, List<Extension> extensions,int draft, MaskGen maskgen)
|
||||
throws IOException
|
||||
{
|
||||
super(endpoint,timestamp);
|
||||
|
@ -159,7 +177,7 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
_onTextMessage=_webSocket instanceof OnTextMessage ? (OnTextMessage)_webSocket : null;
|
||||
_onBinaryMessage=_webSocket instanceof OnBinaryMessage ? (OnBinaryMessage)_webSocket : null;
|
||||
_onControl=_webSocket instanceof OnControl ? (OnControl)_webSocket : null;
|
||||
_generator = new WebSocketGeneratorD13(buffers, _endp,maskgen);
|
||||
_generator = new WebSocketGeneratorRFC6455(buffers, _endp,maskgen);
|
||||
|
||||
_extensions=extensions;
|
||||
WebSocketParser.FrameHandler frameHandler = new WSFrameHandler();
|
||||
|
@ -217,7 +235,6 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
int filled=_parser.parseNext();
|
||||
|
||||
progress = flushed>0 || filled>0;
|
||||
|
||||
_endp.flush();
|
||||
|
||||
if (_endp instanceof AsyncEndPoint && ((AsyncEndPoint)_endp).hasProgressed())
|
||||
|
@ -272,7 +289,7 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
@Override
|
||||
public void onIdleExpired(long idleForMs)
|
||||
{
|
||||
closeOut(WebSocketConnectionD13.CLOSE_NORMAL,"Idle for "+idleForMs+"ms > "+_endp.getMaxIdleTime()+"ms");
|
||||
closeOut(WebSocketConnectionRFC6455.CLOSE_NORMAL,"Idle for "+idleForMs+"ms > "+_endp.getMaxIdleTime()+"ms");
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -289,10 +306,10 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
{
|
||||
closed=_closeCode==0;
|
||||
if (closed)
|
||||
_closeCode=WebSocketConnectionD13.CLOSE_NO_CLOSE;
|
||||
_closeCode=WebSocketConnectionRFC6455.CLOSE_NO_CLOSE;
|
||||
}
|
||||
if (closed)
|
||||
_webSocket.onClose(WebSocketConnectionD13.CLOSE_NO_CLOSE,"closed");
|
||||
_webSocket.onClose(WebSocketConnectionRFC6455.CLOSE_NO_CLOSE,"closed");
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -356,18 +373,23 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
{
|
||||
if (!closed_out)
|
||||
{
|
||||
// Close code 1005/1006 are never to be sent as a status over
|
||||
// Close code 1005/1006/1015 are never to be sent as a status over
|
||||
// a Close control frame. Code<-1 also means no node.
|
||||
|
||||
if (code<0 || (code == WebSocketConnectionD13.CLOSE_NO_CODE) || code==WebSocketConnectionD13.CLOSE_NO_CLOSE)
|
||||
code=-1;
|
||||
else if (code==0)
|
||||
code=WebSocketConnectionD13.CLOSE_NORMAL;
|
||||
if (code < 0 || (code == WebSocketConnectionRFC6455.CLOSE_NO_CODE) || (code == WebSocketConnectionRFC6455.CLOSE_NO_CLOSE)
|
||||
|| (code == WebSocketConnectionRFC6455.CLOSE_FAILED_TLS_HANDSHAKE))
|
||||
{
|
||||
code = -1;
|
||||
}
|
||||
else if (code == 0)
|
||||
{
|
||||
code = WebSocketConnectionRFC6455.CLOSE_NORMAL;
|
||||
}
|
||||
|
||||
byte[] bytes = ("xx"+(message==null?"":message)).getBytes(StringUtil.__ISO_8859_1);
|
||||
bytes[0]=(byte)(code/0x100);
|
||||
bytes[1]=(byte)(code%0x100);
|
||||
_outbound.addFrame((byte)FLAG_FIN,WebSocketConnectionD13.OP_CLOSE,bytes,0,code>0?bytes.length:0);
|
||||
_outbound.addFrame((byte)FLAG_FIN,WebSocketConnectionRFC6455.OP_CLOSE,bytes,0,code>0?bytes.length:0);
|
||||
_outbound.flush();
|
||||
}
|
||||
}
|
||||
|
@ -417,7 +439,7 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
if (_closedOut)
|
||||
throw new IOException("closedOut "+_closeCode+":"+_closeMessage);
|
||||
byte[] data = content.getBytes(StringUtil.__UTF8);
|
||||
_outbound.addFrame((byte)FLAG_FIN,WebSocketConnectionD13.OP_TEXT,data,0,data.length);
|
||||
_outbound.addFrame((byte)FLAG_FIN,WebSocketConnectionRFC6455.OP_TEXT,data,0,data.length);
|
||||
checkWriteable();
|
||||
}
|
||||
|
||||
|
@ -426,7 +448,7 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
{
|
||||
if (_closedOut)
|
||||
throw new IOException("closedOut "+_closeCode+":"+_closeMessage);
|
||||
_outbound.addFrame((byte)FLAG_FIN,WebSocketConnectionD13.OP_BINARY,content,offset,length);
|
||||
_outbound.addFrame((byte)FLAG_FIN,WebSocketConnectionRFC6455.OP_BINARY,content,offset,length);
|
||||
checkWriteable();
|
||||
}
|
||||
|
||||
|
@ -467,7 +489,7 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
if (_disconnecting)
|
||||
return;
|
||||
_disconnecting=true;
|
||||
WebSocketConnectionD13.this.closeOut(code,message);
|
||||
WebSocketConnectionRFC6455.this.closeOut(code,message);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -631,7 +653,7 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
{
|
||||
boolean lastFrame = isLastFrame(flags);
|
||||
|
||||
synchronized(WebSocketConnectionD13.this)
|
||||
synchronized(WebSocketConnectionRFC6455.this)
|
||||
{
|
||||
// Ignore incoming after a close
|
||||
if (_closedIn)
|
||||
|
@ -643,14 +665,14 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
|
||||
if (isControlFrame(opcode) && buffer.length()>MAX_CONTROL_FRAME_PAYLOAD)
|
||||
{
|
||||
errorClose(WebSocketConnectionD13.CLOSE_PROTOCOL,"Control frame too large: " + buffer.length() + " > " + MAX_CONTROL_FRAME_PAYLOAD);
|
||||
errorClose(WebSocketConnectionRFC6455.CLOSE_PROTOCOL,"Control frame too large: " + buffer.length() + " > " + MAX_CONTROL_FRAME_PAYLOAD);
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: check extensions for RSV bit(s) meanings
|
||||
if ((flags&0x7)!=0)
|
||||
{
|
||||
errorClose(WebSocketConnectionD13.CLOSE_PROTOCOL,"RSV bits set 0x"+Integer.toHexString(flags));
|
||||
errorClose(WebSocketConnectionRFC6455.CLOSE_PROTOCOL,"RSV bits set 0x"+Integer.toHexString(flags));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -675,16 +697,16 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
|
||||
switch(opcode)
|
||||
{
|
||||
case WebSocketConnectionD13.OP_CONTINUATION:
|
||||
case WebSocketConnectionRFC6455.OP_CONTINUATION:
|
||||
{
|
||||
if (_opcode==-1)
|
||||
{
|
||||
errorClose(WebSocketConnectionD13.CLOSE_PROTOCOL,"Bad Continuation");
|
||||
errorClose(WebSocketConnectionRFC6455.CLOSE_PROTOCOL,"Bad Continuation");
|
||||
return;
|
||||
}
|
||||
|
||||
// If text, append to the message buffer
|
||||
if (_onTextMessage!=null && _opcode==WebSocketConnectionD13.OP_TEXT)
|
||||
if (_onTextMessage!=null && _opcode==WebSocketConnectionRFC6455.OP_TEXT)
|
||||
{
|
||||
if (_utf8.append(buffer.array(),buffer.getIndex(),buffer.length(),_connection.getMaxTextMessageSize()))
|
||||
{
|
||||
|
@ -724,39 +746,39 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
}
|
||||
break;
|
||||
}
|
||||
case WebSocketConnectionD13.OP_PING:
|
||||
case WebSocketConnectionRFC6455.OP_PING:
|
||||
{
|
||||
LOG.debug("PING {}",this);
|
||||
if (!_closedOut)
|
||||
{
|
||||
_connection.sendControl(WebSocketConnectionD13.OP_PONG,buffer.array(),buffer.getIndex(),buffer.length());
|
||||
_connection.sendControl(WebSocketConnectionRFC6455.OP_PONG,buffer.array(),buffer.getIndex(),buffer.length());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case WebSocketConnectionD13.OP_PONG:
|
||||
case WebSocketConnectionRFC6455.OP_PONG:
|
||||
{
|
||||
LOG.debug("PONG {}",this);
|
||||
break;
|
||||
}
|
||||
|
||||
case WebSocketConnectionD13.OP_CLOSE:
|
||||
case WebSocketConnectionRFC6455.OP_CLOSE:
|
||||
{
|
||||
int code=WebSocketConnectionD13.CLOSE_NO_CODE;
|
||||
int code=WebSocketConnectionRFC6455.CLOSE_NO_CODE;
|
||||
String message=null;
|
||||
if (buffer.length()>=2)
|
||||
{
|
||||
code=(0xff&buffer.array()[buffer.getIndex()])*0x100+(0xff&buffer.array()[buffer.getIndex()+1]);
|
||||
|
||||
// Validate close status codes.
|
||||
if (code < WebSocketConnectionD13.CLOSE_NORMAL ||
|
||||
code == WebSocketConnectionD13.CLOSE_UNDEFINED ||
|
||||
code == WebSocketConnectionD13.CLOSE_NO_CLOSE ||
|
||||
code == WebSocketConnectionD13.CLOSE_NO_CODE ||
|
||||
( code > 1010 && code <= 2999 ) ||
|
||||
if (code < WebSocketConnectionRFC6455.CLOSE_NORMAL ||
|
||||
code == WebSocketConnectionRFC6455.CLOSE_UNDEFINED ||
|
||||
code == WebSocketConnectionRFC6455.CLOSE_NO_CLOSE ||
|
||||
code == WebSocketConnectionRFC6455.CLOSE_NO_CODE ||
|
||||
( code > 1011 && code <= 2999 ) ||
|
||||
code >= 5000 )
|
||||
{
|
||||
errorClose(WebSocketConnectionD13.CLOSE_PROTOCOL,"Invalid close code " + code);
|
||||
errorClose(WebSocketConnectionRFC6455.CLOSE_PROTOCOL,"Invalid close code " + code);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -772,18 +794,18 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
else if(buffer.length() == 1)
|
||||
{
|
||||
// Invalid length. use status code 1002 (Protocol error)
|
||||
errorClose(WebSocketConnectionD13.CLOSE_PROTOCOL,"Invalid payload length of 1");
|
||||
errorClose(WebSocketConnectionRFC6455.CLOSE_PROTOCOL,"Invalid payload length of 1");
|
||||
return;
|
||||
}
|
||||
closeIn(code,message);
|
||||
break;
|
||||
}
|
||||
|
||||
case WebSocketConnectionD13.OP_TEXT:
|
||||
case WebSocketConnectionRFC6455.OP_TEXT:
|
||||
{
|
||||
if (_opcode!=-1)
|
||||
{
|
||||
errorClose(WebSocketConnectionD13.CLOSE_PROTOCOL,"Expected Continuation"+Integer.toHexString(opcode));
|
||||
errorClose(WebSocketConnectionRFC6455.CLOSE_PROTOCOL,"Expected Continuation"+Integer.toHexString(opcode));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -797,7 +819,7 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
else
|
||||
{
|
||||
LOG.warn("Frame discarded. Text aggregation disabled for {}",_endp);
|
||||
errorClose(WebSocketConnectionD13.CLOSE_POLICY_VIOLATION,"Text frame aggregation disabled");
|
||||
errorClose(WebSocketConnectionRFC6455.CLOSE_POLICY_VIOLATION,"Text frame aggregation disabled");
|
||||
}
|
||||
}
|
||||
// append bytes to message buffer (if they fit)
|
||||
|
@ -811,7 +833,7 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
}
|
||||
else
|
||||
{
|
||||
_opcode=WebSocketConnectionD13.OP_TEXT;
|
||||
_opcode=WebSocketConnectionRFC6455.OP_TEXT;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -820,11 +842,11 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
break;
|
||||
}
|
||||
|
||||
case WebSocketConnectionD13.OP_BINARY:
|
||||
case WebSocketConnectionRFC6455.OP_BINARY:
|
||||
{
|
||||
if (_opcode!=-1)
|
||||
{
|
||||
errorClose(WebSocketConnectionD13.CLOSE_PROTOCOL,"Expected Continuation"+Integer.toHexString(opcode));
|
||||
errorClose(WebSocketConnectionRFC6455.CLOSE_PROTOCOL,"Expected Continuation"+Integer.toHexString(opcode));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -845,28 +867,28 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
else
|
||||
{
|
||||
LOG.warn("Frame discarded. Binary aggregation disabed for {}",_endp);
|
||||
errorClose(WebSocketConnectionD13.CLOSE_POLICY_VIOLATION,"Binary frame aggregation disabled");
|
||||
errorClose(WebSocketConnectionRFC6455.CLOSE_POLICY_VIOLATION,"Binary frame aggregation disabled");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
errorClose(WebSocketConnectionD13.CLOSE_PROTOCOL,"Bad opcode 0x"+Integer.toHexString(opcode));
|
||||
errorClose(WebSocketConnectionRFC6455.CLOSE_PROTOCOL,"Bad opcode 0x"+Integer.toHexString(opcode));
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch(Utf8Appendable.NotUtf8Exception notUtf8)
|
||||
{
|
||||
LOG.warn("{} for {}",notUtf8,_endp);
|
||||
LOG.warn("NOTUTF8 - {} for {}",notUtf8,_endp, notUtf8);
|
||||
LOG.debug(notUtf8);
|
||||
errorClose(WebSocketConnectionD13.CLOSE_BAD_PAYLOAD,"Invalid UTF-8");
|
||||
errorClose(WebSocketConnectionRFC6455.CLOSE_BAD_PAYLOAD,"Invalid UTF-8");
|
||||
}
|
||||
catch(Throwable probablyNotUtf8)
|
||||
catch(Throwable e)
|
||||
{
|
||||
LOG.warn("{} for {}",probablyNotUtf8,_endp);
|
||||
LOG.debug(probablyNotUtf8);
|
||||
errorClose(WebSocketConnectionD13.CLOSE_BAD_PAYLOAD,"Invalid Payload: "+probablyNotUtf8);
|
||||
LOG.warn("{} for {}",e,_endp, e);
|
||||
LOG.debug(e);
|
||||
errorClose(WebSocketConnectionRFC6455.CLOSE_SERVER_ERROR,"Internal Server Error: "+e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -892,7 +914,7 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
if (max>0 && (bufferLen+length)>max)
|
||||
{
|
||||
LOG.warn("Binary message too large > {}B for {}",_connection.getMaxBinaryMessageSize(),_endp);
|
||||
_connection.close(WebSocketConnectionD13.CLOSE_MESSAGE_TOO_LARGE,"Message size > "+_connection.getMaxBinaryMessageSize());
|
||||
_connection.close(WebSocketConnectionRFC6455.CLOSE_MESSAGE_TOO_LARGE,"Message size > "+_connection.getMaxBinaryMessageSize());
|
||||
_opcode=-1;
|
||||
if (_aggregate!=null)
|
||||
_aggregate.clear();
|
||||
|
@ -904,7 +926,7 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
private void textMessageTooLarge()
|
||||
{
|
||||
LOG.warn("Text message too large > {} chars for {}",_connection.getMaxTextMessageSize(),_endp);
|
||||
_connection.close(WebSocketConnectionD13.CLOSE_MESSAGE_TOO_LARGE,"Text message size > "+_connection.getMaxTextMessageSize()+" chars");
|
||||
_connection.close(WebSocketConnectionRFC6455.CLOSE_MESSAGE_TOO_LARGE,"Text message size > "+_connection.getMaxTextMessageSize()+" chars");
|
||||
|
||||
_opcode=-1;
|
||||
_utf8.reset();
|
||||
|
@ -920,7 +942,7 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return WebSocketConnectionD13.this.toString()+"FH";
|
||||
return WebSocketConnectionRFC6455.this.toString()+"FH";
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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.
|
||||
*******************************************************************************/
|
||||
// ========================================================================
|
||||
// Copyright (c) 2010 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -20,6 +35,7 @@ import java.util.Enumeration;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
|
@ -192,8 +208,10 @@ public class WebSocketFactory
|
|||
throw new IllegalStateException("!HTTP/1.1");
|
||||
|
||||
int draft = request.getIntHeader("Sec-WebSocket-Version");
|
||||
if (draft < 0)
|
||||
if (draft < 0) {
|
||||
// Old pre-RFC version specifications (header not present in RFC-6455)
|
||||
draft = request.getIntHeader("Sec-WebSocket-Draft");
|
||||
}
|
||||
AbstractHttpConnection http = AbstractHttpConnection.getCurrentConnection();
|
||||
if (http instanceof BlockingHttpConnection)
|
||||
throw new IllegalStateException("Websockets not supported on blocking connectors");
|
||||
|
@ -215,8 +233,8 @@ public class WebSocketFactory
|
|||
final List<Extension> extensions;
|
||||
switch (draft)
|
||||
{
|
||||
case -1:
|
||||
case 0:
|
||||
case -1: // unspecified draft/version
|
||||
case 0: // Old school draft/version
|
||||
extensions=Collections.emptyList();
|
||||
connection = new WebSocketServletConnectionD00(websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol);
|
||||
break;
|
||||
|
@ -234,14 +252,16 @@ public class WebSocketFactory
|
|||
extensions= initExtensions(extensions_requested,8-WebSocketConnectionD08.OP_EXT_DATA, 16-WebSocketConnectionD08.OP_EXT_CTRL,3);
|
||||
connection = new WebSocketServletConnectionD08(websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol,extensions,draft);
|
||||
break;
|
||||
case 13:
|
||||
extensions= initExtensions(extensions_requested,8-WebSocketConnectionD13.OP_EXT_DATA, 16-WebSocketConnectionD13.OP_EXT_CTRL,3);
|
||||
connection = new WebSocketServletConnectionD13(websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol,extensions,draft);
|
||||
case WebSocketConnectionRFC6455.VERSION: // RFC 6455 Version
|
||||
extensions= initExtensions(extensions_requested,8-WebSocketConnectionRFC6455.OP_EXT_DATA, 16-WebSocketConnectionRFC6455.OP_EXT_CTRL,3);
|
||||
connection = new WebSocketServletConnectionRFC6455(websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol,extensions,draft);
|
||||
break;
|
||||
default:
|
||||
LOG.warn("Unsupported Websocket version: "+draft);
|
||||
response.setHeader("Sec-WebSocket-Version","0,6,8,13");
|
||||
throw new HttpException(400, "Unsupported draft specification: " + draft);
|
||||
// Per RFC 6455 - 4.4 - Supporting Multiple Versions of WebSocket Protocol
|
||||
// Using the examples as outlined
|
||||
response.setHeader("Sec-WebSocket-Version","13, 8, 6, 0");
|
||||
throw new HttpException(400, "Unsupported websocket version specification: " + draft);
|
||||
}
|
||||
|
||||
// Set the defaults
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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.
|
||||
*******************************************************************************/
|
||||
// ========================================================================
|
||||
// Copyright (c) 2010 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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.
|
||||
*******************************************************************************/
|
||||
// ========================================================================
|
||||
// Copyright (c) 2010 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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.
|
||||
*******************************************************************************/
|
||||
// ========================================================================
|
||||
// Copyright (c) 2010 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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.
|
||||
*******************************************************************************/
|
||||
// ========================================================================
|
||||
// Copyright (c) 2010 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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.
|
||||
*******************************************************************************/
|
||||
// ========================================================================
|
||||
// Copyright (c) 2010 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -27,7 +42,7 @@ import org.eclipse.jetty.io.EofException;
|
|||
* threads will call the addMessage methods while other
|
||||
* threads are flushing the generator.
|
||||
*/
|
||||
public class WebSocketGeneratorD13 implements WebSocketGenerator
|
||||
public class WebSocketGeneratorRFC6455 implements WebSocketGenerator
|
||||
{
|
||||
final private WebSocketBuffers _buffers;
|
||||
final private EndPoint _endp;
|
||||
|
@ -38,14 +53,14 @@ public class WebSocketGeneratorD13 implements WebSocketGenerator
|
|||
private final MaskGen _maskGen;
|
||||
private boolean _closed;
|
||||
|
||||
public WebSocketGeneratorD13(WebSocketBuffers buffers, EndPoint endp)
|
||||
public WebSocketGeneratorRFC6455(WebSocketBuffers buffers, EndPoint endp)
|
||||
{
|
||||
_buffers=buffers;
|
||||
_endp=endp;
|
||||
_maskGen=null;
|
||||
}
|
||||
|
||||
public WebSocketGeneratorD13(WebSocketBuffers buffers, EndPoint endp, MaskGen maskGen)
|
||||
public WebSocketGeneratorRFC6455(WebSocketBuffers buffers, EndPoint endp, MaskGen maskGen)
|
||||
{
|
||||
_buffers=buffers;
|
||||
_endp=endp;
|
||||
|
@ -63,7 +78,7 @@ public class WebSocketGeneratorD13 implements WebSocketGenerator
|
|||
|
||||
if (_closed)
|
||||
throw new EofException("Closed");
|
||||
if (opcode==WebSocketConnectionD13.OP_CLOSE)
|
||||
if (opcode==WebSocketConnectionRFC6455.OP_CLOSE)
|
||||
_closed=true;
|
||||
|
||||
boolean mask=_maskGen!=null;
|
||||
|
@ -71,13 +86,13 @@ public class WebSocketGeneratorD13 implements WebSocketGenerator
|
|||
if (_buffer==null)
|
||||
_buffer=mask?_buffers.getBuffer():_buffers.getDirectBuffer();
|
||||
|
||||
boolean last=WebSocketConnectionD13.isLastFrame(flags);
|
||||
boolean last=WebSocketConnectionRFC6455.isLastFrame(flags);
|
||||
|
||||
int space=mask?14:10;
|
||||
|
||||
do
|
||||
{
|
||||
opcode = _opsent?WebSocketConnectionD13.OP_CONTINUATION:opcode;
|
||||
opcode = _opsent?WebSocketConnectionRFC6455.OP_CONTINUATION:opcode;
|
||||
opcode=(byte)(((0xf&flags)<<4)+(0xf&opcode));
|
||||
_opsent=true;
|
||||
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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.
|
||||
*******************************************************************************/
|
||||
// ========================================================================
|
||||
// Copyright (c) 2010 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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.
|
||||
*******************************************************************************/
|
||||
// ========================================================================
|
||||
// Copyright (c) 2010 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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.
|
||||
*******************************************************************************/
|
||||
// ========================================================================
|
||||
// Copyright (c) 2010 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -18,6 +33,7 @@ import java.io.IOException;
|
|||
import org.eclipse.jetty.io.Buffer;
|
||||
import org.eclipse.jetty.io.Buffers;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.util.TypeUtil;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
|
@ -86,7 +102,7 @@ public class WebSocketParserD00 implements WebSocketParser
|
|||
if (_buffer==null)
|
||||
_buffer=_buffers.getBuffer();
|
||||
|
||||
int total_filled=0;
|
||||
int progress=0;
|
||||
|
||||
// Loop until an datagram call back or can't fill anymore
|
||||
while(true)
|
||||
|
@ -108,14 +124,14 @@ public class WebSocketParserD00 implements WebSocketParser
|
|||
{
|
||||
int filled=_endp.isOpen()?_endp.fill(_buffer):-1;
|
||||
if (filled<=0)
|
||||
return total_filled;
|
||||
total_filled+=filled;
|
||||
return progress;
|
||||
progress+=filled;
|
||||
length=_buffer.length();
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
LOG.debug(e);
|
||||
return total_filled>0?total_filled:-1;
|
||||
return progress>0?progress:-1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -147,6 +163,7 @@ public class WebSocketParserD00 implements WebSocketParser
|
|||
{
|
||||
_state=STATE_START;
|
||||
int l=_buffer.getIndex()-_buffer.markIndex()-1;
|
||||
progress++;
|
||||
_handler.onFrame((byte)0,_opcode,_buffer.sliceFromMark(l));
|
||||
_buffer.setMarkIndex(-1);
|
||||
if (_buffer.length()==0)
|
||||
|
@ -154,7 +171,7 @@ public class WebSocketParserD00 implements WebSocketParser
|
|||
_buffers.returnBuffer(_buffer);
|
||||
_buffer=null;
|
||||
}
|
||||
return total_filled;
|
||||
return progress;
|
||||
}
|
||||
continue;
|
||||
|
||||
|
@ -175,6 +192,7 @@ public class WebSocketParserD00 implements WebSocketParser
|
|||
Buffer data=_buffer.sliceFromMark(_length);
|
||||
_buffer.skip(_length);
|
||||
_state=STATE_START;
|
||||
progress++;
|
||||
_handler.onFrame((byte)0, _opcode, data);
|
||||
|
||||
if (_buffer.length()==0)
|
||||
|
@ -183,7 +201,7 @@ public class WebSocketParserD00 implements WebSocketParser
|
|||
_buffer=null;
|
||||
}
|
||||
|
||||
return total_filled;
|
||||
return progress;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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.
|
||||
*******************************************************************************/
|
||||
// ========================================================================
|
||||
// Copyright (c) 2010 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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.
|
||||
*******************************************************************************/
|
||||
// ========================================================================
|
||||
// Copyright (c) 2010 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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.
|
||||
*******************************************************************************/
|
||||
// ========================================================================
|
||||
// Copyright (c) 2010 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -161,9 +176,9 @@ public class WebSocketParserD13 implements WebSocketParser
|
|||
// System.err.printf("%s %s %s >>\n",TypeUtil.toHexString(_flags),TypeUtil.toHexString(_opcode),data.length());
|
||||
_bytesNeeded-=data.length();
|
||||
progress=true;
|
||||
_handler.onFrame((byte)(_flags&(0xff^WebSocketConnectionD13.FLAG_FIN)), _opcode, data);
|
||||
_handler.onFrame((byte)(_flags&(0xff^WebSocketConnectionRFC6455.FLAG_FIN)), _opcode, data);
|
||||
|
||||
_opcode=WebSocketConnectionD13.OP_CONTINUATION;
|
||||
_opcode=WebSocketConnectionRFC6455.OP_CONTINUATION;
|
||||
}
|
||||
|
||||
if (_buffer.space() == 0)
|
||||
|
@ -199,7 +214,7 @@ public class WebSocketParserD13 implements WebSocketParser
|
|||
{
|
||||
case START:
|
||||
_skip=false;
|
||||
_state=_opcode==WebSocketConnectionD13.OP_CLOSE?State.SEEK_EOF:State.OPCODE;
|
||||
_state=_opcode==WebSocketConnectionRFC6455.OP_CLOSE?State.SEEK_EOF:State.OPCODE;
|
||||
_bytesNeeded=_state.getNeeds();
|
||||
continue;
|
||||
|
||||
|
@ -209,10 +224,10 @@ public class WebSocketParserD13 implements WebSocketParser
|
|||
_opcode=(byte)(b&0xf);
|
||||
_flags=(byte)(0xf&(b>>4));
|
||||
|
||||
if (WebSocketConnectionD13.isControlFrame(_opcode)&&!WebSocketConnectionD13.isLastFrame(_flags))
|
||||
if (WebSocketConnectionRFC6455.isControlFrame(_opcode)&&!WebSocketConnectionRFC6455.isLastFrame(_flags))
|
||||
{
|
||||
LOG.warn("Fragmented Control from "+_endp);
|
||||
_handler.close(WebSocketConnectionD13.CLOSE_PROTOCOL,"Fragmented control");
|
||||
_handler.close(WebSocketConnectionRFC6455.CLOSE_PROTOCOL,"Fragmented control");
|
||||
progress=true;
|
||||
_skip=true;
|
||||
}
|
||||
|
@ -254,7 +269,7 @@ public class WebSocketParserD13 implements WebSocketParser
|
|||
if (_length>_buffer.capacity() && !_fragmentFrames)
|
||||
{
|
||||
progress=true;
|
||||
_handler.close(WebSocketConnectionD13.CLOSE_POLICY_VIOLATION,"frame size "+_length+">"+_buffer.capacity());
|
||||
_handler.close(WebSocketConnectionRFC6455.CLOSE_POLICY_VIOLATION,"frame size "+_length+">"+_buffer.capacity());
|
||||
_skip=true;
|
||||
}
|
||||
|
||||
|
@ -273,7 +288,7 @@ public class WebSocketParserD13 implements WebSocketParser
|
|||
if (_length>=_buffer.capacity() && !_fragmentFrames)
|
||||
{
|
||||
progress=true;
|
||||
_handler.close(WebSocketConnectionD13.CLOSE_POLICY_VIOLATION,"frame size "+_length+">"+_buffer.capacity());
|
||||
_handler.close(WebSocketConnectionRFC6455.CLOSE_POLICY_VIOLATION,"frame size "+_length+">"+_buffer.capacity());
|
||||
_skip=true;
|
||||
}
|
||||
|
||||
|
@ -323,7 +338,7 @@ public class WebSocketParserD13 implements WebSocketParser
|
|||
_buffer.skip(_bytesNeeded);
|
||||
_state=State.START;
|
||||
progress=true;
|
||||
_handler.close(WebSocketConnectionD13.CLOSE_PROTOCOL,"Not masked");
|
||||
_handler.close(WebSocketConnectionRFC6455.CLOSE_PROTOCOL,"Not masked");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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.
|
||||
*******************************************************************************/
|
||||
// ========================================================================
|
||||
// Copyright (c) 2010 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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;
|
||||
|
||||
import java.io.IOException;
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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;
|
||||
|
||||
import java.io.IOException;
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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;
|
||||
|
||||
import java.io.IOException;
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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;
|
||||
|
||||
import java.io.IOException;
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -7,15 +22,15 @@ import javax.servlet.http.HttpServletResponse;
|
|||
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
|
||||
public class WebSocketServletConnectionD13 extends WebSocketConnectionD13 implements WebSocketServletConnection
|
||||
public class WebSocketServletConnectionRFC6455 extends WebSocketConnectionRFC6455 implements WebSocketServletConnection
|
||||
{
|
||||
public WebSocketServletConnectionD13(WebSocket websocket, EndPoint endpoint, WebSocketBuffers buffers, long timestamp, int maxIdleTime, String protocol,
|
||||
public WebSocketServletConnectionRFC6455(WebSocket websocket, EndPoint endpoint, WebSocketBuffers buffers, long timestamp, int maxIdleTime, String protocol,
|
||||
List<Extension> extensions, int draft, MaskGen maskgen) throws IOException
|
||||
{
|
||||
super(websocket,endpoint,buffers,timestamp,maxIdleTime,protocol,extensions,draft,maskgen);
|
||||
}
|
||||
|
||||
public WebSocketServletConnectionD13(WebSocket websocket, EndPoint endpoint, WebSocketBuffers buffers, long timestamp, int maxIdleTime, String protocol,
|
||||
public WebSocketServletConnectionRFC6455(WebSocket websocket, EndPoint endpoint, WebSocketBuffers buffers, long timestamp, int maxIdleTime, String protocol,
|
||||
List<Extension> extensions, int draft) throws IOException
|
||||
{
|
||||
super(websocket,endpoint,buffers,timestamp,maxIdleTime,protocol,extensions,draft);
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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;
|
||||
|
||||
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
@ -30,8 +45,8 @@ public class SafariWebsocketDraft0Test
|
|||
public static void initLogging()
|
||||
{
|
||||
// Configure Logging
|
||||
System.setProperty("org.eclipse.jetty.util.log.class",StdErrLog.class.getName());
|
||||
System.setProperty("org.eclipse.jetty.LEVEL","DEBUG");
|
||||
// System.setProperty("org.eclipse.jetty.util.log.class",StdErrLog.class.getName());
|
||||
// System.setProperty("org.eclipse.jetty.LEVEL","DEBUG");
|
||||
}
|
||||
|
||||
@Before
|
||||
|
@ -59,11 +74,10 @@ public class SafariWebsocketDraft0Test
|
|||
}
|
||||
int port = conn.getLocalPort();
|
||||
serverUri = new URI(String.format("ws://%s:%d/",host,port));
|
||||
System.out.printf("Server URI: %s%n",serverUri);
|
||||
// System.out.printf("Server URI: %s%n",serverUri);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testSendTextMessages() throws Exception
|
||||
{
|
||||
SafariD00 safari = new SafariD00(serverUri);
|
||||
|
@ -91,7 +105,7 @@ public class SafariWebsocketDraft0Test
|
|||
}
|
||||
finally
|
||||
{
|
||||
System.out.println("Closing client socket");
|
||||
// System.out.println("Closing client socket");
|
||||
safari.disconnect();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
|
@ -15,8 +30,6 @@ import org.eclipse.jetty.util.StringUtil;
|
|||
import org.eclipse.jetty.util.TypeUtil;
|
||||
|
||||
/**
|
||||
* @version $Revision$ $Date$
|
||||
*
|
||||
* This is not a general purpose websocket client.
|
||||
* It's only for testing the websocket server and is hardwired to a specific draft version of the protocol.
|
||||
*/
|
||||
|
@ -140,7 +153,7 @@ public class TestClient implements WebSocket.OnFrame
|
|||
{
|
||||
__framesSent++;
|
||||
byte flags= (byte)(off+len==data.length?0x8:0);
|
||||
byte op=(byte)(off==0?opcode:WebSocketConnectionD13.OP_CONTINUATION);
|
||||
byte op=(byte)(off==0?opcode:WebSocketConnectionRFC6455.OP_CONTINUATION);
|
||||
|
||||
if (_verbose)
|
||||
System.err.printf("%s#sendFrame %s|%s %s\n",this.getClass().getSimpleName(),TypeUtil.toHexString(flags),TypeUtil.toHexString(op),TypeUtil.toHexString(data,off,len));
|
||||
|
@ -158,7 +171,9 @@ public class TestClient implements WebSocket.OnFrame
|
|||
public void disconnect() throws Exception
|
||||
{
|
||||
if (_connection!=null)
|
||||
_connection.disconnect();
|
||||
{
|
||||
_connection.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -245,11 +260,11 @@ public class TestClient implements WebSocket.OnFrame
|
|||
{
|
||||
long next = System.currentTimeMillis()+delay;
|
||||
|
||||
byte opcode=binary?WebSocketConnectionD13.OP_BINARY:WebSocketConnectionD13.OP_TEXT;
|
||||
byte opcode=binary?WebSocketConnectionRFC6455.OP_BINARY:WebSocketConnectionRFC6455.OP_TEXT;
|
||||
|
||||
byte data[]=null;
|
||||
|
||||
if (opcode==WebSocketConnectionD13.OP_TEXT)
|
||||
if (opcode==WebSocketConnectionRFC6455.OP_TEXT)
|
||||
{
|
||||
StringBuilder b = new StringBuilder();
|
||||
while (b.length()<size)
|
||||
|
@ -263,7 +278,7 @@ public class TestClient implements WebSocket.OnFrame
|
|||
}
|
||||
|
||||
for (int i=0;i<clients;i++)
|
||||
client[i].ping(opcode,data,opcode==WebSocketConnectionD13.OP_PING?-1:fragment);
|
||||
client[i].ping(opcode,data,opcode==WebSocketConnectionRFC6455.OP_PING?-1:fragment);
|
||||
|
||||
while(System.currentTimeMillis()<next)
|
||||
Thread.sleep(10);
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -207,7 +222,7 @@ public class TestServer extends Server
|
|||
{
|
||||
System.err.println("Ping "+connection);
|
||||
byte[] data = { (byte)1, (byte) 2, (byte) 3 };
|
||||
connection.sendControl(WebSocketConnectionD13.OP_PING,data,0,data.length);
|
||||
connection.sendControl(WebSocketConnectionRFC6455.OP_PING,data,0,data.length);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
|
@ -223,7 +238,7 @@ public class TestServer extends Server
|
|||
@Override
|
||||
public boolean onControl(byte controlCode, byte[] data, int offset, int length)
|
||||
{
|
||||
if (controlCode==WebSocketConnectionD13.OP_PONG)
|
||||
if (controlCode==WebSocketConnectionRFC6455.OP_PONG)
|
||||
System.err.println("Pong "+getConnection());
|
||||
return super.onControl(controlCode,data,offset,length);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,21 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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;
|
||||
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
|
@ -8,6 +23,7 @@ import java.io.InputStream;
|
|||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.ConnectException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.URI;
|
||||
|
@ -133,7 +149,6 @@ public class WebSocketClientTest
|
|||
Assert.assertFalse(open.get());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testAsyncConnectionRefused() throws Exception
|
||||
{
|
||||
|
@ -167,13 +182,11 @@ public class WebSocketClientTest
|
|||
}
|
||||
|
||||
Assert.assertFalse(open.get());
|
||||
Assert.assertEquals(WebSocketConnectionD13.CLOSE_NO_CLOSE,close.get());
|
||||
Assert.assertEquals(WebSocketConnectionRFC6455.CLOSE_NO_CLOSE,close.get());
|
||||
Assert.assertTrue(error instanceof ConnectException);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testConnectionNotAccepted() throws Exception
|
||||
{
|
||||
|
@ -207,7 +220,7 @@ public class WebSocketClientTest
|
|||
}
|
||||
|
||||
Assert.assertFalse(open.get());
|
||||
Assert.assertEquals(WebSocketConnectionD13.CLOSE_NO_CLOSE,close.get());
|
||||
Assert.assertEquals(WebSocketConnectionRFC6455.CLOSE_NO_CLOSE,close.get());
|
||||
Assert.assertTrue(error instanceof TimeoutException);
|
||||
|
||||
}
|
||||
|
@ -246,12 +259,11 @@ public class WebSocketClientTest
|
|||
}
|
||||
|
||||
Assert.assertFalse(open.get());
|
||||
Assert.assertEquals(WebSocketConnectionD13.CLOSE_NO_CLOSE,close.get());
|
||||
Assert.assertEquals(WebSocketConnectionRFC6455.CLOSE_NO_CLOSE,close.get());
|
||||
Assert.assertTrue(error instanceof TimeoutException);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testBadHandshake() throws Exception
|
||||
{
|
||||
|
@ -287,7 +299,7 @@ public class WebSocketClientTest
|
|||
}
|
||||
|
||||
Assert.assertFalse(open.get());
|
||||
Assert.assertEquals(WebSocketConnectionD13.CLOSE_PROTOCOL,close.get());
|
||||
Assert.assertEquals(WebSocketConnectionRFC6455.CLOSE_PROTOCOL,close.get());
|
||||
Assert.assertTrue(error instanceof IOException);
|
||||
Assert.assertTrue(error.getMessage().indexOf("404 NOT FOUND")>0);
|
||||
|
||||
|
@ -330,7 +342,7 @@ public class WebSocketClientTest
|
|||
error=e.getCause();
|
||||
}
|
||||
Assert.assertFalse(open.get());
|
||||
Assert.assertEquals(WebSocketConnectionD13.CLOSE_PROTOCOL,close.get());
|
||||
Assert.assertEquals(WebSocketConnectionRFC6455.CLOSE_PROTOCOL,close.get());
|
||||
Assert.assertTrue(error instanceof IOException);
|
||||
Assert.assertTrue(error.getMessage().indexOf("Bad Sec-WebSocket-Accept")>=0);
|
||||
}
|
||||
|
@ -368,7 +380,7 @@ public class WebSocketClientTest
|
|||
socket.close();
|
||||
_latch.await(10,TimeUnit.SECONDS);
|
||||
|
||||
Assert.assertEquals(WebSocketConnectionD13.CLOSE_NO_CLOSE,close.get());
|
||||
Assert.assertEquals(WebSocketConnectionRFC6455.CLOSE_NO_CLOSE,close.get());
|
||||
|
||||
}
|
||||
|
||||
|
@ -406,10 +418,9 @@ public class WebSocketClientTest
|
|||
long start=System.currentTimeMillis();
|
||||
_latch.await(10,TimeUnit.SECONDS);
|
||||
Assert.assertTrue(System.currentTimeMillis()-start<5000);
|
||||
Assert.assertEquals(WebSocketConnectionD13.CLOSE_NORMAL,close.get());
|
||||
Assert.assertEquals(WebSocketConnectionRFC6455.CLOSE_NORMAL,close.get());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testNotIdle() throws Exception
|
||||
{
|
||||
|
@ -484,7 +495,6 @@ public class WebSocketClientTest
|
|||
Assert.assertEquals("Invalid close code 1111", closeMessage.toString());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testBlockSending() throws Exception
|
||||
{
|
||||
|
@ -566,18 +576,17 @@ public class WebSocketClientTest
|
|||
long writeDur = (System.currentTimeMillis() - start);
|
||||
|
||||
// wait for consumer to complete
|
||||
while (totalB.get()<messages*(mesg.length()+6L))
|
||||
while (totalB.get()<messages*(mesg.length()+6L))
|
||||
{
|
||||
Thread.sleep(10);
|
||||
}
|
||||
|
||||
|
||||
Assert.assertThat("write duration", writeDur, greaterThan(1000L)); // writing was blocked
|
||||
Assert.assertEquals(messages*(mesg.length()+6L),totalB.get());
|
||||
|
||||
consumer.interrupt();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testBlockReceiving() throws Exception
|
||||
{
|
||||
|
@ -677,12 +686,12 @@ public class WebSocketClientTest
|
|||
socket.getOutputStream().write(send,0,send.length);
|
||||
socket.getOutputStream().flush();
|
||||
}
|
||||
|
||||
while(consumer.isAlive())
|
||||
|
||||
while(consumer.isAlive())
|
||||
{
|
||||
Thread.sleep(10);
|
||||
}
|
||||
|
||||
|
||||
// Duration of the read operation.
|
||||
long readDur = (System.currentTimeMillis() - start);
|
||||
|
||||
|
@ -700,6 +709,24 @@ public class WebSocketClientTest
|
|||
Assert.assertEquals("Invalid close code 1111", closeMessage.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testURIWithDefaultPort() throws Exception
|
||||
{
|
||||
URI uri = new URI("ws://localhost");
|
||||
InetSocketAddress addr = WebSocketClient.toSocketAddress(uri);
|
||||
Assert.assertThat("URI (" + uri + ").host", addr.getHostName(), is("localhost"));
|
||||
Assert.assertThat("URI (" + uri + ").port", addr.getPort(), is(80));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testURIWithDefaultWSSPort() throws Exception
|
||||
{
|
||||
URI uri = new URI("wss://localhost");
|
||||
InetSocketAddress addr = WebSocketClient.toSocketAddress(uri);
|
||||
Assert.assertThat("URI (" + uri + ").host", addr.getHostName(), is("localhost"));
|
||||
Assert.assertThat("URI (" + uri + ").port", addr.getPort(), is(443));
|
||||
}
|
||||
|
||||
private void respondToClient(Socket connection, String serverResponse) throws IOException
|
||||
{
|
||||
InputStream in = null;
|
||||
|
@ -748,7 +775,7 @@ public class WebSocketClientTest
|
|||
}
|
||||
connection.getOutputStream().write((
|
||||
"HTTP/1.1 101 Upgrade\r\n" +
|
||||
"Sec-WebSocket-Accept: "+ WebSocketConnectionD13.hashKey(key) +"\r\n" +
|
||||
"Sec-WebSocket-Accept: "+ WebSocketConnectionRFC6455.hashKey(key) +"\r\n" +
|
||||
"\r\n").getBytes());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
@ -9,13 +24,12 @@ import org.eclipse.jetty.server.Connector;
|
|||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.eclipse.jetty.util.log.StdErrLog;
|
||||
import org.eclipse.jetty.websocket.helper.CaptureSocket;
|
||||
import org.eclipse.jetty.websocket.helper.MessageSender;
|
||||
import org.eclipse.jetty.websocket.helper.WebSocketCaptureServlet;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
|
@ -28,14 +42,6 @@ public class WebSocketCommTest
|
|||
private WebSocketCaptureServlet servlet;
|
||||
private URI serverUri;
|
||||
|
||||
@BeforeClass
|
||||
public static void initLogging()
|
||||
{
|
||||
// Configure Logging
|
||||
System.setProperty("org.eclipse.jetty.util.log.class",StdErrLog.class.getName());
|
||||
System.setProperty("org.eclipse.jetty.LEVEL","DEBUG");
|
||||
}
|
||||
|
||||
@Before
|
||||
public void startServer() throws Exception
|
||||
{
|
||||
|
@ -64,6 +70,19 @@ public class WebSocketCommTest
|
|||
System.out.printf("Server URI: %s%n",serverUri);
|
||||
}
|
||||
|
||||
@After
|
||||
public void stopServer()
|
||||
{
|
||||
try
|
||||
{
|
||||
server.stop();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace(System.err);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendTextMessages() throws Exception
|
||||
{
|
||||
|
@ -90,10 +109,11 @@ public class WebSocketCommTest
|
|||
|
||||
CaptureSocket socket = servlet.captures.get(0);
|
||||
Assert.assertThat("CaptureSocket",socket,notNullValue());
|
||||
Assert.assertThat("CaptureSocket.isConnected", socket.isConnected(), is(true));
|
||||
Assert.assertThat("CaptureSocket.isConnected",socket.isConnected(),is(true));
|
||||
|
||||
// Give servlet 500 millisecond to process messages
|
||||
threadSleep(500,TimeUnit.MILLISECONDS);
|
||||
TimeUnit.MILLISECONDS.sleep(500);
|
||||
|
||||
// Should have captured 5 messages.
|
||||
Assert.assertThat("CaptureSocket.messages.size",socket.messages.size(),is(5));
|
||||
}
|
||||
|
@ -103,10 +123,4 @@ public class WebSocketCommTest
|
|||
sender.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static void threadSleep(int dur, TimeUnit unit) throws InterruptedException
|
||||
{
|
||||
long ms = TimeUnit.MILLISECONDS.convert(dur,unit);
|
||||
Thread.sleep(ms);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,21 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.*;
|
||||
|
||||
import org.eclipse.jetty.io.ByteArrayBuffer;
|
||||
import org.eclipse.jetty.io.ByteArrayEndPoint;
|
||||
|
@ -8,9 +23,6 @@ import org.eclipse.jetty.util.StringUtil;
|
|||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
public class WebSocketGeneratorD00Test
|
||||
{
|
||||
private ByteArrayBuffer _out;
|
||||
|
|
|
@ -1,6 +1,21 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.*;
|
||||
|
||||
import org.eclipse.jetty.io.ByteArrayBuffer;
|
||||
import org.eclipse.jetty.io.ByteArrayEndPoint;
|
||||
|
@ -8,9 +23,6 @@ import org.eclipse.jetty.util.StringUtil;
|
|||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
public class WebSocketGeneratorD06Test
|
||||
{
|
||||
private ByteArrayBuffer _out;
|
||||
|
|
|
@ -1,6 +1,21 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.*;
|
||||
|
||||
import org.eclipse.jetty.io.ByteArrayBuffer;
|
||||
import org.eclipse.jetty.io.ByteArrayEndPoint;
|
||||
|
@ -8,9 +23,6 @@ import org.eclipse.jetty.util.StringUtil;
|
|||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
public class WebSocketGeneratorD08Test
|
||||
{
|
||||
private ByteArrayBuffer _out;
|
||||
|
|
|
@ -1,7 +1,21 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
import static junit.framework.Assert.*;
|
||||
|
||||
import org.eclipse.jetty.io.ByteArrayBuffer;
|
||||
import org.eclipse.jetty.io.ByteArrayEndPoint;
|
||||
|
@ -11,9 +25,8 @@ import org.junit.Before;
|
|||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
public class WebSocketGeneratorD13Test
|
||||
public class WebSocketGeneratorRFC6455Test
|
||||
{
|
||||
private ByteArrayBuffer _out;
|
||||
private WebSocketGenerator _generator;
|
||||
|
@ -44,7 +57,7 @@ public class WebSocketGeneratorD13Test
|
|||
@Test
|
||||
public void testOneString() throws Exception
|
||||
{
|
||||
_generator = new WebSocketGeneratorD13(_buffers, _endPoint,null);
|
||||
_generator = new WebSocketGeneratorRFC6455(_buffers, _endPoint,null);
|
||||
|
||||
byte[] data = "Hell\uFF4F W\uFF4Frld".getBytes(StringUtil.__UTF8);
|
||||
_generator.addFrame((byte)0x8,(byte)0x04,data,0,data.length);
|
||||
|
@ -71,7 +84,7 @@ public class WebSocketGeneratorD13Test
|
|||
@Test
|
||||
public void testOneBuffer() throws Exception
|
||||
{
|
||||
_generator = new WebSocketGeneratorD13(_buffers, _endPoint,null);
|
||||
_generator = new WebSocketGeneratorRFC6455(_buffers, _endPoint,null);
|
||||
|
||||
String string = "Hell\uFF4F W\uFF4Frld";
|
||||
byte[] bytes=string.getBytes(StringUtil.__UTF8);
|
||||
|
@ -99,7 +112,7 @@ public class WebSocketGeneratorD13Test
|
|||
@Test
|
||||
public void testOneLongBuffer() throws Exception
|
||||
{
|
||||
_generator = new WebSocketGeneratorD13(_buffers, _endPoint,null);
|
||||
_generator = new WebSocketGeneratorRFC6455(_buffers, _endPoint,null);
|
||||
|
||||
byte[] b=new byte[150];
|
||||
for (int i=0;i<b.length;i++)
|
||||
|
@ -120,7 +133,7 @@ public class WebSocketGeneratorD13Test
|
|||
@Test
|
||||
public void testOneStringMasked() throws Exception
|
||||
{
|
||||
_generator = new WebSocketGeneratorD13(_buffers, _endPoint,_maskGen);
|
||||
_generator = new WebSocketGeneratorRFC6455(_buffers, _endPoint,_maskGen);
|
||||
|
||||
byte[] data = "Hell\uFF4F W\uFF4Frld".getBytes(StringUtil.__UTF8);
|
||||
_generator.addFrame((byte)0x8,(byte)0x04,data,0,data.length);
|
||||
|
@ -149,7 +162,7 @@ public class WebSocketGeneratorD13Test
|
|||
@Test
|
||||
public void testOneBufferMasked() throws Exception
|
||||
{
|
||||
_generator = new WebSocketGeneratorD13(_buffers, _endPoint,_maskGen);
|
||||
_generator = new WebSocketGeneratorRFC6455(_buffers, _endPoint,_maskGen);
|
||||
|
||||
String string = "Hell\uFF4F W\uFF4Frld";
|
||||
byte[] bytes=string.getBytes(StringUtil.__UTF8);
|
||||
|
@ -179,7 +192,7 @@ public class WebSocketGeneratorD13Test
|
|||
@Test
|
||||
public void testOneLongBufferMasked() throws Exception
|
||||
{
|
||||
_generator = new WebSocketGeneratorD13(_buffers, _endPoint,_maskGen);
|
||||
_generator = new WebSocketGeneratorRFC6455(_buffers, _endPoint,_maskGen);
|
||||
|
||||
byte[] b=new byte[150];
|
||||
for (int i=0;i<b.length;i++)
|
||||
|
@ -203,7 +216,7 @@ public class WebSocketGeneratorD13Test
|
|||
@Test
|
||||
public void testClose() throws Exception
|
||||
{
|
||||
_generator = new WebSocketGeneratorD13(_buffers, _endPoint,null);
|
||||
_generator = new WebSocketGeneratorRFC6455(_buffers, _endPoint,null);
|
||||
|
||||
byte[] data = "xxGame Over".getBytes(StringUtil.__UTF8);
|
||||
data[0]=(byte)(1000/0x100);
|
|
@ -1,6 +1,21 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
|
@ -30,9 +45,6 @@ import org.junit.AfterClass;
|
|||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
public class WebSocketLoadD08Test
|
||||
{
|
||||
private static Server _server;
|
||||
|
|
|
@ -1,6 +1,21 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
|
@ -30,9 +45,6 @@ import org.junit.AfterClass;
|
|||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
public class WebSocketLoadD13Test
|
||||
{
|
||||
private static Server _server;
|
||||
|
@ -142,7 +154,7 @@ public class WebSocketLoadD13Test
|
|||
private final int iterations;
|
||||
private final CountDownLatch latch;
|
||||
private final SocketEndPoint _endp;
|
||||
private final WebSocketGeneratorD13 _generator;
|
||||
private final WebSocketGeneratorRFC6455 _generator;
|
||||
private final WebSocketParserD13 _parser;
|
||||
private final WebSocketParser.FrameHandler _handler = new WebSocketParser.FrameHandler()
|
||||
{
|
||||
|
@ -167,7 +179,7 @@ public class WebSocketLoadD13Test
|
|||
this.iterations = iterations;
|
||||
|
||||
_endp=new SocketEndPoint(socket);
|
||||
_generator = new WebSocketGeneratorD13(new WebSocketBuffers(32*1024),_endp,new FixedMaskGen());
|
||||
_generator = new WebSocketGeneratorRFC6455(new WebSocketBuffers(32*1024),_endp,new FixedMaskGen());
|
||||
_parser = new WebSocketParserD13(new WebSocketBuffers(32*1024),_endp,_handler,false);
|
||||
|
||||
}
|
||||
|
@ -202,7 +214,7 @@ public class WebSocketLoadD13Test
|
|||
for (int i = 0; i < iterations; ++i)
|
||||
{
|
||||
byte[] data = message.getBytes(StringUtil.__UTF8);
|
||||
_generator.addFrame((byte)0x8,WebSocketConnectionD13.OP_TEXT,data,0,data.length);
|
||||
_generator.addFrame((byte)0x8,WebSocketConnectionRFC6455.OP_TEXT,data,0,data.length);
|
||||
_generator.flush();
|
||||
|
||||
//System.err.println("-> "+message);
|
||||
|
|
|
@ -1,8 +1,21 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
@ -26,9 +39,6 @@ import org.junit.AfterClass;
|
|||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
public class WebSocketMessageD00Test
|
||||
{
|
||||
private static Server _server;
|
||||
|
|
|
@ -1,8 +1,21 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
|
@ -27,9 +40,6 @@ import org.junit.AfterClass;
|
|||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
public class WebSocketMessageD06Test
|
||||
{
|
||||
private static Server _server;
|
||||
|
|
|
@ -1,8 +1,21 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
|
@ -32,9 +45,6 @@ import org.junit.AfterClass;
|
|||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
public class WebSocketMessageD08Test
|
||||
{
|
||||
private static Server __server;
|
||||
|
@ -461,6 +471,7 @@ public class WebSocketMessageD08Test
|
|||
// unblock the latch in 4s
|
||||
new Thread()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
|
@ -544,6 +555,7 @@ public class WebSocketMessageD08Test
|
|||
final AtomicLong totalB=new AtomicLong();
|
||||
new Thread()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
|
|
|
@ -1,8 +1,21 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
|
@ -32,10 +45,7 @@ import org.junit.AfterClass;
|
|||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
public class WebSocketMessageD13Test
|
||||
public class WebSocketMessageRFC6455Test
|
||||
{
|
||||
private static Server __server;
|
||||
private static Connector __connector;
|
||||
|
@ -82,7 +92,7 @@ public class WebSocketMessageD13Test
|
|||
@Test
|
||||
public void testHash()
|
||||
{
|
||||
assertEquals("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",WebSocketConnectionD13.hashKey("dGhlIHNhbXBsZSBub25jZQ=="));
|
||||
assertEquals("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",WebSocketConnectionRFC6455.hashKey("dGhlIHNhbXBsZSBub25jZQ=="));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -98,7 +108,7 @@ public class WebSocketMessageD13Test
|
|||
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"+
|
||||
"Sec-WebSocket-Origin: http://example.com\r\n"+
|
||||
"Sec-WebSocket-Protocol: chat, superchat\r\n"+
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionD13.VERSION+"\r\n"+
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionRFC6455.VERSION+"\r\n"+
|
||||
"\r\n").getBytes("ISO-8859-1"));
|
||||
output.flush();
|
||||
|
||||
|
@ -123,7 +133,7 @@ public class WebSocketMessageD13Test
|
|||
String data=message.toString();
|
||||
__serverWebSocket.connection.sendMessage(data);
|
||||
|
||||
assertEquals(WebSocketConnectionD13.OP_TEXT,input.read());
|
||||
assertEquals(WebSocketConnectionRFC6455.OP_TEXT,input.read());
|
||||
assertEquals(0x7e,input.read());
|
||||
assertEquals(0x1f,input.read());
|
||||
assertEquals(0xf6,input.read());
|
||||
|
@ -146,7 +156,7 @@ public class WebSocketMessageD13Test
|
|||
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"+
|
||||
"Sec-WebSocket-Origin: http://example.com\r\n"+
|
||||
"Sec-WebSocket-Protocol: onConnect\r\n" +
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionD13.VERSION+"\r\n"+
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionRFC6455.VERSION+"\r\n"+
|
||||
"\r\n").getBytes("ISO-8859-1"));
|
||||
output.flush();
|
||||
|
||||
|
@ -181,7 +191,7 @@ public class WebSocketMessageD13Test
|
|||
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"+
|
||||
"Sec-WebSocket-Origin: http://example.com\r\n"+
|
||||
"Sec-WebSocket-Protocol: onConnect\r\n" +
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionD13.VERSION+"\r\n"+
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionRFC6455.VERSION+"\r\n"+
|
||||
"Sec-WebSocket-Extensions: identity;param=0\r\n"+
|
||||
"Sec-WebSocket-Extensions: identity;param=1, identity ; param = '2' ; other = ' some = value ' \r\n"+
|
||||
"\r\n").getBytes("ISO-8859-1"));
|
||||
|
@ -224,7 +234,7 @@ public class WebSocketMessageD13Test
|
|||
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"+
|
||||
"Sec-WebSocket-Origin: http://example.com\r\n"+
|
||||
"Sec-WebSocket-Protocol: onConnect\r\n" +
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionD13.VERSION+"\r\n"+
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionRFC6455.VERSION+"\r\n"+
|
||||
"Sec-WebSocket-Extensions: fragment;maxLength=4;minFragments=7\r\n"+
|
||||
"\r\n").getBytes("ISO-8859-1"));
|
||||
output.flush();
|
||||
|
@ -278,7 +288,7 @@ public class WebSocketMessageD13Test
|
|||
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"+
|
||||
"Sec-WebSocket-Origin: http://example.com\r\n"+
|
||||
"Sec-WebSocket-Protocol: echo\r\n" +
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionD13.VERSION+"\r\n"+
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionRFC6455.VERSION+"\r\n"+
|
||||
"Sec-WebSocket-Extensions: x-deflate-frame;minLength=64\r\n"+
|
||||
"Sec-WebSocket-Extensions: fragment;minFragments=2\r\n"+
|
||||
"\r\n").getBytes("ISO-8859-1"));
|
||||
|
@ -329,7 +339,7 @@ public class WebSocketMessageD13Test
|
|||
output.write(buf,0,l+3);
|
||||
output.flush();
|
||||
|
||||
assertEquals(0x40+WebSocketConnectionD13.OP_TEXT,input.read());
|
||||
assertEquals(0x40+WebSocketConnectionRFC6455.OP_TEXT,input.read());
|
||||
assertEquals(0x20+3,input.read());
|
||||
assertEquals(0x7e,input.read());
|
||||
assertEquals(0x02,input.read());
|
||||
|
@ -376,7 +386,7 @@ public class WebSocketMessageD13Test
|
|||
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"+
|
||||
"Sec-WebSocket-Origin: http://example.com\r\n"+
|
||||
"Sec-WebSocket-Protocol: echo\r\n" +
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionD13.VERSION+"\r\n"+
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionRFC6455.VERSION+"\r\n"+
|
||||
"\r\n").getBytes("ISO-8859-1"));
|
||||
output.flush();
|
||||
output.write(0x84);
|
||||
|
@ -415,7 +425,7 @@ public class WebSocketMessageD13Test
|
|||
|
||||
byte[] bytes="This is a long message of text that we will send again and again".getBytes(StringUtil.__ISO_8859_1);
|
||||
byte[] mesg=new byte[bytes.length+6];
|
||||
mesg[0]=(byte)(0x80+WebSocketConnectionD13.OP_TEXT);
|
||||
mesg[0]=(byte)(0x80+WebSocketConnectionRFC6455.OP_TEXT);
|
||||
mesg[1]=(byte)(0x80+bytes.length);
|
||||
mesg[2]=(byte)0xff;
|
||||
mesg[3]=(byte)0xff;
|
||||
|
@ -434,7 +444,7 @@ public class WebSocketMessageD13Test
|
|||
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"+
|
||||
"Sec-WebSocket-Origin: http://example.com\r\n"+
|
||||
"Sec-WebSocket-Protocol: latch\r\n" +
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionD13.VERSION+"\r\n"+
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionRFC6455.VERSION+"\r\n"+
|
||||
"\r\n").getBytes("ISO-8859-1"));
|
||||
output.flush();
|
||||
|
||||
|
@ -522,7 +532,7 @@ public class WebSocketMessageD13Test
|
|||
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"+
|
||||
"Sec-WebSocket-Origin: http://example.com\r\n"+
|
||||
"Sec-WebSocket-Protocol: latch\r\n" +
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionD13.VERSION+"\r\n"+
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionRFC6455.VERSION+"\r\n"+
|
||||
"\r\n").getBytes("ISO-8859-1"));
|
||||
output.flush();
|
||||
|
||||
|
@ -610,7 +620,7 @@ public class WebSocketMessageD13Test
|
|||
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"+
|
||||
"Sec-WebSocket-Origin: http://example.com\r\n"+
|
||||
"Sec-WebSocket-Protocol: echo\r\n" +
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionD13.VERSION+"\r\n"+
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionRFC6455.VERSION+"\r\n"+
|
||||
"\r\n").getBytes("ISO-8859-1"));
|
||||
output.flush();
|
||||
output.write(0x89);
|
||||
|
@ -649,7 +659,7 @@ public class WebSocketMessageD13Test
|
|||
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"+
|
||||
"Sec-WebSocket-Origin: http://example.com\r\n"+
|
||||
"Sec-WebSocket-Protocol: other\r\n" +
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionD13.VERSION+"\r\n"+
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionRFC6455.VERSION+"\r\n"+
|
||||
"\r\n").getBytes("ISO-8859-1"));
|
||||
output.flush();
|
||||
|
||||
|
@ -681,10 +691,10 @@ public class WebSocketMessageD13Test
|
|||
output.flush();
|
||||
|
||||
|
||||
assertEquals(0x80|WebSocketConnectionD13.OP_CLOSE,input.read());
|
||||
assertEquals(0x80|WebSocketConnectionRFC6455.OP_CLOSE,input.read());
|
||||
assertEquals(33,input.read());
|
||||
int code=(0xff&input.read())*0x100+(0xff&input.read());
|
||||
assertEquals(WebSocketConnectionD13.CLOSE_MESSAGE_TOO_LARGE,code);
|
||||
assertEquals(WebSocketConnectionRFC6455.CLOSE_MESSAGE_TOO_LARGE,code);
|
||||
lookFor("Text message size > 10240 chars",input);
|
||||
}
|
||||
|
||||
|
@ -701,7 +711,7 @@ public class WebSocketMessageD13Test
|
|||
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"+
|
||||
"Sec-WebSocket-Origin: http://example.com\r\n"+
|
||||
"Sec-WebSocket-Protocol: other\r\n" +
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionD13.VERSION+"\r\n"+
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionRFC6455.VERSION+"\r\n"+
|
||||
"\r\n").getBytes("ISO-8859-1"));
|
||||
output.flush();
|
||||
|
||||
|
@ -739,10 +749,10 @@ public class WebSocketMessageD13Test
|
|||
output.write(bytes[i]^0xff);
|
||||
output.flush();
|
||||
|
||||
assertEquals(0x80|WebSocketConnectionD13.OP_CLOSE,input.read());
|
||||
assertEquals(0x80|WebSocketConnectionRFC6455.OP_CLOSE,input.read());
|
||||
assertEquals(30,input.read());
|
||||
int code=(0xff&input.read())*0x100+(0xff&input.read());
|
||||
assertEquals(WebSocketConnectionD13.CLOSE_MESSAGE_TOO_LARGE,code);
|
||||
assertEquals(WebSocketConnectionRFC6455.CLOSE_MESSAGE_TOO_LARGE,code);
|
||||
lookFor("Text message size > 15 chars",input);
|
||||
}
|
||||
|
||||
|
@ -760,7 +770,7 @@ public class WebSocketMessageD13Test
|
|||
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"+
|
||||
"Sec-WebSocket-Origin: http://example.com\r\n"+
|
||||
"Sec-WebSocket-Protocol: other\r\n" +
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionD13.VERSION+"\r\n"+
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionRFC6455.VERSION+"\r\n"+
|
||||
"\r\n").getBytes("ISO-8859-1"));
|
||||
output.flush();
|
||||
|
||||
|
@ -790,10 +800,10 @@ public class WebSocketMessageD13Test
|
|||
|
||||
|
||||
|
||||
assertEquals(0x80|WebSocketConnectionD13.OP_CLOSE,input.read());
|
||||
assertEquals(0x80|WebSocketConnectionRFC6455.OP_CLOSE,input.read());
|
||||
assertEquals(30,input.read());
|
||||
int code=(0xff&input.read())*0x100+(0xff&input.read());
|
||||
assertEquals(WebSocketConnectionD13.CLOSE_MESSAGE_TOO_LARGE,code);
|
||||
assertEquals(WebSocketConnectionRFC6455.CLOSE_MESSAGE_TOO_LARGE,code);
|
||||
lookFor("Text message size > 15 chars",input);
|
||||
}
|
||||
|
||||
|
@ -810,7 +820,7 @@ public class WebSocketMessageD13Test
|
|||
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"+
|
||||
"Sec-WebSocket-Origin: http://example.com\r\n"+
|
||||
"Sec-WebSocket-Protocol: aggregate\r\n" +
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionD13.VERSION+"\r\n"+
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionRFC6455.VERSION+"\r\n"+
|
||||
"\r\n").getBytes("ISO-8859-1"));
|
||||
output.flush();
|
||||
|
||||
|
@ -826,7 +836,7 @@ public class WebSocketMessageD13Test
|
|||
assertNotNull(__serverWebSocket.connection);
|
||||
__serverWebSocket.getConnection().setMaxBinaryMessageSize(1024);
|
||||
|
||||
output.write(WebSocketConnectionD13.OP_BINARY);
|
||||
output.write(WebSocketConnectionRFC6455.OP_BINARY);
|
||||
output.write(0x8a);
|
||||
output.write(0xff);
|
||||
output.write(0xff);
|
||||
|
@ -847,7 +857,7 @@ public class WebSocketMessageD13Test
|
|||
output.write(bytes[i]^0xff);
|
||||
output.flush();
|
||||
|
||||
assertEquals(0x80+WebSocketConnectionD13.OP_BINARY,input.read());
|
||||
assertEquals(0x80+WebSocketConnectionRFC6455.OP_BINARY,input.read());
|
||||
assertEquals(20,input.read());
|
||||
lookFor("01234567890123456789",input);
|
||||
}
|
||||
|
@ -865,7 +875,7 @@ public class WebSocketMessageD13Test
|
|||
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"+
|
||||
"Sec-WebSocket-Origin: http://example.com\r\n"+
|
||||
"Sec-WebSocket-Protocol: other\r\n" +
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionD13.VERSION+"\r\n"+
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionRFC6455.VERSION+"\r\n"+
|
||||
"\r\n").getBytes("ISO-8859-1"));
|
||||
output.flush();
|
||||
|
||||
|
@ -904,10 +914,10 @@ public class WebSocketMessageD13Test
|
|||
output.flush();
|
||||
|
||||
|
||||
assertEquals(0x80|WebSocketConnectionD13.OP_CLOSE,input.read());
|
||||
assertEquals(0x80|WebSocketConnectionRFC6455.OP_CLOSE,input.read());
|
||||
assertEquals(19,input.read());
|
||||
int code=(0xff&input.read())*0x100+(0xff&input.read());
|
||||
assertEquals(WebSocketConnectionD13.CLOSE_MESSAGE_TOO_LARGE,code);
|
||||
assertEquals(WebSocketConnectionRFC6455.CLOSE_MESSAGE_TOO_LARGE,code);
|
||||
lookFor("Message size > 15",input);
|
||||
}
|
||||
|
||||
|
@ -977,7 +987,7 @@ public class WebSocketMessageD13Test
|
|||
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"+
|
||||
"Sec-WebSocket-Origin: http://example.com\r\n"+
|
||||
"Sec-WebSocket-Protocol: chat\r\n" +
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionD13.VERSION+"\r\n"+
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionRFC6455.VERSION+"\r\n"+
|
||||
"\r\n").getBytes("ISO-8859-1"));
|
||||
output.flush();
|
||||
|
||||
|
@ -1088,7 +1098,7 @@ public class WebSocketMessageD13Test
|
|||
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"+
|
||||
"Sec-WebSocket-Origin: http://example.com\r\n"+
|
||||
"Sec-WebSocket-Protocol: chat\r\n" +
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionD13.VERSION+"\r\n"+
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionRFC6455.VERSION+"\r\n"+
|
||||
"\r\n").getBytes("ISO-8859-1"));
|
||||
output.flush();
|
||||
|
||||
|
@ -1159,7 +1169,7 @@ public class WebSocketMessageD13Test
|
|||
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"+
|
||||
"Sec-WebSocket-Origin: http://example.com\r\n"+
|
||||
"Sec-WebSocket-Protocol: chat\r\n" +
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionD13.VERSION+"\r\n"+
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionRFC6455.VERSION+"\r\n"+
|
||||
"\r\n").getBytes("ISO-8859-1"));
|
||||
output.flush();
|
||||
|
||||
|
@ -1186,10 +1196,10 @@ public class WebSocketMessageD13Test
|
|||
output.write(0x28);
|
||||
output.flush();
|
||||
|
||||
assertEquals(0x80|WebSocketConnectionD13.OP_CLOSE,input.read());
|
||||
assertEquals(0x80|WebSocketConnectionRFC6455.OP_CLOSE,input.read());
|
||||
assertEquals(15,input.read());
|
||||
int code=(0xff&input.read())*0x100+(0xff&input.read());
|
||||
assertEquals(WebSocketConnectionD13.CLOSE_BAD_PAYLOAD,code);
|
||||
assertEquals(WebSocketConnectionRFC6455.CLOSE_BAD_PAYLOAD,code);
|
||||
lookFor("Invalid UTF-8",input);
|
||||
}
|
||||
|
||||
|
@ -1206,7 +1216,7 @@ public class WebSocketMessageD13Test
|
|||
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"+
|
||||
"Sec-WebSocket-Origin: http://example.com\r\n"+
|
||||
"Sec-WebSocket-Protocol: other\r\n" +
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionD13.VERSION+"\r\n"+
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionRFC6455.VERSION+"\r\n"+
|
||||
"\r\n").getBytes("ISO-8859-1"));
|
||||
output.flush();
|
||||
|
||||
|
@ -1234,10 +1244,10 @@ public class WebSocketMessageD13Test
|
|||
output.write(bytes[i]^0xff);
|
||||
output.flush();
|
||||
|
||||
assertEquals(0x80|WebSocketConnectionD13.OP_CLOSE,input.read());
|
||||
assertEquals(0x80|WebSocketConnectionRFC6455.OP_CLOSE,input.read());
|
||||
assertEquals(19,input.read());
|
||||
int code=(0xff&input.read())*0x100+(0xff&input.read());
|
||||
assertEquals(WebSocketConnectionD13.CLOSE_MESSAGE_TOO_LARGE,code);
|
||||
assertEquals(WebSocketConnectionRFC6455.CLOSE_MESSAGE_TOO_LARGE,code);
|
||||
lookFor("Message size > 15",input);
|
||||
}
|
||||
|
||||
|
@ -1254,7 +1264,7 @@ public class WebSocketMessageD13Test
|
|||
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"+
|
||||
"Sec-WebSocket-Origin: http://example.com\r\n"+
|
||||
"Sec-WebSocket-Protocol: onConnect\r\n" +
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionD13.VERSION+"\r\n"+
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionRFC6455.VERSION+"\r\n"+
|
||||
"\r\n").getBytes("ISO-8859-1"));
|
||||
output.flush();
|
||||
|
||||
|
@ -1316,7 +1326,7 @@ public class WebSocketMessageD13Test
|
|||
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"+
|
||||
"Sec-WebSocket-Origin: http://example.com\r\n"+
|
||||
"Sec-WebSocket-Protocol: onConnect\r\n" +
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionD13.VERSION+"\r\n"+
|
||||
"Sec-WebSocket-Version: "+WebSocketConnectionRFC6455.VERSION+"\r\n"+
|
||||
"\r\n").getBytes("ISO-8859-1"));
|
||||
output.flush();
|
||||
|
||||
|
@ -1360,7 +1370,7 @@ public class WebSocketMessageD13Test
|
|||
final AtomicReference<String> received = new AtomicReference<String>();
|
||||
ByteArrayEndPoint endp = new ByteArrayEndPoint(new byte[0],4096);
|
||||
|
||||
WebSocketGeneratorD13 gen = new WebSocketGeneratorD13(new WebSocketBuffers(8096),endp,null);
|
||||
WebSocketGeneratorRFC6455 gen = new WebSocketGeneratorRFC6455(new WebSocketBuffers(8096),endp,null);
|
||||
|
||||
byte[] data = message.getBytes(StringUtil.__UTF8);
|
||||
gen.addFrame((byte)0x8,(byte)0x4,data,0,data.length);
|
||||
|
@ -1394,7 +1404,7 @@ public class WebSocketMessageD13Test
|
|||
|
||||
MaskGen maskGen = new RandomMaskGen();
|
||||
|
||||
WebSocketGeneratorD13 gen = new WebSocketGeneratorD13(new WebSocketBuffers(8096),endp,maskGen);
|
||||
WebSocketGeneratorRFC6455 gen = new WebSocketGeneratorRFC6455(new WebSocketBuffers(8096),endp,maskGen);
|
||||
byte[] data = message.getBytes(StringUtil.__UTF8);
|
||||
gen.addFrame((byte)0x8,(byte)0x1,data,0,data.length);
|
||||
|
||||
|
@ -1524,9 +1534,9 @@ public class WebSocketMessageD13Test
|
|||
{
|
||||
switch(opcode)
|
||||
{
|
||||
case WebSocketConnectionD13.OP_CLOSE:
|
||||
case WebSocketConnectionD13.OP_PING:
|
||||
case WebSocketConnectionD13.OP_PONG:
|
||||
case WebSocketConnectionRFC6455.OP_CLOSE:
|
||||
case WebSocketConnectionRFC6455.OP_PING:
|
||||
case WebSocketConnectionRFC6455.OP_PONG:
|
||||
break;
|
||||
|
||||
default:
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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;
|
||||
|
||||
import java.io.IOException;
|
||||
|
|
|
@ -1,8 +1,22 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -16,9 +30,6 @@ import org.eclipse.jetty.util.StringUtil;
|
|||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
public class WebSocketParserD00Test
|
||||
{
|
||||
private ByteArrayBuffer _in;
|
||||
|
@ -51,7 +62,7 @@ public class WebSocketParserD00Test
|
|||
|
||||
int filled =_parser.parseNext();
|
||||
|
||||
assertEquals(13,filled);
|
||||
assertThat(filled,greaterThan(0));
|
||||
assertEquals("Hello World",_handler._data.get(0));
|
||||
assertTrue(_parser.isBufferEmpty());
|
||||
assertTrue(_parser.getBuffer()==null);
|
||||
|
@ -69,14 +80,14 @@ public class WebSocketParserD00Test
|
|||
|
||||
int filled =_parser.parseNext();
|
||||
|
||||
assertEquals(30,filled);
|
||||
assertThat(filled,greaterThan(0));
|
||||
assertEquals("Hello World",_handler._data.get(0));
|
||||
assertFalse(_parser.isBufferEmpty());
|
||||
assertFalse(_parser.getBuffer()==null);
|
||||
|
||||
filled =_parser.parseNext();
|
||||
|
||||
assertEquals(0,filled);
|
||||
assertThat(filled,greaterThan(0));
|
||||
assertEquals("Hell\uFF4f W\uFF4Frld",_handler._data.get(1));
|
||||
assertTrue(_parser.isBufferEmpty());
|
||||
assertTrue(_parser.getBuffer()==null);
|
||||
|
@ -91,7 +102,7 @@ public class WebSocketParserD00Test
|
|||
|
||||
int filled =_parser.parseNext();
|
||||
|
||||
assertEquals(13,filled);
|
||||
assertThat(filled,greaterThan(0));
|
||||
assertEquals("Hello World",_handler._data.get(0));
|
||||
assertTrue(_parser.isBufferEmpty());
|
||||
assertTrue(_parser.getBuffer()==null);
|
||||
|
@ -113,15 +124,14 @@ public class WebSocketParserD00Test
|
|||
_in.put((byte)(data.length&0x7f));
|
||||
_in.put(data);
|
||||
|
||||
|
||||
int filled =_parser.parseNext();
|
||||
assertEquals(13+3+data.length,filled);
|
||||
assertThat(filled,greaterThan(0));
|
||||
assertEquals("Hello World",_handler._data.get(0));
|
||||
assertFalse(_parser.isBufferEmpty());
|
||||
assertFalse(_parser.getBuffer()==null);
|
||||
|
||||
filled =_parser.parseNext();
|
||||
assertEquals(0,filled);
|
||||
assertThat(filled,greaterThan(0));
|
||||
String got=_handler._data.get(1);
|
||||
assertEquals(data.length,got.length());
|
||||
assertTrue(got.startsWith("012345678901234567890123"));
|
||||
|
|
|
@ -1,8 +1,21 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -17,9 +30,6 @@ import org.eclipse.jetty.util.Utf8StringBuilder;
|
|||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
public class WebSocketParserD06Test
|
||||
{
|
||||
private MaskedByteArrayBuffer _in;
|
||||
|
|
|
@ -1,8 +1,21 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -17,9 +30,6 @@ import org.eclipse.jetty.util.Utf8StringBuilder;
|
|||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
public class WebSocketParserD08Test
|
||||
{
|
||||
private MaskedByteArrayBuffer _in;
|
||||
|
|
|
@ -1,8 +1,21 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -17,10 +30,7 @@ import org.eclipse.jetty.util.Utf8StringBuilder;
|
|||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
public class WebSocketParserD13Test
|
||||
public class WebSocketParserRFC6455Test
|
||||
{
|
||||
private ByteArrayEndPoint _endPoint;
|
||||
private MaskedByteArrayBuffer _in;
|
||||
|
@ -269,7 +279,7 @@ public class WebSocketParserD13Test
|
|||
int progress =_parser.parseNext();
|
||||
|
||||
assertTrue(progress>0);
|
||||
assertEquals(WebSocketConnectionD13.CLOSE_POLICY_VIOLATION,_handler._code);
|
||||
assertEquals(WebSocketConnectionRFC6455.CLOSE_POLICY_VIOLATION,_handler._code);
|
||||
|
||||
|
||||
for (int i=0;i<2048;i++)
|
||||
|
@ -313,7 +323,7 @@ public class WebSocketParserD13Test
|
|||
assertTrue(progress>0);
|
||||
|
||||
assertEquals(2,_handler._frames);
|
||||
assertEquals(WebSocketConnectionD13.OP_CONTINUATION,_handler._opcode);
|
||||
assertEquals(WebSocketConnectionRFC6455.OP_CONTINUATION,_handler._opcode);
|
||||
assertEquals(1,_handler._data.size());
|
||||
String mesg=_handler._data.remove(0);
|
||||
|
|
@ -0,0 +1,225 @@
|
|||
package org.eclipse.jetty.websocket;
|
||||
|
||||
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.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.URI;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.eclipse.jetty.server.Connector;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.eclipse.jetty.websocket.helper.MessageSender;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Test various <a href="http://tools.ietf.org/html/rfc6455">RFC 6455</a> specified requirements placed on
|
||||
* {@link WebSocketServlet}
|
||||
* <p>
|
||||
* This test serves a different purpose than than the {@link WebSocketGeneratorRFC6455Test},
|
||||
* {@link WebSocketMessageRFC6455Test}, and {@link WebSocketParserRFC6455Test} tests.
|
||||
*/
|
||||
public class WebSocketServletRFCTest
|
||||
{
|
||||
private static class RFCSocket implements WebSocket, WebSocket.OnTextMessage
|
||||
{
|
||||
private Connection conn;
|
||||
|
||||
public void onOpen(Connection connection)
|
||||
{
|
||||
this.conn = connection;
|
||||
}
|
||||
|
||||
public void onClose(int closeCode, String message)
|
||||
{
|
||||
this.conn = null;
|
||||
}
|
||||
|
||||
public void onMessage(String data)
|
||||
{
|
||||
// Test the RFC 6455 close code 1011 that should close
|
||||
// trigger a WebSocket server terminated close.
|
||||
if (data.equals("CRASH"))
|
||||
{
|
||||
throw new RuntimeException("Something bad happened");
|
||||
}
|
||||
|
||||
// echo the message back.
|
||||
try
|
||||
{
|
||||
conn.sendMessage(data);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace(System.err);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static class RFCServlet extends WebSocketServlet
|
||||
{
|
||||
public WebSocket doWebSocketConnect(HttpServletRequest request, String protocol)
|
||||
{
|
||||
return new RFCSocket();
|
||||
}
|
||||
}
|
||||
|
||||
private static Server server;
|
||||
private static URI serverUri;
|
||||
|
||||
@BeforeClass
|
||||
public static void startServer() throws Exception
|
||||
{
|
||||
// Configure Server
|
||||
server = new Server(0);
|
||||
|
||||
ServletContextHandler context = new ServletContextHandler();
|
||||
context.setContextPath("/");
|
||||
server.setHandler(context);
|
||||
|
||||
// Serve capture servlet
|
||||
context.addServlet(new ServletHolder(new RFCServlet()),"/*");
|
||||
|
||||
// Start Server
|
||||
server.start();
|
||||
|
||||
Connector conn = server.getConnectors()[0];
|
||||
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);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void stopServer()
|
||||
{
|
||||
try
|
||||
{
|
||||
server.stop();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace(System.err);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the requirement of responding with an http 400 when using a Sec-WebSocket-Version that is unsupported.
|
||||
*/
|
||||
@Test
|
||||
public void testResponseOnInvalidVersion() throws Exception
|
||||
{
|
||||
// Using straight Socket to accomplish this as jetty's WebSocketClient
|
||||
// doesn't allow the use of invalid versions. (obviously)
|
||||
|
||||
Socket socket = new Socket();
|
||||
SocketAddress endpoint = new InetSocketAddress(serverUri.getHost(),serverUri.getPort());
|
||||
socket.connect(endpoint);
|
||||
|
||||
StringBuilder req = new StringBuilder();
|
||||
req.append("GET / HTTP/1.1\r\n");
|
||||
req.append(String.format("Host: %s:%d\r\n",serverUri.getHost(),serverUri.getPort()));
|
||||
req.append("Upgrade: WebSocket\r\n");
|
||||
req.append("Connection: Upgrade\r\n");
|
||||
req.append("Sec-WebSocket-Version: 29\r\n"); // bad version
|
||||
req.append("\r\n");
|
||||
|
||||
OutputStream out = null;
|
||||
InputStream in = null;
|
||||
try
|
||||
{
|
||||
out = socket.getOutputStream();
|
||||
in = socket.getInputStream();
|
||||
|
||||
// Write request
|
||||
out.write(req.toString().getBytes());
|
||||
out.flush();
|
||||
|
||||
// Read response
|
||||
String respHeader = readResponseHeader(in);
|
||||
// System.out.println("RESPONSE: " + respHeader);
|
||||
|
||||
Assert.assertThat("Response Code",respHeader,startsWith("HTTP/1.1 400 Unsupported websocket version specification"));
|
||||
Assert.assertThat("Response Header Versions",respHeader,containsString("Sec-WebSocket-Version: 13, 8, 6, 0\r\n"));
|
||||
}
|
||||
finally
|
||||
{
|
||||
IO.close(in);
|
||||
IO.close(out);
|
||||
socket.close();
|
||||
}
|
||||
}
|
||||
|
||||
private String readResponseHeader(InputStream in) throws IOException
|
||||
{
|
||||
InputStreamReader isr = new InputStreamReader(in);
|
||||
BufferedReader reader = new BufferedReader(isr);
|
||||
StringBuilder header = new StringBuilder();
|
||||
// Read the response header
|
||||
String line = reader.readLine();
|
||||
Assert.assertNotNull(line);
|
||||
Assert.assertThat(line,startsWith("HTTP/1.1 "));
|
||||
header.append(line).append("\r\n");
|
||||
while ((line = reader.readLine()) != null)
|
||||
{
|
||||
if (line.trim().length() == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
header.append(line).append("\r\n");
|
||||
}
|
||||
return header.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the requirement of responding with server terminated close code 1011 when there is an unhandled (internal
|
||||
* server error) being produced by the extended WebSocketServlet.
|
||||
*/
|
||||
@Test
|
||||
public void testResponseOnInternalError() throws Exception
|
||||
{
|
||||
WebSocketClientFactory clientFactory = new WebSocketClientFactory();
|
||||
clientFactory.start();
|
||||
|
||||
WebSocketClient wsc = clientFactory.newWebSocketClient();
|
||||
MessageSender sender = new MessageSender();
|
||||
wsc.open(serverUri,sender);
|
||||
|
||||
try
|
||||
{
|
||||
sender.awaitConnect();
|
||||
|
||||
sender.sendMessage("CRASH");
|
||||
|
||||
// Give servlet 500 millisecond to process messages
|
||||
TimeUnit.MILLISECONDS.sleep(500);
|
||||
|
||||
Assert.assertThat("WebSocket should be closed",sender.isConnected(),is(false));
|
||||
Assert.assertThat("WebSocket close clode",sender.getCloseCode(),is(1011));
|
||||
}
|
||||
finally
|
||||
{
|
||||
sender.close();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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.helper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -26,7 +41,7 @@ public class CaptureSocket implements WebSocket, WebSocket.OnTextMessage
|
|||
|
||||
public void onMessage(String data)
|
||||
{
|
||||
System.out.printf("Received Message \"%s\" [size %d]%n", data, data.length());
|
||||
// System.out.printf("Received Message \"%s\" [size %d]%n", data, data.length());
|
||||
messages.add(data);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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.helper;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -10,6 +25,8 @@ public class MessageSender implements WebSocket
|
|||
{
|
||||
private Connection conn;
|
||||
private CountDownLatch connectLatch = new CountDownLatch(1);
|
||||
private int closeCode = -1;
|
||||
private String closeMessage = null;
|
||||
|
||||
public void onOpen(Connection connection)
|
||||
{
|
||||
|
@ -20,6 +37,8 @@ public class MessageSender implements WebSocket
|
|||
public void onClose(int closeCode, String message)
|
||||
{
|
||||
this.conn = null;
|
||||
this.closeCode = closeCode;
|
||||
this.closeMessage = message;
|
||||
}
|
||||
|
||||
public boolean isConnected()
|
||||
|
@ -30,6 +49,16 @@ public class MessageSender implements WebSocket
|
|||
}
|
||||
return this.conn.isOpen();
|
||||
}
|
||||
|
||||
public int getCloseCode()
|
||||
{
|
||||
return closeCode;
|
||||
}
|
||||
|
||||
public String getCloseMessage()
|
||||
{
|
||||
return closeMessage;
|
||||
}
|
||||
|
||||
public void sendMessage(String format, Object... args) throws IOException
|
||||
{
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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.helper;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
@ -65,7 +80,7 @@ public class SafariD00
|
|||
req.append("Sec-WebSocket-Key2: 3? C;7~0 8 \" 3 2105 6 `_ {\r\n");
|
||||
req.append("\r\n");
|
||||
|
||||
System.out.printf("--- Request ---%n%s",req);
|
||||
// System.out.printf("--- Request ---%n%s",req);
|
||||
|
||||
byte reqBytes[] = req.toString().getBytes("UTF-8");
|
||||
byte hixieBytes[] = TypeUtil.fromHexString("e739617916c9daf3");
|
||||
|
@ -86,7 +101,7 @@ public class SafariD00
|
|||
while (!foundEnd)
|
||||
{
|
||||
line = br.readLine();
|
||||
System.out.printf("RESP: %s%n",line);
|
||||
// System.out.printf("RESP: %s%n",line);
|
||||
if (line.length() == 0)
|
||||
{
|
||||
foundEnd = true;
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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.helper;
|
||||
|
||||
import java.io.IOException;
|
||||
|
|
2
pom.xml
2
pom.xml
|
@ -351,7 +351,7 @@
|
|||
<module>jetty-http-spi</module>
|
||||
<module>jetty-distribution</module>
|
||||
<module>test-continuation</module>
|
||||
<module>test-continuation-jetty6</module>
|
||||
<!--module>test-continuation-jetty6</module-->
|
||||
<module>test-jetty-servlet</module>
|
||||
<module>test-jetty-webapp</module>
|
||||
<module>test-jetty-nested</module>
|
||||
|
|
|
@ -233,9 +233,13 @@ public abstract class ContinuationBase extends TestCase
|
|||
request+=" HTTP/1.1\r\n"+
|
||||
"Host: localhost\r\n"+
|
||||
"Connection: close\r\n";
|
||||
if (content!=null)
|
||||
if (content==null)
|
||||
request+="\r\n";
|
||||
else
|
||||
{
|
||||
request+="Content-Length: "+content.length()+"\r\n";
|
||||
request+="\r\n" + content;
|
||||
request+="\r\n" + content;
|
||||
}
|
||||
|
||||
int port=_port;
|
||||
String response=null;
|
||||
|
|
Loading…
Reference in New Issue