Ripping out javax.net.websocket.extension.* SPI as it is going away
This commit is contained in:
parent
09625a64e2
commit
8548331735
|
@ -237,6 +237,18 @@ public class UpgradeRequest implements HandshakeRequest
|
|||
this.cookies = cookies;
|
||||
}
|
||||
|
||||
public void setHeader(String name, List<String> values)
|
||||
{
|
||||
headers.put(name,values);
|
||||
}
|
||||
|
||||
public void setHeader(String name, String value)
|
||||
{
|
||||
List<String> values = new ArrayList<>();
|
||||
values.add(value);
|
||||
setHeader(name,values);
|
||||
}
|
||||
|
||||
public void setHttpVersion(String httpVersion)
|
||||
{
|
||||
this.httpVersion = httpVersion;
|
||||
|
|
|
@ -39,7 +39,7 @@ public interface WebSocketConnection
|
|||
* @see StatusCode
|
||||
* @see #close(int, String)
|
||||
*/
|
||||
public void close();
|
||||
public void close() throws IOException;
|
||||
|
||||
/**
|
||||
* Send a websocket Close frame, with status code.
|
||||
|
@ -52,7 +52,7 @@ public interface WebSocketConnection
|
|||
* the (optional) reason. (can be null for no reason)
|
||||
* @see StatusCode
|
||||
*/
|
||||
public void close(int statusCode, String reason);
|
||||
public void close(int statusCode, String reason) throws IOException;
|
||||
|
||||
/**
|
||||
* Get the address of the local side.
|
||||
|
@ -102,8 +102,11 @@ public interface WebSocketConnection
|
|||
* NIO style with callbacks, allows for knowledge of successful ping send.
|
||||
* <p>
|
||||
* Use @OnWebSocketFrame and monitor Pong frames
|
||||
*
|
||||
* @param the
|
||||
* ping application data
|
||||
*/
|
||||
Future<SendResult> ping(byte payload[]) throws IOException;
|
||||
void ping(ByteBuffer buf) throws IOException;
|
||||
|
||||
/**
|
||||
* Suspend a the incoming read events on the connection.
|
||||
|
|
|
@ -26,9 +26,12 @@ public interface WebSocketListener
|
|||
/**
|
||||
* A WebSocket binary frame has been received.
|
||||
*
|
||||
* @param payload the raw payload array received
|
||||
* @param offset the offset in the payload array where the data starts
|
||||
* @param len the length of bytes in the payload
|
||||
* @param payload
|
||||
* the raw payload array received
|
||||
* @param offset
|
||||
* the offset in the payload array where the data starts
|
||||
* @param len
|
||||
* the length of bytes in the payload
|
||||
*/
|
||||
void onWebSocketBinary(byte payload[], int offset, int len);
|
||||
|
||||
|
|
|
@ -25,28 +25,8 @@ import javax.net.websocket.extensions.FrameHandler;
|
|||
* <p>
|
||||
* That work is performed by the two {@link FrameHandler} implementations for incoming and outgoing frame handling.
|
||||
*/
|
||||
public interface Extension extends javax.net.websocket.extensions.Extension
|
||||
public interface Extension extends IncomingFrames, OutgoingFrames
|
||||
{
|
||||
/**
|
||||
* Create an instance of a Incoming {@link FrameHandler} for working with frames destined for the End User WebSocket Object.
|
||||
*
|
||||
* @param the
|
||||
* incoming {@link FrameHandler} to wrap
|
||||
* @return the frame handler for incoming frames.
|
||||
*/
|
||||
@Override
|
||||
public FrameHandler createIncomingFrameHandler(FrameHandler incoming);
|
||||
|
||||
/**
|
||||
* Create an instance of a Outgoing {@link FrameHandler} for working with frames destined for the Network Bytes Layer.
|
||||
*
|
||||
* @param the
|
||||
* outgoing {@link FrameHandler} to wrap
|
||||
* @return the frame handler for outgoing frames.
|
||||
*/
|
||||
@Override
|
||||
public FrameHandler createOutgoingFrameHandler(FrameHandler outgoing);
|
||||
|
||||
/**
|
||||
* The active configuration for this extension.
|
||||
*
|
||||
|
@ -59,7 +39,6 @@ public interface Extension extends javax.net.websocket.extensions.Extension
|
|||
* <p>
|
||||
* Also known as the <a href="https://tools.ietf.org/html/rfc6455#section-9.1"><code>extension-token</code> per Section 9.1. Negotiating Extensions</a>.
|
||||
*/
|
||||
@Override
|
||||
public String getName();
|
||||
|
||||
/**
|
||||
|
@ -101,4 +80,20 @@ public interface Extension extends javax.net.websocket.extensions.Extension
|
|||
* now free to validate the conformance to spec of TEXT Data Frames.
|
||||
*/
|
||||
public abstract boolean isTextDataDecoder();
|
||||
|
||||
/**
|
||||
* Set the next {@link IncomingFrames} to call in the chain.
|
||||
*
|
||||
* @param nextIncoming
|
||||
* the next incoming extension
|
||||
*/
|
||||
public void setNextIncomingFrames(IncomingFrames nextIncoming);
|
||||
|
||||
/**
|
||||
* Set the next {@link OutgoingFrames} to call in the chain.
|
||||
*
|
||||
* @param nextOutgoing
|
||||
* the next outgoing extension
|
||||
*/
|
||||
public void setNextOutgoingFrames(OutgoingFrames nextOutgoing);
|
||||
}
|
|
@ -24,26 +24,26 @@ import java.util.Map;
|
|||
import java.util.ServiceLoader;
|
||||
import java.util.Set;
|
||||
|
||||
public class ExtensionFactory implements Iterable<Extension>
|
||||
public abstract class ExtensionFactory implements Iterable<Class<? extends Extension>>
|
||||
{
|
||||
private ServiceLoader<Extension> extensionLoader = ServiceLoader.load(Extension.class);
|
||||
private Map<String, Extension> availableExtensions;
|
||||
private Map<String, Class<? extends Extension>> availableExtensions;
|
||||
|
||||
public ExtensionFactory()
|
||||
{
|
||||
availableExtensions = new HashMap<>();
|
||||
for (Extension ext : extensionLoader)
|
||||
{
|
||||
availableExtensions.put(ext.getName(),ext);
|
||||
availableExtensions.put(ext.getName(),ext.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, Extension> getAvailableExtensions()
|
||||
public Map<String, Class<? extends Extension>> getAvailableExtensions()
|
||||
{
|
||||
return availableExtensions;
|
||||
}
|
||||
|
||||
public Extension getExtension(String name)
|
||||
public Class<? extends Extension> getExtension(String name)
|
||||
{
|
||||
return availableExtensions.get(name);
|
||||
}
|
||||
|
@ -59,12 +59,14 @@ public class ExtensionFactory implements Iterable<Extension>
|
|||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Extension> iterator()
|
||||
public Iterator<Class<? extends Extension>> iterator()
|
||||
{
|
||||
return availableExtensions.values().iterator();
|
||||
}
|
||||
|
||||
public void register(String name, Extension extension)
|
||||
public abstract Extension newInstance(ExtensionConfig config);
|
||||
|
||||
public void register(String name, Class<? extends Extension> extension)
|
||||
{
|
||||
availableExtensions.put(name,extension);
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ public interface Frame extends javax.net.websocket.extensions.Frame
|
|||
{
|
||||
public static enum Type
|
||||
{
|
||||
CONTINUATION((byte)0x00),
|
||||
TEXT((byte)0x01),
|
||||
BINARY((byte)0x02),
|
||||
CLOSE((byte)0x08),
|
||||
|
@ -35,12 +36,6 @@ public interface Frame extends javax.net.websocket.extensions.Frame
|
|||
|
||||
public static Type from(byte op)
|
||||
{
|
||||
if (op == 0)
|
||||
{
|
||||
// continuation has no type, but is a valid opcode.
|
||||
return null;
|
||||
}
|
||||
|
||||
for (Type type : values())
|
||||
{
|
||||
if (type.opcode == op)
|
||||
|
@ -82,12 +77,18 @@ public interface Frame extends javax.net.websocket.extensions.Frame
|
|||
|
||||
public byte[] getMask();
|
||||
|
||||
public byte getOpCode();
|
||||
|
||||
public ByteBuffer getPayload();
|
||||
|
||||
public int getPayloadLength();
|
||||
|
||||
public int getPayloadStart();
|
||||
|
||||
public Type getType();
|
||||
|
||||
public boolean hasPayload();
|
||||
|
||||
public boolean isContinuation();
|
||||
|
||||
public boolean isFin();
|
||||
|
@ -106,4 +107,10 @@ public interface Frame extends javax.net.websocket.extensions.Frame
|
|||
public boolean isRsv2();
|
||||
|
||||
public boolean isRsv3();
|
||||
|
||||
public void notifySendFailed(Throwable t);
|
||||
|
||||
public void notifySendSuccess();
|
||||
|
||||
public int remaining();
|
||||
}
|
||||
|
|
|
@ -16,10 +16,9 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.common.io;
|
||||
package org.eclipse.jetty.websocket.api.extensions;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.WebSocketException;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
|
||||
/**
|
||||
* Interface for dealing with Incoming Frames.
|
||||
|
@ -28,5 +27,5 @@ public interface IncomingFrames
|
|||
{
|
||||
public void incomingError(WebSocketException e);
|
||||
|
||||
public void incomingFrame(WebSocketFrame frame);
|
||||
public void incomingFrame(Frame frame);
|
||||
}
|
|
@ -16,19 +16,17 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.common.io;
|
||||
package org.eclipse.jetty.websocket.api.extensions;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import javax.net.websocket.SendResult;
|
||||
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
|
||||
/**
|
||||
* Interface for dealing with frames outgoing to the network (eventually)
|
||||
*/
|
||||
public interface OutgoingFrames
|
||||
{
|
||||
Future<SendResult> outgoingFrame(WebSocketFrame frame) throws IOException;
|
||||
Future<SendResult> outgoingFrame(Frame frame) throws IOException;
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.client;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import javax.net.websocket.ClientContainer;
|
||||
import javax.net.websocket.ClientEndpointConfiguration;
|
||||
import javax.net.websocket.DeploymentException;
|
||||
import javax.net.websocket.Endpoint;
|
||||
import javax.net.websocket.Session;
|
||||
|
||||
public class JettyClientContainer implements ClientContainer
|
||||
{
|
||||
@Override
|
||||
public void connectToServer(Endpoint endpoint, ClientEndpointConfiguration olc) throws DeploymentException
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Session> getActiveSessions()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getInstalledExtensions()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getMaxBinaryMessageBufferSize()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getMaxSessionIdleTimeout()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getMaxTextMessageBufferSize()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaxBinaryMessageBufferSize(long max)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaxSessionIdleTimeout(long timeout)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaxTextMessageBufferSize(long max)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
}
|
|
@ -40,10 +40,10 @@ import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
|
|||
import org.eclipse.jetty.websocket.api.extensions.ExtensionFactory;
|
||||
import org.eclipse.jetty.websocket.client.internal.ConnectionManager;
|
||||
import org.eclipse.jetty.websocket.client.internal.DefaultWebSocketClient;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketSession;
|
||||
import org.eclipse.jetty.websocket.common.events.EventDriver;
|
||||
import org.eclipse.jetty.websocket.common.events.EventDriverFactory;
|
||||
import org.eclipse.jetty.websocket.common.extensions.WebSocketExtensionRegistry;
|
||||
import org.eclipse.jetty.websocket.common.io.WebSocketSession;
|
||||
import org.eclipse.jetty.websocket.common.extensions.WebSocketExtensionFactory;
|
||||
|
||||
public class WebSocketClientFactory extends ContainerLifeCycle
|
||||
{
|
||||
|
@ -54,7 +54,7 @@ public class WebSocketClientFactory extends ContainerLifeCycle
|
|||
private final Scheduler scheduler;
|
||||
private final EventDriverFactory eventDriverFactory;
|
||||
private final WebSocketPolicy policy;
|
||||
private final WebSocketExtensionRegistry extensionRegistry;
|
||||
private final WebSocketExtensionFactory extensionRegistry;
|
||||
private SocketAddress bindAddress;
|
||||
|
||||
private final Queue<WebSocketSession> sessions = new ConcurrentLinkedQueue<>();
|
||||
|
@ -98,7 +98,7 @@ public class WebSocketClientFactory extends ContainerLifeCycle
|
|||
}
|
||||
|
||||
this.policy = WebSocketPolicy.newClientPolicy();
|
||||
this.extensionRegistry = new WebSocketExtensionRegistry(policy,bufferPool);
|
||||
this.extensionRegistry = new WebSocketExtensionFactory(policy,bufferPool);
|
||||
|
||||
this.connectionManager = new ConnectionManager(bufferPool,executor,scheduler,sslContextFactory,policy);
|
||||
addBean(this.connectionManager);
|
||||
|
@ -205,7 +205,7 @@ public class WebSocketClientFactory extends ContainerLifeCycle
|
|||
LOG.debug("Session Opened: {}",session);
|
||||
}
|
||||
boolean ret = sessions.offer(session);
|
||||
session.onConnect();
|
||||
session.open();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -95,13 +95,20 @@ public class ConnectionManager extends ContainerLifeCycle
|
|||
clients.add(client);
|
||||
}
|
||||
|
||||
private void closeConnections()
|
||||
private void closeAllConnections()
|
||||
{
|
||||
for (DefaultWebSocketClient client : clients)
|
||||
{
|
||||
if (client.getConnection() != null)
|
||||
{
|
||||
client.getConnection().close();
|
||||
try
|
||||
{
|
||||
client.getConnection().close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
LOG.debug("During Close All Connections",e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -138,7 +145,7 @@ public class ConnectionManager extends ContainerLifeCycle
|
|||
@Override
|
||||
protected void doStop() throws Exception
|
||||
{
|
||||
closeConnections();
|
||||
closeAllConnections();
|
||||
clients.clear();
|
||||
super.doStop();
|
||||
}
|
||||
|
|
|
@ -38,14 +38,13 @@ import org.eclipse.jetty.websocket.api.UpgradeException;
|
|||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Extension;
|
||||
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
|
||||
import org.eclipse.jetty.websocket.api.extensions.IncomingFrames;
|
||||
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.client.ClientUpgradeResponse;
|
||||
import org.eclipse.jetty.websocket.client.internal.DefaultWebSocketClient;
|
||||
import org.eclipse.jetty.websocket.common.AcceptHash;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketSession;
|
||||
import org.eclipse.jetty.websocket.common.events.EventDriver;
|
||||
import org.eclipse.jetty.websocket.common.io.IncomingFrames;
|
||||
import org.eclipse.jetty.websocket.common.io.OutgoingFrames;
|
||||
import org.eclipse.jetty.websocket.common.io.WebSocketSession;
|
||||
|
||||
/**
|
||||
* This is the initial connection handling that exists immediately after physical connection is established to destination server.
|
||||
|
@ -217,13 +216,17 @@ public class UpgradeConnection extends AbstractConnection
|
|||
EventDriver websocket = client.getWebSocket();
|
||||
WebSocketPolicy policy = client.getPolicy();
|
||||
String acceptedSubProtocol = response.getAcceptedSubProtocol();
|
||||
WebSocketSession session = new WebSocketSession(websocket,connection,policy,acceptedSubProtocol);
|
||||
|
||||
WebSocketSession session = new WebSocketSession(request.getRequestURI(),websocket,connection);
|
||||
session.setPolicy(policy);
|
||||
session.setNegotiatedSubprotocol(acceptedSubProtocol);
|
||||
|
||||
connection.setSession(session);
|
||||
List<Extension> extensions = client.getFactory().initExtensions(response.getExtensions());
|
||||
|
||||
// Start with default routing.
|
||||
IncomingFrames incoming = session;
|
||||
OutgoingFrames outgoing = connection;
|
||||
// OutgoingFrames outgoing = connection;
|
||||
|
||||
// Connect extensions
|
||||
if (extensions != null)
|
||||
|
@ -254,7 +257,7 @@ public class UpgradeConnection extends AbstractConnection
|
|||
}
|
||||
|
||||
// configure session for outgoing flows
|
||||
session.setOutgoing(outgoing);
|
||||
// session.setOutgoing(outgoing);
|
||||
// configure connection for incoming flows
|
||||
connection.getParser().setIncomingFramesHandler(incoming);
|
||||
|
||||
|
|
|
@ -19,20 +19,20 @@
|
|||
package org.eclipse.jetty.websocket.client.internal.io;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import javax.net.websocket.SendResult;
|
||||
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Extension;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.api.extensions.IncomingFrames;
|
||||
import org.eclipse.jetty.websocket.client.WebSocketClientFactory;
|
||||
import org.eclipse.jetty.websocket.client.internal.DefaultWebSocketClient;
|
||||
import org.eclipse.jetty.websocket.client.masks.Masker;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection;
|
||||
import org.eclipse.jetty.websocket.common.io.IncomingFrames;
|
||||
|
||||
/**
|
||||
* Client side WebSocket physical connection.
|
||||
|
@ -53,17 +53,23 @@ public class WebSocketClientConnection extends AbstractWebSocketConnection
|
|||
this.masker = client.getMasker();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureFromExtensions(List<Extension> extensions)
|
||||
{
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
public DefaultWebSocketClient getClient()
|
||||
{
|
||||
return client;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress getLocalAddress()
|
||||
{
|
||||
return getEndPoint().getLocalAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress getRemoteAddress()
|
||||
{
|
||||
return getEndPoint().getRemoteAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose()
|
||||
{
|
||||
|
@ -83,14 +89,17 @@ public class WebSocketClientConnection extends AbstractWebSocketConnection
|
|||
}
|
||||
|
||||
@Override
|
||||
public Future<SendResult> outgoingFrame(WebSocketFrame frame) throws IOException
|
||||
public Future<SendResult> outgoingFrame(Frame frame) throws IOException
|
||||
{
|
||||
masker.setMask(frame);
|
||||
if (frame instanceof WebSocketFrame)
|
||||
{
|
||||
masker.setMask((WebSocketFrame)frame);
|
||||
}
|
||||
return super.outgoingFrame(frame);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIncoming(IncomingFrames incoming)
|
||||
public void setNextIncomingFrames(IncomingFrames incoming)
|
||||
{
|
||||
getParser().setIncomingFramesHandler(incoming);
|
||||
}
|
||||
|
|
|
@ -18,9 +18,9 @@
|
|||
|
||||
package org.eclipse.jetty.websocket.client.internal.mux;
|
||||
|
||||
import org.eclipse.jetty.websocket.common.WebSocketSession;
|
||||
import org.eclipse.jetty.websocket.common.extensions.mux.add.MuxAddClient;
|
||||
import org.eclipse.jetty.websocket.common.extensions.mux.op.MuxAddChannelResponse;
|
||||
import org.eclipse.jetty.websocket.common.io.WebSocketSession;
|
||||
|
||||
public class MuxClientAddHandler implements MuxAddClient
|
||||
{
|
||||
|
|
|
@ -53,15 +53,16 @@ import org.eclipse.jetty.websocket.api.WebSocketException;
|
|||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Extension;
|
||||
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.api.extensions.IncomingFrames;
|
||||
import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames;
|
||||
import org.eclipse.jetty.websocket.common.AcceptHash;
|
||||
import org.eclipse.jetty.websocket.common.CloseInfo;
|
||||
import org.eclipse.jetty.websocket.common.Generator;
|
||||
import org.eclipse.jetty.websocket.common.OpCode;
|
||||
import org.eclipse.jetty.websocket.common.Parser;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.extensions.WebSocketExtensionRegistry;
|
||||
import org.eclipse.jetty.websocket.common.io.IncomingFrames;
|
||||
import org.eclipse.jetty.websocket.common.io.OutgoingFrames;
|
||||
import org.eclipse.jetty.websocket.common.extensions.WebSocketExtensionFactory;
|
||||
import org.junit.Assert;
|
||||
|
||||
/**
|
||||
|
@ -81,7 +82,7 @@ public class BlockheadServer
|
|||
private final Parser parser;
|
||||
private final Generator generator;
|
||||
private final AtomicInteger parseCount;
|
||||
private final WebSocketExtensionRegistry extensionRegistry;
|
||||
private final WebSocketExtensionFactory extensionRegistry;
|
||||
|
||||
/** Set to true to disable timeouts (for debugging reasons) */
|
||||
private boolean debug = false;
|
||||
|
@ -100,7 +101,7 @@ public class BlockheadServer
|
|||
this.parser = new Parser(policy);
|
||||
this.parseCount = new AtomicInteger(0);
|
||||
this.generator = new Generator(policy,bufferPool,false);
|
||||
this.extensionRegistry = new WebSocketExtensionRegistry(policy,bufferPool);
|
||||
this.extensionRegistry = new WebSocketExtensionFactory(policy,bufferPool);
|
||||
}
|
||||
|
||||
public void close() throws IOException
|
||||
|
@ -141,7 +142,7 @@ public class BlockheadServer
|
|||
LOG.debug("Echo Frames [expecting {}]",expectedFrames);
|
||||
IncomingFramesCapture cap = readFrames(expectedFrames,timeoutUnit,timeoutDuration);
|
||||
// now echo them back.
|
||||
for (WebSocketFrame frame : cap.getFrames())
|
||||
for (Frame frame : cap.getFrames())
|
||||
{
|
||||
write(frame);
|
||||
}
|
||||
|
@ -197,7 +198,7 @@ public class BlockheadServer
|
|||
}
|
||||
|
||||
@Override
|
||||
public void incomingFrame(WebSocketFrame frame)
|
||||
public void incomingFrame(Frame frame)
|
||||
{
|
||||
LOG.debug("incoming({})",frame);
|
||||
int count = parseCount.incrementAndGet();
|
||||
|
@ -210,7 +211,7 @@ public class BlockheadServer
|
|||
}
|
||||
|
||||
@Override
|
||||
public Future<SendResult> outgoingFrame(WebSocketFrame frame) throws IOException
|
||||
public Future<SendResult> outgoingFrame(Frame frame) throws IOException
|
||||
{
|
||||
ByteBuffer buf = generator.generate(frame);
|
||||
if (LOG.isDebugEnabled())
|
||||
|
@ -220,7 +221,7 @@ public class BlockheadServer
|
|||
BufferUtil.writeTo(buf,out);
|
||||
out.flush();
|
||||
|
||||
if (frame.getOpCode() == OpCode.CLOSE)
|
||||
if (frame.getType().getOpCode() == OpCode.CLOSE)
|
||||
{
|
||||
disconnect();
|
||||
}
|
||||
|
@ -434,16 +435,16 @@ public class BlockheadServer
|
|||
getOutputStream().write(buf,offset,length);
|
||||
}
|
||||
|
||||
public void write(int b) throws IOException
|
||||
{
|
||||
getOutputStream().write(b);
|
||||
}
|
||||
|
||||
public void write(WebSocketFrame frame) throws IOException
|
||||
public void write(Frame frame) throws IOException
|
||||
{
|
||||
LOG.debug("write(Frame->{}) to {}",frame,outgoing);
|
||||
outgoing.outgoingFrame(frame);
|
||||
}
|
||||
|
||||
public void write(int b) throws IOException
|
||||
{
|
||||
getOutputStream().write(b);
|
||||
}
|
||||
}
|
||||
|
||||
private static final Logger LOG = Log.getLogger(BlockheadServer.class);
|
||||
|
|
|
@ -26,9 +26,10 @@ import org.eclipse.jetty.util.BufferUtil;
|
|||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketException;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.api.extensions.IncomingFrames;
|
||||
import org.eclipse.jetty.websocket.common.OpCode;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.io.IncomingFrames;
|
||||
import org.junit.Assert;
|
||||
|
||||
public class IncomingFramesCapture implements IncomingFrames
|
||||
|
@ -77,7 +78,7 @@ public class IncomingFramesCapture implements IncomingFrames
|
|||
System.err.printf("Captured %d incoming frames%n",frames.size());
|
||||
for (int i = 0; i < frames.size(); i++)
|
||||
{
|
||||
WebSocketFrame frame = frames.get(i);
|
||||
Frame frame = frames.get(i);
|
||||
System.err.printf("[%3d] %s%n",i,frame);
|
||||
System.err.printf(" %s%n",BufferUtil.toDetailString(frame.getPayload()));
|
||||
}
|
||||
|
@ -127,7 +128,7 @@ public class IncomingFramesCapture implements IncomingFrames
|
|||
}
|
||||
|
||||
@Override
|
||||
public void incomingFrame(WebSocketFrame frame)
|
||||
public void incomingFrame(Frame frame)
|
||||
{
|
||||
WebSocketFrame copy = new WebSocketFrame(frame);
|
||||
frames.add(copy);
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
<groupId>org.eclipse.jetty.drafts</groupId>
|
||||
<artifactId>javax.net.websocket-api</artifactId>
|
||||
<version>0.006.0.EDR-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.websocket</groupId>
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.common;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.FutureTask;
|
||||
|
||||
import javax.net.websocket.SendHandler;
|
||||
import javax.net.websocket.SendResult;
|
||||
|
||||
public class FailedFuture extends FutureTask<SendResult> implements Future<SendResult>
|
||||
{
|
||||
private static class FailedRunner implements Callable<SendResult>
|
||||
{
|
||||
private SendHandler completion;
|
||||
private Throwable error;
|
||||
|
||||
public FailedRunner(SendHandler completion, Throwable error)
|
||||
{
|
||||
this.completion = completion;
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SendResult call() throws Exception
|
||||
{
|
||||
SendResult result = new SendResult(this.error);
|
||||
if (completion != null)
|
||||
{
|
||||
completion.setResult(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public FailedFuture(SendHandler completion, Throwable error)
|
||||
{
|
||||
super(new FailedRunner(completion,error));
|
||||
run();
|
||||
}
|
||||
}
|
|
@ -29,6 +29,7 @@ import org.eclipse.jetty.websocket.api.ProtocolException;
|
|||
import org.eclipse.jetty.websocket.api.WebSocketBehavior;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Extension;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
|
||||
/**
|
||||
* Generating a frame in WebSocket land.
|
||||
|
@ -103,7 +104,7 @@ public class Generator
|
|||
this.validating = validating;
|
||||
}
|
||||
|
||||
public void assertFrameValid(WebSocketFrame frame)
|
||||
public void assertFrameValid(Frame frame)
|
||||
{
|
||||
if (!validating)
|
||||
{
|
||||
|
@ -131,7 +132,7 @@ public class Generator
|
|||
throw new ProtocolException("RSV3 not allowed to be set");
|
||||
}
|
||||
|
||||
if (frame.isControlFrame())
|
||||
if (frame.getType().isControl())
|
||||
{
|
||||
/*
|
||||
* RFC 6455 Section 5.5
|
||||
|
@ -153,7 +154,7 @@ public class Generator
|
|||
*
|
||||
* close frame payload is specially formatted which is checked in CloseInfo
|
||||
*/
|
||||
if (frame.getOpCode() == OpCode.CLOSE)
|
||||
if (frame.getType().getOpCode() == OpCode.CLOSE)
|
||||
{
|
||||
|
||||
ByteBuffer payload = frame.getPayload();
|
||||
|
@ -191,11 +192,25 @@ public class Generator
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* generate a byte buffer based on the frame being passed in
|
||||
*
|
||||
* bufferSize is determined by the length of the payload + 28 for frame overhead
|
||||
*
|
||||
* @param frame
|
||||
* @return
|
||||
*/
|
||||
public ByteBuffer generate(Frame frame)
|
||||
{
|
||||
int bufferSize = frame.getPayloadLength() + OVERHEAD;
|
||||
return generate(bufferSize,frame);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate, into a ByteBuffer, no more than bufferSize of contents from the frame. If the frame exceeds the bufferSize, then multiple calls to
|
||||
* {@link #generate(int, WebSocketFrame)} are required to obtain each window of ByteBuffer to complete the frame.
|
||||
*/
|
||||
public ByteBuffer generate(int windowSize, WebSocketFrame frame)
|
||||
public ByteBuffer generate(int windowSize, Frame frame)
|
||||
{
|
||||
if (windowSize < OVERHEAD)
|
||||
{
|
||||
|
@ -204,22 +219,7 @@ public class Generator
|
|||
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
StringBuilder dbg = new StringBuilder();
|
||||
dbg.append(behavior);
|
||||
dbg.append(" Generate.Frame[");
|
||||
dbg.append("opcode=").append(frame.getOpCode());
|
||||
dbg.append(",fin=").append(frame.isFin());
|
||||
dbg.append(",cont=").append(frame.isContinuation());
|
||||
dbg.append(",rsv1=").append(frame.isRsv1());
|
||||
dbg.append(",rsv2=").append(frame.isRsv2());
|
||||
dbg.append(",rsv3=").append(frame.isRsv3());
|
||||
dbg.append(",mask=").append(frame.isMasked());
|
||||
dbg.append(",payloadLength=").append(frame.getPayloadLength());
|
||||
dbg.append(",payloadStart=").append(frame.getPayloadStart());
|
||||
dbg.append(",remaining=").append(frame.remaining());
|
||||
dbg.append(",position=").append(frame.position());
|
||||
dbg.append(']');
|
||||
LOG.debug(dbg.toString());
|
||||
LOG.debug("{} Generate: {}",behavior,frame);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -260,6 +260,7 @@ public class Generator
|
|||
b |= 0x10;
|
||||
}
|
||||
|
||||
// NOTE: using .getOpCode() here, not .getType().getOpCode() for testing reasons
|
||||
byte opcode = frame.getOpCode();
|
||||
|
||||
if (frame.isContinuation())
|
||||
|
@ -366,20 +367,6 @@ public class Generator
|
|||
return buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* generate a byte buffer based on the frame being passed in
|
||||
*
|
||||
* bufferSize is determined by the length of the payload + 28 for frame overhead
|
||||
*
|
||||
* @param frame
|
||||
* @return
|
||||
*/
|
||||
public ByteBuffer generate(WebSocketFrame frame)
|
||||
{
|
||||
int bufferSize = frame.getPayloadLength() + OVERHEAD;
|
||||
return generate(bufferSize,frame);
|
||||
}
|
||||
|
||||
public boolean isRsv1InUse()
|
||||
{
|
||||
return rsv1InUse;
|
||||
|
|
|
@ -18,14 +18,33 @@
|
|||
|
||||
package org.eclipse.jetty.websocket.common;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.StatusCode;
|
||||
import org.eclipse.jetty.websocket.api.SuspendToken;
|
||||
import org.eclipse.jetty.websocket.common.io.OutgoingFrames;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.api.extensions.IncomingFrames;
|
||||
import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames;
|
||||
|
||||
public interface LogicalConnection extends OutgoingFrames
|
||||
public interface LogicalConnection extends OutgoingFrames, SuspendToken
|
||||
{
|
||||
/**
|
||||
* Perform a quick check that the connection input is open.
|
||||
*
|
||||
* @throws IOException
|
||||
* if the connection input is closed
|
||||
*/
|
||||
void assertInputOpen() throws IOException;
|
||||
|
||||
/**
|
||||
* Perform a quick check that the connection output is open.
|
||||
*
|
||||
* @throws IOException
|
||||
* if the connection output is closed
|
||||
*/
|
||||
void assertOutputOpen() throws IOException;
|
||||
|
||||
/**
|
||||
* Send a websocket Close frame, without a status code or reason.
|
||||
* <p>
|
||||
|
@ -55,12 +74,36 @@ public interface LogicalConnection extends OutgoingFrames
|
|||
void disconnect();
|
||||
|
||||
/**
|
||||
* Get the remote Address in use for this connection.
|
||||
* Get the local {@link InetSocketAddress} in use for this connection.
|
||||
* <p>
|
||||
* Note: Non-physical connections, like during the Mux extensions, or during unit testing can result in a InetSocketAddress on port 0 and/or on localhost.
|
||||
*
|
||||
* @return the remote address if available. (situations like mux extension and proxying makes this information unreliable)
|
||||
* @return the local address.
|
||||
*/
|
||||
InetSocketAddress getLocalAddress();
|
||||
|
||||
/**
|
||||
* The policy that the connection is running under.
|
||||
* @return the policy for the connection
|
||||
*/
|
||||
WebSocketPolicy getPolicy();
|
||||
|
||||
/**
|
||||
* Get the remote Address in use for this connection.
|
||||
* <p>
|
||||
* Note: Non-physical connections, like during the Mux extensions, or during unit testing can result in a InetSocketAddress on port 0 and/or on localhost.
|
||||
*
|
||||
* @return the remote address.
|
||||
*/
|
||||
InetSocketAddress getRemoteAddress();
|
||||
|
||||
/**
|
||||
* Get the Session for this connection
|
||||
*
|
||||
* @return the Session for this connection
|
||||
*/
|
||||
WebSocketSession getSession();
|
||||
|
||||
/**
|
||||
* Get the WebSocket connection State.
|
||||
*
|
||||
|
@ -106,6 +149,24 @@ public interface LogicalConnection extends OutgoingFrames
|
|||
*/
|
||||
void onCloseHandshake(boolean incoming, CloseInfo close);
|
||||
|
||||
/**
|
||||
* Set where the connection should send the incoming frames to.
|
||||
* <p>
|
||||
* Often this is from the Parser to the start of the extension stack, and eventually on to the session.
|
||||
*
|
||||
* @param incoming
|
||||
* the incoming frames handler
|
||||
*/
|
||||
void setNextIncomingFrames(IncomingFrames incoming);
|
||||
|
||||
/**
|
||||
* Set the session associated with this connection
|
||||
*
|
||||
* @param session
|
||||
* the session
|
||||
*/
|
||||
void setSession(WebSocketSession session);
|
||||
|
||||
/**
|
||||
* Suspend a the incoming read events on the connection.
|
||||
*
|
||||
|
|
|
@ -29,7 +29,8 @@ import org.eclipse.jetty.websocket.api.ProtocolException;
|
|||
import org.eclipse.jetty.websocket.api.WebSocketException;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Extension;
|
||||
import org.eclipse.jetty.websocket.common.io.IncomingFrames;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.api.extensions.IncomingFrames;
|
||||
import org.eclipse.jetty.websocket.common.io.payload.CloseReasonValidator;
|
||||
import org.eclipse.jetty.websocket.common.io.payload.DeMaskProcessor;
|
||||
import org.eclipse.jetty.websocket.common.io.payload.NoOpValidator;
|
||||
|
@ -59,7 +60,7 @@ public class Parser
|
|||
private int cursor = 0;
|
||||
// Frame
|
||||
private WebSocketFrame frame;
|
||||
private WebSocketFrame priorDataFrame;
|
||||
private Frame priorDataFrame;
|
||||
private byte lastDataOpcode;
|
||||
// payload specific
|
||||
private ByteBuffer payload;
|
||||
|
@ -170,7 +171,7 @@ public class Parser
|
|||
return rsv3InUse;
|
||||
}
|
||||
|
||||
protected void notifyFrame(final WebSocketFrame f)
|
||||
protected void notifyFrame(final Frame f)
|
||||
{
|
||||
if (LOG_FRAMES.isDebugEnabled())
|
||||
{
|
||||
|
|
|
@ -91,7 +91,7 @@ public class WebSocketFrame implements Frame
|
|||
private boolean rsv1 = false;
|
||||
private boolean rsv2 = false;
|
||||
private boolean rsv3 = false;
|
||||
private byte opcode = OpCode.UNDEFINED;
|
||||
protected byte opcode = OpCode.UNDEFINED;
|
||||
private boolean masked = false;
|
||||
private byte mask[];
|
||||
/**
|
||||
|
@ -141,10 +141,13 @@ public class WebSocketFrame implements Frame
|
|||
*/
|
||||
public WebSocketFrame(Frame frame)
|
||||
{
|
||||
if(frame instanceof WebSocketFrame) {
|
||||
if (frame instanceof WebSocketFrame)
|
||||
{
|
||||
WebSocketFrame wsf = (WebSocketFrame)frame;
|
||||
copy(wsf,wsf.data);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// Copy manually
|
||||
fin = frame.isFin();
|
||||
rsv1 = frame.isRsv1();
|
||||
|
@ -320,6 +323,7 @@ public class WebSocketFrame implements Frame
|
|||
return payloadLength;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPayloadStart()
|
||||
{
|
||||
if (data == null)
|
||||
|
@ -329,7 +333,7 @@ public class WebSocketFrame implements Frame
|
|||
return payloadStart;
|
||||
}
|
||||
|
||||
public SendHandler getSendResult()
|
||||
public SendHandler getSendHandler()
|
||||
{
|
||||
return sendHandler;
|
||||
}
|
||||
|
@ -340,6 +344,7 @@ public class WebSocketFrame implements Frame
|
|||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPayload()
|
||||
{
|
||||
return ((data != null) && (payloadLength > 0));
|
||||
|
@ -402,20 +407,26 @@ public class WebSocketFrame implements Frame
|
|||
return rsv3;
|
||||
}
|
||||
|
||||
public void notifySendHandler() {
|
||||
if(sendHandler == null) {
|
||||
return;
|
||||
}
|
||||
sendHandler.setResult(new SendResult(null));
|
||||
}
|
||||
|
||||
public void notifySendHandler(Throwable t) {
|
||||
if(sendHandler == null) {
|
||||
@Override
|
||||
public void notifySendFailed(Throwable t)
|
||||
{
|
||||
if (sendHandler == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
sendHandler.setResult(new SendResult(t));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifySendSuccess()
|
||||
{
|
||||
if (sendHandler == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
sendHandler.setResult(new SendResult(null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the position currently within the payload data.
|
||||
* <p>
|
||||
|
@ -439,6 +450,7 @@ public class WebSocketFrame implements Frame
|
|||
*
|
||||
* @return the number of bytes remaining in the payload data that has not yet been written out to Network ByteBuffers.
|
||||
*/
|
||||
@Override
|
||||
public int remaining()
|
||||
{
|
||||
if (data == null)
|
||||
|
@ -463,13 +475,13 @@ public class WebSocketFrame implements Frame
|
|||
continuation = false;
|
||||
}
|
||||
|
||||
public WebSocketFrame setContinuation(boolean continuation)
|
||||
public Frame setContinuation(boolean continuation)
|
||||
{
|
||||
this.continuation = continuation;
|
||||
return this;
|
||||
}
|
||||
|
||||
public WebSocketFrame setContinuationIndex(int continuationIndex)
|
||||
public Frame setContinuationIndex(int continuationIndex)
|
||||
{
|
||||
this.continuationIndex = continuationIndex;
|
||||
return this;
|
||||
|
@ -481,14 +493,14 @@ public class WebSocketFrame implements Frame
|
|||
return this;
|
||||
}
|
||||
|
||||
public WebSocketFrame setMask(byte[] maskingKey)
|
||||
public Frame setMask(byte[] maskingKey)
|
||||
{
|
||||
this.mask = maskingKey;
|
||||
this.masked = (mask != null);
|
||||
return this;
|
||||
}
|
||||
|
||||
public WebSocketFrame setMasked(boolean mask)
|
||||
public Frame setMasked(boolean mask)
|
||||
{
|
||||
this.masked = mask;
|
||||
return this;
|
||||
|
@ -640,6 +652,9 @@ public class WebSocketFrame implements Frame
|
|||
b.append(rsv3?'1':'.');
|
||||
b.append(",masked=").append(masked);
|
||||
b.append(",continuation=").append(continuation);
|
||||
b.append(",payloadStart=").append(getPayloadStart());
|
||||
b.append(",remaining=").append(remaining());
|
||||
b.append(",position=").append(position());
|
||||
if (sendHandler != null)
|
||||
{
|
||||
b.append(",sendHandler=").append(sendHandler);
|
||||
|
|
|
@ -0,0 +1,243 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.common;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Writer;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import javax.net.websocket.EncodeException;
|
||||
import javax.net.websocket.RemoteEndpoint;
|
||||
import javax.net.websocket.SendHandler;
|
||||
import javax.net.websocket.SendResult;
|
||||
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames;
|
||||
import org.eclipse.jetty.websocket.common.message.MessageOutputStream;
|
||||
import org.eclipse.jetty.websocket.common.message.MessageWriter;
|
||||
|
||||
/**
|
||||
* Endpoint for Writing messages to the Remote websocket.
|
||||
*/
|
||||
public class WebSocketRemoteEndpoint implements RemoteEndpoint<Object>
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(WebSocketRemoteEndpoint.class);
|
||||
public final LogicalConnection connection;
|
||||
public final OutgoingFrames outgoing;
|
||||
public MessageOutputStream stream;
|
||||
public MessageWriter writer;
|
||||
|
||||
public WebSocketRemoteEndpoint(LogicalConnection connection, OutgoingFrames outgoing)
|
||||
{
|
||||
if (connection == null)
|
||||
{
|
||||
throw new IllegalArgumentException("LogicalConnection cannot be null");
|
||||
}
|
||||
this.connection = connection;
|
||||
this.outgoing = outgoing;
|
||||
}
|
||||
|
||||
public InetSocketAddress getInetSocketAddress()
|
||||
{
|
||||
return connection.getRemoteAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream getSendStream() throws IOException
|
||||
{
|
||||
if (isWriterActive())
|
||||
{
|
||||
throw new IOException("Cannot get OutputStream while Writer is open");
|
||||
}
|
||||
|
||||
if (isStreamActive())
|
||||
{
|
||||
LOG.debug("getSendStream() -> (existing) {}",stream);
|
||||
return stream;
|
||||
}
|
||||
|
||||
stream = new MessageOutputStream(connection,outgoing);
|
||||
LOG.debug("getSendStream() -> (new) {}",stream);
|
||||
return stream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Writer getSendWriter() throws IOException
|
||||
{
|
||||
if (isStreamActive())
|
||||
{
|
||||
throw new IOException("Cannot get Writer while OutputStream is open");
|
||||
}
|
||||
|
||||
if (isWriterActive())
|
||||
{
|
||||
LOG.debug("getSendWriter() -> (existing) {}",writer);
|
||||
return writer;
|
||||
}
|
||||
|
||||
writer = new MessageWriter(connection,outgoing);
|
||||
LOG.debug("getSendWriter() -> (new) {}",writer);
|
||||
return writer;
|
||||
}
|
||||
|
||||
private boolean isStreamActive()
|
||||
{
|
||||
if (stream == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return !stream.isClosed();
|
||||
}
|
||||
|
||||
private boolean isWriterActive()
|
||||
{
|
||||
if (writer == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return !writer.isClosed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal
|
||||
*
|
||||
* @param frame
|
||||
* @return
|
||||
*/
|
||||
private Future<SendResult> sendAsyncFrame(WebSocketFrame frame)
|
||||
{
|
||||
try
|
||||
{
|
||||
connection.assertOutputOpen();
|
||||
return outgoing.outgoingFrame(frame);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
SendHandler handler = frame.getSendHandler();
|
||||
return new FailedFuture(handler, e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendBytes(ByteBuffer data) throws IOException
|
||||
{
|
||||
connection.assertOutputOpen();
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
LOG.debug("sendBytes({})",BufferUtil.toDetailString(data));
|
||||
}
|
||||
Frame frame = WebSocketFrame.binary().setPayload(data);
|
||||
outgoing.outgoingFrame(frame);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<SendResult> sendBytes(ByteBuffer data, SendHandler completion)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
LOG.debug("sendBytes({}, {})",BufferUtil.toDetailString(data),completion);
|
||||
}
|
||||
WebSocketFrame frame = WebSocketFrame.binary().setPayload(data);
|
||||
frame.setSendHandler(completion);
|
||||
return sendAsyncFrame(frame);
|
||||
}
|
||||
|
||||
private void sendFrame(Frame frame)
|
||||
{
|
||||
try
|
||||
{
|
||||
outgoing.outgoingFrame(frame);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
LOG.warn(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendObject(Object o) throws IOException, EncodeException
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<SendResult> sendObject(Object o, SendHandler handler)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPartialBytes(ByteBuffer partialByte, boolean isLast) throws IOException
|
||||
{
|
||||
Frame frame = WebSocketFrame.binary().setPayload(partialByte).setFin(isLast);
|
||||
outgoing.outgoingFrame(frame);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPartialString(String fragment, boolean isLast) throws IOException
|
||||
{
|
||||
Frame frame = WebSocketFrame.text(fragment).setFin(isLast);
|
||||
outgoing.outgoingFrame(frame);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPing(ByteBuffer applicationData)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
LOG.debug("Ping with {}",BufferUtil.toDetailString(applicationData));
|
||||
}
|
||||
Frame frame = WebSocketFrame.ping().setPayload(applicationData);
|
||||
sendFrame(frame);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPong(ByteBuffer applicationData)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
LOG.debug("Pong with {}",BufferUtil.toDetailString(applicationData));
|
||||
}
|
||||
Frame frame = WebSocketFrame.pong().setPayload(applicationData);
|
||||
sendFrame(frame);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendString(String text) throws IOException
|
||||
{
|
||||
Frame frame = WebSocketFrame.text(text);
|
||||
outgoing.outgoingFrame(frame);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<SendResult> sendString(String text, SendHandler completion)
|
||||
{
|
||||
WebSocketFrame frame = WebSocketFrame.text(text);
|
||||
frame.setSendHandler(completion);
|
||||
return sendAsyncFrame(frame);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,510 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.common;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URI;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import javax.net.websocket.ClientContainer;
|
||||
import javax.net.websocket.CloseReason;
|
||||
import javax.net.websocket.ContainerProvider;
|
||||
import javax.net.websocket.Encoder;
|
||||
import javax.net.websocket.MessageHandler;
|
||||
import javax.net.websocket.RemoteEndpoint;
|
||||
import javax.net.websocket.SendResult;
|
||||
import javax.net.websocket.Session;
|
||||
|
||||
import org.eclipse.jetty.util.MultiMap;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.UrlEncoded;
|
||||
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
||||
import org.eclipse.jetty.util.annotation.ManagedObject;
|
||||
import org.eclipse.jetty.util.component.ContainerLifeCycle;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.api.SuspendToken;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketConnection;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketException;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Extension;
|
||||
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
|
||||
import org.eclipse.jetty.websocket.api.extensions.ExtensionFactory;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.api.extensions.IncomingFrames;
|
||||
import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames;
|
||||
import org.eclipse.jetty.websocket.common.events.EventDriver;
|
||||
|
||||
@ManagedObject
|
||||
public class WebSocketSession extends ContainerLifeCycle implements Session<Object>, WebSocketConnection, IncomingFrames
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(WebSocketSession.class);
|
||||
private final URI requestURI;
|
||||
private final EventDriver websocket;
|
||||
private final LogicalConnection connection;
|
||||
private Set<MessageHandler> messageHandlers = new HashSet<>();
|
||||
private List<Encoder> encoders = new ArrayList<>();
|
||||
private ExtensionFactory extensionFactory;
|
||||
private boolean active = false;
|
||||
private long maximumMessageSize;
|
||||
private long inactiveTime;
|
||||
private List<String> negotiatedExtensions = new ArrayList<>();
|
||||
private String protocolVersion;
|
||||
private String negotiatedSubprotocol;
|
||||
private long timeout;
|
||||
private Map<String, String[]> parameterMap = new HashMap<>();
|
||||
private List<ExtensionConfig> extensionConfigs = new ArrayList<>();
|
||||
private WebSocketRemoteEndpoint remote;
|
||||
private IncomingFrames incomingHandler;
|
||||
private OutgoingFrames outgoingHandler;
|
||||
private WebSocketPolicy policy;
|
||||
|
||||
public WebSocketSession(URI requestURI, EventDriver websocket, LogicalConnection connection)
|
||||
{
|
||||
if (requestURI == null)
|
||||
{
|
||||
throw new RuntimeException("Request URI cannot be null");
|
||||
}
|
||||
|
||||
this.requestURI = requestURI;
|
||||
this.websocket = websocket;
|
||||
this.connection = connection;
|
||||
this.outgoingHandler = connection;
|
||||
this.incomingHandler = websocket;
|
||||
|
||||
// Get the parameter map (use the jetty MultiMap to do this right)
|
||||
MultiMap<String> params = new MultiMap<>();
|
||||
String query = requestURI.getQuery();
|
||||
if (StringUtil.isNotBlank(query))
|
||||
{
|
||||
UrlEncoded.decodeTo(query,params,StringUtil.__UTF8);
|
||||
}
|
||||
|
||||
for (String name : params.keySet())
|
||||
{
|
||||
List<String> valueList = params.getValues(name);
|
||||
String valueArr[] = new String[valueList.size()];
|
||||
valueArr = valueList.toArray(valueArr);
|
||||
parameterMap.put(name,valueArr);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addMessageHandler(MessageHandler listener)
|
||||
{
|
||||
messageHandlers.add(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException
|
||||
{
|
||||
connection.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close(CloseReason closeStatus) throws IOException
|
||||
{
|
||||
connection.close(closeStatus.getCloseCode().getCode(),closeStatus.getReasonPhrase());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close(int statusCode, String reason)
|
||||
{
|
||||
connection.close(statusCode,reason);
|
||||
}
|
||||
|
||||
public LogicalConnection getConnection()
|
||||
{
|
||||
return connection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientContainer getContainer()
|
||||
{
|
||||
return ContainerProvider.getClientContainer();
|
||||
}
|
||||
|
||||
public ExtensionFactory getExtensionFactory()
|
||||
{
|
||||
return extensionFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getInactiveTime()
|
||||
{
|
||||
return inactiveTime;
|
||||
}
|
||||
|
||||
@ManagedAttribute(readonly = true)
|
||||
public IncomingFrames getIncomingHandler()
|
||||
{
|
||||
return incomingHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress getLocalAddress()
|
||||
{
|
||||
return connection.getLocalAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getMaximumMessageSize()
|
||||
{
|
||||
return maximumMessageSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<MessageHandler> getMessageHandlers()
|
||||
{
|
||||
return Collections.unmodifiableSet(messageHandlers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNegotiatedExtensions()
|
||||
{
|
||||
return negotiatedExtensions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNegotiatedSubprotocol()
|
||||
{
|
||||
return negotiatedSubprotocol;
|
||||
}
|
||||
|
||||
@ManagedAttribute(readonly = true)
|
||||
public OutgoingFrames getOutgoingHandler()
|
||||
{
|
||||
return outgoingHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String[]> getParameterMap()
|
||||
{
|
||||
return parameterMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebSocketPolicy getPolicy()
|
||||
{
|
||||
return policy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProtocolVersion()
|
||||
{
|
||||
return protocolVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQueryString()
|
||||
{
|
||||
return getRequestURI().getQuery();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RemoteEndpoint<Object> getRemote()
|
||||
{
|
||||
if (!isOpen())
|
||||
{
|
||||
throw new WebSocketException("Session has not been opened yet");
|
||||
}
|
||||
return remote;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RemoteEndpoint<Object> getRemote(Class<Object> c)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress getRemoteAddress()
|
||||
{
|
||||
return remote.getInetSocketAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI getRequestURI()
|
||||
{
|
||||
return requestURI;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSubProtocol()
|
||||
{
|
||||
return getNegotiatedSubprotocol();
|
||||
}
|
||||
|
||||
/**
|
||||
* The timeout in seconds
|
||||
*/
|
||||
@Override
|
||||
public long getTimeout()
|
||||
{
|
||||
return timeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Incoming Errors from Parser
|
||||
*/
|
||||
@Override
|
||||
public void incomingError(WebSocketException e)
|
||||
{
|
||||
if (connection.isInputClosed())
|
||||
{
|
||||
return; // input is closed
|
||||
}
|
||||
// Forward Errors to User WebSocket Object
|
||||
websocket.incomingError(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Incoming Raw Frames from Parser
|
||||
*/
|
||||
@Override
|
||||
public void incomingFrame(Frame frame)
|
||||
{
|
||||
if (connection.isInputClosed())
|
||||
{
|
||||
return; // input is closed
|
||||
}
|
||||
|
||||
// Forward Frames Through Extension List
|
||||
incomingHandler.incomingFrame(frame);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive()
|
||||
{
|
||||
return active;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOpen()
|
||||
{
|
||||
return isActive();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSecure()
|
||||
{
|
||||
return getRequestURI().getScheme().equalsIgnoreCase("wss");
|
||||
}
|
||||
|
||||
/**
|
||||
* Open/Activate the session
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public void open()
|
||||
{
|
||||
if (isOpen())
|
||||
{
|
||||
throw new WebSocketException("Cannot Open WebSocketSession, Already open");
|
||||
}
|
||||
|
||||
// Initialize extensions
|
||||
LOG.debug("Extension Configs={}",extensionConfigs);
|
||||
List<Extension> extensions = new ArrayList<>();
|
||||
for (ExtensionConfig config : extensionConfigs)
|
||||
{
|
||||
Extension ext = extensionFactory.newInstance(config);
|
||||
extensions.add(ext);
|
||||
LOG.debug("Adding Extension: {}",ext);
|
||||
}
|
||||
|
||||
// Wire up Extensions
|
||||
if (extensions.size() > 0)
|
||||
{
|
||||
Iterator<Extension> extIter;
|
||||
|
||||
// Connect outgoings
|
||||
extIter = extensions.iterator();
|
||||
while (extIter.hasNext())
|
||||
{
|
||||
Extension ext = extIter.next();
|
||||
ext.setNextOutgoingFrames(outgoingHandler);
|
||||
outgoingHandler = ext;
|
||||
}
|
||||
|
||||
// Connect incomings
|
||||
Collections.reverse(extensions);
|
||||
extIter = extensions.iterator();
|
||||
while (extIter.hasNext())
|
||||
{
|
||||
Extension ext = extIter.next();
|
||||
ext.setNextIncomingFrames(incomingHandler);
|
||||
incomingHandler = ext;
|
||||
}
|
||||
}
|
||||
|
||||
addBean(incomingHandler);
|
||||
addBean(outgoingHandler);
|
||||
|
||||
// Connect remote
|
||||
remote = new WebSocketRemoteEndpoint(connection,outgoingHandler);
|
||||
|
||||
// Activate Session
|
||||
this.active = true;
|
||||
|
||||
// Open WebSocket
|
||||
websocket.setSession(this);
|
||||
websocket.onConnect();
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
LOG.debug("{}",dump());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ping(ByteBuffer buf) throws IOException
|
||||
{
|
||||
remote.sendPing(buf);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeMessageHandler(MessageHandler listener)
|
||||
{
|
||||
messageHandlers.remove(listener);
|
||||
}
|
||||
|
||||
public void setActive(boolean active)
|
||||
{
|
||||
this.active = active;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEncoders(List<Encoder> encoders)
|
||||
{
|
||||
this.encoders.clear();
|
||||
if (encoders != null)
|
||||
{
|
||||
encoders.addAll(encoders);
|
||||
}
|
||||
}
|
||||
|
||||
public void setExtensionFactory(ExtensionFactory extensionFactory)
|
||||
{
|
||||
this.extensionFactory = extensionFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaximumMessageSize(long length)
|
||||
{
|
||||
this.maximumMessageSize = length;
|
||||
}
|
||||
|
||||
public void setNegotiatedExtensionConfigs(List<ExtensionConfig> extensions)
|
||||
{
|
||||
this.negotiatedExtensions.clear();
|
||||
this.extensionConfigs.clear();
|
||||
|
||||
for (ExtensionConfig config : extensions)
|
||||
{
|
||||
this.extensionConfigs.add(config);
|
||||
this.negotiatedExtensions.add(config.getParameterizedName());
|
||||
}
|
||||
}
|
||||
|
||||
public void setNegotiatedExtensions(List<String> negotiatedExtensions)
|
||||
{
|
||||
this.negotiatedExtensions = negotiatedExtensions;
|
||||
|
||||
this.extensionConfigs.clear();
|
||||
for (String negotiatedExtension : negotiatedExtensions)
|
||||
{
|
||||
this.extensionConfigs.add(ExtensionConfig.parse(negotiatedExtension));
|
||||
}
|
||||
}
|
||||
|
||||
public void setNegotiatedSubprotocol(String negotiatedSubprotocol)
|
||||
{
|
||||
this.negotiatedSubprotocol = negotiatedSubprotocol;
|
||||
}
|
||||
|
||||
public void setOutgoingHandler(OutgoingFrames outgoing)
|
||||
{
|
||||
this.outgoingHandler = outgoing;
|
||||
}
|
||||
|
||||
public void setPolicy(WebSocketPolicy policy)
|
||||
{
|
||||
this.policy = policy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the timeout in seconds
|
||||
*/
|
||||
@Override
|
||||
public void setTimeout(long seconds)
|
||||
{
|
||||
this.timeout = seconds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SuspendToken suspend()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("WebSocketSession[");
|
||||
builder.append("websocket=").append(websocket);
|
||||
builder.append(",connection=").append(connection);
|
||||
builder.append(",remote=").append(remote);
|
||||
builder.append(",incoming=").append(incomingHandler);
|
||||
builder.append(",outgoing=").append(outgoingHandler);
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<SendResult> write(byte[] buf, int offset, int len) throws IOException
|
||||
{
|
||||
return remote.sendBytes(ByteBuffer.wrap(buf,offset,len),null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<SendResult> write(ByteBuffer buffer) throws IOException
|
||||
{
|
||||
return remote.sendBytes(buffer,null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<SendResult> write(String message) throws IOException
|
||||
{
|
||||
return remote.sendString(message,null);
|
||||
}
|
||||
}
|
|
@ -31,17 +31,16 @@ import org.eclipse.jetty.websocket.api.StatusCode;
|
|||
import org.eclipse.jetty.websocket.api.WebSocketException;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.api.extensions.IncomingFrames;
|
||||
import org.eclipse.jetty.websocket.common.CloseInfo;
|
||||
import org.eclipse.jetty.websocket.common.OpCode;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.extensions.AbstractJettyFrameHandler;
|
||||
import org.eclipse.jetty.websocket.common.io.IncomingFrames;
|
||||
import org.eclipse.jetty.websocket.common.io.WebSocketSession;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketSession;
|
||||
|
||||
/**
|
||||
* EventDriver is the main interface between the User's WebSocket POJO and the internal jetty implementation of WebSocket.
|
||||
*/
|
||||
public abstract class EventDriver extends AbstractJettyFrameHandler implements IncomingFrames
|
||||
public abstract class EventDriver implements IncomingFrames
|
||||
{
|
||||
protected final Logger LOG;
|
||||
protected final WebSocketPolicy policy;
|
||||
|
@ -50,7 +49,6 @@ public abstract class EventDriver extends AbstractJettyFrameHandler implements I
|
|||
|
||||
public EventDriver(WebSocketPolicy policy, Object websocket)
|
||||
{
|
||||
super(null);
|
||||
this.policy = policy;
|
||||
this.websocket = websocket;
|
||||
this.LOG = Log.getLogger(websocket.getClass());
|
||||
|
@ -66,12 +64,6 @@ public abstract class EventDriver extends AbstractJettyFrameHandler implements I
|
|||
return session;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleJettyFrame(WebSocketFrame frame)
|
||||
{
|
||||
incomingFrame(frame);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void incomingError(WebSocketException e)
|
||||
{
|
||||
|
@ -90,7 +82,7 @@ public abstract class EventDriver extends AbstractJettyFrameHandler implements I
|
|||
}
|
||||
|
||||
@Override
|
||||
public void incomingFrame(WebSocketFrame frame)
|
||||
public void incomingFrame(Frame frame)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
|
@ -101,7 +93,7 @@ public abstract class EventDriver extends AbstractJettyFrameHandler implements I
|
|||
|
||||
try
|
||||
{
|
||||
switch (frame.getOpCode())
|
||||
switch (frame.getType().getOpCode())
|
||||
{
|
||||
case OpCode.CLOSE:
|
||||
{
|
||||
|
@ -115,27 +107,21 @@ public abstract class EventDriver extends AbstractJettyFrameHandler implements I
|
|||
session.close(close.getStatusCode(),close.getReason());
|
||||
|
||||
// process handshake
|
||||
session.onCloseHandshake(true,close);
|
||||
session.getConnection().onCloseHandshake(true,close);
|
||||
|
||||
return;
|
||||
}
|
||||
case OpCode.PING:
|
||||
{
|
||||
WebSocketFrame pong = new WebSocketFrame(OpCode.PONG);
|
||||
ByteBuffer pongBuf = ByteBuffer.allocate(frame.getPayloadLength());
|
||||
if (frame.getPayloadLength() > 0)
|
||||
{
|
||||
// Copy payload
|
||||
ByteBuffer pongBuf = ByteBuffer.allocate(frame.getPayloadLength());
|
||||
BufferUtil.clearToFill(pongBuf);
|
||||
BufferUtil.put(frame.getPayload(),pongBuf);
|
||||
BufferUtil.flipToFlush(pongBuf,0);
|
||||
pong.setPayload(pongBuf);
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
LOG.debug("Pong with {}",BufferUtil.toDetailString(pongBuf));
|
||||
}
|
||||
}
|
||||
session.outgoingFrame(pong);
|
||||
session.getRemote().sendPong(pongBuf);
|
||||
break;
|
||||
}
|
||||
case OpCode.BINARY:
|
||||
|
|
|
@ -18,20 +18,37 @@
|
|||
|
||||
package org.eclipse.jetty.websocket.common.extensions;
|
||||
|
||||
import java.util.Map;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import javax.net.websocket.SendResult;
|
||||
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketConnection;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketException;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Extension;
|
||||
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.api.extensions.IncomingFrames;
|
||||
import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames;
|
||||
import org.eclipse.jetty.websocket.common.LogicalConnection;
|
||||
|
||||
public abstract class AbstractExtension implements Extension
|
||||
{
|
||||
private final Logger log;
|
||||
private WebSocketPolicy policy;
|
||||
private ByteBufferPool bufferPool;
|
||||
private ExtensionConfig config;
|
||||
private WebSocketConnection connection;
|
||||
private LogicalConnection connection;
|
||||
private OutgoingFrames nextOutgoing;
|
||||
private IncomingFrames nextIncoming;
|
||||
|
||||
public AbstractExtension()
|
||||
{
|
||||
log = Log.getLogger(this.getClass());
|
||||
}
|
||||
|
||||
public ByteBufferPool getBufferPool()
|
||||
{
|
||||
|
@ -44,7 +61,7 @@ public abstract class AbstractExtension implements Extension
|
|||
return config;
|
||||
}
|
||||
|
||||
public WebSocketConnection getConnection()
|
||||
public LogicalConnection getConnection()
|
||||
{
|
||||
return connection;
|
||||
}
|
||||
|
@ -55,17 +72,17 @@ public abstract class AbstractExtension implements Extension
|
|||
return config.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getParameters()
|
||||
{
|
||||
return config.getParameters();
|
||||
}
|
||||
|
||||
public WebSocketPolicy getPolicy()
|
||||
{
|
||||
return policy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void incomingError(WebSocketException e)
|
||||
{
|
||||
nextIncomingError(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to indicate that the extension makes use of the RSV1 bit of the base websocket framing.
|
||||
* <p>
|
||||
|
@ -122,6 +139,23 @@ public abstract class AbstractExtension implements Extension
|
|||
return false;
|
||||
}
|
||||
|
||||
protected void nextIncomingError(WebSocketException e)
|
||||
{
|
||||
this.nextIncoming.incomingError(e);
|
||||
}
|
||||
|
||||
protected void nextIncomingFrame(Frame frame)
|
||||
{
|
||||
log.debug("nextIncomingFrame({})",frame);
|
||||
this.nextIncoming.incomingFrame(frame);
|
||||
}
|
||||
|
||||
protected Future<SendResult> nextOutgoingFrame(Frame frame) throws IOException
|
||||
{
|
||||
log.debug("nextOutgoingFrame({})",frame);
|
||||
return this.nextOutgoing.outgoingFrame(frame);
|
||||
}
|
||||
|
||||
public void setBufferPool(ByteBufferPool bufferPool)
|
||||
{
|
||||
this.bufferPool = bufferPool;
|
||||
|
@ -132,11 +166,23 @@ public abstract class AbstractExtension implements Extension
|
|||
this.config = config;
|
||||
}
|
||||
|
||||
public void setConnection(WebSocketConnection connection)
|
||||
public void setConnection(LogicalConnection connection)
|
||||
{
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNextIncomingFrames(IncomingFrames nextIncoming)
|
||||
{
|
||||
this.nextIncoming = nextIncoming;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNextOutgoingFrames(OutgoingFrames nextOutgoing)
|
||||
{
|
||||
this.nextOutgoing = nextOutgoing;
|
||||
}
|
||||
|
||||
public void setPolicy(WebSocketPolicy policy)
|
||||
{
|
||||
this.policy = policy;
|
||||
|
|
|
@ -1,75 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.common.extensions;
|
||||
|
||||
import javax.net.websocket.extensions.FrameHandler;
|
||||
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
|
||||
public abstract class AbstractJettyFrameHandler extends FrameHandler
|
||||
{
|
||||
private Logger log;
|
||||
|
||||
public AbstractJettyFrameHandler(FrameHandler nextHandler)
|
||||
{
|
||||
super(nextHandler);
|
||||
log = Log.getLogger(this.getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Incoming for javax.net.websocket based frames.
|
||||
* <p>
|
||||
* Note: As of 006EDR of the JavaWebSocket API is, the {@link javax.net.websocket.extensions.Frame} interface is insufficient to handle the intricacies of
|
||||
* Extensions. The implementations of {@link javax.net.websocket.extensions.Extension} within Jetty will attempt to cast to
|
||||
* {@link org.eclipse.jetty.websocket.common.WebSocketFrame} to handle only jetty managed/created WebSocketFrames.
|
||||
*/
|
||||
@Override
|
||||
public final void handleFrame(javax.net.websocket.extensions.Frame f)
|
||||
{
|
||||
if (f instanceof WebSocketFrame)
|
||||
{
|
||||
handleJettyFrame((WebSocketFrame)f);
|
||||
}
|
||||
else
|
||||
{
|
||||
// [006EDR]
|
||||
throw new RuntimeException("Unsupported, Frame type [" + f.getClass().getName() + "] must be an instanceof [" + WebSocketFrame.class.getName()
|
||||
+ "]");
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void handleJettyFrame(WebSocketFrame frame);
|
||||
|
||||
protected void nextJettyHandler(WebSocketFrame frame)
|
||||
{
|
||||
FrameHandler next = getNextHandler();
|
||||
if (next == null)
|
||||
{
|
||||
log.debug("No next handler (ending chain) {}",frame);
|
||||
return;
|
||||
}
|
||||
if (log.isDebugEnabled())
|
||||
{
|
||||
log.debug("nextHandler({}) -> {}",frame,next);
|
||||
}
|
||||
next.handleFrame(frame);
|
||||
}
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.common.extensions;
|
||||
|
||||
import javax.net.websocket.extensions.FrameHandler;
|
||||
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketException;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.io.IncomingFrames;
|
||||
|
||||
/**
|
||||
* Route jetty internal frames into extension {@link FrameHandler} concept.
|
||||
*/
|
||||
public class IncomingFrameHandler implements IncomingFrames
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(IncomingFrameHandler.class);
|
||||
private FrameHandler extHandler;
|
||||
|
||||
public IncomingFrameHandler(FrameHandler nextHandler)
|
||||
{
|
||||
this.extHandler = nextHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void incomingError(WebSocketException e)
|
||||
{
|
||||
LOG.info("Not able to forward error into extension stack",e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void incomingFrame(WebSocketFrame frame)
|
||||
{
|
||||
extHandler.handleFrame(frame);
|
||||
}
|
||||
}
|
|
@ -25,23 +25,29 @@ import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
|||
import org.eclipse.jetty.websocket.api.extensions.Extension;
|
||||
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
|
||||
import org.eclipse.jetty.websocket.api.extensions.ExtensionFactory;
|
||||
import org.eclipse.jetty.websocket.common.extensions.compress.FrameCompressionExtension;
|
||||
import org.eclipse.jetty.websocket.common.extensions.compress.MessageCompressionExtension;
|
||||
import org.eclipse.jetty.websocket.common.extensions.fragment.FragmentExtension;
|
||||
import org.eclipse.jetty.websocket.common.extensions.identity.IdentityExtension;
|
||||
|
||||
public class WebSocketExtensionRegistry extends ExtensionFactory
|
||||
public class WebSocketExtensionFactory extends ExtensionFactory
|
||||
{
|
||||
private WebSocketPolicy policy;
|
||||
private ByteBufferPool bufferPool;
|
||||
|
||||
public WebSocketExtensionRegistry(WebSocketPolicy policy, ByteBufferPool bufferPool)
|
||||
public WebSocketExtensionFactory(WebSocketPolicy policy, ByteBufferPool bufferPool)
|
||||
{
|
||||
super();
|
||||
this.policy = policy;
|
||||
this.bufferPool = bufferPool;
|
||||
|
||||
// FIXME this.registry.put("identity",IdentityExtension.class);
|
||||
// FIXME this.registry.put("fragment",FragmentExtension.class);
|
||||
// FIXME this.registry.put("x-webkit-deflate-frame",WebkitDeflateFrameExtension.class);
|
||||
// FIXME this.registry.put("permessage-compress",PerMessageCompressionExtension.class);
|
||||
register("identity",IdentityExtension.class);
|
||||
register("fragment",FragmentExtension.class);
|
||||
register("x-webkit-deflate-frame",FrameCompressionExtension.class);
|
||||
register("permessage-compress",MessageCompressionExtension.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Extension newInstance(ExtensionConfig config)
|
||||
{
|
||||
if (config == null)
|
||||
|
@ -55,14 +61,12 @@ public class WebSocketExtensionRegistry extends ExtensionFactory
|
|||
return null;
|
||||
}
|
||||
|
||||
Extension registeredExt = getExtension(name);
|
||||
if (registeredExt == null)
|
||||
Class<? extends Extension> extClass = getExtension(name);
|
||||
if (extClass == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Class<? extends Extension> extClass = registeredExt.getClass();
|
||||
|
||||
try
|
||||
{
|
||||
Extension ext = extClass.newInstance();
|
|
@ -1,81 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.common.extensions.compress;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import javax.net.websocket.extensions.FrameHandler;
|
||||
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.extensions.AbstractJettyFrameHandler;
|
||||
|
||||
/**
|
||||
* Compress individual data frames.
|
||||
*/
|
||||
public class CompressFrameHandler extends AbstractJettyFrameHandler
|
||||
{
|
||||
private final CompressionMethod method;
|
||||
private final ByteBufferPool bufferPool;
|
||||
|
||||
public CompressFrameHandler(FrameHandler outgoing, DeflateCompressionMethod method, ByteBufferPool bufferPool)
|
||||
{
|
||||
super(outgoing);
|
||||
this.method = method;
|
||||
this.bufferPool = bufferPool;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleJettyFrame(WebSocketFrame frame)
|
||||
{
|
||||
if (frame.getType().isControl())
|
||||
{
|
||||
// skip, cannot compress control frames.
|
||||
nextJettyHandler(frame);
|
||||
return;
|
||||
}
|
||||
|
||||
ByteBuffer data = frame.getPayload();
|
||||
try
|
||||
{
|
||||
// deflate data
|
||||
method.compress().input(data);
|
||||
while (!method.compress().isDone())
|
||||
{
|
||||
ByteBuffer buf = method.compress().process();
|
||||
WebSocketFrame out = new WebSocketFrame(frame).setPayload(buf);
|
||||
out.setRsv1(true);
|
||||
if (!method.compress().isDone())
|
||||
{
|
||||
out.setFin(false);
|
||||
}
|
||||
|
||||
nextJettyHandler(out);
|
||||
}
|
||||
|
||||
// reset on every frame.
|
||||
method.compress().end();
|
||||
}
|
||||
finally
|
||||
{
|
||||
// free original data buffer
|
||||
bufferPool.release(data);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,88 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.common.extensions.compress;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import javax.net.websocket.extensions.FrameHandler;
|
||||
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.extensions.AbstractJettyFrameHandler;
|
||||
|
||||
/**
|
||||
* Compress entire message (regardless of number of frames).
|
||||
*/
|
||||
public class CompressMessageHandler extends AbstractJettyFrameHandler
|
||||
{
|
||||
private final CompressionMethod method;
|
||||
private final ByteBufferPool bufferPool;
|
||||
|
||||
public CompressMessageHandler(FrameHandler nextHandler, CompressionMethod method, ByteBufferPool bufferPool)
|
||||
{
|
||||
super(nextHandler);
|
||||
this.method = method;
|
||||
this.bufferPool = bufferPool;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleJettyFrame(WebSocketFrame frame)
|
||||
{
|
||||
if (frame.getType().isControl())
|
||||
{
|
||||
// skip, cannot compress control frames.
|
||||
nextJettyHandler(frame);
|
||||
return;
|
||||
}
|
||||
|
||||
ByteBuffer data = frame.getPayload();
|
||||
try
|
||||
{
|
||||
// deflate data
|
||||
method.compress().input(data);
|
||||
while (!method.compress().isDone())
|
||||
{
|
||||
ByteBuffer buf = method.compress().process();
|
||||
WebSocketFrame out = new WebSocketFrame(frame).setPayload(buf);
|
||||
out.setRsv1(true);
|
||||
if (!method.compress().isDone())
|
||||
{
|
||||
out.setFin(false);
|
||||
nextJettyHandler(out);
|
||||
}
|
||||
else
|
||||
{
|
||||
nextJettyHandler(out);
|
||||
}
|
||||
}
|
||||
|
||||
// reset only at end of message
|
||||
if (frame.isFin())
|
||||
{
|
||||
method.compress().end();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
// free original data buffer
|
||||
bufferPool.release(data);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,84 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.common.extensions.compress;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import javax.net.websocket.extensions.FrameHandler;
|
||||
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.extensions.AbstractJettyFrameHandler;
|
||||
|
||||
/**
|
||||
* Handler for Decompress of individual Data frames.
|
||||
*/
|
||||
public class DecompressFrameHandler extends AbstractJettyFrameHandler
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(DecompressFrameHandler.class);
|
||||
private final CompressionMethod method;
|
||||
private final ByteBufferPool bufferPool;
|
||||
|
||||
public DecompressFrameHandler(FrameHandler incoming, DeflateCompressionMethod method, ByteBufferPool bufferPool)
|
||||
{
|
||||
super(incoming);
|
||||
this.method = method;
|
||||
this.bufferPool = bufferPool;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleJettyFrame(WebSocketFrame frame)
|
||||
{
|
||||
if (frame.getType().isControl() || !frame.isRsv1())
|
||||
{
|
||||
// Cannot modify incoming control frames or ones with RSV1 set.
|
||||
nextJettyHandler(frame);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG.debug("Decompressing Frame: {}",frame);
|
||||
|
||||
ByteBuffer data = frame.getPayload();
|
||||
try
|
||||
{
|
||||
method.decompress().input(data);
|
||||
while (!method.decompress().isDone())
|
||||
{
|
||||
ByteBuffer uncompressed = method.decompress().process();
|
||||
WebSocketFrame out = new WebSocketFrame(frame).setPayload(uncompressed);
|
||||
if (!method.decompress().isDone())
|
||||
{
|
||||
out.setFin(false);
|
||||
}
|
||||
out.setRsv1(false); // Unset RSV1 on decompressed frame
|
||||
nextJettyHandler(out);
|
||||
}
|
||||
|
||||
// reset on every frame.
|
||||
method.decompress().end();
|
||||
}
|
||||
finally
|
||||
{
|
||||
// release original buffer (no longer needed)
|
||||
bufferPool.release(data);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,86 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.common.extensions.compress;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import javax.net.websocket.extensions.FrameHandler;
|
||||
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.extensions.AbstractJettyFrameHandler;
|
||||
|
||||
/**
|
||||
* Decompress entire message (regardless of number of frames)
|
||||
*/
|
||||
public class DecompressMessageHandler extends AbstractJettyFrameHandler
|
||||
{
|
||||
private CompressionMethod method;
|
||||
private final ByteBufferPool bufferPool;
|
||||
|
||||
public DecompressMessageHandler(FrameHandler nextHandler, CompressionMethod method, ByteBufferPool bufferPool)
|
||||
{
|
||||
super(nextHandler);
|
||||
this.method = method;
|
||||
this.bufferPool = bufferPool;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleJettyFrame(WebSocketFrame frame)
|
||||
{
|
||||
if (frame.getType().isControl() || !frame.isRsv1())
|
||||
{
|
||||
// Cannot modify incoming control frames or ones with RSV1 set.
|
||||
nextJettyHandler(frame);
|
||||
return;
|
||||
}
|
||||
|
||||
ByteBuffer data = frame.getPayload();
|
||||
try
|
||||
{
|
||||
method.decompress().input(data);
|
||||
while (!method.decompress().isDone())
|
||||
{
|
||||
ByteBuffer uncompressed = method.decompress().process();
|
||||
if (uncompressed == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
WebSocketFrame out = new WebSocketFrame(frame).setPayload(uncompressed);
|
||||
if (!method.decompress().isDone())
|
||||
{
|
||||
out.setFin(false);
|
||||
}
|
||||
out.setRsv1(false); // Unset RSV1 on decompressed frame
|
||||
nextJettyHandler(out);
|
||||
}
|
||||
|
||||
// reset only at the end of a message.
|
||||
if (frame.isFin())
|
||||
{
|
||||
method.decompress().end();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
// release original buffer (no longer needed)
|
||||
bufferPool.release(data);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,151 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.common.extensions.compress;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import javax.net.websocket.SendResult;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.extensions.AbstractExtension;
|
||||
|
||||
/**
|
||||
* Implementation of the <a href="https://tools.ietf.org/id/draft-tyoshino-hybi-websocket-perframe-deflate-05.txt">x-webkit-deflate-frame</a> extension seen out
|
||||
* in the wild.
|
||||
*/
|
||||
public class FrameCompressionExtension extends AbstractExtension
|
||||
{
|
||||
private DeflateCompressionMethod method;
|
||||
|
||||
@Override
|
||||
public void incomingFrame(Frame frame)
|
||||
{
|
||||
if (frame.getType().isControl() || !frame.isRsv1())
|
||||
{
|
||||
// Cannot modify incoming control frames or ones with RSV1 set.
|
||||
nextIncomingFrame(frame);
|
||||
return;
|
||||
}
|
||||
|
||||
ByteBuffer data = frame.getPayload();
|
||||
try
|
||||
{
|
||||
method.decompress().input(data);
|
||||
while (!method.decompress().isDone())
|
||||
{
|
||||
ByteBuffer uncompressed = method.decompress().process();
|
||||
WebSocketFrame out = new WebSocketFrame(frame).setPayload(uncompressed);
|
||||
if (!method.decompress().isDone())
|
||||
{
|
||||
out.setFin(false);
|
||||
}
|
||||
out.setRsv1(false); // Unset RSV1 on decompressed frame
|
||||
nextIncomingFrame(out);
|
||||
}
|
||||
|
||||
// reset on every frame.
|
||||
method.decompress().end();
|
||||
}
|
||||
finally
|
||||
{
|
||||
// release original buffer (no longer needed)
|
||||
getBufferPool().release(data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates use of RSV1 flag for indicating deflation is in use.
|
||||
* <p>
|
||||
* Also known as the "COMP" framing header bit
|
||||
*/
|
||||
@Override
|
||||
public boolean isRsv1User()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that this extensions is now responsible for TEXT Data Frame compliance to the WebSocket spec.
|
||||
*/
|
||||
@Override
|
||||
public boolean isTextDataDecoder()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<SendResult> outgoingFrame(Frame frame) throws IOException
|
||||
{
|
||||
if (frame.getType().isControl())
|
||||
{
|
||||
// skip, cannot compress control frames.
|
||||
return nextOutgoingFrame(frame);
|
||||
}
|
||||
|
||||
Future<SendResult> future = null;
|
||||
|
||||
ByteBuffer data = frame.getPayload();
|
||||
try
|
||||
{
|
||||
// deflate data
|
||||
method.compress().input(data);
|
||||
while (!method.compress().isDone())
|
||||
{
|
||||
ByteBuffer buf = method.compress().process();
|
||||
WebSocketFrame out = new WebSocketFrame(frame).setPayload(buf);
|
||||
out.setRsv1(true);
|
||||
if (!method.compress().isDone())
|
||||
{
|
||||
out.setFin(false);
|
||||
}
|
||||
|
||||
future = nextOutgoingFrame(out);
|
||||
}
|
||||
|
||||
// reset on every frame.
|
||||
method.compress().end();
|
||||
}
|
||||
finally
|
||||
{
|
||||
// free original data buffer
|
||||
getBufferPool().release(data);
|
||||
}
|
||||
|
||||
return future;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConfig(ExtensionConfig config)
|
||||
{
|
||||
super.setConfig(config);
|
||||
|
||||
method = new DeflateCompressionMethod();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return this.getClass().getSimpleName() + "[]";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,168 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.common.extensions.compress;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import javax.net.websocket.SendResult;
|
||||
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.extensions.AbstractExtension;
|
||||
|
||||
/**
|
||||
* Per Message Compression extension for WebSocket.
|
||||
* <p>
|
||||
* Attempts to follow <a href="https://tools.ietf.org/html/draft-ietf-hybi-permessage-compression-01">draft-ietf-hybi-permessage-compression-01</a>
|
||||
*/
|
||||
public class MessageCompressionExtension extends AbstractExtension
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(MessageCompressionExtension.class);
|
||||
|
||||
private CompressionMethod method;
|
||||
|
||||
@Override
|
||||
public void incomingFrame(Frame frame)
|
||||
{
|
||||
if (frame.getType().isControl() || !frame.isRsv1())
|
||||
{
|
||||
// Cannot modify incoming control frames or ones with RSV1 set.
|
||||
nextIncomingFrame(frame);
|
||||
return;
|
||||
}
|
||||
|
||||
ByteBuffer data = frame.getPayload();
|
||||
try
|
||||
{
|
||||
method.decompress().input(data);
|
||||
while (!method.decompress().isDone())
|
||||
{
|
||||
ByteBuffer uncompressed = method.decompress().process();
|
||||
if (uncompressed == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
WebSocketFrame out = new WebSocketFrame(frame).setPayload(uncompressed);
|
||||
if (!method.decompress().isDone())
|
||||
{
|
||||
out.setFin(false);
|
||||
}
|
||||
out.setRsv1(false); // Unset RSV1 on decompressed frame
|
||||
nextIncomingFrame(out);
|
||||
}
|
||||
|
||||
// reset only at the end of a message.
|
||||
if (frame.isFin())
|
||||
{
|
||||
method.decompress().end();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
// release original buffer (no longer needed)
|
||||
getBufferPool().release(data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates use of RSV1 flag for indicating deflation is in use.
|
||||
*/
|
||||
@Override
|
||||
public boolean isRsv1User()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTextDataDecoder()
|
||||
{
|
||||
// this extension is responsible for text data frames
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<SendResult> outgoingFrame(Frame frame) throws IOException
|
||||
{
|
||||
if (frame.getType().isControl())
|
||||
{
|
||||
// skip, cannot compress control frames.
|
||||
return nextOutgoingFrame(frame);
|
||||
}
|
||||
|
||||
Future<SendResult> future = null;
|
||||
|
||||
ByteBuffer data = frame.getPayload();
|
||||
try
|
||||
{
|
||||
// deflate data
|
||||
method.compress().input(data);
|
||||
while (!method.compress().isDone())
|
||||
{
|
||||
ByteBuffer buf = method.compress().process();
|
||||
WebSocketFrame out = new WebSocketFrame(frame).setPayload(buf);
|
||||
out.setRsv1(true);
|
||||
if (!method.compress().isDone())
|
||||
{
|
||||
out.setFin(false);
|
||||
future = nextOutgoingFrame(out);
|
||||
}
|
||||
else
|
||||
{
|
||||
future = nextOutgoingFrame(out);
|
||||
}
|
||||
}
|
||||
|
||||
// reset only at end of message
|
||||
if (frame.isFin())
|
||||
{
|
||||
method.compress().end();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
// free original data buffer
|
||||
getBufferPool().release(data);
|
||||
}
|
||||
|
||||
return future;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConfig(ExtensionConfig config)
|
||||
{
|
||||
super.setConfig(config);
|
||||
|
||||
String methodOptions = config.getParameter("method","deflate");
|
||||
LOG.debug("Method requested: {}",methodOptions);
|
||||
|
||||
method = new DeflateCompressionMethod();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return String.format("%s[method=%s]",this.getClass().getSimpleName(),method);
|
||||
}
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.common.extensions.compress;
|
||||
|
||||
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
|
||||
import org.eclipse.jetty.websocket.common.extensions.AbstractExtension;
|
||||
|
||||
/**
|
||||
* Per Message Compression extension for WebSocket.
|
||||
* <p>
|
||||
* Attempts to follow <a href="https://tools.ietf.org/html/draft-ietf-hybi-permessage-compression-01">draft-ietf-hybi-permessage-compression-01</a>
|
||||
*/
|
||||
public class PerMessageCompressionExtension extends AbstractExtension
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(PerMessageCompressionExtension.class);
|
||||
|
||||
private CompressionMethod method;
|
||||
|
||||
@Override
|
||||
public javax.net.websocket.extensions.FrameHandler createIncomingFrameHandler(javax.net.websocket.extensions.FrameHandler incoming)
|
||||
{
|
||||
return new DecompressMessageHandler(incoming,method,getBufferPool());
|
||||
}
|
||||
|
||||
@Override
|
||||
public javax.net.websocket.extensions.FrameHandler createOutgoingFrameHandler(javax.net.websocket.extensions.FrameHandler outgoing)
|
||||
{
|
||||
return new CompressMessageHandler(outgoing,method,getBufferPool());
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates use of RSV1 flag for indicating deflation is in use.
|
||||
*/
|
||||
@Override
|
||||
public boolean isRsv1User()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTextDataDecoder()
|
||||
{
|
||||
// this extension is responsible for text data frames
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConfig(ExtensionConfig config)
|
||||
{
|
||||
super.setConfig(config);
|
||||
|
||||
String methodOptions = config.getParameter("method","deflate");
|
||||
LOG.debug("Method requested: {}",methodOptions);
|
||||
|
||||
method = new DeflateCompressionMethod();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return String.format("%s[method=%s]",this.getClass().getSimpleName(),method);
|
||||
}
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.common.extensions.compress;
|
||||
|
||||
|
||||
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
|
||||
import org.eclipse.jetty.websocket.common.extensions.AbstractExtension;
|
||||
|
||||
/**
|
||||
* Implementation of the <a href="https://tools.ietf.org/id/draft-tyoshino-hybi-websocket-perframe-deflate-05.txt">x-webkit-deflate-frame</a> extension seen out
|
||||
* in the wild.
|
||||
*/
|
||||
public class WebkitDeflateFrameExtension extends AbstractExtension
|
||||
{
|
||||
private DeflateCompressionMethod method;
|
||||
|
||||
@Override
|
||||
public javax.net.websocket.extensions.FrameHandler createIncomingFrameHandler(javax.net.websocket.extensions.FrameHandler incoming)
|
||||
{
|
||||
return new DecompressFrameHandler(incoming,method,getBufferPool());
|
||||
}
|
||||
|
||||
@Override
|
||||
public javax.net.websocket.extensions.FrameHandler createOutgoingFrameHandler(javax.net.websocket.extensions.FrameHandler outgoing)
|
||||
{
|
||||
return new CompressFrameHandler(outgoing,method,getBufferPool());
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates use of RSV1 flag for indicating deflation is in use.
|
||||
* <p>
|
||||
* Also known as the "COMP" framing header bit
|
||||
*/
|
||||
@Override
|
||||
public boolean isRsv1User()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that this extensions is now responsible for TEXT Data Frame compliance to the WebSocket spec.
|
||||
*/
|
||||
@Override
|
||||
public boolean isTextDataDecoder()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConfig(ExtensionConfig config)
|
||||
{
|
||||
super.setConfig(config);
|
||||
|
||||
method = new DeflateCompressionMethod();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return this.getClass().getSimpleName() + "[]";
|
||||
}
|
||||
}
|
|
@ -19,9 +19,18 @@
|
|||
package org.eclipse.jetty.websocket.common.extensions.fragment;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import javax.net.websocket.SendResult;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.WebSocketException;
|
||||
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.common.OpCode;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.extensions.AbstractExtension;
|
||||
import org.eclipse.jetty.websocket.common.extensions.PassthruFrameHandler;
|
||||
|
||||
/**
|
||||
* Fragment Extension
|
||||
|
@ -31,16 +40,72 @@ public class FragmentExtension extends AbstractExtension
|
|||
private int maxLength = -1;
|
||||
|
||||
@Override
|
||||
public javax.net.websocket.extensions.FrameHandler createIncomingFrameHandler(javax.net.websocket.extensions.FrameHandler incoming)
|
||||
public void incomingError(WebSocketException e)
|
||||
{
|
||||
// pass through handler
|
||||
return new PassthruFrameHandler(incoming);
|
||||
// Pass thru
|
||||
nextIncomingError(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public javax.net.websocket.extensions.FrameHandler createOutgoingFrameHandler(javax.net.websocket.extensions.FrameHandler outgoing)
|
||||
public void incomingFrame(Frame frame)
|
||||
{
|
||||
return new FragmentHandler(outgoing,maxLength);
|
||||
// Pass thru
|
||||
nextIncomingFrame(frame);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<SendResult> outgoingFrame(Frame frame) throws IOException
|
||||
{
|
||||
if (frame.getType().isControl())
|
||||
{
|
||||
// Cannot fragment Control Frames
|
||||
return nextOutgoingFrame(frame);
|
||||
}
|
||||
|
||||
int length = frame.getPayloadLength();
|
||||
|
||||
byte opcode = frame.getType().getOpCode(); // original opcode
|
||||
ByteBuffer payload = frame.getPayload().slice();
|
||||
int originalLimit = payload.limit();
|
||||
int currentPosition = payload.position();
|
||||
|
||||
if (maxLength <= 0)
|
||||
{
|
||||
// output original frame
|
||||
return nextOutgoingFrame(frame);
|
||||
}
|
||||
|
||||
boolean continuation = false;
|
||||
|
||||
// break apart payload based on maxLength rules
|
||||
while (length > maxLength)
|
||||
{
|
||||
WebSocketFrame frag = new WebSocketFrame(frame);
|
||||
frag.setOpCode(opcode);
|
||||
frag.setFin(false); // always false here
|
||||
frag.setContinuation(continuation);
|
||||
payload.position(currentPosition);
|
||||
payload.limit(Math.min(payload.position() + maxLength,originalLimit));
|
||||
frag.setPayload(payload);
|
||||
|
||||
nextOutgoingFrame(frag);
|
||||
|
||||
length -= maxLength;
|
||||
opcode = OpCode.CONTINUATION;
|
||||
continuation = true;
|
||||
currentPosition = payload.limit();
|
||||
}
|
||||
|
||||
// write remaining
|
||||
WebSocketFrame frag = new WebSocketFrame(frame);
|
||||
frag.setOpCode(opcode);
|
||||
frag.setFin(frame.isFin()); // use original fin
|
||||
frag.setContinuation(continuation);
|
||||
payload.position(currentPosition);
|
||||
payload.limit(originalLimit);
|
||||
frag.setPayload(payload);
|
||||
|
||||
return nextOutgoingFrame(frag);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,83 +0,0 @@
|
|||
package org.eclipse.jetty.websocket.common.extensions.fragment;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import javax.net.websocket.extensions.FrameHandler;
|
||||
|
||||
import org.eclipse.jetty.websocket.common.OpCode;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.extensions.AbstractJettyFrameHandler;
|
||||
|
||||
/**
|
||||
* Handler to break apart the frames into multiple smaller frames.
|
||||
*/
|
||||
public class FragmentHandler extends AbstractJettyFrameHandler
|
||||
{
|
||||
private final int maxLength;
|
||||
|
||||
/**
|
||||
* @param fragmentExtension
|
||||
*/
|
||||
public FragmentHandler(FrameHandler nextHandler, int maxLength)
|
||||
{
|
||||
super(nextHandler);
|
||||
this.maxLength = maxLength;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleJettyFrame(WebSocketFrame frame)
|
||||
{
|
||||
if (frame.getType().isControl())
|
||||
{
|
||||
// Cannot fragment Control Frames
|
||||
nextJettyHandler(frame);
|
||||
return;
|
||||
}
|
||||
|
||||
int length = frame.getPayloadLength();
|
||||
|
||||
byte opcode = frame.getType().getOpCode(); // original opcode
|
||||
ByteBuffer payload = frame.getPayload().slice();
|
||||
int originalLimit = payload.limit();
|
||||
int currentPosition = payload.position();
|
||||
|
||||
if (maxLength <= 0)
|
||||
{
|
||||
// output original frame
|
||||
nextJettyHandler(frame);
|
||||
return;
|
||||
}
|
||||
|
||||
boolean continuation = false;
|
||||
|
||||
// break apart payload based on maxLength rules
|
||||
while (length > maxLength)
|
||||
{
|
||||
WebSocketFrame frag = new WebSocketFrame(frame);
|
||||
frag.setOpCode(opcode);
|
||||
frag.setFin(false); // always false here
|
||||
frag.setContinuation(continuation);
|
||||
payload.position(currentPosition);
|
||||
payload.limit(Math.min(payload.position() + maxLength,originalLimit));
|
||||
frag.setPayload(payload);
|
||||
|
||||
nextJettyHandler(frag);
|
||||
|
||||
length -= maxLength;
|
||||
opcode = OpCode.CONTINUATION;
|
||||
continuation = true;
|
||||
currentPosition = payload.limit();
|
||||
}
|
||||
|
||||
// write remaining
|
||||
WebSocketFrame frag = new WebSocketFrame(frame);
|
||||
frag.setOpCode(opcode);
|
||||
frag.setFin(frame.isFin()); // use original fin
|
||||
frag.setContinuation(continuation);
|
||||
payload.position(currentPosition);
|
||||
payload.limit(originalLimit);
|
||||
frag.setPayload(payload);
|
||||
|
||||
nextJettyHandler(frag);
|
||||
}
|
||||
}
|
|
@ -18,25 +18,40 @@
|
|||
|
||||
package org.eclipse.jetty.websocket.common.extensions.identity;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import javax.net.websocket.SendResult;
|
||||
|
||||
import org.eclipse.jetty.util.QuotedStringTokenizer;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketException;
|
||||
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.common.extensions.AbstractExtension;
|
||||
import org.eclipse.jetty.websocket.common.extensions.PassthruFrameHandler;
|
||||
|
||||
public class IdentityExtension extends AbstractExtension
|
||||
{
|
||||
private String id;
|
||||
|
||||
@Override
|
||||
public javax.net.websocket.extensions.FrameHandler createIncomingFrameHandler(javax.net.websocket.extensions.FrameHandler incoming)
|
||||
public void incomingError(WebSocketException e)
|
||||
{
|
||||
return new PassthruFrameHandler(incoming);
|
||||
// pass through
|
||||
nextIncomingError(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public javax.net.websocket.extensions.FrameHandler createOutgoingFrameHandler(javax.net.websocket.extensions.FrameHandler outgoing)
|
||||
public void incomingFrame(Frame frame)
|
||||
{
|
||||
return new PassthruFrameHandler(outgoing);
|
||||
// pass through
|
||||
nextIncomingFrame(frame);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<SendResult> outgoingFrame(Frame frame) throws IOException
|
||||
{
|
||||
// pass through
|
||||
return nextOutgoingFrame(frame);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -18,9 +18,13 @@
|
|||
|
||||
package org.eclipse.jetty.websocket.common.extensions.mux;
|
||||
|
||||
import javax.net.websocket.extensions.FrameHandler;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.WebSocketConnection;
|
||||
import javax.net.websocket.SendResult;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.common.LogicalConnection;
|
||||
import org.eclipse.jetty.websocket.common.extensions.AbstractExtension;
|
||||
|
||||
/**
|
||||
|
@ -40,19 +44,20 @@ public abstract class AbstractMuxExtension extends AbstractExtension
|
|||
public abstract void configureMuxer(Muxer muxer);
|
||||
|
||||
@Override
|
||||
public FrameHandler createIncomingFrameHandler(FrameHandler incoming)
|
||||
public void incomingFrame(Frame frame)
|
||||
{
|
||||
return new MuxerIncomingFrameHandler(incoming,muxer);
|
||||
this.muxer.incomingFrame(frame);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FrameHandler createOutgoingFrameHandler(FrameHandler outgoing)
|
||||
public Future<SendResult> outgoingFrame(Frame frame) throws IOException
|
||||
{
|
||||
return new MuxerOutgoingFrameHandler(outgoing,muxer);
|
||||
/* do nothing */
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConnection(WebSocketConnection connection)
|
||||
public void setConnection(LogicalConnection connection)
|
||||
{
|
||||
super.setConnection(connection);
|
||||
if (muxer != null)
|
||||
|
|
|
@ -22,7 +22,6 @@ import java.io.IOException;
|
|||
import java.net.InetSocketAddress;
|
||||
import java.net.URI;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
|
@ -35,20 +34,18 @@ import org.eclipse.jetty.websocket.api.SuspendToken;
|
|||
import org.eclipse.jetty.websocket.api.WebSocketConnection;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketException;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Extension;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.api.extensions.IncomingFrames;
|
||||
import org.eclipse.jetty.websocket.common.CloseInfo;
|
||||
import org.eclipse.jetty.websocket.common.ConnectionState;
|
||||
import org.eclipse.jetty.websocket.common.LogicalConnection;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.extensions.AbstractExtension;
|
||||
import org.eclipse.jetty.websocket.common.io.IncomingFrames;
|
||||
import org.eclipse.jetty.websocket.common.io.InternalConnection;
|
||||
import org.eclipse.jetty.websocket.common.io.OutgoingFrames;
|
||||
import org.eclipse.jetty.websocket.common.io.WebSocketSession;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketSession;
|
||||
|
||||
/**
|
||||
* MuxChannel, acts as WebSocketConnection for specific sub-channel.
|
||||
*/
|
||||
public class MuxChannel implements WebSocketConnection, InternalConnection, IncomingFrames, OutgoingFrames, SuspendToken
|
||||
public class MuxChannel implements WebSocketConnection, LogicalConnection, IncomingFrames, SuspendToken
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(MuxChannel.class);
|
||||
|
||||
|
@ -76,6 +73,20 @@ public class MuxChannel implements WebSocketConnection, InternalConnection, Inco
|
|||
this.outputClosed = new AtomicBoolean(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void assertInputOpen() throws IOException
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void assertOutputOpen() throws IOException
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
|
@ -97,12 +108,6 @@ public class MuxChannel implements WebSocketConnection, InternalConnection, Inco
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureFromExtensions(List<Extension> extensions)
|
||||
{
|
||||
/* ignore */
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect()
|
||||
{
|
||||
|
@ -141,6 +146,7 @@ public class MuxChannel implements WebSocketConnection, InternalConnection, Inco
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebSocketSession getSession()
|
||||
{
|
||||
return session;
|
||||
|
@ -171,7 +177,7 @@ public class MuxChannel implements WebSocketConnection, InternalConnection, Inco
|
|||
* Incoming frames from Muxer
|
||||
*/
|
||||
@Override
|
||||
public void incomingFrame(WebSocketFrame frame)
|
||||
public void incomingFrame(Frame frame)
|
||||
{
|
||||
incoming.incomingFrame(frame);
|
||||
}
|
||||
|
@ -250,7 +256,7 @@ public class MuxChannel implements WebSocketConnection, InternalConnection, Inco
|
|||
* Frames destined for the Muxer
|
||||
*/
|
||||
@Override
|
||||
public Future<SendResult> outgoingFrame(WebSocketFrame frame) throws IOException
|
||||
public Future<SendResult> outgoingFrame(Frame frame) throws IOException
|
||||
{
|
||||
return muxer.output(channelId,frame);
|
||||
}
|
||||
|
@ -259,9 +265,9 @@ public class MuxChannel implements WebSocketConnection, InternalConnection, Inco
|
|||
* Ping frame destined for the Muxer
|
||||
*/
|
||||
@Override
|
||||
public Future<SendResult> ping(byte[] payload) throws IOException
|
||||
public void ping(ByteBuffer buf) throws IOException
|
||||
{
|
||||
return outgoingFrame(WebSocketFrame.ping().setPayload(payload));
|
||||
outgoingFrame(WebSocketFrame.ping().setPayload(buf));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -274,7 +280,7 @@ public class MuxChannel implements WebSocketConnection, InternalConnection, Inco
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setIncoming(IncomingFrames incoming)
|
||||
public void setNextIncomingFrames(IncomingFrames incoming)
|
||||
{
|
||||
this.incoming = incoming;
|
||||
}
|
||||
|
@ -283,7 +289,7 @@ public class MuxChannel implements WebSocketConnection, InternalConnection, Inco
|
|||
public void setSession(WebSocketSession session)
|
||||
{
|
||||
this.session = session;
|
||||
session.setOutgoing(this);
|
||||
// session.setOutgoing(this);
|
||||
}
|
||||
|
||||
public void setSubProtocol(String subProtocol)
|
||||
|
@ -299,40 +305,6 @@ public class MuxChannel implements WebSocketConnection, InternalConnection, Inco
|
|||
return this;
|
||||
}
|
||||
|
||||
public void wireUpExtensions(List<AbstractExtension> extensions)
|
||||
{
|
||||
// Start with default routing.
|
||||
incoming = session;
|
||||
OutgoingFrames outgoing = this;
|
||||
|
||||
if (extensions != null)
|
||||
{
|
||||
// FIXME
|
||||
// Iterator<AbstractExtension> extIter;
|
||||
// // Connect outgoings
|
||||
// extIter = extensions.iterator();
|
||||
// while (extIter.hasNext())
|
||||
// {
|
||||
// AbstractExtension ext = extIter.next();
|
||||
// ext.setNextOutgoingFrames(outgoing);
|
||||
// outgoing = ext;
|
||||
// }
|
||||
//
|
||||
// // Connect incomings
|
||||
// Collections.reverse(extensions);
|
||||
// extIter = extensions.iterator();
|
||||
// while (extIter.hasNext())
|
||||
// {
|
||||
// AbstractExtension ext = extIter.next();
|
||||
// ext.setNextIncomingFrames(incoming);
|
||||
// incoming = ext;
|
||||
// }
|
||||
}
|
||||
|
||||
// set outgoing
|
||||
this.session.setOutgoing(outgoing);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a binary message, destined for Muxer
|
||||
*/
|
||||
|
|
|
@ -27,13 +27,14 @@ import javax.net.websocket.SendResult;
|
|||
import org.eclipse.jetty.io.ArrayByteBufferPool;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.extensions.mux.op.MuxAddChannelRequest;
|
||||
import org.eclipse.jetty.websocket.common.extensions.mux.op.MuxAddChannelResponse;
|
||||
import org.eclipse.jetty.websocket.common.extensions.mux.op.MuxDropChannel;
|
||||
import org.eclipse.jetty.websocket.common.extensions.mux.op.MuxFlowControl;
|
||||
import org.eclipse.jetty.websocket.common.extensions.mux.op.MuxNewChannelSlot;
|
||||
import org.eclipse.jetty.websocket.common.io.OutgoingFrames;
|
||||
|
||||
/**
|
||||
* Generate Mux frames destined for the physical connection.
|
||||
|
@ -56,7 +57,7 @@ public class MuxGenerator
|
|||
this.bufferPool = bufferPool;
|
||||
}
|
||||
|
||||
public Future<SendResult> generate(long channelId, WebSocketFrame frame) throws IOException
|
||||
public Future<SendResult> generate(long channelId, Frame frame) throws IOException
|
||||
{
|
||||
ByteBuffer muxPayload = bufferPool.acquire(frame.getPayloadLength() + DATA_FRAME_OVERHEAD,false);
|
||||
BufferUtil.flipToFill(muxPayload);
|
||||
|
@ -67,7 +68,7 @@ public class MuxGenerator
|
|||
b |= (byte)(frame.isRsv1()?0x40:0x00); // rsv1
|
||||
b |= (byte)(frame.isRsv2()?0x20:0x00); // rsv2
|
||||
b |= (byte)(frame.isRsv3()?0x10:0x00); // rsv3
|
||||
b |= (byte)(frame.getOpCode() & 0x0F); // opcode
|
||||
b |= (byte)(frame.getType().getOpCode() & 0x0F); // opcode
|
||||
muxPayload.put(b);
|
||||
BufferUtil.put(frame.getPayload(),muxPayload);
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ import java.nio.ByteBuffer;
|
|||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.common.OpCode;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.extensions.mux.op.MuxAddChannelRequest;
|
||||
|
@ -67,7 +68,7 @@ public class MuxParser
|
|||
* @param frame
|
||||
* the WebSocketFrame to parse for mux payload
|
||||
*/
|
||||
public synchronized void parse(WebSocketFrame frame)
|
||||
public synchronized void parse(Frame frame)
|
||||
{
|
||||
if (events == null)
|
||||
{
|
||||
|
@ -80,7 +81,7 @@ public class MuxParser
|
|||
return; // nothing to parse
|
||||
}
|
||||
|
||||
if (frame.getOpCode() != OpCode.BINARY)
|
||||
if (frame.getType().getOpCode() != OpCode.BINARY)
|
||||
{
|
||||
LOG.debug("Not a binary opcode (base frame), skipping");
|
||||
return; // not a binary opcode
|
||||
|
|
|
@ -32,10 +32,14 @@ import org.eclipse.jetty.util.log.Log;
|
|||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.api.StatusCode;
|
||||
import org.eclipse.jetty.websocket.api.UpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.api.UpgradeResponse;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketBehavior;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketConnection;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketException;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.api.extensions.IncomingFrames;
|
||||
import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames;
|
||||
import org.eclipse.jetty.websocket.common.LogicalConnection;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.extensions.mux.add.MuxAddClient;
|
||||
import org.eclipse.jetty.websocket.common.extensions.mux.add.MuxAddServer;
|
||||
|
@ -44,8 +48,6 @@ import org.eclipse.jetty.websocket.common.extensions.mux.op.MuxAddChannelRespons
|
|||
import org.eclipse.jetty.websocket.common.extensions.mux.op.MuxDropChannel;
|
||||
import org.eclipse.jetty.websocket.common.extensions.mux.op.MuxFlowControl;
|
||||
import org.eclipse.jetty.websocket.common.extensions.mux.op.MuxNewChannelSlot;
|
||||
import org.eclipse.jetty.websocket.common.io.IncomingFrames;
|
||||
import org.eclipse.jetty.websocket.common.io.OutgoingFrames;
|
||||
|
||||
/**
|
||||
* Muxer responsible for managing sub-channels.
|
||||
|
@ -67,7 +69,7 @@ public class Muxer implements IncomingFrames, MuxParser.Listener
|
|||
private Map<Long, MuxChannel> channels = new HashMap<Long, MuxChannel>();
|
||||
|
||||
private final WebSocketPolicy policy;
|
||||
private final WebSocketConnection physicalConnection;
|
||||
private final LogicalConnection physicalConnection;
|
||||
private InetSocketAddress remoteAddress;
|
||||
/** Parsing frames destined for sub-channels */
|
||||
private MuxParser parser;
|
||||
|
@ -76,11 +78,11 @@ public class Muxer implements IncomingFrames, MuxParser.Listener
|
|||
private MuxAddServer addServer;
|
||||
private MuxAddClient addClient;
|
||||
/** The original request headers, used for delta encoded AddChannelRequest blocks */
|
||||
private List<String> physicalRequestHeaders;
|
||||
private UpgradeRequest physicalRequestHeaders;
|
||||
/** The original response headers, used for delta encoded AddChannelResponse blocks */
|
||||
private List<String> physicalResponseHeaders;
|
||||
private UpgradeResponse physicalResponseHeaders;
|
||||
|
||||
public Muxer(final WebSocketConnection connection)
|
||||
public Muxer(final LogicalConnection connection)
|
||||
{
|
||||
this.physicalConnection = connection;
|
||||
this.policy = connection.getPolicy().clonePolicy();
|
||||
|
@ -152,7 +154,7 @@ public class Muxer implements IncomingFrames, MuxParser.Listener
|
|||
* Incoming mux encapsulated frames.
|
||||
*/
|
||||
@Override
|
||||
public void incomingFrame(WebSocketFrame frame)
|
||||
public void incomingFrame(Frame frame)
|
||||
{
|
||||
parser.parse(frame);
|
||||
}
|
||||
|
@ -383,7 +385,7 @@ public class Muxer implements IncomingFrames, MuxParser.Listener
|
|||
/**
|
||||
* Outgoing frame, without mux encapsulated payload.
|
||||
*/
|
||||
public Future<SendResult> output(long channelId, WebSocketFrame frame) throws IOException
|
||||
public Future<SendResult> output(long channelId, Frame frame) throws IOException
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
|
|
|
@ -1,57 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.common.extensions.mux;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import javax.net.websocket.SendResult;
|
||||
import javax.net.websocket.extensions.FrameHandler;
|
||||
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.extensions.AbstractJettyFrameHandler;
|
||||
import org.eclipse.jetty.websocket.common.io.OutgoingFrames;
|
||||
|
||||
/**
|
||||
* Process frames destined for the network layer.
|
||||
* <p>
|
||||
* Outgoing frames are not mangled by this handler, as they have already been captured by the {@link Muxer} and encapsulated.
|
||||
*/
|
||||
public class MuxerOutgoingFrameHandler extends AbstractJettyFrameHandler implements OutgoingFrames
|
||||
{
|
||||
public MuxerOutgoingFrameHandler(FrameHandler nextHandler, Muxer muxer)
|
||||
{
|
||||
super(nextHandler);
|
||||
muxer.setOutgoingFramesHandler(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleJettyFrame(WebSocketFrame frame)
|
||||
{
|
||||
// pass through. Muxer already encapsulated frame.
|
||||
nextJettyHandler(frame);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<SendResult> outgoingFrame(WebSocketFrame frame) throws IOException
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -18,8 +18,8 @@
|
|||
|
||||
package org.eclipse.jetty.websocket.common.extensions.mux.add;
|
||||
|
||||
import org.eclipse.jetty.websocket.common.WebSocketSession;
|
||||
import org.eclipse.jetty.websocket.common.extensions.mux.op.MuxAddChannelResponse;
|
||||
import org.eclipse.jetty.websocket.common.io.WebSocketSession;
|
||||
|
||||
/**
|
||||
* Interface for Mux Client to handle receiving a AddChannelResponse
|
||||
|
|
|
@ -22,10 +22,10 @@ import java.io.IOException;
|
|||
|
||||
import org.eclipse.jetty.websocket.api.UpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.api.UpgradeResponse;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketSession;
|
||||
import org.eclipse.jetty.websocket.common.extensions.mux.MuxChannel;
|
||||
import org.eclipse.jetty.websocket.common.extensions.mux.MuxException;
|
||||
import org.eclipse.jetty.websocket.common.extensions.mux.Muxer;
|
||||
import org.eclipse.jetty.websocket.common.io.WebSocketSession;
|
||||
|
||||
/**
|
||||
* Server interface, for dealing with incoming AddChannelRequest / AddChannelResponse flows.
|
||||
|
|
|
@ -44,17 +44,19 @@ import org.eclipse.jetty.websocket.api.SuspendToken;
|
|||
import org.eclipse.jetty.websocket.api.WebSocketConnection;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.common.CloseInfo;
|
||||
import org.eclipse.jetty.websocket.common.ConnectionState;
|
||||
import org.eclipse.jetty.websocket.common.Generator;
|
||||
import org.eclipse.jetty.websocket.common.LogicalConnection;
|
||||
import org.eclipse.jetty.websocket.common.OpCode;
|
||||
import org.eclipse.jetty.websocket.common.Parser;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketSession;
|
||||
|
||||
/**
|
||||
* Provides the implementation of {@link WebSocketConnection} within the framework of the new {@link Connection} framework of jetty-io
|
||||
*/
|
||||
public abstract class AbstractWebSocketConnection extends AbstractConnection implements InternalConnection, SuspendToken
|
||||
public abstract class AbstractWebSocketConnection extends AbstractConnection implements LogicalConnection
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(AbstractWebSocketConnection.class);
|
||||
private static final Logger LOG_FRAMES = Log.getLogger("org.eclipse.jetty.websocket.io.Frames");
|
||||
|
@ -91,6 +93,24 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp
|
|||
this.outputClosed = new AtomicBoolean(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void assertInputOpen() throws IOException
|
||||
{
|
||||
if (isInputClosed())
|
||||
{
|
||||
throw new IOException("Connection input is closed");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void assertOutputOpen() throws IOException
|
||||
{
|
||||
if (isOutputClosed())
|
||||
{
|
||||
throw new IOException("Connection output is closed");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
|
@ -232,6 +252,7 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp
|
|||
return parser;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebSocketPolicy getPolicy()
|
||||
{
|
||||
return this.policy;
|
||||
|
@ -253,6 +274,7 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp
|
|||
return scheduler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebSocketSession getSession()
|
||||
{
|
||||
return session;
|
||||
|
@ -370,15 +392,12 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue internal frame from {@link OutgoingFrames} stack for eventual write out on the physical connection.
|
||||
*/
|
||||
@Override
|
||||
public Future<SendResult> outgoingFrame(WebSocketFrame frame) throws IOException
|
||||
public Future<SendResult> outgoingFrame(Frame frame) throws IOException
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
LOG.debug("output({})",frame);
|
||||
LOG.debug("outgoingFrame({})",frame);
|
||||
}
|
||||
|
||||
Future<SendResult> future = null;
|
||||
|
@ -402,7 +421,7 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp
|
|||
|
||||
if (isOpen())
|
||||
{
|
||||
if (frame.getOpCode() == OpCode.PING)
|
||||
if (frame.getType().getOpCode() == OpCode.PING)
|
||||
{
|
||||
queue.prepend(bytes);
|
||||
}
|
||||
|
|
|
@ -24,9 +24,9 @@ import javax.net.websocket.SendResult;
|
|||
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.common.CloseInfo;
|
||||
import org.eclipse.jetty.websocket.common.OpCode;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
|
||||
public class ControlFrameBytes extends FrameBytes
|
||||
{
|
||||
|
@ -34,7 +34,7 @@ public class ControlFrameBytes extends FrameBytes
|
|||
private ByteBuffer buffer;
|
||||
private ByteBuffer origPayload;
|
||||
|
||||
public ControlFrameBytes(AbstractWebSocketConnection connection, WebSocketFrame frame)
|
||||
public ControlFrameBytes(AbstractWebSocketConnection connection, Frame frame)
|
||||
{
|
||||
super(connection,frame);
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ public class ControlFrameBytes extends FrameBytes
|
|||
|
||||
super.completed(context);
|
||||
|
||||
if (frame.getOpCode() == OpCode.CLOSE)
|
||||
if (frame.getType().getOpCode() == OpCode.CLOSE)
|
||||
{
|
||||
CloseInfo close = new CloseInfo(origPayload,false);
|
||||
connection.onCloseHandshake(false,close);
|
||||
|
|
|
@ -24,14 +24,14 @@ import javax.net.websocket.SendResult;
|
|||
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
|
||||
public class DataFrameBytes extends FrameBytes
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(DataFrameBytes.class);
|
||||
private ByteBuffer buffer;
|
||||
|
||||
public DataFrameBytes(AbstractWebSocketConnection connection, WebSocketFrame frame)
|
||||
public DataFrameBytes(AbstractWebSocketConnection connection, Frame frame)
|
||||
{
|
||||
super(connection,frame);
|
||||
}
|
||||
|
|
|
@ -28,17 +28,17 @@ import org.eclipse.jetty.util.FutureCallback;
|
|||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.util.thread.Scheduler;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
|
||||
public abstract class FrameBytes extends FutureCallback<SendResult> implements Runnable
|
||||
{
|
||||
private final static Logger LOG = Log.getLogger(FrameBytes.class);
|
||||
protected final AbstractWebSocketConnection connection;
|
||||
protected final WebSocketFrame frame;
|
||||
protected final Frame frame;
|
||||
// Task used to timeout the bytes
|
||||
protected volatile Scheduler.Task task;
|
||||
|
||||
protected FrameBytes(AbstractWebSocketConnection connection, WebSocketFrame frame)
|
||||
protected FrameBytes(AbstractWebSocketConnection connection, Frame frame)
|
||||
{
|
||||
this.connection = connection;
|
||||
this.frame = frame;
|
||||
|
@ -63,7 +63,7 @@ public abstract class FrameBytes extends FutureCallback<SendResult> implements R
|
|||
}
|
||||
cancelTask();
|
||||
connection.complete(this);
|
||||
frame.notifySendHandler();
|
||||
frame.notifySendSuccess();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -80,7 +80,7 @@ public abstract class FrameBytes extends FutureCallback<SendResult> implements R
|
|||
LOG.warn("failed(" + v + ")",x);
|
||||
}
|
||||
cancelTask();
|
||||
frame.notifySendHandler(x);
|
||||
frame.notifySendFailed(x);
|
||||
}
|
||||
|
||||
public abstract ByteBuffer getByteBuffer();
|
||||
|
|
|
@ -8,7 +8,9 @@ import javax.net.websocket.SendResult;
|
|||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketException;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.api.extensions.IncomingFrames;
|
||||
import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames;
|
||||
|
||||
public class FramePipes
|
||||
{
|
||||
|
@ -29,7 +31,7 @@ public class FramePipes
|
|||
}
|
||||
|
||||
@Override
|
||||
public void incomingFrame(WebSocketFrame frame)
|
||||
public void incomingFrame(Frame frame)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -52,7 +54,7 @@ public class FramePipes
|
|||
}
|
||||
|
||||
@Override
|
||||
public Future<SendResult> outgoingFrame(WebSocketFrame frame) throws IOException
|
||||
public Future<SendResult> outgoingFrame(Frame frame) throws IOException
|
||||
{
|
||||
this.incoming.incomingFrame(frame);
|
||||
|
||||
|
|
|
@ -1,295 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.common.io;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URI;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import javax.net.websocket.SendResult;
|
||||
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.api.SuspendToken;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketConnection;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketException;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.common.CloseInfo;
|
||||
import org.eclipse.jetty.websocket.common.ConnectionState;
|
||||
import org.eclipse.jetty.websocket.common.LogicalConnection;
|
||||
import org.eclipse.jetty.websocket.common.OpCode;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.events.EventDriver;
|
||||
|
||||
public class WebSocketSession implements WebSocketConnection, LogicalConnection, IncomingFrames, OutgoingFrames
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(WebSocketSession.class);
|
||||
|
||||
/**
|
||||
* The reference to the logical connection.
|
||||
* <p>
|
||||
* This will be the {@link AbstractWebSocketConnection} on normal websocket use, and be a MuxChannel when MUX is in the picture.
|
||||
*/
|
||||
private final LogicalConnection baseConnection;
|
||||
private final WebSocketPolicy policy;
|
||||
private final String subprotocol;
|
||||
private final EventDriver websocket;
|
||||
private OutgoingFrames outgoing;
|
||||
|
||||
public WebSocketSession(EventDriver websocket, LogicalConnection connection, WebSocketPolicy policy, String subprotocol)
|
||||
{
|
||||
super();
|
||||
this.websocket = websocket;
|
||||
this.baseConnection = connection;
|
||||
this.policy = policy;
|
||||
this.subprotocol = subprotocol;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
baseConnection.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close(int statusCode, String reason)
|
||||
{
|
||||
baseConnection.close(statusCode,reason);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect()
|
||||
{
|
||||
baseConnection.disconnect();
|
||||
}
|
||||
|
||||
public IncomingFrames getIncoming()
|
||||
{
|
||||
return websocket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress getLocalAddress()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
public OutgoingFrames getOutgoing()
|
||||
{
|
||||
return outgoing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebSocketPolicy getPolicy()
|
||||
{
|
||||
return policy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress getRemoteAddress()
|
||||
{
|
||||
return baseConnection.getRemoteAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI getRequestURI()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConnectionState getState()
|
||||
{
|
||||
return baseConnection.getState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSubProtocol()
|
||||
{
|
||||
return subprotocol;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void incomingError(WebSocketException e)
|
||||
{
|
||||
if (baseConnection.isInputClosed())
|
||||
{
|
||||
return; // input is closed
|
||||
}
|
||||
// pass on incoming to websocket itself
|
||||
websocket.incomingError(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void incomingFrame(WebSocketFrame frame)
|
||||
{
|
||||
if (baseConnection.isInputClosed())
|
||||
{
|
||||
return; // input is closed
|
||||
}
|
||||
// pass on incoming to websocket itself
|
||||
websocket.incomingFrame(frame);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInputClosed()
|
||||
{
|
||||
return baseConnection.isInputClosed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOpen()
|
||||
{
|
||||
return baseConnection.isOpen();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOutputClosed()
|
||||
{
|
||||
return baseConnection.isOutputClosed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReading()
|
||||
{
|
||||
return baseConnection.isReading();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCloseHandshake(boolean incoming, CloseInfo close)
|
||||
{
|
||||
baseConnection.onCloseHandshake(incoming,close);
|
||||
}
|
||||
|
||||
public void onConnect()
|
||||
{
|
||||
LOG.debug("onConnect()");
|
||||
websocket.setSession(this);
|
||||
websocket.onConnect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<SendResult> outgoingFrame(WebSocketFrame frame) throws IOException
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
LOG.debug("output({}) - {}",frame,outgoing);
|
||||
}
|
||||
// forward on to chain
|
||||
return outgoing.outgoingFrame(frame);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Future<SendResult> ping(byte[] payload) throws IOException
|
||||
{
|
||||
// Delegate the application called ping to the OutgoingFrames interface to allow
|
||||
// extensions to process the frame appropriately.
|
||||
WebSocketFrame frame = new WebSocketFrame(OpCode.PING).setPayload(payload);
|
||||
frame.setFin(true);
|
||||
return outgoingFrame(frame);
|
||||
}
|
||||
|
||||
public void setOutgoing(OutgoingFrames outgoing)
|
||||
{
|
||||
this.outgoing = outgoing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SuspendToken suspend()
|
||||
{
|
||||
return baseConnection.suspend();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("WebSocketSession[websocket=");
|
||||
builder.append(websocket);
|
||||
builder.append(",baseConnection=");
|
||||
builder.append(baseConnection);
|
||||
builder.append(",subprotocol=");
|
||||
builder.append(subprotocol);
|
||||
builder.append(",outgoing=");
|
||||
builder.append(outgoing);
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<SendResult> write(byte[] buf, int offset, int len) throws IOException
|
||||
{
|
||||
assertBaseConnectionOpen();
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
LOG.debug("write(byte[],{},{})",offset,len);
|
||||
}
|
||||
// Delegate the application called write to the OutgoingFrames interface to allow
|
||||
// extensions to process the frame appropriately.
|
||||
WebSocketFrame frame = WebSocketFrame.binary().setPayload(buf,offset,len);
|
||||
frame.setFin(true);
|
||||
return outgoingFrame(frame);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<SendResult> write(ByteBuffer buffer) throws IOException
|
||||
{
|
||||
assertBaseConnectionOpen();
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
LOG.debug("write({})",BufferUtil.toDetailString(buffer));
|
||||
}
|
||||
// Delegate the application called write to the OutgoingFrames interface to allow
|
||||
// extensions to process the frame appropriately.
|
||||
WebSocketFrame frame = WebSocketFrame.binary().setPayload(buffer);
|
||||
frame.setFin(true);
|
||||
return outgoingFrame(frame);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<SendResult> write(String message) throws IOException
|
||||
{
|
||||
assertBaseConnectionOpen();
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
LOG.debug("write(message.length:{})",message.length());
|
||||
}
|
||||
// Delegate the application called ping to the OutgoingFrames interface to allow
|
||||
// extensions to process the frame appropriately.
|
||||
WebSocketFrame frame = WebSocketFrame.text(message);
|
||||
frame.setFin(true);
|
||||
return outgoingFrame(frame);
|
||||
}
|
||||
|
||||
private void assertBaseConnectionOpen() throws IOException
|
||||
{
|
||||
if (baseConnection.isOutputClosed())
|
||||
{
|
||||
throw new IOException("Connection is closed");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,7 +20,7 @@ package org.eclipse.jetty.websocket.common.io.payload;
|
|||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
|
||||
public class DeMaskProcessor implements PayloadProcessor
|
||||
{
|
||||
|
@ -45,7 +45,7 @@ public class DeMaskProcessor implements PayloadProcessor
|
|||
}
|
||||
|
||||
@Override
|
||||
public void reset(WebSocketFrame frame)
|
||||
public void reset(Frame frame)
|
||||
{
|
||||
this.isMasked = frame.isMasked();
|
||||
if (isMasked)
|
||||
|
|
|
@ -20,7 +20,7 @@ package org.eclipse.jetty.websocket.common.io.payload;
|
|||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
|
||||
/**
|
||||
* payload validator does no validation.
|
||||
|
@ -36,7 +36,7 @@ public class NoOpValidator implements PayloadProcessor
|
|||
}
|
||||
|
||||
@Override
|
||||
public void reset(WebSocketFrame frame)
|
||||
public void reset(Frame frame)
|
||||
{
|
||||
/* do nothing */
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ package org.eclipse.jetty.websocket.common.io.payload;
|
|||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.BadPayloadException;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
|
||||
/**
|
||||
* Process the payload (for demasking, validating, etc..)
|
||||
|
@ -38,5 +38,5 @@ public interface PayloadProcessor
|
|||
*/
|
||||
public void process(ByteBuffer payload);
|
||||
|
||||
public void reset(WebSocketFrame frame);
|
||||
public void reset(Frame frame);
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ import org.eclipse.jetty.util.Utf8Appendable;
|
|||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.api.BadPayloadException;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
|
||||
/**
|
||||
* Used to perform validation of UTF8 payload contents (for fast-fail reasons)
|
||||
|
@ -104,7 +104,7 @@ public class UTF8Validator extends Utf8Appendable implements PayloadProcessor
|
|||
}
|
||||
|
||||
@Override
|
||||
public void reset(WebSocketFrame frame)
|
||||
public void reset(Frame frame)
|
||||
{
|
||||
/* do nothing */
|
||||
}
|
||||
|
|
|
@ -16,19 +16,34 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.common.io;
|
||||
package org.eclipse.jetty.websocket.common.message;
|
||||
|
||||
import java.util.List;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.extensions.Extension;
|
||||
import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames;
|
||||
import org.eclipse.jetty.websocket.common.LogicalConnection;
|
||||
|
||||
public interface InternalConnection extends LogicalConnection
|
||||
public class MessageOutputStream extends OutputStream
|
||||
{
|
||||
// TODO: find way to remove
|
||||
void configureFromExtensions(List<Extension> extensions);
|
||||
private final LogicalConnection connection;
|
||||
private final OutgoingFrames outgoing;
|
||||
|
||||
void setIncoming(IncomingFrames incoming);
|
||||
public MessageOutputStream(LogicalConnection connection, OutgoingFrames outgoing)
|
||||
{
|
||||
this.connection = connection;
|
||||
this.outgoing = outgoing;
|
||||
}
|
||||
|
||||
void setSession(WebSocketSession session);
|
||||
public boolean isClosed()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.common.message;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames;
|
||||
import org.eclipse.jetty.websocket.common.LogicalConnection;
|
||||
|
||||
public class MessageWriter extends Writer
|
||||
{
|
||||
private final LogicalConnection connection;
|
||||
private final OutgoingFrames outgoing;
|
||||
|
||||
public MessageWriter(LogicalConnection connection, OutgoingFrames outgoing)
|
||||
{
|
||||
this.connection = connection;
|
||||
this.outgoing = outgoing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
public boolean isClosed()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(char[] cbuf, int off, int len) throws IOException
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -16,30 +16,37 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.common.extensions.mux;
|
||||
package org.eclipse.jetty.websocket.common;
|
||||
|
||||
import javax.net.websocket.extensions.FrameHandler;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.FutureTask;
|
||||
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.extensions.AbstractJettyFrameHandler;
|
||||
import org.eclipse.jetty.websocket.common.io.IncomingFrames;
|
||||
import javax.net.websocket.SendResult;
|
||||
|
||||
/**
|
||||
* Process incoming frames and forward them off to the Muxer.
|
||||
*/
|
||||
public class MuxerIncomingFrameHandler extends AbstractJettyFrameHandler
|
||||
public class FinishedFuture extends FutureTask<SendResult> implements Future<SendResult>
|
||||
{
|
||||
private final IncomingFrames muxerHandler;
|
||||
public static Future<SendResult> INSTANCE;
|
||||
|
||||
public MuxerIncomingFrameHandler(FrameHandler nextHandler, Muxer muxer)
|
||||
static
|
||||
{
|
||||
super(nextHandler);
|
||||
this.muxerHandler = muxer;
|
||||
Callable<SendResult> callable = new Callable<SendResult>()
|
||||
{
|
||||
@Override
|
||||
public SendResult call() throws Exception
|
||||
{
|
||||
return new SendResult();
|
||||
}
|
||||
};
|
||||
|
||||
FinishedFuture fut = new FinishedFuture(callable);
|
||||
fut.run();
|
||||
|
||||
INSTANCE = fut;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleJettyFrame(WebSocketFrame frame)
|
||||
public FinishedFuture(Callable<SendResult> callable)
|
||||
{
|
||||
this.muxerHandler.incomingFrame(frame);
|
||||
super(callable);
|
||||
}
|
||||
}
|
|
@ -26,24 +26,17 @@ import org.eclipse.jetty.util.BufferUtil;
|
|||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketException;
|
||||
import org.eclipse.jetty.websocket.common.OpCode;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.extensions.AbstractJettyFrameHandler;
|
||||
import org.eclipse.jetty.websocket.common.io.IncomingFrames;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.api.extensions.IncomingFrames;
|
||||
import org.junit.Assert;
|
||||
|
||||
public class IncomingFramesCapture extends AbstractJettyFrameHandler implements IncomingFrames
|
||||
public class IncomingFramesCapture implements IncomingFrames
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(IncomingFramesCapture.class);
|
||||
|
||||
private LinkedList<WebSocketFrame> frames = new LinkedList<>();
|
||||
private LinkedList<WebSocketException> errors = new LinkedList<>();
|
||||
|
||||
public IncomingFramesCapture()
|
||||
{
|
||||
super(null); // End of Chain (don't pass frames to anyone else)
|
||||
}
|
||||
|
||||
public void assertErrorCount(int expectedCount)
|
||||
{
|
||||
Assert.assertThat("Captured error count",errors.size(),is(expectedCount));
|
||||
|
@ -84,7 +77,7 @@ public class IncomingFramesCapture extends AbstractJettyFrameHandler implements
|
|||
System.err.printf("Captured %d incoming frames%n",frames.size());
|
||||
for (int i = 0; i < frames.size(); i++)
|
||||
{
|
||||
WebSocketFrame frame = frames.get(i);
|
||||
Frame frame = frames.get(i);
|
||||
System.err.printf("[%3d] %s%n",i,frame);
|
||||
System.err.printf(" %s%n",BufferUtil.toDetailString(frame.getPayload()));
|
||||
}
|
||||
|
@ -126,12 +119,6 @@ public class IncomingFramesCapture extends AbstractJettyFrameHandler implements
|
|||
return frames;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleJettyFrame(WebSocketFrame frame)
|
||||
{
|
||||
incomingFrame(frame);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void incomingError(WebSocketException e)
|
||||
{
|
||||
|
@ -140,7 +127,7 @@ public class IncomingFramesCapture extends AbstractJettyFrameHandler implements
|
|||
}
|
||||
|
||||
@Override
|
||||
public void incomingFrame(WebSocketFrame frame)
|
||||
public void incomingFrame(Frame frame)
|
||||
{
|
||||
WebSocketFrame copy = new WebSocketFrame(frame);
|
||||
frames.add(copy);
|
||||
|
|
|
@ -26,19 +26,14 @@ import java.util.concurrent.Future;
|
|||
import javax.net.websocket.SendResult;
|
||||
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.websocket.common.extensions.AbstractJettyFrameHandler;
|
||||
import org.eclipse.jetty.websocket.common.io.OutgoingFrames;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames;
|
||||
import org.junit.Assert;
|
||||
|
||||
public class OutgoingFramesCapture extends AbstractJettyFrameHandler implements OutgoingFrames
|
||||
public class OutgoingFramesCapture implements OutgoingFrames
|
||||
{
|
||||
private LinkedList<WebSocketFrame> frames = new LinkedList<>();
|
||||
|
||||
public OutgoingFramesCapture()
|
||||
{
|
||||
super(null); // Do not forward frames anywhere else, capture is the end of the line
|
||||
}
|
||||
|
||||
public void assertFrameCount(int expectedCount)
|
||||
{
|
||||
Assert.assertThat("Captured frame count",frames.size(),is(expectedCount));
|
||||
|
@ -64,7 +59,7 @@ public class OutgoingFramesCapture extends AbstractJettyFrameHandler implements
|
|||
System.out.printf("Captured %d outgoing writes%n",frames.size());
|
||||
for (int i = 0; i < frames.size(); i++)
|
||||
{
|
||||
WebSocketFrame frame = frames.get(i);
|
||||
Frame frame = frames.get(i);
|
||||
System.out.printf("[%3d] %s%n",i,frame);
|
||||
System.out.printf(" %s%n",BufferUtil.toDetailString(frame.getPayload()));
|
||||
}
|
||||
|
@ -89,16 +84,11 @@ public class OutgoingFramesCapture extends AbstractJettyFrameHandler implements
|
|||
}
|
||||
|
||||
@Override
|
||||
public void handleJettyFrame(WebSocketFrame frame)
|
||||
public Future<SendResult> outgoingFrame(Frame frame)
|
||||
{
|
||||
outgoingFrame(frame);
|
||||
}
|
||||
WebSocketFrame copy = new WebSocketFrame(frame);
|
||||
frames.add(copy);
|
||||
|
||||
@Override
|
||||
public Future<SendResult> outgoingFrame(WebSocketFrame frame)
|
||||
{
|
||||
frames.add(frame);
|
||||
|
||||
return null; // FIXME: should return completed future.
|
||||
return FinishedFuture.INSTANCE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,21 +30,20 @@ import javax.net.websocket.SendResult;
|
|||
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.TypeUtil;
|
||||
import org.eclipse.jetty.websocket.common.extensions.AbstractJettyFrameHandler;
|
||||
import org.eclipse.jetty.websocket.common.io.OutgoingFrames;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames;
|
||||
import org.junit.Assert;
|
||||
|
||||
/**
|
||||
* Capture outgoing network bytes.
|
||||
*/
|
||||
public class OutgoingNetworkBytesCapture extends AbstractJettyFrameHandler implements OutgoingFrames
|
||||
public class OutgoingNetworkBytesCapture implements OutgoingFrames
|
||||
{
|
||||
private final Generator generator;
|
||||
private List<ByteBuffer> captured;
|
||||
|
||||
public OutgoingNetworkBytesCapture(Generator generator)
|
||||
{
|
||||
super(null); // no sub handling, capture is end of the line.
|
||||
this.generator = generator;
|
||||
this.captured = new ArrayList<>();
|
||||
}
|
||||
|
@ -63,24 +62,11 @@ public class OutgoingNetworkBytesCapture extends AbstractJettyFrameHandler imple
|
|||
}
|
||||
|
||||
@Override
|
||||
public void handleJettyFrame(WebSocketFrame frame)
|
||||
{
|
||||
try
|
||||
{
|
||||
outgoingFrame(frame);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<SendResult> outgoingFrame(WebSocketFrame frame) throws IOException
|
||||
public Future<SendResult> outgoingFrame(Frame frame) throws IOException
|
||||
{
|
||||
ByteBuffer buf = generator.generate(frame);
|
||||
captured.add(buf.slice());
|
||||
|
||||
return null; // FIXME: should return completed future.
|
||||
return FinishedFuture.INSTANCE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import java.nio.ByteBuffer;
|
|||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketBehavior;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.common.OpCode;
|
||||
import org.eclipse.jetty.websocket.common.Parser;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
|
@ -146,7 +147,7 @@ public class RFC6455ExamplesParserTest
|
|||
capture.assertNoErrors();
|
||||
capture.assertHasFrame(OpCode.BINARY,1);
|
||||
|
||||
WebSocketFrame bin = capture.getFrames().get(0);
|
||||
Frame bin = capture.getFrames().get(0);
|
||||
|
||||
Assert.assertThat("BinaryFrame.payloadLength",bin.getPayloadLength(),is(dataSize));
|
||||
|
||||
|
@ -186,7 +187,7 @@ public class RFC6455ExamplesParserTest
|
|||
capture.assertNoErrors();
|
||||
capture.assertHasFrame(OpCode.BINARY,1);
|
||||
|
||||
WebSocketFrame bin = capture.getFrames().get(0);
|
||||
Frame bin = capture.getFrames().get(0);
|
||||
|
||||
Assert.assertThat("BinaryFrame.payloadLength",bin.getPayloadLength(),is(dataSize));
|
||||
ByteBuffer data = bin.getPayload();
|
||||
|
|
|
@ -24,8 +24,7 @@ import java.util.List;
|
|||
import org.eclipse.jetty.io.MappedByteBufferPool;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.common.Generator;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
|
||||
/**
|
||||
* Convenience Generator.
|
||||
|
@ -34,7 +33,7 @@ public class UnitGenerator extends Generator
|
|||
{
|
||||
public static ByteBuffer generate(List<WebSocketFrame> frames)
|
||||
{
|
||||
// Create non-symmetrical mask (shows mask bytes order issues)
|
||||
// Create non-symmetrical mask (helps show mask bytes order issues)
|
||||
byte[] MASK =
|
||||
{ 0x11, 0x22, 0x33, 0x44 };
|
||||
|
||||
|
@ -43,7 +42,7 @@ public class UnitGenerator extends Generator
|
|||
|
||||
// Generate into single bytebuffer
|
||||
int buflen = 0;
|
||||
for (WebSocketFrame f : frames)
|
||||
for (Frame f : frames)
|
||||
{
|
||||
buflen += f.getPayloadLength() + Generator.OVERHEAD;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import java.nio.ByteBuffer;
|
|||
|
||||
import org.eclipse.jetty.websocket.api.WebSocketBehavior;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.common.ByteBufferAssert;
|
||||
import org.eclipse.jetty.websocket.common.Generator;
|
||||
import org.eclipse.jetty.websocket.common.IncomingFramesCapture;
|
||||
|
@ -320,7 +321,7 @@ public class TestABCase1_1
|
|||
capture.assertNoErrors();
|
||||
capture.assertHasFrame(OpCode.TEXT,1);
|
||||
|
||||
WebSocketFrame pActual = capture.getFrames().get(0);
|
||||
Frame pActual = capture.getFrames().get(0);
|
||||
Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length));
|
||||
// Assert.assertEquals("TextFrame.payload",length,pActual.getPayloadData().length);
|
||||
}
|
||||
|
@ -354,7 +355,7 @@ public class TestABCase1_1
|
|||
capture.assertNoErrors();
|
||||
capture.assertHasFrame(OpCode.TEXT,1);
|
||||
|
||||
WebSocketFrame pActual = capture.getFrames().get(0);
|
||||
Frame pActual = capture.getFrames().get(0);
|
||||
Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length));
|
||||
// Assert.assertEquals("TextFrame.payload",length,pActual.getPayloadData().length);
|
||||
}
|
||||
|
@ -388,7 +389,7 @@ public class TestABCase1_1
|
|||
capture.assertNoErrors();
|
||||
capture.assertHasFrame(OpCode.TEXT,1);
|
||||
|
||||
WebSocketFrame pActual = capture.getFrames().get(0);
|
||||
Frame pActual = capture.getFrames().get(0);
|
||||
Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length));
|
||||
// Assert.assertEquals("TextFrame.payload",length,pActual.getPayloadData().length);
|
||||
}
|
||||
|
@ -422,7 +423,7 @@ public class TestABCase1_1
|
|||
capture.assertNoErrors();
|
||||
capture.assertHasFrame(OpCode.TEXT,1);
|
||||
|
||||
WebSocketFrame pActual = capture.getFrames().get(0);
|
||||
Frame pActual = capture.getFrames().get(0);
|
||||
Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length));
|
||||
// .assertEquals("TextFrame.payload",length,pActual.getPayloadData().length);
|
||||
}
|
||||
|
@ -461,7 +462,7 @@ public class TestABCase1_1
|
|||
capture.assertNoErrors();
|
||||
capture.assertHasFrame(OpCode.TEXT,1);
|
||||
|
||||
WebSocketFrame pActual = capture.getFrames().get(0);
|
||||
Frame pActual = capture.getFrames().get(0);
|
||||
Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length));
|
||||
// Assert.assertEquals("TextFrame.payload",length,pActual.getPayloadData().length);
|
||||
}
|
||||
|
@ -498,7 +499,7 @@ public class TestABCase1_1
|
|||
capture.assertNoErrors();
|
||||
capture.assertHasFrame(OpCode.TEXT,1);
|
||||
|
||||
WebSocketFrame pActual = capture.getFrames().get(0);
|
||||
Frame pActual = capture.getFrames().get(0);
|
||||
Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length));
|
||||
// Assert.assertEquals("TextFrame.payload",length,pActual.getPayloadData().length);
|
||||
}
|
||||
|
@ -522,7 +523,7 @@ public class TestABCase1_1
|
|||
capture.assertNoErrors();
|
||||
capture.assertHasFrame(OpCode.TEXT,1);
|
||||
|
||||
WebSocketFrame pActual = capture.getFrames().get(0);
|
||||
Frame pActual = capture.getFrames().get(0);
|
||||
Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(0));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import java.nio.ByteBuffer;
|
|||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketBehavior;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.common.ByteBufferAssert;
|
||||
import org.eclipse.jetty.websocket.common.Generator;
|
||||
import org.eclipse.jetty.websocket.common.IncomingFramesCapture;
|
||||
|
@ -336,7 +337,7 @@ public class TestABCase1_2
|
|||
capture.assertNoErrors();
|
||||
capture.assertHasFrame(OpCode.BINARY,1);
|
||||
|
||||
WebSocketFrame pActual = capture.getFrames().get(0);
|
||||
Frame pActual = capture.getFrames().get(0);
|
||||
Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length));
|
||||
// Assert.assertEquals("BinaryFrame.payload",length,pActual.getPayloadData().length);
|
||||
}
|
||||
|
@ -370,7 +371,7 @@ public class TestABCase1_2
|
|||
capture.assertNoErrors();
|
||||
capture.assertHasFrame(OpCode.BINARY,1);
|
||||
|
||||
WebSocketFrame pActual = capture.getFrames().get(0);
|
||||
Frame pActual = capture.getFrames().get(0);
|
||||
Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length));
|
||||
// Assert.assertEquals("BinaryFrame.payload",length,pActual.getPayloadData().length);
|
||||
}
|
||||
|
@ -404,7 +405,7 @@ public class TestABCase1_2
|
|||
capture.assertNoErrors();
|
||||
capture.assertHasFrame(OpCode.BINARY,1);
|
||||
|
||||
WebSocketFrame pActual = capture.getFrames().get(0);
|
||||
Frame pActual = capture.getFrames().get(0);
|
||||
Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length));
|
||||
// .assertEquals("BinaryFrame.payload",length,pActual.getPayloadData().length);
|
||||
}
|
||||
|
@ -438,7 +439,7 @@ public class TestABCase1_2
|
|||
capture.assertNoErrors();
|
||||
capture.assertHasFrame(OpCode.BINARY,1);
|
||||
|
||||
WebSocketFrame pActual = capture.getFrames().get(0);
|
||||
Frame pActual = capture.getFrames().get(0);
|
||||
Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length));
|
||||
// Assert.assertEquals("BinaryFrame.payload",length,pActual.getPayloadData().length);
|
||||
}
|
||||
|
@ -473,7 +474,7 @@ public class TestABCase1_2
|
|||
capture.assertNoErrors();
|
||||
capture.assertHasFrame(OpCode.BINARY,1);
|
||||
|
||||
WebSocketFrame pActual = capture.getFrames().get(0);
|
||||
Frame pActual = capture.getFrames().get(0);
|
||||
Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length));
|
||||
// Assert.assertEquals("BinaryFrame.payload",length,pActual.getPayloadData().length);
|
||||
}
|
||||
|
@ -510,7 +511,7 @@ public class TestABCase1_2
|
|||
capture.assertNoErrors();
|
||||
capture.assertHasFrame(OpCode.BINARY,1);
|
||||
|
||||
WebSocketFrame pActual = capture.getFrames().get(0);
|
||||
Frame pActual = capture.getFrames().get(0);
|
||||
Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length));
|
||||
// Assert.assertEquals("BinaryFrame.payload",length,pActual.getPayloadData().length);
|
||||
}
|
||||
|
@ -534,7 +535,7 @@ public class TestABCase1_2
|
|||
capture.assertNoErrors();
|
||||
capture.assertHasFrame(OpCode.BINARY,1);
|
||||
|
||||
WebSocketFrame pActual = capture.getFrames().get(0);
|
||||
Frame pActual = capture.getFrames().get(0);
|
||||
Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(0));
|
||||
// Assert.assertNull("BinaryFrame.payload",pActual.getPayloadData());
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.eclipse.jetty.websocket.api.ProtocolException;
|
|||
import org.eclipse.jetty.websocket.api.WebSocketBehavior;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketException;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.common.ByteBufferAssert;
|
||||
import org.eclipse.jetty.websocket.common.Generator;
|
||||
import org.eclipse.jetty.websocket.common.IncomingFramesCapture;
|
||||
|
@ -201,7 +202,7 @@ public class TestABCase2
|
|||
capture.assertNoErrors();
|
||||
capture.assertHasFrame(OpCode.PING,1);
|
||||
|
||||
WebSocketFrame pActual = capture.getFrames().get(0);
|
||||
Frame pActual = capture.getFrames().get(0);
|
||||
Assert.assertThat("PingFrame.payloadLength",pActual.getPayloadLength(),is(bytes.length));
|
||||
Assert.assertEquals("PingFrame.payload",bytes.length,pActual.getPayloadLength());
|
||||
}
|
||||
|
@ -231,7 +232,7 @@ public class TestABCase2
|
|||
capture.assertNoErrors();
|
||||
capture.assertHasFrame(OpCode.PING,1);
|
||||
|
||||
WebSocketFrame pActual = capture.getFrames().get(0);
|
||||
Frame pActual = capture.getFrames().get(0);
|
||||
Assert.assertThat("PingFrame.payloadLength",pActual.getPayloadLength(),is(bytes.length));
|
||||
Assert.assertEquals("PingFrame.payload",bytes.length,pActual.getPayloadLength());
|
||||
}
|
||||
|
@ -254,7 +255,7 @@ public class TestABCase2
|
|||
capture.assertNoErrors();
|
||||
capture.assertHasFrame(OpCode.PING,1);
|
||||
|
||||
WebSocketFrame pActual = capture.getFrames().get(0);
|
||||
Frame pActual = capture.getFrames().get(0);
|
||||
Assert.assertThat("PingFrame.payloadLength",pActual.getPayloadLength(),is(0));
|
||||
Assert.assertEquals("PingFrame.payload",0,pActual.getPayloadLength());
|
||||
}
|
||||
|
@ -285,7 +286,7 @@ public class TestABCase2
|
|||
capture.assertNoErrors();
|
||||
capture.assertHasFrame(OpCode.PING,1);
|
||||
|
||||
WebSocketFrame pActual = capture.getFrames().get(0);
|
||||
Frame pActual = capture.getFrames().get(0);
|
||||
Assert.assertThat("PingFrame.payloadLength",pActual.getPayloadLength(),is(message.length()));
|
||||
Assert.assertEquals("PingFrame.payload",message.length(),pActual.getPayloadLength());
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.eclipse.jetty.util.StringUtil;
|
|||
import org.eclipse.jetty.websocket.api.ProtocolException;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketBehavior;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.common.ByteBufferAssert;
|
||||
import org.eclipse.jetty.websocket.common.CloseInfo;
|
||||
import org.eclipse.jetty.websocket.common.Generator;
|
||||
|
@ -80,7 +81,7 @@ public class TestABCase7_3
|
|||
capture.assertNoErrors();
|
||||
capture.assertHasFrame(OpCode.CLOSE,1);
|
||||
|
||||
WebSocketFrame pActual = capture.getFrames().get(0);
|
||||
Frame pActual = capture.getFrames().get(0);
|
||||
Assert.assertThat("CloseFrame.payloadLength",pActual.getPayloadLength(),is(0));
|
||||
|
||||
}
|
||||
|
@ -154,7 +155,7 @@ public class TestABCase7_3
|
|||
capture.assertNoErrors();
|
||||
capture.assertHasFrame(OpCode.CLOSE,1);
|
||||
|
||||
WebSocketFrame pActual = capture.getFrames().get(0);
|
||||
Frame pActual = capture.getFrames().get(0);
|
||||
Assert.assertThat("CloseFrame.payloadLength",pActual.getPayloadLength(),is(2));
|
||||
|
||||
}
|
||||
|
@ -212,7 +213,7 @@ public class TestABCase7_3
|
|||
capture.assertNoErrors();
|
||||
capture.assertHasFrame(OpCode.CLOSE,1);
|
||||
|
||||
WebSocketFrame pActual = capture.getFrames().get(0);
|
||||
Frame pActual = capture.getFrames().get(0);
|
||||
Assert.assertThat("CloseFrame.payloadLength",pActual.getPayloadLength(),is(messageBytes.length + 2));
|
||||
|
||||
}
|
||||
|
@ -282,7 +283,7 @@ public class TestABCase7_3
|
|||
capture.assertNoErrors();
|
||||
capture.assertHasFrame(OpCode.CLOSE,1);
|
||||
|
||||
WebSocketFrame pActual = capture.getFrames().get(0);
|
||||
Frame pActual = capture.getFrames().get(0);
|
||||
Assert.assertThat("CloseFrame.payloadLength",pActual.getPayloadLength(),is(125));
|
||||
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ package org.eclipse.jetty.websocket.common.events;
|
|||
|
||||
import org.eclipse.jetty.websocket.api.StatusCode;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.common.CloseInfo;
|
||||
import org.eclipse.jetty.websocket.common.OpCode;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
|
@ -39,7 +40,7 @@ public class EventDriverTest
|
|||
@Rule
|
||||
public TestName testname = new TestName();
|
||||
|
||||
private WebSocketFrame makeBinaryFrame(String content, boolean fin)
|
||||
private Frame makeBinaryFrame(String content, boolean fin)
|
||||
{
|
||||
return WebSocketFrame.binary().setFin(fin).setPayload(content);
|
||||
}
|
||||
|
@ -50,9 +51,8 @@ public class EventDriverTest
|
|||
AdapterConnectCloseSocket socket = new AdapterConnectCloseSocket();
|
||||
EventDriver driver = wrap(socket);
|
||||
|
||||
LocalWebSocketSession conn = new LocalWebSocketSession(testname);
|
||||
driver.setSession(conn);
|
||||
driver.onConnect();
|
||||
LocalWebSocketSession conn = new LocalWebSocketSession(testname,driver);
|
||||
conn.open();
|
||||
driver.incomingFrame(new CloseInfo(StatusCode.NORMAL).asFrame());
|
||||
|
||||
socket.capture.assertEventCount(2);
|
||||
|
@ -66,9 +66,8 @@ public class EventDriverTest
|
|||
AnnotatedBinaryArraySocket socket = new AnnotatedBinaryArraySocket();
|
||||
EventDriver driver = wrap(socket);
|
||||
|
||||
LocalWebSocketSession conn = new LocalWebSocketSession(testname);
|
||||
driver.setSession(conn);
|
||||
driver.onConnect();
|
||||
LocalWebSocketSession conn = new LocalWebSocketSession(testname,driver);
|
||||
conn.open();
|
||||
driver.incomingFrame(makeBinaryFrame("Hello World",true));
|
||||
driver.incomingFrame(new CloseInfo(StatusCode.NORMAL).asFrame());
|
||||
|
||||
|
@ -84,9 +83,8 @@ public class EventDriverTest
|
|||
AnnotatedFramesSocket socket = new AnnotatedFramesSocket();
|
||||
EventDriver driver = wrap(socket);
|
||||
|
||||
LocalWebSocketSession conn = new LocalWebSocketSession(testname);
|
||||
driver.setSession(conn);
|
||||
driver.onConnect();
|
||||
LocalWebSocketSession conn = new LocalWebSocketSession(testname,driver);
|
||||
conn.open();
|
||||
driver.incomingFrame(new WebSocketFrame(OpCode.PING).setPayload("PING"));
|
||||
driver.incomingFrame(WebSocketFrame.text("Text Me"));
|
||||
driver.incomingFrame(WebSocketFrame.binary().setPayload("Hello Bin"));
|
||||
|
@ -107,9 +105,8 @@ public class EventDriverTest
|
|||
AnnotatedBinaryStreamSocket socket = new AnnotatedBinaryStreamSocket();
|
||||
EventDriver driver = wrap(socket);
|
||||
|
||||
LocalWebSocketSession conn = new LocalWebSocketSession(testname);
|
||||
driver.setSession(conn);
|
||||
driver.onConnect();
|
||||
LocalWebSocketSession conn = new LocalWebSocketSession(testname,driver);
|
||||
conn.open();
|
||||
driver.incomingFrame(makeBinaryFrame("Hello World",true));
|
||||
driver.incomingFrame(new CloseInfo(StatusCode.NORMAL).asFrame());
|
||||
|
||||
|
@ -125,9 +122,8 @@ public class EventDriverTest
|
|||
ListenerBasicSocket socket = new ListenerBasicSocket();
|
||||
EventDriver driver = wrap(socket);
|
||||
|
||||
LocalWebSocketSession conn = new LocalWebSocketSession(testname);
|
||||
driver.setSession(conn);
|
||||
driver.onConnect();
|
||||
LocalWebSocketSession conn = new LocalWebSocketSession(testname,driver);
|
||||
conn.open();
|
||||
driver.incomingFrame(WebSocketFrame.text("Hello World"));
|
||||
driver.incomingFrame(new CloseInfo(StatusCode.NORMAL).asFrame());
|
||||
|
||||
|
|
|
@ -26,13 +26,12 @@ import java.util.ArrayList;
|
|||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.net.websocket.extensions.FrameHandler;
|
||||
|
||||
import org.eclipse.jetty.io.MappedByteBufferPool;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.common.ByteBufferAssert;
|
||||
import org.eclipse.jetty.websocket.common.IncomingFramesCapture;
|
||||
import org.eclipse.jetty.websocket.common.OpCode;
|
||||
|
@ -58,7 +57,7 @@ public class FragmentExtensionTest
|
|||
ExtensionConfig config = ExtensionConfig.parse("fragment;maxLength=4");
|
||||
ext.setConfig(config);
|
||||
|
||||
FrameHandler incomingHandler = ext.createIncomingFrameHandler(capture);
|
||||
ext.setNextIncomingFrames(capture);
|
||||
|
||||
// Quote
|
||||
List<String> quote = new ArrayList<>();
|
||||
|
@ -69,8 +68,8 @@ public class FragmentExtensionTest
|
|||
// Manually create frame and pass into extension
|
||||
for (String q : quote)
|
||||
{
|
||||
WebSocketFrame frame = WebSocketFrame.text(q);
|
||||
incomingHandler.handleFrame(frame);
|
||||
Frame frame = WebSocketFrame.text(q);
|
||||
ext.incomingFrame(frame);
|
||||
}
|
||||
|
||||
int len = quote.size();
|
||||
|
@ -110,11 +109,11 @@ public class FragmentExtensionTest
|
|||
ExtensionConfig config = ExtensionConfig.parse("fragment;maxLength=4");
|
||||
ext.setConfig(config);
|
||||
|
||||
FrameHandler incomingHandler = ext.createIncomingFrameHandler(capture);
|
||||
ext.setNextIncomingFrames(capture);
|
||||
|
||||
String payload = "Are you there?";
|
||||
WebSocketFrame ping = WebSocketFrame.ping().setPayload(payload);
|
||||
incomingHandler.handleFrame(ping);
|
||||
Frame ping = WebSocketFrame.ping().setPayload(payload);
|
||||
ext.incomingFrame(ping);
|
||||
|
||||
capture.assertFrameCount(1);
|
||||
capture.assertHasFrame(OpCode.PING,1);
|
||||
|
@ -145,7 +144,7 @@ public class FragmentExtensionTest
|
|||
ExtensionConfig config = ExtensionConfig.parse("fragment;maxLength=20");
|
||||
ext.setConfig(config);
|
||||
|
||||
FrameHandler outgoingHandler = ext.createOutgoingFrameHandler(capture);
|
||||
ext.setNextOutgoingFrames(capture);
|
||||
|
||||
// Quote
|
||||
List<String> quote = new ArrayList<>();
|
||||
|
@ -156,8 +155,8 @@ public class FragmentExtensionTest
|
|||
// Write quote as separate frames
|
||||
for (String section : quote)
|
||||
{
|
||||
WebSocketFrame frame = WebSocketFrame.text(section);
|
||||
outgoingHandler.handleFrame(frame);
|
||||
Frame frame = WebSocketFrame.text(section);
|
||||
ext.outgoingFrame(frame);
|
||||
}
|
||||
|
||||
// Expected Frames
|
||||
|
@ -214,7 +213,7 @@ public class FragmentExtensionTest
|
|||
ExtensionConfig config = ExtensionConfig.parse("fragment");
|
||||
ext.setConfig(config);
|
||||
|
||||
FrameHandler outgoingHandler = ext.createOutgoingFrameHandler(capture);
|
||||
ext.setNextOutgoingFrames(capture);
|
||||
|
||||
// Quote
|
||||
List<String> quote = new ArrayList<>();
|
||||
|
@ -225,8 +224,8 @@ public class FragmentExtensionTest
|
|||
// Write quote as separate frames
|
||||
for (String section : quote)
|
||||
{
|
||||
WebSocketFrame frame = WebSocketFrame.text(section);
|
||||
outgoingHandler.handleFrame(frame);
|
||||
Frame frame = WebSocketFrame.text(section);
|
||||
ext.outgoingFrame(frame);
|
||||
}
|
||||
|
||||
// Expected Frames
|
||||
|
@ -278,12 +277,12 @@ public class FragmentExtensionTest
|
|||
ExtensionConfig config = ExtensionConfig.parse("fragment;maxLength=4");
|
||||
ext.setConfig(config);
|
||||
|
||||
FrameHandler outgoingHandler = ext.createOutgoingFrameHandler(capture);
|
||||
ext.setNextOutgoingFrames(capture);
|
||||
|
||||
String payload = "Are you there?";
|
||||
WebSocketFrame ping = WebSocketFrame.ping().setPayload(payload);
|
||||
Frame ping = WebSocketFrame.ping().setPayload(payload);
|
||||
|
||||
outgoingHandler.handleFrame(ping);
|
||||
ext.outgoingFrame(ping);
|
||||
|
||||
capture.assertFrameCount(1);
|
||||
capture.assertHasFrame(OpCode.PING,1);
|
||||
|
|
|
@ -23,11 +23,10 @@ import static org.hamcrest.Matchers.*;
|
|||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import javax.net.websocket.extensions.FrameHandler;
|
||||
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Extension;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.common.ByteBufferAssert;
|
||||
import org.eclipse.jetty.websocket.common.IncomingFramesCapture;
|
||||
import org.eclipse.jetty.websocket.common.OpCode;
|
||||
|
@ -48,10 +47,10 @@ public class IdentityExtensionTest
|
|||
IncomingFramesCapture capture = new IncomingFramesCapture();
|
||||
|
||||
Extension ext = new IdentityExtension();
|
||||
FrameHandler incomingHandler = ext.createIncomingFrameHandler(capture);
|
||||
ext.setNextIncomingFrames(capture);
|
||||
|
||||
WebSocketFrame frame = WebSocketFrame.text("hello");
|
||||
incomingHandler.handleFrame(frame);
|
||||
Frame frame = WebSocketFrame.text("hello");
|
||||
ext.incomingFrame(frame);
|
||||
|
||||
capture.assertFrameCount(1);
|
||||
capture.assertHasFrame(OpCode.TEXT,1);
|
||||
|
@ -77,10 +76,10 @@ public class IdentityExtensionTest
|
|||
OutgoingFramesCapture capture = new OutgoingFramesCapture();
|
||||
|
||||
Extension ext = new IdentityExtension();
|
||||
FrameHandler outgoingHandler = ext.createOutgoingFrameHandler(capture);
|
||||
ext.setNextOutgoingFrames(capture);
|
||||
|
||||
WebSocketFrame frame = WebSocketFrame.text("hello");
|
||||
outgoingHandler.handleFrame(frame);
|
||||
Frame frame = WebSocketFrame.text("hello");
|
||||
ext.outgoingFrame(frame);
|
||||
|
||||
capture.assertFrameCount(1);
|
||||
capture.assertHasFrame(OpCode.TEXT,1);
|
||||
|
|
|
@ -26,14 +26,13 @@ import java.util.ArrayList;
|
|||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.net.websocket.extensions.FrameHandler;
|
||||
|
||||
import org.eclipse.jetty.io.MappedByteBufferPool;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.TypeUtil;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.common.ByteBufferAssert;
|
||||
import org.eclipse.jetty.websocket.common.IncomingFramesCapture;
|
||||
import org.eclipse.jetty.websocket.common.OpCode;
|
||||
|
@ -49,7 +48,7 @@ public class PerMessageCompressionExtensionTest
|
|||
WebSocketPolicy policy = WebSocketPolicy.newServerPolicy();
|
||||
|
||||
// Setup extension
|
||||
PerMessageCompressionExtension ext = new PerMessageCompressionExtension();
|
||||
MessageCompressionExtension ext = new MessageCompressionExtension();
|
||||
ext.setBufferPool(new MappedByteBufferPool());
|
||||
ext.setPolicy(policy);
|
||||
ExtensionConfig config = ExtensionConfig.parse("permessage-compress");
|
||||
|
@ -59,7 +58,7 @@ public class PerMessageCompressionExtensionTest
|
|||
IncomingFramesCapture capture = new IncomingFramesCapture();
|
||||
|
||||
// Wire up stack
|
||||
FrameHandler incomingHandler = ext.createIncomingFrameHandler(capture);
|
||||
ext.setNextIncomingFrames(capture);
|
||||
|
||||
// Receive frame
|
||||
String hex = hexStr.replaceAll("\\s*0x","");
|
||||
|
@ -69,7 +68,7 @@ public class PerMessageCompressionExtensionTest
|
|||
frame.setPayload(net);
|
||||
|
||||
// Send frame into stack
|
||||
incomingHandler.handleFrame(frame);
|
||||
ext.incomingFrame(frame);
|
||||
|
||||
// Verify captured frames.
|
||||
capture.assertFrameCount(1);
|
||||
|
@ -162,7 +161,7 @@ public class PerMessageCompressionExtensionTest
|
|||
*/
|
||||
@Test
|
||||
public void testIncomingPing() {
|
||||
PerMessageCompressionExtension ext = new PerMessageCompressionExtension();
|
||||
MessageCompressionExtension ext = new MessageCompressionExtension();
|
||||
ext.setBufferPool(new MappedByteBufferPool());
|
||||
ext.setPolicy(WebSocketPolicy.newServerPolicy());
|
||||
ExtensionConfig config = ExtensionConfig.parse("permessage-compress");
|
||||
|
@ -172,11 +171,11 @@ public class PerMessageCompressionExtensionTest
|
|||
IncomingFramesCapture capture = new IncomingFramesCapture();
|
||||
|
||||
// Wire up stack
|
||||
FrameHandler incomingHandler = ext.createIncomingFrameHandler(capture);
|
||||
ext.setNextIncomingFrames(capture);
|
||||
|
||||
String payload = "Are you there?";
|
||||
WebSocketFrame ping = WebSocketFrame.ping().setPayload(payload);
|
||||
incomingHandler.handleFrame(ping);
|
||||
Frame ping = WebSocketFrame.ping().setPayload(payload);
|
||||
ext.incomingFrame(ping);
|
||||
|
||||
capture.assertFrameCount(1);
|
||||
capture.assertHasFrame(OpCode.PING,1);
|
||||
|
@ -199,7 +198,7 @@ public class PerMessageCompressionExtensionTest
|
|||
@Test
|
||||
public void testIncomingUncompressedFrames()
|
||||
{
|
||||
PerMessageCompressionExtension ext = new PerMessageCompressionExtension();
|
||||
MessageCompressionExtension ext = new MessageCompressionExtension();
|
||||
ext.setBufferPool(new MappedByteBufferPool());
|
||||
ext.setPolicy(WebSocketPolicy.newServerPolicy());
|
||||
ExtensionConfig config = ExtensionConfig.parse("permessage-compress");
|
||||
|
@ -209,7 +208,8 @@ public class PerMessageCompressionExtensionTest
|
|||
IncomingFramesCapture capture = new IncomingFramesCapture();
|
||||
|
||||
// Wire up stack
|
||||
FrameHandler incomingHandler = ext.createIncomingFrameHandler(capture);
|
||||
ext.setNextIncomingFrames(capture);
|
||||
|
||||
// Quote
|
||||
List<String> quote = new ArrayList<>();
|
||||
quote.add("No amount of experimentation can ever prove me right;");
|
||||
|
@ -222,7 +222,7 @@ public class PerMessageCompressionExtensionTest
|
|||
WebSocketFrame frame = new WebSocketFrame(OpCode.TEXT);
|
||||
frame.setPayload(q);
|
||||
frame.setRsv1(false); // indication to extension that frame is not compressed (ie: a normal frame)
|
||||
incomingHandler.handleFrame(frame);
|
||||
ext.incomingFrame(frame);
|
||||
}
|
||||
|
||||
int len = quote.size();
|
||||
|
@ -254,7 +254,7 @@ public class PerMessageCompressionExtensionTest
|
|||
@Test
|
||||
public void testOutgoingFrames() throws IOException
|
||||
{
|
||||
PerMessageCompressionExtension ext = new PerMessageCompressionExtension();
|
||||
MessageCompressionExtension ext = new MessageCompressionExtension();
|
||||
ext.setBufferPool(new MappedByteBufferPool());
|
||||
ext.setPolicy(WebSocketPolicy.newServerPolicy());
|
||||
ExtensionConfig config = ExtensionConfig.parse("permessage-compress");
|
||||
|
@ -264,7 +264,7 @@ public class PerMessageCompressionExtensionTest
|
|||
OutgoingFramesCapture capture = new OutgoingFramesCapture();
|
||||
|
||||
// Wire up stack
|
||||
FrameHandler outgoingHandler = ext.createOutgoingFrameHandler(capture);
|
||||
ext.setNextOutgoingFrames(capture);
|
||||
|
||||
// Quote
|
||||
List<String> quote = new ArrayList<>();
|
||||
|
@ -275,8 +275,8 @@ public class PerMessageCompressionExtensionTest
|
|||
// Write quote as separate frames
|
||||
for (String section : quote)
|
||||
{
|
||||
WebSocketFrame frame = WebSocketFrame.text(section);
|
||||
outgoingHandler.handleFrame(frame);
|
||||
Frame frame = WebSocketFrame.text(section);
|
||||
ext.outgoingFrame(frame);
|
||||
}
|
||||
|
||||
int len = quote.size();
|
||||
|
@ -314,7 +314,7 @@ public class PerMessageCompressionExtensionTest
|
|||
@Test
|
||||
public void testOutgoingPing() throws IOException
|
||||
{
|
||||
PerMessageCompressionExtension ext = new PerMessageCompressionExtension();
|
||||
MessageCompressionExtension ext = new MessageCompressionExtension();
|
||||
ext.setBufferPool(new MappedByteBufferPool());
|
||||
ext.setPolicy(WebSocketPolicy.newServerPolicy());
|
||||
ExtensionConfig config = ExtensionConfig.parse("permessage-compress");
|
||||
|
@ -324,12 +324,12 @@ public class PerMessageCompressionExtensionTest
|
|||
OutgoingFramesCapture capture = new OutgoingFramesCapture();
|
||||
|
||||
// Wire up stack
|
||||
FrameHandler outgoingHandler = ext.createOutgoingFrameHandler(capture);
|
||||
ext.setNextOutgoingFrames(capture);
|
||||
|
||||
String payload = "Are you there?";
|
||||
WebSocketFrame ping = WebSocketFrame.ping().setPayload(payload);
|
||||
Frame ping = WebSocketFrame.ping().setPayload(payload);
|
||||
|
||||
outgoingHandler.handleFrame(ping);
|
||||
ext.outgoingFrame(ping);
|
||||
|
||||
capture.assertFrameCount(1);
|
||||
capture.assertHasFrame(OpCode.PING,1);
|
||||
|
|
|
@ -26,8 +26,6 @@ import java.util.Collections;
|
|||
import java.util.zip.Deflater;
|
||||
import java.util.zip.Inflater;
|
||||
|
||||
import javax.net.websocket.extensions.FrameHandler;
|
||||
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.MappedByteBufferPool;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
|
@ -35,6 +33,7 @@ import org.eclipse.jetty.util.StringUtil;
|
|||
import org.eclipse.jetty.util.TypeUtil;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.common.ByteBufferAssert;
|
||||
import org.eclipse.jetty.websocket.common.Generator;
|
||||
import org.eclipse.jetty.websocket.common.IncomingFramesCapture;
|
||||
|
@ -42,8 +41,6 @@ import org.eclipse.jetty.websocket.common.OpCode;
|
|||
import org.eclipse.jetty.websocket.common.OutgoingNetworkBytesCapture;
|
||||
import org.eclipse.jetty.websocket.common.Parser;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.extensions.IncomingFrameHandler;
|
||||
import org.eclipse.jetty.websocket.common.io.IncomingFrames;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -53,7 +50,7 @@ public class WebkitDeflateFrameExtensionTest
|
|||
{
|
||||
WebSocketPolicy policy = WebSocketPolicy.newServerPolicy();
|
||||
|
||||
WebkitDeflateFrameExtension ext = new WebkitDeflateFrameExtension();
|
||||
FrameCompressionExtension ext = new FrameCompressionExtension();
|
||||
ext.setBufferPool(new MappedByteBufferPool());
|
||||
ext.setPolicy(policy);
|
||||
|
||||
|
@ -64,12 +61,11 @@ public class WebkitDeflateFrameExtensionTest
|
|||
IncomingFramesCapture capture = new IncomingFramesCapture();
|
||||
|
||||
// Wire up stack
|
||||
FrameHandler incomingHandler = ext.createIncomingFrameHandler(capture);
|
||||
IncomingFrames incoming = new IncomingFrameHandler(incomingHandler);
|
||||
ext.setNextIncomingFrames(capture);
|
||||
|
||||
Parser parser = new Parser(policy);
|
||||
parser.configureFromExtensions(Collections.singletonList(ext));
|
||||
parser.setIncomingFramesHandler(incoming);
|
||||
parser.setIncomingFramesHandler(ext);
|
||||
|
||||
parser.parse(ByteBuffer.wrap(raw));
|
||||
|
||||
|
@ -97,7 +93,7 @@ public class WebkitDeflateFrameExtensionTest
|
|||
{
|
||||
WebSocketPolicy policy = WebSocketPolicy.newServerPolicy();
|
||||
|
||||
WebkitDeflateFrameExtension ext = new WebkitDeflateFrameExtension();
|
||||
FrameCompressionExtension ext = new FrameCompressionExtension();
|
||||
ext.setBufferPool(new MappedByteBufferPool());
|
||||
ext.setPolicy(policy);
|
||||
|
||||
|
@ -110,10 +106,10 @@ public class WebkitDeflateFrameExtensionTest
|
|||
generator.configureFromExtensions(Collections.singletonList(ext));
|
||||
|
||||
OutgoingNetworkBytesCapture capture = new OutgoingNetworkBytesCapture(generator);
|
||||
FrameHandler outgoingHandler = ext.createOutgoingFrameHandler(capture);
|
||||
ext.setNextOutgoingFrames(capture);
|
||||
|
||||
WebSocketFrame frame = WebSocketFrame.text(text);
|
||||
outgoingHandler.handleFrame(frame);
|
||||
Frame frame = WebSocketFrame.text(text);
|
||||
ext.outgoingFrame(frame);
|
||||
|
||||
capture.assertBytes(0,expectedHex);
|
||||
}
|
||||
|
|
|
@ -23,8 +23,8 @@ import java.util.concurrent.Future;
|
|||
|
||||
import javax.net.websocket.SendResult;
|
||||
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.io.OutgoingFrames;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames;
|
||||
|
||||
/**
|
||||
* Helpful utility class to parse arbitrary mux events from a physical connection's OutgoingFrames.
|
||||
|
@ -42,7 +42,7 @@ public class MuxDecoder extends MuxEventCapture implements OutgoingFrames
|
|||
}
|
||||
|
||||
@Override
|
||||
public Future<SendResult> outgoingFrame(WebSocketFrame frame) throws IOException
|
||||
public Future<SendResult> outgoingFrame(Frame frame) throws IOException
|
||||
{
|
||||
parser.parse(frame);
|
||||
return null; // FIXME: should return completed future.
|
||||
|
|
|
@ -20,12 +20,12 @@ package org.eclipse.jetty.websocket.common.extensions.mux;
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.extensions.IncomingFrames;
|
||||
import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.extensions.mux.MuxControlBlock;
|
||||
import org.eclipse.jetty.websocket.common.extensions.mux.MuxGenerator;
|
||||
import org.eclipse.jetty.websocket.common.io.FramePipes;
|
||||
import org.eclipse.jetty.websocket.common.io.IncomingFrames;
|
||||
import org.eclipse.jetty.websocket.common.io.OutgoingFrames;
|
||||
|
||||
/**
|
||||
* Helpful utility class to send arbitrary mux events into a physical connection's IncomingFrames.
|
||||
|
|
|
@ -32,6 +32,7 @@ import java.util.regex.Pattern;
|
|||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.TypeUtil;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.common.IncomingFramesCapture;
|
||||
import org.eclipse.jetty.websocket.common.OpCode;
|
||||
import org.eclipse.jetty.websocket.common.Parser;
|
||||
|
@ -81,7 +82,7 @@ public class MuxParserRFCTest
|
|||
MuxParser parser = new MuxParser();
|
||||
MuxEventCapture capture = new MuxEventCapture();
|
||||
parser.setEvents(capture);
|
||||
for(WebSocketFrame frame: frames) {
|
||||
for(Frame frame: frames) {
|
||||
parser.parse(frame);
|
||||
}
|
||||
return capture;
|
||||
|
|
|
@ -18,9 +18,8 @@
|
|||
|
||||
package org.eclipse.jetty.websocket.common.extensions.mux.add;
|
||||
|
||||
import org.eclipse.jetty.websocket.common.extensions.mux.add.MuxAddClient;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketSession;
|
||||
import org.eclipse.jetty.websocket.common.extensions.mux.op.MuxAddChannelResponse;
|
||||
import org.eclipse.jetty.websocket.common.io.WebSocketSession;
|
||||
|
||||
public class DummyMuxAddClient implements MuxAddClient
|
||||
{
|
||||
|
|
|
@ -25,14 +25,13 @@ import org.eclipse.jetty.util.log.Logger;
|
|||
import org.eclipse.jetty.websocket.api.UpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.api.UpgradeResponse;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketSession;
|
||||
import org.eclipse.jetty.websocket.common.events.EventDriver;
|
||||
import org.eclipse.jetty.websocket.common.events.EventDriverFactory;
|
||||
import org.eclipse.jetty.websocket.common.extensions.mux.MuxChannel;
|
||||
import org.eclipse.jetty.websocket.common.extensions.mux.MuxException;
|
||||
import org.eclipse.jetty.websocket.common.extensions.mux.Muxer;
|
||||
import org.eclipse.jetty.websocket.common.extensions.mux.add.MuxAddServer;
|
||||
import org.eclipse.jetty.websocket.common.extensions.mux.op.MuxAddChannelResponse;
|
||||
import org.eclipse.jetty.websocket.common.io.WebSocketSession;
|
||||
|
||||
import examples.echo.AdapterEchoSocket;
|
||||
|
||||
|
@ -79,11 +78,12 @@ public class DummyMuxAddServer implements MuxAddServer
|
|||
response.append("\r\n");
|
||||
|
||||
EventDriver websocket = this.eventDriverFactory.wrap(echo);
|
||||
WebSocketSession session = new WebSocketSession(websocket,channel,channel.getPolicy(),"echo");
|
||||
WebSocketSession session = new WebSocketSession(request.getRequestURI(),websocket,channel);
|
||||
session.setNegotiatedSubprotocol("echo");
|
||||
channel.setSession(session);
|
||||
channel.setSubProtocol("echo");
|
||||
channel.onOpen();
|
||||
session.onConnect();
|
||||
session.open();
|
||||
|
||||
MuxAddChannelResponse addChannelResponse = new MuxAddChannelResponse();
|
||||
addChannelResponse.setChannelId(channel.getChannelId());
|
||||
|
|
|
@ -60,7 +60,7 @@ public class MuxerAddServerTest
|
|||
muxer.setOutgoingFramesHandler(clientRead);
|
||||
|
||||
// Wire up physical connection to forward incoming frames to muxer
|
||||
physical.setIncoming(muxer);
|
||||
physical.setNextIncomingFrames(muxer);
|
||||
|
||||
// Client simulator
|
||||
// Can inject mux encapsulated frames into physical connection as if from
|
||||
|
|
|
@ -30,10 +30,12 @@ import org.eclipse.jetty.websocket.api.SuspendToken;
|
|||
import org.eclipse.jetty.websocket.api.WebSocketConnection;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketException;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.api.extensions.IncomingFrames;
|
||||
import org.eclipse.jetty.websocket.common.CloseInfo;
|
||||
import org.eclipse.jetty.websocket.common.ConnectionState;
|
||||
import org.eclipse.jetty.websocket.common.LogicalConnection;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketSession;
|
||||
import org.junit.rules.TestName;
|
||||
|
||||
public class LocalWebSocketConnection implements WebSocketConnection, LogicalConnection, IncomingFrames
|
||||
|
@ -58,6 +60,16 @@ public class LocalWebSocketConnection implements WebSocketConnection, LogicalCon
|
|||
this.id = testname.getMethodName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void assertInputOpen() throws IOException
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void assertOutputOpen() throws IOException
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
|
@ -105,6 +117,12 @@ public class LocalWebSocketConnection implements WebSocketConnection, LogicalCon
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebSocketSession getSession()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConnectionState getState()
|
||||
{
|
||||
|
@ -124,7 +142,7 @@ public class LocalWebSocketConnection implements WebSocketConnection, LogicalCon
|
|||
}
|
||||
|
||||
@Override
|
||||
public void incomingFrame(WebSocketFrame frame)
|
||||
public void incomingFrame(Frame frame)
|
||||
{
|
||||
incoming.incomingFrame(frame);
|
||||
}
|
||||
|
@ -163,18 +181,23 @@ public class LocalWebSocketConnection implements WebSocketConnection, LogicalCon
|
|||
}
|
||||
|
||||
@Override
|
||||
public Future<SendResult> outgoingFrame(WebSocketFrame frame) throws IOException
|
||||
public Future<SendResult> outgoingFrame(Frame frame) throws IOException
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<SendResult> ping(byte[] payload) throws IOException
|
||||
public void ping(ByteBuffer buf) throws IOException
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setIncoming(IncomingFrames incoming)
|
||||
@Override
|
||||
public void resume()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNextIncomingFrames(IncomingFrames incoming)
|
||||
{
|
||||
this.incoming = incoming;
|
||||
}
|
||||
|
@ -184,6 +207,11 @@ public class LocalWebSocketConnection implements WebSocketConnection, LogicalCon
|
|||
this.policy = policy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSession(WebSocketSession session)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public SuspendToken suspend()
|
||||
{
|
||||
|
|
|
@ -18,10 +18,11 @@
|
|||
|
||||
package org.eclipse.jetty.websocket.common.io;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import java.net.URI;
|
||||
|
||||
import org.eclipse.jetty.websocket.common.OutgoingFramesCapture;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketSession;
|
||||
import org.eclipse.jetty.websocket.common.events.EventDriver;
|
||||
import org.eclipse.jetty.websocket.common.io.WebSocketSession;
|
||||
import org.junit.rules.TestName;
|
||||
|
||||
public class LocalWebSocketSession extends WebSocketSession
|
||||
|
@ -29,17 +30,12 @@ public class LocalWebSocketSession extends WebSocketSession
|
|||
private String id;
|
||||
private OutgoingFramesCapture outgoingCapture;
|
||||
|
||||
public LocalWebSocketSession(TestName testname)
|
||||
{
|
||||
this(testname,null);
|
||||
outgoingCapture = new OutgoingFramesCapture();
|
||||
setOutgoing(outgoingCapture);
|
||||
}
|
||||
|
||||
public LocalWebSocketSession(TestName testname, EventDriver driver)
|
||||
{
|
||||
super(driver,new LocalWebSocketConnection(testname),WebSocketPolicy.newServerPolicy(),"testing");
|
||||
super(URI.create("ws://localhost/LocalWebSocketSesssion/" + testname.getMethodName()),driver,new LocalWebSocketConnection(testname));
|
||||
this.id = testname.getMethodName();
|
||||
outgoingCapture = new OutgoingFramesCapture();
|
||||
setOutgoingHandler(outgoingCapture);
|
||||
}
|
||||
|
||||
public OutgoingFramesCapture getOutgoingCapture()
|
||||
|
|
|
@ -17,17 +17,7 @@
|
|||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.websocket</groupId>
|
||||
<artifactId>websocket-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.websocket</groupId>
|
||||
<artifactId>websocket-common</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.websocket</groupId>
|
||||
<artifactId>websocket-servlet</artifactId>
|
||||
<artifactId>websocket-client</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -16,17 +16,19 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.common.extensions;
|
||||
package org.eclipse.jetty.websocket.server;
|
||||
|
||||
import javax.net.websocket.extensions.FrameHandler;
|
||||
import javax.net.websocket.Endpoint;
|
||||
import javax.net.websocket.ServerContainer;
|
||||
import javax.net.websocket.ServerEndpointConfiguration;
|
||||
|
||||
/**
|
||||
* FrameHandler that just passes frames through with no modification.
|
||||
*/
|
||||
public class PassthruFrameHandler extends FrameHandler
|
||||
import org.eclipse.jetty.websocket.client.JettyClientContainer;
|
||||
|
||||
public class JettyServerContainer extends JettyClientContainer implements ServerContainer
|
||||
{
|
||||
public PassthruFrameHandler(FrameHandler nextHandler)
|
||||
@Override
|
||||
public void publishServer(Endpoint endpoint, ServerEndpointConfiguration ilc)
|
||||
{
|
||||
super(nextHandler);
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
}
|
|
@ -21,20 +21,19 @@ package org.eclipse.jetty.websocket.server;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.eclipse.jetty.util.QuotedStringTokenizer;
|
||||
import org.eclipse.jetty.websocket.api.UpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Extension;
|
||||
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
|
||||
import org.eclipse.jetty.websocket.api.util.QuoteUtil;
|
||||
|
||||
public class ServletWebSocketRequest extends UpgradeRequest
|
||||
{
|
||||
private List<ExtensionConfig> extensions;
|
||||
private Map<String, String> cookieMap;
|
||||
private HttpServletRequest req;
|
||||
|
||||
|
@ -43,12 +42,32 @@ public class ServletWebSocketRequest extends UpgradeRequest
|
|||
super(request.getRequestURI());
|
||||
this.req = request;
|
||||
|
||||
// Copy Request Line Details
|
||||
setMethod(request.getMethod());
|
||||
setHttpVersion(request.getProtocol());
|
||||
|
||||
// Copy Cookies
|
||||
cookieMap = new HashMap<String, String>();
|
||||
for (Cookie cookie : request.getCookies())
|
||||
{
|
||||
cookieMap.put(cookie.getName(),cookie.getValue());
|
||||
}
|
||||
|
||||
// Copy Headers
|
||||
Enumeration<String> headerNames = request.getHeaderNames();
|
||||
while (headerNames.hasMoreElements())
|
||||
{
|
||||
String name = headerNames.nextElement();
|
||||
Enumeration<String> valuesEnum = request.getHeaders(name);
|
||||
List<String> values = new ArrayList<>();
|
||||
while (valuesEnum.hasMoreElements())
|
||||
{
|
||||
values.add(valuesEnum.nextElement());
|
||||
}
|
||||
setHeader(name,values);
|
||||
}
|
||||
|
||||
// Parse Sub Protocols
|
||||
Enumeration<String> protocols = request.getHeaders("Sec-WebSocket-Protocol");
|
||||
List<String> subProtocols = new ArrayList<>();
|
||||
String protocol = null;
|
||||
|
@ -62,14 +81,15 @@ public class ServletWebSocketRequest extends UpgradeRequest
|
|||
}
|
||||
setSubProtocols(subProtocols);
|
||||
|
||||
extensions = new ArrayList<>();
|
||||
// Parse Extension Configurations
|
||||
Enumeration<String> e = request.getHeaders("Sec-WebSocket-Extensions");
|
||||
while (e.hasMoreElements())
|
||||
{
|
||||
QuotedStringTokenizer tok = new QuotedStringTokenizer(e.nextElement(),",");
|
||||
while (tok.hasMoreTokens())
|
||||
Iterator<String> extTokenIter = QuoteUtil.splitAt(e.nextElement(),",");
|
||||
while (extTokenIter.hasNext())
|
||||
{
|
||||
ExtensionConfig config = ExtensionConfig.parse(tok.nextToken());
|
||||
String extToken = extTokenIter.next();
|
||||
ExtensionConfig config = ExtensionConfig.parse(extToken);
|
||||
addExtensions(config);
|
||||
}
|
||||
}
|
||||
|
@ -98,21 +118,4 @@ public class ServletWebSocketRequest extends UpgradeRequest
|
|||
{
|
||||
this.req.setAttribute(name,o);
|
||||
}
|
||||
|
||||
public void setValidExtensions(List<Extension> valid)
|
||||
{
|
||||
if (this.extensions != null)
|
||||
{
|
||||
this.extensions.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.extensions = new ArrayList<>();
|
||||
}
|
||||
|
||||
for (Extension ext : valid)
|
||||
{
|
||||
extensions.add(ext.getConfig());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,19 +32,24 @@ public class ServletWebSocketResponse extends UpgradeResponse
|
|||
{
|
||||
super();
|
||||
this.resp = resp;
|
||||
// TODO: copy values from resp
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addHeader(String name, String value)
|
||||
{
|
||||
this.resp.addHeader(name,value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStatusCode()
|
||||
{
|
||||
throw new UnsupportedOperationException("Server cannot get Status Code");
|
||||
return this.resp.getStatus();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStatusReason()
|
||||
{
|
||||
throw new UnsupportedOperationException("Server cannot get Status Reason");
|
||||
throw new UnsupportedOperationException("Server cannot get Status Reason Message");
|
||||
}
|
||||
|
||||
public boolean isCommitted()
|
||||
|
@ -65,6 +70,12 @@ public class ServletWebSocketResponse extends UpgradeResponse
|
|||
resp.sendError(HttpServletResponse.SC_FORBIDDEN,message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHeader(String name, String value)
|
||||
{
|
||||
this.resp.setHeader(name,value);
|
||||
}
|
||||
|
||||
public void setStatus(int status)
|
||||
{
|
||||
this.resp.setStatus(status);
|
||||
|
|
|
@ -20,15 +20,15 @@ package org.eclipse.jetty.websocket.server;
|
|||
|
||||
import org.eclipse.jetty.websocket.api.UpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.api.UpgradeResponse;
|
||||
import org.eclipse.jetty.websocket.common.io.InternalConnection;
|
||||
import org.eclipse.jetty.websocket.common.LogicalConnection;
|
||||
|
||||
public class UpgradeContext
|
||||
{
|
||||
private InternalConnection connection;
|
||||
private LogicalConnection connection;
|
||||
private UpgradeRequest request;
|
||||
private UpgradeResponse response;
|
||||
|
||||
public InternalConnection getConnection()
|
||||
public LogicalConnection getConnection()
|
||||
{
|
||||
return connection;
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ public class UpgradeContext
|
|||
return response;
|
||||
}
|
||||
|
||||
public void setConnection(InternalConnection connection)
|
||||
public void setConnection(LogicalConnection connection)
|
||||
{
|
||||
this.connection = connection;
|
||||
}
|
||||
|
|
|
@ -18,16 +18,15 @@
|
|||
|
||||
package org.eclipse.jetty.websocket.server;
|
||||
|
||||
import java.util.List;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.util.thread.Scheduler;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Extension;
|
||||
import org.eclipse.jetty.websocket.api.extensions.IncomingFrames;
|
||||
import org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection;
|
||||
import org.eclipse.jetty.websocket.common.io.IncomingFrames;
|
||||
|
||||
public class WebSocketServerConnection extends AbstractWebSocketConnection
|
||||
{
|
||||
|
@ -43,10 +42,15 @@ public class WebSocketServerConnection extends AbstractWebSocketConnection
|
|||
}
|
||||
|
||||
@Override
|
||||
public void configureFromExtensions(List<Extension> extensions)
|
||||
public InetSocketAddress getLocalAddress()
|
||||
{
|
||||
getParser().configureFromExtensions(extensions);
|
||||
getGenerator().configureFromExtensions(extensions);
|
||||
return getEndPoint().getLocalAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress getRemoteAddress()
|
||||
{
|
||||
return getEndPoint().getRemoteAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -68,7 +72,7 @@ public class WebSocketServerConnection extends AbstractWebSocketConnection
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setIncoming(IncomingFrames incoming)
|
||||
public void setNextIncomingFrames(IncomingFrames incoming)
|
||||
{
|
||||
getParser().setIncomingFramesHandler(incoming);
|
||||
}
|
||||
|
|
|
@ -46,16 +46,14 @@ import org.eclipse.jetty.websocket.api.UpgradeResponse;
|
|||
import org.eclipse.jetty.websocket.api.WebSocketException;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Extension;
|
||||
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
|
||||
import org.eclipse.jetty.websocket.api.extensions.ExtensionFactory;
|
||||
import org.eclipse.jetty.websocket.api.extensions.IncomingFrames;
|
||||
import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames;
|
||||
import org.eclipse.jetty.websocket.common.LogicalConnection;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketSession;
|
||||
import org.eclipse.jetty.websocket.common.events.EventDriver;
|
||||
import org.eclipse.jetty.websocket.common.events.EventDriverFactory;
|
||||
import org.eclipse.jetty.websocket.common.extensions.WebSocketExtensionRegistry;
|
||||
import org.eclipse.jetty.websocket.common.io.IncomingFrames;
|
||||
import org.eclipse.jetty.websocket.common.io.InternalConnection;
|
||||
import org.eclipse.jetty.websocket.common.io.OutgoingFrames;
|
||||
import org.eclipse.jetty.websocket.common.io.WebSocketSession;
|
||||
import org.eclipse.jetty.websocket.common.extensions.WebSocketExtensionFactory;
|
||||
import org.eclipse.jetty.websocket.server.handshake.HandshakeRFC6455;
|
||||
|
||||
/**
|
||||
|
@ -90,7 +88,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
|
|||
private final String supportedVersions;
|
||||
private final WebSocketPolicy basePolicy;
|
||||
private final EventDriverFactory eventDriverFactory;
|
||||
private final WebSocketExtensionRegistry extensionRegistry;
|
||||
private final WebSocketExtensionFactory extensionFactory;
|
||||
private WebSocketCreator creator;
|
||||
private List<Class<?>> registeredSocketClasses;
|
||||
|
||||
|
@ -108,7 +106,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
|
|||
|
||||
this.basePolicy = policy;
|
||||
this.eventDriverFactory = new EventDriverFactory(basePolicy);
|
||||
this.extensionRegistry = new WebSocketExtensionRegistry(basePolicy,bufferPool);
|
||||
this.extensionFactory = new WebSocketExtensionFactory(basePolicy,bufferPool);
|
||||
this.creator = this;
|
||||
|
||||
// Create supportedVersions
|
||||
|
@ -166,11 +164,18 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
|
|||
return upgrade(sockreq,sockresp,driver);
|
||||
}
|
||||
|
||||
protected void closeConnections()
|
||||
protected void closeAllConnections()
|
||||
{
|
||||
for (WebSocketSession session : sessions)
|
||||
{
|
||||
session.close();
|
||||
try
|
||||
{
|
||||
session.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
LOG.warn("CloseAllConnections Close failure",e);
|
||||
}
|
||||
}
|
||||
sessions.clear();
|
||||
}
|
||||
|
@ -205,7 +210,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
|
|||
@Override
|
||||
protected void doStop() throws Exception
|
||||
{
|
||||
closeConnections();
|
||||
closeAllConnections();
|
||||
super.doStop();
|
||||
}
|
||||
|
||||
|
@ -214,9 +219,9 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
|
|||
return this.creator;
|
||||
}
|
||||
|
||||
public ExtensionFactory getExtensionRegistry()
|
||||
public ExtensionFactory getExtensionFactory()
|
||||
{
|
||||
return extensionRegistry;
|
||||
return extensionFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -231,26 +236,6 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
|
|||
return basePolicy;
|
||||
}
|
||||
|
||||
public List<Extension> initExtensions(List<ExtensionConfig> requested)
|
||||
{
|
||||
List<Extension> extensions = new ArrayList<Extension>();
|
||||
|
||||
for (ExtensionConfig cfg : requested)
|
||||
{
|
||||
Extension extension = extensionRegistry.newInstance(cfg);
|
||||
|
||||
if (extension == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
LOG.debug("added {}",extension);
|
||||
extensions.add(extension);
|
||||
}
|
||||
LOG.debug("extensions={}",extensions);
|
||||
return extensions;
|
||||
}
|
||||
|
||||
public boolean isUpgradeRequest(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
String upgrade = request.getHeader("Upgrade");
|
||||
|
@ -324,7 +309,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
|
|||
return false;
|
||||
}
|
||||
boolean ret = sessions.offer(session);
|
||||
session.onConnect();
|
||||
session.open();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -379,7 +364,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
|
|||
|
||||
// Create connection
|
||||
UpgradeContext context = getActiveUpgradeContext();
|
||||
InternalConnection connection = context.getConnection();
|
||||
LogicalConnection connection = context.getConnection();
|
||||
|
||||
if (connection == null)
|
||||
{
|
||||
|
@ -394,46 +379,26 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
|
|||
}
|
||||
|
||||
// Initialize / Negotiate Extensions
|
||||
WebSocketSession session = new WebSocketSession(driver,connection,getPolicy(),response.getAcceptedSubProtocol());
|
||||
WebSocketSession session = new WebSocketSession(request.getRequestURI(),driver,connection);
|
||||
session.setPolicy(getPolicy().clonePolicy());
|
||||
session.setNegotiatedSubprotocol(response.getAcceptedSubProtocol());
|
||||
session.setNegotiatedExtensionConfigs(request.getExtensions());
|
||||
session.setExtensionFactory(extensionFactory);
|
||||
connection.setSession(session);
|
||||
List<Extension> extensions = initExtensions(request.getExtensions());
|
||||
request.setValidExtensions(extensions);
|
||||
|
||||
// Start with default routing.
|
||||
IncomingFrames incoming = session;
|
||||
OutgoingFrames outgoing = connection;
|
||||
|
||||
// Connect extensions
|
||||
if (extensions != null)
|
||||
{
|
||||
connection.configureFromExtensions(extensions);
|
||||
|
||||
// FIXME:
|
||||
// Iterator<Extension> extIter;
|
||||
// // Connect outgoings
|
||||
// extIter = extensions.iterator();
|
||||
// while (extIter.hasNext())
|
||||
// {
|
||||
// Extension ext = extIter.next();
|
||||
// ext.setNextOutgoingFrames(outgoing);
|
||||
// outgoing = ext;
|
||||
// }
|
||||
//
|
||||
// // Connect incomings
|
||||
// Collections.reverse(extensions);
|
||||
// extIter = extensions.iterator();
|
||||
// while (extIter.hasNext())
|
||||
// {
|
||||
// Extension ext = extIter.next();
|
||||
// ext.setNextIncomingFrames(incoming);
|
||||
// incoming = ext;
|
||||
// }
|
||||
}
|
||||
// if (extensions != null)
|
||||
// {
|
||||
// // FIXME connection.configureFromExtensions(extensions);
|
||||
// }
|
||||
|
||||
// configure session for outgoing flows
|
||||
session.setOutgoing(outgoing);
|
||||
session.setOutgoingHandler(outgoing);
|
||||
// configure connection for incoming flows
|
||||
connection.setIncoming(incoming);
|
||||
connection.setNextIncomingFrames(incoming);
|
||||
|
||||
// Tell jetty about the new connection
|
||||
request.setAttribute(HttpConnection.UPGRADE_CONNECTION_ATTRIBUTE,connection);
|
||||
|
|
|
@ -58,6 +58,7 @@ public class HandshakeRFC6455 implements WebSocketHandshake
|
|||
|
||||
if (request.getExtensions() != null)
|
||||
{
|
||||
response.setExtensions(request.getExtensions());
|
||||
for (ExtensionConfig ext : request.getExtensions())
|
||||
{
|
||||
response.addHeader("Sec-WebSocket-Extensions",ext.getParameterizedName());
|
||||
|
|
|
@ -41,10 +41,11 @@ import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
|||
import org.eclipse.jetty.websocket.api.WebSocketBehavior;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketException;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.api.extensions.IncomingFrames;
|
||||
import org.eclipse.jetty.websocket.common.Generator;
|
||||
import org.eclipse.jetty.websocket.common.Parser;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.io.IncomingFrames;
|
||||
import org.eclipse.jetty.websocket.server.examples.MyEchoSocket;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
|
@ -72,7 +73,7 @@ public class WebSocketLoadRFC6455Test
|
|||
}
|
||||
|
||||
@Override
|
||||
public void incomingFrame(WebSocketFrame frame)
|
||||
public void incomingFrame(Frame frame)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
|
|
@ -28,6 +28,7 @@ import java.util.concurrent.TimeUnit;
|
|||
import org.eclipse.jetty.util.Utf8Appendable.NotUtf8Exception;
|
||||
import org.eclipse.jetty.util.Utf8StringBuilder;
|
||||
import org.eclipse.jetty.websocket.api.StatusCode;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.common.CloseInfo;
|
||||
import org.eclipse.jetty.websocket.common.Generator;
|
||||
import org.eclipse.jetty.websocket.common.OpCode;
|
||||
|
@ -102,7 +103,7 @@ public class WebSocketServletRFCTest
|
|||
|
||||
// Read frame echo'd back (hopefully a single binary frame)
|
||||
IncomingFramesCapture capture = client.readFrames(1,TimeUnit.MILLISECONDS,1000);
|
||||
WebSocketFrame binmsg = capture.getFrames().get(0);
|
||||
Frame binmsg = capture.getFrames().get(0);
|
||||
int expectedSize = buf1.length + buf2.length + buf3.length;
|
||||
Assert.assertThat("BinaryFrame.payloadLength",binmsg.getPayloadLength(),is(expectedSize));
|
||||
|
||||
|
@ -225,7 +226,7 @@ public class WebSocketServletRFCTest
|
|||
|
||||
// Read frame (hopefully close frame)
|
||||
IncomingFramesCapture capture = client.readFrames(1,TimeUnit.MILLISECONDS,500);
|
||||
WebSocketFrame cf = capture.getFrames().get(0);
|
||||
Frame cf = capture.getFrames().get(0);
|
||||
CloseInfo close = new CloseInfo(cf);
|
||||
Assert.assertThat("Close Frame.status code",close.getStatusCode(),is(StatusCode.SERVER_ERROR));
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ import org.eclipse.jetty.util.BufferUtil;
|
|||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.common.CloseInfo;
|
||||
import org.eclipse.jetty.websocket.common.Generator;
|
||||
import org.eclipse.jetty.websocket.common.OpCode;
|
||||
|
@ -86,7 +87,7 @@ public class Fuzzer
|
|||
public ByteBuffer asNetworkBuffer(List<WebSocketFrame> send)
|
||||
{
|
||||
int buflen = 0;
|
||||
for (WebSocketFrame f : send)
|
||||
for (Frame f : send)
|
||||
{
|
||||
buflen += f.getPayloadLength() + Generator.OVERHEAD;
|
||||
}
|
||||
|
@ -213,7 +214,7 @@ public class Fuzzer
|
|||
if ((sendMode == SendMode.BULK) || (sendMode == SendMode.SLOW))
|
||||
{
|
||||
int buflen = 0;
|
||||
for (WebSocketFrame f : send)
|
||||
for (Frame f : send)
|
||||
{
|
||||
buflen += f.getPayloadLength() + Generator.OVERHEAD;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,17 @@ import org.junit.Test;
|
|||
|
||||
public class TestABCase4 extends AbstractABCase
|
||||
{
|
||||
// Allow Fuzzer / Generator to create bad frames for testing frame validation
|
||||
private static class BadFrame extends WebSocketFrame
|
||||
{
|
||||
public BadFrame(byte opcode)
|
||||
{
|
||||
super();
|
||||
super.opcode = opcode;
|
||||
// NOTE: Not setting Frame.Type intentionally
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send opcode 3 (reserved)
|
||||
*/
|
||||
|
@ -36,7 +47,7 @@ public class TestABCase4 extends AbstractABCase
|
|||
public void testCase4_1_1() throws Exception
|
||||
{
|
||||
List<WebSocketFrame> send = new ArrayList<>();
|
||||
send.add(new WebSocketFrame((byte)3)); // intentionally bad
|
||||
send.add(new BadFrame((byte)3)); // intentionally bad
|
||||
|
||||
List<WebSocketFrame> expect = new ArrayList<>();
|
||||
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
|
||||
|
@ -64,7 +75,7 @@ public class TestABCase4 extends AbstractABCase
|
|||
byte payload[] = StringUtil.getUtf8Bytes("reserved payload");
|
||||
|
||||
List<WebSocketFrame> send = new ArrayList<>();
|
||||
send.add(new WebSocketFrame((byte)4).setPayload(payload)); // intentionally bad
|
||||
send.add(new BadFrame((byte)4).setPayload(payload)); // intentionally bad
|
||||
|
||||
List<WebSocketFrame> expect = new ArrayList<>();
|
||||
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
|
||||
|
@ -91,7 +102,7 @@ public class TestABCase4 extends AbstractABCase
|
|||
{
|
||||
List<WebSocketFrame> send = new ArrayList<>();
|
||||
send.add(WebSocketFrame.text("hello"));
|
||||
send.add(new WebSocketFrame((byte)5)); // intentionally bad
|
||||
send.add(new BadFrame((byte)5)); // intentionally bad
|
||||
send.add(WebSocketFrame.ping());
|
||||
|
||||
List<WebSocketFrame> expect = new ArrayList<>();
|
||||
|
@ -120,7 +131,7 @@ public class TestABCase4 extends AbstractABCase
|
|||
{
|
||||
List<WebSocketFrame> send = new ArrayList<>();
|
||||
send.add(WebSocketFrame.text("hello"));
|
||||
send.add(new WebSocketFrame((byte)6).setPayload("bad")); // intentionally bad
|
||||
send.add(new BadFrame((byte)6).setPayload("bad")); // intentionally bad
|
||||
send.add(WebSocketFrame.ping());
|
||||
|
||||
List<WebSocketFrame> expect = new ArrayList<>();
|
||||
|
@ -149,7 +160,7 @@ public class TestABCase4 extends AbstractABCase
|
|||
{
|
||||
List<WebSocketFrame> send = new ArrayList<>();
|
||||
send.add(WebSocketFrame.text("hello"));
|
||||
send.add(new WebSocketFrame((byte)7).setPayload("bad")); // intentionally bad
|
||||
send.add(new BadFrame((byte)7).setPayload("bad")); // intentionally bad
|
||||
send.add(WebSocketFrame.ping());
|
||||
|
||||
List<WebSocketFrame> expect = new ArrayList<>();
|
||||
|
@ -177,7 +188,7 @@ public class TestABCase4 extends AbstractABCase
|
|||
public void testCase4_2_1() throws Exception
|
||||
{
|
||||
List<WebSocketFrame> send = new ArrayList<>();
|
||||
send.add(new WebSocketFrame((byte)11)); // intentionally bad
|
||||
send.add(new BadFrame((byte)11)); // intentionally bad
|
||||
|
||||
List<WebSocketFrame> expect = new ArrayList<>();
|
||||
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
|
||||
|
@ -203,7 +214,7 @@ public class TestABCase4 extends AbstractABCase
|
|||
public void testCase4_2_2() throws Exception
|
||||
{
|
||||
List<WebSocketFrame> send = new ArrayList<>();
|
||||
send.add(new WebSocketFrame((byte)12).setPayload("bad")); // intentionally bad
|
||||
send.add(new BadFrame((byte)12).setPayload("bad")); // intentionally bad
|
||||
|
||||
List<WebSocketFrame> expect = new ArrayList<>();
|
||||
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
|
||||
|
@ -230,7 +241,7 @@ public class TestABCase4 extends AbstractABCase
|
|||
{
|
||||
List<WebSocketFrame> send = new ArrayList<>();
|
||||
send.add(WebSocketFrame.text("hello"));
|
||||
send.add(new WebSocketFrame((byte)13)); // intentionally bad
|
||||
send.add(new BadFrame((byte)13)); // intentionally bad
|
||||
send.add(WebSocketFrame.ping());
|
||||
|
||||
List<WebSocketFrame> expect = new ArrayList<>();
|
||||
|
@ -259,7 +270,7 @@ public class TestABCase4 extends AbstractABCase
|
|||
{
|
||||
List<WebSocketFrame> send = new ArrayList<>();
|
||||
send.add(WebSocketFrame.text("hello"));
|
||||
send.add(new WebSocketFrame((byte)14).setPayload("bad")); // intentionally bad
|
||||
send.add(new BadFrame((byte)14).setPayload("bad")); // intentionally bad
|
||||
send.add(WebSocketFrame.ping());
|
||||
|
||||
List<WebSocketFrame> expect = new ArrayList<>();
|
||||
|
@ -288,7 +299,7 @@ public class TestABCase4 extends AbstractABCase
|
|||
{
|
||||
List<WebSocketFrame> send = new ArrayList<>();
|
||||
send.add(WebSocketFrame.text("hello"));
|
||||
send.add(new WebSocketFrame((byte)15).setPayload("bad")); // intentionally bad
|
||||
send.add(new BadFrame((byte)15).setPayload("bad")); // intentionally bad
|
||||
send.add(WebSocketFrame.ping());
|
||||
|
||||
List<WebSocketFrame> expect = new ArrayList<>();
|
||||
|
|
|
@ -34,6 +34,8 @@ import java.net.URI;
|
|||
import java.net.URISyntaxException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
@ -57,14 +59,15 @@ import org.eclipse.jetty.websocket.api.WebSocketException;
|
|||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Extension;
|
||||
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.api.extensions.IncomingFrames;
|
||||
import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames;
|
||||
import org.eclipse.jetty.websocket.common.CloseInfo;
|
||||
import org.eclipse.jetty.websocket.common.Generator;
|
||||
import org.eclipse.jetty.websocket.common.OpCode;
|
||||
import org.eclipse.jetty.websocket.common.Parser;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.extensions.WebSocketExtensionRegistry;
|
||||
import org.eclipse.jetty.websocket.common.io.IncomingFrames;
|
||||
import org.eclipse.jetty.websocket.common.io.OutgoingFrames;
|
||||
import org.eclipse.jetty.websocket.common.extensions.WebSocketExtensionFactory;
|
||||
import org.eclipse.jetty.websocket.server.helper.FinishedFuture;
|
||||
import org.eclipse.jetty.websocket.server.helper.IncomingFramesCapture;
|
||||
import org.junit.Assert;
|
||||
|
@ -93,7 +96,7 @@ public class BlockheadClient implements IncomingFrames, OutgoingFrames
|
|||
private final Generator generator;
|
||||
private final Parser parser;
|
||||
private final IncomingFramesCapture incomingFrames;
|
||||
private final WebSocketExtensionRegistry extensionRegistry;
|
||||
private final WebSocketExtensionFactory extensionRegistry;
|
||||
|
||||
private Socket socket;
|
||||
private OutputStream out;
|
||||
|
@ -131,7 +134,7 @@ public class BlockheadClient implements IncomingFrames, OutgoingFrames
|
|||
|
||||
this.incomingFrames = new IncomingFramesCapture();
|
||||
|
||||
this.extensionRegistry = new WebSocketExtensionRegistry(policy,bufferPool);
|
||||
this.extensionRegistry = new WebSocketExtensionFactory(policy,bufferPool);
|
||||
}
|
||||
|
||||
public void addExtensions(String xtension)
|
||||
|
@ -220,26 +223,25 @@ public class BlockheadClient implements IncomingFrames, OutgoingFrames
|
|||
generator.configureFromExtensions(extensions);
|
||||
parser.configureFromExtensions(extensions);
|
||||
|
||||
// FIXME
|
||||
// Iterator<Extension> extIter;
|
||||
// // Connect outgoings
|
||||
// extIter = extensions.iterator();
|
||||
// while (extIter.hasNext())
|
||||
// {
|
||||
// Extension ext = extIter.next();
|
||||
// ext.setNextOutgoingFrames(outgoing);
|
||||
// outgoing = ext;
|
||||
// }
|
||||
//
|
||||
// // Connect incomings
|
||||
// Collections.reverse(extensions);
|
||||
// extIter = extensions.iterator();
|
||||
// while (extIter.hasNext())
|
||||
// {
|
||||
// Extension ext = extIter.next();
|
||||
// ext.setNextIncomingFrames(incoming);
|
||||
// incoming = ext;
|
||||
// }
|
||||
Iterator<Extension> extIter;
|
||||
// Connect outgoings
|
||||
extIter = extensions.iterator();
|
||||
while (extIter.hasNext())
|
||||
{
|
||||
Extension ext = extIter.next();
|
||||
ext.setNextOutgoingFrames(outgoing);
|
||||
outgoing = ext;
|
||||
}
|
||||
|
||||
// Connect incomings
|
||||
Collections.reverse(extensions);
|
||||
extIter = extensions.iterator();
|
||||
while (extIter.hasNext())
|
||||
{
|
||||
Extension ext = extIter.next();
|
||||
ext.setNextIncomingFrames(incoming);
|
||||
incoming = ext;
|
||||
}
|
||||
}
|
||||
|
||||
// configure parser
|
||||
|
@ -309,7 +311,7 @@ public class BlockheadClient implements IncomingFrames, OutgoingFrames
|
|||
}
|
||||
|
||||
@Override
|
||||
public void incomingFrame(WebSocketFrame frame)
|
||||
public void incomingFrame(Frame frame)
|
||||
{
|
||||
LOG.debug("incoming({})",frame);
|
||||
int count = parseCount.incrementAndGet();
|
||||
|
@ -356,7 +358,7 @@ public class BlockheadClient implements IncomingFrames, OutgoingFrames
|
|||
}
|
||||
|
||||
@Override
|
||||
public Future<SendResult> outgoingFrame(WebSocketFrame frame) throws IOException
|
||||
public Future<SendResult> outgoingFrame(Frame frame) throws IOException
|
||||
{
|
||||
ByteBuffer buf = generator.generate(frame);
|
||||
if (LOG.isDebugEnabled())
|
||||
|
@ -366,7 +368,7 @@ public class BlockheadClient implements IncomingFrames, OutgoingFrames
|
|||
BufferUtil.writeTo(buf,out);
|
||||
out.flush();
|
||||
|
||||
if (frame.getOpCode() == OpCode.CLOSE)
|
||||
if (frame.getType().getOpCode() == OpCode.CLOSE)
|
||||
{
|
||||
disconnect();
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
package org.eclipse.jetty.websocket.server.examples.echo;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
@ -45,8 +46,10 @@ public class EchoBroadcastPingSocket extends EchoBroadcastSocket
|
|||
while (!latch.await(10,TimeUnit.SECONDS))
|
||||
{
|
||||
System.err.println("Ping");
|
||||
byte data[] = new byte[]
|
||||
{ (byte)1, (byte)2, (byte)3 };
|
||||
ByteBuffer data = ByteBuffer.allocate(3);
|
||||
data.put(new byte[]
|
||||
{ (byte)1, (byte)2, (byte)3 });
|
||||
data.flip();
|
||||
conn.ping(data);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,9 +26,10 @@ import org.eclipse.jetty.util.BufferUtil;
|
|||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketException;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.api.extensions.IncomingFrames;
|
||||
import org.eclipse.jetty.websocket.common.OpCode;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.io.IncomingFrames;
|
||||
import org.junit.Assert;
|
||||
|
||||
public class IncomingFramesCapture implements IncomingFrames
|
||||
|
@ -77,7 +78,7 @@ public class IncomingFramesCapture implements IncomingFrames
|
|||
System.err.printf("Captured %d incoming frames%n",frames.size());
|
||||
for (int i = 0; i < frames.size(); i++)
|
||||
{
|
||||
WebSocketFrame frame = frames.get(i);
|
||||
Frame frame = frames.get(i);
|
||||
System.err.printf("[%3d] %s%n",i,frame);
|
||||
System.err.printf(" %s%n",BufferUtil.toDetailString(frame.getPayload()));
|
||||
}
|
||||
|
@ -127,7 +128,7 @@ public class IncomingFramesCapture implements IncomingFrames
|
|||
}
|
||||
|
||||
@Override
|
||||
public void incomingFrame(WebSocketFrame frame)
|
||||
public void incomingFrame(Frame frame)
|
||||
{
|
||||
WebSocketFrame copy = new WebSocketFrame(frame);
|
||||
frames.add(copy);
|
||||
|
|
|
@ -28,9 +28,10 @@ import javax.net.websocket.SendResult;
|
|||
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames;
|
||||
import org.eclipse.jetty.websocket.common.OpCode;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.io.OutgoingFrames;
|
||||
import org.junit.Assert;
|
||||
|
||||
public class OutgoingFramesCapture implements OutgoingFrames
|
||||
|
@ -39,7 +40,7 @@ public class OutgoingFramesCapture implements OutgoingFrames
|
|||
{
|
||||
public C context;
|
||||
public Callback<C> callback;
|
||||
public WebSocketFrame frame;
|
||||
public Frame frame;
|
||||
}
|
||||
|
||||
private LinkedList<WebSocketFrame> frames = new LinkedList<>();
|
||||
|
@ -69,7 +70,7 @@ public class OutgoingFramesCapture implements OutgoingFrames
|
|||
System.out.printf("Captured %d outgoing writes%n",frames.size());
|
||||
for (int i = 0; i < frames.size(); i++)
|
||||
{
|
||||
WebSocketFrame frame = frames.get(i);
|
||||
Frame frame = frames.get(i);
|
||||
System.out.printf("[%3d] %s%n",i,frame);
|
||||
System.out.printf(" %s%n",BufferUtil.toDetailString(frame.getPayload()));
|
||||
}
|
||||
|
@ -94,9 +95,10 @@ public class OutgoingFramesCapture implements OutgoingFrames
|
|||
}
|
||||
|
||||
@Override
|
||||
public Future<SendResult> outgoingFrame(WebSocketFrame frame) throws IOException
|
||||
public Future<SendResult> outgoingFrame(Frame frame) throws IOException
|
||||
{
|
||||
frames.add(frame);
|
||||
WebSocketFrame copy = new WebSocketFrame(frame);
|
||||
frames.add(copy);
|
||||
return FinishedFuture.INSTANCE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
|
||||
org.eclipse.jetty.LEVEL=WARN
|
||||
# org.eclipse.jetty.websocket.LEVEL=WARN
|
||||
# org.eclipse.jetty.websocket.LEVEL=DEBUG
|
||||
org.eclipse.jetty.websocket.LEVEL=DEBUG
|
||||
# org.eclipse.jetty.websocket.io.LEVEL=DEBUG
|
||||
# org.eclipse.jetty.websocket.io.WebSocketAsyncConnection.LEVEL=DEBUG
|
||||
# org.eclipse.jetty.websocket.io.ControlFrameBytes.LEVEL=DEBUG
|
||||
|
|
Loading…
Reference in New Issue