Merge branch 'master' into release
This commit is contained in:
commit
772cabf893
|
@ -0,0 +1,88 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<groupId>org.eclipse.jetty.aggregate</groupId>
|
||||
<artifactId>jetty-aggregate-project</artifactId>
|
||||
<version>7.6.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jetty-websocket</artifactId>
|
||||
<name>Jetty :: Aggregate :: Websocket</name>
|
||||
|
||||
<build>
|
||||
<sourceDirectory>${project.build.directory}/sources</sourceDirectory>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>unpack-dependencies</id>
|
||||
<goals>
|
||||
<goal>unpack-dependencies</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<includes>META-INF/**,org/eclipse/**</includes>
|
||||
<excludes>**/MANIFEST.MF,javax/**,about.html</excludes>
|
||||
<outputDirectory>${project.build.directory}/classes</outputDirectory>
|
||||
<overWriteReleases>false</overWriteReleases>
|
||||
<overWriteSnapshots>true</overWriteSnapshots>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>unpack-source</id>
|
||||
<phase>generate-sources</phase>
|
||||
<goals>
|
||||
<goal>unpack-dependencies</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<classifier>sources</classifier>
|
||||
<includes>**/*</includes>
|
||||
<excludes>META-INF/**</excludes>
|
||||
<includeGroupIds>org.eclipse.jetty</includeGroupIds>
|
||||
<outputDirectory>${project.build.directory}/sources</outputDirectory>
|
||||
<overWriteReleases>true</overWriteReleases>
|
||||
<overWriteSnapshots>true</overWriteSnapshots>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins
|
||||
</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>package</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
</manifest>
|
||||
<manifestEntries>
|
||||
<mode>development</mode>
|
||||
<url>http://eclipse.org/jetty</url>
|
||||
<Built-By>${user.name}</Built-By>
|
||||
<package>org.eclipse.jetty</package>
|
||||
<Bundle-License>http://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk/NOTICE.txt</Bundle-License>
|
||||
<Bundle-Name>Jetty HTTP Server</Bundle-Name>
|
||||
</manifestEntries>
|
||||
</archive>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-websocket</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -35,6 +35,7 @@
|
|||
<module>jetty-client</module>
|
||||
<module>jetty-servlet</module>
|
||||
<module>jetty-webapp</module>
|
||||
<module>jetty-websocket</module>
|
||||
<module>jetty-plus</module>
|
||||
<module>jetty-all-server</module>
|
||||
<module>jetty-all</module>
|
||||
|
|
|
@ -454,7 +454,10 @@ public class AnnotationParser
|
|||
className = className.replace('.', '/')+".class";
|
||||
URL resource = Loader.getResource(this.getClass(), className, false);
|
||||
if (resource!= null)
|
||||
scanClass(resource.openStream());
|
||||
{
|
||||
Resource r = Resource.newResource(resource);
|
||||
scanClass(r.getInputStream());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -472,7 +475,10 @@ public class AnnotationParser
|
|||
String nameAsResource = cz.getName().replace('.', '/')+".class";
|
||||
URL resource = Loader.getResource(this.getClass(), nameAsResource, false);
|
||||
if (resource!= null)
|
||||
scanClass(resource.openStream());
|
||||
{
|
||||
Resource r = Resource.newResource(resource);
|
||||
scanClass(r.getInputStream());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (visitSuperClasses)
|
||||
|
@ -501,7 +507,10 @@ public class AnnotationParser
|
|||
s = s.replace('.', '/')+".class";
|
||||
URL resource = Loader.getResource(this.getClass(), s, false);
|
||||
if (resource!= null)
|
||||
scanClass(resource.openStream());
|
||||
{
|
||||
Resource r = Resource.newResource(resource);
|
||||
scanClass(r.getInputStream());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -525,7 +534,10 @@ public class AnnotationParser
|
|||
if (name.endsWith(".class"))
|
||||
{
|
||||
if ((resolver == null)|| (!resolver.isExcluded(name) && (!isParsed(name) || resolver.shouldOverride(name))))
|
||||
scanClass(res.getURL().openStream());
|
||||
{
|
||||
Resource r = Resource.newResource(res.getURL());
|
||||
scanClass(r.getInputStream());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -355,9 +355,8 @@ public abstract class AbstractHttpConnection extends AbstractConnection implemen
|
|||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return String.format("%s@%x//%s,g=%s,p=%s",
|
||||
getClass().getSimpleName(),
|
||||
hashCode(),
|
||||
return String.format("%s %s g=%s p=%s",
|
||||
super.toString(),
|
||||
_destination == null ? "?.?.?.?:??" : _destination.getAddress(),
|
||||
_generator,
|
||||
_parser);
|
||||
|
|
|
@ -43,6 +43,9 @@ public class Address
|
|||
|
||||
public Address(String host, int port)
|
||||
{
|
||||
if (host == null)
|
||||
throw new IllegalArgumentException("Host is null");
|
||||
|
||||
this.host = host.trim();
|
||||
this.port = port;
|
||||
}
|
||||
|
|
|
@ -439,7 +439,9 @@ public class HttpDestination implements Dumpable
|
|||
|
||||
public void returnIdleConnection(AbstractHttpConnection connection)
|
||||
{
|
||||
connection.onIdleExpired();
|
||||
// TODO work out the real idle time;
|
||||
long idleForMs=connection!=null&&connection.getEndPoint()!=null?connection.getEndPoint().getMaxIdleTime():-1;
|
||||
connection.onIdleExpired(idleForMs);
|
||||
|
||||
boolean startConnection = false;
|
||||
synchronized (this)
|
||||
|
|
|
@ -437,9 +437,9 @@ class SelectConnector extends AbstractLifeCycle implements HttpClient.Connector,
|
|||
_endp.setMaxIdleTime(timeMs);
|
||||
}
|
||||
|
||||
public void onIdleExpired()
|
||||
public void onIdleExpired(long idleForMs)
|
||||
{
|
||||
_endp.onIdleExpired();
|
||||
_endp.onIdleExpired(idleForMs);
|
||||
}
|
||||
|
||||
public void setCheckForIdle(boolean check)
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
package org.eclipse.jetty.client;
|
||||
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
import static org.hamcrest.Matchers.lessThan;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
@ -17,19 +14,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;
|
||||
|
@ -40,6 +39,7 @@ import org.eclipse.jetty.server.Server;
|
|||
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||
import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
|
||||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||
import org.eclipse.jetty.toolchain.test.OS;
|
||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
|
@ -48,10 +48,16 @@ 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 AtomicInteger sslHandles = new AtomicInteger();
|
||||
private final AtomicInteger sslFlushes = new AtomicInteger();
|
||||
private final AtomicInteger httpParses = new AtomicInteger();
|
||||
private final AtomicReference<EndPoint> serverEndPoint = new AtomicReference<EndPoint>();
|
||||
private final int idleTimeout = 2000;
|
||||
private ExecutorService threadPool;
|
||||
private Server server;
|
||||
private SSLContext sslContext;
|
||||
|
@ -68,6 +74,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
@Override
|
||||
protected SslConnection newSslConnection(AsyncEndPoint endPoint, SSLEngine engine)
|
||||
{
|
||||
serverEndPoint.set(endPoint);
|
||||
return new SslConnection(engine, endPoint)
|
||||
{
|
||||
@Override
|
||||
|
@ -76,6 +83,20 @@ 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);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -100,6 +121,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
};
|
||||
}
|
||||
};
|
||||
connector.setMaxIdleTime(idleTimeout);
|
||||
|
||||
// connector.setPort(5870);
|
||||
connector.setPort(0);
|
||||
|
@ -119,9 +141,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 +227,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 +254,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 +268,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 +278,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 +288,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 +305,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 +317,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 +378,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 +401,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 +410,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 +449,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 +469,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 +477,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);
|
||||
|
@ -565,6 +569,21 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
@Test
|
||||
public void testRequestWithCloseAlert() throws Exception
|
||||
{
|
||||
if ( !OS.IS_LINUX )
|
||||
{
|
||||
// currently we are ignoring this test on anything other then linux
|
||||
|
||||
//http://tools.ietf.org/html/rfc2246#section-7.2.1
|
||||
|
||||
// TODO (react to this portion which seems to allow win/mac behavior)
|
||||
//It is required that the other party respond with a close_notify alert of its own
|
||||
//and close down the connection immediately, discarding any pending writes. It is not
|
||||
//required for the initiator of the close to wait for the responding
|
||||
//close_notify alert before closing the read side of the connection.
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
final SSLSocket client = newClient();
|
||||
|
||||
SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow();
|
||||
|
@ -587,6 +606,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 +614,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 +635,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 +674,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 +693,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();
|
||||
|
@ -678,6 +759,20 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
@Test
|
||||
public void testRequestWithCloseAlertWithSplitBoundary() throws Exception
|
||||
{
|
||||
if ( !OS.IS_LINUX )
|
||||
{
|
||||
// currently we are ignoring this test on anything other then linux
|
||||
|
||||
//http://tools.ietf.org/html/rfc2246#section-7.2.1
|
||||
|
||||
// TODO (react to this portion which seems to allow win/mac behavior)
|
||||
//It is required that the other party respond with a close_notify alert of its own
|
||||
//and close down the connection immediately, discarding any pending writes. It is not
|
||||
//required for the initiator of the close to wait for the responding
|
||||
//close_notify alert before closing the read side of the connection.
|
||||
return;
|
||||
}
|
||||
|
||||
final SSLSocket client = newClient();
|
||||
|
||||
SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow();
|
||||
|
@ -713,13 +808,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 +832,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 +879,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 +901,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 +948,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 +975,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 +1106,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 +1162,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 +1200,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 +1211,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 +1235,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,11 +1265,66 @@ 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);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServerShutdownOutputClientDoesNotCloseServerCloses() throws Exception
|
||||
{
|
||||
final SSLSocket client = newClient();
|
||||
final OutputStream clientOutput = client.getOutputStream();
|
||||
|
||||
SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow();
|
||||
client.startHandshake();
|
||||
Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS));
|
||||
|
||||
byte[] data = new byte[3 * 1024];
|
||||
Arrays.fill(data, (byte)'Y');
|
||||
String content = new String(data, "UTF-8");
|
||||
automaticProxyFlow = proxy.startAutomaticFlow();
|
||||
clientOutput.write(("" +
|
||||
"POST / HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"Content-Type: text/plain\r\n" +
|
||||
"Content-Length: " + content.length() + "\r\n" +
|
||||
"Connection: close\r\n" +
|
||||
"\r\n" +
|
||||
content).getBytes("UTF-8"));
|
||||
clientOutput.flush();
|
||||
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream(), "UTF-8"));
|
||||
String line = reader.readLine();
|
||||
Assert.assertNotNull(line);
|
||||
Assert.assertTrue(line.startsWith("HTTP/1.1 200 "));
|
||||
while ((line = reader.readLine()) != null)
|
||||
{
|
||||
if (line.trim().length() == 0)
|
||||
break;
|
||||
}
|
||||
Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS));
|
||||
|
||||
// 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(sslFlushes.get(), lessThan(20));
|
||||
Assert.assertThat(httpParses.get(), lessThan(50));
|
||||
|
||||
// The server has shutdown the output since the client sent a Connection: close
|
||||
// but the client does not close, so the server must idle timeout the endPoint.
|
||||
|
||||
TimeUnit.MILLISECONDS.sleep(idleTimeout + idleTimeout/2);
|
||||
|
||||
Assert.assertFalse(serverEndPoint.get().isOpen());
|
||||
}
|
||||
|
||||
private void assumeJavaVersionSupportsTLSRenegotiations()
|
||||
{
|
||||
// Due to a security bug, TLS renegotiations were disabled in JDK 1.6.0_19-21
|
||||
|
@ -1203,7 +1347,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
return client;
|
||||
}
|
||||
|
||||
private void closeClient(SSLSocket client) throws IOException
|
||||
private void closeClient(SSLSocket client) throws Exception
|
||||
{
|
||||
client.close();
|
||||
|
||||
|
@ -1223,5 +1367,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;
|
||||
|
|
|
@ -0,0 +1,420 @@
|
|||
package org.eclipse.jetty.client;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
import java.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;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.http.HttpParser;
|
||||
import org.eclipse.jetty.io.AsyncEndPoint;
|
||||
import org.eclipse.jetty.io.Buffers;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.io.nio.AsyncConnection;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||
import org.eclipse.jetty.server.nio.SelectChannelConnector;
|
||||
import org.eclipse.jetty.toolchain.test.IO;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
public class TimeoutTest
|
||||
{
|
||||
private static final Logger logger = Log.getLogger(TimeoutTest.class);
|
||||
private final AtomicInteger httpParses = new AtomicInteger();
|
||||
private 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
|
||||
{
|
||||
threadPool = Executors.newCachedThreadPool();
|
||||
server = new Server();
|
||||
|
||||
SelectChannelConnector connector = new SelectChannelConnector()
|
||||
{
|
||||
@Override
|
||||
protected AsyncConnection newConnection(SocketChannel channel, final AsyncEndPoint endPoint)
|
||||
{
|
||||
serverEndPoint.set(endPoint);
|
||||
return new org.eclipse.jetty.server.AsyncHttpConnection(this,endPoint,getServer())
|
||||
{
|
||||
@Override
|
||||
protected HttpParser newHttpParser(Buffers requestBuffers, EndPoint endPoint, HttpParser.EventHandler requestHandler)
|
||||
{
|
||||
return new HttpParser(requestBuffers,endPoint,requestHandler)
|
||||
{
|
||||
@Override
|
||||
public int parseNext() throws IOException
|
||||
{
|
||||
httpParses.incrementAndGet();
|
||||
return super.parseNext();
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
connector.setMaxIdleTime(2000);
|
||||
|
||||
// connector.setPort(5870);
|
||||
connector.setPort(0);
|
||||
|
||||
server.addConnector(connector);
|
||||
server.setHandler(new AbstractHandler()
|
||||
{
|
||||
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException,
|
||||
ServletException
|
||||
{
|
||||
httpRequests.incrementAndGet();
|
||||
request.setHandled(true);
|
||||
String contentLength = request.getHeader("Content-Length");
|
||||
if (contentLength != null)
|
||||
{
|
||||
int length = Integer.parseInt(contentLength);
|
||||
ServletInputStream input = request.getInputStream();
|
||||
for (int i = 0; i < length; ++i)
|
||||
input.read();
|
||||
}
|
||||
}
|
||||
});
|
||||
server.start();
|
||||
serverPort = connector.getLocalPort();
|
||||
|
||||
httpRequests.set(0);
|
||||
logger.debug(" => :{}",serverPort);
|
||||
}
|
||||
|
||||
@After
|
||||
public void destroy() throws Exception
|
||||
{
|
||||
if (server != null)
|
||||
server.stop();
|
||||
if (threadPool != null)
|
||||
threadPool.shutdownNow();
|
||||
}
|
||||
|
||||
private Socket newClient() throws IOException, InterruptedException
|
||||
{
|
||||
Socket client = new Socket("localhost",serverPort);
|
||||
return client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that performs a 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", and then attempts to
|
||||
* write a second POST request.
|
||||
* <p>
|
||||
* 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.
|
||||
*/
|
||||
@Test
|
||||
public void testServerCloseClientDoesNotClose() throws Exception
|
||||
{
|
||||
// Log.getLogger("").setDebugEnabled(true);
|
||||
final Socket client = newClient();
|
||||
final OutputStream clientOutput = client.getOutputStream();
|
||||
|
||||
byte[] data = new byte[3 * 1024];
|
||||
Arrays.fill(data,(byte)'Y');
|
||||
String content = new String(data,"UTF-8");
|
||||
|
||||
// The request section
|
||||
StringBuilder req = new StringBuilder();
|
||||
req.append("POST / HTTP/1.1\r\n");
|
||||
req.append("Host: localhost\r\n");
|
||||
req.append("Content-Type: text/plain\r\n");
|
||||
req.append("Content-Length: ").append(content.length()).append("\r\n");
|
||||
req.append("Connection: close\r\n");
|
||||
req.append("\r\n");
|
||||
// and now, the POST content section.
|
||||
req.append(content);
|
||||
|
||||
// Send request to server
|
||||
clientOutput.write(req.toString().getBytes("UTF-8"));
|
||||
clientOutput.flush();
|
||||
|
||||
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());
|
||||
|
||||
|
||||
// Wait for the server idle timeout
|
||||
TimeUnit.SECONDS.sleep(3);
|
||||
int 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());
|
||||
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
IO.close(reader);
|
||||
IO.close(isr);
|
||||
IO.close(in);
|
||||
closeClient(client);
|
||||
}
|
||||
}
|
||||
|
||||
private void closeClient(Socket client) throws IOException
|
||||
{
|
||||
client.close();
|
||||
}
|
||||
}
|
|
@ -21,7 +21,7 @@
|
|||
# -Dorg.apache.jasper.compiler.disablejsr199=true
|
||||
# -Dcom.sun.management.jmxremote
|
||||
# -Dorg.eclipse.jetty.util.log.IGNORED=true
|
||||
# -Dorg.eclipse.jetty.util.log.stderr.DEBUG=true
|
||||
# -Dorg.eclipse.jetty.LEVEL=DEBUG
|
||||
# -Dorg.eclipse.jetty.util.log.stderr.SOURCE=true
|
||||
# -Xmx2000m
|
||||
# -Xmn512m
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
package org.eclipse.jetty.http.spi;
|
||||
|
||||
//========================================================================
|
||||
//Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd.
|
||||
//------------------------------------------------------------------------
|
||||
|
@ -12,19 +13,25 @@ package org.eclipse.jetty.http.spi;
|
|||
//You may elect to redistribute this code under either of these licenses.
|
||||
//========================================================================
|
||||
|
||||
import com.sun.net.httpserver.Authenticator;
|
||||
import com.sun.net.httpserver.Authenticator.Result;
|
||||
import com.sun.net.httpserver.HttpContext;
|
||||
import com.sun.net.httpserver.HttpHandler;
|
||||
import com.sun.net.httpserver.HttpPrincipal;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||
|
||||
import com.sun.net.httpserver.Authenticator;
|
||||
import com.sun.net.httpserver.Authenticator.Result;
|
||||
import com.sun.net.httpserver.BasicAuthenticator;
|
||||
import com.sun.net.httpserver.HttpContext;
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import com.sun.net.httpserver.HttpHandler;
|
||||
import com.sun.net.httpserver.HttpPrincipal;
|
||||
|
||||
/**
|
||||
* Jetty handler that bridges requests to {@link HttpHandler}.
|
||||
|
@ -36,7 +43,6 @@ public class HttpSpiContextHandler extends ContextHandler
|
|||
|
||||
private HttpHandler _httpHandler;
|
||||
|
||||
|
||||
public HttpSpiContextHandler(HttpContext httpContext, HttpHandler httpHandler)
|
||||
{
|
||||
this._httpContext = httpContext;
|
||||
|
@ -46,9 +52,20 @@ public class HttpSpiContextHandler extends ContextHandler
|
|||
@Override
|
||||
public void doScope(String target, Request baseRequest, HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException
|
||||
{
|
||||
if (!target.startsWith(getContextPath())) return;
|
||||
if (!target.startsWith(getContextPath()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
JettyHttpExchange jettyHttpExchange = new JettyHttpExchange(_httpContext, req, resp);
|
||||
HttpExchange jettyHttpExchange;
|
||||
if (baseRequest.isSecure())
|
||||
{
|
||||
jettyHttpExchange = new JettyHttpsExchange(_httpContext,req,resp);
|
||||
}
|
||||
else
|
||||
{
|
||||
jettyHttpExchange = new JettyHttpExchange(_httpContext,req,resp);
|
||||
}
|
||||
|
||||
// TODO: add filters processing
|
||||
|
||||
|
@ -56,53 +73,67 @@ public class HttpSpiContextHandler extends ContextHandler
|
|||
{
|
||||
Authenticator auth = _httpContext.getAuthenticator();
|
||||
if (auth != null)
|
||||
handleAuthentication(resp, jettyHttpExchange, auth);
|
||||
{
|
||||
handleAuthentication(resp,jettyHttpExchange,auth);
|
||||
}
|
||||
else
|
||||
{
|
||||
_httpHandler.handle(jettyHttpExchange);
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
catch (Exception ex)
|
||||
{
|
||||
PrintWriter writer = new PrintWriter(jettyHttpExchange.getResponseBody());
|
||||
|
||||
|
||||
resp.setStatus(500);
|
||||
writer.println("<h2>HTTP ERROR: 500</h2>");
|
||||
writer.println("<pre>INTERNAL_SERVER_ERROR</pre>");
|
||||
writer.println("<p>RequestURI=" + req.getRequestURI() + "</p>");
|
||||
|
||||
|
||||
writer.println("<pre>");
|
||||
ex.printStackTrace(writer);
|
||||
writer.println("</pre>");
|
||||
|
||||
|
||||
writer.println("<p><i><small><a href=\"http://jetty.mortbay.org\">Powered by jetty://</a></small></i></p>");
|
||||
|
||||
|
||||
writer.close();
|
||||
}
|
||||
finally
|
||||
{
|
||||
baseRequest.setHandled(true);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void handleAuthentication(HttpServletResponse resp, JettyHttpExchange jettyHttpExchange, Authenticator auth) throws IOException
|
||||
private void handleAuthentication(HttpServletResponse resp, HttpExchange httpExchange, Authenticator auth) throws IOException
|
||||
{
|
||||
Result result = auth.authenticate(jettyHttpExchange);
|
||||
Result result = auth.authenticate(httpExchange);
|
||||
if (result instanceof Authenticator.Failure)
|
||||
{
|
||||
int rc = ((Authenticator.Failure)result).getResponseCode();
|
||||
for (Map.Entry<String,List<String>> header : httpExchange.getResponseHeaders().entrySet())
|
||||
{
|
||||
for (String value : header.getValue())
|
||||
resp.addHeader(header.getKey(),value);
|
||||
}
|
||||
resp.sendError(rc);
|
||||
}
|
||||
else if (result instanceof Authenticator.Retry)
|
||||
{
|
||||
int rc = ((Authenticator.Retry)result).getResponseCode();
|
||||
resp.sendError(rc);
|
||||
for (Map.Entry<String,List<String>> header : httpExchange.getResponseHeaders().entrySet())
|
||||
{
|
||||
for (String value : header.getValue())
|
||||
resp.addHeader(header.getKey(),value);
|
||||
}
|
||||
resp.setStatus(rc);
|
||||
resp.flushBuffer();
|
||||
}
|
||||
else if (result instanceof Authenticator.Success)
|
||||
{
|
||||
HttpPrincipal principal = ((Authenticator.Success)result).getPrincipal();
|
||||
jettyHttpExchange.setPrincipal(principal);
|
||||
_httpHandler.handle(jettyHttpExchange);
|
||||
((JettyExchange)httpExchange).setPrincipal(principal);
|
||||
_httpHandler.handle(httpExchange);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.http.spi;
|
||||
|
||||
import com.sun.net.httpserver.HttpPrincipal;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
*/
|
||||
public interface JettyExchange
|
||||
{
|
||||
|
||||
HttpPrincipal getPrincipal();
|
||||
|
||||
void setPrincipal(HttpPrincipal principal);
|
||||
|
||||
}
|
|
@ -1,227 +1,252 @@
|
|||
package org.eclipse.jetty.http.spi;
|
||||
|
||||
//========================================================================
|
||||
//Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd.
|
||||
//------------------------------------------------------------------------
|
||||
//All rights reserved. This program and the accompanying materials
|
||||
//are made available under the terms of the Eclipse Public License v1.0
|
||||
//and Apache License v2.0 which accompanies this distribution.
|
||||
//The Eclipse Public License is available at
|
||||
//http://www.eclipse.org/legal/epl-v10.html
|
||||
//The Apache License v2.0 is available at
|
||||
//http://www.opensource.org/licenses/apache2.0.php
|
||||
//You may elect to redistribute this code under either of these licenses.
|
||||
//========================================================================
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.sun.net.httpserver.Headers;
|
||||
import com.sun.net.httpserver.HttpContext;
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import com.sun.net.httpserver.HttpPrincipal;
|
||||
|
||||
/**
|
||||
* Jetty implementation of {@link com.sun.net.httpserver.HttpExchange}
|
||||
*/
|
||||
public class JettyHttpExchange extends HttpExchange
|
||||
{
|
||||
|
||||
private HttpContext _httpContext;
|
||||
|
||||
private HttpServletRequest _req;
|
||||
|
||||
private HttpServletResponse _resp;
|
||||
|
||||
private Headers _responseHeaders = new Headers();
|
||||
|
||||
private int _responseCode = 0;
|
||||
|
||||
private InputStream _is;
|
||||
|
||||
private OutputStream _os;
|
||||
|
||||
private HttpPrincipal _httpPrincipal;
|
||||
|
||||
|
||||
public JettyHttpExchange(HttpContext jaxWsContext , HttpServletRequest req,
|
||||
HttpServletResponse resp)
|
||||
{
|
||||
this._httpContext = jaxWsContext;
|
||||
this._req = req;
|
||||
this._resp = resp;
|
||||
try
|
||||
{
|
||||
this._is = req.getInputStream();
|
||||
this._os = resp.getOutputStream();
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Headers getRequestHeaders()
|
||||
{
|
||||
Headers headers = new Headers();
|
||||
Enumeration<?> en = _req.getHeaderNames();
|
||||
while (en.hasMoreElements())
|
||||
{
|
||||
String name = (String) en.nextElement();
|
||||
Enumeration<?> en2 = _req.getHeaders(name);
|
||||
while (en2.hasMoreElements())
|
||||
{
|
||||
String value = (String) en2.nextElement();
|
||||
headers.add(name, value);
|
||||
}
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Headers getResponseHeaders()
|
||||
{
|
||||
return _responseHeaders;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI getRequestURI()
|
||||
{
|
||||
try
|
||||
{
|
||||
String uriAsString = _req.getRequestURI();
|
||||
if (_req.getQueryString() != null)
|
||||
uriAsString += "?" + _req.getQueryString();
|
||||
|
||||
return new URI(uriAsString);
|
||||
}
|
||||
catch (URISyntaxException ex)
|
||||
{
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRequestMethod()
|
||||
{
|
||||
return _req.getMethod();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpContext getHttpContext()
|
||||
{
|
||||
return _httpContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
try
|
||||
{
|
||||
_resp.getOutputStream().close();
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getRequestBody()
|
||||
{
|
||||
return _is;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream getResponseBody()
|
||||
{
|
||||
return _os;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendResponseHeaders(int rCode, long responseLength)
|
||||
throws IOException
|
||||
{
|
||||
this._responseCode = rCode;
|
||||
|
||||
for (Map.Entry<String, List<String>> stringListEntry : _responseHeaders.entrySet())
|
||||
{
|
||||
String name = stringListEntry.getKey();
|
||||
List<String> values = stringListEntry.getValue();
|
||||
|
||||
for (String value : values)
|
||||
{
|
||||
_resp.setHeader(name, value);
|
||||
}
|
||||
}
|
||||
if (responseLength > 0)
|
||||
_resp.setHeader("content-length", "" + responseLength);
|
||||
_resp.setStatus(rCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress getRemoteAddress()
|
||||
{
|
||||
return new InetSocketAddress(_req.getRemoteAddr(), _req.getRemotePort());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getResponseCode()
|
||||
{
|
||||
return _responseCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress getLocalAddress()
|
||||
{
|
||||
return new InetSocketAddress(_req.getLocalAddr(), _req.getLocalPort());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProtocol()
|
||||
{
|
||||
return _req.getProtocol();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAttribute(String name)
|
||||
{
|
||||
return _req.getAttribute(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(String name, Object value)
|
||||
{
|
||||
_req.setAttribute(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStreams(InputStream i, OutputStream o)
|
||||
{
|
||||
_is = i;
|
||||
_os = o;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpPrincipal getPrincipal()
|
||||
{
|
||||
return _httpPrincipal;
|
||||
}
|
||||
|
||||
public void setPrincipal(HttpPrincipal principal)
|
||||
{
|
||||
this._httpPrincipal = principal;
|
||||
}
|
||||
|
||||
}
|
||||
// ========================================================================
|
||||
// Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.http.spi;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URI;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.sun.net.httpserver.Headers;
|
||||
import com.sun.net.httpserver.HttpContext;
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import com.sun.net.httpserver.HttpPrincipal;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
*/
|
||||
public class JettyHttpExchange extends HttpExchange implements JettyExchange
|
||||
{
|
||||
private JettyHttpExchangeDelegate _delegate;
|
||||
|
||||
public JettyHttpExchange(HttpContext jaxWsContext, HttpServletRequest req, HttpServletResponse resp)
|
||||
{
|
||||
super();
|
||||
_delegate = new JettyHttpExchangeDelegate(jaxWsContext,req,resp);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.http.spi.JettyExchange#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return _delegate.hashCode();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.http.spi.JettyExchange#getRequestHeaders()
|
||||
*/
|
||||
@Override
|
||||
public Headers getRequestHeaders()
|
||||
{
|
||||
return _delegate.getRequestHeaders();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.http.spi.JettyExchange#getResponseHeaders()
|
||||
*/
|
||||
@Override
|
||||
public Headers getResponseHeaders()
|
||||
{
|
||||
return _delegate.getResponseHeaders();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.http.spi.JettyExchange#getRequestURI()
|
||||
*/
|
||||
@Override
|
||||
public URI getRequestURI()
|
||||
{
|
||||
return _delegate.getRequestURI();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.http.spi.JettyExchange#getRequestMethod()
|
||||
*/
|
||||
@Override
|
||||
public String getRequestMethod()
|
||||
{
|
||||
return _delegate.getRequestMethod();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.http.spi.JettyExchange#getHttpContext()
|
||||
*/
|
||||
@Override
|
||||
public HttpContext getHttpContext()
|
||||
{
|
||||
return _delegate.getHttpContext();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.http.spi.JettyExchange#close()
|
||||
*/
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
_delegate.close();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.http.spi.JettyExchange#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
return _delegate.equals(obj);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.http.spi.JettyExchange#getRequestBody()
|
||||
*/
|
||||
@Override
|
||||
public InputStream getRequestBody()
|
||||
{
|
||||
return _delegate.getRequestBody();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.http.spi.JettyExchange#getResponseBody()
|
||||
*/
|
||||
@Override
|
||||
public OutputStream getResponseBody()
|
||||
{
|
||||
return _delegate.getResponseBody();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.http.spi.JettyExchange#sendResponseHeaders(int, long)
|
||||
*/
|
||||
@Override
|
||||
public void sendResponseHeaders(int rCode, long responseLength) throws IOException
|
||||
{
|
||||
_delegate.sendResponseHeaders(rCode,responseLength);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.http.spi.JettyExchange#getRemoteAddress()
|
||||
*/
|
||||
@Override
|
||||
public InetSocketAddress getRemoteAddress()
|
||||
{
|
||||
return _delegate.getRemoteAddress();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.http.spi.JettyExchange#getResponseCode()
|
||||
*/
|
||||
@Override
|
||||
public int getResponseCode()
|
||||
{
|
||||
return _delegate.getResponseCode();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.http.spi.JettyExchange#getLocalAddress()
|
||||
*/
|
||||
@Override
|
||||
public InetSocketAddress getLocalAddress()
|
||||
{
|
||||
return _delegate.getLocalAddress();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.http.spi.JettyExchange#getProtocol()
|
||||
*/
|
||||
@Override
|
||||
public String getProtocol()
|
||||
{
|
||||
return _delegate.getProtocol();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.http.spi.JettyExchange#getAttribute(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public Object getAttribute(String name)
|
||||
{
|
||||
return _delegate.getAttribute(name);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.http.spi.JettyExchange#setAttribute(java.lang.String, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public void setAttribute(String name, Object value)
|
||||
{
|
||||
_delegate.setAttribute(name,value);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.http.spi.JettyExchange#setStreams(java.io.InputStream, java.io.OutputStream)
|
||||
*/
|
||||
@Override
|
||||
public void setStreams(InputStream i, OutputStream o)
|
||||
{
|
||||
_delegate.setStreams(i,o);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.http.spi.JettyExchange#getPrincipal()
|
||||
*/
|
||||
@Override
|
||||
public HttpPrincipal getPrincipal()
|
||||
{
|
||||
return _delegate.getPrincipal();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.http.spi.JettyExchange#setPrincipal(com.sun.net.httpserver.HttpPrincipal)
|
||||
*/
|
||||
public void setPrincipal(HttpPrincipal principal)
|
||||
{
|
||||
_delegate.setPrincipal(principal);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.http.spi.JettyExchange#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return _delegate.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,228 @@
|
|||
package org.eclipse.jetty.http.spi;
|
||||
|
||||
//========================================================================
|
||||
//Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd.
|
||||
//------------------------------------------------------------------------
|
||||
//All rights reserved. This program and the accompanying materials
|
||||
//are made available under the terms of the Eclipse Public License v1.0
|
||||
//and Apache License v2.0 which accompanies this distribution.
|
||||
//The Eclipse Public License is available at
|
||||
//http://www.eclipse.org/legal/epl-v10.html
|
||||
//The Apache License v2.0 is available at
|
||||
//http://www.opensource.org/licenses/apache2.0.php
|
||||
//You may elect to redistribute this code under either of these licenses.
|
||||
//========================================================================
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.sun.net.httpserver.Headers;
|
||||
import com.sun.net.httpserver.HttpContext;
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import com.sun.net.httpserver.HttpPrincipal;
|
||||
|
||||
/**
|
||||
* Jetty implementation of {@link com.sun.net.httpserver.HttpExchange}
|
||||
*/
|
||||
public class JettyHttpExchangeDelegate extends HttpExchange
|
||||
{
|
||||
|
||||
private HttpContext _httpContext;
|
||||
|
||||
private HttpServletRequest _req;
|
||||
|
||||
private HttpServletResponse _resp;
|
||||
|
||||
private Headers _responseHeaders = new Headers();
|
||||
|
||||
private int _responseCode = 0;
|
||||
|
||||
private InputStream _is;
|
||||
|
||||
private OutputStream _os;
|
||||
|
||||
private HttpPrincipal _httpPrincipal;
|
||||
|
||||
JettyHttpExchangeDelegate(HttpContext jaxWsContext, HttpServletRequest req, HttpServletResponse resp)
|
||||
{
|
||||
this._httpContext = jaxWsContext;
|
||||
this._req = req;
|
||||
this._resp = resp;
|
||||
try
|
||||
{
|
||||
this._is = req.getInputStream();
|
||||
this._os = resp.getOutputStream();
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Headers getRequestHeaders()
|
||||
{
|
||||
Headers headers = new Headers();
|
||||
Enumeration<?> en = _req.getHeaderNames();
|
||||
while (en.hasMoreElements())
|
||||
{
|
||||
String name = (String)en.nextElement();
|
||||
Enumeration<?> en2 = _req.getHeaders(name);
|
||||
while (en2.hasMoreElements())
|
||||
{
|
||||
String value = (String)en2.nextElement();
|
||||
headers.add(name,value);
|
||||
}
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Headers getResponseHeaders()
|
||||
{
|
||||
return _responseHeaders;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI getRequestURI()
|
||||
{
|
||||
try
|
||||
{
|
||||
String uriAsString = _req.getRequestURI();
|
||||
if (_req.getQueryString() != null)
|
||||
{
|
||||
uriAsString += "?" + _req.getQueryString();
|
||||
}
|
||||
|
||||
return new URI(uriAsString);
|
||||
}
|
||||
catch (URISyntaxException ex)
|
||||
{
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRequestMethod()
|
||||
{
|
||||
return _req.getMethod();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpContext getHttpContext()
|
||||
{
|
||||
return _httpContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
try
|
||||
{
|
||||
_resp.getOutputStream().close();
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getRequestBody()
|
||||
{
|
||||
return _is;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream getResponseBody()
|
||||
{
|
||||
return _os;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendResponseHeaders(int rCode, long responseLength) throws IOException
|
||||
{
|
||||
this._responseCode = rCode;
|
||||
|
||||
for (Map.Entry<String, List<String>> stringListEntry : _responseHeaders.entrySet())
|
||||
{
|
||||
String name = stringListEntry.getKey();
|
||||
List<String> values = stringListEntry.getValue();
|
||||
|
||||
for (String value : values)
|
||||
{
|
||||
_resp.setHeader(name,value);
|
||||
}
|
||||
}
|
||||
if (responseLength > 0)
|
||||
{
|
||||
_resp.setHeader("content-length","" + responseLength);
|
||||
}
|
||||
_resp.setStatus(rCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress getRemoteAddress()
|
||||
{
|
||||
return new InetSocketAddress(_req.getRemoteAddr(),_req.getRemotePort());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getResponseCode()
|
||||
{
|
||||
return _responseCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress getLocalAddress()
|
||||
{
|
||||
return new InetSocketAddress(_req.getLocalAddr(),_req.getLocalPort());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProtocol()
|
||||
{
|
||||
return _req.getProtocol();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAttribute(String name)
|
||||
{
|
||||
return _req.getAttribute(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(String name, Object value)
|
||||
{
|
||||
_req.setAttribute(name,value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStreams(InputStream i, OutputStream o)
|
||||
{
|
||||
_is = i;
|
||||
_os = o;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpPrincipal getPrincipal()
|
||||
{
|
||||
return _httpPrincipal;
|
||||
}
|
||||
|
||||
public void setPrincipal(HttpPrincipal principal)
|
||||
{
|
||||
this._httpPrincipal = principal;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,179 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.http.spi;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URI;
|
||||
|
||||
import javax.net.ssl.SSLSession;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.sun.net.httpserver.Headers;
|
||||
import com.sun.net.httpserver.HttpContext;
|
||||
import com.sun.net.httpserver.HttpPrincipal;
|
||||
import com.sun.net.httpserver.HttpsExchange;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
*/
|
||||
public class JettyHttpsExchange extends HttpsExchange implements JettyExchange
|
||||
{
|
||||
private JettyHttpExchangeDelegate _delegate;
|
||||
|
||||
public JettyHttpsExchange(HttpContext jaxWsContext, HttpServletRequest req, HttpServletResponse resp)
|
||||
{
|
||||
super();
|
||||
_delegate = new JettyHttpExchangeDelegate(jaxWsContext,req,resp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return _delegate.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Headers getRequestHeaders()
|
||||
{
|
||||
return _delegate.getRequestHeaders();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Headers getResponseHeaders()
|
||||
{
|
||||
return _delegate.getResponseHeaders();
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI getRequestURI()
|
||||
{
|
||||
return _delegate.getRequestURI();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRequestMethod()
|
||||
{
|
||||
return _delegate.getRequestMethod();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpContext getHttpContext()
|
||||
{
|
||||
return _delegate.getHttpContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
_delegate.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
return _delegate.equals(obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getRequestBody()
|
||||
{
|
||||
return _delegate.getRequestBody();
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream getResponseBody()
|
||||
{
|
||||
return _delegate.getResponseBody();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendResponseHeaders(int rCode, long responseLength) throws IOException
|
||||
{
|
||||
_delegate.sendResponseHeaders(rCode,responseLength);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress getRemoteAddress()
|
||||
{
|
||||
return _delegate.getRemoteAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getResponseCode()
|
||||
{
|
||||
return _delegate.getResponseCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress getLocalAddress()
|
||||
{
|
||||
return _delegate.getLocalAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProtocol()
|
||||
{
|
||||
return _delegate.getProtocol();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAttribute(String name)
|
||||
{
|
||||
return _delegate.getAttribute(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(String name, Object value)
|
||||
{
|
||||
_delegate.setAttribute(name,value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStreams(InputStream i, OutputStream o)
|
||||
{
|
||||
_delegate.setStreams(i,o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpPrincipal getPrincipal()
|
||||
{
|
||||
return _delegate.getPrincipal();
|
||||
}
|
||||
|
||||
public void setPrincipal(HttpPrincipal principal)
|
||||
{
|
||||
_delegate.setPrincipal(principal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return _delegate.toString();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see com.sun.net.httpserver.HttpsExchange#getSSLSession()
|
||||
*/
|
||||
@Override
|
||||
public SSLSession getSSLSession()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
package org.eclipse.jetty.http.spi;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.sun.net.httpserver.BasicAuthenticator;
|
||||
import com.sun.net.httpserver.Headers;
|
||||
import com.sun.net.httpserver.HttpContext;
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import com.sun.net.httpserver.HttpHandler;
|
||||
import com.sun.net.httpserver.HttpServer;
|
||||
|
||||
|
||||
public class TestSPIServer
|
||||
{
|
||||
public static void main(String[] args) throws Exception
|
||||
{
|
||||
String host="localhost";
|
||||
int port = 8080;
|
||||
|
||||
HttpServer server = new JettyHttpServerProvider().createHttpServer(new
|
||||
InetSocketAddress(host, port), 10);
|
||||
server.start();
|
||||
|
||||
final HttpContext httpContext = server.createContext("/",
|
||||
new HttpHandler()
|
||||
{
|
||||
|
||||
@Override
|
||||
public void handle(HttpExchange exchange) throws IOException
|
||||
{
|
||||
Headers responseHeaders = exchange.getResponseHeaders();
|
||||
responseHeaders.set("Content-Type","text/plain");
|
||||
exchange.sendResponseHeaders(200,0);
|
||||
|
||||
OutputStream responseBody = exchange.getResponseBody();
|
||||
Headers requestHeaders = exchange.getRequestHeaders();
|
||||
Set<String> keySet = requestHeaders.keySet();
|
||||
Iterator<String> iter = keySet.iterator();
|
||||
while (iter.hasNext())
|
||||
{
|
||||
String key = iter.next();
|
||||
List values = requestHeaders.get(key);
|
||||
String s = key + " = " + values.toString() + "\n";
|
||||
responseBody.write(s.getBytes());
|
||||
}
|
||||
responseBody.close();
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
httpContext.setAuthenticator(new BasicAuthenticator("Test")
|
||||
{
|
||||
@Override
|
||||
public boolean checkCredentials(String username, String password)
|
||||
{
|
||||
if ("username".equals(username) && password.equals("password"))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Thread.sleep(10000000);
|
||||
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -35,11 +35,11 @@ public abstract class AbstractConnection implements Connection
|
|||
return _endp;
|
||||
}
|
||||
|
||||
public void onIdleExpired()
|
||||
public void onIdleExpired(long idleForMs)
|
||||
{
|
||||
try
|
||||
{
|
||||
LOG.debug("onIdleExpired {} {}",this,_endp);
|
||||
LOG.debug("onIdleExpired {}ms {} {}",idleForMs,this,_endp);
|
||||
if (_endp.isInputShutdown() || _endp.isOutputShutdown())
|
||||
_endp.close();
|
||||
else
|
||||
|
@ -62,12 +62,6 @@ public abstract class AbstractConnection implements Connection
|
|||
|
||||
public String toString()
|
||||
{
|
||||
return String.format("%s@%x//%s:%d<->%s:%d",
|
||||
getClass().getSimpleName(),
|
||||
hashCode(),
|
||||
_endp.getLocalAddr(),
|
||||
_endp.getLocalPort(),
|
||||
_endp.getRemoteAddr(),
|
||||
_endp.getRemotePort());
|
||||
return String.format("%s@%x", getClass().getSimpleName(), hashCode());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,8 +35,9 @@ public interface AsyncEndPoint extends ConnectedEndPoint
|
|||
/** Callback when idle.
|
||||
* <p>An endpoint is idle if there has been no IO activity for
|
||||
* {@link #getMaxIdleTime()} and {@link #isCheckForIdle()} is true.
|
||||
* @param idleForMs TODO
|
||||
*/
|
||||
public void onIdleExpired();
|
||||
public void onIdleExpired(long idleForMs);
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Set if the endpoint should be checked for idleness
|
||||
|
|
|
@ -54,6 +54,7 @@ public interface Connection
|
|||
|
||||
/**
|
||||
* Called when the connection idle timeout expires
|
||||
* @param idleForMs TODO
|
||||
*/
|
||||
void onIdleExpired();
|
||||
void onIdleExpired(long idleForMs);
|
||||
}
|
||||
|
|
|
@ -35,7 +35,8 @@ public class UncheckedPrintWriter extends PrintWriter
|
|||
private static final Logger LOG = Log.getLogger(UncheckedPrintWriter.class);
|
||||
|
||||
private boolean _autoFlush = false;
|
||||
private boolean _throwUnchecked=true;
|
||||
private IOException _ioException;
|
||||
private boolean _isClosed = false;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
|
@ -102,38 +103,45 @@ public class UncheckedPrintWriter extends PrintWriter
|
|||
this(new BufferedWriter(new OutputStreamWriter(out)),autoFlush);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
private void setError(Throwable th)
|
||||
public boolean checkError()
|
||||
{
|
||||
setError();
|
||||
if (_throwUnchecked)
|
||||
throw new RuntimeIOException(th);
|
||||
LOG.debug(th);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Are unchecked exceptions thrown.
|
||||
* @return True if {@link RuntimeIOException}s are thrown
|
||||
*/
|
||||
public boolean isUncheckedPrintWriter()
|
||||
{
|
||||
return _throwUnchecked;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Set if unchecked exceptions are thrown
|
||||
* @param uncheckedPrintWriter True if {@link RuntimeIOException}s are to be thrown
|
||||
*/
|
||||
public void setUncheckedPrintWriter(boolean uncheckedPrintWriter)
|
||||
{
|
||||
_throwUnchecked = uncheckedPrintWriter;
|
||||
return _ioException!=null || super.checkError();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
private void setError(Throwable th)
|
||||
{
|
||||
|
||||
super.setError();
|
||||
|
||||
if (th instanceof IOException)
|
||||
_ioException=(IOException)th;
|
||||
else
|
||||
{
|
||||
_ioException=new IOException(String.valueOf(th));
|
||||
_ioException.initCause(th);
|
||||
}
|
||||
|
||||
LOG.debug(th);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void setError()
|
||||
{
|
||||
setError(new IOException());
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Check to make sure that the stream has not been closed */
|
||||
private void isOpen() throws IOException
|
||||
{
|
||||
if (super.out == null)
|
||||
{
|
||||
if (_ioException!=null)
|
||||
throw new RuntimeIOException(_ioException);
|
||||
|
||||
if (_isClosed)
|
||||
throw new IOException("Stream closed");
|
||||
}
|
||||
|
||||
|
@ -170,6 +178,7 @@ public class UncheckedPrintWriter extends PrintWriter
|
|||
synchronized (lock)
|
||||
{
|
||||
out.close();
|
||||
_isClosed = true;
|
||||
}
|
||||
}
|
||||
catch (IOException ex)
|
||||
|
@ -248,7 +257,7 @@ public class UncheckedPrintWriter extends PrintWriter
|
|||
*/
|
||||
@Override
|
||||
public void write(char buf[])
|
||||
{
|
||||
{
|
||||
this.write(buf,0,buf.length);
|
||||
}
|
||||
|
||||
|
|
|
@ -262,35 +262,41 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
|
|||
{
|
||||
_idleTimestamp=check?System.currentTimeMillis():0;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public boolean isCheckForIdle()
|
||||
{
|
||||
return _idleTimestamp!=0;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void notIdle()
|
||||
{
|
||||
if (_idleTimestamp!=0)
|
||||
_idleTimestamp=System.currentTimeMillis();
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void checkIdleTimestamp(long now)
|
||||
{
|
||||
long idleTimestamp=_idleTimestamp;
|
||||
if (!getChannel().isOpen() || idleTimestamp!=0 && _maxIdleTime>0 && now>(idleTimestamp+_maxIdleTime))
|
||||
|
||||
if (idleTimestamp!=0 && _maxIdleTime>0)
|
||||
{
|
||||
onIdleExpired();
|
||||
_idleTimestamp=now;
|
||||
long idleForMs=now-idleTimestamp;
|
||||
|
||||
if (idleForMs>_maxIdleTime)
|
||||
{
|
||||
onIdleExpired(idleForMs);
|
||||
_idleTimestamp=now;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void onIdleExpired()
|
||||
public void onIdleExpired(long idleForMs)
|
||||
{
|
||||
_connection.onIdleExpired();
|
||||
_connection.onIdleExpired(idleForMs);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -704,24 +710,43 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
|
|||
@Override
|
||||
public String toString()
|
||||
{
|
||||
synchronized(this)
|
||||
// Do NOT use synchronized (this)
|
||||
// because it's very easy to deadlock when debugging is enabled.
|
||||
// We do a best effort to print the right toString() and that's it.
|
||||
SelectionKey key = _key;
|
||||
String keyString = "";
|
||||
if (key != null)
|
||||
{
|
||||
return String.format("SCEP@%x{%s->%s,d=%b,open=%b,ishut=%b,oshut=%b,rb=%b,wb=%b,w=%b,i=%d%s%s%s}",
|
||||
hashCode(),
|
||||
_socket.getRemoteSocketAddress(),
|
||||
_socket.getLocalSocketAddress(),
|
||||
_dispatched,
|
||||
isOpen(),
|
||||
isInputShutdown(),
|
||||
isOutputShutdown(),
|
||||
_readBlocked,
|
||||
_writeBlocked,
|
||||
_writable,
|
||||
_interestOps,
|
||||
_key != null && _key.isValid() ? "" : "!",
|
||||
_key != null && _key.isValid() && _key.isReadable() ? "r" : "",
|
||||
_key != null && _key.isValid() && _key.isWritable() ? "w" : "");
|
||||
if (key.isValid())
|
||||
{
|
||||
if (key.isReadable())
|
||||
keyString += "r";
|
||||
if (key.isWritable())
|
||||
keyString += "w";
|
||||
}
|
||||
else
|
||||
{
|
||||
keyString += "!";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
keyString += "-";
|
||||
}
|
||||
return String.format("SCEP@%x{l(%s)<->r(%s),d=%b,open=%b,ishut=%b,oshut=%b,rb=%b,wb=%b,w=%b,i=%d%s}-{%s}",
|
||||
hashCode(),
|
||||
_socket.getRemoteSocketAddress(),
|
||||
_socket.getLocalSocketAddress(),
|
||||
_dispatched,
|
||||
isOpen(),
|
||||
isInputShutdown(),
|
||||
isOutputShutdown(),
|
||||
_readBlocked,
|
||||
_writeBlocked,
|
||||
_writable,
|
||||
_interestOps,
|
||||
keyString,
|
||||
_connection);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
|
|
@ -16,7 +16,6 @@ package org.eclipse.jetty.io.nio;
|
|||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import javax.net.ssl.SSLEngine;
|
||||
import javax.net.ssl.SSLEngineResult;
|
||||
import javax.net.ssl.SSLEngineResult.HandshakeStatus;
|
||||
|
@ -51,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;
|
||||
|
@ -94,6 +93,13 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
_engine=engine;
|
||||
_session=_engine.getSession();
|
||||
_aEndp=(AsyncEndPoint)endp;
|
||||
_sslEndPoint = newSslEndPoint();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected SslEndPoint newSslEndPoint()
|
||||
{
|
||||
return new SslEndPoint();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -191,9 +197,10 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
_connection=next;
|
||||
progress=true;
|
||||
}
|
||||
// TODO: consider moving here hasProgressed() - it's only used in SSL
|
||||
}
|
||||
|
||||
LOG.debug("{} handle {} progress=",_session,this, progress);
|
||||
LOG.debug("{} handle {} progress={}", _session, this, progress);
|
||||
}
|
||||
}
|
||||
finally
|
||||
|
@ -238,16 +245,20 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public void onIdleExpired()
|
||||
public void onIdleExpired(long idleForMs)
|
||||
{
|
||||
try
|
||||
{
|
||||
_sslEndPoint.shutdownOutput();
|
||||
LOG.debug("onIdleExpired {}ms on {}",idleForMs,this);
|
||||
if (_endp.isOutputShutdown())
|
||||
_sslEndPoint.close();
|
||||
else
|
||||
_sslEndPoint.shutdownOutput();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
LOG.warn(e);
|
||||
super.onIdleExpired();
|
||||
super.onIdleExpired(idleForMs);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -307,12 +318,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())
|
||||
|
@ -322,13 +336,13 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
|
||||
case NOT_HANDSHAKING:
|
||||
{
|
||||
// Try wrapping some application data
|
||||
if (toFlush.hasContent() && _outbound.space()>0 && wrap(toFlush))
|
||||
progress=true;
|
||||
|
||||
// Try unwrapping some application data
|
||||
if (toFill.space()>0 && _inbound.hasContent() && unwrap(toFill))
|
||||
progress=true;
|
||||
|
||||
// Try wrapping some application data
|
||||
if (toFlush.hasContent() && _outbound.space()>0 && wrap(toFlush))
|
||||
progress=true;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -381,13 +395,17 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
}
|
||||
|
||||
// pass on ishut/oshut state
|
||||
if (!_inbound.hasContent() && _endp.isInputShutdown())
|
||||
if (_endp.isOpen() && _endp.isInputShutdown() && !_inbound.hasContent())
|
||||
_engine.closeInbound();
|
||||
if (!_outbound.hasContent() && _engine.isOutboundDone())
|
||||
|
||||
if (_endp.isOpen() && _engine.isOutboundDone() && !_outbound.hasContent())
|
||||
_endp.shutdownOutput();
|
||||
|
||||
some_progress|=progress;
|
||||
}
|
||||
|
||||
if (toFill.hasContent())
|
||||
_aEndp.asyncDispatch();
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -430,7 +448,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;
|
||||
}
|
||||
|
@ -506,10 +524,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
|
||||
|
@ -568,13 +584,10 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
return _sslEndPoint;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public String toString()
|
||||
{
|
||||
Buffer i=_inbound;
|
||||
Buffer o=_outbound;
|
||||
Buffer u=_unwrapBuf;
|
||||
|
||||
return super.toString()+"|"+_engine.getHandshakeStatus()+" i/u/o="+(i==null?0:i.length())+"/"+(u==null?0:u.length())+"/"+(o==null?0:o.length());
|
||||
return String.format("%s %s", super.toString(), _sslEndPoint);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -585,6 +598,11 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
{
|
||||
return _engine;
|
||||
}
|
||||
|
||||
public AsyncEndPoint getEndpoint()
|
||||
{
|
||||
return _aEndp;
|
||||
}
|
||||
|
||||
public void shutdownOutput() throws IOException
|
||||
{
|
||||
|
@ -631,7 +649,7 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
public int fill(Buffer buffer) throws IOException
|
||||
{
|
||||
int size=buffer.length();
|
||||
process(buffer,null);
|
||||
process(buffer, null);
|
||||
|
||||
int filled=buffer.length()-size;
|
||||
|
||||
|
@ -691,7 +709,7 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
|
||||
public void flush() throws IOException
|
||||
{
|
||||
process(null,null);
|
||||
process(null, null);
|
||||
}
|
||||
|
||||
public void asyncDispatch()
|
||||
|
@ -704,9 +722,9 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
_aEndp.scheduleWrite();
|
||||
}
|
||||
|
||||
public void onIdleExpired()
|
||||
public void onIdleExpired(long idleForMs)
|
||||
{
|
||||
_aEndp.onIdleExpired();
|
||||
_aEndp.onIdleExpired(idleForMs);
|
||||
}
|
||||
|
||||
public void setCheckForIdle(boolean check)
|
||||
|
@ -796,20 +814,21 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
|
||||
public String toString()
|
||||
{
|
||||
int i;
|
||||
int o;
|
||||
int u;
|
||||
synchronized(SslConnection.this)
|
||||
{
|
||||
i=_inbound==null?-1:_inbound.length();
|
||||
o=_outbound==null?-1:_outbound.length();
|
||||
u=_unwrapBuf==null?-1:_unwrapBuf.length();
|
||||
}
|
||||
return String.format("SSL:%s %s i/u/o=%d/%d/%d ishut=%b oshut=%b",
|
||||
_endp,
|
||||
// Do NOT use synchronized (SslConnection.this)
|
||||
// because it's very easy to deadlock when debugging is enabled.
|
||||
// We do a best effort to print the right toString() and that's it.
|
||||
Buffer inbound = _inbound;
|
||||
Buffer outbound = _outbound;
|
||||
Buffer unwrap = _unwrapBuf;
|
||||
int i = inbound == null? -1 : inbound.length();
|
||||
int o = outbound == null ? -1 : outbound.length();
|
||||
int u = unwrap == null ? -1 : unwrap.length();
|
||||
return String.format("SSL %s i/o/u=%d/%d/%d ishut=%b oshut=%b {%s}",
|
||||
_engine.getHandshakeStatus(),
|
||||
i, u, o,
|
||||
_ishut, _oshut);
|
||||
i, o, u,
|
||||
_ishut, _oshut,
|
||||
_connection);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -271,7 +271,8 @@ public class ServerInstanceWrapper {
|
|||
try
|
||||
{
|
||||
// Execute a Jetty configuration file
|
||||
is = jettyConfiguration.openStream();
|
||||
Resource r = Resource.newResource(jettyConfiguration);
|
||||
is = r.getInputStream();
|
||||
XmlConfiguration config = new XmlConfiguration(is);
|
||||
config.getIdMap().putAll(id_map);
|
||||
|
||||
|
|
|
@ -376,7 +376,8 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
|
|||
URL contextURL = contributor.getEntry(contextFileRelativePath);
|
||||
if (contextURL != null)
|
||||
{
|
||||
return registerContext(contributor,contextFileRelativePath,contextURL.openStream(),extraClasspath,overrideBundleInstallLocation,requireTldBundle,handler);
|
||||
Resource r = Resource.newResource(contextURL);
|
||||
return registerContext(contributor,contextFileRelativePath,r.getInputStream(),extraClasspath,overrideBundleInstallLocation,requireTldBundle,handler);
|
||||
}
|
||||
throw new IllegalArgumentException("Could not find the context " + "file " + contextFileRelativePath + " for the bundle "
|
||||
+ contributor.getSymbolicName() + (overrideBundleInstallLocation != null?" using the install location " + overrideBundleInstallLocation:""));
|
||||
|
|
|
@ -21,6 +21,7 @@ import java.security.KeyStore;
|
|||
|
||||
import org.eclipse.jetty.policy.PolicyContext;
|
||||
import org.eclipse.jetty.policy.PolicyException;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
|
||||
public class KeystoreEntry extends AbstractEntry
|
||||
{
|
||||
|
@ -49,7 +50,8 @@ public class KeystoreEntry extends AbstractEntry
|
|||
keystore = KeyStore.getInstance( type );
|
||||
|
||||
URL keyStoreLocation = new URL ( url );
|
||||
InputStream istream = keyStoreLocation.openStream();
|
||||
Resource r = Resource.newResource(keyStoreLocation);
|
||||
InputStream istream = r.getInputStream();
|
||||
|
||||
keystore.load( istream, null );
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@ package org.eclipse.jetty.server;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
import javax.servlet.ServletInputStream;
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
@ -356,7 +355,27 @@ public abstract class AbstractHttpConnection extends AbstractConnection
|
|||
if (_writer==null)
|
||||
{
|
||||
_writer=new OutputWriter();
|
||||
_printWriter=new UncheckedPrintWriter(_writer);
|
||||
if (_server.isUncheckedPrintWriter())
|
||||
_printWriter=new UncheckedPrintWriter(_writer);
|
||||
else
|
||||
_printWriter = new PrintWriter(_writer)
|
||||
{
|
||||
public void close()
|
||||
{
|
||||
synchronized (lock)
|
||||
{
|
||||
try
|
||||
{
|
||||
out.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
setError();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
_writer.setCharacterEncoding(encoding);
|
||||
return _printWriter;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -54,6 +54,10 @@ public class AsyncHttpConnection extends AbstractHttpConnection implements Async
|
|||
try
|
||||
{
|
||||
setCurrentConnection(this);
|
||||
|
||||
// don't check for idle while dispatched (unless blocking IO is done).
|
||||
_asyncEndp.setCheckForIdle(false);
|
||||
|
||||
|
||||
// While progress and the connection has not changed
|
||||
while (progress && connection==this)
|
||||
|
@ -62,8 +66,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;
|
||||
|
@ -130,10 +137,16 @@ public class AsyncHttpConnection extends AbstractHttpConnection implements Async
|
|||
finally
|
||||
{
|
||||
setCurrentConnection(null);
|
||||
|
||||
// If we are not suspended
|
||||
if (!_request.isAsyncStarted())
|
||||
{
|
||||
// return buffers
|
||||
_parser.returnBuffers();
|
||||
_generator.returnBuffers();
|
||||
|
||||
// resuming checking for idle
|
||||
_asyncEndp.setCheckForIdle(true);
|
||||
}
|
||||
|
||||
// Safety net to catch spinning
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.server;
|
||||
|
@ -16,7 +16,6 @@ package org.eclipse.jetty.server;
|
|||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Enumeration;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
@ -56,14 +55,14 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
private static final String __version;
|
||||
static
|
||||
{
|
||||
if (Server.class.getPackage()!=null &&
|
||||
if (Server.class.getPackage()!=null &&
|
||||
"Eclipse.org - Jetty".equals(Server.class.getPackage().getImplementationVendor()) &&
|
||||
Server.class.getPackage().getImplementationVersion()!=null)
|
||||
__version=Server.class.getPackage().getImplementationVersion();
|
||||
else
|
||||
__version=System.getProperty("jetty.version","7.x.y-SNAPSHOT");
|
||||
}
|
||||
|
||||
|
||||
private final Container _container=new Container();
|
||||
private final AttributesMap _attributes = new AttributesMap();
|
||||
private ThreadPool _threadPool;
|
||||
|
@ -76,14 +75,15 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
private int _maxCookieVersion=1;
|
||||
private boolean _dumpAfterStart=false;
|
||||
private boolean _dumpBeforeStop=false;
|
||||
|
||||
private boolean _uncheckedPrintWriter=false;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public Server()
|
||||
{
|
||||
setServer(this);
|
||||
setServer(this);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Convenience constructor
|
||||
* Creates server and a {@link SelectChannelConnector} at the passed port.
|
||||
|
@ -96,7 +96,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
connector.setPort(port);
|
||||
setConnectors(new Connector[]{connector});
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Convenience constructor
|
||||
* Creates server and a {@link SelectChannelConnector} at the passed address.
|
||||
|
@ -117,7 +117,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
{
|
||||
return __version;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return Returns the container.
|
||||
|
@ -132,7 +132,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
{
|
||||
return _stopAtShutdown;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void setStopAtShutdown(boolean stop)
|
||||
{
|
||||
|
@ -142,7 +142,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
else
|
||||
ShutdownThread.deregister(this);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return Returns the connectors.
|
||||
|
@ -160,7 +160,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Conveniance method which calls {@link #getConnectors()} and {@link #setConnectors(Connector[])} to
|
||||
* Conveniance method which calls {@link #getConnectors()} and {@link #setConnectors(Connector[])} to
|
||||
* remove a connector.
|
||||
* @param connector The connector to remove.
|
||||
*/
|
||||
|
@ -180,7 +180,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
for (int i=0;i<connectors.length;i++)
|
||||
connectors[i].setServer(this);
|
||||
}
|
||||
|
||||
|
||||
_container.update(this, _connectors, connectors, "connector");
|
||||
_connectors = connectors;
|
||||
}
|
||||
|
@ -193,7 +193,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
{
|
||||
return _threadPool;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @param threadPool The threadPool to set.
|
||||
|
@ -239,32 +239,32 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
{
|
||||
_dumpBeforeStop = dumpBeforeStop;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
protected void doStart() throws Exception
|
||||
{
|
||||
if (getStopAtShutdown())
|
||||
ShutdownThread.register(this);
|
||||
|
||||
|
||||
LOG.info("jetty-"+__version);
|
||||
HttpGenerator.setServerVersion(__version);
|
||||
MultiException mex=new MultiException();
|
||||
|
||||
|
||||
if (_threadPool==null)
|
||||
setThreadPool(new QueuedThreadPool());
|
||||
|
||||
try
|
||||
{
|
||||
super.doStart();
|
||||
}
|
||||
catch(Throwable e)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
super.doStart();
|
||||
}
|
||||
catch(Throwable e)
|
||||
{
|
||||
mex.add(e);
|
||||
}
|
||||
|
||||
|
||||
if (_connectors!=null)
|
||||
{
|
||||
for (int i=0;i<_connectors.length;i++)
|
||||
|
@ -276,10 +276,10 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (isDumpAfterStart())
|
||||
dumpStdErr();
|
||||
|
||||
|
||||
mex.ifExceptionThrow();
|
||||
}
|
||||
|
||||
|
@ -289,9 +289,9 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
{
|
||||
if (isDumpBeforeStop())
|
||||
dumpStdErr();
|
||||
|
||||
|
||||
MultiException mex=new MultiException();
|
||||
|
||||
|
||||
if (_graceful>0)
|
||||
{
|
||||
if (_connectors!=null)
|
||||
|
@ -302,7 +302,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
try{_connectors[i].close();}catch(Throwable e){mex.add(e);}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Handler[] contexts = getChildHandlersByClass(Graceful.class);
|
||||
for (int c=0;c<contexts.length;c++)
|
||||
{
|
||||
|
@ -312,7 +312,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
}
|
||||
Thread.sleep(_graceful);
|
||||
}
|
||||
|
||||
|
||||
if (_connectors!=null)
|
||||
{
|
||||
for (int i=_connectors.length;i-->0;)
|
||||
|
@ -320,7 +320,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
}
|
||||
|
||||
try {super.doStop(); } catch(Throwable e) { mex.add(e);}
|
||||
|
||||
|
||||
mex.ifExceptionThrow();
|
||||
|
||||
if (getStopAtShutdown())
|
||||
|
@ -338,7 +338,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
final String target=connection.getRequest().getPathInfo();
|
||||
final Request request=connection.getRequest();
|
||||
final Response response=connection.getResponse();
|
||||
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
LOG.debug("REQUEST "+target+" on "+connection);
|
||||
|
@ -348,7 +348,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
else
|
||||
handle(target, request, request, response);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* Handle a request from a connection.
|
||||
* Called to handle a request on the connection when either the header has been received,
|
||||
|
@ -377,7 +377,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
baseRequest.setRequestURI(null);
|
||||
baseRequest.setPathInfo(baseRequest.getRequestURI());
|
||||
if (uri.getQuery()!=null)
|
||||
baseRequest.mergeQueryString(uri.getQuery());
|
||||
baseRequest.mergeQueryString(uri.getQuery());
|
||||
}
|
||||
|
||||
final String target=baseRequest.getPathInfo();
|
||||
|
@ -394,10 +394,10 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
handle(target, baseRequest, request, response);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void join() throws InterruptedException
|
||||
public void join() throws InterruptedException
|
||||
{
|
||||
getThreadPool().join();
|
||||
}
|
||||
|
@ -489,8 +489,8 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
/**
|
||||
* Add an associated bean.
|
||||
* The bean will be added to the servers {@link Container}
|
||||
* and if it is a {@link LifeCycle} instance, it will be
|
||||
* started/stopped along with the Server. Any beans that are also
|
||||
* and if it is a {@link LifeCycle} instance, it will be
|
||||
* started/stopped along with the Server. Any beans that are also
|
||||
* {@link Destroyable}, will be destroyed with the server.
|
||||
* @param o the bean object to add
|
||||
*/
|
||||
|
@ -506,7 +506,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
}
|
||||
|
||||
/**
|
||||
* Remove a LifeCycle object to be started/stopped
|
||||
* Remove a LifeCycle object to be started/stopped
|
||||
* along with the Server
|
||||
* @deprecated Use {@link #removeBean(Object)}
|
||||
*/
|
||||
|
@ -515,7 +515,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
{
|
||||
removeBean(c);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Remove an associated bean.
|
||||
|
@ -532,7 +532,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/*
|
||||
/*
|
||||
* @see org.eclipse.util.AttributesMap#clearAttributes()
|
||||
*/
|
||||
public void clearAttributes()
|
||||
|
@ -541,7 +541,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/*
|
||||
/*
|
||||
* @see org.eclipse.util.AttributesMap#getAttribute(java.lang.String)
|
||||
*/
|
||||
public Object getAttribute(String name)
|
||||
|
@ -550,7 +550,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/*
|
||||
/*
|
||||
* @see org.eclipse.util.AttributesMap#getAttributeNames()
|
||||
*/
|
||||
public Enumeration getAttributeNames()
|
||||
|
@ -559,7 +559,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/*
|
||||
/*
|
||||
* @see org.eclipse.util.AttributesMap#removeAttribute(java.lang.String)
|
||||
*/
|
||||
public void removeAttribute(String name)
|
||||
|
@ -568,7 +568,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/*
|
||||
/*
|
||||
* @see org.eclipse.util.AttributesMap#setAttribute(java.lang.String, java.lang.Object)
|
||||
*/
|
||||
public void setAttribute(String name, Object attribute)
|
||||
|
@ -587,13 +587,13 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Set graceful shutdown timeout. If set, the internal <code>doStop()</code> method will not immediately stop the
|
||||
* Set graceful shutdown timeout. If set, the internal <code>doStop()</code> method will not immediately stop the
|
||||
* server. Instead, all {@link Connector}s will be closed so that new connections will not be accepted
|
||||
* and all handlers that implement {@link Graceful} will be put into the shutdown mode so that no new requests
|
||||
* will be accepted, but existing requests can complete. The server will then wait the configured timeout
|
||||
* will be accepted, but existing requests can complete. The server will then wait the configured timeout
|
||||
* before stopping.
|
||||
* @param timeoutMS the milliseconds to wait for existing request to complete before stopping the server.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public void setGracefulShutdown(int timeoutMS)
|
||||
{
|
||||
|
@ -612,9 +612,23 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
public void dump(Appendable out,String indent) throws IOException
|
||||
{
|
||||
dumpThis(out);
|
||||
dump(out,indent,TypeUtil.asList(getHandlers()),getBeans(),TypeUtil.asList(_connectors));
|
||||
dump(out,indent,TypeUtil.asList(getHandlers()),getBeans(),TypeUtil.asList(_connectors));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public boolean isUncheckedPrintWriter()
|
||||
{
|
||||
return _uncheckedPrintWriter;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void setUncheckedPrintWriter(boolean unchecked)
|
||||
{
|
||||
_uncheckedPrintWriter=unchecked;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* A handler that can be gracefully shutdown.
|
||||
* Called by doStop if a {@link #setGracefulShutdown} period is set.
|
||||
|
|
|
@ -667,7 +667,7 @@ public class ConnectHandler extends HandlerWrapper
|
|||
_endPoint.shutdownOutput();
|
||||
}
|
||||
|
||||
public void onIdleExpired()
|
||||
public void onIdleExpired(long idleForMs)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -834,7 +834,7 @@ public class ConnectHandler extends HandlerWrapper
|
|||
_endPoint.shutdownOutput();
|
||||
}
|
||||
|
||||
public void onIdleExpired()
|
||||
public void onIdleExpired(long idleForMs)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
|
@ -30,7 +30,6 @@ import java.util.List;
|
|||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.Servlet;
|
||||
import javax.servlet.ServletContext;
|
||||
|
@ -70,13 +69,13 @@ import org.eclipse.jetty.util.resource.Resource;
|
|||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* ContextHandler.
|
||||
*
|
||||
*
|
||||
* This handler wraps a call to handle by setting the context and servlet path, plus setting the context classloader.
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* If the context init parameter "org.eclipse.jetty.server.context.ManagedAttributes" is set to a comma separated list of names, then they are treated as
|
||||
* context attribute names, which if set as attributes are passed to the servers Container so that they may be managed with JMX.
|
||||
*
|
||||
*
|
||||
* @org.apache.xbean.XBean description="Creates a basic HTTP context"
|
||||
*/
|
||||
public class ContextHandler extends ScopedHandler implements Attributes, Server.Graceful
|
||||
|
@ -95,7 +94,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
|
|||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Get the current ServletContext implementation.
|
||||
*
|
||||
*
|
||||
* @return ServletContext implementation
|
||||
*/
|
||||
public static Context getCurrentContext()
|
||||
|
@ -244,7 +243,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
|
|||
* Set the virtual hosts for the context. Only requests that have a matching host header or fully qualified URL will be passed to that context with a
|
||||
* virtual host name. A context with no virtual host names or a null virtual host name is available to all requests that are not served by a context with a
|
||||
* matching virtual host name.
|
||||
*
|
||||
*
|
||||
* @param vhosts
|
||||
* Array of virtual hosts that this context responds to. A null host name or null/empty array means any hostname is acceptable. Host names may be
|
||||
* String representation of IP addresses. Host names may start with '*.' to wildcard one level of names.
|
||||
|
@ -265,7 +264,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
|
|||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Either set virtual hosts or add to an existing set of virtual hosts.
|
||||
*
|
||||
*
|
||||
* @param virtualHosts
|
||||
* Array of virtual hosts that this context responds to. A null host name or null/empty array means any hostname is acceptable. Host names may be
|
||||
* String representation of IP addresses. Host names may start with '*.' to wildcard one level of names.
|
||||
|
@ -287,7 +286,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
|
|||
{
|
||||
currentVirtualHosts = new ArrayList<String>();
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; i < virtualHosts.length; i++)
|
||||
{
|
||||
String normVhost = normalizeHostname(virtualHosts[i]);
|
||||
|
@ -303,7 +302,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
|
|||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Removes an array of virtual host entries, if this removes all entries the _vhosts will be set to null
|
||||
*
|
||||
*
|
||||
* @param virtualHosts
|
||||
* Array of virtual hosts that this context responds to. A null host name or null/empty array means any hostname is acceptable. Host names may be
|
||||
* String representation of IP addresses. Host names may start with '*.' to wildcard one level of names.
|
||||
|
@ -321,7 +320,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
|
|||
else
|
||||
{
|
||||
List<String> existingVirtualHosts = new ArrayList<String>(Arrays.asList(_vhosts));
|
||||
|
||||
|
||||
for (int i = 0; i < virtualHosts.length; i++)
|
||||
{
|
||||
String toRemoveVirtualHost = normalizeHostname(virtualHosts[i]);
|
||||
|
@ -330,7 +329,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
|
|||
existingVirtualHosts.remove(toRemoveVirtualHost);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (existingVirtualHosts.isEmpty())
|
||||
{
|
||||
_vhosts = null; // if we ended up removing them all, just null out _vhosts
|
||||
|
@ -341,13 +340,13 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Get the virtual hosts for the context. Only requests that have a matching host header or fully qualified URL will be passed to that context with a
|
||||
* virtual host name. A context with no virtual host names or a null virtual host name is available to all requests that are not served by a context with a
|
||||
* matching virtual host name.
|
||||
*
|
||||
*
|
||||
* @return Array of virtual hosts that this context responds to. A null host name or empty array means any hostname is acceptable. Host names may be String
|
||||
* representation of IP addresses. Host names may start with '*.' to wildcard one level of names.
|
||||
*/
|
||||
|
@ -371,9 +370,9 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
|
|||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Set the names of accepted connectors.
|
||||
*
|
||||
*
|
||||
* Names are either "host:port" or a specific configured name for a connector.
|
||||
*
|
||||
*
|
||||
* @param connectors
|
||||
* If non null, an array of connector names that this context will accept a request from.
|
||||
*/
|
||||
|
@ -425,7 +424,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
|
|||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Make best effort to extract a file classpath from the context classloader
|
||||
*
|
||||
*
|
||||
* @return Returns the classLoader.
|
||||
*/
|
||||
public String getClassPath()
|
||||
|
@ -521,7 +520,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
|
|||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Set the context event listeners.
|
||||
*
|
||||
*
|
||||
* @param eventListeners
|
||||
* the event listeners
|
||||
* @see ServletContextListener
|
||||
|
@ -559,7 +558,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
|
|||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Add a context event listeners.
|
||||
*
|
||||
*
|
||||
* @see ServletContextListener
|
||||
* @see ServletContextAttributeListener
|
||||
* @see ServletRequestListener
|
||||
|
@ -586,7 +585,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
|
|||
/**
|
||||
* Set shutdown status. This field allows for graceful shutdown of a context. A started context may be put into non accepting state so that existing
|
||||
* requests can complete, but no new requests are accepted.
|
||||
*
|
||||
*
|
||||
* @param shutdown
|
||||
* true if this context is (not?) accepting new requests
|
||||
*/
|
||||
|
@ -694,7 +693,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
|
|||
/**
|
||||
* Extensible startContext. this method is called from {@link ContextHandler#doStart()} instead of a call to super.doStart(). This allows derived classes to
|
||||
* insert additional handling (Eg configuration) before the call to super.doStart by this method will start contained handlers.
|
||||
*
|
||||
*
|
||||
* @see org.eclipse.jetty.server.handler.ContextHandler.Context
|
||||
*/
|
||||
protected void startContext() throws Exception
|
||||
|
@ -1116,7 +1115,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
|
|||
/*
|
||||
* Set a context attribute. Attributes set via this API cannot be overriden by the ServletContext.setAttribute API. Their lifecycle spans the stop/start of
|
||||
* a context. No attribute listener events are triggered by this API.
|
||||
*
|
||||
*
|
||||
* @see javax.servlet.ServletContext#setAttribute(java.lang.String, java.lang.Object)
|
||||
*/
|
||||
public void setAttribute(String name, Object value)
|
||||
|
@ -1381,14 +1380,17 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
|
|||
|
||||
StringBuilder b = new StringBuilder();
|
||||
|
||||
String p = getClass().getPackage().getName();
|
||||
if (p != null && p.length() > 0)
|
||||
Package pkg = getClass().getPackage();
|
||||
if (pkg != null)
|
||||
{
|
||||
String[] ss = p.split("\\.");
|
||||
for (String s : ss)
|
||||
b.append(s.charAt(0)).append('.');
|
||||
String p = pkg.getName();
|
||||
if (p != null && p.length() > 0)
|
||||
{
|
||||
String[] ss = p.split("\\.");
|
||||
for (String s : ss)
|
||||
b.append(s.charAt(0)).append('.');
|
||||
}
|
||||
}
|
||||
|
||||
b.append(getClass().getSimpleName());
|
||||
b.append('{').append(getContextPath()).append(',').append(getBaseResource());
|
||||
|
||||
|
@ -1431,7 +1433,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
|
|||
/**
|
||||
* Get the character encoding for a locale. The full locale name is first looked up in the map of encodings. If no encoding is found, then the locale
|
||||
* language is looked up.
|
||||
*
|
||||
*
|
||||
* @param locale
|
||||
* a <code>Locale</code> value
|
||||
* @return a <code>String</code> representing the character encoding for the locale or null if none found.
|
||||
|
@ -1495,7 +1497,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
|
|||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Convert a URL or path to a Resource. The default implementation is a wrapper for {@link Resource#newResource(String)}.
|
||||
*
|
||||
*
|
||||
* @param urlOrPath
|
||||
* The URL or path to convert
|
||||
* @return The Resource for the URL/path
|
||||
|
@ -1557,8 +1559,8 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
|
|||
* <p>
|
||||
* A partial implementation of {@link javax.servlet.ServletContext}. A complete implementation is provided by the derived {@link ContextHandler}.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class Context implements ServletContext
|
||||
{
|
||||
|
@ -1787,7 +1789,8 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
|
|||
URL url = getResource(path);
|
||||
if (url == null)
|
||||
return null;
|
||||
return url.openStream();
|
||||
Resource r = Resource.newResource(url);
|
||||
return r.getInputStream();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
|
@ -31,6 +31,7 @@ import org.eclipse.jetty.util.ByteArrayISO8859Writer;
|
|||
import org.eclipse.jetty.util.IO;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -60,7 +61,10 @@ public class DefaultHandler extends AbstractHandler
|
|||
{
|
||||
URL fav = this.getClass().getClassLoader().getResource("org/eclipse/jetty/favicon.ico");
|
||||
if (fav!=null)
|
||||
_favicon=IO.readBytes(fav.openStream());
|
||||
{
|
||||
Resource r = Resource.newResource(fav);
|
||||
_favicon=IO.readBytes(r.getInputStream());
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
|
|
|
@ -51,7 +51,7 @@ import org.eclipse.jetty.util.resource.Resource;
|
|||
*
|
||||
* @org.apache.xbean.XBean
|
||||
*/
|
||||
public class ResourceHandler extends AbstractHandler
|
||||
public class ResourceHandler extends HandlerWrapper
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(ResourceHandler.class);
|
||||
|
||||
|
@ -358,6 +358,8 @@ public class ResourceHandler extends AbstractHandler
|
|||
{
|
||||
if(!HttpMethods.HEAD.equals(request.getMethod()))
|
||||
{
|
||||
//try another handler
|
||||
super.handle(target, baseRequest, request, response);
|
||||
return;
|
||||
}
|
||||
skipContentBody = true;
|
||||
|
@ -375,7 +377,11 @@ public class ResourceHandler extends AbstractHandler
|
|||
response.setContentType("text/css");
|
||||
}
|
||||
else
|
||||
{
|
||||
//no resource - try other handlers
|
||||
super.handle(target, baseRequest, request, response);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_aliases && resource.getAlias()!=null)
|
||||
|
|
|
@ -122,7 +122,6 @@ public class SelectChannelConnector extends AbstractNIOConnector
|
|||
public void customize(EndPoint endpoint, Request request) throws IOException
|
||||
{
|
||||
AsyncEndPoint aEndp = ((AsyncEndPoint)endpoint);
|
||||
aEndp.setCheckForIdle(false);
|
||||
request.setTimeStamp(System.currentTimeMillis());
|
||||
endpoint.setMaxIdleTime(_maxIdleTime);
|
||||
super.customize(endpoint, request);
|
||||
|
|
|
@ -13,44 +13,48 @@
|
|||
|
||||
package org.eclipse.jetty.server;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
|
||||
import java.net.SocketException;
|
||||
import java.util.concurrent.Exchanger;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.net.ssl.SSLException;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.io.nio.SslConnection;
|
||||
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.matchers.JUnitMatchers.containsString;
|
||||
|
||||
public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
||||
{
|
||||
protected static final int MAX_IDLE_TIME=250;
|
||||
|
||||
|
||||
static
|
||||
{
|
||||
System.setProperty("org.eclipse.jetty.io.nio.IDLE_TICK","100");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testMaxIdleWithRequest10() throws Exception
|
||||
{
|
||||
{
|
||||
configureServer(new HelloWorldHandler());
|
||||
Socket client=newSocket(HOST,_connector.getLocalPort());
|
||||
client.setSoTimeout(10000);
|
||||
|
||||
assertFalse(client.isClosed());
|
||||
|
||||
|
||||
OutputStream os=client.getOutputStream();
|
||||
InputStream is=client.getInputStream();
|
||||
|
||||
|
@ -63,7 +67,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
|
||||
long start = System.currentTimeMillis();
|
||||
IO.toString(is);
|
||||
|
||||
|
||||
Thread.sleep(300);
|
||||
assertEquals(-1, is.read());
|
||||
|
||||
|
@ -73,13 +77,13 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
|
||||
@Test
|
||||
public void testMaxIdleWithRequest11() throws Exception
|
||||
{
|
||||
{
|
||||
configureServer(new EchoHandler());
|
||||
Socket client=newSocket(HOST,_connector.getLocalPort());
|
||||
client.setSoTimeout(10000);
|
||||
|
||||
assertFalse(client.isClosed());
|
||||
|
||||
|
||||
OutputStream os=client.getOutputStream();
|
||||
InputStream is=client.getInputStream();
|
||||
|
||||
|
@ -96,24 +100,172 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
|
||||
long start = System.currentTimeMillis();
|
||||
IO.toString(is);
|
||||
|
||||
|
||||
Thread.sleep(300);
|
||||
assertEquals(-1, is.read());
|
||||
|
||||
Assert.assertTrue(System.currentTimeMillis()-start>200);
|
||||
Assert.assertTrue(System.currentTimeMillis()-start<5000);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testMaxIdleWithRequest10NoClientClose() throws Exception
|
||||
{
|
||||
final Exchanger<EndPoint> endpoint = new Exchanger<EndPoint>();
|
||||
configureServer(new HelloWorldHandler()
|
||||
{
|
||||
@Override
|
||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException,
|
||||
ServletException
|
||||
{
|
||||
try
|
||||
{
|
||||
endpoint.exchange(baseRequest.getConnection().getEndPoint());
|
||||
}
|
||||
catch(Exception e)
|
||||
{}
|
||||
super.handle(target,baseRequest,request,response);
|
||||
}
|
||||
|
||||
});
|
||||
Socket client=newSocket(HOST,_connector.getLocalPort());
|
||||
client.setSoTimeout(10000);
|
||||
|
||||
assertFalse(client.isClosed());
|
||||
|
||||
OutputStream os=client.getOutputStream();
|
||||
InputStream is=client.getInputStream();
|
||||
|
||||
os.write((
|
||||
"GET / HTTP/1.0\r\n"+
|
||||
"host: "+HOST+":"+_connector.getLocalPort()+"\r\n"+
|
||||
"connection: close\r\n"+
|
||||
"\r\n").getBytes("utf-8"));
|
||||
os.flush();
|
||||
|
||||
// Get the server side endpoint
|
||||
EndPoint endp = endpoint.exchange(null,10,TimeUnit.SECONDS);
|
||||
if (endp instanceof SslConnection.SslEndPoint)
|
||||
endp=((SslConnection.SslEndPoint)endp).getEndpoint();
|
||||
|
||||
// read the response
|
||||
String result=IO.toString(is);
|
||||
Assert.assertThat("OK",result,containsString("200 OK"));
|
||||
|
||||
// check client reads EOF
|
||||
assertEquals(-1, is.read());
|
||||
|
||||
// wait for idle timeout
|
||||
TimeUnit.MILLISECONDS.sleep(MAX_IDLE_TIME+MAX_IDLE_TIME/2);
|
||||
|
||||
|
||||
// further writes will get broken pipe or similar
|
||||
try
|
||||
{
|
||||
for (int i=0;i<1000;i++)
|
||||
{
|
||||
os.write((
|
||||
"GET / HTTP/1.0\r\n"+
|
||||
"host: "+HOST+":"+_connector.getLocalPort()+"\r\n"+
|
||||
"connection: keep-alive\r\n"+
|
||||
"\r\n").getBytes("utf-8"));
|
||||
os.flush();
|
||||
}
|
||||
Assert.fail("half close should have timed out");
|
||||
}
|
||||
catch(SocketException e)
|
||||
{
|
||||
// expected
|
||||
}
|
||||
// check the server side is closed
|
||||
Assert.assertFalse(endp.isOpen());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMaxIdleWithRequest11NoClientClose() throws Exception
|
||||
{
|
||||
final Exchanger<EndPoint> endpoint = new Exchanger<EndPoint>();
|
||||
configureServer(new EchoHandler()
|
||||
{
|
||||
@Override
|
||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException,
|
||||
ServletException
|
||||
{
|
||||
try
|
||||
{
|
||||
endpoint.exchange(baseRequest.getConnection().getEndPoint());
|
||||
}
|
||||
catch(Exception e)
|
||||
{}
|
||||
super.handle(target,baseRequest,request,response);
|
||||
}
|
||||
|
||||
});
|
||||
Socket client=newSocket(HOST,_connector.getLocalPort());
|
||||
client.setSoTimeout(10000);
|
||||
|
||||
assertFalse(client.isClosed());
|
||||
|
||||
OutputStream os=client.getOutputStream();
|
||||
InputStream is=client.getInputStream();
|
||||
|
||||
String content="Wibble";
|
||||
byte[] contentB=content.getBytes("utf-8");
|
||||
os.write((
|
||||
"POST /echo HTTP/1.1\r\n"+
|
||||
"host: "+HOST+":"+_connector.getLocalPort()+"\r\n"+
|
||||
"content-type: text/plain; charset=utf-8\r\n"+
|
||||
"content-length: "+contentB.length+"\r\n"+
|
||||
"connection: close\r\n"+
|
||||
"\r\n").getBytes("utf-8"));
|
||||
os.write(contentB);
|
||||
os.flush();
|
||||
|
||||
// Get the server side endpoint
|
||||
EndPoint endp = endpoint.exchange(null,10,TimeUnit.SECONDS);
|
||||
|
||||
// read the response
|
||||
IO.toString(is);
|
||||
|
||||
// check client reads EOF
|
||||
assertEquals(-1, is.read());
|
||||
|
||||
TimeUnit.MILLISECONDS.sleep(MAX_IDLE_TIME+MAX_IDLE_TIME/2);
|
||||
|
||||
|
||||
// further writes will get broken pipe or similar
|
||||
try
|
||||
{
|
||||
for (int i=0;i<1000;i++)
|
||||
{
|
||||
os.write((
|
||||
"GET / HTTP/1.0\r\n"+
|
||||
"host: "+HOST+":"+_connector.getLocalPort()+"\r\n"+
|
||||
"connection: keep-alive\r\n"+
|
||||
"\r\n").getBytes("utf-8"));
|
||||
os.flush();
|
||||
}
|
||||
Assert.fail("half close should have timed out");
|
||||
}
|
||||
catch(SocketException e)
|
||||
{
|
||||
// expected
|
||||
}
|
||||
|
||||
// check the server side is closed
|
||||
Assert.assertFalse(endp.isOpen());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testMaxIdleNoRequest() throws Exception
|
||||
{
|
||||
{
|
||||
configureServer(new EchoHandler());
|
||||
Socket client=newSocket(HOST,_connector.getLocalPort());
|
||||
client.setSoTimeout(10000);
|
||||
InputStream is=client.getInputStream();
|
||||
assertFalse(client.isClosed());
|
||||
|
||||
|
||||
Thread.sleep(500);
|
||||
long start = System.currentTimeMillis();
|
||||
try
|
||||
|
@ -123,25 +275,25 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
}
|
||||
catch(SSLException e)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
Assert.assertTrue(System.currentTimeMillis()-start<5000);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMaxIdleWithSlowRequest() throws Exception
|
||||
{
|
||||
{
|
||||
configureServer(new EchoHandler());
|
||||
Socket client=newSocket(HOST,_connector.getLocalPort());
|
||||
client.setSoTimeout(10000);
|
||||
|
||||
assertFalse(client.isClosed());
|
||||
|
||||
|
||||
OutputStream os=client.getOutputStream();
|
||||
InputStream is=client.getInputStream();
|
||||
|
||||
|
@ -163,7 +315,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
os.write(contentB);
|
||||
os.flush();
|
||||
}
|
||||
|
||||
|
||||
String in = IO.toString(is);
|
||||
int offset=0;
|
||||
for (int i =0;i<20;i++)
|
||||
|
@ -175,13 +327,13 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
|
||||
@Test
|
||||
public void testMaxIdleWithSlowResponse() throws Exception
|
||||
{
|
||||
{
|
||||
configureServer(new SlowResponseHandler());
|
||||
Socket client=newSocket(HOST,_connector.getLocalPort());
|
||||
client.setSoTimeout(10000);
|
||||
|
||||
assertFalse(client.isClosed());
|
||||
|
||||
|
||||
OutputStream os=client.getOutputStream();
|
||||
InputStream is=client.getInputStream();
|
||||
|
||||
|
@ -192,7 +344,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
"Connection: close\r\n"+
|
||||
"\r\n").getBytes("utf-8"));
|
||||
os.flush();
|
||||
|
||||
|
||||
String in = IO.toString(is);
|
||||
int offset=0;
|
||||
for (int i =0;i<20;i++)
|
||||
|
@ -204,13 +356,13 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
|
||||
@Test
|
||||
public void testMaxIdleWithWait() throws Exception
|
||||
{
|
||||
{
|
||||
configureServer(new WaitHandler());
|
||||
Socket client=newSocket(HOST,_connector.getLocalPort());
|
||||
client.setSoTimeout(10000);
|
||||
|
||||
assertFalse(client.isClosed());
|
||||
|
||||
|
||||
OutputStream os=client.getOutputStream();
|
||||
InputStream is=client.getInputStream();
|
||||
|
||||
|
@ -221,12 +373,12 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
"Connection: close\r\n"+
|
||||
"\r\n").getBytes("utf-8"));
|
||||
os.flush();
|
||||
|
||||
|
||||
String in = IO.toString(is);
|
||||
int offset=in.indexOf("Hello World");
|
||||
Assert.assertTrue(offset>0);
|
||||
}
|
||||
|
||||
|
||||
protected static class SlowResponseHandler extends AbstractHandler
|
||||
{
|
||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
|
@ -234,7 +386,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
baseRequest.setHandled(true);
|
||||
response.setStatus(200);
|
||||
OutputStream out = response.getOutputStream();
|
||||
|
||||
|
||||
for (int i=0;i<20;i++)
|
||||
{
|
||||
out.write("Hello World\r\n".getBytes());
|
||||
|
@ -244,7 +396,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected static class WaitHandler extends AbstractHandler
|
||||
{
|
||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
|
|
|
@ -13,10 +13,6 @@
|
|||
|
||||
package org.eclipse.jetty.server;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
@ -29,14 +25,12 @@ import java.net.URL;
|
|||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.Exchanger;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
|
@ -44,6 +38,10 @@ import org.eclipse.jetty.util.log.Log;
|
|||
import org.eclipse.jetty.util.log.StdErrLog;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -222,7 +220,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
|
||||
// Read the response
|
||||
String response=readResponse(client);
|
||||
|
||||
|
||||
// Check the response
|
||||
assertEquals("response "+i,RESPONSE2,response);
|
||||
}
|
||||
|
@ -378,7 +376,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
try
|
||||
{
|
||||
URL url=new URL(_scheme+"://"+HOST+":"+_connector.getLocalPort()+"/?writes="+w+"&block="+b+ (e==0?"":("&encoding="+encoding[e]))+(c==0?"&chars=true":""));
|
||||
|
||||
|
||||
InputStream in = (InputStream)url.getContent();
|
||||
String response=IO.toString(in,e==0?null:encoding[e]);
|
||||
|
||||
|
@ -453,7 +451,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
client.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testBlockingWhileWritingResponseContent() throws Exception
|
||||
{
|
||||
|
@ -521,7 +519,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
"\r\n"
|
||||
).getBytes());
|
||||
os.flush();
|
||||
|
||||
|
||||
// read the chunked response header
|
||||
boolean chunked=false;
|
||||
boolean closed=false;
|
||||
|
@ -530,13 +528,13 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
String line=in.readLine();
|
||||
if (line==null || line.length()==0)
|
||||
break;
|
||||
|
||||
|
||||
chunked|="Transfer-Encoding: chunked".equals(line);
|
||||
closed|="Connection: close".equals(line);
|
||||
}
|
||||
Assert.assertTrue(chunked);
|
||||
Assert.assertFalse(closed);
|
||||
|
||||
|
||||
// Read the chunks
|
||||
int max=Integer.MIN_VALUE;
|
||||
while(true)
|
||||
|
@ -550,22 +548,22 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
if (max<len)
|
||||
max=len;
|
||||
}
|
||||
|
||||
|
||||
// Check that a direct content buffer was used as a chunk
|
||||
Assert.assertEquals(128*1024,max);
|
||||
|
||||
|
||||
// read and check the times are < 999ms
|
||||
String[] times=in.readLine().split(",");
|
||||
for (String t: times)
|
||||
Assert.assertTrue(Integer.valueOf(t).intValue()<999);
|
||||
|
||||
|
||||
|
||||
|
||||
// read the EOF chunk
|
||||
String end=in.readLine();
|
||||
Assert.assertEquals("0",end);
|
||||
end=in.readLine();
|
||||
Assert.assertEquals(0,end.length());
|
||||
|
||||
|
||||
|
||||
// read the non-chunked response header
|
||||
chunked=false;
|
||||
|
@ -575,13 +573,13 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
String line=in.readLine();
|
||||
if (line==null || line.length()==0)
|
||||
break;
|
||||
|
||||
|
||||
chunked|="Transfer-Encoding: chunked".equals(line);
|
||||
closed|="Connection: close".equals(line);
|
||||
}
|
||||
Assert.assertFalse(chunked);
|
||||
Assert.assertTrue(closed);
|
||||
|
||||
|
||||
String bigline = in.readLine();
|
||||
Assert.assertEquals(10*128*1024,bigline.length());
|
||||
|
||||
|
@ -589,7 +587,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
times=in.readLine().split(",");
|
||||
for (String t: times)
|
||||
Assert.assertTrue(t,Integer.valueOf(t).intValue()<999);
|
||||
|
||||
|
||||
// check close
|
||||
Assert.assertTrue(in.readLine()==null);
|
||||
}
|
||||
|
@ -607,7 +605,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
byte[] buf = new byte[128*1024];
|
||||
for (int i=0;i<buf.length;i++)
|
||||
buf[i]=(byte)("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_".charAt(i%63));
|
||||
|
||||
|
||||
baseRequest.setHandled(true);
|
||||
response.setStatus(200);
|
||||
response.setContentType("text/plain");
|
||||
|
@ -631,7 +629,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testPipeline() throws Exception
|
||||
|
@ -741,6 +739,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
IO.copy(is,bout);
|
||||
byte[] b=bout.toByteArray();
|
||||
|
||||
System.err.println("OUTPUT: "+new String(b));
|
||||
int i=0;
|
||||
while (b[i]!='Z')
|
||||
i++;
|
||||
|
@ -795,14 +794,14 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
"content-length: 10\r\n"+
|
||||
"\015\012"+
|
||||
"123456789\n" +
|
||||
|
||||
|
||||
"HEAD /R1 HTTP/1.1\015\012"+
|
||||
"Host: "+HOST+":"+_connector.getLocalPort()+"\015\012"+
|
||||
"content-type: text/plain; charset=utf-8\r\n"+
|
||||
"content-length: 10\r\n"+
|
||||
"\015\012"+
|
||||
"123456789\n"+
|
||||
|
||||
|
||||
"POST /R1 HTTP/1.1\015\012"+
|
||||
"Host: "+HOST+":"+_connector.getLocalPort()+"\015\012"+
|
||||
"content-type: text/plain; charset=utf-8\r\n"+
|
||||
|
@ -810,25 +809,25 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
"Connection: close\015\012"+
|
||||
"\015\012"+
|
||||
"123456789\n"
|
||||
|
||||
|
||||
).getBytes("iso-8859-1"));
|
||||
|
||||
|
||||
String in = IO.toString(is);
|
||||
|
||||
|
||||
int index=in.indexOf("123456789");
|
||||
assertTrue(index>0);
|
||||
index=in.indexOf("123456789",index+1);
|
||||
assertTrue(index>0);
|
||||
index=in.indexOf("123456789",index+1);
|
||||
assertTrue(index==-1);
|
||||
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRecycledReaders() throws Exception
|
||||
{
|
||||
|
@ -908,27 +907,27 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
"Connection: Keep-Alive\r\n"+
|
||||
"\r\n"
|
||||
).getBytes());
|
||||
|
||||
|
||||
// Never send a body.
|
||||
// HelloWorldHandler does not read content, so 100 is not sent.
|
||||
// So close will have to happen anyway, without reset!
|
||||
|
||||
|
||||
os.flush();
|
||||
|
||||
|
||||
client.setSoTimeout(2000);
|
||||
long start=System.currentTimeMillis();
|
||||
String in = IO.toString(is);
|
||||
assertTrue(System.currentTimeMillis()-start<1000);
|
||||
assertTrue(in.indexOf("Connection: close")>0);
|
||||
assertTrue(in.indexOf("Hello world")>0);
|
||||
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCommittedError() throws Exception
|
||||
{
|
||||
|
@ -949,25 +948,25 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
"\r\n"
|
||||
).getBytes());
|
||||
os.flush();
|
||||
|
||||
|
||||
client.setSoTimeout(2000);
|
||||
String in = IO.toString(is);
|
||||
|
||||
assertEquals(-1,is.read()); // Closed by error!
|
||||
|
||||
|
||||
assertTrue(in.indexOf("HTTP/1.1 200 OK")>=0);
|
||||
assertTrue(in.indexOf("Transfer-Encoding: chunked")>0);
|
||||
assertTrue(in.indexOf("Now is the time for all good men to come to the aid of the party")>0);
|
||||
assertTrue(in.indexOf("\r\n0\r\n")==-1); // chunking is interrupted by error close
|
||||
|
||||
client.close();
|
||||
Thread.sleep(100);
|
||||
Thread.sleep(100);
|
||||
assertTrue(!handler._endp.isOpen());
|
||||
}
|
||||
finally
|
||||
{
|
||||
((StdErrLog)Log.getLogger(AbstractHttpConnection.class)).setHideStacks(false);
|
||||
|
||||
|
||||
if (!client.isClosed())
|
||||
client.close();
|
||||
}
|
||||
|
@ -976,7 +975,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
protected static class CommittedErrorHandler extends AbstractHandler
|
||||
{
|
||||
public EndPoint _endp;
|
||||
|
||||
|
||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
_endp=baseRequest.getConnection().getEndPoint();
|
||||
|
@ -986,15 +985,15 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
response.getWriter().println("Now is the time for all good men to come to the aid of the party");
|
||||
response.getWriter().flush();
|
||||
response.flushBuffer();
|
||||
|
||||
|
||||
throw new ServletException(new Exception("exception after commit"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected static class AvailableHandler extends AbstractHandler
|
||||
{
|
||||
public Exchanger<Object> _ex = new Exchanger<Object>();
|
||||
|
||||
|
||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
baseRequest.setHandled(true);
|
||||
|
@ -1002,31 +1001,31 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
response.setContentType("text/plain");
|
||||
InputStream in = request.getInputStream();
|
||||
ServletOutputStream out=response.getOutputStream();
|
||||
|
||||
|
||||
// should always be some input available, because of deferred dispatch.
|
||||
int avail=in.available();
|
||||
out.println(avail);
|
||||
|
||||
|
||||
String buf="";
|
||||
for (int i=0;i<avail;i++)
|
||||
buf+=(char)in.read();
|
||||
|
||||
|
||||
|
||||
avail=in.available();
|
||||
out.println(avail);
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
_ex.exchange(null);
|
||||
_ex.exchange(null);
|
||||
_ex.exchange(null);
|
||||
}
|
||||
catch(InterruptedException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
avail=in.available();
|
||||
|
||||
|
||||
if (avail==0)
|
||||
{
|
||||
// handle blocking channel connectors
|
||||
|
@ -1046,15 +1045,15 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
|
||||
for (int i=0;i<avail;i++)
|
||||
buf+=(char)in.read();
|
||||
|
||||
|
||||
avail=in.available();
|
||||
out.println(avail);
|
||||
out.println(buf);
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testAvailable() throws Exception
|
||||
{
|
||||
|
@ -1081,7 +1080,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
"1234567890"
|
||||
).getBytes());
|
||||
os.flush();
|
||||
|
||||
|
||||
ah._ex.exchange(null);
|
||||
|
||||
os.write((
|
||||
|
@ -1090,7 +1089,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
os.flush();
|
||||
Thread.sleep(500);
|
||||
ah._ex.exchange(null);
|
||||
|
||||
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
|
||||
// skip header
|
||||
while(reader.readLine().length()>0);
|
||||
|
@ -1099,7 +1098,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
assertEquals(20,Integer.parseInt(reader.readLine()));
|
||||
assertEquals(0,Integer.parseInt(reader.readLine()));
|
||||
assertEquals("1234567890abcdefghijklmnopqrst",reader.readLine());
|
||||
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -1107,7 +1106,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testDualRequest1() throws Exception
|
||||
{
|
||||
|
@ -1205,5 +1204,5 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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,12 +1,10 @@
|
|||
package org.eclipse.jetty.server.handler;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
|
@ -18,6 +16,9 @@ import org.eclipse.jetty.server.Server;
|
|||
import org.eclipse.jetty.server.nio.SelectChannelConnector;
|
||||
import org.junit.AfterClass;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
|
@ -91,11 +92,21 @@ public abstract class AbstractConnectHandlerTest
|
|||
StringBuilder body = new StringBuilder();
|
||||
if (headers.containsKey("content-length"))
|
||||
{
|
||||
int readLen = 0;
|
||||
int length = Integer.parseInt(headers.get("content-length"));
|
||||
for (int i = 0; i < length; ++i)
|
||||
try
|
||||
{
|
||||
char c = (char)reader.read();
|
||||
body.append(c);
|
||||
for (int i = 0; i < length; ++i)
|
||||
{
|
||||
char c = (char)reader.read();
|
||||
body.append(c);
|
||||
readLen++;
|
||||
}
|
||||
}
|
||||
catch (SocketTimeoutException e)
|
||||
{
|
||||
System.err.printf("Read %,d bytes (out of an expected %,d bytes)%n",readLen,length);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
else if ("chunked".equals(headers.get("transfer-encoding")))
|
||||
|
@ -126,7 +137,7 @@ public abstract class AbstractConnectHandlerTest
|
|||
protected Socket newSocket() throws IOException
|
||||
{
|
||||
Socket socket = new Socket("localhost", proxyConnector.getLocalPort());
|
||||
socket.setSoTimeout(5000);
|
||||
socket.setSoTimeout(10000);
|
||||
return socket;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,23 +14,17 @@
|
|||
|
||||
package org.eclipse.jetty.server.handler;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.eclipse.jetty.server.Connector;
|
||||
import org.eclipse.jetty.server.LocalConnector;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
|
@ -38,6 +32,10 @@ import org.eclipse.jetty.server.Server;
|
|||
import org.eclipse.jetty.util.resource.Resource;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @version $Revision$
|
||||
*/
|
||||
|
@ -122,22 +120,22 @@ public class ContextHandlerTest
|
|||
server.setConnectors(new Connector[] { connector });
|
||||
ContextHandlerCollection contexts = new ContextHandlerCollection();
|
||||
server.setHandler(contexts);
|
||||
|
||||
|
||||
ContextHandler rootA = new ContextHandler(contexts,"/");
|
||||
ContextHandler fooA = new ContextHandler(contexts,"/foo");
|
||||
ContextHandler foobarA = new ContextHandler(contexts,"/foo/bar");
|
||||
|
||||
|
||||
server.start();
|
||||
|
||||
|
||||
// System.err.println(server.dump());
|
||||
|
||||
|
||||
Assert.assertEquals(rootA._scontext,rootA._scontext.getContext("/"));
|
||||
Assert.assertEquals(fooA._scontext,rootA._scontext.getContext("/foo"));
|
||||
Assert.assertEquals(foobarA._scontext,rootA._scontext.getContext("/foo/bar"));
|
||||
Assert.assertEquals(foobarA._scontext,rootA._scontext.getContext("/foo/bar/bob.jsp"));
|
||||
Assert.assertEquals(rootA._scontext,rootA._scontext.getContext("/other"));
|
||||
Assert.assertEquals(fooA._scontext,rootA._scontext.getContext("/foo/other"));
|
||||
|
||||
|
||||
Assert.assertEquals(rootA._scontext,foobarA._scontext.getContext("/"));
|
||||
Assert.assertEquals(fooA._scontext,foobarA._scontext.getContext("/foo"));
|
||||
Assert.assertEquals(foobarA._scontext,foobarA._scontext.getContext("/foo/bar"));
|
||||
|
@ -145,7 +143,7 @@ public class ContextHandlerTest
|
|||
Assert.assertEquals(rootA._scontext,foobarA._scontext.getContext("/other"));
|
||||
Assert.assertEquals(fooA._scontext,foobarA._scontext.getContext("/foo/other"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testContextVirtualGetContext() throws Exception
|
||||
{
|
||||
|
@ -154,45 +152,45 @@ public class ContextHandlerTest
|
|||
server.setConnectors(new Connector[] { connector });
|
||||
ContextHandlerCollection contexts = new ContextHandlerCollection();
|
||||
server.setHandler(contexts);
|
||||
|
||||
|
||||
ContextHandler rootA = new ContextHandler(contexts,"/");
|
||||
rootA.setVirtualHosts(new String[] {"a.com"});
|
||||
|
||||
|
||||
ContextHandler rootB = new ContextHandler(contexts,"/");
|
||||
rootB.setVirtualHosts(new String[] {"b.com"});
|
||||
|
||||
|
||||
ContextHandler rootC = new ContextHandler(contexts,"/");
|
||||
rootC.setVirtualHosts(new String[] {"c.com"});
|
||||
|
||||
|
||||
|
||||
|
||||
ContextHandler fooA = new ContextHandler(contexts,"/foo");
|
||||
fooA.setVirtualHosts(new String[] {"a.com"});
|
||||
|
||||
|
||||
ContextHandler fooB = new ContextHandler(contexts,"/foo");
|
||||
fooB.setVirtualHosts(new String[] {"b.com"});
|
||||
|
||||
|
||||
ContextHandler foobarA = new ContextHandler(contexts,"/foo/bar");
|
||||
foobarA.setVirtualHosts(new String[] {"a.com"});
|
||||
|
||||
|
||||
server.start();
|
||||
|
||||
|
||||
// System.err.println(server.dump());
|
||||
|
||||
|
||||
Assert.assertEquals(rootA._scontext,rootA._scontext.getContext("/"));
|
||||
Assert.assertEquals(fooA._scontext,rootA._scontext.getContext("/foo"));
|
||||
Assert.assertEquals(foobarA._scontext,rootA._scontext.getContext("/foo/bar"));
|
||||
Assert.assertEquals(foobarA._scontext,rootA._scontext.getContext("/foo/bar/bob"));
|
||||
|
||||
|
||||
Assert.assertEquals(rootA._scontext,rootA._scontext.getContext("/other"));
|
||||
Assert.assertEquals(rootB._scontext,rootB._scontext.getContext("/other"));
|
||||
Assert.assertEquals(rootC._scontext,rootC._scontext.getContext("/other"));
|
||||
|
||||
|
||||
Assert.assertEquals(fooB._scontext,rootB._scontext.getContext("/foo/other"));
|
||||
Assert.assertEquals(rootC._scontext,rootC._scontext.getContext("/foo/other"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testVirtualHostWildcard() throws Exception
|
||||
{
|
||||
|
@ -238,31 +236,31 @@ public class ContextHandlerTest
|
|||
ContextHandler context = new ContextHandler("/");
|
||||
|
||||
// test singular
|
||||
context.setVirtualHosts(new String[] { "www.example.com"} );
|
||||
context.setVirtualHosts(new String[] { "www.example.com"} );
|
||||
Assert.assertEquals(1,context.getVirtualHosts().length);
|
||||
|
||||
|
||||
// test adding two more
|
||||
context.addVirtualHosts(new String[] { "www.example2.com", "www.example3.com"});
|
||||
Assert.assertEquals(3,context.getVirtualHosts().length);
|
||||
|
||||
|
||||
// test adding existing context
|
||||
context.addVirtualHosts(new String[] { "www.example.com" });
|
||||
Assert.assertEquals(3,context.getVirtualHosts().length);
|
||||
|
||||
|
||||
// test removing existing
|
||||
context.removeVirtualHosts(new String[] { "www.example3.com" });
|
||||
Assert.assertEquals(2,context.getVirtualHosts().length);
|
||||
|
||||
|
||||
// test removing non-existent
|
||||
context.removeVirtualHosts(new String[] { "www.example3.com" });
|
||||
Assert.assertEquals(2,context.getVirtualHosts().length);
|
||||
|
||||
|
||||
// test removing all remaining and resets to null
|
||||
context.removeVirtualHosts(new String[] { "www.example.com", "www.example2.com" });
|
||||
Assert.assertEquals(null,context.getVirtualHosts());
|
||||
|
||||
Assert.assertEquals(null,context.getVirtualHosts());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testAttributes() throws Exception
|
||||
{
|
||||
|
@ -332,11 +330,12 @@ public class ContextHandlerTest
|
|||
|
||||
return root;
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testUncheckedPrintWriter() throws Exception
|
||||
{
|
||||
Server server = new Server();
|
||||
server.setUncheckedPrintWriter(true);
|
||||
LocalConnector connector = new LocalConnector();
|
||||
server.setConnectors(new Connector[] { connector });
|
||||
ContextHandler context = new ContextHandler("/");
|
||||
|
@ -347,7 +346,7 @@ public class ContextHandlerTest
|
|||
try
|
||||
{
|
||||
server.start();
|
||||
|
||||
|
||||
String response = connector.getResponses("GET / HTTP/1.1\n" + "Host: www.example.com.\n\n");
|
||||
|
||||
Assert.assertTrue(response.indexOf("Goodbye")>0);
|
||||
|
@ -400,7 +399,7 @@ public class ContextHandlerTest
|
|||
handled = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static final class WriterHandler extends AbstractHandler
|
||||
{
|
||||
boolean error;
|
||||
|
@ -422,7 +421,10 @@ public class ContextHandlerTest
|
|||
writer.write("Goodbye cruel world\n");
|
||||
writer.close();
|
||||
response.flushBuffer();
|
||||
writer.write("speaking from the dead");
|
||||
//writer.write("speaking from the dead");
|
||||
writer.write("give the printwriter a chance"); //should create an error
|
||||
if (writer.checkError())
|
||||
writer.write("didn't take the chance, will throw now"); //write after an error
|
||||
}
|
||||
catch(Throwable th)
|
||||
{
|
||||
|
|
|
@ -1230,7 +1230,6 @@ public class ServletHandler extends ScopedHandler
|
|||
HttpServletResponse response)
|
||||
throws IOException
|
||||
{
|
||||
new Throwable().printStackTrace();
|
||||
if(LOG.isDebugEnabled())
|
||||
LOG.debug("Not Found "+request.getRequestURI());
|
||||
response.sendError(HttpServletResponse.SC_NOT_FOUND);
|
||||
|
|
|
@ -14,7 +14,9 @@
|
|||
package org.eclipse.jetty.servlets;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
@ -32,8 +34,10 @@ import javax.servlet.ServletResponse;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import javax.servlet.http.HttpSessionActivationListener;
|
||||
import javax.servlet.http.HttpSessionBindingEvent;
|
||||
import javax.servlet.http.HttpSessionBindingListener;
|
||||
import javax.servlet.http.HttpSessionEvent;
|
||||
|
||||
import org.eclipse.jetty.continuation.Continuation;
|
||||
import org.eclipse.jetty.continuation.ContinuationListener;
|
||||
|
@ -908,13 +912,14 @@ public class DoSFilter implements Filter
|
|||
* A RateTracker is associated with a connection, and stores request rate
|
||||
* data.
|
||||
*/
|
||||
class RateTracker extends Timeout.Task implements HttpSessionBindingListener
|
||||
class RateTracker extends Timeout.Task implements HttpSessionBindingListener, HttpSessionActivationListener
|
||||
{
|
||||
protected final String _id;
|
||||
protected final int _type;
|
||||
protected final long[] _timestamps;
|
||||
protected int _next;
|
||||
|
||||
transient protected final String _id;
|
||||
transient protected final int _type;
|
||||
transient protected final long[] _timestamps;
|
||||
transient protected int _next;
|
||||
|
||||
|
||||
public RateTracker(String id, int type,int maxRequestsPerSecond)
|
||||
{
|
||||
_id = id;
|
||||
|
@ -953,25 +958,49 @@ public class DoSFilter implements Filter
|
|||
|
||||
|
||||
public void valueBound(HttpSessionBindingEvent event)
|
||||
{
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Value bound:"+_id);
|
||||
}
|
||||
|
||||
public void valueUnbound(HttpSessionBindingEvent event)
|
||||
{
|
||||
_rateTrackers.remove(_id);
|
||||
//take the tracker out of the list of trackers
|
||||
if (_rateTrackers != null)
|
||||
_rateTrackers.remove(_id);
|
||||
if (LOG.isDebugEnabled()) LOG.debug("Tracker removed: "+_id);
|
||||
}
|
||||
|
||||
public void sessionWillPassivate(HttpSessionEvent se)
|
||||
{
|
||||
//take the tracker of the list of trackers (if its still there)
|
||||
//and ensure that we take ourselves out of the session so we are not saved
|
||||
if (_rateTrackers != null)
|
||||
_rateTrackers.remove(_id);
|
||||
se.getSession().removeAttribute(__TRACKER);
|
||||
if (LOG.isDebugEnabled()) LOG.debug("Value removed: "+_id);
|
||||
}
|
||||
|
||||
public void sessionDidActivate(HttpSessionEvent se)
|
||||
{
|
||||
LOG.warn("Unexpected session activation");
|
||||
}
|
||||
|
||||
|
||||
public void expired()
|
||||
{
|
||||
long now = _trackerTimeoutQ.getNow();
|
||||
int latestIndex = _next == 0 ? 3 : (_next - 1 ) % _timestamps.length;
|
||||
long last=_timestamps[latestIndex];
|
||||
boolean hasRecentRequest = last != 0 && (now-last)<1000L;
|
||||
if (_rateTrackers != null && _trackerTimeoutQ != null)
|
||||
{
|
||||
long now = _trackerTimeoutQ.getNow();
|
||||
int latestIndex = _next == 0 ? 3 : (_next - 1 ) % _timestamps.length;
|
||||
long last=_timestamps[latestIndex];
|
||||
boolean hasRecentRequest = last != 0 && (now-last)<1000L;
|
||||
|
||||
if (hasRecentRequest)
|
||||
reschedule();
|
||||
else
|
||||
_rateTrackers.remove(_id);
|
||||
if (hasRecentRequest)
|
||||
reschedule();
|
||||
else
|
||||
_rateTrackers.remove(_id);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -979,6 +1008,8 @@ public class DoSFilter implements Filter
|
|||
{
|
||||
return "RateTracker/"+_id+"/"+_type;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
class FixedRateTracker extends RateTracker
|
||||
|
|
|
@ -67,10 +67,10 @@ public class IncludableGzipFilter extends GzipFilter
|
|||
public IncludableResponseWrapper(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
super(request,response);
|
||||
|
||||
_mimeTypes = IncludableGzipFilter.this._mimeTypes;
|
||||
_bufferSize = IncludableGzipFilter.this._bufferSize;
|
||||
_minGzipSize = IncludableGzipFilter.this._minGzipSize;
|
||||
|
||||
super.setMimeTypes(IncludableGzipFilter.this._mimeTypes);
|
||||
super.setBufferSize(IncludableGzipFilter.this._bufferSize);
|
||||
super.setMinGzipSize(IncludableGzipFilter.this._minGzipSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
package org.eclipse.jetty.servlets;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.Servlet;
|
||||
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.eclipse.jetty.http.gzip.GzipResponseWrapper;
|
||||
import org.eclipse.jetty.servlet.DefaultServlet;
|
||||
import org.eclipse.jetty.servlet.FilterHolder;
|
||||
import org.eclipse.jetty.servlets.gzip.GzipTester;
|
||||
import org.eclipse.jetty.servlets.gzip.TestServletLengthStreamTypeWrite;
|
||||
|
@ -25,7 +24,7 @@ import org.junit.runners.Parameterized.Parameters;
|
|||
|
||||
/**
|
||||
* Test the GzipFilter support for Content-Length setting variations.
|
||||
*
|
||||
*
|
||||
* @see <a href="Eclipse Bug 354014">http://bugs.eclipse.org/354014</a>
|
||||
*/
|
||||
@RunWith(Parameterized.class)
|
||||
|
@ -39,9 +38,9 @@ public class GzipFilterContentLengthTest
|
|||
* in different order so as to simulate the real world scenario
|
||||
* that caused the bug in Eclipse <a href="Bug 354014">http://bugs.eclipse.org/354014</a>
|
||||
* <p>
|
||||
* This test case will be run with each of the entries in
|
||||
* This test case will be run with each of the entries in
|
||||
* the array below as setup parameters for the test case.
|
||||
*
|
||||
*
|
||||
* @return the junit parameters
|
||||
*/
|
||||
@Parameters
|
||||
|
@ -49,7 +48,6 @@ public class GzipFilterContentLengthTest
|
|||
{
|
||||
return Arrays.asList(new Object[][]
|
||||
{
|
||||
{ DefaultServlet.class },
|
||||
{ TestServletLengthStreamTypeWrite.class },
|
||||
{ TestServletLengthTypeStreamWrite.class },
|
||||
{ TestServletStreamLengthTypeWrite.class },
|
||||
|
@ -77,7 +75,7 @@ public class GzipFilterContentLengthTest
|
|||
{
|
||||
GzipTester tester = new GzipTester(testingdir);
|
||||
|
||||
tester.prepareServerFile(filename,filesize);
|
||||
File testfile = tester.prepareServerFile(testServlet.getSimpleName() + "-" + filename,filesize);
|
||||
|
||||
FilterHolder holder = tester.setContentServlet(testServlet);
|
||||
holder.setInitParameter("mimeTypes","text/plain");
|
||||
|
@ -85,7 +83,7 @@ public class GzipFilterContentLengthTest
|
|||
try
|
||||
{
|
||||
tester.start();
|
||||
tester.assertIsResponseGzipCompressed(filename);
|
||||
tester.assertIsResponseGzipCompressed(testfile.getName());
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -97,7 +95,7 @@ public class GzipFilterContentLengthTest
|
|||
{
|
||||
GzipTester tester = new GzipTester(testingdir);
|
||||
|
||||
tester.prepareServerFile(filename,filesize);
|
||||
File testfile = tester.prepareServerFile(testServlet.getSimpleName() + "-" + filename,filesize);
|
||||
|
||||
FilterHolder holder = tester.setContentServlet(testServlet);
|
||||
holder.setInitParameter("mimeTypes","text/plain");
|
||||
|
@ -105,7 +103,7 @@ public class GzipFilterContentLengthTest
|
|||
try
|
||||
{
|
||||
tester.start();
|
||||
tester.assertIsResponseNotGzipCompressed(filename,filesize,HttpStatus.OK_200);
|
||||
tester.assertIsResponseNotGzipCompressed(testfile.getName(),filesize,HttpStatus.OK_200);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -119,7 +117,7 @@ public class GzipFilterContentLengthTest
|
|||
@Test
|
||||
public void testIsGzipCompressedSmall() throws Exception
|
||||
{
|
||||
assertIsGzipCompressed("file.txt",SMALL);
|
||||
assertIsGzipCompressed("file-small.txt",SMALL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -128,7 +126,7 @@ public class GzipFilterContentLengthTest
|
|||
@Test
|
||||
public void testIsGzipCompressedMedium() throws Exception
|
||||
{
|
||||
assertIsGzipCompressed("file.txt",MEDIUM);
|
||||
assertIsGzipCompressed("file-med.txt",MEDIUM);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -137,54 +135,54 @@ public class GzipFilterContentLengthTest
|
|||
@Test
|
||||
public void testIsGzipCompressedLarge() throws Exception
|
||||
{
|
||||
assertIsGzipCompressed("file.txt",LARGE);
|
||||
assertIsGzipCompressed("file-large.txt",LARGE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for problems with Content-Length header on small size files
|
||||
* Tests for problems with Content-Length header on small size files
|
||||
* that are not being compressed encountered when using GzipFilter
|
||||
*
|
||||
*
|
||||
* @see <a href="Eclipse Bug 354014">http://bugs.eclipse.org/354014</a>
|
||||
*/
|
||||
@Test
|
||||
public void testIsNotGzipCompressedTiny() throws Exception
|
||||
{
|
||||
assertIsNotGzipCompressed("file.txt",TINY);
|
||||
assertIsNotGzipCompressed("file-tiny.txt",TINY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for problems with Content-Length header on small size files
|
||||
* Tests for problems with Content-Length header on small size files
|
||||
* that are not being compressed encountered when using GzipFilter
|
||||
*
|
||||
*
|
||||
* @see <a href="Eclipse Bug 354014">http://bugs.eclipse.org/354014</a>
|
||||
*/
|
||||
@Test
|
||||
public void testIsNotGzipCompressedSmall() throws Exception
|
||||
{
|
||||
assertIsNotGzipCompressed("file.mp3",SMALL);
|
||||
assertIsNotGzipCompressed("file-small.mp3",SMALL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for problems with Content-Length header on medium size files
|
||||
* Tests for problems with Content-Length header on medium size files
|
||||
* that are not being compressed encountered when using GzipFilter
|
||||
*
|
||||
*
|
||||
* @see <a href="Eclipse Bug 354014">http://bugs.eclipse.org/354014</a>
|
||||
*/
|
||||
@Test
|
||||
public void testIsNotGzipCompressedMedium() throws Exception
|
||||
{
|
||||
assertIsNotGzipCompressed("file.mp3",MEDIUM);
|
||||
assertIsNotGzipCompressed("file-medium.mp3",MEDIUM);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for problems with Content-Length header on large size files
|
||||
* Tests for problems with Content-Length header on large size files
|
||||
* that were not being compressed encountered when using GzipFilter
|
||||
*
|
||||
*
|
||||
* @see <a href="Eclipse Bug 354014">http://bugs.eclipse.org/354014</a>
|
||||
*/
|
||||
@Test
|
||||
public void testIsNotGzipCompressedLarge() throws Exception
|
||||
{
|
||||
assertIsNotGzipCompressed("file.mp3",LARGE);
|
||||
assertIsNotGzipCompressed("file-large.mp3",LARGE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.servlets;
|
||||
|
||||
import javax.servlet.Servlet;
|
||||
|
||||
import org.eclipse.jetty.servlet.FilterHolder;
|
||||
import org.eclipse.jetty.servlets.gzip.GzipTester;
|
||||
import org.eclipse.jetty.servlets.gzip.TestMinGzipSizeServlet;
|
||||
import org.eclipse.jetty.toolchain.test.TestingDir;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Perform specific tests on the IncludableGzipFilter's ability to manage
|
||||
* minGzipSize initialization parameter.
|
||||
*
|
||||
* @see <a href="Eclipse Bug 366106">http://bugs.eclipse.org/366106</a>
|
||||
*/
|
||||
public class IncludableGzipFilterMinSizeTest
|
||||
{
|
||||
@Rule
|
||||
public TestingDir testdir = new TestingDir();
|
||||
|
||||
private Class<? extends Servlet> testServlet = TestMinGzipSizeServlet.class;
|
||||
|
||||
@Test
|
||||
public void testUnderMinSize() throws Exception
|
||||
{
|
||||
GzipTester tester = new GzipTester(testdir);
|
||||
// Use IncludableGzipFilter
|
||||
tester.setGzipFilterClass(IncludableGzipFilter.class);
|
||||
|
||||
FilterHolder holder = tester.setContentServlet(testServlet);
|
||||
// A valid mime type that we will never use in this test.
|
||||
// configured here to prevent mimeType==null logic
|
||||
holder.setInitParameter("mimeTypes","application/soap+xml");
|
||||
holder.setInitParameter("minGzipSize", "2048");
|
||||
holder.setInitParameter("uncheckedPrintWriter","true");
|
||||
|
||||
tester.copyTestServerFile("small_script.js");
|
||||
|
||||
try {
|
||||
tester.start();
|
||||
tester.assertIsResponseNotGzipFiltered("small_script.js",
|
||||
"small_script.js.sha1",
|
||||
"text/javascript; charset=utf-8");
|
||||
} finally {
|
||||
tester.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOverMinSize() throws Exception
|
||||
{
|
||||
GzipTester tester = new GzipTester(testdir);
|
||||
// Use IncludableGzipFilter
|
||||
tester.setGzipFilterClass(IncludableGzipFilter.class);
|
||||
|
||||
FilterHolder holder = tester.setContentServlet(testServlet);
|
||||
holder.setInitParameter("mimeTypes","application/soap+xml,text/javascript");
|
||||
holder.setInitParameter("minGzipSize", "2048");
|
||||
holder.setInitParameter("uncheckedPrintWriter","true");
|
||||
|
||||
tester.copyTestServerFile("big_script.js");
|
||||
|
||||
try {
|
||||
tester.start();
|
||||
tester.assertIsResponseGzipCompressed("big_script.js");
|
||||
} finally {
|
||||
tester.stop();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,12 +1,5 @@
|
|||
package org.eclipse.jetty.servlets.gzip;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
|
@ -19,7 +12,6 @@ import java.util.Enumeration;
|
|||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
import javax.servlet.Servlet;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
|
@ -34,8 +26,15 @@ import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
|||
import org.eclipse.jetty.toolchain.test.TestingDir;
|
||||
import org.junit.Assert;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
|
||||
public class GzipTester
|
||||
{
|
||||
private Class<? extends GzipFilter> gzipFilterClass = GzipFilter.class;
|
||||
private String encoding = "ISO8859_1";
|
||||
private ServletTester servletTester;
|
||||
private TestingDir testdir;
|
||||
|
@ -44,7 +43,7 @@ public class GzipTester
|
|||
{
|
||||
this.testdir = testingdir;
|
||||
// Make sure we start with a clean testing directory.
|
||||
this.testdir.ensureEmpty();
|
||||
// DOES NOT WORK IN WINDOWS - this.testdir.ensureEmpty();
|
||||
}
|
||||
|
||||
public void assertIsResponseGzipCompressed(String filename) throws Exception
|
||||
|
@ -109,7 +108,7 @@ public class GzipTester
|
|||
* <p>
|
||||
* An example is to test that it is possible to configure GzipFilter to not recompress content that shouldn't be
|
||||
* compressed by the GzipFilter.
|
||||
*
|
||||
*
|
||||
* @param requestedFilename
|
||||
* the filename used to on the GET request,.
|
||||
* @param testResourceSha1Sum
|
||||
|
@ -192,7 +191,7 @@ public class GzipTester
|
|||
/**
|
||||
* Asserts that the requested filename results in a properly structured GzipFilter response, where the content is
|
||||
* not compressed, and the content-length is returned appropriately.
|
||||
*
|
||||
*
|
||||
* @param filename
|
||||
* the filename used for the request, and also used to compare the response to the server file, assumes
|
||||
* that the file is suitable for {@link Assert#assertEquals(Object, Object)} use. (in other words, the
|
||||
|
@ -233,7 +232,7 @@ public class GzipTester
|
|||
Assert.assertThat("Response.header[Content-Length]",serverLength,is(expectedFilesize));
|
||||
}
|
||||
Assert.assertThat("Response.header[Content-Encoding]",response.getHeader("Content-Encoding"),not(containsString("gzip")));
|
||||
|
||||
|
||||
// Assert that the contents are what we expect.
|
||||
if (filename != null)
|
||||
{
|
||||
|
@ -259,13 +258,13 @@ public class GzipTester
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Generate string content of arbitrary length.
|
||||
*
|
||||
*
|
||||
* @param length
|
||||
* the length of the string to generate.
|
||||
* @return the string content.
|
||||
|
@ -306,37 +305,56 @@ public class GzipTester
|
|||
|
||||
/**
|
||||
* Create a file on the server resource path of a specified filename and size.
|
||||
*
|
||||
*
|
||||
* @param filename
|
||||
* the filename to create
|
||||
* @param filesize
|
||||
* the file size to create (Note: this isn't suitable for creating large multi-megabyte files)
|
||||
*/
|
||||
public void prepareServerFile(String filename, int filesize) throws IOException
|
||||
public File prepareServerFile(String filename, int filesize) throws IOException
|
||||
{
|
||||
File testFile = testdir.getFile(filename);
|
||||
File dir = testdir.getDir();
|
||||
File testFile = new File(dir,filename);
|
||||
// Make sure we have a uniq filename (to work around windows File.delete bug)
|
||||
int i = 0;
|
||||
while (testFile.exists())
|
||||
{
|
||||
testFile = new File(dir,(i++) + "-" + filename);
|
||||
}
|
||||
|
||||
FileOutputStream fos = null;
|
||||
BufferedOutputStream out = null;
|
||||
ByteArrayInputStream in = null;
|
||||
try
|
||||
{
|
||||
fos = new FileOutputStream(testFile,false);
|
||||
out = new BufferedOutputStream(fos);
|
||||
in = new ByteArrayInputStream(generateContent(filesize).getBytes(encoding));
|
||||
IO.copy(in,out);
|
||||
IO.copy(in,fos);
|
||||
return testFile;
|
||||
}
|
||||
finally
|
||||
{
|
||||
IO.close(in);
|
||||
IO.close(out);
|
||||
IO.close(fos);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy a src/test/resource file into the server tree for eventual serving.
|
||||
*
|
||||
* @param filename
|
||||
* the filename to look for in src/test/resources
|
||||
*/
|
||||
public void copyTestServerFile(String filename) throws IOException
|
||||
{
|
||||
File srcFile = MavenTestingUtils.getTestResourceFile(filename);
|
||||
File testFile = testdir.getFile(filename);
|
||||
|
||||
IO.copy(srcFile,testFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the servlet that provides content for the GzipFilter in being tested.
|
||||
*
|
||||
*
|
||||
* @param servletClass
|
||||
* the servlet that will provide content.
|
||||
* @return the FilterHolder for configuring the GzipFilter's initParameters with
|
||||
|
@ -348,11 +366,19 @@ public class GzipTester
|
|||
servletTester.setResourceBase(testdir.getDir().getCanonicalPath());
|
||||
ServletHolder servletHolder = servletTester.addServlet(servletClass,"/");
|
||||
servletHolder.setInitParameter("baseDir",testdir.getDir().getAbsolutePath());
|
||||
FilterHolder holder = servletTester.addFilter(GzipFilter.class,"/*",0);
|
||||
FilterHolder holder = servletTester.addFilter(gzipFilterClass,"/*",0);
|
||||
return holder;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public Class<? extends GzipFilter> getGzipFilterClass()
|
||||
{
|
||||
return gzipFilterClass;
|
||||
}
|
||||
|
||||
public void setGzipFilterClass(Class<? extends GzipFilter> gzipFilterClass)
|
||||
{
|
||||
this.gzipFilterClass = gzipFilterClass;
|
||||
}
|
||||
|
||||
public void setEncoding(String encoding)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
package org.eclipse.jetty.servlets.gzip;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.http.MimeTypes;
|
||||
import org.eclipse.jetty.io.Buffer;
|
||||
|
||||
/**
|
||||
* Test servlet for testing against unusual minGzip configurable.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class TestMinGzipSizeServlet extends TestDirContentServlet
|
||||
{
|
||||
private MimeTypes mimeTypes;
|
||||
|
||||
@Override
|
||||
public void init(ServletConfig config) throws ServletException
|
||||
{
|
||||
super.init(config);
|
||||
mimeTypes = new MimeTypes();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||
{
|
||||
String fileName = request.getServletPath();
|
||||
byte[] dataBytes = loadContentFileBytes(fileName);
|
||||
|
||||
response.setContentLength(dataBytes.length);
|
||||
if (fileName.endsWith(".js"))
|
||||
{
|
||||
// intentionally long-form content type to test ";" splitting in code
|
||||
response.setContentType("text/javascript; charset=utf-8");
|
||||
}
|
||||
else
|
||||
{
|
||||
Buffer buf = mimeTypes.getMimeByExtension(fileName);
|
||||
if (buf != null)
|
||||
{
|
||||
response.setContentType(buf.toString());
|
||||
}
|
||||
}
|
||||
ServletOutputStream out = response.getOutputStream();
|
||||
out.write(dataBytes);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,792 @@
|
|||
//----------------------------------------------------------------------
|
||||
//
|
||||
// Silly / Pointless Javascript to test GZIP compression.
|
||||
//
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
var LOGO = {
|
||||
dat: [
|
||||
0x50, 0x89, 0x47, 0x4e, 0x0a, 0x0d, 0x0a, 0x1a, 0x00, 0x00, 0x0d, 0x00, 0x48, 0x49, 0x52, 0x44,
|
||||
0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x78, 0x00, 0x06, 0x08, 0x00, 0x00, 0x2a, 0x00, 0x21, 0x96,
|
||||
0x00, 0x0f, 0x00, 0x00, 0x73, 0x04, 0x49, 0x42, 0x08, 0x54, 0x08, 0x08, 0x7c, 0x08, 0x64, 0x08,
|
||||
0x00, 0x88, 0x00, 0x00, 0x70, 0x09, 0x59, 0x48, 0x00, 0x73, 0x04, 0x00, 0x00, 0x27, 0x04, 0x00,
|
||||
0x01, 0x27, 0x4f, 0xd9, 0x80, 0x1d, 0x00, 0x00, 0x19, 0x00, 0x45, 0x74, 0x74, 0x58, 0x6f, 0x53,
|
||||
0x74, 0x66, 0x61, 0x77, 0x65, 0x72, 0x77, 0x00, 0x77, 0x77, 0x69, 0x2e, 0x6b, 0x6e, 0x63, 0x73,
|
||||
0x70, 0x61, 0x2e, 0x65, 0x72, 0x6f, 0x9b, 0x67, 0x3c, 0xee, 0x00, 0x1a, 0x20, 0x00, 0x49, 0x00,
|
||||
0x41, 0x44, 0x78, 0x54, 0xed, 0x9c, 0x79, 0x9d, 0x1c, 0xd8, 0x95, 0x55, 0x3f, 0xff, 0xfb, 0xa7,
|
||||
0xb2, 0xdd, 0x24, 0xef, 0x24, 0x81, 0x81, 0x2c, 0x20, 0x40, 0xd5, 0x91, 0x8b, 0xb0, 0x3f, 0xbb,
|
||||
0x1d, 0x04, 0x54, 0x1c, 0x46, 0x74, 0x17, 0x18, 0xd1, 0x98, 0x19, 0xd1, 0x05, 0x11, 0x37, 0xf4,
|
||||
0xe2, 0x8f, 0xcc, 0xb8, 0x28, 0x8c, 0x82, 0x02, 0x22, 0x8c, 0xe0, 0xe8, 0xe2, 0x86, 0x02, 0x88,
|
||||
0x8e, 0xa2, 0x08, 0xe8, 0x42, 0x42, 0x4b, 0x08, 0xc2, 0xc8, 0x12, 0x12, 0xf6, 0x42, 0x7d, 0x90,
|
||||
0xf7, 0x7d, 0x3e, 0xee, 0x47, 0xf3, 0x77, 0x75, 0xeb, 0x6a, 0xdf, 0x7e, 0xee, 0xea, 0xab, 0x7b,
|
||||
0xdc, 0x93, 0xf3, 0xcf, 0xd0, 0xf0, 0xa9, 0x55, 0x53, 0xae, 0x6f, 0x5d, 0x3d, 0xd5, 0x9e, 0xf7,
|
||||
0xee, 0x7b, 0x8a, 0xf9, 0xe2, 0xaa, 0x38, 0x70, 0x0e, 0x1c, 0xc3, 0x87, 0x99, 0x2e, 0x2f, 0xb4,
|
||||
0xe1, 0xc0, 0x38, 0x70, 0x8e, 0x1c, 0x11, 0x83, 0x80, 0xe7, 0x0e, 0x1d, 0xc3, 0x87, 0x48, 0xe1,
|
||||
0xe7, 0x01, 0x1d, 0x80, 0x87, 0x0e, 0xe1, 0xc3, 0x01, 0x48, 0x80, 0xe7, 0x0e, 0x1d, 0xc3, 0x87,
|
||||
0x48, 0xe1, 0xe7, 0x01, 0x1d, 0x80, 0x87, 0x0e, 0xe1, 0xc3, 0x01, 0x48, 0x80, 0xe7, 0x0e, 0x1d,
|
||||
0xc3, 0x87, 0x48, 0xe1, 0xe7, 0x01, 0x1d, 0x80, 0x87, 0x0e, 0xe1, 0xc3, 0x01, 0x48, 0x80, 0xe7,
|
||||
0x0e, 0x1d, 0xc3, 0x87, 0x48, 0xe1, 0xe7, 0x01, 0x1d, 0x80, 0x87, 0x0e, 0xe1, 0xc3, 0x01, 0x48,
|
||||
0x80, 0xe7, 0x0e, 0x1d, 0xc3, 0x87, 0x48, 0xe1, 0xe7, 0x01, 0x1d, 0x80, 0x87, 0x0e, 0xe1, 0xc3,
|
||||
0x01, 0x48, 0x80, 0xe7, 0x0e, 0x1d, 0xc3, 0x87, 0x48, 0xe1, 0x96, 0x81, 0x2f, 0xb4, 0x44, 0x40,
|
||||
0x2c, 0x3a, 0xe9, 0x98, 0xa7, 0x55, 0xe1, 0x3a, 0x38, 0x70, 0x8e, 0x1c, 0x42, 0x26, 0xf0, 0xd2,
|
||||
0x22, 0x4b, 0x16, 0x32, 0x0c, 0xb8, 0x02, 0xb8, 0xde, 0x38, 0xc9, 0x82, 0xe0, 0x4e, 0x80, 0xbf,
|
||||
0xa9, 0x4f, 0xbf, 0x6a, 0x7b, 0x05, 0x88, 0xb1, 0x6c, 0xc8, 0xc3, 0xe0, 0xfb, 0xc0, 0xd1, 0x81,
|
||||
0xcd, 0x86, 0x81, 0xe5, 0xc0, 0xe5, 0xab, 0xdf, 0x02, 0xea, 0xb6, 0xc3, 0x0e, 0x1c, 0xa3, 0x87,
|
||||
0x44, 0x6e, 0x12, 0x64, 0x29, 0x70, 0x41, 0xf0, 0x7a, 0x60, 0xaf, 0xc2, 0x01, 0x77, 0x80, 0xf3,
|
||||
0x55, 0x9b, 0x21, 0xf5, 0xf6, 0x0b, 0x81, 0xba, 0x81, 0xc7, 0x54, 0x5b, 0x77, 0xf5, 0xbf, 0x09,
|
||||
0xd9, 0xeb, 0xed, 0xb7, 0x45, 0x80, 0x0b, 0x24, 0x04, 0x2c, 0x5b, 0x66, 0xec, 0x35, 0x28, 0xf1,
|
||||
0xd7, 0xf0, 0xba, 0xaa, 0xb6, 0xd5, 0x11, 0x61, 0x23, 0x79, 0x27, 0xf0, 0x76, 0xdb, 0x5e, 0x81,
|
||||
0x27, 0x3c, 0xc3, 0xfc, 0x6c, 0x14, 0x1c, 0x3b, 0xc7, 0x0e, 0x10, 0xa0, 0x23, 0x91, 0x67, 0x81,
|
||||
0x91, 0x81, 0x9e, 0x75, 0x13, 0xaa, 0x4b, 0x38, 0x17, 0x55, 0xb2, 0x5b, 0x05, 0xd7, 0xa3, 0x9c,
|
||||
0x0b, 0xaa, 0x7e, 0x93, 0x8d, 0x31, 0xe0, 0x39, 0x48, 0x2b, 0xf9, 0xc7, 0x9c, 0x02, 0xbc, 0x0b,
|
||||
0xb6, 0xdb, 0x62, 0xd1, 0xe3, 0xa7, 0xdb, 0x66, 0x8b, 0x76, 0x03, 0xb4, 0xa5, 0x37, 0xdb, 0x64,
|
||||
0x70, 0xe1, 0x06, 0x38, 0x2d, 0xcb, 0xef, 0xd4, 0x01, 0x0c, 0x01, 0x86, 0x8b, 0xf7, 0xab, 0x48,
|
||||
0x7b, 0x25, 0x81, 0x43, 0x0d, 0x5f, 0x5e, 0xc2, 0x34, 0x84, 0x80, 0xe6, 0x50, 0x3f, 0x20, 0xfa,
|
||||
0x98, 0x19, 0xfa, 0xfd, 0xd7, 0xc4, 0x0c, 0x9c, 0x96, 0x55, 0x92, 0x3c, 0x0b, 0x43, 0x3d, 0xe5,
|
||||
0xcc, 0x33, 0x8c, 0x1a, 0x0e, 0x65, 0xab, 0x30, 0x31, 0xb4, 0x4d, 0xb9, 0xd6, 0x98, 0xb6, 0x6e,
|
||||
0xf3, 0xef, 0x9f, 0x6a, 0xba, 0xb2, 0xfc, 0xb7, 0xc7, 0xa3, 0xc8, 0x88, 0x55, 0x04, 0x62, 0xdd,
|
||||
0xa8, 0xd4, 0xe1, 0xc3, 0xd4, 0x70, 0x71, 0x40, 0xee, 0x7a, 0xd2, 0x82, 0xb0, 0xf6, 0x30, 0x8c,
|
||||
0x58, 0x6b, 0x36, 0xb2, 0x55, 0x72, 0x81, 0x4f, 0xfd, 0x4d, 0x88, 0xe5, 0x34, 0xee, 0x69, 0xbc,
|
||||
0x63, 0x38, 0xd6, 0xf6, 0x16, 0xf4, 0xd8, 0xd8, 0xb6, 0x57, 0x38, 0x77, 0xa8, 0x50, 0x78, 0x72,
|
||||
0x56, 0x2c, 0xb0, 0x1d, 0xb4, 0x88, 0xa7, 0x03, 0xb6, 0x95, 0x1e, 0xa7, 0xe5, 0x97, 0x9f, 0x9a,
|
||||
0x33, 0x0f, 0x73, 0x6a, 0xba, 0xdb, 0x9f, 0x02, 0x79, 0x3c, 0x7f, 0xb7, 0x34, 0xd7, 0x06, 0xa3,
|
||||
0x39, 0xe3, 0xbf, 0xdb, 0xdd, 0x71, 0x76, 0x94, 0x9f, 0x2e, 0x66, 0xd8, 0xe0, 0xd4, 0xaf, 0x95,
|
||||
0x70, 0xf4, 0xab, 0xeb, 0xfe, 0x7d, 0x87, 0x5d, 0xce, 0x03, 0x3b, 0x01, 0x8e, 0x1c, 0xe4, 0x66,
|
||||
0xff, 0x5a, 0xa7, 0xc6, 0x6d, 0x0e, 0x8b, 0xe3, 0xdb, 0x53, 0xfd, 0x07, 0x02, 0xe5, 0xfc, 0x70,
|
||||
0xbd, 0xc2, 0x07, 0x7e, 0x53, 0xbc, 0xab, 0x55, 0xc4, 0x39, 0xea, 0x6b, 0xa7, 0xb1, 0x89, 0xc0,
|
||||
0xf6, 0x8b, 0x1d, 0xfa, 0xa7, 0x70, 0x56, 0xaa, 0xf8, 0x74, 0xb0, 0x95, 0x82, 0x1d, 0x15, 0x3e,
|
||||
0x24, 0x2f, 0xc0, 0x0a, 0x73, 0x31, 0xfb, 0xcc, 0x65, 0xff, 0xe4, 0x4f, 0xbb, 0xc2, 0x1a, 0x96,
|
||||
0x1a, 0x37, 0xe0, 0x25, 0xcf, 0x80, 0x69, 0x1a, 0x77, 0xfe, 0xdd, 0xcf, 0x78, 0x13, 0xf2, 0x16,
|
||||
0x32, 0xc0, 0x46, 0xe3, 0x0e, 0x1d, 0x23, 0x87, 0x22, 0x21, 0x38, 0x72, 0x49, 0x70, 0x7b, 0x69,
|
||||
0x46, 0x68, 0xc4, 0xf8, 0x64, 0xe4, 0x94, 0x03, 0xb7, 0x7b, 0xb3, 0xf5, 0x27, 0xa2, 0x6f, 0xe0,
|
||||
0xb6, 0x2b, 0x45, 0x77, 0xef, 0x7b, 0xc7, 0xab, 0x83, 0xde, 0x72, 0x3b, 0xdf, 0x3c, 0xb0, 0x15,
|
||||
0x3c, 0xb7, 0x09, 0xd1, 0xd8, 0x8a, 0xc0, 0x76, 0x47, 0x01, 0x63, 0x34, 0xd6, 0x4e, 0xc1, 0xb8,
|
||||
0x16, 0x97, 0x3a, 0x44, 0x8f, 0x25, 0x37, 0x19, 0xe5, 0x1a, 0xd2, 0xac, 0xb1, 0x87, 0xc2, 0x2d,
|
||||
0x21, 0xcc, 0x6f, 0x66, 0xde, 0xfb, 0xb2, 0xbc, 0x2b, 0xb8, 0xbb, 0xf0, 0xa8, 0x97, 0x1e, 0xea,
|
||||
0x46, 0xa3, 0x0e, 0x1d, 0xa3, 0x87, 0x3e, 0x36, 0x2f, 0x8d, 0xfb, 0x1a, 0x43, 0xa1, 0x19, 0x5a,
|
||||
0x22, 0xdf, 0x4e, 0x89, 0xfd, 0x70, 0xbe, 0xfa, 0xae, 0xf0, 0xcd, 0x1b, 0xeb, 0xda, 0xef, 0x0d,
|
||||
0x66, 0xfa, 0x13, 0xa2, 0xb1, 0x14, 0x07, 0x3d, 0x74, 0x1c, 0xa7, 0xc0, 0x37, 0x9b, 0xd2, 0xff,
|
||||
0xc0, 0xfc, 0x38, 0x08, 0xcc, 0x0f, 0x6e, 0x37, 0x87, 0xd4, 0x1c, 0x88, 0x1c, 0x03, 0xda, 0x52,
|
||||
0x63, 0x3e, 0x96, 0x44, 0x7f, 0x64, 0xe4, 0xea, 0xd8, 0x2c, 0x27, 0x9b, 0x4c, 0x1f, 0x9f, 0x6e,
|
||||
0xd8, 0x6b, 0x01, 0xe4, 0x88, 0x83, 0x0d, 0x1c, 0x0e, 0x5c, 0x07, 0x9c, 0xff, 0x46, 0x0a, 0x54,
|
||||
0xc2, 0x6c, 0x32, 0x5b, 0x67, 0xf1, 0x46, 0x53, 0x64, 0x44, 0x5e, 0x08, 0xe1, 0xe2, 0x62, 0xdf,
|
||||
0xe9, 0x7e, 0x37, 0x5b, 0x08, 0xf0, 0x15, 0xf0, 0x8d, 0x55, 0x9e, 0x84, 0x8e, 0x1c, 0x22, 0x30,
|
||||
0x1e, 0x32, 0x48, 0xf8, 0xbb, 0x69, 0xe0, 0x45, 0x43, 0xaa, 0x8d, 0x93, 0xff, 0x46, 0x57, 0x77,
|
||||
0x67, 0x8e, 0x03, 0x3a, 0x8e, 0x03, 0xc0, 0x15, 0x9b, 0x7f, 0x37, 0xb2, 0x4f, 0x77, 0x79, 0x9e,
|
||||
0x08, 0xc1, 0x1a, 0xe3, 0xee, 0xe0, 0x27, 0x44, 0xd9, 0x29, 0xe5, 0xaf, 0x75, 0x4b, 0x1e, 0x50,
|
||||
0x8e, 0x09, 0x98, 0x9e, 0xc2, 0x61, 0xb3, 0x34, 0xc1, 0x23, 0xdd, 0xae, 0xda, 0xca, 0x03, 0x17,
|
||||
0x6a, 0x37, 0xaa, 0x91, 0x35, 0xee, 0x34, 0x6a, 0x30, 0x4a, 0x3c, 0xfc, 0xfc, 0xc2, 0x3f, 0xa8,
|
||||
0x7e, 0x14, 0xe7, 0x06, 0x07, 0x80, 0x88, 0x85, 0x1b, 0xfc, 0x59, 0xf0, 0x3a, 0xcc, 0x30, 0xde,
|
||||
0x88, 0x17, 0xa7, 0xc8, 0xf5, 0x55, 0x8d, 0x5b, 0xb1, 0x3e, 0xcc, 0x88, 0x8b, 0xc2, 0x8c, 0xf8,
|
||||
0xf4, 0x6a, 0xab, 0xb9, 0x7a, 0xf0, 0xf5, 0xe0, 0xf2, 0x22, 0x55, 0x5e, 0x6c, 0xdd, 0xae, 0xd1,
|
||||
0xff, 0x63, 0x9f, 0xe4, 0xb2, 0xf0, 0x01, 0x88, 0xef, 0x78, 0x56, 0xb8, 0x4f, 0x0e, 0xa0, 0x98,
|
||||
0xb5, 0xfa, 0xe8, 0xe8, 0x1b, 0xf7, 0xe6, 0x55, 0xeb, 0x7f, 0x17, 0xb6, 0xfa, 0x37, 0xb5, 0xad,
|
||||
0x69, 0xc3, 0x04, 0x2d, 0x22, 0x2d, 0x80, 0x33, 0xa5, 0x09, 0x1b, 0x6d, 0xe7, 0xe1, 0x4f, 0x15,
|
||||
0xb2, 0x05, 0x21, 0x9f, 0x47, 0x1d, 0x70, 0x14, 0x67, 0xc0, 0x30, 0x8f, 0xe7, 0xdf, 0xe7, 0x99,
|
||||
0x70, 0x1c, 0x44, 0x62, 0x38, 0xe4, 0x6a, 0xe0, 0x3a, 0xec, 0xf0, 0x5f, 0xc1, 0x3a, 0x8b, 0x37,
|
||||
0x39, 0xc8, 0xce, 0x06, 0x13, 0x7d, 0x9d, 0x76, 0x89, 0x6f, 0x80, 0xf3, 0x52, 0xdb, 0xeb, 0xb0,
|
||||
0x8f, 0xd8, 0x91, 0x10, 0xc0, 0x61, 0xfc, 0x27, 0xae, 0xfb, 0x6c, 0x39, 0x89, 0xf0, 0x00, 0x50,
|
||||
0x74, 0xcf, 0xf9, 0xe6, 0xae, 0xd3, 0xef, 0x80, 0x04, 0xdb, 0x65, 0xdc, 0xde, 0xca, 0x5d, 0x73,
|
||||
0x7e, 0x05, 0x23, 0xbb, 0x6f, 0x60, 0x70, 0x1b, 0xa2, 0x47, 0xf8, 0x93, 0x39, 0xb0, 0xb6, 0x02,
|
||||
0x7e, 0x1f, 0xa2, 0x7e, 0xe6, 0x29, 0xcb, 0x7f, 0xbb, 0xbf, 0xe0, 0x55, 0xe1, 0xb4, 0x3b, 0x66,
|
||||
0x05, 0x1e, 0x7e, 0x60, 0x01, 0xd0, 0x53, 0xaf, 0x35, 0xd5, 0x8d, 0x46, 0x18, 0x1e, 0x13, 0xfc,
|
||||
0xf7, 0xbe, 0x3d, 0xa1, 0x3e, 0x63, 0xdc, 0xfe, 0xec, 0x1b, 0xce, 0x1c, 0x81, 0xa4, 0x67, 0xcf,
|
||||
0x99, 0x71, 0x9b, 0xc5, 0xdb, 0x4a, 0xf1, 0x59, 0x3f, 0x9e, 0xf4, 0x93, 0x02, 0x15, 0x30, 0xeb,
|
||||
0x9a, 0x66, 0xe6, 0xb5, 0x00, 0x38, 0x02, 0xb8, 0x5b, 0x18, 0x38, 0xda, 0x4c, 0x7f, 0xb3, 0x0b,
|
||||
0x26, 0x86, 0x8d, 0x1d, 0x46, 0x46, 0x37, 0xbf, 0x6a, 0xa9, 0x85, 0x4f, 0x2f, 0xc3, 0xd7, 0xaf,
|
||||
0xd7, 0xde, 0xf4, 0x37, 0x2a, 0x12, 0x75, 0x5d, 0xaa, 0xab, 0x26, 0x76, 0x89, 0x3a, 0xf4, 0x8f,
|
||||
0x70, 0x1c, 0x19, 0x3a, 0x56, 0xd0, 0x82, 0x47, 0x32, 0x22, 0x38, 0x0e, 0xb4, 0xae, 0xca, 0x7d,
|
||||
0x2c, 0xf0, 0xf3, 0x86, 0x58, 0xaf, 0x99, 0xd2, 0x4f, 0x67, 0x02, 0x70, 0x8d, 0xd8, 0x07, 0x7e,
|
||||
0x79, 0x47, 0xda, 0x04, 0x81, 0x9e, 0xaf, 0xed, 0x89, 0x1d, 0xa5, 0xc9, 0x8b, 0xda, 0xf3, 0x3b,
|
||||
0xb2, 0x9c, 0xf0, 0x38, 0x1e, 0xde, 0x60, 0xd3, 0x81, 0x13, 0xf5, 0x11, 0x87, 0xf5, 0xf0, 0x77,
|
||||
0x84, 0xc9, 0x9e, 0x99, 0x79, 0x49, 0x73, 0xd3, 0x3c, 0x5d, 0xbb, 0xb2, 0xce, 0xfc, 0x17, 0x4d,
|
||||
0x71, 0x11, 0xd8, 0x35, 0x71, 0x1d, 0x8b, 0x14, 0x5c, 0x56, 0xdf, 0xe5, 0xed, 0x77, 0xc9, 0xa1,
|
||||
0xa3, 0x46, 0x7a, 0x2b, 0xdc, 0x0a, 0x2d, 0xbb, 0x59, 0x50, 0x37, 0x78, 0x9f, 0xf0, 0xec, 0x55,
|
||||
0xba, 0x7d, 0x7b, 0x1e, 0x7a, 0x6b, 0xfc, 0x0b, 0x6b, 0x6c, 0x5e, 0xc0, 0x5e, 0x17, 0x8f, 0x31,
|
||||
0xb1, 0x9a, 0x05, 0x99, 0x76, 0x5d, 0x6d, 0xc0, 0x84, 0x43, 0x67, 0xc3, 0x1d, 0x9b, 0xe6, 0x09,
|
||||
0xe1, 0xfb, 0x67, 0xe5, 0x23, 0x02, 0x55, 0xc1, 0xba, 0xaa, 0xa8, 0xde, 0x28, 0xd1, 0xe2, 0x67,
|
||||
0x48, 0x1b, 0x9d, 0x9d, 0xfc, 0xce, 0x3c, 0xef, 0x46, 0xe3, 0x73, 0xf7, 0x64, 0x44, 0xbe, 0x14,
|
||||
0x29, 0x42, 0x0c, 0xa7, 0x1a, 0xcb, 0xbe, 0x75, 0xfb, 0x10, 0x6a, 0x77, 0xb3, 0xf4, 0x70, 0x19,
|
||||
0xa6, 0xc0, 0xbd, 0x9f, 0xc2, 0x9c, 0x7b, 0x93, 0xbf, 0x03, 0xa3, 0x69, 0xbe, 0x73, 0x2a, 0x8e,
|
||||
0x0d, 0xfc, 0xb5, 0x30, 0x71, 0xb4, 0x88, 0xc6, 0xe7, 0x2c, 0x4c, 0x8c, 0x8c, 0xf6, 0x73, 0x7e,
|
||||
0x5f, 0x43, 0xf2, 0xb8, 0x77, 0xc5, 0x75, 0x55, 0x85, 0x57, 0xdf, 0xc3, 0xaf, 0x5f, 0x1b, 0xbd,
|
||||
0xf6, 0x37, 0x0b, 0x91, 0xd1, 0x3e, 0xa8, 0x77, 0xb6, 0xea, 0x27, 0x44, 0x61, 0x09, 0x01, 0xc5,
|
||||
0x47, 0x17, 0xc7, 0x82, 0xb6, 0x96, 0x9f, 0xa7, 0x25, 0x92, 0x78, 0x6b, 0xbc, 0x00, 0x49, 0x6a,
|
||||
0xbe, 0x9e, 0xc0, 0xee, 0x4a, 0xdd, 0xfc, 0x23, 0x68, 0x1c, 0xcf, 0x04, 0xf3, 0x72, 0xcd, 0xbf,
|
||||
0x59, 0xca, 0xde, 0xf8, 0x1b, 0x05, 0x25, 0x1d, 0x7f, 0x0b, 0xf2, 0xa7, 0x37, 0xb3, 0x23, 0x34,
|
||||
0x34, 0x9c, 0xec, 0xcc, 0x7a, 0x6f, 0x33, 0xb6, 0x57, 0x4f, 0x45, 0xc1, 0x1c, 0x5e, 0x23, 0x03,
|
||||
0x42, 0x22, 0x10, 0xa8, 0xb5, 0xc6, 0xe7, 0x09, 0x5f, 0x62, 0x57, 0xed, 0xda, 0xee, 0x08, 0x12,
|
||||
0xf7, 0x3f, 0x61, 0x52, 0x51, 0xe9, 0xec, 0x23, 0xcb, 0x6d, 0x77, 0x29, 0x0a, 0x6e, 0x7e, 0x8c,
|
||||
0xc0, 0x73, 0x89, 0x0d, 0x12, 0x4e, 0xad, 0x83, 0xf0, 0x11, 0xf8, 0x59, 0x82, 0x46, 0xc2, 0x36,
|
||||
0x2f, 0xcf, 0x48, 0x2d, 0xfc, 0x37, 0x24, 0x5c, 0x76, 0x10, 0xd3, 0x3f, 0xc3, 0x7e, 0x89, 0xde,
|
||||
0x6c, 0x57, 0x51, 0xdc, 0x50, 0x9d, 0xba, 0xa6, 0x8e, 0xf5, 0x17, 0x52, 0xfc, 0x0d, 0x89, 0x3b,
|
||||
0x14, 0xc8, 0x15, 0x7c, 0x5e, 0xdf, 0x3c, 0x3b, 0xc2, 0x4b, 0x8e, 0x65, 0x71, 0x89, 0xf7, 0x99,
|
||||
0x04, 0x8e, 0x03, 0xbc, 0x0a, 0x9f, 0xf1, 0xde, 0x32, 0x43, 0x38, 0x5c, 0xd9, 0x26, 0x77, 0x3b,
|
||||
0xc6, 0xcb, 0x70, 0xbe, 0xc5, 0x0e, 0x54, 0x8f, 0x63, 0x75, 0xc3, 0x85, 0x04, 0x2f, 0xa8, 0x4e,
|
||||
0xde, 0xc7, 0x37, 0xb7, 0x85, 0xf6, 0x98, 0x3b, 0x37, 0x77, 0xb7, 0x22, 0x96, 0xc6, 0x0e, 0x03,
|
||||
0x60, 0x25, 0x28, 0x59, 0x11, 0xc0, 0xff, 0x9d, 0x3a, 0xb5, 0x16, 0x02, 0x36, 0x91, 0x65, 0x7c,
|
||||
0x8f, 0x37, 0xc8, 0xee, 0xd1, 0x30, 0x16, 0x70, 0xba, 0xcc, 0x02, 0xbe, 0x82, 0x6b, 0xe5, 0x4f,
|
||||
0xb5, 0x13, 0x47, 0x94, 0x08, 0x3b, 0x44, 0x09, 0x4c, 0x2a, 0x94, 0x77, 0x07, 0xd6, 0x74, 0xeb,
|
||||
0xf7, 0x83, 0x6a, 0x77, 0xba, 0xe4, 0xab, 0x59, 0x67, 0xe1, 0x91, 0x70, 0x47, 0x17, 0x02, 0x22,
|
||||
0x27, 0x65, 0x73, 0x3f, 0x7b, 0x58, 0x84, 0xa2, 0xdd, 0xc7, 0xe5, 0x79, 0xc1, 0x3b, 0xbb, 0x32,
|
||||
0xe0, 0x05, 0xa6, 0xeb, 0x75, 0xec, 0x94, 0x16, 0x07, 0x6f, 0x29, 0xed, 0x7d, 0x70, 0x53, 0x82,
|
||||
0xc4, 0x54, 0x03, 0x96, 0x27, 0x2e, 0x88, 0x98, 0x31, 0xc0, 0xd9, 0xa7, 0x80, 0xc8, 0xb4, 0x0e,
|
||||
0x3b, 0x67, 0xe7, 0x81, 0x1b, 0x8c, 0x32, 0x0d, 0xe8, 0x0d, 0x6d, 0x28, 0x58, 0xd8, 0xeb, 0xff,
|
||||
0xc1, 0x1a, 0x14, 0xe4, 0x33, 0x93, 0x94, 0xe6, 0x67, 0xb6, 0x64, 0x74, 0x60, 0x98, 0xa3, 0xb8,
|
||||
0x6f, 0x34, 0xf1, 0x8f, 0x4c, 0xe8, 0xf4, 0xa8, 0x8d, 0xa9, 0x2f, 0x67, 0x9b, 0xf0, 0x93, 0x76,
|
||||
0xc9, 0x4e, 0x47, 0x57, 0x53, 0x93, 0x6e, 0x5c, 0xae, 0x57, 0x31, 0x07, 0x2d, 0xb5, 0xfb, 0xc3,
|
||||
0x27, 0xc7, 0xe4, 0x13, 0xee, 0xf9, 0x7e, 0xa6, 0x05, 0x76, 0x4d, 0x13, 0xa5, 0x7f, 0x2f, 0xaa,
|
||||
0xb0, 0x55, 0x36, 0x77, 0xf7, 0xbe, 0x16, 0xa1, 0x77, 0x7b, 0xea, 0x6e, 0x5b, 0x67, 0xf2, 0x70,
|
||||
0x41, 0xf7, 0x6d, 0x55, 0xf3, 0xc8, 0x2b, 0x6d, 0xba, 0x0b, 0x54, 0x3c, 0x0c, 0x97, 0xf1, 0x7c,
|
||||
0xb3, 0x7c, 0x30, 0xb5, 0x05, 0x0a, 0xd7, 0x65, 0xc0, 0x96, 0x9b, 0x0d, 0x42, 0x97, 0xc8, 0x42,
|
||||
0xbc, 0x5a, 0x59, 0x9e, 0xe0, 0x06, 0x3b, 0x0f, 0x9c, 0x73, 0xb8, 0xba, 0x6c, 0xe6, 0x41, 0xf5,
|
||||
0xb9, 0xb1, 0xb2, 0x3f, 0x7c, 0xf6, 0x86, 0xc0, 0x58, 0xbd, 0x75, 0x17, 0xe9, 0x22, 0x53, 0x48,
|
||||
0x16, 0x0e, 0xf6, 0x05, 0xad, 0xe0, 0xdb, 0xf1, 0xcb, 0x5e, 0x52, 0xdf, 0x0e, 0x44, 0x5e, 0x25,
|
||||
0x63, 0x88, 0x30, 0x06, 0xb4, 0xa4, 0xc7, 0x61, 0x45, 0x59, 0x4a, 0x3a, 0x45, 0xbb, 0x8c, 0xe4,
|
||||
0x9a, 0x06, 0x43, 0x78, 0x43, 0xe9, 0x38, 0x06, 0xf0, 0xc3, 0xb7, 0xd2, 0x82, 0x57, 0x30, 0xaa,
|
||||
0x55, 0xe0, 0x9a, 0x22, 0x4d, 0xe3, 0xd5, 0xbd, 0x3f, 0x44, 0x52, 0xb0, 0x77, 0x55, 0x48, 0x88,
|
||||
0x38, 0x06, 0x5f, 0x11, 0x79, 0x0d, 0xf4, 0x43, 0x2b, 0x00, 0x16, 0x92, 0x11, 0xea, 0xc3, 0x91,
|
||||
0x25, 0xf0, 0x18, 0xf7, 0x7c, 0xa2, 0xaa, 0x3f, 0x47, 0x5c, 0x70, 0x2b, 0x60, 0x12, 0x01, 0xfa,
|
||||
0x01, 0xee, 0xd7, 0x96, 0xf4, 0xb1, 0xb3, 0xe6, 0x8d, 0xfe, 0x0f, 0x2b, 0x4b, 0x6d, 0x3c, 0xb4,
|
||||
0xb7, 0xae, 0xdf, 0x00, 0x18, 0xda, 0x84, 0x29, 0x35, 0xf1, 0xf6, 0x53, 0x15, 0xfa, 0xdc, 0x6e,
|
||||
0x59, 0x10, 0x54, 0xea, 0x5e, 0xcd, 0x6c, 0x22, 0xe0, 0x39, 0x1f, 0xf2, 0x90, 0xab, 0x0d, 0x87,
|
||||
0xad, 0xcb, 0x45, 0x47, 0x6b, 0xbf, 0x20, 0xdb, 0xdb, 0x5e, 0x03, 0xb7, 0x07, 0x18, 0xd2, 0x5e,
|
||||
0xab, 0xc0, 0x56, 0xfd, 0xf7, 0x7f, 0x40, 0xcb, 0xc4, 0xa4, 0xb1, 0x61, 0xc4, 0xe0, 0xc0, 0x25,
|
||||
0x78, 0x19, 0xf2, 0x21, 0x36, 0xf1, 0xaa, 0x2f, 0xf4, 0x01, 0xc8, 0x8b, 0xc0, 0xab, 0xe0, 0x02,
|
||||
0xc0, 0xd7, 0x55, 0x03, 0x1f, 0x32, 0x91, 0x11, 0x00, 0xb7, 0x0c, 0xff, 0xcf, 0x9c, 0x1a, 0x20,
|
||||
0x1b, 0x27, 0xbf, 0xf3, 0x77, 0x73, 0x9e, 0x47, 0x86, 0x83, 0xb3, 0x84, 0x98, 0xe2, 0x34, 0x39,
|
||||
0x68, 0xc3, 0x13, 0xc3, 0xf3, 0xc0, 0xbf, 0xa2, 0x14, 0xe7, 0xf1, 0xe0, 0x4f, 0x3a, 0x2d, 0xdb,
|
||||
0x77, 0x22, 0xef, 0x00, 0x53, 0xc4, 0xb2, 0xf2, 0x16, 0xc1, 0x79, 0x11, 0xaa, 0x8f, 0x32, 0x3e,
|
||||
0x81, 0xd0, 0xf2, 0x22, 0xe0, 0x0e, 0xc0, 0xe3, 0xb0, 0x5b, 0x79, 0xd3, 0x16, 0xed, 0x2b, 0x91,
|
||||
0xf5, 0x54, 0xa1, 0x27, 0x98, 0xeb, 0x5c, 0x02, 0x5c, 0x09, 0xaf, 0x86, 0x91, 0xd0, 0x36, 0x61,
|
||||
0xc8, 0x89, 0x55, 0xbb, 0xd1, 0x35, 0x5e, 0xb4, 0x32, 0xb1, 0xdb, 0xdb, 0xdb, 0x4b, 0x5b, 0x63,
|
||||
0xcb, 0x84, 0x26, 0x27, 0x8d, 0x1b, 0x68, 0xfe, 0x5f, 0x4b, 0xb3, 0xb8, 0x67, 0xf7, 0x7d, 0x55,
|
||||
0x82, 0xb2, 0x13, 0xbd, 0x49, 0xf0, 0xd6, 0x0e, 0xef, 0x62, 0x5b, 0x67, 0x59, 0xfb, 0x17, 0xdb,
|
||||
0xd8, 0x18, 0x4d, 0xcc, 0xbb, 0xfa, 0x61, 0xab, 0xb5, 0xbc, 0xf6, 0x29, 0xaf, 0x10, 0x6d, 0x34,
|
||||
0x0a, 0xa7, 0x50, 0x7f, 0xfb, 0xd5, 0xb0, 0x53, 0x59, 0xfb, 0xce, 0x8a, 0x25, 0x37, 0xad, 0x3e,
|
||||
0xe5, 0xaa, 0x9b, 0xae, 0x4c, 0x88, 0xbe, 0x04, 0x4f, 0x81, 0x79, 0x8f, 0xa5, 0x3f, 0x6f, 0x15,
|
||||
0x31, 0xc4, 0xb8, 0x15, 0xe8, 0x18, 0x91, 0x13, 0x80, 0x07, 0x54, 0xeb, 0x30, 0x35, 0x20, 0xcd,
|
||||
0x33, 0x22, 0x07, 0x81, 0xdf, 0x8b, 0x14, 0x19, 0xe7, 0xa6, 0x3b, 0x4b, 0xca, 0x0b, 0x2e, 0xa2,
|
||||
0x1d, 0x7b, 0x73, 0xb1, 0x74, 0x6c, 0xa2, 0x28, 0xfa, 0x23, 0x30, 0x46, 0xaf, 0x04, 0x8a, 0x38,
|
||||
0x26, 0x4d, 0x7f, 0x00, 0x91, 0x14, 0x86, 0x0f, 0x9d, 0x1d, 0x11, 0x1f, 0x15, 0x39, 0x0f, 0xb8,
|
||||
0x55, 0xbb, 0x86, 0xd3, 0x3f, 0x00, 0x91, 0x16, 0xaa, 0xe9, 0x25, 0xfa, 0xfe, 0xdf, 0x00, 0x9f,
|
||||
0xb3, 0xaf, 0x1d, 0x78, 0x45, 0xe0, 0xfe, 0xcc, 0x78, 0xb7, 0x7e, 0x9f, 0xe0, 0x9a, 0xd7, 0x7b,
|
||||
0xbb, 0xe2, 0x1f, 0x67, 0xd4, 0x9f, 0xb0, 0xc6, 0xe0, 0xcc, 0x61, 0x6f, 0x6f, 0x01, 0x51, 0xe9,
|
||||
0xff, 0x88, 0xf2, 0xa8, 0x6b, 0x95, 0xb1, 0xea, 0x78, 0xa7, 0x37, 0x85, 0x34, 0x42, 0xf4, 0x6c,
|
||||
0x76, 0x0b, 0x6e, 0x7a, 0x01, 0x5f, 0x8a, 0xcc, 0x56, 0xfe, 0xfa, 0xc7, 0x57, 0xe8, 0x26, 0x44,
|
||||
0x95, 0xe3, 0x4c, 0x35, 0x35, 0x8b, 0x7a, 0xaa, 0xf1, 0x5f, 0x32, 0x5a, 0xf2, 0x22, 0xc0, 0x8f,
|
||||
0xec, 0x8b, 0xce, 0xff, 0x8e, 0x37, 0x3c, 0x36, 0xbc, 0x47, 0x44, 0x50, 0x26, 0xbe, 0x43, 0x22,
|
||||
0xff, 0x7d, 0x4d, 0xf6, 0x38, 0x12, 0xf1, 0xdf, 0xc2, 0x2d, 0x86, 0xb1, 0xa5, 0x2b, 0xb1, 0x3c,
|
||||
0x22, 0x27, 0x61, 0x94, 0x3b, 0x14, 0xc7, 0xb5, 0x28, 0x0f, 0x85, 0xdd, 0xe0, 0x16, 0x01, 0xd2,
|
||||
0xb9, 0x8e, 0xfb, 0x01, 0x4b, 0x25, 0x7c, 0x4b, 0xf4, 0xb8, 0x44, 0x41, 0xc2, 0x2e, 0xf3, 0xbe,
|
||||
0xd1, 0x2d, 0x27, 0x8a, 0x31, 0xf0, 0xe2, 0x28, 0x00, 0x24, 0x9e, 0x3f, 0x30, 0xb0, 0xaf, 0xcc,
|
||||
0xf5, 0xb7, 0x52, 0xf3, 0x72, 0x50, 0xa1, 0x70, 0xfe, 0xaa, 0x82, 0xa1, 0x69, 0xbd, 0x6b, 0x78,
|
||||
0x6b, 0x7f, 0x17, 0xb6, 0x39, 0x23, 0x1c, 0xf8, 0x9b, 0xf0, 0x27, 0x44, 0x00, 0x19, 0x21, 0x1b,
|
||||
0x0b, 0xe8, 0x1f, 0x4b, 0x8f, 0x86, 0xde, 0x15, 0xb9, 0x7a, 0xa9, 0xd9, 0xae, 0x9c, 0xca, 0x5d,
|
||||
0xbf, 0xef, 0xe8, 0x1b, 0xcc, 0xb5, 0x6a, 0x30, 0x9e, 0x30, 0xe1, 0xb7, 0x57, 0x9b, 0xcb, 0x7c,
|
||||
0x16, 0xe8, 0x31, 0x4e, 0x0e, 0xbc, 0x4f, 0xf3, 0x72, 0xbb, 0xb5, 0x3c, 0x10, 0xaf, 0x54, 0xc2,
|
||||
0xe9, 0x11, 0x53, 0xc0, 0xfa, 0x7f, 0xf0, 0x39, 0xb8, 0xae, 0x4c, 0xef, 0x13, 0x6e, 0x19, 0x4e,
|
||||
0xe5, 0x96, 0x21, 0xb8, 0x5a, 0x19, 0x9f, 0x6a, 0x33, 0xaf, 0x02, 0x8e, 0x72, 0xbb, 0x86, 0xca,
|
||||
0x02, 0xbe, 0xfa, 0x1b, 0x95, 0x95, 0x05, 0x3d, 0xe4, 0x76, 0x5e, 0x22, 0x15, 0xac, 0xc7, 0xaf,
|
||||
0x57, 0xfb, 0x72, 0x22, 0xb0, 0x3e, 0x2f, 0x05, 0x08, 0x3c, 0x94, 0xc0, 0x0c, 0xb6, 0x3b, 0x7f,
|
||||
0xba, 0xa1, 0x3e, 0x2f, 0xdd, 0xb2, 0x3d, 0xfc, 0xc8, 0xe8, 0xe2, 0x48, 0x88, 0x35, 0xf0, 0xf5,
|
||||
0x51, 0xc6, 0x5f, 0x66, 0x02, 0xf1, 0xce, 0xf0, 0xad, 0x31, 0x38, 0x5c, 0x71, 0xa6, 0x0c, 0xe7,
|
||||
0xcb, 0x3d, 0x7b, 0xbc, 0x2b, 0x5c, 0x3b, 0xd3, 0x76, 0xcc, 0x7e, 0x8c, 0xad, 0xb1, 0x95, 0x9f,
|
||||
0x1a, 0xfb, 0x8a, 0xf7, 0x86, 0x6d, 0x8c, 0x88, 0xe7, 0xc1, 0x8e, 0xf4, 0xcf, 0x68, 0x49, 0x70,
|
||||
0xa4, 0xc2, 0xa4, 0x9e, 0xbd, 0xc4, 0xc5, 0xdb, 0x8b, 0x72, 0xf9, 0x17, 0xfb, 0x8f, 0x21, 0xc8,
|
||||
0x8c, 0xad, 0xb5, 0x6f, 0x9f, 0x7a, 0x4e, 0x8e, 0xd5, 0xf0, 0xf0, 0xab, 0x9b, 0xf9, 0xd7, 0x0f,
|
||||
0x01, 0x22, 0x1d, 0x18, 0x56, 0xfd, 0xba, 0x9b, 0x0a, 0xb9, 0xe7, 0x5f, 0x16, 0xbb, 0x5f, 0x7b,
|
||||
0x8a, 0x8b, 0x5c, 0x2e, 0xe8, 0xdf, 0x22, 0x5c, 0x6f, 0xa3, 0x31, 0x67, 0x58, 0x04, 0x63, 0x9e,
|
||||
0xfe, 0x3c, 0x16, 0xec, 0xfa, 0xfe, 0x8e, 0xea, 0xdf, 0x2a, 0x9f, 0xa8, 0x1f, 0x67, 0x0f, 0xea,
|
||||
0xe0, 0x3b, 0x36, 0x06, 0x83, 0x0d, 0x90, 0x26, 0xfa, 0x85, 0x0f, 0xff, 0xe7, 0x6b, 0xc3, 0x5c,
|
||||
0x3d, 0xc9, 0xbc, 0xcf, 0x08, 0x10, 0x0a, 0x03, 0xcd, 0x5e, 0x2f, 0xd3, 0x72, 0x11, 0xad, 0xbe,
|
||||
0x57, 0x02, 0xda, 0x1d, 0x27, 0xce, 0xb5, 0x26, 0xb9, 0x31, 0x79, 0xad, 0x6e, 0x9d, 0xf2, 0x35,
|
||||
0x8f, 0x0a, 0xce, 0xec, 0xef, 0x71, 0x1c, 0xb6, 0x6f, 0x77, 0x64, 0x8d, 0x1e, 0x44, 0x3c, 0x0b,
|
||||
0x17, 0x8a, 0x2a, 0x2a, 0xf4, 0xdf, 0xc6, 0x0b, 0xf0, 0xb4, 0x69, 0xd5, 0x1c, 0xf6, 0x25, 0x5f,
|
||||
0x1a, 0xce, 0xb5, 0x91, 0x2a, 0x32, 0x45, 0xb5, 0xf8, 0x06, 0x83, 0x72, 0xeb, 0xef, 0xe0, 0xc2,
|
||||
0xcc, 0xb3, 0x87, 0xf5, 0x33, 0xb7, 0x70, 0xcd, 0xb2, 0x69, 0x83, 0xbb, 0x06, 0x25, 0x4d, 0xab,
|
||||
0x05, 0x1d, 0x1a, 0x6a, 0x34, 0x5c, 0xfc, 0xd6, 0x15, 0x73, 0xb7, 0x7a, 0x78, 0x33, 0xda, 0x6d,
|
||||
0x7c, 0x46, 0x4c, 0xed, 0x06, 0x47, 0x39, 0x6e, 0x08, 0x6a, 0x5f, 0xa6, 0xd0, 0xe9, 0x1a, 0x7d,
|
||||
0xdb, 0x54, 0x2c, 0x5a, 0x74, 0xc4, 0x69, 0x79, 0x45, 0xbb, 0x53, 0xe0, 0x25, 0x09, 0xff, 0x00,
|
||||
0xea, 0x1c, 0x01, 0x94, 0x81, 0x2b, 0x98, 0x5f, 0x37, 0xb2, 0x4f, 0x77, 0xc7, 0x9e, 0x24, 0x1b,
|
||||
0x58, 0x39, 0xd3, 0x0d, 0xe8, 0x21, 0x7a, 0xc0, 0x63, 0xc4, 0xb0, 0xcf, 0x80, 0x51, 0x32, 0x23,
|
||||
0xb5, 0x1f, 0xb8, 0xc0, 0x28, 0xd1, 0x05, 0xd6, 0x9e, 0x18, 0x3e, 0x08, 0x1b, 0x2c, 0xf7, 0x81,
|
||||
0xd3, 0xe2, 0x04, 0xbd, 0x6f, 0x38, 0x0b, 0x64, 0x9c, 0xcf, 0x9c, 0x38, 0x4e, 0xaf, 0xdf, 0x6b,
|
||||
0x9d, 0x6f, 0x78, 0x2f, 0x02, 0xc2, 0x1c, 0x6f, 0xc2, 0xd5, 0x47, 0xad, 0xf0, 0x75, 0xc9, 0xc2,
|
||||
0xb9, 0xc3, 0x42, 0x6c, 0x38, 0x6b, 0x78, 0x1e, 0x10, 0x18, 0xf7, 0x90, 0x90, 0x3b, 0xde, 0x9c,
|
||||
0x4c, 0x81, 0x4c, 0x58, 0x4a, 0x64, 0xc6, 0x5b, 0xf3, 0xb8, 0x59, 0x8d, 0xff, 0x3f, 0x95, 0x54,
|
||||
0xad, 0xc3, 0x8b, 0xca, 0xbc, 0xc6, 0x1b, 0xdb, 0x75, 0x54, 0x31, 0x63, 0xa3, 0xa7, 0x02, 0x3c,
|
||||
0x75, 0x3d, 0xd6, 0x58, 0xf3, 0xb8, 0xb9, 0x8d, 0xb1, 0x4f, 0x4f, 0xc9, 0x04, 0x31, 0x00, 0x24,
|
||||
0x19, 0x2f, 0x83, 0x5f, 0x60, 0x04, 0xf4, 0x74, 0x8d, 0xfb, 0x35, 0x2a, 0x3e, 0x0e, 0x6f, 0x81,
|
||||
0xb3, 0xda, 0x7b, 0x16, 0xa3, 0x31, 0x6f, 0xdf, 0x6a, 0xaa, 0xdc, 0x7f, 0xf5, 0xb1, 0xd5, 0x60,
|
||||
0xdb, 0x01, 0x40, 0x51, 0x5d, 0x4a, 0x61, 0x80, 0x3e, 0x2c, 0x86, 0x01, 0x87, 0x93, 0x17, 0x99,
|
||||
0x58, 0x60, 0x99, 0xda, 0x77, 0x67, 0x14, 0x70, 0xc1, 0x98, 0xb8, 0x4b, 0x73, 0x2a, 0xc4, 0xc5,
|
||||
0xfe, 0x36, 0xc2, 0x74, 0x66, 0x50, 0xbe, 0x9a, 0xcb, 0x18, 0xd2, 0x1c, 0x7c, 0x2a, 0xe8, 0xff,
|
||||
0xfc, 0x21, 0xd8, 0xe2, 0x55, 0xa1, 0x37, 0xeb, 0x58, 0xdb, 0xe4, 0x5e, 0x9f, 0xa8, 0xba, 0xe7,
|
||||
0xcf, 0x82, 0x13, 0x72, 0x9f, 0xae, 0x96, 0x0f, 0x1d, 0x97, 0xb6, 0x69, 0x8b, 0x4d, 0xb7, 0x79,
|
||||
0xd7, 0x4b, 0x96, 0x76, 0xe7, 0x7f, 0x86, 0xd9, 0x03, 0xaf, 0xab, 0x6a, 0x10, 0x33, 0x01, 0x27,
|
||||
0x75, 0x78, 0x11, 0x42, 0x67, 0x84, 0xf3, 0x3b, 0xb4, 0x3c, 0xd0, 0x33, 0x6f, 0xae, 0x7e, 0x06,
|
||||
0xc1, 0x50, 0xd0, 0xde, 0xed, 0x7a, 0xd7, 0x3d, 0xe0, 0x55, 0x0d, 0x77, 0x1c, 0x94, 0x86, 0xac,
|
||||
0x07, 0x35, 0x31, 0xdc, 0x38, 0x4c, 0x96, 0x7c, 0x01, 0x79, 0x95, 0x86, 0x83, 0x0b, 0x0a, 0x61,
|
||||
0x7d, 0x55, 0xa8, 0xd5, 0x28, 0xd1, 0x10, 0x81, 0x4a, 0x55, 0x0c, 0x02, 0xf1, 0x13, 0x5f, 0x85,
|
||||
0x3f, 0x5f, 0x85, 0xaa, 0x1d, 0x6f, 0x36, 0x69, 0x9f, 0xf4, 0x17, 0x36, 0x6d, 0x8d, 0xbe, 0xe1,
|
||||
0x86, 0xe3, 0x96, 0xc6, 0x9c, 0x5c, 0x26, 0xdc, 0x69, 0x1c, 0x5d, 0x5a, 0xd1, 0xc1, 0xc2, 0x10,
|
||||
0xb2, 0xcf, 0x75, 0x95, 0xd1, 0xd9, 0x54, 0x65, 0x8e, 0xb1, 0x58, 0xa5, 0xee, 0xdd, 0xa5, 0xb5,
|
||||
0xa3, 0xed, 0x32, 0x3a, 0x32, 0x4c, 0xb4, 0x5c, 0x4a, 0xa5, 0x4f, 0x89, 0xd5, 0xeb, 0x62, 0xce,
|
||||
0xcf, 0x96, 0x46, 0x0d, 0xe5, 0xe8, 0x7c, 0x72, 0xfd, 0x21, 0x49, 0x06, 0xde, 0x0e, 0x45, 0x5c,
|
||||
0xf0, 0x72, 0xf8, 0x23, 0x3d, 0xa6, 0x41, 0x9b, 0xb0, 0x72, 0xc6, 0x1a, 0xa5, 0x5a, 0xe1, 0x62,
|
||||
0xa3, 0x83, 0xdb, 0x4a, 0x9f, 0x47, 0x25, 0x96, 0xf8, 0x63, 0x59, 0x19, 0x38, 0xb5, 0x5f, 0x4f,
|
||||
0xea, 0x4f, 0xe1, 0x05, 0xa8, 0x53, 0x54, 0x42, 0x19, 0x79, 0xd1, 0xc8, 0x19, 0x1d, 0x99, 0xee,
|
||||
0xc4, 0x31, 0x16, 0xb8, 0x33, 0x6c, 0xe6, 0xf0, 0x2d, 0x51, 0x74, 0x7c, 0x74, 0x62, 0xe7, 0xae,
|
||||
0x0b, 0x4c, 0x71, 0x4b, 0x8d, 0x1c, 0x34, 0x21, 0xc6, 0xef, 0x16, 0x39, 0xcb, 0x1c, 0x41, 0x63,
|
||||
0x05, 0x9b, 0xaf, 0x2a, 0x3e, 0x61, 0x5f, 0x05, 0xbb, 0x75, 0x4b, 0x94, 0x96, 0x7c, 0x19, 0xdb,
|
||||
0x4e, 0xc1, 0xf9, 0x9d, 0x67, 0x50, 0xc7, 0x20, 0xd3, 0x00, 0x8d, 0x7b, 0x1c, 0x90, 0xb9, 0x7c,
|
||||
0xc0, 0xa7, 0xb7, 0x2f, 0x22, 0x07, 0x7b, 0xbf, 0xdb, 0x80, 0xd8, 0x2a, 0xa1, 0x6b, 0xc9, 0x4e,
|
||||
0xd5, 0xc1, 0x24, 0x06, 0xab, 0x07, 0x72, 0x61, 0x90, 0x58, 0xfc, 0xc2, 0xf3, 0x6f, 0x30, 0x09,
|
||||
0xa4, 0xa4, 0x54, 0x80, 0xc6, 0xe6, 0x3a, 0x23, 0x6b, 0x18, 0x12, 0xba, 0x13, 0x7f, 0xdd, 0x71,
|
||||
0xf6, 0xd4, 0xb6, 0x48, 0x9b, 0xa3, 0xdd, 0xff, 0xf0, 0x7f, 0x46, 0x8f, 0x67, 0x87, 0xd9, 0x85,
|
||||
0xcd, 0x43, 0xed, 0xfe, 0xe6, 0xf6, 0x25, 0x95, 0x75, 0xc1, 0x4b, 0xd9, 0x75, 0x54, 0x85, 0x77,
|
||||
0xad, 0xc3, 0xff, 0xce, 0xbc, 0x42, 0x8a, 0xb8, 0x0c, 0x88, 0xeb, 0xc1, 0x00, 0x0c, 0xdc, 0x70,
|
||||
0x8c, 0x90, 0x77, 0xf1, 0x4f, 0x7c, 0x3e, 0xf4, 0x54, 0x2d, 0xae, 0xd5, 0xbe, 0x01, 0x7e, 0xf6,
|
||||
0xd5, 0x7c, 0x6a, 0xe7, 0x1c, 0x95, 0x2d, 0x0c, 0xbb, 0xdb, 0x55, 0x5d, 0x56, 0x77, 0xfc, 0x38,
|
||||
0xf8, 0x7d, 0xb6, 0x8a, 0x62, 0xd4, 0x26, 0xef, 0x92, 0x03, 0xd5, 0x83, 0xe7, 0xb0, 0x6d, 0x80,
|
||||
0xff, 0xcc, 0xec, 0xa6, 0xc3, 0x80, 0x2a, 0x21, 0x02, 0x5b, 0xa1, 0x0c, 0xfe, 0xc2, 0x26, 0x65,
|
||||
0x0a, 0xb5, 0x1d, 0x6f, 0x70, 0x7d, 0xfe, 0x8d, 0xb4, 0xc6, 0xff, 0x08, 0xca, 0x1a, 0xb5, 0x4a,
|
||||
0x52, 0x31, 0xd4, 0x71, 0xc6, 0xcf, 0xe5, 0x3e, 0xdf, 0x15, 0x7c, 0xb3, 0xf0, 0xfa, 0x59, 0x2c,
|
||||
0x7d, 0xc3, 0x27, 0xc7, 0x46, 0xf6, 0x65, 0xd6, 0x7a, 0x0f, 0xf7, 0xfe, 0xc3, 0x6c, 0xeb, 0x9d,
|
||||
0xa2, 0x2a, 0x73, 0x1d, 0x2d, 0xf0, 0xb1, 0xb1, 0xff, 0x31, 0xf0, 0x9b, 0x35, 0x3e, 0x02, 0x44,
|
||||
0x53, 0x70, 0x72, 0x54, 0x8f, 0xb0, 0x92, 0x0a, 0x45, 0x83, 0xb2, 0xea, 0x35, 0xb7, 0x72, 0x5e,
|
||||
0x9b, 0xf0, 0x4e, 0x89, 0x10, 0x92, 0x0e, 0x93, 0xdc, 0xf8, 0x87, 0xd2, 0x0b, 0x6c, 0x3f, 0x4c,
|
||||
0x82, 0xd5, 0x52, 0x02, 0x03, 0x30, 0x0d, 0x3a, 0x86, 0x01, 0x88, 0x40, 0xa5, 0x2a, 0x92, 0x04,
|
||||
0x7f, 0x32, 0xa1, 0x33, 0x78, 0xd5, 0xd6, 0x03, 0xbc, 0x8c, 0xec, 0x6b, 0x75, 0xbe, 0x43, 0x99,
|
||||
0x18, 0x32, 0xc2, 0xd7, 0x34, 0x75, 0xb0, 0x86, 0x45, 0x48, 0xf9, 0x4a, 0xd5, 0x13, 0x4b, 0x1c,
|
||||
0xf1, 0x39, 0x4c, 0x69, 0x30, 0x8b, 0xe1, 0x33, 0x62, 0xdc, 0x62, 0x52, 0x9c, 0x0a, 0xc2, 0x44,
|
||||
0x60, 0xcf, 0x9d, 0xa9, 0xe4, 0x19, 0xb9, 0x3c, 0xba, 0x8f, 0x00, 0x25, 0xd9, 0x6f, 0x47, 0xd8,
|
||||
0xee, 0xb0, 0x3f, 0x06, 0xd5, 0x56, 0x71, 0xf5, 0x8a, 0xc7, 0x05, 0xc8, 0xec, 0xc0, 0xec, 0x7a,
|
||||
0x16, 0xdd, 0x1c, 0x95, 0x99, 0xfc, 0xae, 0xaa, 0x74, 0x4e, 0x84, 0x92, 0x79, 0x18, 0x44, 0x82,
|
||||
0x24, 0x64, 0x9a, 0xf0, 0xf6, 0xd2, 0xb3, 0xe1, 0xb4, 0xb3, 0x35, 0x0f, 0x09, 0xeb, 0xad, 0x36,
|
||||
0xb0, 0x2a, 0x73, 0x6b, 0xaf, 0xe0, 0x78, 0xf5, 0x02, 0x0a, 0xcd, 0x0c, 0x62, 0xf0, 0xb9, 0x94,
|
||||
0x42, 0x6c, 0xb5, 0xb2, 0x07, 0x6f, 0x87, 0x0a, 0x0a, 0xb4, 0x8a, 0x63, 0xb9, 0x21, 0x86, 0xd3,
|
||||
0x0f, 0x67, 0xf9, 0x8a, 0x03, 0xef, 0xf0, 0x81, 0x6f, 0xfc, 0x25, 0x93, 0x1d, 0x60, 0x1c, 0x03,
|
||||
0xda, 0x52, 0x63, 0x3e, 0xd6, 0x44, 0x29, 0x78, 0x2a, 0xac, 0x66, 0xd7, 0x9d, 0xbd, 0x41, 0xa9,
|
||||
0xb9, 0xef, 0x09, 0x2e, 0x3d, 0xc0, 0xe5, 0x79, 0x9b, 0x3b, 0x12, 0x22, 0x46, 0x80, 0x07, 0x25,
|
||||
0x8d, 0x6f, 0x0e, 0x4a, 0xb4, 0x36, 0x64, 0xec, 0xa6, 0x1c, 0x17, 0x62, 0xe2, 0x67, 0xee, 0x73,
|
||||
0xc2, 0x36, 0xcb, 0xcf, 0x5e, 0x53, 0x54, 0x7e, 0x94, 0x24, 0x95, 0x80, 0x1d, 0x5e, 0xe9, 0xde,
|
||||
0x99, 0x1d, 0xd9, 0xc4, 0xf5, 0x7f, 0x6c, 0xf0, 0x9e, 0x67, 0x6d, 0xef, 0x67, 0xea, 0x4f, 0x45,
|
||||
0x97, 0x81, 0x0a, 0x7b, 0x30, 0x28, 0x4d, 0xa5, 0xd6, 0x98, 0xe1, 0x9e, 0xa3, 0x6d, 0xf8, 0x5b,
|
||||
0x00, 0xc0, 0xa8, 0x55, 0x4d, 0x1a, 0x4d, 0x69, 0xfc, 0xe4, 0x79, 0x3d, 0x3f, 0xc6, 0xa7, 0xb9,
|
||||
0xb1, 0xea, 0x1e, 0x37, 0xc1, 0xd1, 0x86, 0xa5, 0xef, 0xaf, 0xcf, 0xcd, 0xf1, 0x77, 0xa7, 0x6c,
|
||||
0x1a, 0x9d, 0xc7, 0xd0, 0xc9, 0x0e, 0x77, 0x30, 0xd9, 0x96, 0xaf, 0xea, 0xde, 0x3f, 0xcf, 0xd2,
|
||||
0xab, 0x95, 0x25, 0x2a, 0xd6, 0xa2, 0xa7, 0x46, 0xc6, 0x2f, 0x15, 0x99, 0x04, 0x2f, 0x92, 0x6d,
|
||||
0x7a, 0xbc, 0x55, 0xa1, 0xeb, 0x1f, 0x8c, 0xab, 0x82, 0x78, 0x8f, 0xcb, 0x3b, 0xec, 0x02, 0xbd,
|
||||
0xbf, 0x30, 0xda, 0x18, 0x8f, 0x2d, 0x27, 0xc4, 0x0a, 0xb6, 0x1b, 0x47, 0x12, 0xae, 0x73, 0x16,
|
||||
0x56, 0x9f, 0xea, 0xa9, 0x4a, 0xc6, 0x37, 0xc7, 0x02, 0x42, 0xf6, 0xf0, 0xfd, 0x4d, 0x0c, 0xec,
|
||||
0xc6, 0x4e, 0x5a, 0xfe, 0x5f, 0x55, 0x60, 0xac, 0x4c, 0xef, 0x11, 0x7c, 0x5a, 0xd7, 0x07, 0x25,
|
||||
0x07, 0xb7, 0xfd, 0xed, 0x51, 0xb6, 0x83, 0x92, 0x30, 0xd5, 0x21, 0xe5, 0xaf, 0xec, 0x6d, 0xff,
|
||||
0x04, 0xb2, 0xb1, 0xac, 0x62, 0x2d, 0xcd, 0x7c, 0xde, 0xed, 0xb2, 0xbc, 0x42, 0xb8, 0xff, 0x61,
|
||||
0x59, 0xd7, 0xf7, 0x5a, 0x5d, 0xda, 0x2f, 0x80, 0xed, 0xae, 0xa6, 0xe1, 0x91, 0x8d, 0x09, 0x64,
|
||||
0xf7, 0x56, 0x8d, 0x7a, 0xdd, 0xc8, 0xfb, 0x5b, 0x7f, 0xb9, 0x8e, 0x47, 0xa7, 0x3b, 0x30, 0x77,
|
||||
0x42, 0xc2, 0x7c, 0x4c, 0x5e, 0x4f, 0xd4, 0xd9, 0x5d, 0xef, 0xbf, 0x4c, 0x7e, 0x12, 0x23, 0x91,
|
||||
0x6a, 0x9c, 0xa1, 0xb8, 0x2a, 0xef, 0x73, 0x28, 0xe7, 0x77, 0xb7, 0xe8, 0x8f, 0x14, 0x9d, 0x31,
|
||||
0x04, 0xb8, 0x97, 0xf0, 0xb9, 0xdd, 0xef, 0x01, 0x3d, 0x6b, 0x1e, 0xcc, 0x35, 0x9a, 0xac, 0xfe,
|
||||
0xe9, 0x2c, 0xb3, 0xca, 0xf8, 0x27, 0x56, 0xd0, 0xb9, 0x53, 0x74, 0x09, 0x4d, 0xae, 0x5c, 0x8b,
|
||||
0xbc, 0xc4, 0x4b, 0xdb, 0x75, 0x55, 0x51, 0x57, 0x68, 0x51, 0x69, 0x74, 0x8d, 0xa7, 0xcf, 0x24,
|
||||
0x5d, 0xc5, 0xf6, 0x79, 0xaf, 0xc6, 0xae, 0x45, 0x5d, 0x44, 0x80, 0x12, 0x0a, 0x7d, 0x27, 0x37,
|
||||
0x1c, 0x93, 0x8c, 0x0c, 0x1b, 0x7e, 0x39, 0x24, 0x4d, 0x58, 0xa1, 0xe4, 0x98, 0x61, 0x10, 0xf2,
|
||||
0xfa, 0xe7, 0x52, 0x37, 0x80, 0xa8, 0x60, 0x35, 0x7c, 0x8a, 0x49, 0xa3, 0x44, 0x23, 0x20, 0xb5,
|
||||
0x18, 0x9a, 0xe6, 0x51, 0x16, 0x75, 0xdf, 0x46, 0x57, 0x00, 0xea, 0xaf, 0x86, 0xe1, 0xa6, 0x68,
|
||||
0x84, 0x62, 0xb7, 0x7b, 0xf3, 0xf5, 0x3b, 0x3f, 0x14, 0xed, 0x5f, 0xed, 0x13, 0xd1, 0x94, 0x9f,
|
||||
0xc7, 0x16, 0x0b, 0x18, 0xa5, 0x1d, 0xf7, 0x27, 0xad, 0xe6, 0x5f, 0x39, 0x2d, 0x48, 0xd9, 0x24,
|
||||
0x9a, 0x50, 0xfe, 0x70, 0x6a, 0xd7, 0xbb, 0x75, 0x77, 0x98, 0x3e, 0x3b, 0x6c, 0xfc, 0xa3, 0xa1,
|
||||
0xe4, 0x9d, 0x35, 0x3e, 0x02, 0x42, 0xc7, 0xf0, 0xfa, 0x5b, 0x10, 0xd9, 0x1c, 0x94, 0x44, 0x7c,
|
||||
0x9f, 0x55, 0x60, 0xa8, 0x26, 0x6f, 0x64, 0x9e, 0xcd, 0x65, 0x62, 0xf6, 0x07, 0x24, 0x35, 0xe7,
|
||||
0x72, 0x52, 0x1a, 0xb0, 0x6f, 0x0d, 0x8b, 0xa5, 0xbf, 0x6b, 0x94, 0xe6, 0x27, 0xb6, 0xcf, 0x4d,
|
||||
0x72, 0x30, 0x59, 0xbc, 0xd4, 0x57, 0x4b, 0xb5, 0xbf, 0x59, 0x71, 0x2c, 0x7c, 0x8a, 0x69, 0xa3,
|
||||
0x79, 0x86, 0x32, 0x99, 0x6b, 0xa6, 0x83, 0x4f, 0x48, 0xd7, 0xbe, 0xdc, 0xd2, 0x29, 0x04, 0x73,
|
||||
0x72, 0xaf, 0x37, 0x4c, 0x09, 0x30, 0x33, 0xdf, 0x60, 0xb6, 0x9e, 0x6f, 0x8f, 0x77, 0x1f, 0x33,
|
||||
0x5e, 0x8a, 0x75, 0x1e, 0x6b, 0xc0, 0xed, 0x81, 0xcf, 0xc5, 0xf0, 0xc3, 0xf0, 0x95, 0xd3, 0x3b,
|
||||
0x47, 0x42, 0xe6, 0x29, 0xb4, 0xef, 0x6f, 0x12, 0x63, 0x3d, 0x98, 0xa3, 0x4f, 0x81, 0xc3, 0xfc,
|
||||
0xb3, 0xf4, 0x35, 0xb7, 0x2c, 0xa7, 0x0e, 0xeb, 0xe3, 0xdc, 0xc0, 0xdd, 0x75, 0x2b, 0x76, 0x9e,
|
||||
0xbe, 0x0a, 0x0d, 0x82, 0x54, 0xcd, 0xab, 0x01, 0x5b, 0x58, 0x6a, 0xd8, 0xbb, 0x75, 0x4e, 0x2a,
|
||||
0xd0, 0x2f, 0x58, 0xce, 0x8b, 0x59, 0x2c, 0x9c, 0xab, 0x01, 0xc9, 0x6e, 0x1b, 0xc1, 0x12, 0xa2,
|
||||
0xb6, 0x80, 0x07, 0x25, 0x8c, 0xad, 0xc1, 0x7e, 0x08, 0x4c, 0x54, 0xfa, 0x8d, 0x7c, 0x95, 0x81,
|
||||
0x47, 0xe5, 0xe6, 0x4f, 0x04, 0xd0, 0xf2, 0x29, 0xb0, 0x86, 0xa2, 0x1a, 0xca, 0x82, 0xd0, 0x19,
|
||||
0xda, 0xd3, 0x1c, 0x33, 0xb8, 0x61, 0x93, 0xf2, 0x1f, 0x02, 0xd9, 0x5d, 0xc8, 0x43, 0xdd, 0xd5,
|
||||
0x7c, 0x07, 0x34, 0xac, 0x54, 0x3f, 0xcb, 0x2c, 0x5e, 0x59, 0xb7, 0x43, 0x73, 0xa8, 0x23, 0xf0,
|
||||
0x7a, 0xd3, 0xde, 0x58, 0xb1, 0x1d, 0x89, 0xf3, 0x26, 0x92, 0x88, 0xb4, 0x10, 0x7c, 0x19, 0x5f,
|
||||
0x94, 0xbb, 0xe5, 0x12, 0xae, 0xde, 0xcb, 0xaa, 0x71, 0x1a, 0xe2, 0xee, 0xe0, 0x9c, 0x8a, 0x36,
|
||||
0xdc, 0xef, 0x16, 0x21, 0x04, 0xe6, 0xc9, 0xc3, 0xc0, 0x52, 0x55, 0xf7, 0x53, 0xf5, 0x9c, 0xf5,
|
||||
0x44, 0x53, 0x8f, 0x7e, 0x22, 0xa7, 0xa4, 0x06, 0x80, 0x92, 0x17, 0xb5, 0x54, 0x58, 0x50, 0xe1,
|
||||
0x4e, 0xfb, 0x10, 0x6f, 0xb0, 0x15, 0x64, 0x86, 0xce, 0xbc, 0xe5, 0x80, 0xd9, 0x6b, 0xc4, 0x0d,
|
||||
0x8d, 0xce, 0x42, 0x36, 0xf0, 0x02, 0xed, 0xbe, 0xe1, 0xfd, 0xdd, 0xce, 0x55, 0x22, 0x7d, 0xfd,
|
||||
0x7b, 0x05, 0xf0, 0x53, 0x22, 0x49, 0x48, 0x36, 0xf0, 0x72, 0x1a, 0x79, 0x39, 0x2c, 0x0d, 0x58,
|
||||
0x5e, 0x13, 0x7e, 0xc2, 0xf9, 0xf8, 0x81, 0x89, 0x68, 0x7b, 0x1a, 0xc5, 0xef, 0xa1, 0xce, 0x01,
|
||||
0xb9, 0x20, 0x67, 0x96, 0x58, 0x01, 0x7c, 0x07, 0x55, 0x5b, 0x55, 0x77, 0xa6, 0x38, 0x92, 0xfc,
|
||||
0x59, 0xb6, 0x60, 0x12, 0x5f, 0x98, 0x01, 0xc1, 0x98, 0xdb, 0x7d, 0xff, 0x6f, 0x7a, 0xc5, 0x9e,
|
||||
0xa4, 0xd1, 0x1e, 0xa2, 0x3a, 0xe0, 0x27, 0xd9, 0x18, 0x6d, 0x7f, 0xa8, 0xc1, 0x39, 0x3a, 0x52,
|
||||
0x4c, 0x72, 0x7a, 0x08, 0xef, 0xb9, 0xa8, 0x73, 0x35, 0x31, 0x7c, 0xfb, 0x30, 0x2a, 0x98, 0x3f,
|
||||
0xb2, 0xc0, 0x51, 0xa5, 0xb7, 0xce, 0xf1, 0xc8, 0x54, 0xf8, 0xec, 0x69, 0x28, 0x74, 0x53, 0x22,
|
||||
0x75, 0x09, 0xeb, 0x85, 0x24, 0x44, 0x97, 0x83, 0x09, 0xb8, 0x49, 0x78, 0x53, 0x34, 0xcc, 0xdb,
|
||||
0x22, 0x76, 0xf6, 0xd6, 0xc2, 0x15, 0xc7, 0x61, 0xaa, 0x27, 0xf7, 0x14, 0x1a, 0xb7, 0xad, 0xf6,
|
||||
0xc0, 0x20, 0xaa, 0xb0, 0x33, 0xa8, 0x64, 0x7e, 0xe7, 0x69, 0x2d, 0x6b, 0xf8, 0x64, 0xee, 0xaf,
|
||||
0xb0, 0x2d, 0x2f, 0xae, 0xba, 0xb2, 0x52, 0xa4, 0xba, 0x4f, 0xc9, 0x7e, 0x68, 0xc1, 0x49, 0xd9,
|
||||
0x92, 0xdb, 0x5f, 0x83, 0xb9, 0xb3, 0xc6, 0x7a, 0xeb, 0x44, 0x3d, 0x63, 0x6b, 0x01, 0x00, 0xf9,
|
||||
0x58, 0x09, 0x72, 0x22, 0x70, 0x15, 0x30, 0x1d, 0x4e, 0xb2, 0x97, 0x53, 0xc8, 0x89, 0x85, 0x5f,
|
||||
0xd0, 0x1b, 0x00, 0x88, 0xf0, 0xc3, 0x86, 0x2c, 0x21, 0x07, 0xe9, 0x2c, 0x24, 0x8c, 0x94, 0x90,
|
||||
0x31, 0xb1, 0x7b, 0xff, 0xf6, 0xdf, 0xf9, 0xd8, 0x4b, 0xdc, 0x7d, 0xaa, 0x18, 0xe7, 0x37, 0xd3,
|
||||
0x48, 0xa5, 0x04, 0x28, 0xc0, 0x5d, 0xf9, 0x0b, 0xb0, 0x96, 0x97, 0x3a, 0x7c, 0xf7, 0x21, 0x57,
|
||||
0xac, 0x9c, 0x98, 0x34, 0xb9, 0xfa, 0xb0, 0x49, 0x79, 0x5e, 0x86, 0xad, 0x29, 0x25, 0x31, 0x03,
|
||||
0xdf, 0x1b, 0xd9, 0xbb, 0xcb, 0x4c, 0x8a, 0x8f, 0xbd, 0x58, 0x31, 0xc7, 0x0c, 0x02, 0x0e, 0xa5,
|
||||
0xd5, 0x8e, 0x23, 0xce, 0x0e, 0x24, 0xd7, 0xd3, 0x01, 0x25, 0xf0, 0xf8, 0x1c, 0xae, 0x86, 0x4f,
|
||||
0xad, 0xb2, 0xf4, 0xf1, 0xe3, 0xcc, 0x8d, 0xec, 0xae, 0x01, 0xc7, 0xa8, 0x8c, 0x5e, 0xe0, 0xe4,
|
||||
0x0c, 0x5a, 0x0e, 0x48, 0xa3, 0x56, 0x2d, 0xa1, 0x31, 0x62, 0x56, 0x1c, 0x48, 0x7e, 0x4d, 0x46,
|
||||
0x26, 0x10, 0x65, 0x1d, 0x45, 0x38, 0x1f, 0xbe, 0x7e, 0x5e, 0x70, 0x26, 0x5f, 0x13, 0xa7, 0xf1,
|
||||
0x8b, 0xc8, 0x0c, 0xc8, 0x98, 0xbc, 0xbd, 0x7e, 0x17, 0xce, 0xad, 0x3c, 0x27, 0xd9, 0x35, 0x8a,
|
||||
0xfd, 0x47, 0x83, 0x34, 0x43, 0x00, 0x1b, 0x19, 0xbf, 0xf3, 0xed, 0xf7, 0xae, 0x48, 0x65, 0xcc,
|
||||
0x34, 0x3a, 0x62, 0x5a, 0x30, 0x45, 0xb5, 0x84, 0x55, 0x56, 0x21, 0x7b, 0xb9, 0xad, 0xc6, 0xbc,
|
||||
0x16, 0x8e, 0xb0, 0x63, 0x94, 0x5a, 0xb7, 0xbf, 0x4f, 0x00, 0x23, 0x07, 0x2f, 0x1f, 0x40, 0x37,
|
||||
0xc4, 0xf0, 0x88, 0x7a, 0xe6, 0x37, 0x89, 0xfd, 0xbb, 0xfd, 0x48, 0x88, 0x70, 0x3b, 0x69, 0x5a,
|
||||
0x46, 0xdb, 0xbb, 0x75, 0x06, 0xc7, 0xff, 0x39, 0xd2, 0x9b, 0x79, 0x3c, 0x0e, 0xa5, 0xdd, 0x64,
|
||||
0x80, 0x12, 0x25, 0x09, 0x3f, 0x07, 0x0c, 0x0e, 0xc7, 0xaf, 0x2d, 0x9e, 0xc1, 0xc9, 0x34, 0x6a,
|
||||
0xf9, 0xba, 0x89, 0x99, 0x91, 0x2f, 0xc6, 0xc2, 0x77, 0xe8, 0x92, 0xd5, 0x05, 0x01, 0x3e, 0x18,
|
||||
0x2f, 0x8b, 0xd1, 0x4c, 0x46, 0x00, 0x13, 0xe1, 0x28, 0x99, 0x34, 0xd2, 0x9f, 0xf5, 0xb7, 0x27,
|
||||
0xf1, 0x89, 0xe6, 0x91, 0x9e, 0x8a, 0x78, 0x42, 0x64, 0xde, 0xd8, 0x50, 0xc0, 0x70, 0xfb, 0x9b,
|
||||
0xad, 0x95, 0x11, 0xc1, 0x3f, 0xa7, 0x1c, 0xfc, 0x28, 0xe8, 0xad, 0x25, 0x5b, 0x13, 0xb5, 0x0b,
|
||||
0xb8, 0x48, 0xa4, 0x25, 0xec, 0xfc, 0xc9, 0x0d, 0x29, 0xc0, 0x47, 0x86, 0xcf, 0xf4, 0xe6, 0x74,
|
||||
0x55, 0x09, 0x6d, 0x3e, 0xef, 0xc4, 0xdb, 0x49, 0xe7, 0x01, 0xf9, 0x81, 0x0e, 0x15, 0x0d, 0x3d,
|
||||
0xd7, 0x28, 0x4c, 0x34, 0x39, 0x39, 0x98, 0xec, 0x0e, 0xd2, 0x02, 0x5b, 0x8f, 0x0c, 0x8e, 0xed,
|
||||
0xa7, 0xdc, 0x36, 0x48, 0x71, 0x72, 0xef, 0x7a, 0xfc, 0x9f, 0x92, 0xfb, 0x00, 0x4a, 0xea, 0x2e,
|
||||
0xf3, 0xcc, 0xe0, 0x87, 0x89, 0x2a, 0xc0, 0x2d, 0xe3, 0xf7, 0x2d, 0x8e, 0xc2, 0xd6, 0xe7, 0xfe,
|
||||
0xec, 0x7a, 0x48, 0xc5, 0x6e, 0x0e, 0xbe, 0x07, 0xe8, 0x97, 0x0d, 0x24, 0xd1, 0xa0, 0xa2, 0x9e,
|
||||
0x05, 0x19, 0x5e, 0x18, 0xfa, 0x5f, 0xd6, 0xd0, 0x7c, 0x21, 0x8f, 0xf9, 0xc9, 0xc3, 0x5c, 0x24,
|
||||
0xf8, 0x5f, 0x6f, 0xe4, 0xb8, 0xfa, 0xab, 0xe7, 0xa2, 0x81, 0x33, 0x03, 0x97, 0x80, 0xdb, 0x7c,
|
||||
0xd0, 0xcd, 0x05, 0x33, 0x84, 0xec, 0x27, 0x9f, 0x0a, 0xb5, 0x9d, 0xcf, 0x7c, 0x34, 0x03, 0xe0,
|
||||
0x1c, 0x43, 0xc1, 0x65, 0x3f, 0x01, 0x9d, 0x1a, 0x7c, 0x9f, 0xf7, 0xc6, 0xed, 0x39, 0x52, 0x8e,
|
||||
0xf0, 0x0f, 0xa3, 0x74, 0x2d, 0xce, 0x93, 0x22, 0x75, 0xf0, 0x6d, 0x06, 0xfd, 0x54, 0xec, 0x1a,
|
||||
0x31, 0xc8, 0xe5, 0x21, 0xcb, 0xbf, 0xac, 0x88, 0xcb, 0x30, 0x3a, 0xf0, 0x3d, 0xe6, 0x65, 0x79,
|
||||
0x54, 0x69, 0xa1, 0x80, 0x56, 0x52, 0xda, 0x7a, 0x76, 0xef, 0xfb, 0x27, 0xc3, 0x92, 0x53, 0xca,
|
||||
0x19, 0x29, 0x73, 0x81, 0x1a, 0x96, 0xc8, 0x51, 0x10, 0x0b, 0x10, 0x93, 0x37, 0xb5, 0xb0, 0xe6,
|
||||
0xe4, 0x80, 0xdb, 0xe0, 0x91, 0x6b, 0x8c, 0x1c, 0x7e, 0x8e, 0x51, 0x6f, 0xee, 0xd5, 0x87, 0x0a,
|
||||
0x18, 0x7f, 0x50, 0x98, 0x3d, 0x9f, 0x92, 0x7b, 0xd5, 0x83, 0xeb, 0x30, 0x6d, 0x80, 0x40, 0x64,
|
||||
0xa9, 0x57, 0x15, 0x80, 0x5a, 0x4e, 0x7e, 0x98, 0x96, 0x4a, 0x8e, 0xc3, 0xfe, 0x4d, 0x6d, 0x02,
|
||||
0x1f, 0x5b, 0x6b, 0x99, 0x2f, 0x2d, 0x8a, 0x71, 0x60, 0x13, 0xc4, 0x38, 0x00, 0x82, 0x9a, 0xc3,
|
||||
0x02, 0x0a, 0x36, 0x0c, 0xb0, 0x12, 0x67, 0x86, 0x63, 0x85, 0x34, 0x87, 0x7d, 0x67, 0x47, 0xc7,
|
||||
0x73, 0xa3, 0x8f, 0x7b, 0x3e, 0xf8, 0x6d, 0x5b, 0x37, 0x4c, 0x29, 0xf6, 0x83, 0x2b, 0xd1, 0xf3,
|
||||
0xaa, 0x4f, 0xec, 0x6a, 0xad, 0xba, 0x49, 0x1a, 0x4e, 0x61, 0xb1, 0xb0, 0x6f, 0x05, 0xe4, 0x44,
|
||||
0x7c, 0x30, 0x36, 0x0a, 0x28, 0x4d, 0x60, 0xc0, 0xba, 0xb5, 0xcc, 0x5d, 0x5d, 0xbb, 0x60, 0x12,
|
||||
0x5f, 0x00, 0x3f, 0xa7, 0xf0, 0xaf, 0x34, 0x62, 0xdf, 0xdb, 0xff, 0x34, 0xde, 0x19, 0x27, 0x11,
|
||||
0x78, 0x01, 0xc2, 0x4d, 0xe8, 0xd1, 0x9e, 0xca, 0xff, 0x02, 0x2d, 0xbd, 0xf9, 0x10, 0x0b, 0xdd,
|
||||
0x1a, 0xdc, 0xac, 0x77, 0x64, 0x88, 0xb5, 0xeb, 0xba, 0xb7, 0xc0, 0xb7, 0x2d, 0xcf, 0x0e, 0x4a,
|
||||
0xa3, 0x56, 0x43, 0xd1, 0xb2, 0x92, 0x6e, 0x03, 0x2a, 0x1f, 0x9b, 0x4c, 0x5d, 0x65, 0x61, 0x80,
|
||||
0x41, 0x17, 0x86, 0x01, 0xcb, 0xc0, 0xcc, 0x73, 0xda, 0x9c, 0x9e, 0x5e, 0x93, 0x90, 0x11, 0xcf,
|
||||
0xc3, 0x0c, 0x95, 0x34, 0x83, 0x00, 0x02, 0xad, 0xcd, 0x1c, 0x23, 0xca, 0x90, 0xd1, 0x63, 0xd9,
|
||||
0xee, 0x50, 0x05, 0x28, 0xf2, 0xe6, 0x77, 0x4c, 0x1a, 0x94, 0xac, 0xed, 0x48, 0x62, 0xf6, 0xbb,
|
||||
0x76, 0xf8, 0x85, 0xe0, 0x4f, 0x3a, 0x2c, 0x19, 0xd8, 0xf1, 0x09, 0xc4, 0x36, 0x58, 0xdb, 0xaa,
|
||||
0x30, 0x0d, 0xf1, 0x65, 0xe0, 0x43, 0xa3, 0x7e, 0x50, 0x17, 0x05, 0x99, 0x87, 0xc4, 0x03, 0x84,
|
||||
0x83, 0x92, 0xd6, 0x67, 0x01, 0x20, 0x63, 0x78, 0x8a, 0xb4, 0xf7, 0xde, 0x75, 0x54, 0x85, 0x47,
|
||||
0x2f, 0xc3, 0x37, 0xc1, 0xaa, 0xa8, 0xde, 0xc9, 0x88, 0x86, 0xe0, 0xe4, 0xaa, 0x9d, 0x35, 0xba,
|
||||
0x49, 0xd1, 0x44, 0x1a, 0x5a, 0xc3, 0x62, 0xeb, 0xb6, 0x4f, 0x63, 0x7c, 0x3e, 0x8e, 0x4b, 0x2d,
|
||||
0xb0, 0xd6, 0xd8, 0x2f, 0x3a, 0xbc, 0x80, 0x56, 0xbf, 0xc1, 0x14, 0x23, 0x4f, 0x12, 0x72, 0xfe,
|
||||
0xed, 0x77, 0xd6, 0x52, 0x8b, 0x05, 0x3c, 0x7c, 0x0a, 0x1b, 0x04, 0x55, 0x21, 0x47, 0x1c, 0x16,
|
||||
0x25, 0x60, 0x86, 0x01, 0xad, 0x09, 0x1b, 0xe6, 0x66, 0x88, 0x47, 0x66, 0x12, 0x2e, 0x5c, 0x5a,
|
||||
0xd3, 0xe8, 0x3d, 0x76, 0xf4, 0x95, 0x4a, 0x3b, 0x4e, 0x8d, 0xb2, 0xc0, 0xca, 0x2a, 0xac, 0xbe,
|
||||
0x10, 0xbb, 0x5f, 0x9e, 0xd7, 0x9f, 0x25, 0x80, 0x69, 0x1b, 0xff, 0xcf, 0xe5, 0x42, 0xde, 0xcc,
|
||||
0xf0, 0xe3, 0x56, 0x85, 0x16, 0x53, 0x40, 0x60, 0x77, 0x55, 0xc8, 0x8b, 0xc0, 0x45, 0x80, 0xe7,
|
||||
0x00, 0x0f, 0x0d, 0x63, 0x0e, 0x5f, 0xb3, 0xc0, 0x73, 0x78, 0xf7, 0xa3, 0x97, 0x87, 0xc5, 0x1f,
|
||||
0x0e, 0x49, 0x93, 0x5e, 0x02, 0x50, 0x73, 0x70, 0xf2, 0xbf, 0xcd, 0x83, 0xa0, 0x81, 0x3f, 0x50,
|
||||
0x25, 0xd5, 0xeb, 0x00, 0xb7, 0xb2, 0xa7, 0x35, 0x7f, 0x7c, 0x44, 0x73, 0xf0, 0x72, 0x44, 0x86,
|
||||
0x69, 0x27, 0x8d, 0x20, 0x16, 0xf4, 0x15, 0x4d, 0x2e, 0x7e, 0xaf, 0xb2, 0x12, 0x81, 0xe6, 0x38,
|
||||
0xe4, 0xb4, 0xb4, 0xd7, 0xa9, 0xfc, 0x5a, 0x1c, 0xe9, 0x3d, 0x7a, 0xc4, 0xf6, 0x91, 0x2c, 0x98,
|
||||
0x00, 0x49, 0x3d, 0xce, 0x47, 0xc8, 0x8f, 0xbf, 0xc9, 0xed, 0xe7, 0x87, 0x1e, 0x75, 0x7d, 0xf6,
|
||||
0xbb, 0x4e, 0x99, 0x52, 0xc0, 0xd2, 0x48, 0x25, 0xc4, 0xc5, 0x93, 0x97, 0xdb, 0x4b, 0x87, 0x33,
|
||||
0xca, 0x64, 0x50, 0x0a, 0x30, 0xa6, 0x50, 0x94, 0xfe, 0x56, 0xa4, 0xbb, 0xc0, 0x24, 0x56, 0xb0,
|
||||
0xd7, 0x55, 0x74, 0x0c, 0x90, 0x6d, 0xe7, 0x4a, 0x00, 0xa0, 0xee, 0x3c, 0x51, 0xdf, 0xf0, 0xec,
|
||||
0x5b, 0xfc, 0xbf, 0xf1, 0xb9, 0xb4, 0x98, 0x00, 0xda, 0x55, 0x45, 0xa8, 0xf0, 0x02, 0xa8, 0xd6,
|
||||
0xe0, 0xe4, 0x54, 0x4f, 0x5d, 0x75, 0xb1, 0xdc, 0xf2, 0x22, 0x80, 0xff, 0xeb, 0x13, 0xf7, 0xb1,
|
||||
0x14, 0xed, 0x07, 0x24, 0xd1, 0xab, 0xe1, 0xc8, 0x53, 0x52, 0x60, 0x25, 0xc8, 0x89, 0xe0, 0x30,
|
||||
0xd2, 0xa4, 0x61, 0xf6, 0x65, 0xc7, 0x3a, 0x19, 0x79, 0x2a, 0x35, 0x03, 0x22, 0x88, 0x65, 0x1f,
|
||||
0x92, 0x65, 0x2d, 0xb1, 0x71, 0xc2, 0x04, 0x16, 0x96, 0x18, 0x2c, 0xa4, 0xd0, 0xc0, 0xdc, 0xac,
|
||||
0x3d, 0xb7, 0x82, 0xb2, 0x3f, 0xc0, 0x1b, 0xff, 0xae, 0x5c, 0xb8, 0x63, 0xd2, 0xb3, 0xd0, 0x55,
|
||||
0xfa, 0xb0, 0xf3, 0xd1, 0xc2, 0x55, 0xb5, 0x6a, 0x5d, 0x60, 0x3d, 0x94, 0xa4, 0x26, 0x6f, 0x5e,
|
||||
0x8e, 0x01, 0xf8, 0xe1, 0xd4, 0x1a, 0x0c, 0xd7, 0x32, 0xcd, 0xf0, 0xdc, 0x70, 0x04, 0x61, 0x42,
|
||||
0xd0, 0x81, 0xaf, 0x12, 0x04, 0x54, 0x76, 0x18, 0x3a, 0x57, 0x09, 0xbe, 0x5b, 0xa8, 0xf0, 0x72,
|
||||
0xa8, 0xb6, 0x60, 0xe4, 0xc2, 0xb5, 0x01, 0x1b, 0x87, 0x91, 0x24, 0x5a, 0xbf, 0x07, 0x95, 0x1d,
|
||||
0xac, 0x1c, 0xcf, 0x66, 0x8d, 0x38, 0x16, 0xf4, 0x0a, 0xe5, 0xd9, 0x58, 0x2f, 0x16, 0x6d, 0x04,
|
||||
0x18, 0x9a, 0x06, 0x01, 0xdc, 0xff, 0x1c, 0xec, 0x23, 0x7c, 0x19, 0xfc, 0x6a, 0x73, 0x9e, 0xbb,
|
||||
0x9c, 0x01, 0x40, 0x7c, 0xc1, 0x80, 0x5d, 0x46, 0x98, 0xe1, 0x92, 0x04, 0xe7, 0x32, 0xc4, 0x1d,
|
||||
0xb8, 0x0e, 0x23, 0x4f, 0x41, 0xc5, 0x81, 0xba, 0xfb, 0x3f, 0xad, 0xb6, 0x94, 0x76, 0xdc, 0x9e,
|
||||
0x0f, 0x9b, 0x33, 0xcf, 0xff, 0xed, 0xbf, 0xf3, 0xd1, 0xc1, 0x1f, 0x59, 0x54, 0xf0, 0xa7, 0x9d,
|
||||
0x1d, 0x3c, 0x5f, 0x28, 0x33, 0x78, 0x9f, 0x85, 0x58, 0x8b, 0x6e, 0xad, 0x23, 0x17, 0x60, 0xc0,
|
||||
0x10, 0x45, 0x16, 0xa0, 0xe4, 0x44, 0x7c, 0x2c, 0x94, 0x1d, 0x24, 0x5a, 0xbf, 0x00, 0x95, 0x17,
|
||||
0x7c, 0x1c, 0x55, 0x40, 0x73, 0x63, 0x44, 0x0a, 0x74, 0xe4, 0xbc, 0xe0, 0xec, 0x7a, 0x11, 0xdd,
|
||||
0x39, 0x2f, 0x24, 0xb8, 0x49, 0xd1, 0x4c, 0x1a, 0xba, 0x43, 0x22, 0x74, 0x0a, 0x32, 0x9a, 0xaf,
|
||||
0x00, 0x0d, 0x66, 0xd3, 0x69, 0x65, 0x6a, 0x1f, 0x80, 0x41, 0xc5, 0xe1, 0xdc, 0xc8, 0x5f, 0xac,
|
||||
0xa1, 0x80, 0x90, 0xee, 0x85, 0x78, 0x1f, 0x22, 0x7c, 0x1b, 0x69, 0xdb, 0x35, 0x87, 0x8c, 0xcb,
|
||||
0x31, 0x69, 0x7c, 0xbf, 0x99, 0xa3, 0xe3, 0xf9, 0x1c, 0xce, 0x82, 0x3b, 0xd7, 0x2f, 0xa5, 0x83,
|
||||
0xfa, 0xb9, 0x31, 0x62, 0xf2, 0x96, 0x85, 0xb2, 0x04, 0x94, 0x8c, 0x18, 0xff, 0xcd, 0x2a, 0x42,
|
||||
0x0c, 0x02, 0xa9, 0x4f, 0xbd, 0x6a, 0xc0, 0x82, 0x9b, 0x4d, 0x25, 0x80, 0x87, 0x22, 0x5b, 0xe0,
|
||||
0x6b, 0x77, 0xba, 0xa3, 0x40, 0xdd, 0x03, 0x9d, 0x19, 0x11, 0xbc, 0x0d, 0xc6, 0x89, 0x35, 0xd6,
|
||||
0xa3, 0x88, 0xaf, 0x17, 0xad, 0x3d, 0xb0, 0x26, 0x42, 0x61, 0xb0, 0x72, 0x08, 0x9a, 0xdd, 0x42,
|
||||
0x83, 0x92, 0x45, 0x37, 0x3a, 0x97, 0x93, 0x55, 0xb4, 0x38, 0xa3, 0x42, 0x2a, 0x62, 0xe2, 0x67,
|
||||
0x4d, 0x1b, 0x98, 0xdb, 0x5d, 0xff, 0xd4, 0xfe, 0x02, 0x80, 0x81, 0x0c, 0xaa, 0x06, 0xa2, 0x96,
|
||||
0xab, 0x20, 0xe4, 0x96, 0xeb, 0xe9, 0x1a, 0xae, 0xb2, 0xae, 0x0c, 0xbf, 0x42, 0xa4, 0xd6, 0x02,
|
||||
0x16, 0x39, 0x4a, 0x9c, 0x73, 0x33, 0xb6, 0xcf, 0xf8, 0x48, 0x1e, 0xf9, 0xe7, 0xdf, 0xb3, 0xb4,
|
||||
0xa1, 0x85, 0x23, 0x81, 0x62, 0xe0, 0x4b, 0xf2, 0x76, 0xb9, 0xc4, 0xf2, 0x61, 0x56, 0x7d, 0xba,
|
||||
0x86, 0x01, 0x17, 0x86, 0x48, 0xe0, 0x14, 0x61, 0x07, 0xbf, 0x5c, 0x58, 0xd0, 0xe1, 0xfc, 0xb3,
|
||||
0x56, 0x1b, 0xe7, 0x46, 0x9e, 0x15, 0x11, 0x19, 0x12, 0x39, 0x57, 0xf8, 0xdd, 0xe0, 0x84, 0xf8,
|
||||
0x0c, 0x6e, 0x27, 0xd3, 0x9f, 0x22, 0xd5, 0x50, 0x71, 0x48, 0xa2, 0x8a, 0xe0, 0xe4, 0xa5, 0x85,
|
||||
0x5a, 0xed, 0x00, 0x24, 0xb2, 0x7f, 0x9f, 0xa5, 0x41, 0xf5, 0xc1, 0xc9, 0x55, 0x47, 0xf1, 0xf5,
|
||||
0x63, 0xb8, 0xc9, 0x8b, 0x17, 0x70, 0x63, 0xd5, 0xee, 0xef, 0xc9, 0x78, 0x47, 0xc1, 0x9d, 0x13,
|
||||
0x00, 0xc4, 0xf2, 0x8d, 0xf6, 0x18, 0x7f, 0xe7, 0xcc, 0xab, 0x86, 0xcd, 0xa8, 0x1b, 0x13, 0xd1,
|
||||
0x4c, 0x33, 0x96, 0x98, 0x81, 0xbc, 0x44, 0x1a, 0x0f, 0x91, 0x21, 0xab, 0x98, 0xaa, 0x92, 0x04,
|
||||
0xaf, 0x32, 0x75, 0x1b, 0x26, 0xf0, 0xf5, 0x60, 0xe0, 0x16, 0x60, 0xfe, 0xb9, 0xf8, 0x78, 0x13,
|
||||
0xb7, 0xd0, 0xb6, 0x9d, 0xc3, 0x00, 0x55, 0x46, 0x59, 0x5d, 0xf0, 0xe1, 0x38, 0x5a, 0xcb, 0x01,
|
||||
0xec, 0xa2, 0x02, 0x31, 0xf5, 0x0c, 0xff, 0xae, 0xe2, 0xcd, 0xa3, 0x09, 0x70, 0x00, 0x7b, 0x78,
|
||||
0x29, 0x86, 0x05, 0x86, 0x62, 0x18, 0x05, 0x84, 0x09, 0xaa, 0x58, 0x30, 0xff, 0x9d, 0x10, 0x2d,
|
||||
0xb7, 0x79, 0xfb, 0xd7, 0x83, 0x92, 0x07, 0x6e, 0x6c, 0xde, 0x02, 0xf4, 0xb4, 0xa2, 0xb7, 0x01,
|
||||
0xc8, 0x8b, 0x55, 0x14, 0x2e, 0xbd, 0x6f, 0xf4, 0x4b, 0x75, 0xc6, 0x00, 0x0e, 0x48, 0x1b, 0x56,
|
||||
0x5e, 0x8d, 0xaf, 0x5d, 0x6f, 0xbd, 0x88, 0xc4, 0x0c, 0x2e, 0x04, 0xfa, 0x69, 0x06, 0x53, 0xd4,
|
||||
0x50, 0x15, 0xb2, 0x40, 0x82, 0x51, 0x9a, 0xb2, 0x54, 0x73, 0x15, 0x55, 0xf2, 0x91, 0x3c, 0xd3,
|
||||
0x92, 0x66, 0xf4, 0xf0, 0x92, 0xef, 0xf8, 0x97, 0x26, 0x7c, 0x1d, 0xfa, 0x93, 0xbf, 0x08, 0x0f,
|
||||
0x9c, 0x30, 0x21, 0x62, 0xb5, 0x44, 0xab, 0xb4, 0x00, 0x8a, 0x85, 0x83, 0xfa, 0x1e, 0xbb, 0xc3,
|
||||
0x54, 0x72, 0x80, 0x18, 0xca, 0xa7, 0xae, 0xe2, 0xf1, 0x48, 0x07, 0xfa, 0xd3, 0x43, 0x56, 0x11,
|
||||
0x4a, 0x3b, 0x02, 0x31, 0x66, 0x0c, 0x7f, 0xe7, 0x4c, 0x9b, 0x7d, 0x94, 0xcc, 0x90, 0x46, 0x06,
|
||||
0x36, 0x94, 0x70, 0x9a, 0x58, 0x59, 0x1e, 0xe0, 0x5e, 0x9b, 0x15, 0xe2, 0xae, 0x23, 0x1a, 0x52,
|
||||
0xbe, 0xfd, 0xfb, 0x15, 0xd7, 0xce, 0xc5, 0xcf, 0x42, 0x78, 0x00, 0x36, 0xc8, 0x88, 0xea, 0x54,
|
||||
0x1c, 0x94, 0x7f, 0xbc, 0x2e, 0x7b, 0x44, 0x5c, 0x09, 0x64, 0xdb, 0xf0, 0x63, 0xb8, 0xcb, 0x8b,
|
||||
0x3f, 0x5b, 0x8f, 0x50, 0xdf, 0xbd, 0xc8, 0xec, 0x7c, 0xf1, 0xde, 0xd0, 0xc0, 0xf3, 0x89, 0x03,
|
||||
0x62, 0x4e, 0xba, 0x88, 0x65, 0x3d, 0xc0, 0xb1, 0x9c, 0xc1, 0xf6, 0xd2, 0xa3, 0xa4, 0x8c, 0x32,
|
||||
0x60, 0x9a, 0x18, 0x36, 0xcf, 0x9a, 0xe6, 0x45, 0x57, 0x66, 0xe6, 0x85, 0x01, 0x66, 0x51, 0x96,
|
||||
0x61, 0xec, 0xb2, 0xbf, 0xcf, 0x28, 0x97, 0x8d, 0x5d, 0xd5, 0x6c, 0x65, 0xc1, 0x23, 0x1f, 0x22,
|
||||
0x05, 0xd6, 0x2a, 0x18, 0x3f, 0x2d, 0xe0, 0x12, 0xc3, 0x78, 0xbf, 0xf3, 0x85, 0x79, 0x96, 0x8b,
|
||||
0x87, 0x75, 0x48, 0x33, 0x95, 0x9b, 0x82, 0xb2, 0x58, 0x4a, 0xc1, 0x80, 0x47, 0x46, 0x46, 0x29,
|
||||
0xc1, 0x80, 0x03, 0xa8, 0xc7, 0x3e, 0x00, 0xbe, 0xb2, 0xc3, 0x14, 0x06, 0x48, 0x2e, 0xfc, 0x3b,
|
||||
0x95, 0x0c, 0x7f, 0xe7, 0xf0, 0x3b, 0xec, 0x0a, 0x9e, 0x00, 0x97, 0x8a, 0xa2, 0xe9, 0x55, 0x2d,
|
||||
0x38, 0x3a, 0xfb, 0xe7, 0x7e, 0x77, 0x72, 0x6a, 0xc7, 0x1b, 0x4e, 0x18, 0xbc, 0x20, 0x4b, 0x6b,
|
||||
0x5f, 0xbf, 0xf1, 0x0e, 0x11, 0x68, 0xf8, 0xc9, 0x00, 0xd6, 0x90, 0x9b, 0xbc, 0x00, 0xca, 0xbe,
|
||||
0xf2, 0x7a, 0xe1, 0x4f, 0xc6, 0x8d, 0xb6, 0x6b, 0x7d, 0x77, 0x7b, 0x32, 0x69, 0x56, 0x50, 0xc4,
|
||||
0x50, 0x35, 0xc0, 0xe0, 0xe8, 0xc6, 0xf5, 0x77, 0x73, 0xc0, 0x00, 0xb3, 0xe1, 0x0f, 0x71, 0x0b,
|
||||
0x80, 0x35, 0x09, 0x7f, 0x44, 0x2d, 0xbb, 0x4f, 0x70, 0xae, 0x69, 0x99, 0x19, 0xed, 0xaa, 0xe3,
|
||||
0x31, 0x3e, 0x37, 0xcb, 0x95, 0x9a, 0xc0, 0x05, 0xbe, 0x7d, 0xb4, 0xed, 0x72, 0xd7, 0x41, 0x82,
|
||||
0xa4, 0x05, 0x19, 0x21, 0xc9, 0x38, 0x28, 0xb0, 0xd3, 0xfb, 0x01, 0x51, 0x86, 0x86, 0x7f, 0xd6,
|
||||
0xa6, 0x86, 0x60, 0x13, 0x83, 0x98, 0xd1, 0xaf, 0xb9, 0x4f, 0x10, 0x73, 0xb6, 0x28, 0x2f, 0xf2,
|
||||
0xda, 0x53, 0x6d, 0x19, 0xbd, 0x78, 0x77, 0xf7, 0x05, 0x36, 0x7f, 0x22, 0x78, 0x2d, 0x14, 0x62,
|
||||
0xc5, 0xdd, 0x5f, 0xa8, 0x12, 0x5d, 0x7f, 0x80, 0x9d, 0xd9, 0x41, 0x67, 0xd4, 0x30, 0x1a, 0xbe,
|
||||
0x59, 0xf8, 0xb1, 0xdc, 0xa4, 0xc5, 0xbf, 0xb3, 0xc7, 0xaf, 0x05, 0x5e, 0xc1, 0xc9, 0x26, 0x9f,
|
||||
0x89, 0x3a, 0x1a, 0x41, 0x6c, 0xd1, 0xc2, 0x07, 0x69, 0xcf, 0xff, 0xaf, 0xa1, 0x2d, 0x5f, 0xaa,
|
||||
0xeb, 0xc0, 0xd5, 0x3d, 0x34, 0x1b, 0x01, 0xdd, 0x08, 0xdc, 0x15, 0xdc, 0x6f, 0xda, 0x44, 0x35,
|
||||
0x95, 0x05, 0xb0, 0x13, 0x58, 0x66, 0x7e, 0xa8, 0x4d, 0x55, 0xb0, 0xfe, 0xc8, 0x49, 0xcd, 0xe3,
|
||||
0x5e, 0xfb, 0x9a, 0x1a, 0x9b, 0xd7, 0x3f, 0xe9, 0x4c, 0xe8, 0x1d, 0x0b, 0x67, 0xa5, 0x0d, 0x82,
|
||||
0x17, 0x4c, 0x35, 0x5e, 0x86, 0xa1, 0x22, 0x20, 0xf1, 0x23, 0x9c, 0x55, 0x21, 0xb3, 0xf0, 0xc0,
|
||||
0x67, 0x4c, 0xc3, 0xc3, 0xe0, 0xcf, 0x44, 0xeb, 0xcc, 0x8c, 0xb3, 0x0a, 0x77, 0x0c, 0x76, 0x22,
|
||||
0x95, 0xe7, 0xc1, 0xa5, 0xb1, 0xdf, 0x82, 0xb8, 0x00, 0xb0, 0xae, 0x58, 0x0c, 0xff, 0x02, 0xf1,
|
||||
0xe1, 0x0c, 0x2b, 0x62, 0x0f, 0xc7, 0x18, 0xcd, 0xbe, 0x77, 0xee, 0x15, 0x49, 0x53, 0xa1, 0x14,
|
||||
0xc9, 0x6e, 0x98, 0xc1, 0xef, 0xd1, 0xbe, 0x0d, 0xd7, 0x5a, 0xfe, 0x61, 0xdf, 0x11, 0xc5, 0x34,
|
||||
0x2a, 0xfe, 0x58, 0x39, 0x46, 0x8d, 0x59, 0x3c, 0x58, 0xcd, 0x0b, 0x01, 0x55, 0x00, 0x49, 0xbd,
|
||||
0xfe, 0x44, 0x37, 0x8c, 0xae, 0x12, 0x7b, 0x25, 0x03, 0x70, 0x09, 0x5e, 0xc0, 0xb6, 0x8b, 0x72,
|
||||
0x00, 0xb0, 0x8d, 0x83, 0xd5, 0x10, 0xbe, 0xda, 0x38, 0x42, 0xaf, 0x8b, 0xb1, 0xcc, 0x54, 0x16,
|
||||
0x62, 0x86, 0xff, 0x9c, 0x03, 0xbf, 0x8d, 0x9b, 0x1e, 0x1b, 0x3d, 0x1c, 0x6b, 0x78, 0xd7, 0x08,
|
||||
0xfc, 0xc7, 0x24, 0xdb, 0xc6, 0xff, 0xed, 0x11, 0xa7, 0x86, 0x14, 0x47, 0x0e, 0x5e, 0xf6, 0x96,
|
||||
0xb1, 0x79, 0x03, 0x4a, 0x0b, 0x53, 0xfd, 0x93, 0x47, 0x1b, 0x6c, 0x25, 0x6a, 0x90, 0xf4, 0x21,
|
||||
0x00, 0x7b, 0xd6, 0x96, 0xbe, 0x73, 0x3c, 0xe2, 0xd4, 0xe2, 0xf6, 0xd2, 0x23, 0xe9, 0x0d, 0xb2,
|
||||
0x4a, 0x2f, 0xe6, 0x1f, 0x3d, 0x89, 0x42, 0x79, 0x62, 0xbf, 0x02, 0xf0, 0x86, 0x0c, 0xd7, 0x3b,
|
||||
0x04, 0x95, 0x44, 0x18, 0x5c, 0xe4, 0x6d, 0x7c, 0x8d, 0xb4, 0x16, 0x55, 0xa3, 0xf3, 0xa9, 0xf7,
|
||||
0x4b, 0x54, 0x20, 0x3d, 0x28, 0x39, 0x97, 0x24, 0x5c, 0x00, 0x99, 0xdc, 0x7f, 0xe7, 0x92, 0x82,
|
||||
0x5b, 0x83, 0x3b, 0x81, 0x8e, 0xe3, 0x4e, 0x2d, 0x7c, 0x03, 0x1e, 0xb2, 0xcd, 0x7b, 0x39, 0x22,
|
||||
0x8d, 0x58, 0xfe, 0xba, 0xc5, 0xa2, 0xe3, 0x6c, 0xc3, 0xf2, 0x72, 0x3a, 0x30, 0xbc, 0xba, 0x69,
|
||||
0x06, 0xf9, 0x46, 0x21, 0xa1, 0x80, 0x83, 0x62, 0xaa, 0xa0, 0xd8, 0x8b, 0xe7, 0x27, 0x28, 0xd5,
|
||||
0xd7, 0xec, 0xae, 0x15, 0xfd, 0x92, 0x63, 0x64, 0x1c, 0x04, 0xab, 0x23, 0x1b, 0x77, 0xf1, 0x5e,
|
||||
0x34, 0x93, 0x01, 0xc9, 0x06, 0xdb, 0xcf, 0x98, 0xc4, 0x39, 0x31, 0xbf, 0x70, 0xde, 0x69, 0x47,
|
||||
0x6f, 0x75, 0xe0, 0x81, 0x0a, 0xea, 0x89, 0x26, 0x4d, 0xc8, 0x3a, 0xc0, 0xf0, 0xbc, 0x06, 0xd7,
|
||||
0xfb, 0xbc, 0xc7, 0x97, 0x7e, 0x4b, 0xfb, 0xcd, 0x8b, 0xfe, 0xee, 0xdb, 0xd5, 0x54, 0xbe, 0x5d,
|
||||
0x05, 0xf3, 0x8f, 0x7e, 0x8e, 0xe9, 0x78, 0x1f, 0xcf, 0xfa, 0xae, 0x21, 0x91, 0x15, 0x80, 0x17,
|
||||
0x78, 0x55, 0xc4, 0x21, 0x44, 0xdd, 0xbf, 0xaf, 0x6f, 0xd2, 0x11, 0xcb, 0x9a, 0x8a, 0x34, 0xa5,
|
||||
0xf0, 0x2d, 0x51, 0x42, 0x31, 0xce, 0xf2, 0x8e, 0xa4, 0x12, 0x16, 0x71, 0xb6, 0x8a, 0x49, 0x54,
|
||||
0x6b, 0x0e, 0x79, 0xa6, 0x8f, 0xf2, 0xe3, 0x00, 0x3b, 0x4b, 0xaf, 0xcf, 0x02, 0x41, 0xeb, 0xf0,
|
||||
0x75, 0xd1, 0xb7, 0xb8, 0x92, 0x86, 0xfd, 0x25, 0x08, 0x7c, 0xb3, 0xdf, 0x8b, 0x5e, 0x66, 0xbd,
|
||||
0x1c, 0x91, 0x46, 0xac, 0x5d, 0xbd, 0xe3, 0xaa, 0x15, 0xf1, 0xb7, 0x04, 0xff, 0x31, 0x65, 0xbb,
|
||||
0x81, 0x4d, 0x9b, 0x9d, 0x0d, 0x02, 0xfc, 0xc2, 0x91, 0x70, 0x0b, 0x70, 0x1d, 0xa4, 0x0a, 0xa2,
|
||||
0xba, 0x60, 0x58, 0x81, 0x5d, 0x13, 0xd1, 0xbe, 0xe7, 0x81, 0x9a, 0x4c, 0xed, 0x81, 0x72, 0x22,
|
||||
0xaa, 0xa9, 0x66, 0xc6, 0x12, 0x51, 0x58, 0x72, 0x5a, 0x13, 0xde, 0xcc, 0x18, 0xab, 0x75, 0x67,
|
||||
0xbe, 0x28, 0x7c, 0x9e, 0x88, 0x2d, 0x42, 0xc8, 0xe2, 0xe0, 0x61, 0x62, 0xe0, 0x84, 0x69, 0xef,
|
||||
0xdf, 0x35, 0x5a, 0xf9, 0xfd, 0x19, 0x17, 0x4d, 0xf2, 0x37, 0x29, 0xfc, 0xe0, 0x39, 0x17, 0x6f,
|
||||
0xab, 0xff, 0x8d, 0x8a, 0x2d, 0xa2, 0xd6, 0x55, 0x37, 0x8c, 0xa1, 0x43, 0xb9, 0x9f, 0x90, 0x8d,
|
||||
0x7c, 0x1c, 0xb7, 0xa5, 0x5e, 0x10, 0xdf, 0xab, 0x75, 0x49, 0xc1, 0xc9, 0xd4, 0xcf, 0xaf, 0x63,
|
||||
0x24, 0x99, 0xab, 0x07, 0xef, 0x51, 0x9b, 0xdb, 0xfa, 0xc2, 0xe3, 0x5f, 0xa6, 0x19, 0x21, 0x83,
|
||||
0x04, 0xed, 0x00, 0x92, 0x47, 0xa6, 0xd5, 0xc0, 0x7f, 0x9c, 0x30, 0x13, 0x78, 0x16, 0x44, 0x40,
|
||||
0xaa, 0xae, 0xef, 0xf0, 0x4b, 0x13, 0x46, 0x1f, 0x05, 0x64, 0x11, 0xd3, 0x13, 0xdb, 0x66, 0x86,
|
||||
0x30, 0x31, 0x77, 0x4d, 0xf0, 0x32, 0x88, 0xa4, 0x8d, 0x9c, 0xf7, 0xef, 0x57, 0x80, 0xc3, 0x84,
|
||||
0x27, 0x34, 0x9c, 0x1b, 0x6d, 0x9f, 0x98, 0x11, 0xf8, 0x63, 0xc9, 0xfd, 0x2c, 0x29, 0xf1, 0xa8,
|
||||
0x4e, 0x19, 0x5c, 0x41, 0x00, 0xa5, 0x17, 0xcc, 0x0c, 0x91, 0x5a, 0xbe, 0x93, 0x06, 0x84, 0xdb,
|
||||
0x0c, 0xa3, 0x35, 0x4f, 0xdc, 0xc5, 0x35, 0xa7, 0x61, 0x45, 0xf7, 0x84, 0xd3, 0xe1, 0xae, 0x6c,
|
||||
0x02, 0x55, 0x94, 0x30, 0x79, 0xc3, 0xaa, 0x87, 0xab, 0x6e, 0xf8, 0x70, 0x80, 0x7b, 0xea, 0xa3,
|
||||
0xd7, 0xb5, 0x92, 0x2c, 0xd5, 0x83, 0xac, 0x68, 0xb6, 0x03, 0xfe, 0xb2, 0x5c, 0xd7, 0xa1, 0x85,
|
||||
0x04, 0x04, 0x54, 0x42, 0x1a, 0xc7, 0x80, 0x76, 0xaa, 0x7b, 0x30, 0x08, 0xcb, 0x0c, 0x87, 0x08,
|
||||
0x2e, 0x19, 0x10, 0x60, 0x05, 0x53, 0xd9, 0xa9, 0xe0, 0xc8, 0xb4, 0x49, 0x51, 0xc5, 0xd0, 0x8e,
|
||||
0x33, 0x8c, 0xc0, 0x9c, 0x70, 0x02, 0x9b, 0x58, 0xdb, 0xf0, 0x43, 0x99, 0x75, 0x39, 0xb6, 0x78,
|
||||
0x99, 0xd1, 0xe3, 0xe9, 0x8f, 0x80, 0x92, 0x12, 0x9b, 0xa0, 0xc1, 0x60, 0xdf, 0x01, 0x64, 0x7c,
|
||||
0x1f, 0x07, 0xc4, 0x3e, 0xe3, 0xbb, 0x00, 0x58, 0x0f, 0x00, 0x49, 0x3b, 0x41, 0x44, 0xa4, 0x54,
|
||||
0x88, 0xd5, 0xd7, 0xad, 0xcd, 0x0c, 0x2a, 0x26, 0x50, 0xaa, 0x8b, 0x0b, 0xf2, 0xbb, 0x16, 0x74,
|
||||
0xcb, 0x6a, 0x37, 0xe0, 0x72, 0x2d, 0x23, 0x11, 0xb2, 0xae, 0x28, 0xa4, 0x30, 0xc0, 0x18, 0x0b,
|
||||
0xda, 0x55, 0x63, 0x69, 0xc5, 0x95, 0xce, 0xa2, 0x7d, 0xc8, 0xb5, 0x2a, 0x75, 0xad, 0x00, 0x49,
|
||||
0x89, 0x6e, 0x0e, 0x4a, 0x38, 0xe6, 0x24, 0x88, 0xab, 0x07, 0xef, 0x51, 0xb5, 0x5f, 0x80, 0xec,
|
||||
0x87, 0xdb, 0x87, 0x0a, 0xb6, 0xcf, 0xc0, 0x20, 0x1c, 0x10, 0x87, 0x01, 0x18, 0x05, 0xd3, 0x8c,
|
||||
0x02, 0x6c, 0x43, 0x0c, 0x18, 0x32, 0x3f, 0xb7, 0x45, 0xb6, 0x24, 0xb8, 0xe1, 0x61, 0x1b, 0x73,
|
||||
0xd7, 0x3c, 0x67, 0x95, 0x57, 0x69, 0x3c, 0x39, 0x5e, 0x3a, 0xc6, 0x44, 0x28, 0xc4, 0x95, 0x0e,
|
||||
0x5d, 0x33, 0x85, 0x43, 0x8d, 0xd8, 0xc6, 0xf1, 0x2d, 0x51, 0x31, 0x3c, 0x7b, 0xdb, 0xb6, 0xb5,
|
||||
0x94, 0xe6, 0xbd, 0x75, 0xd6, 0x05, 0x2a, 0xf4, 0xfa, 0x6b, 0xbc, 0x0a, 0xa7, 0xda, 0x54, 0xe4,
|
||||
0x6b, 0xc9, 0x72, 0x71, 0x8b, 0x54, 0xa3, 0x93, 0x79, 0x0a, 0x7d, 0xd5, 0x81, 0x9f, 0xc2, 0x82,
|
||||
0x77, 0x1f, 0xd8, 0xe5, 0x5f, 0xd2, 0xee, 0xbe, 0x84, 0x19, 0x10, 0x04, 0xfc, 0x6c, 0x71, 0xa6,
|
||||
0xc2, 0x2d, 0xd3, 0xed, 0x1c, 0xbd, 0x9e, 0xc6, 0x97, 0x82, 0xb8, 0x10, 0xb7, 0xae, 0x9a, 0xc0,
|
||||
0x65, 0x3e, 0x6f, 0x6d, 0xce, 0x81, 0xc6, 0xbc, 0x96, 0xfc, 0x67, 0xd2, 0xfc, 0x0d, 0x95, 0x9e,
|
||||
0x05, 0xbd, 0xfb, 0xe6, 0x74, 0x3a, 0x56, 0x36, 0xec, 0x0f, 0x69, 0xca, 0xcf, 0xcd, 0xa9, 0xef,
|
||||
0xb3, 0x86, 0x63, 0xb3, 0xed, 0xde, 0x0b, 0x66, 0x5f, 0x3f, 0xaf, 0x80, 0x7f, 0xce, 0x92, 0x4d,
|
||||
0xaf, 0x83, 0x11, 0xf6, 0x83, 0xac, 0x4f, 0xc1, 0x49, 0x2b, 0x16, 0x40, 0x8f, 0x0b, 0xcb, 0xec,
|
||||
0x6e, 0xfc, 0xe4, 0x8c, 0xcf, 0xe0, 0x94, 0xd3, 0xac, 0x1c, 0xcd, 0x46, 0x58, 0x0e, 0xa6, 0x44,
|
||||
0x47, 0x00, 0xb6, 0x94, 0x9f, 0xa7, 0x25, 0x9a, 0xb8, 0x6b, 0xd6, 0x93, 0x5b, 0xb5, 0xb7, 0x59,
|
||||
0xf0, 0x2c, 0x2c, 0x90, 0x61, 0x4a, 0xbd, 0x52, 0xea, 0x19, 0x97, 0x0a, 0x91, 0xb1, 0x75, 0x05,
|
||||
0xd4, 0xdd, 0x3d, 0x64, 0x5b, 0x50, 0x70, 0x7c, 0xb7, 0x45, 0x01, 0xdf, 0x37, 0x83, 0x1a, 0xdf,
|
||||
0xc0, 0x76, 0x81, 0x2b, 0xc1, 0x63, 0x62, 0x5b, 0x35, 0xb1, 0x89, 0xa7, 0xf2, 0x17, 0xc3, 0xd7,
|
||||
0x16, 0xf8, 0x7c, 0x61, 0x96, 0x4b, 0x86, 0x93, 0x7c, 0x0d, 0x1c, 0x6c, 0x3e, 0x87, 0x27, 0xb5,
|
||||
0x09, 0xb0, 0xf7, 0x2c, 0x88, 0xef, 0x50, 0xc9, 0x4a, 0x36, 0xc6, 0x47, 0xfa, 0xcb, 0xa6, 0x3f,
|
||||
0x70, 0xc6, 0xbf, 0xe8, 0xed, 0xae, 0x38, 0x0d, 0xa4, 0xe0, 0x4a, 0xcb, 0xe1, 0x6a, 0xa3, 0x0d,
|
||||
0x78, 0x5a, 0x93, 0x43, 0x6a, 0x96, 0x52, 0xad, 0x23, 0x80, 0x5d, 0x10, 0x5d, 0x34, 0xa5, 0x6c,
|
||||
0xb5, 0xca, 0xcb, 0x7c, 0x23, 0xbf, 0x04, 0xa9, 0xde, 0xe0, 0x72, 0xbc, 0x32, 0x5b, 0xc0, 0x09,
|
||||
0x4b, 0x46, 0x42, 0x0e, 0x94, 0x93, 0x8c, 0x9d, 0x9e, 0xa3, 0xdf, 0xa7, 0xf8, 0x7a, 0xc5, 0x79,
|
||||
0x39, 0x53, 0xe9, 0x42, 0xe9, 0x56, 0xff, 0xcf, 0x48, 0x5a, 0x8a, 0xc0, 0x31, 0x79, 0x95, 0x36,
|
||||
0xf4, 0x3e, 0x4e, 0xdb, 0x6b, 0x3f, 0x42, 0x22, 0xd3, 0x73, 0xc0, 0xdd, 0x31, 0x4b, 0xad, 0x87,
|
||||
0x6f, 0xf0, 0xdf, 0x3c, 0xff, 0xb5, 0xb0, 0xdc, 0x3d, 0xe5, 0x36, 0x05, 0x07, 0xf7, 0xf2, 0x7a,
|
||||
0x08, 0x8b, 0xc6, 0xfd, 0x89, 0x50, 0xa6, 0xbd, 0xfc, 0x27, 0x5b, 0x2c, 0x0b, 0xec, 0x25, 0x35,
|
||||
0x49, 0x83, 0x1a, 0xc0, 0x11, 0x9a, 0x34, 0x4e, 0x12, 0x3c, 0x88, 0x87, 0xf3, 0xde, 0x60, 0x1e,
|
||||
0xbe, 0x38, 0xf5, 0x8c, 0x24, 0x9a, 0x37, 0x07, 0xc7, 0xf7, 0x94, 0xa9, 0x17, 0x3d, 0xac, 0x77,
|
||||
0xbc, 0x88, 0x78, 0x16, 0x3d, 0x43, 0x9a, 0xf6, 0x72, 0x51, 0x1a, 0xb0, 0x95, 0xfb, 0xae, 0x03,
|
||||
0xc0, 0x26, 0x91, 0x60, 0x5d, 0x40, 0xd3, 0x61, 0xaa, 0x21, 0x01, 0x18, 0xd5, 0x86, 0xb5, 0x78,
|
||||
0x01, 0x4c, 0xf8, 0x4f, 0x52, 0xbd, 0xe8, 0x7d, 0x99, 0x03, 0x7d, 0x8d, 0xce, 0x1a, 0x7d, 0xce,
|
||||
0xc2, 0xb2, 0xfb, 0x02, 0xfc, 0x67, 0xbf, 0x1b, 0xaa, 0x8c, 0x35, 0x26, 0x15, 0x2d, 0x84, 0x96,
|
||||
0xc4, 0xac, 0xf6, 0x5b, 0xc0, 0x03, 0x77, 0x6f, 0xc2, 0xe4, 0xbd, 0xe1, 0x25, 0xa6, 0x84, 0xaf,
|
||||
0x20, 0xab, 0x54, 0xf1, 0x71, 0x05, 0x83, 0x91, 0x98, 0x81, 0x7b, 0x77, 0xaa, 0xbd, 0x2e, 0xae,
|
||||
0x3f, 0xd6, 0x27, 0x2e, 0xcd, 0x3d, 0x61, 0x19, 0xb1, 0x24, 0xc0, 0x2f, 0xbd, 0x2b, 0x36, 0x05,
|
||||
0xd7, 0x06, 0x3d, 0xcf, 0x27, 0x8e, 0x50, 0x82, 0x16, 0xa6, 0xc0, 0x09, 0xa3, 0x9b, 0x8f, 0x4b,
|
||||
0x4b, 0x6c, 0x56, 0x0e, 0x97, 0xb3, 0xf5, 0x3a, 0xe0, 0x38, 0xcf, 0x72, 0x93, 0x28, 0xa3, 0x85,
|
||||
0x6b, 0x5f, 0xfe, 0x61, 0x10, 0x77, 0xb0, 0x15, 0x92, 0x4c, 0x00, 0x86, 0x92, 0xc3, 0x09, 0x68,
|
||||
0xb9, 0xc8, 0xc5, 0x78, 0x01, 0xcb, 0x9e, 0x2f, 0xf4, 0xf3, 0xd8, 0x41, 0xcd, 0x88, 0xd6, 0x8b,
|
||||
0xae, 0x5b, 0x1e, 0x54, 0x7e, 0xf1, 0xec, 0xa0, 0xef, 0x75, 0xd6, 0xd9, 0xce, 0x1f, 0x6c, 0x8e,
|
||||
0xe6, 0x5a, 0x15, 0x46, 0x1e, 0x88, 0x2e, 0x2b, 0xbb, 0xb9, 0xb4, 0xbf, 0x4f, 0x63, 0xf9, 0x5e,
|
||||
0x8e, 0xcd, 0xa3, 0xfd, 0x11, 0x53, 0x2c, 0xf3, 0x54, 0x57, 0x3a, 0xf7, 0x88, 0x18, 0x57, 0x11,
|
||||
0x9d, 0x89, 0xb5, 0xff, 0xca, 0xb1, 0x66, 0x22, 0xbe, 0x24, 0x78, 0x13, 0x69, 0x47, 0x16, 0xa3,
|
||||
0xc0, 0x09, 0x6e, 0x9f, 0x0f, 0xed, 0x5f, 0x2f, 0xab, 0x9c, 0x95, 0xaa, 0x6f, 0xea, 0x00, 0xcf,
|
||||
0x55, 0xde, 0xbd, 0x8f, 0xc9, 0x18, 0xc7, 0xc1, 0x41, 0x9b, 0xb0, 0x72, 0x35, 0x1a, 0x0f, 0xb9,
|
||||
0x19, 0x11, 0x97, 0x85, 0x07, 0xa5, 0xe1, 0xc0, 0xb2, 0xb3, 0x0c, 0x74, 0x2f, 0x33, 0xb0, 0xc0,
|
||||
0xe9, 0xe2, 0x48, 0xe0, 0x42, 0xb0, 0x23, 0xe5, 0x58, 0x93, 0x60, 0x17, 0x30, 0xa8, 0x13, 0x2f,
|
||||
0x3c, 0x48, 0x18, 0x3b, 0xb1, 0x1b, 0x16, 0xc1, 0x57, 0xd6, 0xed, 0xd5, 0x75, 0x78, 0x01, 0xc1,
|
||||
0x23, 0x2f, 0x8e, 0xf3, 0x91, 0xcd, 0x72, 0x5e, 0x12, 0x53, 0x8d, 0xfa, 0xc0, 0x7d, 0xc5, 0x93,
|
||||
0x3f, 0xcf, 0xff, 0xf1, 0xf5, 0xc3, 0x23, 0xeb, 0x2e, 0x4b, 0x92, 0x9a, 0xe5, 0xb8, 0x2f, 0x6c,
|
||||
0xc3, 0x47, 0x07, 0xec, 0x83, 0x0d, 0xff, 0x9d, 0xa9, 0x4d, 0x09, 0x9d, 0x75, 0xb4, 0x24, 0x16,
|
||||
0xaf, 0x00, 0xe7, 0xc6, 0x1a, 0x8f, 0xaf, 0x64, 0x47, 0xa9, 0x50, 0xbf, 0x08, 0xfb, 0x2c, 0xf8,
|
||||
0x77, 0xff, 0x14, 0x6d, 0x58, 0xe0, 0x74, 0xb3, 0x02, 0x50, 0xa6, 0x0c, 0xaa, 0xb1, 0x0b, 0x2b,
|
||||
0x1d, 0x15, 0xa0, 0x4d, 0xfc, 0x88, 0xb7, 0x0f, 0x57, 0xf4, 0x92, 0xcc, 0x50, 0x3e, 0x35, 0x09,
|
||||
0x0a, 0x18, 0xab, 0xcc, 0xf8, 0x72, 0xfd, 0xf7, 0x9f, 0x1b, 0xdd, 0x5d, 0x2b, 0xcb, 0xcd, 0xbd,
|
||||
0xb7, 0x1d, 0x96, 0xdd, 0xb0, 0xd3, 0xdb, 0x64, 0xbe, 0x33, 0xa8, 0x92, 0x01, 0x0f, 0x2c, 0xe5,
|
||||
0x85, 0xd2, 0x79, 0x9d, 0x23, 0xfe, 0xf8, 0xda, 0x1d, 0x34, 0xd6, 0x95, 0x7f, 0x93, 0x4d, 0x7e,
|
||||
0xec, 0x4f, 0x03, 0xfe, 0xc1, 0x9d, 0xc0, 0x54, 0xe0, 0xca, 0xea, 0x95, 0x4d, 0x34, 0x82, 0x8c,
|
||||
0x94, 0xd7, 0x87, 0xd2, 0x24, 0x5a, 0x1f, 0x00, 0x9e, 0xd8, 0x85, 0xe3, 0xf3, 0xe0, 0x1c, 0xfb,
|
||||
0x9b, 0xf0, 0x63, 0xb8, 0x64, 0x45, 0x70, 0x32, 0x3d, 0x69, 0x9a, 0xf6, 0x72, 0x59, 0x1a, 0xb0,
|
||||
0x3a, 0xb5, 0xfb, 0x60, 0x38, 0x05, 0x0e, 0x52, 0x17, 0x3f, 0xfc, 0x09, 0x14, 0xee, 0x18, 0x04,
|
||||
0xe3, 0x76, 0x13, 0xad, 0x09, 0x5c, 0x2c, 0x2c, 0x5c, 0xed, 0x5d, 0xd6, 0xae, 0xe0, 0xfb, 0x2d,
|
||||
0x18, 0x47, 0x11, 0xb2, 0x15, 0x74, 0x67, 0x94, 0x05, 0x83, 0x9f, 0xe3, 0xd5, 0x53, 0x55, 0x9d,
|
||||
0x72, 0xbe, 0xf0, 0x2f, 0x69, 0x48, 0x6f, 0x63, 0xf9, 0x5e, 0xf2, 0xc0, 0xb0, 0xee, 0x6f, 0x66,
|
||||
0x51, 0x53, 0xbb, 0x4d, 0x28, 0xb6, 0x11, 0x36, 0x16, 0xc8, 0xea, 0xfd, 0x5e, 0xba, 0xda, 0x1e,
|
||||
0x76, 0x99, 0xd0, 0x65, 0x54, 0xea, 0xc0, 0x72, 0x6e, 0x77, 0xe7, 0xee, 0xdb, 0xd7, 0xfb, 0x9b,
|
||||
0x4d, 0xda, 0x37, 0x30, 0x6e, 0xf8, 0xc5, 0xef, 0x60, 0x13, 0x0e, 0x18, 0x58, 0x9c, 0x79, 0xda,
|
||||
0xd0, 0xc2, 0xa3, 0x2c, 0x66, 0xb2, 0x8b, 0xa3, 0x73, 0x3b, 0x35, 0x5a, 0xb1, 0x39, 0x09, 0x26,
|
||||
0x0d, 0xc0, 0x24, 0x89, 0xaf, 0x00, 0x53, 0xc4, 0xaa, 0x5c, 0x5e, 0xdd, 0x03, 0xb4, 0xf5, 0xfa,
|
||||
0x91, 0x66, 0xac, 0x1c, 0xad, 0x46, 0x38, 0x0e, 0x80, 0xa8, 0xba, 0x74, 0xf5, 0xf5, 0x60, 0xbf,
|
||||
0xfe, 0x7f, 0x0d, 0xb7, 0xad, 0x38, 0x3d, 0xb4, 0x23, 0xa3, 0xbc, 0x63, 0xc2, 0x08, 0xde, 0x9a,
|
||||
0x00, 0x88, 0xbf, 0x83, 0xe6, 0xec, 0xfc, 0x57, 0xf0, 0xff, 0xd5, 0xb9, 0x07, 0x3d, 0x42, 0x4d,
|
||||
0x82, 0xcb, 0xf9, 0x3d, 0xc8, 0x70, 0xea, 0xb5, 0x50, 0xb3, 0x11, 0x7c, 0x82, 0x3f, 0xfe, 0x57,
|
||||
0xf0, 0x0e, 0xf3, 0x8a, 0xbd, 0x9f, 0x93, 0xb4, 0x96, 0xe5, 0xf1, 0x97, 0x96, 0x0c, 0xd1, 0x79,
|
||||
0xdf, 0xf9, 0x6f, 0xc0, 0xd5, 0x54, 0x81, 0xbb, 0x97, 0x5f, 0xfb, 0xb6, 0x2e, 0x15, 0xb1, 0x7c,
|
||||
0x5b, 0x8b, 0x4b, 0xa3, 0x9a, 0x30, 0xf5, 0x82, 0x1a, 0x7d, 0x1c, 0x16, 0x6c, 0x08, 0xf2, 0x5c,
|
||||
0x17, 0x52, 0xbe, 0xff, 0x52, 0x3e, 0xf7, 0xbb, 0x25, 0x80, 0x5c, 0x46, 0x89, 0xe5, 0xc7, 0x62,
|
||||
0x74, 0xea, 0xdc, 0xa0, 0xda, 0xa0, 0x3f, 0x08, 0xdf, 0xcf, 0xaf, 0x9b, 0xdf, 0x78, 0x91, 0x6b,
|
||||
0x7c, 0x00, 0x77, 0x74, 0xb0, 0x3e, 0x0c, 0xd4, 0x6c, 0xaf, 0xdd, 0xed, 0xc7, 0x71, 0xa7, 0x16,
|
||||
0x3f, 0x33, 0x8f, 0x5a, 0xc7, 0xbd, 0x47, 0x76, 0x07, 0x24, 0x11, 0xd7, 0xa6, 0x9a, 0x56, 0x69,
|
||||
0x3b, 0x12, 0xb0, 0xe0, 0xd0, 0x12, 0x23, 0xc4, 0x8c, 0x32, 0xc4, 0x3a, 0x00, 0xba, 0x6e, 0xc3,
|
||||
0x89, 0x7c, 0x96, 0x48, 0x0a, 0x08, 0x24, 0x30, 0x8d, 0x2c, 0x0b, 0x56, 0xe6, 0xd5, 0x55, 0x39,
|
||||
0x5e, 0xf5, 0xed, 0x3c, 0xc0, 0x5b, 0x59, 0x0b, 0xe9, 0xbe, 0x2e, 0xb9, 0xb5, 0x7e, 0xff, 0xbd,
|
||||
0x6f, 0x80, 0x1e, 0xc4, 0xe4, 0x1b, 0xaf, 0xfc, 0x55, 0x1f, 0x19, 0x7d, 0x4c, 0x4f, 0xcc, 0xbc,
|
||||
0xee, 0xb2, 0x67, 0x02, 0xe9, 0x2f, 0x1b, 0xe4, 0xfa, 0x1b, 0xc5, 0xfc, 0x9a, 0x2e, 0x41, 0x82,
|
||||
0xc6, 0xfe, 0x01, 0x8f, 0x4b, 0x1b, 0x79, 0x1b, 0x2b, 0x85, 0xe9, 0x5f, 0x92, 0xe1, 0xba, 0x97,
|
||||
0xae, 0x9b, 0x68, 0x7c, 0xd2, 0x4c, 0x8d, 0xdc, 0xb2, 0xc0, 0x46, 0xd2, 0xe1, 0x5e, 0x6b, 0xf3,
|
||||
0x79, 0x7a, 0xf3, 0xcb, 0x3c, 0x5d, 0x23, 0xb0, 0x93, 0x47, 0x39, 0xfd, 0x4e, 0x1a, 0xe5, 0x95,
|
||||
0xc1, 0x47, 0x5f, 0xf9, 0xed, 0x0b, 0xdc, 0xcc, 0x75, 0x2a, 0x6a, 0x06, 0x00, 0x91, 0x19, 0x8c,
|
||||
0x56, 0xfd, 0x00, 0x93, 0x18, 0xfc, 0xd2, 0x30, 0xbd, 0xa2, 0xa2, 0xa6, 0xd8, 0x96, 0x78, 0xf1,
|
||||
0x8e, 0x7c, 0x46, 0xc8, 0x79, 0xf8, 0xda, 0xcb, 0x3b, 0x02, 0x6d, 0x5e, 0x01, 0x32, 0xf4, 0x86,
|
||||
0x7f, 0xe6, 0x7c, 0xfd, 0xcf, 0x08, 0x0f, 0x09, 0x6f, 0x03, 0xfa, 0x11, 0x96, 0x7b, 0x73, 0x75,
|
||||
0x90, 0xdc, 0xfe, 0x5e, 0x62, 0x61, 0x67, 0x1b, 0xc8, 0x8c, 0xb9, 0x32, 0x98, 0x4d, 0x9a, 0xd4,
|
||||
0xa0, 0x39, 0x5b, 0xd6, 0x0b, 0x56, 0x56, 0xcf, 0x55, 0x43, 0x2f, 0x6f, 0xb8, 0xf6, 0x83, 0xff,
|
||||
0xe7, 0x62, 0x7b, 0x73, 0xf9, 0x4e, 0xea, 0xec, 0x3e, 0x1e, 0xa6, 0xbf, 0xbf, 0x87, 0xdb, 0x1a,
|
||||
0xdb, 0xca, 0xb4, 0xc7, 0xa5, 0x30, 0x2b, 0xcd, 0x79, 0xef, 0x9b, 0x58, 0xdc, 0x30, 0xf8, 0x70,
|
||||
0x8e, 0x2f, 0x42, 0xde, 0x83, 0x44, 0x25, 0xf7, 0xdd, 0x55, 0x3e, 0x12, 0x55, 0x4e, 0x15, 0x5f,
|
||||
0x37, 0x91, 0xe9, 0xe3, 0x1f, 0x20, 0xda, 0x51, 0xcb, 0xff, 0xfd, 0x6d, 0x72, 0xfc, 0x3f, 0x5b,
|
||||
0x0f, 0xc7, 0x70, 0xcd, 0x84, 0xd9, 0x8e, 0x36, 0x92, 0x1d, 0x4a, 0x61, 0x70, 0x9b, 0x9b, 0x68,
|
||||
0x9b, 0x27, 0xc6, 0x99, 0x10, 0xa3, 0xce, 0x53, 0x21, 0xf4, 0x31, 0x3c, 0x87, 0x84, 0x69, 0x81,
|
||||
0x9d, 0xa5, 0xef, 0x0f, 0xf1, 0xca, 0xae, 0xf0, 0x63, 0x1c, 0x84, 0x5b, 0x8f, 0x77, 0xe5, 0x6b,
|
||||
0x11, 0xec, 0x26, 0x59, 0x9f, 0x16, 0x89, 0xe1, 0xc2, 0xad, 0x56, 0xb8, 0x2e, 0x31, 0x68, 0x5d,
|
||||
0x2a, 0x83, 0xf6, 0xef, 0xfe, 0x61, 0x76, 0x9d, 0x60, 0x2a, 0x87, 0xc5, 0x85, 0xff, 0x22, 0xe4,
|
||||
0x4b, 0x08, 0x48, 0x13, 0x8a, 0x00, 0x3b, 0x48, 0xc9, 0x21, 0x06, 0xc1, 0xbb, 0xd9, 0xd1, 0x3d,
|
||||
0x52, 0x49, 0x6a, 0x44, 0x93, 0x09, 0xc8, 0x8b, 0x8a, 0x5e, 0x7e, 0x8d, 0x0b, 0x26, 0xc3, 0x59,
|
||||
0xbb, 0xad, 0x92, 0xaa, 0x46, 0x0b, 0xbe, 0xd6, 0xaa, 0xa0, 0x36, 0x5f, 0x34, 0x6a, 0x88, 0x84,
|
||||
0x0a, 0xfc, 0xa8, 0xb8, 0xbd, 0xb4, 0xa4, 0xf4, 0xc6, 0xe1, 0x88, 0x55, 0x5d, 0x4e, 0xc9, 0xdc,
|
||||
0x7d, 0xa2, 0x71, 0x0d, 0x18, 0x1e, 0x16, 0x1d, 0x17, 0x11, 0xb3, 0x91, 0x92, 0xf0, 0xc6, 0x1b,
|
||||
0x3a, 0x54, 0x80, 0x8f, 0x11, 0x71, 0x9b, 0x02, 0x16, 0xf4, 0x8f, 0xf0, 0x37, 0xf2, 0xea, 0xa8,
|
||||
0x95, 0x61, 0x8e, 0x8f, 0x22, 0x22, 0xc0, 0xef, 0x51, 0x0b, 0x18, 0x8d, 0xd8, 0xe8, 0x0b, 0x76,
|
||||
0x3e, 0xa5, 0x28, 0xc3, 0x6f, 0xde, 0xf1, 0xf4, 0x55, 0x7d, 0x48, 0xfd, 0xe3, 0xa5, 0x64, 0x45,
|
||||
0x70, 0x3c, 0xbe, 0x0f, 0x06, 0x22, 0xc8, 0x95, 0x89, 0x0a, 0x56, 0xd6, 0x8a, 0x36, 0x42, 0xbe,
|
||||
0xe6, 0x20, 0x00, 0x5c, 0xaa, 0xc6, 0x2e, 0xea, 0x19, 0x11, 0xfc, 0x07, 0x38, 0x08, 0x30, 0x7f,
|
||||
0xb1, 0xe7, 0xfd, 0x71, 0x1c, 0x37, 0xc1, 0xd1, 0x4c, 0x3f, 0x16, 0x4c, 0x4d, 0x06, 0x69, 0xca,
|
||||
0x3b, 0x8b, 0x79, 0xfd, 0x05, 0x0c, 0x8c, 0x60, 0xee, 0xaa, 0x91, 0x16, 0xf1, 0xab, 0x8a, 0x55,
|
||||
0xf1, 0xb2, 0x85, 0xfc, 0xa7, 0xde, 0x6f, 0x32, 0xd3, 0x1f, 0xfd, 0xc2, 0x0d, 0xc7, 0x74, 0x4d,
|
||||
0xcb, 0xae, 0x77, 0x96, 0xd3, 0xf3, 0x0a, 0xa0, 0x97, 0xd1, 0xf5, 0x54, 0xb8, 0xba, 0x45, 0x63,
|
||||
0x1f, 0xe4, 0xef, 0x80, 0x63, 0xd4, 0xef, 0xef, 0x74, 0x56, 0x93, 0xf3, 0xfe, 0x60, 0x97, 0xcb,
|
||||
0xf5, 0x55, 0x89, 0x0b, 0x92, 0x4e, 0xb5, 0x22, 0xe3, 0x0e, 0xc4, 0x5e, 0xc9, 0x0b, 0xc8, 0x52,
|
||||
0xc1, 0x43, 0x0a, 0x6e, 0x6e, 0xee, 0xe9, 0xd2, 0x58, 0xe1, 0x08, 0xd5, 0x93, 0xdd, 0x96, 0x57,
|
||||
0x8b, 0x06, 0x2f, 0xb4, 0x3b, 0x0a, 0x00, 0x5f, 0x9d, 0x55, 0x14, 0x57, 0xfe, 0xee, 0xbe, 0x19,
|
||||
0x61, 0xa5, 0x63, 0x81, 0x6a, 0xf0, 0x1e, 0xf8, 0xdc, 0xa0, 0xf4, 0x98, 0xaa, 0x0b, 0x40, 0xfa,
|
||||
0xea, 0xb1, 0xb7, 0xce, 0xb7, 0x80, 0x3b, 0x56, 0x09, 0xb6, 0xa5, 0x92, 0x84, 0x0b, 0x01, 0xca,
|
||||
0x51, 0x86, 0xad, 0xd5, 0x1a, 0xc5, 0x9f, 0xba, 0x2b, 0xc5, 0x30, 0x66, 0xd2, 0xbc, 0xa5, 0xb1,
|
||||
0xcd, 0x3a, 0x73, 0x29, 0x49, 0x47, 0x58, 0xe3, 0xb7, 0x55, 0xeb, 0x15, 0x7f, 0x0d, 0xf8, 0x12,
|
||||
0x55, 0x02, 0x92, 0x3a, 0xe7, 0x60, 0xdf, 0xfa, 0x3a, 0x3a, 0x01, 0x35, 0xf0, 0x06, 0xe5, 0x85,
|
||||
0xdd, 0x21, 0xef, 0xe7, 0x84, 0xda, 0x08, 0x22, 0xa2, 0xab, 0x83, 0x92, 0x25, 0x15, 0x8b, 0x00,
|
||||
0x4f, 0x6a, 0xc9, 0x01, 0xa4, 0xc1, 0x62, 0xf6, 0x07, 0x24, 0x19, 0xbb, 0x5d, 0xe0, 0x36, 0x69,
|
||||
0xf5, 0x6a, 0xef, 0x22, 0x73, 0xc7, 0xb6, 0xc2, 0x03, 0xc9, 0x53, 0x9f, 0x4d, 0xd5, 0x1e, 0x03,
|
||||
0x00, 0xd9, 0xa4, 0x44, 0x44, 0x45, 0x15, 0x2e, 0xdb, 0x91, 0x09, 0xf0, 0xd8, 0x30, 0x0b, 0x08,
|
||||
0x29, 0x55, 0x1e, 0xd2, 0x58, 0xa1, 0xed, 0xda, 0xe0, 0x64, 0xec, 0x83, 0x2b, 0x5b, 0x30, 0x7a,
|
||||
0x90, 0xb0, 0x5f, 0x1a, 0x55, 0x38, 0xa6, 0x5d, 0x6f, 0xaa, 0x4e, 0x03, 0x6e, 0x00, 0x0b, 0xc6,
|
||||
0x35, 0x5d, 0x37, 0x23, 0xea, 0xa9, 0x81, 0xa2, 0x52, 0x0e, 0x9c, 0xd5, 0x7e, 0xaa, 0x98, 0x05,
|
||||
0x5c, 0x0c, 0xf3, 0x41, 0x07, 0x3e, 0x81, 0x6b, 0xf1, 0x7f, 0x50, 0xef, 0x9b, 0x8f, 0xc2, 0xf0,
|
||||
0x97, 0xaf, 0xbf, 0x00, 0x52, 0x02, 0x57, 0x59, 0xfc, 0x75, 0x0c, 0x90, 0x1a, 0x47, 0x17, 0x0e,
|
||||
0xf0, 0x0d, 0x3f, 0x6e, 0x97, 0x80, 0x99, 0x60, 0x37, 0x6a, 0xcc, 0xe9, 0xd9, 0x11, 0x09, 0xc4,
|
||||
0x09, 0x60, 0x00, 0x25, 0x06, 0x2f, 0xb6, 0x8e, 0xaf, 0x68, 0xa9, 0x29, 0xab, 0xa9, 0xaa, 0xa7,
|
||||
0x45, 0xcb, 0x0c, 0xe4, 0x85, 0xbc, 0x27, 0xd5, 0xa6, 0x00, 0x72, 0xa5, 0xc0, 0x72, 0xf1, 0xef,
|
||||
0x71, 0x42, 0x0c, 0x1b, 0x02, 0xdb, 0x44, 0x40, 0x0b, 0xde, 0x15, 0x7c, 0x43, 0xdf, 0xe2, 0x52,
|
||||
0x0b, 0x2c, 0x9f, 0xf5, 0x24, 0xab, 0xc4, 0x69, 0xaa, 0xa2, 0xe0, 0x39, 0xe0, 0x2e, 0x11, 0x2e,
|
||||
0x11, 0x39, 0x0f, 0x38, 0x5e, 0x6f, 0x2a, 0x70, 0xa3, 0x5e, 0x9c, 0xdc, 0xe8, 0xd5, 0x63, 0x6b,
|
||||
0x70, 0x05, 0xf0, 0x27, 0xbd, 0x70, 0x0d, 0x4b, 0xf5, 0x54, 0xe0, 0x79, 0x11, 0x4a, 0x16, 0xb9,
|
||||
0x03, 0x2f, 0x58, 0xf5, 0x39, 0xbc, 0xa9, 0xc9, 0xff, 0xc5, 0x94, 0x6a, 0xa8, 0x51, 0x05, 0x0b,
|
||||
0x82, 0xfe, 0xa0, 0xd7, 0xd5, 0xc4, 0xae, 0xb7, 0x45, 0xfc, 0x4a, 0x2f, 0x07, 0x72, 0x87, 0x70,
|
||||
0x1c, 0x88, 0x97, 0x8d, 0x59, 0x30, 0x3d, 0xfa, 0x80, 0xd3, 0xd8, 0x09, 0xaa, 0x8f, 0xbc, 0x03,
|
||||
0xfc, 0x0a, 0xaf, 0x00, 0x70, 0x16, 0xa4, 0xec, 0xaa, 0xa3, 0xe3, 0x76, 0xd2, 0x85, 0x11, 0xef,
|
||||
0x91, 0x91, 0x1c, 0xc0, 0x67, 0xbc, 0x50, 0xf8, 0x67, 0xbc, 0x32, 0x78, 0xf5, 0xde, 0xed, 0x27,
|
||||
0x67, 0x01, 0x12, 0xf0, 0x46, 0x7d, 0x49, 0xe3, 0x75, 0xfc, 0x3a, 0x54, 0xe2, 0xf0, 0xe6, 0x71,
|
||||
0xbf, 0x55, 0x14, 0xaa, 0x28, 0xe0, 0xec, 0x65, 0x5e, 0x7f, 0x16, 0x44, 0x97, 0x02, 0x92, 0x13,
|
||||
0x34, 0x9f, 0x4b, 0xc4, 0xd3, 0x78, 0xe5, 0x6b, 0x99, 0x29, 0xa3, 0xa4, 0xad, 0xd1, 0xe5, 0x39,
|
||||
0xc9, 0x07, 0x00, 0x24, 0x65, 0x03, 0x6b, 0x27, 0xb7, 0xb1, 0x48, 0xbf, 0x56, 0x0e, 0xe6, 0xa3,
|
||||
0xb9, 0x46, 0x42, 0x18, 0xe8, 0xfa, 0x07, 0x80, 0x87, 0xee, 0xc8, 0x88, 0xc0, 0x21, 0x89, 0x8f,
|
||||
0x58, 0xe9, 0x08, 0xb4, 0x6b, 0xbc, 0x79, 0xac, 0x56, 0x5f, 0xa6, 0x4b, 0x89, 0x6f, 0x88, 0xe2,
|
||||
0xc0, 0x69, 0x93, 0x51, 0x1f, 0x63, 0xda, 0xaa, 0xe7, 0x8b, 0xfe, 0xf4, 0xf6, 0x92, 0x34, 0xb5,
|
||||
0x55, 0x0a, 0x41, 0x5d, 0x8c, 0x48, 0x2d, 0x22, 0x64, 0x44, 0xf0, 0x22, 0xc0, 0x77, 0x44, 0x67,
|
||||
0xb4, 0xc4, 0x2b, 0x97, 0x85, 0xe0, 0x4b, 0xe1, 0x77, 0x0e, 0x83, 0x04, 0x74, 0xe8, 0x6d, 0x4c,
|
||||
0xf0, 0xcb, 0x84, 0xe9, 0x60, 0x4b, 0x21, 0x6a, 0x73, 0xa6, 0x49, 0x1d, 0x2c, 0x22, 0x72, 0xae,
|
||||
0xd7, 0xb8, 0xc5, 0xf8, 0x22, 0x00, 0x76, 0xf2, 0x85, 0x7c, 0x8e, 0x30, 0x92, 0x1f, 0x02, 0xe1,
|
||||
0x12, 0x83, 0xc5, 0x80, 0xc1, 0xc4, 0x0d, 0x53, 0x5b, 0xd8, 0xe8, 0x95, 0x4d, 0x24, 0x81, 0xc0,
|
||||
0x2a, 0x34, 0x24, 0x6a, 0x47, 0x7f, 0xf3, 0x8c, 0x15, 0x6d, 0xda, 0xf8, 0x1d, 0xe1, 0x6d, 0x1c,
|
||||
0x00, 0xb8, 0x4c, 0x74, 0xfa, 0xd1, 0xaa, 0x35, 0xce, 0xba, 0x51, 0xa8, 0xc3, 0x87, 0x22, 0x10,
|
||||
0x21, 0xf2, 0xbc, 0xbc, 0xa6, 0x8d, 0x6f, 0x6d, 0x74, 0x66, 0xb8, 0x64, 0xe6, 0x7f, 0xe3, 0x50,
|
||||
0xef, 0x59, 0x02, 0x31, 0xeb, 0x0c, 0x69, 0x2a, 0x5a, 0xe3, 0x73, 0xe4, 0x8d, 0xfe, 0xcd, 0xab,
|
||||
0x00, 0x4b, 0x46, 0x06, 0x0d, 0xbf, 0x57, 0xb2, 0xe2, 0x4d, 0x69, 0xb0, 0xda, 0x69, 0x22, 0x17,
|
||||
0xde, 0x65, 0xdf, 0xe4, 0x3b, 0x98, 0x18, 0x6b, 0xda, 0xd3, 0x25, 0xbd, 0x36, 0x1c, 0xa5, 0x56,
|
||||
0x8e, 0x2c, 0x60, 0x17, 0x38, 0x70, 0x3b, 0xf6, 0x64, 0x44, 0x5e, 0x34, 0xd8, 0xe3, 0x6d, 0x74,
|
||||
0xd8, 0xcd, 0xe1, 0x16, 0x31, 0xc2, 0x5c, 0x2d, 0xb6, 0x34, 0xb7, 0x95, 0x6e, 0x8e, 0x2e, 0x31,
|
||||
0x02, 0xac, 0x20, 0x9e, 0x05, 0x45, 0x86, 0x01, 0x10, 0x54, 0xe3, 0x91, 0xad, 0xf0, 0x9e, 0x3d,
|
||||
0x96, 0xda, 0x7d, 0xe1, 0x25, 0x06, 0x45, 0x00, 0x48, 0xe4, 0xcd, 0xe0, 0xec, 0x06, 0x4e, 0x2d,
|
||||
0x92, 0x74, 0xa1, 0x26, 0x5e, 0xe9, 0x26, 0x8a, 0x30, 0x21, 0x34, 0x47, 0x44, 0x67, 0xea, 0xd6,
|
||||
0x59, 0xa4, 0x39, 0xb5, 0x87, 0x22, 0x3f, 0x63, 0x52, 0xe3, 0xda, 0xbc, 0x80, 0x01, 0x45, 0x17,
|
||||
0xdd, 0x32, 0xcd, 0x89, 0x8c, 0x22, 0xc2, 0xc8, 0x16, 0xa8, 0x44, 0x61, 0x18, 0x56, 0x15, 0x99,
|
||||
0x66, 0x46, 0x64, 0x61, 0x18, 0x56, 0x22, 0xd5, 0xce, 0x8c, 0xe7, 0x0a, 0xcc, 0x8e, 0xba, 0xf2,
|
||||
0x2d, 0x91, 0xd7, 0xd6, 0x37, 0xc7, 0xbb, 0xe1, 0xc9, 0x3d, 0xf1, 0xbf, 0x93, 0x8f, 0x28, 0xdb,
|
||||
0xf4, 0x28, 0x32, 0x0e, 0xa2, 0xb3, 0x35, 0x5f, 0x02, 0x4e, 0xda, 0xb0, 0xf7, 0xe8, 0xcb, 0x50,
|
||||
0x9a, 0xf6, 0xe7, 0x1a, 0xe3, 0x80, 0x4f, 0x29, 0xb5, 0x04, 0xfd, 0x8a, 0x95, 0x8c, 0x09, 0xa4,
|
||||
0x0e, 0x58, 0x13, 0x47, 0xa8, 0x13, 0x34, 0xec, 0xf6, 0x7f, 0x2b, 0x30, 0xf2, 0xe2, 0xca, 0xcd,
|
||||
0x44, 0xff, 0x75, 0xeb, 0xfd, 0xa7, 0x8f, 0x6e, 0x6f, 0xf4, 0x6e, 0x7c, 0x0f, 0x75, 0x5b, 0x9f,
|
||||
0x97, 0x5d, 0xc6, 0x38, 0xaa, 0xe3, 0x2d, 0x5a, 0x22, 0x8f, 0xcc, 0xb0, 0x82, 0xcc, 0xa6, 0xbd,
|
||||
0x00, 0xe6, 0xcf, 0x2a, 0x50, 0xd0, 0x0e, 0xca, 0x4d, 0xb8, 0x27, 0xec, 0x86, 0x8c, 0xe4, 0xaa,
|
||||
0xc1, 0xec, 0xd9, 0x7e, 0x87, 0x4d, 0x51, 0xa3, 0x1d, 0x94, 0x88, 0xf0, 0x30, 0xac, 0x20, 0xfb,
|
||||
0xbe, 0x76, 0xf2, 0xbb, 0x1f, 0xca, 0x0e, 0x83, 0x13, 0x78, 0x6c, 0xf0, 0x97, 0x4a, 0x62, 0x53,
|
||||
0xd0, 0x21, 0xa5, 0xc8, 0x5f, 0x3b, 0xe0, 0x1a, 0x17, 0xdf, 0x9b, 0x01, 0x68, 0x1b, 0x6a, 0xcf,
|
||||
0xa6, 0x41, 0xe3, 0x46, 0x70, 0x1c, 0xfb, 0x3c, 0xb0, 0x1c, 0x3b, 0xe5, 0x7c, 0xf4, 0x21, 0x77,
|
||||
0x62, 0x2c, 0x2a, 0x5d, 0xee, 0xd2, 0xec, 0x70, 0x88, 0x57, 0x11, 0xc8, 0x42, 0xf8, 0x67, 0x8e,
|
||||
0xc8, 0x8c, 0xd4, 0x1e, 0xce, 0x0d, 0xdb, 0x03, 0xf4, 0x73, 0x43, 0x05, 0xbf, 0xad, 0xa1, 0x4c,
|
||||
0x6e, 0xa4, 0x55, 0x00, 0x0b, 0x5d, 0x07, 0xbc, 0x19, 0x6f, 0x3d, 0x4f, 0x80, 0xe4, 0x53, 0x7f,
|
||||
0xdf, 0xd5, 0xc2, 0x0f, 0xc5, 0xde, 0xfa, 0x78, 0xf5, 0xd6, 0xfb, 0xda, 0xaa, 0xba, 0xae, 0xfe,
|
||||
0xf3, 0xce, 0x8a, 0xa4, 0x41, 0x0b, 0xe3, 0xc7, 0x01, 0x1b, 0x35, 0xdb, 0x83, 0xfc, 0x91, 0x4d,
|
||||
0xf2, 0xe7, 0x76, 0x0f, 0xc0, 0xaf, 0x68, 0xe1, 0x81, 0x18, 0xb3, 0xf0, 0x02, 0x8d, 0xcd, 0x36,
|
||||
0x01, 0x4a, 0x94, 0xe2, 0x7e, 0xaa, 0xc2, 0x91, 0x44, 0xa5, 0xd5, 0x50, 0x45, 0x87, 0xf5, 0xe4,
|
||||
0x3b, 0xc0, 0xd9, 0x81, 0x1b, 0x24, 0x29, 0x98, 0xd4, 0x9e, 0x7f, 0xe7, 0xea, 0xa9, 0x83, 0xab,
|
||||
0xf7, 0xb4, 0x88, 0x98, 0x87, 0x9c, 0xf6, 0xb7, 0x35, 0xf8, 0xd8, 0x35, 0x4b, 0xfb, 0xde, 0xd1,
|
||||
0x81, 0xc6, 0x6e, 0x0e, 0x9c, 0x76, 0x8e, 0x03, 0x95, 0x27, 0x74, 0x10, 0xc2, 0x9f, 0x82, 0x8f,
|
||||
0x4d, 0x75, 0x78, 0xf3, 0x91, 0xeb, 0x8e, 0x1d, 0x91, 0xfd, 0x80, 0x80, 0x39, 0xc9, 0xb1, 0x07,
|
||||
0xbe, 0x03, 0x63, 0x65, 0x58, 0x5f, 0x74, 0x2e, 0x4d, 0x35, 0xe6, 0xb4, 0x55, 0x5c, 0x62, 0xe7,
|
||||
0x3e, 0x71, 0x55, 0x5a, 0x03, 0xe7, 0x6d, 0xf3, 0x6b, 0xd9, 0x0e, 0x56, 0x88, 0xe6, 0x35, 0x50,
|
||||
0x09, 0x52, 0xdf, 0x41, 0xad, 0xbb, 0xad, 0x9f, 0xf4, 0xc1, 0x07, 0xfa, 0x84, 0x0f, 0x9e, 0x5e,
|
||||
0xa0, 0xe3, 0x3c, 0xa5, 0x6e, 0x02, 0x6f, 0x11, 0xc1, 0x35, 0xc8, 0xc1, 0xce, 0xe2, 0x5f, 0x3c,
|
||||
0x13, 0x58, 0xac, 0xa9, 0xc5, 0xf9, 0xc3, 0xb4, 0x8e, 0xcf, 0x71, 0xf4, 0x38, 0x0e, 0xeb, 0x1e,
|
||||
0xe8, 0x21, 0x39, 0xad, 0x9a, 0xe5, 0x36, 0x68, 0x9d, 0xe0, 0xac, 0x76, 0x1c, 0x3b, 0xa5, 0x8d,
|
||||
0xfe, 0xb8, 0x84, 0xf7, 0xf6, 0xd2, 0xc3, 0x89, 0x0c, 0xb2, 0x1c, 0xcb, 0x9a, 0x40, 0x83, 0x98,
|
||||
0x97, 0xe4, 0xfa, 0xdb, 0x77, 0x39, 0x17, 0x69, 0xc1, 0x9d, 0x4d, 0xaa, 0x54, 0x7f, 0xff, 0xd5,
|
||||
0xe9, 0x4a, 0x1c, 0x92, 0x84, 0x4d, 0x41, 0x0b, 0xb3, 0xc7, 0x19, 0x6f, 0xa5, 0x92, 0xe3, 0x46,
|
||||
0x15, 0x8a, 0x6c, 0xdd, 0x66, 0x08, 0xbc, 0x68, 0xa7, 0x80, 0xea, 0xf3, 0xec, 0x70, 0x9c, 0x8f,
|
||||
0x6f, 0x89, 0x5f, 0x05, 0x42, 0xd2, 0xfb, 0xfb, 0x0b, 0x3b, 0xf3, 0x3b, 0xb2, 0xdc, 0x8f, 0xb1,
|
||||
0x6e, 0x1f, 0xe8, 0x89, 0xef, 0xc2, 0xfe, 0x02, 0x85, 0x3e, 0x72, 0x4b, 0x21, 0x34, 0x01, 0xce,
|
||||
0x63, 0xc7, 0x04, 0x6d, 0x33, 0xbc, 0x7c, 0xa7, 0x55, 0x7a, 0x0f, 0x0f, 0x45, 0x04, 0xf3, 0xa5,
|
||||
0xe5, 0xc0, 0xfb, 0x2e, 0xb1, 0xd9, 0x73, 0x1f, 0x7f, 0x96, 0x40, 0xe3, 0xc0, 0x76, 0xf6, 0xaf,
|
||||
0x2b, 0x2b, 0x0a, 0x7b, 0x7f, 0xde, 0x05, 0xbd, 0xbf, 0x7e, 0x17, 0x23, 0x25, 0x2e, 0x62, 0x5b,
|
||||
0xf0, 0x27, 0x55, 0x4e, 0xc5, 0x7d, 0x25, 0xf2, 0x9a, 0x3a, 0xe7, 0x14, 0xe3, 0x80, 0xea, 0x31,
|
||||
0x0b, 0x80, 0x8b, 0xc0, 0x05, 0x5d, 0xdd, 0x1e, 0xe3, 0x93, 0x6b, 0xcb, 0x79, 0x7b, 0x3f, 0xb5,
|
||||
0x06, 0x52, 0x2b, 0xe6, 0x3a, 0xaa, 0xf1, 0xaf, 0x1d, 0x96, 0x6b, 0x0e, 0x52, 0x04, 0xd7, 0x7e,
|
||||
0x69, 0xf7, 0x2b, 0x58, 0x69, 0xb6, 0xf5, 0x50, 0xbc, 0x7a, 0x85, 0x79, 0x42, 0x9c, 0x95, 0x5e,
|
||||
0x60, 0x5c, 0x72, 0x1b, 0xe4, 0xaa, 0xb6, 0xf1, 0xe6, 0x77, 0xec, 0xb4, 0x5f, 0x6c, 0xd1, 0xe9,
|
||||
0x28, 0xb0, 0x25, 0x40, 0xc2, 0x5e, 0xbe, 0x73, 0x06, 0xcb, 0xd2, 0x3c, 0xd0, 0x71, 0x75, 0x20,
|
||||
0xb9, 0xaa, 0x90, 0x1d, 0xc8, 0x88, 0xe0, 0x4a, 0xf0, 0x48, 0x07, 0x8a, 0x1c, 0xcc, 0x41, 0x92,
|
||||
0x27, 0xd9, 0xa9, 0xd0, 0x2f, 0x78, 0x64, 0x6d, 0x79, 0x5f, 0x06, 0xbf, 0xa1, 0xf6, 0xe3, 0xc1,
|
||||
0xf7, 0xd6, 0xb8, 0x69, 0xac, 0x1e, 0xdf, 0x9f, 0x17, 0x00, 0xd1, 0xb9, 0x63, 0xaf, 0x46, 0x7f,
|
||||
0x2e, 0x44, 0x7e, 0x01, 0xf6, 0x96, 0x34, 0x75, 0xdd, 0x01, 0xf7, 0xc0, 0x2f, 0x80, 0x15, 0x14,
|
||||
0x1c, 0xe4, 0x32, 0x8e, 0x01, 0xce, 0x20, 0xc7, 0x5f, 0x22, 0x3e, 0x02, 0xd9, 0x6f, 0x01, 0x6c,
|
||||
0x18, 0x4f, 0x5a, 0xfe, 0x6d, 0x55, 0xa1, 0xce, 0xc3, 0x82, 0x48, 0x31, 0xe4, 0x44, 0xe0, 0x28,
|
||||
0x3c, 0x19, 0xc0, 0x39, 0x91, 0x83, 0xc0, 0xe5, 0x81, 0x77, 0xa8, 0x1f, 0xf6, 0xea, 0x2f, 0xb4,
|
||||
0xd1, 0xc6, 0x38, 0x9c, 0x1c, 0x07, 0x88, 0x83, 0x07, 0x4c, 0xc6, 0x9e, 0xe3, 0x5e, 0x08, 0xb1,
|
||||
0x98, 0xf8, 0x3e, 0xaa, 0xc9, 0x6e, 0xc3, 0x9e, 0x1c, 0x61, 0x99, 0x11, 0xdc, 0x01, 0x1c, 0x07,
|
||||
0xf6, 0x97, 0x18, 0xb5, 0x13, 0xa2, 0xe9, 0x58, 0xef, 0xfb, 0xe2, 0xe5, 0x97, 0xff, 0xea, 0xa9,
|
||||
0x34, 0xca, 0xcc, 0x2f, 0x7f, 0xb1, 0x1c, 0xe0, 0x05, 0x70, 0x64, 0x44, 0xf0, 0x0c, 0xe0, 0x19,
|
||||
0xc0, 0x63, 0x2a, 0x10, 0x9c, 0x44, 0xdc, 0x6b, 0xaa, 0x57, 0xbc, 0xef, 0x78, 0x00, 0x39, 0xc4,
|
||||
0xc7, 0x5e, 0x8a, 0x81, 0x8c, 0x88, 0xde, 0x00, 0x8c, 0x06, 0xbe, 0xc3, 0xc9, 0xae, 0x51, 0x60,
|
||||
0xd3, 0x8a, 0x78, 0xc0, 0x0e, 0x25, 0xff, 0xfd, 0xdb, 0x8f, 0x09, 0xd7, 0x52, 0xac, 0x4d, 0xd5,
|
||||
0x5c, 0xa9, 0xe3, 0xad, 0xc1, 0x80, 0x60, 0x39, 0xc3, 0x87, 0x70, 0xe1, 0x52, 0x38, 0x15, 0xc0,
|
||||
0x70, 0xe2, 0x1c, 0x38, 0x87, 0x0e, 0x05, 0x23, 0x03, 0x9c, 0x38, 0x76, 0x0e, 0x1c, 0x23, 0x87,
|
||||
0x9c, 0x05, 0x76, 0x03, 0x1c, 0x38, 0x87, 0x0e, 0x05, 0x23, 0x03, 0x9c, 0x38, 0x76, 0x0e, 0x1c,
|
||||
0x23, 0x87, 0x9c, 0x05, 0x76, 0x03, 0x1c, 0x38, 0x87, 0x0e, 0x05, 0x23, 0x03, 0x9c, 0x38, 0x76,
|
||||
0x0e, 0x1c, 0x23, 0x87, 0x9c, 0x05, 0x76, 0x03, 0x1c, 0x38, 0x87, 0x0e, 0x05, 0x23, 0x03, 0x9c,
|
||||
0x38, 0x76, 0x0e, 0x1c, 0x23, 0x87, 0x9c, 0x05, 0x76, 0x03, 0x1c, 0x38, 0x87, 0x0e, 0x05, 0x23,
|
||||
0x03, 0x9c, 0x38, 0x76, 0x0e, 0x1c, 0x23, 0x87, 0x9c, 0x05, 0x76, 0x03, 0x1c, 0x38, 0x87, 0x0e,
|
||||
0x05, 0x23, 0x03, 0x9c, 0x38, 0x76, 0x0e, 0x1c, 0x23, 0x87, 0x9c, 0x05, 0x76, 0x03, 0x1c, 0x38,
|
||||
0x87, 0x0e, 0x05, 0x23, 0x0f, 0xfe, 0xf6, 0xa7, 0xbf, 0x78, 0xfb, 0x2d, 0xfb, 0xc5, 0x00, 0x00,
|
||||
0x00, 0x00, 0x45, 0x49, 0x44, 0x4e, 0x42, 0xae, 0x82, 0x60,
|
||||
],
|
||||
disp: function()
|
||||
{
|
||||
// Do Nothing
|
||||
|
||||
throw "Does Nothing!";
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
LOGO.disp();
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
alert("Error: " + e + "\n");
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
77634b336741a98d2ef79484281245b12e9db939 big_script.js
|
|
@ -0,0 +1,29 @@
|
|||
//----------------------------------------------------------------------
|
||||
//
|
||||
// Silly / Pointless Javascript to test GZIP compression.
|
||||
//
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
var LOGO = {
|
||||
dat: [
|
||||
0x50, 0x89, 0x47, 0x4e, 0x0a, 0x0d, 0x0a, 0x1a, 0x00, 0x00, 0x0d, 0x00, 0x48, 0x49, 0x52, 0x44,
|
||||
0x00, 0x00, 0x45, 0x49, 0x44, 0x4e, 0x42, 0xae, 0x82, 0x60,
|
||||
],
|
||||
disp: function()
|
||||
{
|
||||
// Do Nothing
|
||||
|
||||
throw "Does Nothing!";
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
LOGO.disp();
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
alert("Error: " + e + "\n");
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
b8455ea37194b938cfc1773a73ecee2c994fa98e small_script.js
|
|
@ -46,6 +46,12 @@
|
|||
<artifactId>jetty-test-helper</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-servlet</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
|
@ -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,27 +332,37 @@ 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+"'");
|
||||
if ("wss".equalsIgnoreCase(scheme))
|
||||
throw new IOException("wss not supported");
|
||||
|
||||
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);
|
||||
_factory.getSelectorManager().register( channel, holder);
|
||||
_factory.getSelectorManager().register(channel, holder);
|
||||
|
||||
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.
|
||||
|
@ -422,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
|
||||
|
@ -468,6 +493,7 @@ public class WebSocketClient
|
|||
return _maskGen;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "[" + _uri + ","+_websocket+"]@"+hashCode();
|
||||
|
@ -489,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;
|
||||
|
@ -549,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;
|
||||
|
@ -5,7 +20,9 @@ import java.io.IOException;
|
|||
import java.net.ProtocolException;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import javax.net.ssl.SSLEngine;
|
||||
|
||||
import org.eclipse.jetty.http.HttpFields;
|
||||
import org.eclipse.jetty.http.HttpParser;
|
||||
|
@ -20,30 +37,31 @@ import org.eclipse.jetty.io.SimpleBuffers;
|
|||
import org.eclipse.jetty.io.nio.AsyncConnection;
|
||||
import org.eclipse.jetty.io.nio.SelectChannelEndPoint;
|
||||
import org.eclipse.jetty.io.nio.SelectorManager;
|
||||
import org.eclipse.jetty.io.nio.SslConnection;
|
||||
import org.eclipse.jetty.util.B64Code;
|
||||
import org.eclipse.jetty.util.QuotedStringTokenizer;
|
||||
import org.eclipse.jetty.util.component.AggregateLifeCycle;
|
||||
import org.eclipse.jetty.util.component.LifeCycle;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
||||
import org.eclipse.jetty.util.thread.ThreadPool;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* <p>WebSocketClientFactory contains the common components needed by multiple {@link WebSocketClient} instances
|
||||
* (for example, a {@link ThreadPool}, a {@link SelectorManager NIO selector}, etc).</p>
|
||||
* <p>WebSocketClients with different configurations should share the same factory to avoid to waste resources.</p>
|
||||
* <p>If a ThreadPool or MaskGen is passed in the constructor, then it is not added with {@link AggregateLifeCycle#addBean(Object)},
|
||||
* so it's lifecycle must be controlled externally.
|
||||
* so it's lifecycle must be controlled externally.
|
||||
*
|
||||
* @see WebSocketClient
|
||||
*/
|
||||
public class WebSocketClientFactory extends AggregateLifeCycle
|
||||
{
|
||||
private final static Logger __log = org.eclipse.jetty.util.log.Log.getLogger(WebSocketClientFactory.class.getName());
|
||||
private final static Random __random = new Random();
|
||||
private final static ByteArrayBuffer __ACCEPT = new ByteArrayBuffer.CaseInsensitive("Sec-WebSocket-Accept");
|
||||
|
||||
private SslContextFactory _sslContextFactory = new SslContextFactory();
|
||||
private final ThreadPool _threadPool;
|
||||
private final WebSocketClientSelector _selector;
|
||||
private MaskGen _maskGen;
|
||||
|
@ -55,54 +73,67 @@ public class WebSocketClientFactory extends AggregateLifeCycle
|
|||
*/
|
||||
public WebSocketClientFactory()
|
||||
{
|
||||
_threadPool=new QueuedThreadPool();
|
||||
addBean(_threadPool);
|
||||
_buffers=new WebSocketBuffers(8*1024);
|
||||
addBean(_buffers);
|
||||
_maskGen=new RandomMaskGen();
|
||||
addBean(_maskGen);
|
||||
_selector=new WebSocketClientSelector();
|
||||
addBean(_selector);
|
||||
this(new QueuedThreadPool());
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* <p>Creates a WebSocketClientFactory with the given ThreadPool and the default configuration.</p>
|
||||
*
|
||||
* @param threadPool the ThreadPool instance to use
|
||||
*/
|
||||
public WebSocketClientFactory(ThreadPool threadPool)
|
||||
{
|
||||
_threadPool=threadPool;
|
||||
addBean(threadPool);
|
||||
_buffers=new WebSocketBuffers(8*1024);
|
||||
addBean(_buffers);
|
||||
_maskGen=new RandomMaskGen();
|
||||
addBean(_maskGen);
|
||||
_selector=new WebSocketClientSelector();
|
||||
addBean(_selector);
|
||||
this(threadPool, new RandomMaskGen());
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* <p>Creates a WebSocketClientFactory with the specified configuration.</p>
|
||||
* <p>Creates a WebSocketClientFactory with the given ThreadPool and the given MaskGen.</p>
|
||||
*
|
||||
* @param threadPool the ThreadPool instance to use
|
||||
* @param maskGen the mask generator to use
|
||||
* @param maskGen the MaskGen instance to use
|
||||
*/
|
||||
public WebSocketClientFactory(ThreadPool threadPool, MaskGen maskGen)
|
||||
{
|
||||
this(threadPool, maskGen, 8192);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/**
|
||||
* <p>Creates a WebSocketClientFactory with the specified configuration.</p>
|
||||
*
|
||||
* @param threadPool the ThreadPool instance to use
|
||||
* @param maskGen the mask generator to use
|
||||
* @param bufferSize the read buffer size
|
||||
*/
|
||||
public WebSocketClientFactory(ThreadPool threadPool,MaskGen maskGen,int bufferSize)
|
||||
public WebSocketClientFactory(ThreadPool threadPool, MaskGen maskGen, int bufferSize)
|
||||
{
|
||||
_threadPool=threadPool;
|
||||
_threadPool = threadPool;
|
||||
addBean(threadPool);
|
||||
_buffers=new WebSocketBuffers(bufferSize);
|
||||
_buffers = new WebSocketBuffers(bufferSize);
|
||||
addBean(_buffers);
|
||||
_maskGen=maskGen;
|
||||
_selector=new WebSocketClientSelector();
|
||||
_maskGen = maskGen;
|
||||
addBean(_maskGen);
|
||||
_selector = new WebSocketClientSelector();
|
||||
addBean(_selector);
|
||||
addBean(_sslContextFactory);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return the SslContextFactory used to configure SSL parameters
|
||||
*/
|
||||
public SslContextFactory getSslContextFactory()
|
||||
{
|
||||
return _sslContextFactory;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Get the selectorManager. Used to configure the manager.
|
||||
*
|
||||
* @return The {@link SelectorManager} instance.
|
||||
*/
|
||||
public SelectorManager getSelectorManager()
|
||||
|
@ -111,8 +142,10 @@ public class WebSocketClientFactory extends AggregateLifeCycle
|
|||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get the ThreadPool.
|
||||
/**
|
||||
* Get the ThreadPool.
|
||||
* Used to set/query the thread pool configuration.
|
||||
*
|
||||
* @return The {@link ThreadPool}
|
||||
*/
|
||||
public ThreadPool getThreadPool()
|
||||
|
@ -123,7 +156,7 @@ public class WebSocketClientFactory extends AggregateLifeCycle
|
|||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return the shared mask generator, or null if no shared mask generator is used
|
||||
* @see {@link WebSocketClient#getMaskGen()}
|
||||
* @see WebSocketClient#getMaskGen()
|
||||
*/
|
||||
public MaskGen getMaskGen()
|
||||
{
|
||||
|
@ -133,15 +166,15 @@ public class WebSocketClientFactory extends AggregateLifeCycle
|
|||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @param maskGen the shared mask generator, or null if no shared mask generator is used
|
||||
* @see {@link WebSocketClient#setMaskGen(MaskGen)}
|
||||
* @see WebSocketClient#setMaskGen(MaskGen)
|
||||
*/
|
||||
public void setMaskGen(MaskGen maskGen)
|
||||
{
|
||||
if (isRunning())
|
||||
throw new IllegalStateException(getState());
|
||||
if (removeBean(_maskGen))
|
||||
addBean(maskGen);
|
||||
_maskGen=maskGen;
|
||||
removeBean(_maskGen);
|
||||
_maskGen = maskGen;
|
||||
addBean(maskGen);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -154,7 +187,7 @@ public class WebSocketClientFactory extends AggregateLifeCycle
|
|||
if (isRunning())
|
||||
throw new IllegalStateException(getState());
|
||||
removeBean(_buffers);
|
||||
_buffers=new WebSocketBuffers(bufferSize);
|
||||
_buffers = new WebSocketBuffers(bufferSize);
|
||||
addBean(_buffers);
|
||||
}
|
||||
|
||||
|
@ -179,24 +212,28 @@ public class WebSocketClientFactory extends AggregateLifeCycle
|
|||
return new WebSocketClient(this);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
protected void doStart() throws Exception
|
||||
protected SSLEngine newSslEngine(SocketChannel channel) throws IOException
|
||||
{
|
||||
super.doStart();
|
||||
if (getThreadPool() instanceof LifeCycle && !((LifeCycle)getThreadPool()).isStarted())
|
||||
((LifeCycle)getThreadPool()).start();
|
||||
SSLEngine sslEngine;
|
||||
if (channel != null)
|
||||
{
|
||||
String peerHost = channel.socket().getInetAddress().getHostAddress();
|
||||
int peerPort = channel.socket().getPort();
|
||||
sslEngine = _sslContextFactory.newSslEngine(peerHost, peerPort);
|
||||
}
|
||||
else
|
||||
{
|
||||
sslEngine = _sslContextFactory.newSslEngine();
|
||||
}
|
||||
sslEngine.setUseClientMode(true);
|
||||
sslEngine.beginHandshake();
|
||||
|
||||
return sslEngine;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
protected void doStop() throws Exception
|
||||
{
|
||||
super.doStop();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** WebSocket Client Selector Manager
|
||||
/**
|
||||
* WebSocket Client Selector Manager
|
||||
*/
|
||||
class WebSocketClientSelector extends SelectorManager
|
||||
{
|
||||
|
@ -209,16 +246,33 @@ public class WebSocketClientFactory extends AggregateLifeCycle
|
|||
@Override
|
||||
protected SelectChannelEndPoint newEndPoint(SocketChannel channel, SelectSet selectSet, final SelectionKey key) throws IOException
|
||||
{
|
||||
SelectChannelEndPoint endp= new SelectChannelEndPoint(channel,selectSet,key,channel.socket().getSoTimeout());
|
||||
endp.setConnection(selectSet.getManager().newConnection(channel,endp, key.attachment()));
|
||||
return endp;
|
||||
WebSocketClient.WebSocketFuture holder = (WebSocketClient.WebSocketFuture)key.attachment();
|
||||
int maxIdleTime = holder.getMaxIdleTime();
|
||||
if (maxIdleTime < 0)
|
||||
maxIdleTime = (int)getMaxIdleTime();
|
||||
SelectChannelEndPoint result = new SelectChannelEndPoint(channel, selectSet, key, maxIdleTime);
|
||||
AsyncEndPoint endPoint = result;
|
||||
|
||||
// Detect if it is SSL, and wrap the connection if so
|
||||
if ("wss".equals(holder.getURI().getScheme()))
|
||||
{
|
||||
SSLEngine sslEngine = newSslEngine(channel);
|
||||
SslConnection sslConnection = new SslConnection(sslEngine, endPoint);
|
||||
endPoint.setConnection(sslConnection);
|
||||
endPoint = sslConnection.getSslEndPoint();
|
||||
}
|
||||
|
||||
AsyncConnection connection = selectSet.getManager().newConnection(channel, endPoint, holder);
|
||||
endPoint.setConnection(connection);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsyncConnection newConnection(SocketChannel channel, AsyncEndPoint endpoint, Object attachment)
|
||||
{
|
||||
WebSocketClient.WebSocketFuture holder = (WebSocketClient.WebSocketFuture) attachment;
|
||||
return new HandshakeConnection(endpoint,holder);
|
||||
WebSocketClient.WebSocketFuture holder = (WebSocketClient.WebSocketFuture)attachment;
|
||||
return new HandshakeConnection(endpoint, holder);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -230,7 +284,7 @@ public class WebSocketClientFactory extends AggregateLifeCycle
|
|||
@Override
|
||||
protected void endPointUpgraded(ConnectedEndPoint endpoint, Connection oldConnection)
|
||||
{
|
||||
LOG.debug("upgrade {} -> {}",oldConnection,endpoint.getConnection());
|
||||
LOG.debug("upgrade {} -> {}", oldConnection, endpoint.getConnection());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -243,7 +297,7 @@ public class WebSocketClientFactory extends AggregateLifeCycle
|
|||
protected void connectionFailed(SocketChannel channel, Throwable ex, Object attachment)
|
||||
{
|
||||
if (!(attachment instanceof WebSocketClient.WebSocketFuture))
|
||||
super.connectionFailed(channel,ex,attachment);
|
||||
super.connectionFailed(channel, ex, attachment);
|
||||
else
|
||||
{
|
||||
__log.debug(ex);
|
||||
|
@ -254,9 +308,9 @@ public class WebSocketClientFactory extends AggregateLifeCycle
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Handshake Connection.
|
||||
/**
|
||||
* Handshake Connection.
|
||||
* Handles the connection until the handshake succeeds or fails.
|
||||
*/
|
||||
class HandshakeConnection extends AbstractConnection implements AsyncConnection
|
||||
|
@ -267,29 +321,27 @@ public class WebSocketClientFactory extends AggregateLifeCycle
|
|||
private final HttpParser _parser;
|
||||
private String _accept;
|
||||
private String _error;
|
||||
private boolean _handshaken;
|
||||
|
||||
public HandshakeConnection(AsyncEndPoint endpoint, WebSocketClient.WebSocketFuture future)
|
||||
{
|
||||
super(endpoint,System.currentTimeMillis());
|
||||
_endp=endpoint;
|
||||
_future=future;
|
||||
super(endpoint, System.currentTimeMillis());
|
||||
_endp = endpoint;
|
||||
_future = future;
|
||||
|
||||
byte[] bytes=new byte[16];
|
||||
__random.nextBytes(bytes);
|
||||
_key=new String(B64Code.encode(bytes));
|
||||
byte[] bytes = new byte[16];
|
||||
new Random().nextBytes(bytes);
|
||||
_key = new String(B64Code.encode(bytes));
|
||||
|
||||
|
||||
Buffers buffers = new SimpleBuffers(_buffers.getBuffer(),null);
|
||||
_parser=new HttpParser(buffers,_endp,
|
||||
|
||||
new HttpParser.EventHandler()
|
||||
Buffers buffers = new SimpleBuffers(_buffers.getBuffer(), null);
|
||||
_parser = new HttpParser(buffers, _endp, new HttpParser.EventHandler()
|
||||
{
|
||||
@Override
|
||||
public void startResponse(Buffer version, int status, Buffer reason) throws IOException
|
||||
{
|
||||
if (status!=101)
|
||||
if (status != 101)
|
||||
{
|
||||
_error="Bad response status "+status+" "+reason;
|
||||
_error = "Bad response status " + status + " " + reason;
|
||||
_endp.close();
|
||||
}
|
||||
}
|
||||
|
@ -298,65 +350,64 @@ public class WebSocketClientFactory extends AggregateLifeCycle
|
|||
public void parsedHeader(Buffer name, Buffer value) throws IOException
|
||||
{
|
||||
if (__ACCEPT.equals(name))
|
||||
_accept=value.toString();
|
||||
_accept = value.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startRequest(Buffer method, Buffer url, Buffer version) throws IOException
|
||||
{
|
||||
if (_error==null)
|
||||
_error="Bad response: "+method+" "+url+" "+version;
|
||||
if (_error == null)
|
||||
_error = "Bad response: " + method + " " + url + " " + version;
|
||||
_endp.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void content(Buffer ref) throws IOException
|
||||
{
|
||||
if (_error==null)
|
||||
_error="Bad response. "+ref.length()+"B of content?";
|
||||
if (_error == null)
|
||||
_error = "Bad response. " + ref.length() + "B of content?";
|
||||
_endp.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
String path=_future.getURI().getPath();
|
||||
if (path==null || path.length()==0)
|
||||
{
|
||||
path="/";
|
||||
}
|
||||
|
||||
if(_future.getURI().getRawQuery() != null)
|
||||
{
|
||||
private void handshake()
|
||||
{
|
||||
String path = _future.getURI().getPath();
|
||||
if (path == null || path.length() == 0)
|
||||
path = "/";
|
||||
|
||||
if (_future.getURI().getRawQuery() != null)
|
||||
path += "?" + _future.getURI().getRawQuery();
|
||||
}
|
||||
|
||||
String origin = future.getOrigin();
|
||||
String origin = _future.getOrigin();
|
||||
|
||||
StringBuilder request = new StringBuilder(512);
|
||||
request
|
||||
.append("GET ").append(path).append(" HTTP/1.1\r\n")
|
||||
.append("Host: ").append(future.getURI().getHost()).append(":").append(_future.getURI().getPort()).append("\r\n")
|
||||
.append("Upgrade: websocket\r\n")
|
||||
.append("Connection: Upgrade\r\n")
|
||||
.append("Sec-WebSocket-Key: ")
|
||||
.append(_key).append("\r\n");
|
||||
|
||||
if(origin!=null)
|
||||
request.append("GET ").append(path).append(" HTTP/1.1\r\n")
|
||||
.append("Host: ").append(_future.getURI().getHost()).append(":")
|
||||
.append(_future.getURI().getPort()).append("\r\n")
|
||||
.append("Upgrade: websocket\r\n")
|
||||
.append("Connection: Upgrade\r\n")
|
||||
.append("Sec-WebSocket-Key: ")
|
||||
.append(_key).append("\r\n");
|
||||
|
||||
if (origin != null)
|
||||
request.append("Origin: ").append(origin).append("\r\n");
|
||||
|
||||
request.append("Sec-WebSocket-Version: ").append(WebSocketConnectionD13.VERSION).append("\r\n");
|
||||
|
||||
if (future.getProtocol()!=null)
|
||||
request.append("Sec-WebSocket-Protocol: ").append(future.getProtocol()).append("\r\n");
|
||||
request.append("Sec-WebSocket-Version: ").append(WebSocketConnectionRFC6455.VERSION).append("\r\n");
|
||||
|
||||
if (future.getCookies()!=null && future.getCookies().size()>0)
|
||||
if (_future.getProtocol() != null)
|
||||
request.append("Sec-WebSocket-Protocol: ").append(_future.getProtocol()).append("\r\n");
|
||||
|
||||
Map<String, String> cookies = _future.getCookies();
|
||||
if (cookies != null && cookies.size() > 0)
|
||||
{
|
||||
for (String cookie : future.getCookies().keySet())
|
||||
request
|
||||
.append("Cookie: ")
|
||||
.append(QuotedStringTokenizer.quoteIfNeeded(cookie,HttpFields.__COOKIE_DELIM))
|
||||
.append("=")
|
||||
.append(QuotedStringTokenizer.quoteIfNeeded(future.getCookies().get(cookie),HttpFields.__COOKIE_DELIM))
|
||||
.append("\r\n");
|
||||
for (String cookie : cookies.keySet())
|
||||
request.append("Cookie: ")
|
||||
.append(QuotedStringTokenizer.quoteIfNeeded(cookie, HttpFields.__COOKIE_DELIM))
|
||||
.append("=")
|
||||
.append(QuotedStringTokenizer.quoteIfNeeded(cookies.get(cookie), HttpFields.__COOKIE_DELIM))
|
||||
.append("\r\n");
|
||||
}
|
||||
|
||||
request.append("\r\n");
|
||||
|
@ -365,14 +416,18 @@ public class WebSocketClientFactory extends AggregateLifeCycle
|
|||
|
||||
try
|
||||
{
|
||||
Buffer handshake = new ByteArrayBuffer(request.toString(),false);
|
||||
int len=handshake.length();
|
||||
if (len!=_endp.flush(handshake))
|
||||
Buffer handshake = new ByteArrayBuffer(request.toString(), false);
|
||||
int len = handshake.length();
|
||||
if (len != _endp.flush(handshake))
|
||||
throw new IOException("incomplete");
|
||||
}
|
||||
catch(IOException e)
|
||||
catch (IOException e)
|
||||
{
|
||||
future.handshakeFailed(e);
|
||||
_future.handshakeFailed(e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_handshaken = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -380,6 +435,9 @@ public class WebSocketClientFactory extends AggregateLifeCycle
|
|||
{
|
||||
while (_endp.isOpen() && !_parser.isComplete())
|
||||
{
|
||||
if (!_handshaken)
|
||||
handshake();
|
||||
|
||||
if (!_parser.parseAvailable())
|
||||
{
|
||||
if (_endp.isInputShutdown())
|
||||
|
@ -387,25 +445,29 @@ public class WebSocketClientFactory extends AggregateLifeCycle
|
|||
return this;
|
||||
}
|
||||
}
|
||||
if (_error==null)
|
||||
if (_error == null)
|
||||
{
|
||||
if (_accept==null)
|
||||
_error="No Sec-WebSocket-Accept";
|
||||
else if (!WebSocketConnectionD13.hashKey(_key).equals(_accept))
|
||||
_error="Bad Sec-WebSocket-Accept";
|
||||
if (_accept == null)
|
||||
{
|
||||
_error = "No Sec-WebSocket-Accept";
|
||||
}
|
||||
else if (!WebSocketConnectionRFC6455.hashKey(_key).equals(_accept))
|
||||
{
|
||||
_error = "Bad Sec-WebSocket-Accept";
|
||||
}
|
||||
else
|
||||
{
|
||||
Buffer header=_parser.getHeaderBuffer();
|
||||
MaskGen maskGen=_future.getMaskGen();
|
||||
WebSocketConnectionD13 connection =
|
||||
new WebSocketConnectionD13(_future.getWebSocket(),
|
||||
_endp,
|
||||
_buffers,System.currentTimeMillis(),
|
||||
_future.getMaxIdleTime(),
|
||||
_future.getProtocol(),
|
||||
null,
|
||||
WebSocketConnectionD13.VERSION,
|
||||
maskGen);
|
||||
Buffer header = _parser.getHeaderBuffer();
|
||||
MaskGen maskGen = _future.getMaskGen();
|
||||
WebSocketConnectionRFC6455 connection =
|
||||
new WebSocketConnectionRFC6455(_future.getWebSocket(),
|
||||
_endp,
|
||||
_buffers, System.currentTimeMillis(),
|
||||
_future.getMaxIdleTime(),
|
||||
_future.getProtocol(),
|
||||
null,
|
||||
WebSocketConnectionRFC6455.VERSION,
|
||||
maskGen);
|
||||
|
||||
if (header.hasContent())
|
||||
connection.fillBuffersFrom(header);
|
||||
|
@ -438,15 +500,10 @@ public class WebSocketClientFactory extends AggregateLifeCycle
|
|||
|
||||
public void onClose()
|
||||
{
|
||||
if (_error!=null)
|
||||
if (_error != null)
|
||||
_future.handshakeFailed(new ProtocolException(_error));
|
||||
else
|
||||
_future.handshakeFailed(new EOFException());
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "HS"+super.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,23 @@
|
|||
/*******************************************************************************
|
||||
* 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;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.io.Buffer;
|
||||
import org.eclipse.jetty.io.nio.AsyncConnection;
|
||||
|
||||
|
@ -14,8 +25,6 @@ public interface WebSocketConnection extends AsyncConnection
|
|||
{
|
||||
void fillBuffersFrom(Buffer buffer);
|
||||
|
||||
void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException;
|
||||
|
||||
List<Extension> getExtensions();
|
||||
|
||||
WebSocket.Connection getConnection();
|
||||
|
|
|
@ -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.
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -19,10 +34,6 @@ import java.security.NoSuchAlgorithmException;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.http.HttpURI;
|
||||
import org.eclipse.jetty.io.AbstractConnection;
|
||||
import org.eclipse.jetty.io.AsyncEndPoint;
|
||||
import org.eclipse.jetty.io.Buffer;
|
||||
|
@ -30,7 +41,6 @@ import org.eclipse.jetty.io.ByteArrayBuffer;
|
|||
import org.eclipse.jetty.io.Connection;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.io.nio.IndirectNIOBuffer;
|
||||
import org.eclipse.jetty.util.QuotedStringTokenizer;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
@ -43,13 +53,13 @@ public class WebSocketConnectionD00 extends AbstractConnection implements WebSoc
|
|||
public final static byte LENGTH_FRAME=(byte)0x80;
|
||||
public final static byte SENTINEL_FRAME=(byte)0x00;
|
||||
|
||||
final WebSocketParser _parser;
|
||||
final WebSocketGenerator _generator;
|
||||
final WebSocket _websocket;
|
||||
final String _protocol;
|
||||
String _key1;
|
||||
String _key2;
|
||||
ByteArrayBuffer _hixieBytes;
|
||||
private final WebSocketParser _parser;
|
||||
private final WebSocketGenerator _generator;
|
||||
private final WebSocket _websocket;
|
||||
private final String _protocol;
|
||||
private String _key1;
|
||||
private String _key2;
|
||||
private ByteArrayBuffer _hixieBytes;
|
||||
|
||||
public WebSocketConnectionD00(WebSocket websocket, EndPoint endpoint, WebSocketBuffers buffers, long timestamp, int maxIdleTime, String protocol)
|
||||
throws IOException
|
||||
|
@ -140,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)
|
||||
|
@ -152,7 +161,8 @@ public class WebSocketConnectionD00 extends AbstractConnection implements WebSoc
|
|||
LOG.debug(e);
|
||||
try
|
||||
{
|
||||
_endp.close();
|
||||
if (_endp.isOpen())
|
||||
_endp.close();
|
||||
}
|
||||
catch(IOException e2)
|
||||
{
|
||||
|
@ -340,54 +350,6 @@ public class WebSocketConnectionD00 extends AbstractConnection implements WebSoc
|
|||
}
|
||||
}
|
||||
|
||||
public void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException
|
||||
{
|
||||
String uri=request.getRequestURI();
|
||||
String query=request.getQueryString();
|
||||
if (query!=null && query.length()>0)
|
||||
uri+="?"+query;
|
||||
uri=new HttpURI(uri).toString();
|
||||
String host=request.getHeader("Host");
|
||||
|
||||
String origin=request.getHeader("Sec-WebSocket-Origin");
|
||||
if (origin==null)
|
||||
origin=request.getHeader("Origin");
|
||||
if (origin!=null)
|
||||
origin= QuotedStringTokenizer.quoteIfNeeded(origin, "\r\n");
|
||||
|
||||
|
||||
String key1 = request.getHeader("Sec-WebSocket-Key1");
|
||||
|
||||
if (key1!=null)
|
||||
{
|
||||
String key2 = request.getHeader("Sec-WebSocket-Key2");
|
||||
setHixieKeys(key1,key2);
|
||||
|
||||
response.setHeader("Upgrade","WebSocket");
|
||||
response.addHeader("Connection","Upgrade");
|
||||
if (origin!=null)
|
||||
response.addHeader("Sec-WebSocket-Origin",origin);
|
||||
response.addHeader("Sec-WebSocket-Location",(request.isSecure()?"wss://":"ws://")+host+uri);
|
||||
if (subprotocol!=null)
|
||||
response.addHeader("Sec-WebSocket-Protocol",subprotocol);
|
||||
response.sendError(101,"WebSocket Protocol Handshake");
|
||||
}
|
||||
else
|
||||
{
|
||||
response.setHeader("Upgrade","WebSocket");
|
||||
response.addHeader("Connection","Upgrade");
|
||||
response.addHeader("WebSocket-Origin",origin);
|
||||
response.addHeader("WebSocket-Location",(request.isSecure()?"wss://":"ws://")+host+uri);
|
||||
if (subprotocol!=null)
|
||||
response.addHeader("WebSocket-Protocol",subprotocol);
|
||||
response.sendError(101,"Web Socket Protocol Handshake");
|
||||
response.flushBuffer();
|
||||
if (_websocket instanceof OnFrame)
|
||||
((OnFrame)_websocket).onHandshake(this);
|
||||
_websocket.onOpen(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void setMaxTextMessageSize(int size)
|
||||
{
|
||||
}
|
||||
|
@ -427,6 +389,19 @@ public class WebSocketConnectionD00 extends AbstractConnection implements WebSoc
|
|||
{
|
||||
return _protocol;
|
||||
}
|
||||
|
||||
protected void onFrameHandshake()
|
||||
{
|
||||
if (_websocket instanceof OnFrame)
|
||||
{
|
||||
((OnFrame)_websocket).onHandshake(this);
|
||||
}
|
||||
}
|
||||
|
||||
protected void onWebsocketOpen()
|
||||
{
|
||||
_websocket.onOpen(this);
|
||||
}
|
||||
|
||||
static class FrameHandlerD00 implements WebSocketParser.FrameHandler
|
||||
{
|
||||
|
|
|
@ -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.
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -19,9 +34,6 @@ import java.security.MessageDigest;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.io.AbstractConnection;
|
||||
import org.eclipse.jetty.io.AsyncEndPoint;
|
||||
import org.eclipse.jetty.io.Buffer;
|
||||
|
@ -73,7 +85,6 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private final static byte[] MAGIC;
|
||||
private final WebSocketParser _parser;
|
||||
private final WebSocketGenerator _generator;
|
||||
|
@ -101,10 +112,6 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
|
|||
}
|
||||
|
||||
private final WebSocketParser.FrameHandler _frameHandler= new FrameHandlerD06();
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------ */
|
||||
private final WebSocket.FrameConnection _connection = new FrameConnectionD06();
|
||||
|
||||
|
||||
|
@ -199,7 +206,7 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
|
|||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public void onIdleExpired()
|
||||
public void onIdleExpired(long idleForMs)
|
||||
{
|
||||
closeOut(WebSocketConnectionD06.CLOSE_NORMAL,"Idle");
|
||||
}
|
||||
|
@ -287,9 +294,20 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
|
|||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
protected void onFrameHandshake()
|
||||
{
|
||||
if (_onFrame!=null)
|
||||
{
|
||||
_onFrame.onHandshake(_connection);
|
||||
}
|
||||
}
|
||||
|
||||
protected void onWebSocketOpen()
|
||||
{
|
||||
_webSocket.onOpen(_connection);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------ */
|
||||
private class FrameConnectionD06 implements WebSocket.FrameConnection
|
||||
{
|
||||
|
@ -487,6 +505,7 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
|
|||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return this.getClass().getSimpleName()+"@"+_endp.getLocalAddr()+":"+_endp.getLocalPort()+"<->"+_endp.getRemoteAddr()+":"+_endp.getRemotePort();
|
||||
|
@ -693,29 +712,13 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
|
|||
_connection.close(code,message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return WebSocketConnectionD06.this.toString()+"FH";
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException
|
||||
{
|
||||
String key = request.getHeader("Sec-WebSocket-Key");
|
||||
|
||||
response.setHeader("Upgrade","WebSocket");
|
||||
response.addHeader("Connection","Upgrade");
|
||||
response.addHeader("Sec-WebSocket-Accept",hashKey(key));
|
||||
if (subprotocol!=null)
|
||||
response.addHeader("Sec-WebSocket-Protocol",subprotocol);
|
||||
response.sendError(101);
|
||||
|
||||
if (_onFrame!=null)
|
||||
_onFrame.onHandshake(_connection);
|
||||
_webSocket.onOpen(_connection);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public static String hashKey(String key)
|
||||
{
|
||||
|
|
|
@ -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.
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -19,16 +34,12 @@ import java.security.MessageDigest;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.io.AbstractConnection;
|
||||
import org.eclipse.jetty.io.AsyncEndPoint;
|
||||
import org.eclipse.jetty.io.Buffer;
|
||||
import org.eclipse.jetty.io.ByteArrayBuffer;
|
||||
import org.eclipse.jetty.io.Connection;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.io.nio.SelectChannelEndPoint;
|
||||
import org.eclipse.jetty.util.B64Code;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.Utf8StringBuilder;
|
||||
|
@ -110,7 +121,6 @@ public class WebSocketConnectionD08 extends AbstractConnection implements WebSoc
|
|||
}
|
||||
|
||||
private final WebSocketParser.FrameHandler _frameHandler= new WSFrameHandler();
|
||||
|
||||
private final WebSocket.FrameConnection _connection = new WSFrameConnection();
|
||||
|
||||
|
||||
|
@ -246,10 +256,9 @@ public class WebSocketConnectionD08 extends AbstractConnection implements WebSoc
|
|||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public void onIdleExpired()
|
||||
public void onIdleExpired(long idleForMs)
|
||||
{
|
||||
long idle = System.currentTimeMillis()-((SelectChannelEndPoint)_endp).getIdleTimestamp();
|
||||
closeOut(WebSocketConnectionD08.CLOSE_NORMAL,"Idle for "+idle+"ms > "+_endp.getMaxIdleTime()+"ms");
|
||||
closeOut(WebSocketConnectionD08.CLOSE_NORMAL,"Idle for "+idleForMs+"ms > "+_endp.getMaxIdleTime()+"ms");
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -376,8 +385,19 @@ public class WebSocketConnectionD08 extends AbstractConnection implements WebSoc
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void onFrameHandshake()
|
||||
{
|
||||
if (_onFrame != null)
|
||||
{
|
||||
_onFrame.onHandshake(_connection);
|
||||
}
|
||||
}
|
||||
|
||||
protected void onWebSocketOpen()
|
||||
{
|
||||
_webSocket.onOpen(_connection);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
private class WSFrameConnection implements WebSocket.FrameConnection
|
||||
{
|
||||
|
@ -800,27 +820,6 @@ public class WebSocketConnectionD08 extends AbstractConnection implements WebSoc
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException
|
||||
{
|
||||
String key = request.getHeader("Sec-WebSocket-Key");
|
||||
|
||||
response.setHeader("Upgrade", "WebSocket");
|
||||
response.addHeader("Connection","Upgrade");
|
||||
response.addHeader("Sec-WebSocket-Accept",hashKey(key));
|
||||
if (subprotocol!=null)
|
||||
response.addHeader("Sec-WebSocket-Protocol",subprotocol);
|
||||
|
||||
for(Extension ext : _extensions)
|
||||
response.addHeader("Sec-WebSocket-Extensions",ext.getParameterizedName());
|
||||
|
||||
response.sendError(101);
|
||||
|
||||
if (_onFrame!=null)
|
||||
_onFrame.onHandshake(_connection);
|
||||
_webSocket.onOpen(_connection);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public static String hashKey(String key)
|
||||
{
|
||||
|
@ -841,6 +840,6 @@ public class WebSocketConnectionD08 extends AbstractConnection implements WebSoc
|
|||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "WS/D"+_draft+"-"+_endp;
|
||||
return String.format("WS/D%d p=%s g=%s", _draft, _parser, _generator);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -19,16 +34,12 @@ import java.security.MessageDigest;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.io.AbstractConnection;
|
||||
import org.eclipse.jetty.io.AsyncEndPoint;
|
||||
import org.eclipse.jetty.io.Buffer;
|
||||
import org.eclipse.jetty.io.ByteArrayBuffer;
|
||||
import org.eclipse.jetty.io.Connection;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.io.nio.SelectChannelEndPoint;
|
||||
import org.eclipse.jetty.util.B64Code;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.Utf8Appendable;
|
||||
|
@ -64,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;
|
||||
|
@ -90,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)
|
||||
|
@ -108,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;
|
||||
|
@ -141,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);
|
||||
|
@ -163,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();
|
||||
|
@ -221,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())
|
||||
|
@ -274,10 +287,9 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public void onIdleExpired()
|
||||
public void onIdleExpired(long idleForMs)
|
||||
{
|
||||
long idle = System.currentTimeMillis()-((SelectChannelEndPoint)_endp).getIdleTimestamp();
|
||||
closeOut(WebSocketConnectionD13.CLOSE_NORMAL,"Idle for "+idle+"ms > "+_endp.getMaxIdleTime()+"ms");
|
||||
closeOut(WebSocketConnectionRFC6455.CLOSE_NORMAL,"Idle for "+idleForMs+"ms > "+_endp.getMaxIdleTime()+"ms");
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -294,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");
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -361,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();
|
||||
}
|
||||
}
|
||||
|
@ -398,8 +415,19 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void onFrameHandshake()
|
||||
{
|
||||
if (_onFrame != null)
|
||||
{
|
||||
_onFrame.onHandshake(_connection);
|
||||
}
|
||||
}
|
||||
|
||||
protected void onWebSocketOpen()
|
||||
{
|
||||
_webSocket.onOpen(_connection);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
private class WSFrameConnection implements WebSocket.FrameConnection
|
||||
{
|
||||
|
@ -411,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();
|
||||
}
|
||||
|
||||
|
@ -420,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();
|
||||
}
|
||||
|
||||
|
@ -461,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);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -625,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)
|
||||
|
@ -637,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;
|
||||
}
|
||||
|
||||
|
@ -669,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()))
|
||||
{
|
||||
|
@ -718,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;
|
||||
}
|
||||
|
||||
|
@ -766,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;
|
||||
}
|
||||
|
||||
|
@ -791,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)
|
||||
|
@ -805,7 +833,7 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
}
|
||||
else
|
||||
{
|
||||
_opcode=WebSocketConnectionD13.OP_TEXT;
|
||||
_opcode=WebSocketConnectionRFC6455.OP_TEXT;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -814,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;
|
||||
}
|
||||
|
||||
|
@ -839,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -886,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();
|
||||
|
@ -898,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();
|
||||
|
@ -914,30 +942,9 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return WebSocketConnectionD13.this.toString()+"FH";
|
||||
return WebSocketConnectionRFC6455.this.toString()+"FH";
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException
|
||||
{
|
||||
String key = request.getHeader("Sec-WebSocket-Key");
|
||||
|
||||
response.setHeader("Upgrade","WebSocket");
|
||||
response.addHeader("Connection","Upgrade");
|
||||
response.addHeader("Sec-WebSocket-Accept",hashKey(key));
|
||||
if (subprotocol!=null)
|
||||
response.addHeader("Sec-WebSocket-Protocol",subprotocol);
|
||||
|
||||
for(Extension ext : _extensions)
|
||||
response.addHeader("Sec-WebSocket-Extensions",ext.getParameterizedName());
|
||||
|
||||
response.sendError(101);
|
||||
|
||||
if (_onFrame!=null)
|
||||
_onFrame.onHandshake(_connection);
|
||||
_webSocket.onOpen(_connection);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public static String hashKey(String key)
|
||||
|
@ -959,6 +966,6 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
|
|||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "WS/D"+_draft+"-"+_endp;
|
||||
return String.format("WS/D%d p=%s g=%s", _draft, _parser, _generator);
|
||||
}
|
||||
}
|
|
@ -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.
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -193,53 +208,60 @@ 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");
|
||||
ConnectedEndPoint endp = (ConnectedEndPoint)http.getEndPoint();
|
||||
|
||||
List<String> extensions_requested = new ArrayList<String>();
|
||||
for (Enumeration e=request.getHeaders("Sec-WebSocket-Extensions");e.hasMoreElements();)
|
||||
@SuppressWarnings("unchecked")
|
||||
Enumeration<String> e = request.getHeaders("Sec-WebSocket-Extensions");
|
||||
while (e.hasMoreElements())
|
||||
{
|
||||
QuotedStringTokenizer tok = new QuotedStringTokenizer((String)e.nextElement(),",");
|
||||
QuotedStringTokenizer tok = new QuotedStringTokenizer(e.nextElement(),",");
|
||||
while (tok.hasMoreTokens())
|
||||
{
|
||||
extensions_requested.add(tok.nextToken());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
final WebSocketConnection connection;
|
||||
final WebSocketServletConnection connection;
|
||||
final List<Extension> extensions;
|
||||
switch (draft)
|
||||
{
|
||||
case -1:
|
||||
case 0:
|
||||
case -1: // unspecified draft/version
|
||||
case 0: // Old school draft/version
|
||||
extensions=Collections.emptyList();
|
||||
connection = new WebSocketConnectionD00(websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol);
|
||||
connection = new WebSocketServletConnectionD00(websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol);
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 6:
|
||||
extensions=Collections.emptyList();
|
||||
connection = new WebSocketConnectionD06(websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol);
|
||||
connection = new WebSocketServletConnectionD06(websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol);
|
||||
break;
|
||||
case 7:
|
||||
case 8:
|
||||
extensions= initExtensions(extensions_requested,8-WebSocketConnectionD08.OP_EXT_DATA, 16-WebSocketConnectionD08.OP_EXT_CTRL,3);
|
||||
connection = new WebSocketConnectionD08(websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol,extensions,draft);
|
||||
connection = new WebSocketServletConnectionD08(websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol,extensions,draft);
|
||||
break;
|
||||
case 13:
|
||||
extensions= initExtensions(extensions_requested,8-WebSocketConnectionD13.OP_EXT_DATA, 16-WebSocketConnectionD13.OP_EXT_CTRL,3);
|
||||
connection = new WebSocketConnectionD13(websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol,extensions,draft);
|
||||
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
|
||||
|
@ -292,7 +314,8 @@ public class WebSocketFactory
|
|||
|
||||
// Try each requested protocol
|
||||
WebSocket websocket = null;
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Enumeration<String> protocols = request.getHeaders("Sec-WebSocket-Protocol");
|
||||
String protocol=null;
|
||||
while (protocol==null && protocols!=null && protocols.hasMoreElements())
|
||||
|
@ -314,7 +337,7 @@ public class WebSocketFactory
|
|||
{
|
||||
// Try with no protocol
|
||||
websocket = _acceptor.doWebSocketConnect(request, null);
|
||||
|
||||
|
||||
if (websocket==null)
|
||||
{
|
||||
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
|
||||
|
|
|
@ -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,21 +78,21 @@ 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;
|
||||
|
||||
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;
|
||||
|
||||
|
@ -240,4 +255,17 @@ public class WebSocketGeneratorD13 implements WebSocketGenerator
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
// Do NOT use synchronized (this)
|
||||
// because it's very easy to deadlock when debugging is enabled.
|
||||
// We do a best effort to print the right toString() and that's it.
|
||||
Buffer buffer = _buffer;
|
||||
return String.format("%s@%x closed=%b buffer=%d",
|
||||
getClass().getSimpleName(),
|
||||
hashCode(),
|
||||
_closed,
|
||||
buffer == null ? -1 : buffer.length());
|
||||
}
|
||||
}
|
|
@ -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.
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -125,7 +140,7 @@ public class WebSocketParserD13 implements WebSocketParser
|
|||
{
|
||||
if (_buffer==null)
|
||||
_buffer=_buffers.getBuffer();
|
||||
|
||||
|
||||
boolean progress=false;
|
||||
int filled=-1;
|
||||
|
||||
|
@ -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)
|
||||
|
@ -189,7 +204,7 @@ public class WebSocketParserD13 implements WebSocketParser
|
|||
// Did we get enough?
|
||||
if (available<(_state==State.SKIP?1:_bytesNeeded))
|
||||
break;
|
||||
|
||||
|
||||
// if we are here, then we have sufficient bytes to process the current state.
|
||||
// Parse the buffer byte by byte (unless it is STATE_DATA)
|
||||
byte b;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -307,7 +322,7 @@ public class WebSocketParserD13 implements WebSocketParser
|
|||
if (_bytesNeeded==0)
|
||||
_state=State.START;
|
||||
break;
|
||||
|
||||
|
||||
case SEEK_EOF:
|
||||
progress=true;
|
||||
_buffer.skip(available);
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -349,7 +364,7 @@ public class WebSocketParserD13 implements WebSocketParser
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return progress?1:filled;
|
||||
}
|
||||
|
||||
|
@ -380,8 +395,10 @@ public class WebSocketParserD13 implements WebSocketParser
|
|||
@Override
|
||||
public String toString()
|
||||
{
|
||||
Buffer buffer=_buffer;
|
||||
return WebSocketParserD13.class.getSimpleName()+"@"+ Integer.toHexString(hashCode())+"|"+_state+"|"+(buffer==null?"<>":buffer.toDetailString());
|
||||
return String.format("%s@%x state=%s buffer=%s",
|
||||
getClass().getSimpleName(),
|
||||
hashCode(),
|
||||
_state,
|
||||
_buffer);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,20 +1,34 @@
|
|||
/*******************************************************************************
|
||||
* 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.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.websocket;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
@ -39,12 +53,13 @@ import javax.servlet.http.HttpServletResponse;
|
|||
* <p>
|
||||
* The initParameter "maxBinaryMessagesSize" can be used to set the size in bytes
|
||||
* that a websocket may be accept before closing.
|
||||
*
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public abstract class WebSocketServlet extends HttpServlet implements WebSocketFactory.Acceptor
|
||||
{
|
||||
WebSocketFactory _webSocketFactory;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.GenericServlet#init()
|
||||
|
@ -57,15 +72,15 @@ public abstract class WebSocketServlet extends HttpServlet implements WebSocketF
|
|||
String max=getInitParameter("maxIdleTime");
|
||||
if (max!=null)
|
||||
_webSocketFactory.setMaxIdleTime(Integer.parseInt(max));
|
||||
|
||||
|
||||
max=getInitParameter("maxTextMessageSize");
|
||||
if (max!=null)
|
||||
_webSocketFactory.setMaxTextMessageSize(Integer.parseInt(max));
|
||||
|
||||
|
||||
max=getInitParameter("maxBinaryMessageSize");
|
||||
if (max!=null)
|
||||
_webSocketFactory.setMaxBinaryMessageSize(Integer.parseInt(max));
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -74,7 +89,7 @@ public abstract class WebSocketServlet extends HttpServlet implements WebSocketF
|
|||
*/
|
||||
@Override
|
||||
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||
{
|
||||
{
|
||||
if (_webSocketFactory.acceptWebSocket(request,response) || response.isCommitted())
|
||||
return;
|
||||
super.service(request,response);
|
||||
|
@ -85,7 +100,7 @@ public abstract class WebSocketServlet extends HttpServlet implements WebSocketF
|
|||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
/*******************************************************************************
|
||||
* 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;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
public interface WebSocketServletConnection extends WebSocketConnection
|
||||
{
|
||||
void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException;
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
/*******************************************************************************
|
||||
* 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;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.http.HttpURI;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.util.QuotedStringTokenizer;
|
||||
|
||||
public class WebSocketServletConnectionD00 extends WebSocketConnectionD00 implements WebSocketServletConnection
|
||||
{
|
||||
public WebSocketServletConnectionD00(WebSocket websocket, EndPoint endpoint, WebSocketBuffers buffers, long timestamp, int maxIdleTime, String protocol)
|
||||
throws IOException
|
||||
{
|
||||
super(websocket,endpoint,buffers,timestamp,maxIdleTime,protocol);
|
||||
}
|
||||
|
||||
public void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException
|
||||
{
|
||||
String uri = request.getRequestURI();
|
||||
String query = request.getQueryString();
|
||||
if (query != null && query.length() > 0)
|
||||
{
|
||||
uri += "?" + query;
|
||||
}
|
||||
uri = new HttpURI(uri).toString();
|
||||
String host = request.getHeader("Host");
|
||||
|
||||
String origin = request.getHeader("Sec-WebSocket-Origin");
|
||||
if (origin == null)
|
||||
{
|
||||
origin = request.getHeader("Origin");
|
||||
}
|
||||
if (origin != null)
|
||||
{
|
||||
origin = QuotedStringTokenizer.quoteIfNeeded(origin,"\r\n");
|
||||
}
|
||||
|
||||
String key1 = request.getHeader("Sec-WebSocket-Key1");
|
||||
|
||||
if (key1 != null)
|
||||
{
|
||||
String key2 = request.getHeader("Sec-WebSocket-Key2");
|
||||
setHixieKeys(key1,key2);
|
||||
|
||||
response.setHeader("Upgrade","WebSocket");
|
||||
response.addHeader("Connection","Upgrade");
|
||||
if (origin != null)
|
||||
{
|
||||
response.addHeader("Sec-WebSocket-Origin",origin);
|
||||
}
|
||||
response.addHeader("Sec-WebSocket-Location",(request.isSecure()?"wss://":"ws://") + host + uri);
|
||||
if (subprotocol != null)
|
||||
{
|
||||
response.addHeader("Sec-WebSocket-Protocol",subprotocol);
|
||||
}
|
||||
response.sendError(101,"WebSocket Protocol Handshake");
|
||||
}
|
||||
else
|
||||
{
|
||||
response.setHeader("Upgrade","WebSocket");
|
||||
response.addHeader("Connection","Upgrade");
|
||||
response.addHeader("WebSocket-Origin",origin);
|
||||
response.addHeader("WebSocket-Location",(request.isSecure()?"wss://":"ws://") + host + uri);
|
||||
if (subprotocol != null)
|
||||
{
|
||||
response.addHeader("WebSocket-Protocol",subprotocol);
|
||||
}
|
||||
response.sendError(101,"Web Socket Protocol Handshake");
|
||||
response.flushBuffer();
|
||||
|
||||
onFrameHandshake();
|
||||
onWebsocketOpen();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/*******************************************************************************
|
||||
* 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;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
|
||||
public class WebSocketServletConnectionD06 extends WebSocketConnectionD06 implements WebSocketServletConnection
|
||||
{
|
||||
public WebSocketServletConnectionD06(WebSocket websocket, EndPoint endpoint, WebSocketBuffers buffers, long timestamp, int maxIdleTime, String protocol)
|
||||
throws IOException
|
||||
{
|
||||
super(websocket,endpoint,buffers,timestamp,maxIdleTime,protocol);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException
|
||||
{
|
||||
String key = request.getHeader("Sec-WebSocket-Key");
|
||||
|
||||
response.setHeader("Upgrade","WebSocket");
|
||||
response.addHeader("Connection","Upgrade");
|
||||
response.addHeader("Sec-WebSocket-Accept",hashKey(key));
|
||||
if (subprotocol!=null)
|
||||
{
|
||||
response.addHeader("Sec-WebSocket-Protocol",subprotocol);
|
||||
}
|
||||
|
||||
response.sendError(101);
|
||||
|
||||
onFrameHandshake();
|
||||
onWebSocketOpen();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
/*******************************************************************************
|
||||
* 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;
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
|
||||
public class WebSocketServletConnectionD08 extends WebSocketConnectionD08 implements WebSocketServletConnection
|
||||
{
|
||||
public WebSocketServletConnectionD08(WebSocket websocket, EndPoint endpoint, WebSocketBuffers buffers, long timestamp, int maxIdleTime, String protocol,
|
||||
List<Extension> extensions, int draft, MaskGen maskgen) throws IOException
|
||||
{
|
||||
super(websocket,endpoint,buffers,timestamp,maxIdleTime,protocol,extensions,draft,maskgen);
|
||||
}
|
||||
|
||||
public WebSocketServletConnectionD08(WebSocket websocket, EndPoint endpoint, WebSocketBuffers buffers, long timestamp, int maxIdleTime, String protocol,
|
||||
List<Extension> extensions, int draft) throws IOException
|
||||
{
|
||||
super(websocket,endpoint,buffers,timestamp,maxIdleTime,protocol,extensions,draft);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException
|
||||
{
|
||||
String key = request.getHeader("Sec-WebSocket-Key");
|
||||
|
||||
response.setHeader("Upgrade","WebSocket");
|
||||
response.addHeader("Connection","Upgrade");
|
||||
response.addHeader("Sec-WebSocket-Accept",hashKey(key));
|
||||
if (subprotocol != null)
|
||||
{
|
||||
response.addHeader("Sec-WebSocket-Protocol",subprotocol);
|
||||
}
|
||||
|
||||
for (Extension ext : getExtensions())
|
||||
{
|
||||
response.addHeader("Sec-WebSocket-Extensions",ext.getParameterizedName());
|
||||
}
|
||||
|
||||
response.sendError(101);
|
||||
|
||||
onFrameHandshake();
|
||||
onWebSocketOpen();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
/*******************************************************************************
|
||||
* 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;
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
|
||||
public class WebSocketServletConnectionRFC6455 extends WebSocketConnectionRFC6455 implements WebSocketServletConnection
|
||||
{
|
||||
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 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);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException
|
||||
{
|
||||
String key = request.getHeader("Sec-WebSocket-Key");
|
||||
|
||||
response.setHeader("Upgrade","WebSocket");
|
||||
response.addHeader("Connection","Upgrade");
|
||||
response.addHeader("Sec-WebSocket-Accept",hashKey(key));
|
||||
if (subprotocol != null)
|
||||
{
|
||||
response.addHeader("Sec-WebSocket-Protocol",subprotocol);
|
||||
}
|
||||
|
||||
for (Extension ext : getExtensions())
|
||||
{
|
||||
response.addHeader("Sec-WebSocket-Extensions",ext.getParameterizedName());
|
||||
}
|
||||
|
||||
response.sendError(101);
|
||||
|
||||
onFrameHandshake();
|
||||
onWebSocketOpen();
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
/*******************************************************************************
|
||||
* 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.*;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
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.SafariD00;
|
||||
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.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
public class SafariWebsocketDraft0Test
|
||||
{
|
||||
private Server server;
|
||||
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
|
||||
{
|
||||
// Configure Server
|
||||
server = new Server(0);
|
||||
|
||||
ServletContextHandler context = new ServletContextHandler();
|
||||
context.setContextPath("/");
|
||||
server.setHandler(context);
|
||||
|
||||
// Serve capture servlet
|
||||
servlet = new WebSocketCaptureServlet();
|
||||
context.addServlet(new ServletHolder(servlet),"/");
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendTextMessages() throws Exception
|
||||
{
|
||||
SafariD00 safari = new SafariD00(serverUri);
|
||||
|
||||
try
|
||||
{
|
||||
safari.connect();
|
||||
safari.issueHandshake();
|
||||
|
||||
// Send 5 short messages, using technique seen in Safari.
|
||||
safari.sendMessage("aa-0"); // single msg
|
||||
safari.sendMessage("aa-1", "aa-2", "aa-3", "aa-4");
|
||||
|
||||
// Servlet should show only 1 connection.
|
||||
Assert.assertThat("Servlet.captureSockets.size",servlet.captures.size(),is(1));
|
||||
|
||||
CaptureSocket socket = servlet.captures.get(0);
|
||||
Assert.assertThat("CaptureSocket",socket,notNullValue());
|
||||
Assert.assertThat("CaptureSocket.isConnected", socket.isConnected(), is(true));
|
||||
|
||||
// Give servlet 500 millisecond to process messages
|
||||
threadSleep(1,TimeUnit.SECONDS);
|
||||
// Should have captured 5 messages.
|
||||
Assert.assertThat("CaptureSocket.messages.size",socket.messages.size(),is(5));
|
||||
}
|
||||
finally
|
||||
{
|
||||
// System.out.println("Closing client socket");
|
||||
safari.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
public static void threadSleep(int dur, TimeUnit unit) throws InterruptedException
|
||||
{
|
||||
long ms = TimeUnit.MILLISECONDS.convert(dur,unit);
|
||||
Thread.sleep(ms);
|
||||
}
|
||||
|
||||
@After
|
||||
public void stopServer() throws Exception
|
||||
{
|
||||
server.stop();
|
||||
}
|
||||
}
|
|
@ -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,13 +1,27 @@
|
|||
/*******************************************************************************
|
||||
* 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 java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
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;
|
||||
|
@ -30,6 +44,9 @@ import org.junit.Assert;
|
|||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
public class WebSocketClientTest
|
||||
{
|
||||
private WebSocketClientFactory _factory = new WebSocketClientFactory();
|
||||
|
@ -133,7 +150,6 @@ public class WebSocketClientTest
|
|||
Assert.assertFalse(open.get());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testAsyncConnectionRefused() throws Exception
|
||||
{
|
||||
|
@ -167,13 +183,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 +221,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 +260,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 +300,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 +343,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 +381,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 +419,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 +496,6 @@ public class WebSocketClientTest
|
|||
Assert.assertEquals("Invalid close code 1111", closeMessage.toString());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testBlockSending() throws Exception
|
||||
{
|
||||
|
@ -566,18 +577,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 +687,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 +710,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 +776,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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
/*******************************************************************************
|
||||
* 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.*;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
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.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.Test;
|
||||
|
||||
/**
|
||||
* WebSocketCommTest - to test reported undelivered messages in bug <a
|
||||
* href="https://jira.codehaus.org/browse/JETTY-1463">JETTY-1463</a>
|
||||
*/
|
||||
public class WebSocketCommTest
|
||||
{
|
||||
private Server server;
|
||||
private WebSocketCaptureServlet servlet;
|
||||
private URI serverUri;
|
||||
|
||||
@Before
|
||||
public void startServer() throws Exception
|
||||
{
|
||||
// Configure Server
|
||||
server = new Server(0);
|
||||
|
||||
ServletContextHandler context = new ServletContextHandler();
|
||||
context.setContextPath("/");
|
||||
server.setHandler(context);
|
||||
|
||||
// Serve capture servlet
|
||||
servlet = new WebSocketCaptureServlet();
|
||||
context.addServlet(new ServletHolder(servlet),"/");
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
@After
|
||||
public void stopServer()
|
||||
{
|
||||
try
|
||||
{
|
||||
server.stop();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace(System.err);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendTextMessages() throws Exception
|
||||
{
|
||||
WebSocketClientFactory clientFactory = new WebSocketClientFactory();
|
||||
clientFactory.start();
|
||||
|
||||
WebSocketClient wsc = clientFactory.newWebSocketClient();
|
||||
MessageSender sender = new MessageSender();
|
||||
wsc.open(serverUri,sender);
|
||||
|
||||
try
|
||||
{
|
||||
sender.awaitConnect();
|
||||
|
||||
// Send 5 short messages
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
System.out.printf("Sending msg-%d%n",i);
|
||||
sender.sendMessage("msg-%d",i);
|
||||
}
|
||||
|
||||
// Servlet should show only 1 connection.
|
||||
Assert.assertThat("Servlet.captureSockets.size",servlet.captures.size(),is(1));
|
||||
|
||||
CaptureSocket socket = servlet.captures.get(0);
|
||||
Assert.assertThat("CaptureSocket",socket,notNullValue());
|
||||
Assert.assertThat("CaptureSocket.isConnected",socket.isConnected(),is(true));
|
||||
|
||||
// Give servlet 500 millisecond to process messages
|
||||
TimeUnit.MILLISECONDS.sleep(500);
|
||||
|
||||
// Should have captured 5 messages.
|
||||
Assert.assertThat("CaptureSocket.messages.size",socket.messages.size(),is(5));
|
||||
}
|
||||
finally
|
||||
{
|
||||
System.out.println("Closing client socket");
|
||||
sender.close();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue