Ripping out javax.net.websocket.extension.* SPI as it is going away

This commit is contained in:
Joakim Erdfelt 2012-11-12 12:36:39 -07:00
parent 09625a64e2
commit 8548331735
100 changed files with 2210 additions and 1762 deletions

View File

@ -237,6 +237,18 @@ public class UpgradeRequest implements HandshakeRequest
this.cookies = cookies; 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) public void setHttpVersion(String httpVersion)
{ {
this.httpVersion = httpVersion; this.httpVersion = httpVersion;

View File

@ -39,7 +39,7 @@ public interface WebSocketConnection
* @see StatusCode * @see StatusCode
* @see #close(int, String) * @see #close(int, String)
*/ */
public void close(); public void close() throws IOException;
/** /**
* Send a websocket Close frame, with status code. * Send a websocket Close frame, with status code.
@ -52,7 +52,7 @@ public interface WebSocketConnection
* the (optional) reason. (can be null for no reason) * the (optional) reason. (can be null for no reason)
* @see StatusCode * @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. * 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. * NIO style with callbacks, allows for knowledge of successful ping send.
* <p> * <p>
* Use @OnWebSocketFrame and monitor Pong frames * 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. * Suspend a the incoming read events on the connection.

View File

@ -26,9 +26,12 @@ public interface WebSocketListener
/** /**
* A WebSocket binary frame has been received. * A WebSocket binary frame has been received.
* *
* @param payload the raw payload array received * @param payload
* @param offset the offset in the payload array where the data starts * the raw payload array received
* @param len the length of bytes in the payload * @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); void onWebSocketBinary(byte payload[], int offset, int len);

View File

@ -25,28 +25,8 @@ import javax.net.websocket.extensions.FrameHandler;
* <p> * <p>
* That work is performed by the two {@link FrameHandler} implementations for incoming and outgoing frame handling. * 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. * The active configuration for this extension.
* *
@ -59,7 +39,6 @@ public interface Extension extends javax.net.websocket.extensions.Extension
* <p> * <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>. * 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(); 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. * now free to validate the conformance to spec of TEXT Data Frames.
*/ */
public abstract boolean isTextDataDecoder(); 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);
} }

View File

@ -24,26 +24,26 @@ import java.util.Map;
import java.util.ServiceLoader; import java.util.ServiceLoader;
import java.util.Set; 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 ServiceLoader<Extension> extensionLoader = ServiceLoader.load(Extension.class);
private Map<String, Extension> availableExtensions; private Map<String, Class<? extends Extension>> availableExtensions;
public ExtensionFactory() public ExtensionFactory()
{ {
availableExtensions = new HashMap<>(); availableExtensions = new HashMap<>();
for (Extension ext : extensionLoader) 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; return availableExtensions;
} }
public Extension getExtension(String name) public Class<? extends Extension> getExtension(String name)
{ {
return availableExtensions.get(name); return availableExtensions.get(name);
} }
@ -59,12 +59,14 @@ public class ExtensionFactory implements Iterable<Extension>
} }
@Override @Override
public Iterator<Extension> iterator() public Iterator<Class<? extends Extension>> iterator()
{ {
return availableExtensions.values().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); availableExtensions.put(name,extension);
} }

View File

@ -27,6 +27,7 @@ public interface Frame extends javax.net.websocket.extensions.Frame
{ {
public static enum Type public static enum Type
{ {
CONTINUATION((byte)0x00),
TEXT((byte)0x01), TEXT((byte)0x01),
BINARY((byte)0x02), BINARY((byte)0x02),
CLOSE((byte)0x08), CLOSE((byte)0x08),
@ -35,12 +36,6 @@ public interface Frame extends javax.net.websocket.extensions.Frame
public static Type from(byte op) public static Type from(byte op)
{ {
if (op == 0)
{
// continuation has no type, but is a valid opcode.
return null;
}
for (Type type : values()) for (Type type : values())
{ {
if (type.opcode == op) if (type.opcode == op)
@ -82,12 +77,18 @@ public interface Frame extends javax.net.websocket.extensions.Frame
public byte[] getMask(); public byte[] getMask();
public byte getOpCode();
public ByteBuffer getPayload(); public ByteBuffer getPayload();
public int getPayloadLength(); public int getPayloadLength();
public int getPayloadStart();
public Type getType(); public Type getType();
public boolean hasPayload();
public boolean isContinuation(); public boolean isContinuation();
public boolean isFin(); public boolean isFin();
@ -106,4 +107,10 @@ public interface Frame extends javax.net.websocket.extensions.Frame
public boolean isRsv2(); public boolean isRsv2();
public boolean isRsv3(); public boolean isRsv3();
public void notifySendFailed(Throwable t);
public void notifySendSuccess();
public int remaining();
} }

View File

@ -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.api.WebSocketException;
import org.eclipse.jetty.websocket.common.WebSocketFrame;
/** /**
* Interface for dealing with Incoming Frames. * Interface for dealing with Incoming Frames.
@ -28,5 +27,5 @@ public interface IncomingFrames
{ {
public void incomingError(WebSocketException e); public void incomingError(WebSocketException e);
public void incomingFrame(WebSocketFrame frame); public void incomingFrame(Frame frame);
} }

View File

@ -16,19 +16,17 @@
// ======================================================================== // ========================================================================
// //
package org.eclipse.jetty.websocket.common.io; package org.eclipse.jetty.websocket.api.extensions;
import java.io.IOException; import java.io.IOException;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import javax.net.websocket.SendResult; import javax.net.websocket.SendResult;
import org.eclipse.jetty.websocket.common.WebSocketFrame;
/** /**
* Interface for dealing with frames outgoing to the network (eventually) * Interface for dealing with frames outgoing to the network (eventually)
*/ */
public interface OutgoingFrames public interface OutgoingFrames
{ {
Future<SendResult> outgoingFrame(WebSocketFrame frame) throws IOException; Future<SendResult> outgoingFrame(Frame frame) throws IOException;
} }

View File

@ -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
}
}

View File

@ -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.api.extensions.ExtensionFactory;
import org.eclipse.jetty.websocket.client.internal.ConnectionManager; import org.eclipse.jetty.websocket.client.internal.ConnectionManager;
import org.eclipse.jetty.websocket.client.internal.DefaultWebSocketClient; 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.EventDriver;
import org.eclipse.jetty.websocket.common.events.EventDriverFactory; import org.eclipse.jetty.websocket.common.events.EventDriverFactory;
import org.eclipse.jetty.websocket.common.extensions.WebSocketExtensionRegistry; import org.eclipse.jetty.websocket.common.extensions.WebSocketExtensionFactory;
import org.eclipse.jetty.websocket.common.io.WebSocketSession;
public class WebSocketClientFactory extends ContainerLifeCycle public class WebSocketClientFactory extends ContainerLifeCycle
{ {
@ -54,7 +54,7 @@ public class WebSocketClientFactory extends ContainerLifeCycle
private final Scheduler scheduler; private final Scheduler scheduler;
private final EventDriverFactory eventDriverFactory; private final EventDriverFactory eventDriverFactory;
private final WebSocketPolicy policy; private final WebSocketPolicy policy;
private final WebSocketExtensionRegistry extensionRegistry; private final WebSocketExtensionFactory extensionRegistry;
private SocketAddress bindAddress; private SocketAddress bindAddress;
private final Queue<WebSocketSession> sessions = new ConcurrentLinkedQueue<>(); private final Queue<WebSocketSession> sessions = new ConcurrentLinkedQueue<>();
@ -98,7 +98,7 @@ public class WebSocketClientFactory extends ContainerLifeCycle
} }
this.policy = WebSocketPolicy.newClientPolicy(); 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); this.connectionManager = new ConnectionManager(bufferPool,executor,scheduler,sslContextFactory,policy);
addBean(this.connectionManager); addBean(this.connectionManager);
@ -205,7 +205,7 @@ public class WebSocketClientFactory extends ContainerLifeCycle
LOG.debug("Session Opened: {}",session); LOG.debug("Session Opened: {}",session);
} }
boolean ret = sessions.offer(session); boolean ret = sessions.offer(session);
session.onConnect(); session.open();
return ret; return ret;
} }

View File

@ -95,13 +95,20 @@ public class ConnectionManager extends ContainerLifeCycle
clients.add(client); clients.add(client);
} }
private void closeConnections() private void closeAllConnections()
{ {
for (DefaultWebSocketClient client : clients) for (DefaultWebSocketClient client : clients)
{ {
if (client.getConnection() != null) 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 @Override
protected void doStop() throws Exception protected void doStop() throws Exception
{ {
closeConnections(); closeAllConnections();
clients.clear(); clients.clear();
super.doStop(); super.doStop();
} }

View File

@ -38,14 +38,13 @@ import org.eclipse.jetty.websocket.api.UpgradeException;
import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.api.extensions.Extension; import org.eclipse.jetty.websocket.api.extensions.Extension;
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
import org.eclipse.jetty.websocket.api.extensions.IncomingFrames;
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest; import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
import org.eclipse.jetty.websocket.client.ClientUpgradeResponse; import org.eclipse.jetty.websocket.client.ClientUpgradeResponse;
import org.eclipse.jetty.websocket.client.internal.DefaultWebSocketClient; import org.eclipse.jetty.websocket.client.internal.DefaultWebSocketClient;
import org.eclipse.jetty.websocket.common.AcceptHash; import org.eclipse.jetty.websocket.common.AcceptHash;
import org.eclipse.jetty.websocket.common.WebSocketSession;
import org.eclipse.jetty.websocket.common.events.EventDriver; 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. * 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(); EventDriver websocket = client.getWebSocket();
WebSocketPolicy policy = client.getPolicy(); WebSocketPolicy policy = client.getPolicy();
String acceptedSubProtocol = response.getAcceptedSubProtocol(); 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); connection.setSession(session);
List<Extension> extensions = client.getFactory().initExtensions(response.getExtensions()); List<Extension> extensions = client.getFactory().initExtensions(response.getExtensions());
// Start with default routing. // Start with default routing.
IncomingFrames incoming = session; IncomingFrames incoming = session;
OutgoingFrames outgoing = connection; // OutgoingFrames outgoing = connection;
// Connect extensions // Connect extensions
if (extensions != null) if (extensions != null)
@ -254,7 +257,7 @@ public class UpgradeConnection extends AbstractConnection
} }
// configure session for outgoing flows // configure session for outgoing flows
session.setOutgoing(outgoing); // session.setOutgoing(outgoing);
// configure connection for incoming flows // configure connection for incoming flows
connection.getParser().setIncomingFramesHandler(incoming); connection.getParser().setIncomingFramesHandler(incoming);

View File

@ -19,20 +19,20 @@
package org.eclipse.jetty.websocket.client.internal.io; package org.eclipse.jetty.websocket.client.internal.io;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.net.InetSocketAddress;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import javax.net.websocket.SendResult; import javax.net.websocket.SendResult;
import org.eclipse.jetty.io.EndPoint; 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.WebSocketClientFactory;
import org.eclipse.jetty.websocket.client.internal.DefaultWebSocketClient; import org.eclipse.jetty.websocket.client.internal.DefaultWebSocketClient;
import org.eclipse.jetty.websocket.client.masks.Masker; import org.eclipse.jetty.websocket.client.masks.Masker;
import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.WebSocketFrame;
import org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection; import org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection;
import org.eclipse.jetty.websocket.common.io.IncomingFrames;
/** /**
* Client side WebSocket physical connection. * Client side WebSocket physical connection.
@ -53,17 +53,23 @@ public class WebSocketClientConnection extends AbstractWebSocketConnection
this.masker = client.getMasker(); this.masker = client.getMasker();
} }
@Override
public void configureFromExtensions(List<Extension> extensions)
{
/* do nothing */
}
public DefaultWebSocketClient getClient() public DefaultWebSocketClient getClient()
{ {
return client; return client;
} }
@Override
public InetSocketAddress getLocalAddress()
{
return getEndPoint().getLocalAddress();
}
@Override
public InetSocketAddress getRemoteAddress()
{
return getEndPoint().getRemoteAddress();
}
@Override @Override
public void onClose() public void onClose()
{ {
@ -83,14 +89,17 @@ public class WebSocketClientConnection extends AbstractWebSocketConnection
} }
@Override @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); return super.outgoingFrame(frame);
} }
@Override @Override
public void setIncoming(IncomingFrames incoming) public void setNextIncomingFrames(IncomingFrames incoming)
{ {
getParser().setIncomingFramesHandler(incoming); getParser().setIncomingFramesHandler(incoming);
} }

View File

@ -18,9 +18,9 @@
package org.eclipse.jetty.websocket.client.internal.mux; 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.add.MuxAddClient;
import org.eclipse.jetty.websocket.common.extensions.mux.op.MuxAddChannelResponse; import org.eclipse.jetty.websocket.common.extensions.mux.op.MuxAddChannelResponse;
import org.eclipse.jetty.websocket.common.io.WebSocketSession;
public class MuxClientAddHandler implements MuxAddClient public class MuxClientAddHandler implements MuxAddClient
{ {

View File

@ -53,15 +53,16 @@ import org.eclipse.jetty.websocket.api.WebSocketException;
import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.api.extensions.Extension; import org.eclipse.jetty.websocket.api.extensions.Extension;
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
import org.eclipse.jetty.websocket.api.extensions.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.AcceptHash;
import org.eclipse.jetty.websocket.common.CloseInfo; import org.eclipse.jetty.websocket.common.CloseInfo;
import org.eclipse.jetty.websocket.common.Generator; import org.eclipse.jetty.websocket.common.Generator;
import org.eclipse.jetty.websocket.common.OpCode; import org.eclipse.jetty.websocket.common.OpCode;
import org.eclipse.jetty.websocket.common.Parser; import org.eclipse.jetty.websocket.common.Parser;
import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.WebSocketFrame;
import org.eclipse.jetty.websocket.common.extensions.WebSocketExtensionRegistry; import org.eclipse.jetty.websocket.common.extensions.WebSocketExtensionFactory;
import org.eclipse.jetty.websocket.common.io.IncomingFrames;
import org.eclipse.jetty.websocket.common.io.OutgoingFrames;
import org.junit.Assert; import org.junit.Assert;
/** /**
@ -81,7 +82,7 @@ public class BlockheadServer
private final Parser parser; private final Parser parser;
private final Generator generator; private final Generator generator;
private final AtomicInteger parseCount; private final AtomicInteger parseCount;
private final WebSocketExtensionRegistry extensionRegistry; private final WebSocketExtensionFactory extensionRegistry;
/** Set to true to disable timeouts (for debugging reasons) */ /** Set to true to disable timeouts (for debugging reasons) */
private boolean debug = false; private boolean debug = false;
@ -100,7 +101,7 @@ public class BlockheadServer
this.parser = new Parser(policy); this.parser = new Parser(policy);
this.parseCount = new AtomicInteger(0); this.parseCount = new AtomicInteger(0);
this.generator = new Generator(policy,bufferPool,false); this.generator = new Generator(policy,bufferPool,false);
this.extensionRegistry = new WebSocketExtensionRegistry(policy,bufferPool); this.extensionRegistry = new WebSocketExtensionFactory(policy,bufferPool);
} }
public void close() throws IOException public void close() throws IOException
@ -141,7 +142,7 @@ public class BlockheadServer
LOG.debug("Echo Frames [expecting {}]",expectedFrames); LOG.debug("Echo Frames [expecting {}]",expectedFrames);
IncomingFramesCapture cap = readFrames(expectedFrames,timeoutUnit,timeoutDuration); IncomingFramesCapture cap = readFrames(expectedFrames,timeoutUnit,timeoutDuration);
// now echo them back. // now echo them back.
for (WebSocketFrame frame : cap.getFrames()) for (Frame frame : cap.getFrames())
{ {
write(frame); write(frame);
} }
@ -197,7 +198,7 @@ public class BlockheadServer
} }
@Override @Override
public void incomingFrame(WebSocketFrame frame) public void incomingFrame(Frame frame)
{ {
LOG.debug("incoming({})",frame); LOG.debug("incoming({})",frame);
int count = parseCount.incrementAndGet(); int count = parseCount.incrementAndGet();
@ -210,7 +211,7 @@ public class BlockheadServer
} }
@Override @Override
public Future<SendResult> outgoingFrame(WebSocketFrame frame) throws IOException public Future<SendResult> outgoingFrame(Frame frame) throws IOException
{ {
ByteBuffer buf = generator.generate(frame); ByteBuffer buf = generator.generate(frame);
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
@ -220,7 +221,7 @@ public class BlockheadServer
BufferUtil.writeTo(buf,out); BufferUtil.writeTo(buf,out);
out.flush(); out.flush();
if (frame.getOpCode() == OpCode.CLOSE) if (frame.getType().getOpCode() == OpCode.CLOSE)
{ {
disconnect(); disconnect();
} }
@ -434,16 +435,16 @@ public class BlockheadServer
getOutputStream().write(buf,offset,length); getOutputStream().write(buf,offset,length);
} }
public void write(int b) throws IOException public void write(Frame frame) throws IOException
{
getOutputStream().write(b);
}
public void write(WebSocketFrame frame) throws IOException
{ {
LOG.debug("write(Frame->{}) to {}",frame,outgoing); LOG.debug("write(Frame->{}) to {}",frame,outgoing);
outgoing.outgoingFrame(frame); outgoing.outgoingFrame(frame);
} }
public void write(int b) throws IOException
{
getOutputStream().write(b);
}
} }
private static final Logger LOG = Log.getLogger(BlockheadServer.class); private static final Logger LOG = Log.getLogger(BlockheadServer.class);

View File

@ -26,9 +26,10 @@ import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.api.WebSocketException; 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.OpCode;
import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.WebSocketFrame;
import org.eclipse.jetty.websocket.common.io.IncomingFrames;
import org.junit.Assert; import org.junit.Assert;
public class IncomingFramesCapture implements IncomingFrames public class IncomingFramesCapture implements IncomingFrames
@ -77,7 +78,7 @@ public class IncomingFramesCapture implements IncomingFrames
System.err.printf("Captured %d incoming frames%n",frames.size()); System.err.printf("Captured %d incoming frames%n",frames.size());
for (int i = 0; i < frames.size(); i++) 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("[%3d] %s%n",i,frame);
System.err.printf(" %s%n",BufferUtil.toDetailString(frame.getPayload())); System.err.printf(" %s%n",BufferUtil.toDetailString(frame.getPayload()));
} }
@ -127,7 +128,7 @@ public class IncomingFramesCapture implements IncomingFrames
} }
@Override @Override
public void incomingFrame(WebSocketFrame frame) public void incomingFrame(Frame frame)
{ {
WebSocketFrame copy = new WebSocketFrame(frame); WebSocketFrame copy = new WebSocketFrame(frame);
frames.add(copy); frames.add(copy);

View File

@ -20,7 +20,6 @@
<groupId>org.eclipse.jetty.drafts</groupId> <groupId>org.eclipse.jetty.drafts</groupId>
<artifactId>javax.net.websocket-api</artifactId> <artifactId>javax.net.websocket-api</artifactId>
<version>0.006.0.EDR-SNAPSHOT</version> <version>0.006.0.EDR-SNAPSHOT</version>
<scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.eclipse.jetty.websocket</groupId> <groupId>org.eclipse.jetty.websocket</groupId>

View File

@ -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();
}
}

View File

@ -29,6 +29,7 @@ import org.eclipse.jetty.websocket.api.ProtocolException;
import org.eclipse.jetty.websocket.api.WebSocketBehavior; import org.eclipse.jetty.websocket.api.WebSocketBehavior;
import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.api.extensions.Extension; import org.eclipse.jetty.websocket.api.extensions.Extension;
import org.eclipse.jetty.websocket.api.extensions.Frame;
/** /**
* Generating a frame in WebSocket land. * Generating a frame in WebSocket land.
@ -103,7 +104,7 @@ public class Generator
this.validating = validating; this.validating = validating;
} }
public void assertFrameValid(WebSocketFrame frame) public void assertFrameValid(Frame frame)
{ {
if (!validating) if (!validating)
{ {
@ -131,7 +132,7 @@ public class Generator
throw new ProtocolException("RSV3 not allowed to be set"); throw new ProtocolException("RSV3 not allowed to be set");
} }
if (frame.isControlFrame()) if (frame.getType().isControl())
{ {
/* /*
* RFC 6455 Section 5.5 * RFC 6455 Section 5.5
@ -153,7 +154,7 @@ public class Generator
* *
* close frame payload is specially formatted which is checked in CloseInfo * 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(); 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 * 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. * {@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) if (windowSize < OVERHEAD)
{ {
@ -204,22 +219,7 @@ public class Generator
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
{ {
StringBuilder dbg = new StringBuilder(); LOG.debug("{} Generate: {}",behavior,frame);
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());
} }
/* /*
@ -260,6 +260,7 @@ public class Generator
b |= 0x10; b |= 0x10;
} }
// NOTE: using .getOpCode() here, not .getType().getOpCode() for testing reasons
byte opcode = frame.getOpCode(); byte opcode = frame.getOpCode();
if (frame.isContinuation()) if (frame.isContinuation())
@ -366,20 +367,6 @@ public class Generator
return buffer; 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() public boolean isRsv1InUse()
{ {
return rsv1InUse; return rsv1InUse;

View File

@ -18,14 +18,33 @@
package org.eclipse.jetty.websocket.common; package org.eclipse.jetty.websocket.common;
import java.io.IOException;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import org.eclipse.jetty.websocket.api.StatusCode; import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.SuspendToken; 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. * Send a websocket Close frame, without a status code or reason.
* <p> * <p>
@ -55,12 +74,36 @@ public interface LogicalConnection extends OutgoingFrames
void disconnect(); 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(); InetSocketAddress getRemoteAddress();
/**
* Get the Session for this connection
*
* @return the Session for this connection
*/
WebSocketSession getSession();
/** /**
* Get the WebSocket connection State. * Get the WebSocket connection State.
* *
@ -106,6 +149,24 @@ public interface LogicalConnection extends OutgoingFrames
*/ */
void onCloseHandshake(boolean incoming, CloseInfo close); 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. * Suspend a the incoming read events on the connection.
* *

View File

@ -29,7 +29,8 @@ import org.eclipse.jetty.websocket.api.ProtocolException;
import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.WebSocketException;
import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.api.extensions.Extension; import org.eclipse.jetty.websocket.api.extensions.Extension;
import org.eclipse.jetty.websocket.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.CloseReasonValidator;
import org.eclipse.jetty.websocket.common.io.payload.DeMaskProcessor; import org.eclipse.jetty.websocket.common.io.payload.DeMaskProcessor;
import org.eclipse.jetty.websocket.common.io.payload.NoOpValidator; import org.eclipse.jetty.websocket.common.io.payload.NoOpValidator;
@ -59,7 +60,7 @@ public class Parser
private int cursor = 0; private int cursor = 0;
// Frame // Frame
private WebSocketFrame frame; private WebSocketFrame frame;
private WebSocketFrame priorDataFrame; private Frame priorDataFrame;
private byte lastDataOpcode; private byte lastDataOpcode;
// payload specific // payload specific
private ByteBuffer payload; private ByteBuffer payload;
@ -170,7 +171,7 @@ public class Parser
return rsv3InUse; return rsv3InUse;
} }
protected void notifyFrame(final WebSocketFrame f) protected void notifyFrame(final Frame f)
{ {
if (LOG_FRAMES.isDebugEnabled()) if (LOG_FRAMES.isDebugEnabled())
{ {

View File

@ -91,7 +91,7 @@ public class WebSocketFrame implements Frame
private boolean rsv1 = false; private boolean rsv1 = false;
private boolean rsv2 = false; private boolean rsv2 = false;
private boolean rsv3 = false; private boolean rsv3 = false;
private byte opcode = OpCode.UNDEFINED; protected byte opcode = OpCode.UNDEFINED;
private boolean masked = false; private boolean masked = false;
private byte mask[]; private byte mask[];
/** /**
@ -141,10 +141,13 @@ public class WebSocketFrame implements Frame
*/ */
public WebSocketFrame(Frame frame) public WebSocketFrame(Frame frame)
{ {
if(frame instanceof WebSocketFrame) { if (frame instanceof WebSocketFrame)
{
WebSocketFrame wsf = (WebSocketFrame)frame; WebSocketFrame wsf = (WebSocketFrame)frame;
copy(wsf,wsf.data); copy(wsf,wsf.data);
} else { }
else
{
// Copy manually // Copy manually
fin = frame.isFin(); fin = frame.isFin();
rsv1 = frame.isRsv1(); rsv1 = frame.isRsv1();
@ -320,6 +323,7 @@ public class WebSocketFrame implements Frame
return payloadLength; return payloadLength;
} }
@Override
public int getPayloadStart() public int getPayloadStart()
{ {
if (data == null) if (data == null)
@ -329,7 +333,7 @@ public class WebSocketFrame implements Frame
return payloadStart; return payloadStart;
} }
public SendHandler getSendResult() public SendHandler getSendHandler()
{ {
return sendHandler; return sendHandler;
} }
@ -340,6 +344,7 @@ public class WebSocketFrame implements Frame
return type; return type;
} }
@Override
public boolean hasPayload() public boolean hasPayload()
{ {
return ((data != null) && (payloadLength > 0)); return ((data != null) && (payloadLength > 0));
@ -402,20 +407,26 @@ public class WebSocketFrame implements Frame
return rsv3; return rsv3;
} }
public void notifySendHandler() { @Override
if(sendHandler == null) { public void notifySendFailed(Throwable t)
return; {
} if (sendHandler == null)
sendHandler.setResult(new SendResult(null)); {
}
public void notifySendHandler(Throwable t) {
if(sendHandler == null) {
return; return;
} }
sendHandler.setResult(new SendResult(t)); 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. * Get the position currently within the payload data.
* <p> * <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. * @return the number of bytes remaining in the payload data that has not yet been written out to Network ByteBuffers.
*/ */
@Override
public int remaining() public int remaining()
{ {
if (data == null) if (data == null)
@ -463,13 +475,13 @@ public class WebSocketFrame implements Frame
continuation = false; continuation = false;
} }
public WebSocketFrame setContinuation(boolean continuation) public Frame setContinuation(boolean continuation)
{ {
this.continuation = continuation; this.continuation = continuation;
return this; return this;
} }
public WebSocketFrame setContinuationIndex(int continuationIndex) public Frame setContinuationIndex(int continuationIndex)
{ {
this.continuationIndex = continuationIndex; this.continuationIndex = continuationIndex;
return this; return this;
@ -481,14 +493,14 @@ public class WebSocketFrame implements Frame
return this; return this;
} }
public WebSocketFrame setMask(byte[] maskingKey) public Frame setMask(byte[] maskingKey)
{ {
this.mask = maskingKey; this.mask = maskingKey;
this.masked = (mask != null); this.masked = (mask != null);
return this; return this;
} }
public WebSocketFrame setMasked(boolean mask) public Frame setMasked(boolean mask)
{ {
this.masked = mask; this.masked = mask;
return this; return this;
@ -640,6 +652,9 @@ public class WebSocketFrame implements Frame
b.append(rsv3?'1':'.'); b.append(rsv3?'1':'.');
b.append(",masked=").append(masked); b.append(",masked=").append(masked);
b.append(",continuation=").append(continuation); b.append(",continuation=").append(continuation);
b.append(",payloadStart=").append(getPayloadStart());
b.append(",remaining=").append(remaining());
b.append(",position=").append(position());
if (sendHandler != null) if (sendHandler != null)
{ {
b.append(",sendHandler=").append(sendHandler); b.append(",sendHandler=").append(sendHandler);

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -31,17 +31,16 @@ import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.WebSocketException;
import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.api.extensions.Frame; import org.eclipse.jetty.websocket.api.extensions.Frame;
import org.eclipse.jetty.websocket.api.extensions.IncomingFrames;
import org.eclipse.jetty.websocket.common.CloseInfo; import org.eclipse.jetty.websocket.common.CloseInfo;
import org.eclipse.jetty.websocket.common.OpCode; import org.eclipse.jetty.websocket.common.OpCode;
import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.WebSocketFrame;
import org.eclipse.jetty.websocket.common.extensions.AbstractJettyFrameHandler; import org.eclipse.jetty.websocket.common.WebSocketSession;
import org.eclipse.jetty.websocket.common.io.IncomingFrames;
import org.eclipse.jetty.websocket.common.io.WebSocketSession;
/** /**
* EventDriver is the main interface between the User's WebSocket POJO and the internal jetty implementation of WebSocket. * 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 Logger LOG;
protected final WebSocketPolicy policy; protected final WebSocketPolicy policy;
@ -50,7 +49,6 @@ public abstract class EventDriver extends AbstractJettyFrameHandler implements I
public EventDriver(WebSocketPolicy policy, Object websocket) public EventDriver(WebSocketPolicy policy, Object websocket)
{ {
super(null);
this.policy = policy; this.policy = policy;
this.websocket = websocket; this.websocket = websocket;
this.LOG = Log.getLogger(websocket.getClass()); this.LOG = Log.getLogger(websocket.getClass());
@ -66,12 +64,6 @@ public abstract class EventDriver extends AbstractJettyFrameHandler implements I
return session; return session;
} }
@Override
public void handleJettyFrame(WebSocketFrame frame)
{
incomingFrame(frame);
}
@Override @Override
public final void incomingError(WebSocketException e) public final void incomingError(WebSocketException e)
{ {
@ -90,7 +82,7 @@ public abstract class EventDriver extends AbstractJettyFrameHandler implements I
} }
@Override @Override
public void incomingFrame(WebSocketFrame frame) public void incomingFrame(Frame frame)
{ {
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
{ {
@ -101,7 +93,7 @@ public abstract class EventDriver extends AbstractJettyFrameHandler implements I
try try
{ {
switch (frame.getOpCode()) switch (frame.getType().getOpCode())
{ {
case OpCode.CLOSE: case OpCode.CLOSE:
{ {
@ -115,27 +107,21 @@ public abstract class EventDriver extends AbstractJettyFrameHandler implements I
session.close(close.getStatusCode(),close.getReason()); session.close(close.getStatusCode(),close.getReason());
// process handshake // process handshake
session.onCloseHandshake(true,close); session.getConnection().onCloseHandshake(true,close);
return; return;
} }
case OpCode.PING: case OpCode.PING:
{ {
WebSocketFrame pong = new WebSocketFrame(OpCode.PONG); ByteBuffer pongBuf = ByteBuffer.allocate(frame.getPayloadLength());
if (frame.getPayloadLength() > 0) if (frame.getPayloadLength() > 0)
{ {
// Copy payload // Copy payload
ByteBuffer pongBuf = ByteBuffer.allocate(frame.getPayloadLength());
BufferUtil.clearToFill(pongBuf); BufferUtil.clearToFill(pongBuf);
BufferUtil.put(frame.getPayload(),pongBuf); BufferUtil.put(frame.getPayload(),pongBuf);
BufferUtil.flipToFlush(pongBuf,0); 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; break;
} }
case OpCode.BINARY: case OpCode.BINARY:

View File

@ -18,20 +18,37 @@
package org.eclipse.jetty.websocket.common.extensions; 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.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.WebSocketPolicy;
import org.eclipse.jetty.websocket.api.extensions.Extension; import org.eclipse.jetty.websocket.api.extensions.Extension;
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
import org.eclipse.jetty.websocket.api.extensions.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 public abstract class AbstractExtension implements Extension
{ {
private final Logger log;
private WebSocketPolicy policy; private WebSocketPolicy policy;
private ByteBufferPool bufferPool; private ByteBufferPool bufferPool;
private ExtensionConfig config; 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() public ByteBufferPool getBufferPool()
{ {
@ -44,7 +61,7 @@ public abstract class AbstractExtension implements Extension
return config; return config;
} }
public WebSocketConnection getConnection() public LogicalConnection getConnection()
{ {
return connection; return connection;
} }
@ -55,17 +72,17 @@ public abstract class AbstractExtension implements Extension
return config.getName(); return config.getName();
} }
@Override
public Map<String, String> getParameters()
{
return config.getParameters();
}
public WebSocketPolicy getPolicy() public WebSocketPolicy getPolicy()
{ {
return policy; 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. * Used to indicate that the extension makes use of the RSV1 bit of the base websocket framing.
* <p> * <p>
@ -122,6 +139,23 @@ public abstract class AbstractExtension implements Extension
return false; 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) public void setBufferPool(ByteBufferPool bufferPool)
{ {
this.bufferPool = bufferPool; this.bufferPool = bufferPool;
@ -132,11 +166,23 @@ public abstract class AbstractExtension implements Extension
this.config = config; this.config = config;
} }
public void setConnection(WebSocketConnection connection) public void setConnection(LogicalConnection connection)
{ {
this.connection = 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) public void setPolicy(WebSocketPolicy policy)
{ {
this.policy = policy; this.policy = policy;

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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.Extension;
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
import org.eclipse.jetty.websocket.api.extensions.ExtensionFactory; import org.eclipse.jetty.websocket.api.extensions.ExtensionFactory;
import org.eclipse.jetty.websocket.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 WebSocketPolicy policy;
private ByteBufferPool bufferPool; private ByteBufferPool bufferPool;
public WebSocketExtensionRegistry(WebSocketPolicy policy, ByteBufferPool bufferPool) public WebSocketExtensionFactory(WebSocketPolicy policy, ByteBufferPool bufferPool)
{ {
super();
this.policy = policy; this.policy = policy;
this.bufferPool = bufferPool; this.bufferPool = bufferPool;
// FIXME this.registry.put("identity",IdentityExtension.class); register("identity",IdentityExtension.class);
// FIXME this.registry.put("fragment",FragmentExtension.class); register("fragment",FragmentExtension.class);
// FIXME this.registry.put("x-webkit-deflate-frame",WebkitDeflateFrameExtension.class); register("x-webkit-deflate-frame",FrameCompressionExtension.class);
// FIXME this.registry.put("permessage-compress",PerMessageCompressionExtension.class); register("permessage-compress",MessageCompressionExtension.class);
} }
@Override
public Extension newInstance(ExtensionConfig config) public Extension newInstance(ExtensionConfig config)
{ {
if (config == null) if (config == null)
@ -55,14 +61,12 @@ public class WebSocketExtensionRegistry extends ExtensionFactory
return null; return null;
} }
Extension registeredExt = getExtension(name); Class<? extends Extension> extClass = getExtension(name);
if (registeredExt == null) if (extClass == null)
{ {
return null; return null;
} }
Class<? extends Extension> extClass = registeredExt.getClass();
try try
{ {
Extension ext = extClass.newInstance(); Extension ext = extClass.newInstance();

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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() + "[]";
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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() + "[]";
}
}

View File

@ -19,9 +19,18 @@
package org.eclipse.jetty.websocket.common.extensions.fragment; 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.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.AbstractExtension;
import org.eclipse.jetty.websocket.common.extensions.PassthruFrameHandler;
/** /**
* Fragment Extension * Fragment Extension
@ -31,16 +40,72 @@ public class FragmentExtension extends AbstractExtension
private int maxLength = -1; private int maxLength = -1;
@Override @Override
public javax.net.websocket.extensions.FrameHandler createIncomingFrameHandler(javax.net.websocket.extensions.FrameHandler incoming) public void incomingError(WebSocketException e)
{ {
// pass through handler // Pass thru
return new PassthruFrameHandler(incoming); nextIncomingError(e);
} }
@Override @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 @Override

View File

@ -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);
}
}

View File

@ -18,25 +18,40 @@
package org.eclipse.jetty.websocket.common.extensions.identity; 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.util.QuotedStringTokenizer;
import org.eclipse.jetty.websocket.api.WebSocketException;
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; 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.AbstractExtension;
import org.eclipse.jetty.websocket.common.extensions.PassthruFrameHandler;
public class IdentityExtension extends AbstractExtension public class IdentityExtension extends AbstractExtension
{ {
private String id; private String id;
@Override @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 @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 @Override

View File

@ -18,9 +18,13 @@
package org.eclipse.jetty.websocket.common.extensions.mux; 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; import org.eclipse.jetty.websocket.common.extensions.AbstractExtension;
/** /**
@ -40,19 +44,20 @@ public abstract class AbstractMuxExtension extends AbstractExtension
public abstract void configureMuxer(Muxer muxer); public abstract void configureMuxer(Muxer muxer);
@Override @Override
public FrameHandler createIncomingFrameHandler(FrameHandler incoming) public void incomingFrame(Frame frame)
{ {
return new MuxerIncomingFrameHandler(incoming,muxer); this.muxer.incomingFrame(frame);
} }
@Override @Override
public FrameHandler createOutgoingFrameHandler(FrameHandler outgoing) public Future<SendResult> outgoingFrame(Frame frame) throws IOException
{ {
return new MuxerOutgoingFrameHandler(outgoing,muxer); /* do nothing */
return null;
} }
@Override @Override
public void setConnection(WebSocketConnection connection) public void setConnection(LogicalConnection connection)
{ {
super.setConnection(connection); super.setConnection(connection);
if (muxer != null) if (muxer != null)

View File

@ -22,7 +22,6 @@ import java.io.IOException;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.URI; import java.net.URI;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.List;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicBoolean; 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.WebSocketConnection;
import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.WebSocketException;
import org.eclipse.jetty.websocket.api.WebSocketPolicy; 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.CloseInfo;
import org.eclipse.jetty.websocket.common.ConnectionState; 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.WebSocketFrame;
import org.eclipse.jetty.websocket.common.extensions.AbstractExtension; import org.eclipse.jetty.websocket.common.WebSocketSession;
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;
/** /**
* MuxChannel, acts as WebSocketConnection for specific sub-channel. * 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); 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); 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 @Override
public void close() public void close()
{ {
@ -97,12 +108,6 @@ public class MuxChannel implements WebSocketConnection, InternalConnection, Inco
} }
} }
@Override
public void configureFromExtensions(List<Extension> extensions)
{
/* ignore */
}
@Override @Override
public void disconnect() public void disconnect()
{ {
@ -141,6 +146,7 @@ public class MuxChannel implements WebSocketConnection, InternalConnection, Inco
return null; return null;
} }
@Override
public WebSocketSession getSession() public WebSocketSession getSession()
{ {
return session; return session;
@ -171,7 +177,7 @@ public class MuxChannel implements WebSocketConnection, InternalConnection, Inco
* Incoming frames from Muxer * Incoming frames from Muxer
*/ */
@Override @Override
public void incomingFrame(WebSocketFrame frame) public void incomingFrame(Frame frame)
{ {
incoming.incomingFrame(frame); incoming.incomingFrame(frame);
} }
@ -250,7 +256,7 @@ public class MuxChannel implements WebSocketConnection, InternalConnection, Inco
* Frames destined for the Muxer * Frames destined for the Muxer
*/ */
@Override @Override
public Future<SendResult> outgoingFrame(WebSocketFrame frame) throws IOException public Future<SendResult> outgoingFrame(Frame frame) throws IOException
{ {
return muxer.output(channelId,frame); return muxer.output(channelId,frame);
} }
@ -259,9 +265,9 @@ public class MuxChannel implements WebSocketConnection, InternalConnection, Inco
* Ping frame destined for the Muxer * Ping frame destined for the Muxer
*/ */
@Override @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 @Override
@ -274,7 +280,7 @@ public class MuxChannel implements WebSocketConnection, InternalConnection, Inco
} }
@Override @Override
public void setIncoming(IncomingFrames incoming) public void setNextIncomingFrames(IncomingFrames incoming)
{ {
this.incoming = incoming; this.incoming = incoming;
} }
@ -283,7 +289,7 @@ public class MuxChannel implements WebSocketConnection, InternalConnection, Inco
public void setSession(WebSocketSession session) public void setSession(WebSocketSession session)
{ {
this.session = session; this.session = session;
session.setOutgoing(this); // session.setOutgoing(this);
} }
public void setSubProtocol(String subProtocol) public void setSubProtocol(String subProtocol)
@ -299,40 +305,6 @@ public class MuxChannel implements WebSocketConnection, InternalConnection, Inco
return this; 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 * Generate a binary message, destined for Muxer
*/ */

View File

@ -27,13 +27,14 @@ import javax.net.websocket.SendResult;
import org.eclipse.jetty.io.ArrayByteBufferPool; import org.eclipse.jetty.io.ArrayByteBufferPool;
import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.util.BufferUtil; 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.WebSocketFrame;
import org.eclipse.jetty.websocket.common.extensions.mux.op.MuxAddChannelRequest; 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.MuxAddChannelResponse;
import org.eclipse.jetty.websocket.common.extensions.mux.op.MuxDropChannel; 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.MuxFlowControl;
import org.eclipse.jetty.websocket.common.extensions.mux.op.MuxNewChannelSlot; 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. * Generate Mux frames destined for the physical connection.
@ -56,7 +57,7 @@ public class MuxGenerator
this.bufferPool = bufferPool; 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); ByteBuffer muxPayload = bufferPool.acquire(frame.getPayloadLength() + DATA_FRAME_OVERHEAD,false);
BufferUtil.flipToFill(muxPayload); BufferUtil.flipToFill(muxPayload);
@ -67,7 +68,7 @@ public class MuxGenerator
b |= (byte)(frame.isRsv1()?0x40:0x00); // rsv1 b |= (byte)(frame.isRsv1()?0x40:0x00); // rsv1
b |= (byte)(frame.isRsv2()?0x20:0x00); // rsv2 b |= (byte)(frame.isRsv2()?0x20:0x00); // rsv2
b |= (byte)(frame.isRsv3()?0x10:0x00); // rsv3 b |= (byte)(frame.isRsv3()?0x10:0x00); // rsv3
b |= (byte)(frame.getOpCode() & 0x0F); // opcode b |= (byte)(frame.getType().getOpCode() & 0x0F); // opcode
muxPayload.put(b); muxPayload.put(b);
BufferUtil.put(frame.getPayload(),muxPayload); BufferUtil.put(frame.getPayload(),muxPayload);

View File

@ -23,6 +23,7 @@ import java.nio.ByteBuffer;
import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.api.extensions.Frame;
import org.eclipse.jetty.websocket.common.OpCode; import org.eclipse.jetty.websocket.common.OpCode;
import org.eclipse.jetty.websocket.common.WebSocketFrame; 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.MuxAddChannelRequest;
@ -67,7 +68,7 @@ public class MuxParser
* @param frame * @param frame
* the WebSocketFrame to parse for mux payload * the WebSocketFrame to parse for mux payload
*/ */
public synchronized void parse(WebSocketFrame frame) public synchronized void parse(Frame frame)
{ {
if (events == null) if (events == null)
{ {
@ -80,7 +81,7 @@ public class MuxParser
return; // nothing to parse return; // nothing to parse
} }
if (frame.getOpCode() != OpCode.BINARY) if (frame.getType().getOpCode() != OpCode.BINARY)
{ {
LOG.debug("Not a binary opcode (base frame), skipping"); LOG.debug("Not a binary opcode (base frame), skipping");
return; // not a binary opcode return; // not a binary opcode

View File

@ -32,10 +32,14 @@ import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.api.StatusCode; import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.UpgradeRequest; 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.WebSocketBehavior;
import org.eclipse.jetty.websocket.api.WebSocketConnection;
import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.WebSocketException;
import org.eclipse.jetty.websocket.api.WebSocketPolicy; 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.WebSocketFrame;
import org.eclipse.jetty.websocket.common.extensions.mux.add.MuxAddClient; import org.eclipse.jetty.websocket.common.extensions.mux.add.MuxAddClient;
import org.eclipse.jetty.websocket.common.extensions.mux.add.MuxAddServer; 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.MuxDropChannel;
import org.eclipse.jetty.websocket.common.extensions.mux.op.MuxFlowControl; 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.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. * 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 Map<Long, MuxChannel> channels = new HashMap<Long, MuxChannel>();
private final WebSocketPolicy policy; private final WebSocketPolicy policy;
private final WebSocketConnection physicalConnection; private final LogicalConnection physicalConnection;
private InetSocketAddress remoteAddress; private InetSocketAddress remoteAddress;
/** Parsing frames destined for sub-channels */ /** Parsing frames destined for sub-channels */
private MuxParser parser; private MuxParser parser;
@ -76,11 +78,11 @@ public class Muxer implements IncomingFrames, MuxParser.Listener
private MuxAddServer addServer; private MuxAddServer addServer;
private MuxAddClient addClient; private MuxAddClient addClient;
/** The original request headers, used for delta encoded AddChannelRequest blocks */ /** 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 */ /** 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.physicalConnection = connection;
this.policy = connection.getPolicy().clonePolicy(); this.policy = connection.getPolicy().clonePolicy();
@ -152,7 +154,7 @@ public class Muxer implements IncomingFrames, MuxParser.Listener
* Incoming mux encapsulated frames. * Incoming mux encapsulated frames.
*/ */
@Override @Override
public void incomingFrame(WebSocketFrame frame) public void incomingFrame(Frame frame)
{ {
parser.parse(frame); parser.parse(frame);
} }
@ -383,7 +385,7 @@ public class Muxer implements IncomingFrames, MuxParser.Listener
/** /**
* Outgoing frame, without mux encapsulated payload. * 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()) if (LOG.isDebugEnabled())
{ {

View File

@ -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;
}
}

View File

@ -18,8 +18,8 @@
package org.eclipse.jetty.websocket.common.extensions.mux.add; 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.extensions.mux.op.MuxAddChannelResponse;
import org.eclipse.jetty.websocket.common.io.WebSocketSession;
/** /**
* Interface for Mux Client to handle receiving a AddChannelResponse * Interface for Mux Client to handle receiving a AddChannelResponse

View File

@ -22,10 +22,10 @@ import java.io.IOException;
import org.eclipse.jetty.websocket.api.UpgradeRequest; import org.eclipse.jetty.websocket.api.UpgradeRequest;
import org.eclipse.jetty.websocket.api.UpgradeResponse; 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.MuxChannel;
import org.eclipse.jetty.websocket.common.extensions.mux.MuxException; 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.Muxer;
import org.eclipse.jetty.websocket.common.io.WebSocketSession;
/** /**
* Server interface, for dealing with incoming AddChannelRequest / AddChannelResponse flows. * Server interface, for dealing with incoming AddChannelRequest / AddChannelResponse flows.

View File

@ -44,17 +44,19 @@ import org.eclipse.jetty.websocket.api.SuspendToken;
import org.eclipse.jetty.websocket.api.WebSocketConnection; import org.eclipse.jetty.websocket.api.WebSocketConnection;
import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
import org.eclipse.jetty.websocket.api.extensions.Frame;
import org.eclipse.jetty.websocket.common.CloseInfo; import org.eclipse.jetty.websocket.common.CloseInfo;
import org.eclipse.jetty.websocket.common.ConnectionState; import org.eclipse.jetty.websocket.common.ConnectionState;
import org.eclipse.jetty.websocket.common.Generator; 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.OpCode;
import org.eclipse.jetty.websocket.common.Parser; 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 * 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 = Log.getLogger(AbstractWebSocketConnection.class);
private static final Logger LOG_FRAMES = Log.getLogger("org.eclipse.jetty.websocket.io.Frames"); 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); 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 @Override
public void close() public void close()
{ {
@ -232,6 +252,7 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp
return parser; return parser;
} }
@Override
public WebSocketPolicy getPolicy() public WebSocketPolicy getPolicy()
{ {
return this.policy; return this.policy;
@ -253,6 +274,7 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp
return scheduler; return scheduler;
} }
@Override
public WebSocketSession getSession() public WebSocketSession getSession()
{ {
return session; return session;
@ -370,15 +392,12 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp
return true; return true;
} }
/**
* Enqueue internal frame from {@link OutgoingFrames} stack for eventual write out on the physical connection.
*/
@Override @Override
public Future<SendResult> outgoingFrame(WebSocketFrame frame) throws IOException public Future<SendResult> outgoingFrame(Frame frame) throws IOException
{ {
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
{ {
LOG.debug("output({})",frame); LOG.debug("outgoingFrame({})",frame);
} }
Future<SendResult> future = null; Future<SendResult> future = null;
@ -402,7 +421,7 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp
if (isOpen()) if (isOpen())
{ {
if (frame.getOpCode() == OpCode.PING) if (frame.getType().getOpCode() == OpCode.PING)
{ {
queue.prepend(bytes); queue.prepend(bytes);
} }

View File

@ -24,9 +24,9 @@ import javax.net.websocket.SendResult;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.api.extensions.Frame;
import org.eclipse.jetty.websocket.common.CloseInfo; import org.eclipse.jetty.websocket.common.CloseInfo;
import org.eclipse.jetty.websocket.common.OpCode; import org.eclipse.jetty.websocket.common.OpCode;
import org.eclipse.jetty.websocket.common.WebSocketFrame;
public class ControlFrameBytes extends FrameBytes public class ControlFrameBytes extends FrameBytes
{ {
@ -34,7 +34,7 @@ public class ControlFrameBytes extends FrameBytes
private ByteBuffer buffer; private ByteBuffer buffer;
private ByteBuffer origPayload; private ByteBuffer origPayload;
public ControlFrameBytes(AbstractWebSocketConnection connection, WebSocketFrame frame) public ControlFrameBytes(AbstractWebSocketConnection connection, Frame frame)
{ {
super(connection,frame); super(connection,frame);
} }
@ -47,7 +47,7 @@ public class ControlFrameBytes extends FrameBytes
super.completed(context); super.completed(context);
if (frame.getOpCode() == OpCode.CLOSE) if (frame.getType().getOpCode() == OpCode.CLOSE)
{ {
CloseInfo close = new CloseInfo(origPayload,false); CloseInfo close = new CloseInfo(origPayload,false);
connection.onCloseHandshake(false,close); connection.onCloseHandshake(false,close);

View File

@ -24,14 +24,14 @@ import javax.net.websocket.SendResult;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.api.extensions.Frame;
public class DataFrameBytes extends FrameBytes public class DataFrameBytes extends FrameBytes
{ {
private static final Logger LOG = Log.getLogger(DataFrameBytes.class); private static final Logger LOG = Log.getLogger(DataFrameBytes.class);
private ByteBuffer buffer; private ByteBuffer buffer;
public DataFrameBytes(AbstractWebSocketConnection connection, WebSocketFrame frame) public DataFrameBytes(AbstractWebSocketConnection connection, Frame frame)
{ {
super(connection,frame); super(connection,frame);
} }

View File

@ -28,17 +28,17 @@ import org.eclipse.jetty.util.FutureCallback;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.thread.Scheduler; 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 public abstract class FrameBytes extends FutureCallback<SendResult> implements Runnable
{ {
private final static Logger LOG = Log.getLogger(FrameBytes.class); private final static Logger LOG = Log.getLogger(FrameBytes.class);
protected final AbstractWebSocketConnection connection; protected final AbstractWebSocketConnection connection;
protected final WebSocketFrame frame; protected final Frame frame;
// Task used to timeout the bytes // Task used to timeout the bytes
protected volatile Scheduler.Task task; protected volatile Scheduler.Task task;
protected FrameBytes(AbstractWebSocketConnection connection, WebSocketFrame frame) protected FrameBytes(AbstractWebSocketConnection connection, Frame frame)
{ {
this.connection = connection; this.connection = connection;
this.frame = frame; this.frame = frame;
@ -63,7 +63,7 @@ public abstract class FrameBytes extends FutureCallback<SendResult> implements R
} }
cancelTask(); cancelTask();
connection.complete(this); connection.complete(this);
frame.notifySendHandler(); frame.notifySendSuccess();
} }
@Override @Override
@ -80,7 +80,7 @@ public abstract class FrameBytes extends FutureCallback<SendResult> implements R
LOG.warn("failed(" + v + ")",x); LOG.warn("failed(" + v + ")",x);
} }
cancelTask(); cancelTask();
frame.notifySendHandler(x); frame.notifySendFailed(x);
} }
public abstract ByteBuffer getByteBuffer(); public abstract ByteBuffer getByteBuffer();

View File

@ -8,7 +8,9 @@ import javax.net.websocket.SendResult;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.api.WebSocketException; 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 public class FramePipes
{ {
@ -29,7 +31,7 @@ public class FramePipes
} }
@Override @Override
public void incomingFrame(WebSocketFrame frame) public void incomingFrame(Frame frame)
{ {
try try
{ {
@ -52,7 +54,7 @@ public class FramePipes
} }
@Override @Override
public Future<SendResult> outgoingFrame(WebSocketFrame frame) throws IOException public Future<SendResult> outgoingFrame(Frame frame) throws IOException
{ {
this.incoming.incomingFrame(frame); this.incoming.incomingFrame(frame);

View File

@ -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");
}
}
}

View File

@ -20,7 +20,7 @@ package org.eclipse.jetty.websocket.common.io.payload;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.api.extensions.Frame;
public class DeMaskProcessor implements PayloadProcessor public class DeMaskProcessor implements PayloadProcessor
{ {
@ -45,7 +45,7 @@ public class DeMaskProcessor implements PayloadProcessor
} }
@Override @Override
public void reset(WebSocketFrame frame) public void reset(Frame frame)
{ {
this.isMasked = frame.isMasked(); this.isMasked = frame.isMasked();
if (isMasked) if (isMasked)

View File

@ -20,7 +20,7 @@ package org.eclipse.jetty.websocket.common.io.payload;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.api.extensions.Frame;
/** /**
* payload validator does no validation. * payload validator does no validation.
@ -36,7 +36,7 @@ public class NoOpValidator implements PayloadProcessor
} }
@Override @Override
public void reset(WebSocketFrame frame) public void reset(Frame frame)
{ {
/* do nothing */ /* do nothing */
} }

View File

@ -21,7 +21,7 @@ package org.eclipse.jetty.websocket.common.io.payload;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import org.eclipse.jetty.websocket.api.BadPayloadException; 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..) * Process the payload (for demasking, validating, etc..)
@ -38,5 +38,5 @@ public interface PayloadProcessor
*/ */
public void process(ByteBuffer payload); public void process(ByteBuffer payload);
public void reset(WebSocketFrame frame); public void reset(Frame frame);
} }

View File

@ -26,7 +26,7 @@ import org.eclipse.jetty.util.Utf8Appendable;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.api.BadPayloadException; 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) * Used to perform validation of UTF8 payload contents (for fast-fail reasons)
@ -104,7 +104,7 @@ public class UTF8Validator extends Utf8Appendable implements PayloadProcessor
} }
@Override @Override
public void reset(WebSocketFrame frame) public void reset(Frame frame)
{ {
/* do nothing */ /* do nothing */
} }

View File

@ -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; import org.eclipse.jetty.websocket.common.LogicalConnection;
public interface InternalConnection extends LogicalConnection public class MessageOutputStream extends OutputStream
{ {
// TODO: find way to remove private final LogicalConnection connection;
void configureFromExtensions(List<Extension> extensions); 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
}
} }

View File

@ -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
}
}

View File

@ -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 javax.net.websocket.SendResult;
import org.eclipse.jetty.websocket.common.extensions.AbstractJettyFrameHandler;
import org.eclipse.jetty.websocket.common.io.IncomingFrames;
/** public class FinishedFuture extends FutureTask<SendResult> implements Future<SendResult>
* Process incoming frames and forward them off to the Muxer.
*/
public class MuxerIncomingFrameHandler extends AbstractJettyFrameHandler
{ {
private final IncomingFrames muxerHandler; public static Future<SendResult> INSTANCE;
public MuxerIncomingFrameHandler(FrameHandler nextHandler, Muxer muxer) static
{ {
super(nextHandler); Callable<SendResult> callable = new Callable<SendResult>()
this.muxerHandler = muxer; {
@Override
public SendResult call() throws Exception
{
return new SendResult();
}
};
FinishedFuture fut = new FinishedFuture(callable);
fut.run();
INSTANCE = fut;
} }
@Override public FinishedFuture(Callable<SendResult> callable)
public void handleJettyFrame(WebSocketFrame frame)
{ {
this.muxerHandler.incomingFrame(frame); super(callable);
} }
} }

View File

@ -26,24 +26,17 @@ import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.WebSocketException;
import org.eclipse.jetty.websocket.common.OpCode; import org.eclipse.jetty.websocket.api.extensions.Frame;
import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.api.extensions.IncomingFrames;
import org.eclipse.jetty.websocket.common.extensions.AbstractJettyFrameHandler;
import org.eclipse.jetty.websocket.common.io.IncomingFrames;
import org.junit.Assert; 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 static final Logger LOG = Log.getLogger(IncomingFramesCapture.class);
private LinkedList<WebSocketFrame> frames = new LinkedList<>(); private LinkedList<WebSocketFrame> frames = new LinkedList<>();
private LinkedList<WebSocketException> errors = 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) public void assertErrorCount(int expectedCount)
{ {
Assert.assertThat("Captured error count",errors.size(),is(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()); System.err.printf("Captured %d incoming frames%n",frames.size());
for (int i = 0; i < frames.size(); i++) 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("[%3d] %s%n",i,frame);
System.err.printf(" %s%n",BufferUtil.toDetailString(frame.getPayload())); System.err.printf(" %s%n",BufferUtil.toDetailString(frame.getPayload()));
} }
@ -126,12 +119,6 @@ public class IncomingFramesCapture extends AbstractJettyFrameHandler implements
return frames; return frames;
} }
@Override
public void handleJettyFrame(WebSocketFrame frame)
{
incomingFrame(frame);
}
@Override @Override
public void incomingError(WebSocketException e) public void incomingError(WebSocketException e)
{ {
@ -140,7 +127,7 @@ public class IncomingFramesCapture extends AbstractJettyFrameHandler implements
} }
@Override @Override
public void incomingFrame(WebSocketFrame frame) public void incomingFrame(Frame frame)
{ {
WebSocketFrame copy = new WebSocketFrame(frame); WebSocketFrame copy = new WebSocketFrame(frame);
frames.add(copy); frames.add(copy);

View File

@ -26,19 +26,14 @@ import java.util.concurrent.Future;
import javax.net.websocket.SendResult; import javax.net.websocket.SendResult;
import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.websocket.common.extensions.AbstractJettyFrameHandler; import org.eclipse.jetty.websocket.api.extensions.Frame;
import org.eclipse.jetty.websocket.common.io.OutgoingFrames; import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames;
import org.junit.Assert; import org.junit.Assert;
public class OutgoingFramesCapture extends AbstractJettyFrameHandler implements OutgoingFrames public class OutgoingFramesCapture implements OutgoingFrames
{ {
private LinkedList<WebSocketFrame> frames = new LinkedList<>(); 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) public void assertFrameCount(int expectedCount)
{ {
Assert.assertThat("Captured frame count",frames.size(),is(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()); System.out.printf("Captured %d outgoing writes%n",frames.size());
for (int i = 0; i < frames.size(); i++) 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("[%3d] %s%n",i,frame);
System.out.printf(" %s%n",BufferUtil.toDetailString(frame.getPayload())); System.out.printf(" %s%n",BufferUtil.toDetailString(frame.getPayload()));
} }
@ -89,16 +84,11 @@ public class OutgoingFramesCapture extends AbstractJettyFrameHandler implements
} }
@Override @Override
public void handleJettyFrame(WebSocketFrame frame) public Future<SendResult> outgoingFrame(Frame frame)
{ {
outgoingFrame(frame); WebSocketFrame copy = new WebSocketFrame(frame);
} frames.add(copy);
@Override return FinishedFuture.INSTANCE;
public Future<SendResult> outgoingFrame(WebSocketFrame frame)
{
frames.add(frame);
return null; // FIXME: should return completed future.
} }
} }

View File

@ -30,21 +30,20 @@ import javax.net.websocket.SendResult;
import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.TypeUtil; import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.websocket.common.extensions.AbstractJettyFrameHandler; import org.eclipse.jetty.websocket.api.extensions.Frame;
import org.eclipse.jetty.websocket.common.io.OutgoingFrames; import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames;
import org.junit.Assert; import org.junit.Assert;
/** /**
* Capture outgoing network bytes. * Capture outgoing network bytes.
*/ */
public class OutgoingNetworkBytesCapture extends AbstractJettyFrameHandler implements OutgoingFrames public class OutgoingNetworkBytesCapture implements OutgoingFrames
{ {
private final Generator generator; private final Generator generator;
private List<ByteBuffer> captured; private List<ByteBuffer> captured;
public OutgoingNetworkBytesCapture(Generator generator) public OutgoingNetworkBytesCapture(Generator generator)
{ {
super(null); // no sub handling, capture is end of the line.
this.generator = generator; this.generator = generator;
this.captured = new ArrayList<>(); this.captured = new ArrayList<>();
} }
@ -63,24 +62,11 @@ public class OutgoingNetworkBytesCapture extends AbstractJettyFrameHandler imple
} }
@Override @Override
public void handleJettyFrame(WebSocketFrame frame) public Future<SendResult> outgoingFrame(Frame frame) throws IOException
{
try
{
outgoingFrame(frame);
}
catch (IOException e)
{
throw new RuntimeException(e);
}
}
@Override
public Future<SendResult> outgoingFrame(WebSocketFrame frame) throws IOException
{ {
ByteBuffer buf = generator.generate(frame); ByteBuffer buf = generator.generate(frame);
captured.add(buf.slice()); captured.add(buf.slice());
return null; // FIXME: should return completed future. return FinishedFuture.INSTANCE;
} }
} }

View File

@ -23,6 +23,7 @@ import java.nio.ByteBuffer;
import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.websocket.api.WebSocketBehavior; import org.eclipse.jetty.websocket.api.WebSocketBehavior;
import org.eclipse.jetty.websocket.api.WebSocketPolicy; 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.OpCode;
import org.eclipse.jetty.websocket.common.Parser; import org.eclipse.jetty.websocket.common.Parser;
import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.WebSocketFrame;
@ -146,7 +147,7 @@ public class RFC6455ExamplesParserTest
capture.assertNoErrors(); capture.assertNoErrors();
capture.assertHasFrame(OpCode.BINARY,1); 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)); Assert.assertThat("BinaryFrame.payloadLength",bin.getPayloadLength(),is(dataSize));
@ -186,7 +187,7 @@ public class RFC6455ExamplesParserTest
capture.assertNoErrors(); capture.assertNoErrors();
capture.assertHasFrame(OpCode.BINARY,1); 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)); Assert.assertThat("BinaryFrame.payloadLength",bin.getPayloadLength(),is(dataSize));
ByteBuffer data = bin.getPayload(); ByteBuffer data = bin.getPayload();

View File

@ -24,8 +24,7 @@ import java.util.List;
import org.eclipse.jetty.io.MappedByteBufferPool; import org.eclipse.jetty.io.MappedByteBufferPool;
import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.common.Generator; import org.eclipse.jetty.websocket.api.extensions.Frame;
import org.eclipse.jetty.websocket.common.WebSocketFrame;
/** /**
* Convenience Generator. * Convenience Generator.
@ -34,7 +33,7 @@ public class UnitGenerator extends Generator
{ {
public static ByteBuffer generate(List<WebSocketFrame> frames) 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 = byte[] MASK =
{ 0x11, 0x22, 0x33, 0x44 }; { 0x11, 0x22, 0x33, 0x44 };
@ -43,7 +42,7 @@ public class UnitGenerator extends Generator
// Generate into single bytebuffer // Generate into single bytebuffer
int buflen = 0; int buflen = 0;
for (WebSocketFrame f : frames) for (Frame f : frames)
{ {
buflen += f.getPayloadLength() + Generator.OVERHEAD; buflen += f.getPayloadLength() + Generator.OVERHEAD;
} }

View File

@ -22,6 +22,7 @@ import java.nio.ByteBuffer;
import org.eclipse.jetty.websocket.api.WebSocketBehavior; import org.eclipse.jetty.websocket.api.WebSocketBehavior;
import org.eclipse.jetty.websocket.api.WebSocketPolicy; 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.ByteBufferAssert;
import org.eclipse.jetty.websocket.common.Generator; import org.eclipse.jetty.websocket.common.Generator;
import org.eclipse.jetty.websocket.common.IncomingFramesCapture; import org.eclipse.jetty.websocket.common.IncomingFramesCapture;
@ -320,7 +321,7 @@ public class TestABCase1_1
capture.assertNoErrors(); capture.assertNoErrors();
capture.assertHasFrame(OpCode.TEXT,1); 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.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length));
// Assert.assertEquals("TextFrame.payload",length,pActual.getPayloadData().length); // Assert.assertEquals("TextFrame.payload",length,pActual.getPayloadData().length);
} }
@ -354,7 +355,7 @@ public class TestABCase1_1
capture.assertNoErrors(); capture.assertNoErrors();
capture.assertHasFrame(OpCode.TEXT,1); 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.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length));
// Assert.assertEquals("TextFrame.payload",length,pActual.getPayloadData().length); // Assert.assertEquals("TextFrame.payload",length,pActual.getPayloadData().length);
} }
@ -388,7 +389,7 @@ public class TestABCase1_1
capture.assertNoErrors(); capture.assertNoErrors();
capture.assertHasFrame(OpCode.TEXT,1); 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.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length));
// Assert.assertEquals("TextFrame.payload",length,pActual.getPayloadData().length); // Assert.assertEquals("TextFrame.payload",length,pActual.getPayloadData().length);
} }
@ -422,7 +423,7 @@ public class TestABCase1_1
capture.assertNoErrors(); capture.assertNoErrors();
capture.assertHasFrame(OpCode.TEXT,1); 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.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length));
// .assertEquals("TextFrame.payload",length,pActual.getPayloadData().length); // .assertEquals("TextFrame.payload",length,pActual.getPayloadData().length);
} }
@ -461,7 +462,7 @@ public class TestABCase1_1
capture.assertNoErrors(); capture.assertNoErrors();
capture.assertHasFrame(OpCode.TEXT,1); 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.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length));
// Assert.assertEquals("TextFrame.payload",length,pActual.getPayloadData().length); // Assert.assertEquals("TextFrame.payload",length,pActual.getPayloadData().length);
} }
@ -498,7 +499,7 @@ public class TestABCase1_1
capture.assertNoErrors(); capture.assertNoErrors();
capture.assertHasFrame(OpCode.TEXT,1); 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.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length));
// Assert.assertEquals("TextFrame.payload",length,pActual.getPayloadData().length); // Assert.assertEquals("TextFrame.payload",length,pActual.getPayloadData().length);
} }
@ -522,7 +523,7 @@ public class TestABCase1_1
capture.assertNoErrors(); capture.assertNoErrors();
capture.assertHasFrame(OpCode.TEXT,1); 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)); Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(0));
} }
} }

View File

@ -23,6 +23,7 @@ import java.nio.ByteBuffer;
import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.websocket.api.WebSocketBehavior; import org.eclipse.jetty.websocket.api.WebSocketBehavior;
import org.eclipse.jetty.websocket.api.WebSocketPolicy; 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.ByteBufferAssert;
import org.eclipse.jetty.websocket.common.Generator; import org.eclipse.jetty.websocket.common.Generator;
import org.eclipse.jetty.websocket.common.IncomingFramesCapture; import org.eclipse.jetty.websocket.common.IncomingFramesCapture;
@ -336,7 +337,7 @@ public class TestABCase1_2
capture.assertNoErrors(); capture.assertNoErrors();
capture.assertHasFrame(OpCode.BINARY,1); 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.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length));
// Assert.assertEquals("BinaryFrame.payload",length,pActual.getPayloadData().length); // Assert.assertEquals("BinaryFrame.payload",length,pActual.getPayloadData().length);
} }
@ -370,7 +371,7 @@ public class TestABCase1_2
capture.assertNoErrors(); capture.assertNoErrors();
capture.assertHasFrame(OpCode.BINARY,1); 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.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length));
// Assert.assertEquals("BinaryFrame.payload",length,pActual.getPayloadData().length); // Assert.assertEquals("BinaryFrame.payload",length,pActual.getPayloadData().length);
} }
@ -404,7 +405,7 @@ public class TestABCase1_2
capture.assertNoErrors(); capture.assertNoErrors();
capture.assertHasFrame(OpCode.BINARY,1); 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.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length));
// .assertEquals("BinaryFrame.payload",length,pActual.getPayloadData().length); // .assertEquals("BinaryFrame.payload",length,pActual.getPayloadData().length);
} }
@ -438,7 +439,7 @@ public class TestABCase1_2
capture.assertNoErrors(); capture.assertNoErrors();
capture.assertHasFrame(OpCode.BINARY,1); 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.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length));
// Assert.assertEquals("BinaryFrame.payload",length,pActual.getPayloadData().length); // Assert.assertEquals("BinaryFrame.payload",length,pActual.getPayloadData().length);
} }
@ -473,7 +474,7 @@ public class TestABCase1_2
capture.assertNoErrors(); capture.assertNoErrors();
capture.assertHasFrame(OpCode.BINARY,1); 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.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length));
// Assert.assertEquals("BinaryFrame.payload",length,pActual.getPayloadData().length); // Assert.assertEquals("BinaryFrame.payload",length,pActual.getPayloadData().length);
} }
@ -510,7 +511,7 @@ public class TestABCase1_2
capture.assertNoErrors(); capture.assertNoErrors();
capture.assertHasFrame(OpCode.BINARY,1); 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.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length));
// Assert.assertEquals("BinaryFrame.payload",length,pActual.getPayloadData().length); // Assert.assertEquals("BinaryFrame.payload",length,pActual.getPayloadData().length);
} }
@ -534,7 +535,7 @@ public class TestABCase1_2
capture.assertNoErrors(); capture.assertNoErrors();
capture.assertHasFrame(OpCode.BINARY,1); 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.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(0));
// Assert.assertNull("BinaryFrame.payload",pActual.getPayloadData()); // Assert.assertNull("BinaryFrame.payload",pActual.getPayloadData());
} }

View File

@ -25,6 +25,7 @@ import org.eclipse.jetty.websocket.api.ProtocolException;
import org.eclipse.jetty.websocket.api.WebSocketBehavior; import org.eclipse.jetty.websocket.api.WebSocketBehavior;
import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.WebSocketException;
import org.eclipse.jetty.websocket.api.WebSocketPolicy; 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.ByteBufferAssert;
import org.eclipse.jetty.websocket.common.Generator; import org.eclipse.jetty.websocket.common.Generator;
import org.eclipse.jetty.websocket.common.IncomingFramesCapture; import org.eclipse.jetty.websocket.common.IncomingFramesCapture;
@ -201,7 +202,7 @@ public class TestABCase2
capture.assertNoErrors(); capture.assertNoErrors();
capture.assertHasFrame(OpCode.PING,1); 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.assertThat("PingFrame.payloadLength",pActual.getPayloadLength(),is(bytes.length));
Assert.assertEquals("PingFrame.payload",bytes.length,pActual.getPayloadLength()); Assert.assertEquals("PingFrame.payload",bytes.length,pActual.getPayloadLength());
} }
@ -231,7 +232,7 @@ public class TestABCase2
capture.assertNoErrors(); capture.assertNoErrors();
capture.assertHasFrame(OpCode.PING,1); 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.assertThat("PingFrame.payloadLength",pActual.getPayloadLength(),is(bytes.length));
Assert.assertEquals("PingFrame.payload",bytes.length,pActual.getPayloadLength()); Assert.assertEquals("PingFrame.payload",bytes.length,pActual.getPayloadLength());
} }
@ -254,7 +255,7 @@ public class TestABCase2
capture.assertNoErrors(); capture.assertNoErrors();
capture.assertHasFrame(OpCode.PING,1); 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.assertThat("PingFrame.payloadLength",pActual.getPayloadLength(),is(0));
Assert.assertEquals("PingFrame.payload",0,pActual.getPayloadLength()); Assert.assertEquals("PingFrame.payload",0,pActual.getPayloadLength());
} }
@ -285,7 +286,7 @@ public class TestABCase2
capture.assertNoErrors(); capture.assertNoErrors();
capture.assertHasFrame(OpCode.PING,1); 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.assertThat("PingFrame.payloadLength",pActual.getPayloadLength(),is(message.length()));
Assert.assertEquals("PingFrame.payload",message.length(),pActual.getPayloadLength()); Assert.assertEquals("PingFrame.payload",message.length(),pActual.getPayloadLength());
} }

View File

@ -26,6 +26,7 @@ import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.websocket.api.ProtocolException; import org.eclipse.jetty.websocket.api.ProtocolException;
import org.eclipse.jetty.websocket.api.WebSocketBehavior; import org.eclipse.jetty.websocket.api.WebSocketBehavior;
import org.eclipse.jetty.websocket.api.WebSocketPolicy; 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.ByteBufferAssert;
import org.eclipse.jetty.websocket.common.CloseInfo; import org.eclipse.jetty.websocket.common.CloseInfo;
import org.eclipse.jetty.websocket.common.Generator; import org.eclipse.jetty.websocket.common.Generator;
@ -80,7 +81,7 @@ public class TestABCase7_3
capture.assertNoErrors(); capture.assertNoErrors();
capture.assertHasFrame(OpCode.CLOSE,1); 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)); Assert.assertThat("CloseFrame.payloadLength",pActual.getPayloadLength(),is(0));
} }
@ -154,7 +155,7 @@ public class TestABCase7_3
capture.assertNoErrors(); capture.assertNoErrors();
capture.assertHasFrame(OpCode.CLOSE,1); 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)); Assert.assertThat("CloseFrame.payloadLength",pActual.getPayloadLength(),is(2));
} }
@ -212,7 +213,7 @@ public class TestABCase7_3
capture.assertNoErrors(); capture.assertNoErrors();
capture.assertHasFrame(OpCode.CLOSE,1); 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)); Assert.assertThat("CloseFrame.payloadLength",pActual.getPayloadLength(),is(messageBytes.length + 2));
} }
@ -282,7 +283,7 @@ public class TestABCase7_3
capture.assertNoErrors(); capture.assertNoErrors();
capture.assertHasFrame(OpCode.CLOSE,1); 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)); Assert.assertThat("CloseFrame.payloadLength",pActual.getPayloadLength(),is(125));
} }

View File

@ -20,6 +20,7 @@ package org.eclipse.jetty.websocket.common.events;
import org.eclipse.jetty.websocket.api.StatusCode; import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.WebSocketPolicy; 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.CloseInfo;
import org.eclipse.jetty.websocket.common.OpCode; import org.eclipse.jetty.websocket.common.OpCode;
import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.WebSocketFrame;
@ -39,7 +40,7 @@ public class EventDriverTest
@Rule @Rule
public TestName testname = new TestName(); 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); return WebSocketFrame.binary().setFin(fin).setPayload(content);
} }
@ -50,9 +51,8 @@ public class EventDriverTest
AdapterConnectCloseSocket socket = new AdapterConnectCloseSocket(); AdapterConnectCloseSocket socket = new AdapterConnectCloseSocket();
EventDriver driver = wrap(socket); EventDriver driver = wrap(socket);
LocalWebSocketSession conn = new LocalWebSocketSession(testname); LocalWebSocketSession conn = new LocalWebSocketSession(testname,driver);
driver.setSession(conn); conn.open();
driver.onConnect();
driver.incomingFrame(new CloseInfo(StatusCode.NORMAL).asFrame()); driver.incomingFrame(new CloseInfo(StatusCode.NORMAL).asFrame());
socket.capture.assertEventCount(2); socket.capture.assertEventCount(2);
@ -66,9 +66,8 @@ public class EventDriverTest
AnnotatedBinaryArraySocket socket = new AnnotatedBinaryArraySocket(); AnnotatedBinaryArraySocket socket = new AnnotatedBinaryArraySocket();
EventDriver driver = wrap(socket); EventDriver driver = wrap(socket);
LocalWebSocketSession conn = new LocalWebSocketSession(testname); LocalWebSocketSession conn = new LocalWebSocketSession(testname,driver);
driver.setSession(conn); conn.open();
driver.onConnect();
driver.incomingFrame(makeBinaryFrame("Hello World",true)); driver.incomingFrame(makeBinaryFrame("Hello World",true));
driver.incomingFrame(new CloseInfo(StatusCode.NORMAL).asFrame()); driver.incomingFrame(new CloseInfo(StatusCode.NORMAL).asFrame());
@ -84,9 +83,8 @@ public class EventDriverTest
AnnotatedFramesSocket socket = new AnnotatedFramesSocket(); AnnotatedFramesSocket socket = new AnnotatedFramesSocket();
EventDriver driver = wrap(socket); EventDriver driver = wrap(socket);
LocalWebSocketSession conn = new LocalWebSocketSession(testname); LocalWebSocketSession conn = new LocalWebSocketSession(testname,driver);
driver.setSession(conn); conn.open();
driver.onConnect();
driver.incomingFrame(new WebSocketFrame(OpCode.PING).setPayload("PING")); driver.incomingFrame(new WebSocketFrame(OpCode.PING).setPayload("PING"));
driver.incomingFrame(WebSocketFrame.text("Text Me")); driver.incomingFrame(WebSocketFrame.text("Text Me"));
driver.incomingFrame(WebSocketFrame.binary().setPayload("Hello Bin")); driver.incomingFrame(WebSocketFrame.binary().setPayload("Hello Bin"));
@ -107,9 +105,8 @@ public class EventDriverTest
AnnotatedBinaryStreamSocket socket = new AnnotatedBinaryStreamSocket(); AnnotatedBinaryStreamSocket socket = new AnnotatedBinaryStreamSocket();
EventDriver driver = wrap(socket); EventDriver driver = wrap(socket);
LocalWebSocketSession conn = new LocalWebSocketSession(testname); LocalWebSocketSession conn = new LocalWebSocketSession(testname,driver);
driver.setSession(conn); conn.open();
driver.onConnect();
driver.incomingFrame(makeBinaryFrame("Hello World",true)); driver.incomingFrame(makeBinaryFrame("Hello World",true));
driver.incomingFrame(new CloseInfo(StatusCode.NORMAL).asFrame()); driver.incomingFrame(new CloseInfo(StatusCode.NORMAL).asFrame());
@ -125,9 +122,8 @@ public class EventDriverTest
ListenerBasicSocket socket = new ListenerBasicSocket(); ListenerBasicSocket socket = new ListenerBasicSocket();
EventDriver driver = wrap(socket); EventDriver driver = wrap(socket);
LocalWebSocketSession conn = new LocalWebSocketSession(testname); LocalWebSocketSession conn = new LocalWebSocketSession(testname,driver);
driver.setSession(conn); conn.open();
driver.onConnect();
driver.incomingFrame(WebSocketFrame.text("Hello World")); driver.incomingFrame(WebSocketFrame.text("Hello World"));
driver.incomingFrame(new CloseInfo(StatusCode.NORMAL).asFrame()); driver.incomingFrame(new CloseInfo(StatusCode.NORMAL).asFrame());

View File

@ -26,13 +26,12 @@ import java.util.ArrayList;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import javax.net.websocket.extensions.FrameHandler;
import org.eclipse.jetty.io.MappedByteBufferPool; import org.eclipse.jetty.io.MappedByteBufferPool;
import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
import org.eclipse.jetty.websocket.api.extensions.Frame;
import org.eclipse.jetty.websocket.common.ByteBufferAssert; import org.eclipse.jetty.websocket.common.ByteBufferAssert;
import org.eclipse.jetty.websocket.common.IncomingFramesCapture; import org.eclipse.jetty.websocket.common.IncomingFramesCapture;
import org.eclipse.jetty.websocket.common.OpCode; import org.eclipse.jetty.websocket.common.OpCode;
@ -58,7 +57,7 @@ public class FragmentExtensionTest
ExtensionConfig config = ExtensionConfig.parse("fragment;maxLength=4"); ExtensionConfig config = ExtensionConfig.parse("fragment;maxLength=4");
ext.setConfig(config); ext.setConfig(config);
FrameHandler incomingHandler = ext.createIncomingFrameHandler(capture); ext.setNextIncomingFrames(capture);
// Quote // Quote
List<String> quote = new ArrayList<>(); List<String> quote = new ArrayList<>();
@ -69,8 +68,8 @@ public class FragmentExtensionTest
// Manually create frame and pass into extension // Manually create frame and pass into extension
for (String q : quote) for (String q : quote)
{ {
WebSocketFrame frame = WebSocketFrame.text(q); Frame frame = WebSocketFrame.text(q);
incomingHandler.handleFrame(frame); ext.incomingFrame(frame);
} }
int len = quote.size(); int len = quote.size();
@ -110,11 +109,11 @@ public class FragmentExtensionTest
ExtensionConfig config = ExtensionConfig.parse("fragment;maxLength=4"); ExtensionConfig config = ExtensionConfig.parse("fragment;maxLength=4");
ext.setConfig(config); ext.setConfig(config);
FrameHandler incomingHandler = ext.createIncomingFrameHandler(capture); ext.setNextIncomingFrames(capture);
String payload = "Are you there?"; String payload = "Are you there?";
WebSocketFrame ping = WebSocketFrame.ping().setPayload(payload); Frame ping = WebSocketFrame.ping().setPayload(payload);
incomingHandler.handleFrame(ping); ext.incomingFrame(ping);
capture.assertFrameCount(1); capture.assertFrameCount(1);
capture.assertHasFrame(OpCode.PING,1); capture.assertHasFrame(OpCode.PING,1);
@ -145,7 +144,7 @@ public class FragmentExtensionTest
ExtensionConfig config = ExtensionConfig.parse("fragment;maxLength=20"); ExtensionConfig config = ExtensionConfig.parse("fragment;maxLength=20");
ext.setConfig(config); ext.setConfig(config);
FrameHandler outgoingHandler = ext.createOutgoingFrameHandler(capture); ext.setNextOutgoingFrames(capture);
// Quote // Quote
List<String> quote = new ArrayList<>(); List<String> quote = new ArrayList<>();
@ -156,8 +155,8 @@ public class FragmentExtensionTest
// Write quote as separate frames // Write quote as separate frames
for (String section : quote) for (String section : quote)
{ {
WebSocketFrame frame = WebSocketFrame.text(section); Frame frame = WebSocketFrame.text(section);
outgoingHandler.handleFrame(frame); ext.outgoingFrame(frame);
} }
// Expected Frames // Expected Frames
@ -214,7 +213,7 @@ public class FragmentExtensionTest
ExtensionConfig config = ExtensionConfig.parse("fragment"); ExtensionConfig config = ExtensionConfig.parse("fragment");
ext.setConfig(config); ext.setConfig(config);
FrameHandler outgoingHandler = ext.createOutgoingFrameHandler(capture); ext.setNextOutgoingFrames(capture);
// Quote // Quote
List<String> quote = new ArrayList<>(); List<String> quote = new ArrayList<>();
@ -225,8 +224,8 @@ public class FragmentExtensionTest
// Write quote as separate frames // Write quote as separate frames
for (String section : quote) for (String section : quote)
{ {
WebSocketFrame frame = WebSocketFrame.text(section); Frame frame = WebSocketFrame.text(section);
outgoingHandler.handleFrame(frame); ext.outgoingFrame(frame);
} }
// Expected Frames // Expected Frames
@ -278,12 +277,12 @@ public class FragmentExtensionTest
ExtensionConfig config = ExtensionConfig.parse("fragment;maxLength=4"); ExtensionConfig config = ExtensionConfig.parse("fragment;maxLength=4");
ext.setConfig(config); ext.setConfig(config);
FrameHandler outgoingHandler = ext.createOutgoingFrameHandler(capture); ext.setNextOutgoingFrames(capture);
String payload = "Are you there?"; 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.assertFrameCount(1);
capture.assertHasFrame(OpCode.PING,1); capture.assertHasFrame(OpCode.PING,1);

View File

@ -23,11 +23,10 @@ import static org.hamcrest.Matchers.*;
import java.io.IOException; import java.io.IOException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import javax.net.websocket.extensions.FrameHandler;
import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.websocket.api.extensions.Extension; 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.ByteBufferAssert;
import org.eclipse.jetty.websocket.common.IncomingFramesCapture; import org.eclipse.jetty.websocket.common.IncomingFramesCapture;
import org.eclipse.jetty.websocket.common.OpCode; import org.eclipse.jetty.websocket.common.OpCode;
@ -48,10 +47,10 @@ public class IdentityExtensionTest
IncomingFramesCapture capture = new IncomingFramesCapture(); IncomingFramesCapture capture = new IncomingFramesCapture();
Extension ext = new IdentityExtension(); Extension ext = new IdentityExtension();
FrameHandler incomingHandler = ext.createIncomingFrameHandler(capture); ext.setNextIncomingFrames(capture);
WebSocketFrame frame = WebSocketFrame.text("hello"); Frame frame = WebSocketFrame.text("hello");
incomingHandler.handleFrame(frame); ext.incomingFrame(frame);
capture.assertFrameCount(1); capture.assertFrameCount(1);
capture.assertHasFrame(OpCode.TEXT,1); capture.assertHasFrame(OpCode.TEXT,1);
@ -77,10 +76,10 @@ public class IdentityExtensionTest
OutgoingFramesCapture capture = new OutgoingFramesCapture(); OutgoingFramesCapture capture = new OutgoingFramesCapture();
Extension ext = new IdentityExtension(); Extension ext = new IdentityExtension();
FrameHandler outgoingHandler = ext.createOutgoingFrameHandler(capture); ext.setNextOutgoingFrames(capture);
WebSocketFrame frame = WebSocketFrame.text("hello"); Frame frame = WebSocketFrame.text("hello");
outgoingHandler.handleFrame(frame); ext.outgoingFrame(frame);
capture.assertFrameCount(1); capture.assertFrameCount(1);
capture.assertHasFrame(OpCode.TEXT,1); capture.assertHasFrame(OpCode.TEXT,1);

View File

@ -26,14 +26,13 @@ import java.util.ArrayList;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import javax.net.websocket.extensions.FrameHandler;
import org.eclipse.jetty.io.MappedByteBufferPool; import org.eclipse.jetty.io.MappedByteBufferPool;
import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.TypeUtil; import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
import org.eclipse.jetty.websocket.api.extensions.Frame;
import org.eclipse.jetty.websocket.common.ByteBufferAssert; import org.eclipse.jetty.websocket.common.ByteBufferAssert;
import org.eclipse.jetty.websocket.common.IncomingFramesCapture; import org.eclipse.jetty.websocket.common.IncomingFramesCapture;
import org.eclipse.jetty.websocket.common.OpCode; import org.eclipse.jetty.websocket.common.OpCode;
@ -49,7 +48,7 @@ public class PerMessageCompressionExtensionTest
WebSocketPolicy policy = WebSocketPolicy.newServerPolicy(); WebSocketPolicy policy = WebSocketPolicy.newServerPolicy();
// Setup extension // Setup extension
PerMessageCompressionExtension ext = new PerMessageCompressionExtension(); MessageCompressionExtension ext = new MessageCompressionExtension();
ext.setBufferPool(new MappedByteBufferPool()); ext.setBufferPool(new MappedByteBufferPool());
ext.setPolicy(policy); ext.setPolicy(policy);
ExtensionConfig config = ExtensionConfig.parse("permessage-compress"); ExtensionConfig config = ExtensionConfig.parse("permessage-compress");
@ -59,7 +58,7 @@ public class PerMessageCompressionExtensionTest
IncomingFramesCapture capture = new IncomingFramesCapture(); IncomingFramesCapture capture = new IncomingFramesCapture();
// Wire up stack // Wire up stack
FrameHandler incomingHandler = ext.createIncomingFrameHandler(capture); ext.setNextIncomingFrames(capture);
// Receive frame // Receive frame
String hex = hexStr.replaceAll("\\s*0x",""); String hex = hexStr.replaceAll("\\s*0x","");
@ -69,7 +68,7 @@ public class PerMessageCompressionExtensionTest
frame.setPayload(net); frame.setPayload(net);
// Send frame into stack // Send frame into stack
incomingHandler.handleFrame(frame); ext.incomingFrame(frame);
// Verify captured frames. // Verify captured frames.
capture.assertFrameCount(1); capture.assertFrameCount(1);
@ -162,7 +161,7 @@ public class PerMessageCompressionExtensionTest
*/ */
@Test @Test
public void testIncomingPing() { public void testIncomingPing() {
PerMessageCompressionExtension ext = new PerMessageCompressionExtension(); MessageCompressionExtension ext = new MessageCompressionExtension();
ext.setBufferPool(new MappedByteBufferPool()); ext.setBufferPool(new MappedByteBufferPool());
ext.setPolicy(WebSocketPolicy.newServerPolicy()); ext.setPolicy(WebSocketPolicy.newServerPolicy());
ExtensionConfig config = ExtensionConfig.parse("permessage-compress"); ExtensionConfig config = ExtensionConfig.parse("permessage-compress");
@ -172,11 +171,11 @@ public class PerMessageCompressionExtensionTest
IncomingFramesCapture capture = new IncomingFramesCapture(); IncomingFramesCapture capture = new IncomingFramesCapture();
// Wire up stack // Wire up stack
FrameHandler incomingHandler = ext.createIncomingFrameHandler(capture); ext.setNextIncomingFrames(capture);
String payload = "Are you there?"; String payload = "Are you there?";
WebSocketFrame ping = WebSocketFrame.ping().setPayload(payload); Frame ping = WebSocketFrame.ping().setPayload(payload);
incomingHandler.handleFrame(ping); ext.incomingFrame(ping);
capture.assertFrameCount(1); capture.assertFrameCount(1);
capture.assertHasFrame(OpCode.PING,1); capture.assertHasFrame(OpCode.PING,1);
@ -199,7 +198,7 @@ public class PerMessageCompressionExtensionTest
@Test @Test
public void testIncomingUncompressedFrames() public void testIncomingUncompressedFrames()
{ {
PerMessageCompressionExtension ext = new PerMessageCompressionExtension(); MessageCompressionExtension ext = new MessageCompressionExtension();
ext.setBufferPool(new MappedByteBufferPool()); ext.setBufferPool(new MappedByteBufferPool());
ext.setPolicy(WebSocketPolicy.newServerPolicy()); ext.setPolicy(WebSocketPolicy.newServerPolicy());
ExtensionConfig config = ExtensionConfig.parse("permessage-compress"); ExtensionConfig config = ExtensionConfig.parse("permessage-compress");
@ -209,7 +208,8 @@ public class PerMessageCompressionExtensionTest
IncomingFramesCapture capture = new IncomingFramesCapture(); IncomingFramesCapture capture = new IncomingFramesCapture();
// Wire up stack // Wire up stack
FrameHandler incomingHandler = ext.createIncomingFrameHandler(capture); ext.setNextIncomingFrames(capture);
// Quote // Quote
List<String> quote = new ArrayList<>(); List<String> quote = new ArrayList<>();
quote.add("No amount of experimentation can ever prove me right;"); quote.add("No amount of experimentation can ever prove me right;");
@ -222,7 +222,7 @@ public class PerMessageCompressionExtensionTest
WebSocketFrame frame = new WebSocketFrame(OpCode.TEXT); WebSocketFrame frame = new WebSocketFrame(OpCode.TEXT);
frame.setPayload(q); frame.setPayload(q);
frame.setRsv1(false); // indication to extension that frame is not compressed (ie: a normal frame) 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(); int len = quote.size();
@ -254,7 +254,7 @@ public class PerMessageCompressionExtensionTest
@Test @Test
public void testOutgoingFrames() throws IOException public void testOutgoingFrames() throws IOException
{ {
PerMessageCompressionExtension ext = new PerMessageCompressionExtension(); MessageCompressionExtension ext = new MessageCompressionExtension();
ext.setBufferPool(new MappedByteBufferPool()); ext.setBufferPool(new MappedByteBufferPool());
ext.setPolicy(WebSocketPolicy.newServerPolicy()); ext.setPolicy(WebSocketPolicy.newServerPolicy());
ExtensionConfig config = ExtensionConfig.parse("permessage-compress"); ExtensionConfig config = ExtensionConfig.parse("permessage-compress");
@ -264,7 +264,7 @@ public class PerMessageCompressionExtensionTest
OutgoingFramesCapture capture = new OutgoingFramesCapture(); OutgoingFramesCapture capture = new OutgoingFramesCapture();
// Wire up stack // Wire up stack
FrameHandler outgoingHandler = ext.createOutgoingFrameHandler(capture); ext.setNextOutgoingFrames(capture);
// Quote // Quote
List<String> quote = new ArrayList<>(); List<String> quote = new ArrayList<>();
@ -275,8 +275,8 @@ public class PerMessageCompressionExtensionTest
// Write quote as separate frames // Write quote as separate frames
for (String section : quote) for (String section : quote)
{ {
WebSocketFrame frame = WebSocketFrame.text(section); Frame frame = WebSocketFrame.text(section);
outgoingHandler.handleFrame(frame); ext.outgoingFrame(frame);
} }
int len = quote.size(); int len = quote.size();
@ -314,7 +314,7 @@ public class PerMessageCompressionExtensionTest
@Test @Test
public void testOutgoingPing() throws IOException public void testOutgoingPing() throws IOException
{ {
PerMessageCompressionExtension ext = new PerMessageCompressionExtension(); MessageCompressionExtension ext = new MessageCompressionExtension();
ext.setBufferPool(new MappedByteBufferPool()); ext.setBufferPool(new MappedByteBufferPool());
ext.setPolicy(WebSocketPolicy.newServerPolicy()); ext.setPolicy(WebSocketPolicy.newServerPolicy());
ExtensionConfig config = ExtensionConfig.parse("permessage-compress"); ExtensionConfig config = ExtensionConfig.parse("permessage-compress");
@ -324,12 +324,12 @@ public class PerMessageCompressionExtensionTest
OutgoingFramesCapture capture = new OutgoingFramesCapture(); OutgoingFramesCapture capture = new OutgoingFramesCapture();
// Wire up stack // Wire up stack
FrameHandler outgoingHandler = ext.createOutgoingFrameHandler(capture); ext.setNextOutgoingFrames(capture);
String payload = "Are you there?"; 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.assertFrameCount(1);
capture.assertHasFrame(OpCode.PING,1); capture.assertHasFrame(OpCode.PING,1);

View File

@ -26,8 +26,6 @@ import java.util.Collections;
import java.util.zip.Deflater; import java.util.zip.Deflater;
import java.util.zip.Inflater; import java.util.zip.Inflater;
import javax.net.websocket.extensions.FrameHandler;
import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.MappedByteBufferPool; import org.eclipse.jetty.io.MappedByteBufferPool;
import org.eclipse.jetty.util.BufferUtil; 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.util.TypeUtil;
import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
import org.eclipse.jetty.websocket.api.extensions.Frame;
import org.eclipse.jetty.websocket.common.ByteBufferAssert; import org.eclipse.jetty.websocket.common.ByteBufferAssert;
import org.eclipse.jetty.websocket.common.Generator; import org.eclipse.jetty.websocket.common.Generator;
import org.eclipse.jetty.websocket.common.IncomingFramesCapture; 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.OutgoingNetworkBytesCapture;
import org.eclipse.jetty.websocket.common.Parser; import org.eclipse.jetty.websocket.common.Parser;
import org.eclipse.jetty.websocket.common.WebSocketFrame; 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.Assert;
import org.junit.Test; import org.junit.Test;
@ -53,7 +50,7 @@ public class WebkitDeflateFrameExtensionTest
{ {
WebSocketPolicy policy = WebSocketPolicy.newServerPolicy(); WebSocketPolicy policy = WebSocketPolicy.newServerPolicy();
WebkitDeflateFrameExtension ext = new WebkitDeflateFrameExtension(); FrameCompressionExtension ext = new FrameCompressionExtension();
ext.setBufferPool(new MappedByteBufferPool()); ext.setBufferPool(new MappedByteBufferPool());
ext.setPolicy(policy); ext.setPolicy(policy);
@ -64,12 +61,11 @@ public class WebkitDeflateFrameExtensionTest
IncomingFramesCapture capture = new IncomingFramesCapture(); IncomingFramesCapture capture = new IncomingFramesCapture();
// Wire up stack // Wire up stack
FrameHandler incomingHandler = ext.createIncomingFrameHandler(capture); ext.setNextIncomingFrames(capture);
IncomingFrames incoming = new IncomingFrameHandler(incomingHandler);
Parser parser = new Parser(policy); Parser parser = new Parser(policy);
parser.configureFromExtensions(Collections.singletonList(ext)); parser.configureFromExtensions(Collections.singletonList(ext));
parser.setIncomingFramesHandler(incoming); parser.setIncomingFramesHandler(ext);
parser.parse(ByteBuffer.wrap(raw)); parser.parse(ByteBuffer.wrap(raw));
@ -97,7 +93,7 @@ public class WebkitDeflateFrameExtensionTest
{ {
WebSocketPolicy policy = WebSocketPolicy.newServerPolicy(); WebSocketPolicy policy = WebSocketPolicy.newServerPolicy();
WebkitDeflateFrameExtension ext = new WebkitDeflateFrameExtension(); FrameCompressionExtension ext = new FrameCompressionExtension();
ext.setBufferPool(new MappedByteBufferPool()); ext.setBufferPool(new MappedByteBufferPool());
ext.setPolicy(policy); ext.setPolicy(policy);
@ -110,10 +106,10 @@ public class WebkitDeflateFrameExtensionTest
generator.configureFromExtensions(Collections.singletonList(ext)); generator.configureFromExtensions(Collections.singletonList(ext));
OutgoingNetworkBytesCapture capture = new OutgoingNetworkBytesCapture(generator); OutgoingNetworkBytesCapture capture = new OutgoingNetworkBytesCapture(generator);
FrameHandler outgoingHandler = ext.createOutgoingFrameHandler(capture); ext.setNextOutgoingFrames(capture);
WebSocketFrame frame = WebSocketFrame.text(text); Frame frame = WebSocketFrame.text(text);
outgoingHandler.handleFrame(frame); ext.outgoingFrame(frame);
capture.assertBytes(0,expectedHex); capture.assertBytes(0,expectedHex);
} }

View File

@ -23,8 +23,8 @@ import java.util.concurrent.Future;
import javax.net.websocket.SendResult; import javax.net.websocket.SendResult;
import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.api.extensions.Frame;
import org.eclipse.jetty.websocket.common.io.OutgoingFrames; import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames;
/** /**
* Helpful utility class to parse arbitrary mux events from a physical connection's 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 @Override
public Future<SendResult> outgoingFrame(WebSocketFrame frame) throws IOException public Future<SendResult> outgoingFrame(Frame frame) throws IOException
{ {
parser.parse(frame); parser.parse(frame);
return null; // FIXME: should return completed future. return null; // FIXME: should return completed future.

View File

@ -20,12 +20,12 @@ package org.eclipse.jetty.websocket.common.extensions.mux;
import java.io.IOException; 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.WebSocketFrame;
import org.eclipse.jetty.websocket.common.extensions.mux.MuxControlBlock; import org.eclipse.jetty.websocket.common.extensions.mux.MuxControlBlock;
import org.eclipse.jetty.websocket.common.extensions.mux.MuxGenerator; import org.eclipse.jetty.websocket.common.extensions.mux.MuxGenerator;
import org.eclipse.jetty.websocket.common.io.FramePipes; 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. * Helpful utility class to send arbitrary mux events into a physical connection's IncomingFrames.

View File

@ -32,6 +32,7 @@ import java.util.regex.Pattern;
import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.TypeUtil; import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.websocket.api.WebSocketPolicy; 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.IncomingFramesCapture;
import org.eclipse.jetty.websocket.common.OpCode; import org.eclipse.jetty.websocket.common.OpCode;
import org.eclipse.jetty.websocket.common.Parser; import org.eclipse.jetty.websocket.common.Parser;
@ -81,7 +82,7 @@ public class MuxParserRFCTest
MuxParser parser = new MuxParser(); MuxParser parser = new MuxParser();
MuxEventCapture capture = new MuxEventCapture(); MuxEventCapture capture = new MuxEventCapture();
parser.setEvents(capture); parser.setEvents(capture);
for(WebSocketFrame frame: frames) { for(Frame frame: frames) {
parser.parse(frame); parser.parse(frame);
} }
return capture; return capture;

View File

@ -18,9 +18,8 @@
package org.eclipse.jetty.websocket.common.extensions.mux.add; 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.extensions.mux.op.MuxAddChannelResponse;
import org.eclipse.jetty.websocket.common.io.WebSocketSession;
public class DummyMuxAddClient implements MuxAddClient public class DummyMuxAddClient implements MuxAddClient
{ {

View File

@ -25,14 +25,13 @@ import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.api.UpgradeRequest; import org.eclipse.jetty.websocket.api.UpgradeRequest;
import org.eclipse.jetty.websocket.api.UpgradeResponse; import org.eclipse.jetty.websocket.api.UpgradeResponse;
import org.eclipse.jetty.websocket.api.WebSocketPolicy; 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.EventDriver;
import org.eclipse.jetty.websocket.common.events.EventDriverFactory; 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.MuxChannel;
import org.eclipse.jetty.websocket.common.extensions.mux.MuxException; 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.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.extensions.mux.op.MuxAddChannelResponse;
import org.eclipse.jetty.websocket.common.io.WebSocketSession;
import examples.echo.AdapterEchoSocket; import examples.echo.AdapterEchoSocket;
@ -79,11 +78,12 @@ public class DummyMuxAddServer implements MuxAddServer
response.append("\r\n"); response.append("\r\n");
EventDriver websocket = this.eventDriverFactory.wrap(echo); 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.setSession(session);
channel.setSubProtocol("echo"); channel.setSubProtocol("echo");
channel.onOpen(); channel.onOpen();
session.onConnect(); session.open();
MuxAddChannelResponse addChannelResponse = new MuxAddChannelResponse(); MuxAddChannelResponse addChannelResponse = new MuxAddChannelResponse();
addChannelResponse.setChannelId(channel.getChannelId()); addChannelResponse.setChannelId(channel.getChannelId());

View File

@ -60,7 +60,7 @@ public class MuxerAddServerTest
muxer.setOutgoingFramesHandler(clientRead); muxer.setOutgoingFramesHandler(clientRead);
// Wire up physical connection to forward incoming frames to muxer // Wire up physical connection to forward incoming frames to muxer
physical.setIncoming(muxer); physical.setNextIncomingFrames(muxer);
// Client simulator // Client simulator
// Can inject mux encapsulated frames into physical connection as if from // Can inject mux encapsulated frames into physical connection as if from

View File

@ -30,10 +30,12 @@ import org.eclipse.jetty.websocket.api.SuspendToken;
import org.eclipse.jetty.websocket.api.WebSocketConnection; import org.eclipse.jetty.websocket.api.WebSocketConnection;
import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.WebSocketException;
import org.eclipse.jetty.websocket.api.WebSocketPolicy; 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.CloseInfo;
import org.eclipse.jetty.websocket.common.ConnectionState; import org.eclipse.jetty.websocket.common.ConnectionState;
import org.eclipse.jetty.websocket.common.LogicalConnection; 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; import org.junit.rules.TestName;
public class LocalWebSocketConnection implements WebSocketConnection, LogicalConnection, IncomingFrames public class LocalWebSocketConnection implements WebSocketConnection, LogicalConnection, IncomingFrames
@ -58,6 +60,16 @@ public class LocalWebSocketConnection implements WebSocketConnection, LogicalCon
this.id = testname.getMethodName(); this.id = testname.getMethodName();
} }
@Override
public void assertInputOpen() throws IOException
{
}
@Override
public void assertOutputOpen() throws IOException
{
}
@Override @Override
public void close() public void close()
{ {
@ -105,6 +117,12 @@ public class LocalWebSocketConnection implements WebSocketConnection, LogicalCon
return null; return null;
} }
@Override
public WebSocketSession getSession()
{
return null;
}
@Override @Override
public ConnectionState getState() public ConnectionState getState()
{ {
@ -124,7 +142,7 @@ public class LocalWebSocketConnection implements WebSocketConnection, LogicalCon
} }
@Override @Override
public void incomingFrame(WebSocketFrame frame) public void incomingFrame(Frame frame)
{ {
incoming.incomingFrame(frame); incoming.incomingFrame(frame);
} }
@ -163,18 +181,23 @@ public class LocalWebSocketConnection implements WebSocketConnection, LogicalCon
} }
@Override @Override
public Future<SendResult> outgoingFrame(WebSocketFrame frame) throws IOException public Future<SendResult> outgoingFrame(Frame frame) throws IOException
{ {
return null; return null;
} }
@Override @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; this.incoming = incoming;
} }
@ -184,6 +207,11 @@ public class LocalWebSocketConnection implements WebSocketConnection, LogicalCon
this.policy = policy; this.policy = policy;
} }
@Override
public void setSession(WebSocketSession session)
{
}
@Override @Override
public SuspendToken suspend() public SuspendToken suspend()
{ {

View File

@ -18,10 +18,11 @@
package org.eclipse.jetty.websocket.common.io; 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.OutgoingFramesCapture;
import org.eclipse.jetty.websocket.common.WebSocketSession;
import org.eclipse.jetty.websocket.common.events.EventDriver; import org.eclipse.jetty.websocket.common.events.EventDriver;
import org.eclipse.jetty.websocket.common.io.WebSocketSession;
import org.junit.rules.TestName; import org.junit.rules.TestName;
public class LocalWebSocketSession extends WebSocketSession public class LocalWebSocketSession extends WebSocketSession
@ -29,17 +30,12 @@ public class LocalWebSocketSession extends WebSocketSession
private String id; private String id;
private OutgoingFramesCapture outgoingCapture; private OutgoingFramesCapture outgoingCapture;
public LocalWebSocketSession(TestName testname)
{
this(testname,null);
outgoingCapture = new OutgoingFramesCapture();
setOutgoing(outgoingCapture);
}
public LocalWebSocketSession(TestName testname, EventDriver driver) 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(); this.id = testname.getMethodName();
outgoingCapture = new OutgoingFramesCapture();
setOutgoingHandler(outgoingCapture);
} }
public OutgoingFramesCapture getOutgoingCapture() public OutgoingFramesCapture getOutgoingCapture()

View File

@ -17,17 +17,7 @@
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.eclipse.jetty.websocket</groupId> <groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-api</artifactId> <artifactId>websocket-client</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>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -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;
/** import org.eclipse.jetty.websocket.client.JettyClientContainer;
* FrameHandler that just passes frames through with no modification.
*/ public class JettyServerContainer extends JettyClientContainer implements ServerContainer
public class PassthruFrameHandler extends FrameHandler
{ {
public PassthruFrameHandler(FrameHandler nextHandler) @Override
public void publishServer(Endpoint endpoint, ServerEndpointConfiguration ilc)
{ {
super(nextHandler); // TODO Auto-generated method stub
} }
} }

View File

@ -21,20 +21,19 @@ package org.eclipse.jetty.websocket.server;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import javax.servlet.http.Cookie; import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import org.eclipse.jetty.util.QuotedStringTokenizer;
import org.eclipse.jetty.websocket.api.UpgradeRequest; 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.extensions.ExtensionConfig;
import org.eclipse.jetty.websocket.api.util.QuoteUtil;
public class ServletWebSocketRequest extends UpgradeRequest public class ServletWebSocketRequest extends UpgradeRequest
{ {
private List<ExtensionConfig> extensions;
private Map<String, String> cookieMap; private Map<String, String> cookieMap;
private HttpServletRequest req; private HttpServletRequest req;
@ -43,12 +42,32 @@ public class ServletWebSocketRequest extends UpgradeRequest
super(request.getRequestURI()); super(request.getRequestURI());
this.req = request; this.req = request;
// Copy Request Line Details
setMethod(request.getMethod());
setHttpVersion(request.getProtocol());
// Copy Cookies
cookieMap = new HashMap<String, String>(); cookieMap = new HashMap<String, String>();
for (Cookie cookie : request.getCookies()) for (Cookie cookie : request.getCookies())
{ {
cookieMap.put(cookie.getName(),cookie.getValue()); 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"); Enumeration<String> protocols = request.getHeaders("Sec-WebSocket-Protocol");
List<String> subProtocols = new ArrayList<>(); List<String> subProtocols = new ArrayList<>();
String protocol = null; String protocol = null;
@ -62,14 +81,15 @@ public class ServletWebSocketRequest extends UpgradeRequest
} }
setSubProtocols(subProtocols); setSubProtocols(subProtocols);
extensions = new ArrayList<>(); // Parse Extension Configurations
Enumeration<String> e = request.getHeaders("Sec-WebSocket-Extensions"); Enumeration<String> e = request.getHeaders("Sec-WebSocket-Extensions");
while (e.hasMoreElements()) while (e.hasMoreElements())
{ {
QuotedStringTokenizer tok = new QuotedStringTokenizer(e.nextElement(),","); Iterator<String> extTokenIter = QuoteUtil.splitAt(e.nextElement(),",");
while (tok.hasMoreTokens()) while (extTokenIter.hasNext())
{ {
ExtensionConfig config = ExtensionConfig.parse(tok.nextToken()); String extToken = extTokenIter.next();
ExtensionConfig config = ExtensionConfig.parse(extToken);
addExtensions(config); addExtensions(config);
} }
} }
@ -98,21 +118,4 @@ public class ServletWebSocketRequest extends UpgradeRequest
{ {
this.req.setAttribute(name,o); 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());
}
}
} }

View File

@ -32,19 +32,24 @@ public class ServletWebSocketResponse extends UpgradeResponse
{ {
super(); super();
this.resp = resp; this.resp = resp;
// TODO: copy values from resp }
@Override
public void addHeader(String name, String value)
{
this.resp.addHeader(name,value);
} }
@Override @Override
public int getStatusCode() public int getStatusCode()
{ {
throw new UnsupportedOperationException("Server cannot get Status Code"); return this.resp.getStatus();
} }
@Override @Override
public String getStatusReason() public String getStatusReason()
{ {
throw new UnsupportedOperationException("Server cannot get Status Reason"); throw new UnsupportedOperationException("Server cannot get Status Reason Message");
} }
public boolean isCommitted() public boolean isCommitted()
@ -65,6 +70,12 @@ public class ServletWebSocketResponse extends UpgradeResponse
resp.sendError(HttpServletResponse.SC_FORBIDDEN,message); resp.sendError(HttpServletResponse.SC_FORBIDDEN,message);
} }
@Override
public void setHeader(String name, String value)
{
this.resp.setHeader(name,value);
}
public void setStatus(int status) public void setStatus(int status)
{ {
this.resp.setStatus(status); this.resp.setStatus(status);

View File

@ -20,15 +20,15 @@ package org.eclipse.jetty.websocket.server;
import org.eclipse.jetty.websocket.api.UpgradeRequest; import org.eclipse.jetty.websocket.api.UpgradeRequest;
import org.eclipse.jetty.websocket.api.UpgradeResponse; 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 public class UpgradeContext
{ {
private InternalConnection connection; private LogicalConnection connection;
private UpgradeRequest request; private UpgradeRequest request;
private UpgradeResponse response; private UpgradeResponse response;
public InternalConnection getConnection() public LogicalConnection getConnection()
{ {
return connection; return connection;
} }
@ -43,7 +43,7 @@ public class UpgradeContext
return response; return response;
} }
public void setConnection(InternalConnection connection) public void setConnection(LogicalConnection connection)
{ {
this.connection = connection; this.connection = connection;
} }

View File

@ -18,16 +18,15 @@
package org.eclipse.jetty.websocket.server; package org.eclipse.jetty.websocket.server;
import java.util.List; import java.net.InetSocketAddress;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.util.thread.Scheduler; import org.eclipse.jetty.util.thread.Scheduler;
import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.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.AbstractWebSocketConnection;
import org.eclipse.jetty.websocket.common.io.IncomingFrames;
public class WebSocketServerConnection extends AbstractWebSocketConnection public class WebSocketServerConnection extends AbstractWebSocketConnection
{ {
@ -43,10 +42,15 @@ public class WebSocketServerConnection extends AbstractWebSocketConnection
} }
@Override @Override
public void configureFromExtensions(List<Extension> extensions) public InetSocketAddress getLocalAddress()
{ {
getParser().configureFromExtensions(extensions); return getEndPoint().getLocalAddress();
getGenerator().configureFromExtensions(extensions); }
@Override
public InetSocketAddress getRemoteAddress()
{
return getEndPoint().getRemoteAddress();
} }
@Override @Override
@ -68,7 +72,7 @@ public class WebSocketServerConnection extends AbstractWebSocketConnection
} }
@Override @Override
public void setIncoming(IncomingFrames incoming) public void setNextIncomingFrames(IncomingFrames incoming)
{ {
getParser().setIncomingFramesHandler(incoming); getParser().setIncomingFramesHandler(incoming);
} }

View File

@ -46,16 +46,14 @@ import org.eclipse.jetty.websocket.api.UpgradeResponse;
import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.WebSocketException;
import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.api.annotations.WebSocket; 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.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.EventDriver;
import org.eclipse.jetty.websocket.common.events.EventDriverFactory; import org.eclipse.jetty.websocket.common.events.EventDriverFactory;
import org.eclipse.jetty.websocket.common.extensions.WebSocketExtensionRegistry; import org.eclipse.jetty.websocket.common.extensions.WebSocketExtensionFactory;
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.server.handshake.HandshakeRFC6455; 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 String supportedVersions;
private final WebSocketPolicy basePolicy; private final WebSocketPolicy basePolicy;
private final EventDriverFactory eventDriverFactory; private final EventDriverFactory eventDriverFactory;
private final WebSocketExtensionRegistry extensionRegistry; private final WebSocketExtensionFactory extensionFactory;
private WebSocketCreator creator; private WebSocketCreator creator;
private List<Class<?>> registeredSocketClasses; private List<Class<?>> registeredSocketClasses;
@ -108,7 +106,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
this.basePolicy = policy; this.basePolicy = policy;
this.eventDriverFactory = new EventDriverFactory(basePolicy); this.eventDriverFactory = new EventDriverFactory(basePolicy);
this.extensionRegistry = new WebSocketExtensionRegistry(basePolicy,bufferPool); this.extensionFactory = new WebSocketExtensionFactory(basePolicy,bufferPool);
this.creator = this; this.creator = this;
// Create supportedVersions // Create supportedVersions
@ -166,11 +164,18 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
return upgrade(sockreq,sockresp,driver); return upgrade(sockreq,sockresp,driver);
} }
protected void closeConnections() protected void closeAllConnections()
{ {
for (WebSocketSession session : sessions) for (WebSocketSession session : sessions)
{ {
session.close(); try
{
session.close();
}
catch (IOException e)
{
LOG.warn("CloseAllConnections Close failure",e);
}
} }
sessions.clear(); sessions.clear();
} }
@ -205,7 +210,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
@Override @Override
protected void doStop() throws Exception protected void doStop() throws Exception
{ {
closeConnections(); closeAllConnections();
super.doStop(); super.doStop();
} }
@ -214,9 +219,9 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
return this.creator; 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; 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) public boolean isUpgradeRequest(HttpServletRequest request, HttpServletResponse response)
{ {
String upgrade = request.getHeader("Upgrade"); String upgrade = request.getHeader("Upgrade");
@ -324,7 +309,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
return false; return false;
} }
boolean ret = sessions.offer(session); boolean ret = sessions.offer(session);
session.onConnect(); session.open();
return ret; return ret;
} }
@ -379,7 +364,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
// Create connection // Create connection
UpgradeContext context = getActiveUpgradeContext(); UpgradeContext context = getActiveUpgradeContext();
InternalConnection connection = context.getConnection(); LogicalConnection connection = context.getConnection();
if (connection == null) if (connection == null)
{ {
@ -394,46 +379,26 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
} }
// Initialize / Negotiate Extensions // 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); connection.setSession(session);
List<Extension> extensions = initExtensions(request.getExtensions());
request.setValidExtensions(extensions);
// Start with default routing. // Start with default routing.
IncomingFrames incoming = session; IncomingFrames incoming = session;
OutgoingFrames outgoing = connection; OutgoingFrames outgoing = connection;
// Connect extensions // if (extensions != null)
if (extensions != null) // {
{ // // FIXME connection.configureFromExtensions(extensions);
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;
// }
}
// configure session for outgoing flows // configure session for outgoing flows
session.setOutgoing(outgoing); session.setOutgoingHandler(outgoing);
// configure connection for incoming flows // configure connection for incoming flows
connection.setIncoming(incoming); connection.setNextIncomingFrames(incoming);
// Tell jetty about the new connection // Tell jetty about the new connection
request.setAttribute(HttpConnection.UPGRADE_CONNECTION_ATTRIBUTE,connection); request.setAttribute(HttpConnection.UPGRADE_CONNECTION_ATTRIBUTE,connection);

View File

@ -58,6 +58,7 @@ public class HandshakeRFC6455 implements WebSocketHandshake
if (request.getExtensions() != null) if (request.getExtensions() != null)
{ {
response.setExtensions(request.getExtensions());
for (ExtensionConfig ext : request.getExtensions()) for (ExtensionConfig ext : request.getExtensions())
{ {
response.addHeader("Sec-WebSocket-Extensions",ext.getParameterizedName()); response.addHeader("Sec-WebSocket-Extensions",ext.getParameterizedName());

View File

@ -41,10 +41,11 @@ import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.websocket.api.WebSocketBehavior; import org.eclipse.jetty.websocket.api.WebSocketBehavior;
import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.WebSocketException;
import org.eclipse.jetty.websocket.api.WebSocketPolicy; 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.Generator;
import org.eclipse.jetty.websocket.common.Parser; import org.eclipse.jetty.websocket.common.Parser;
import org.eclipse.jetty.websocket.common.WebSocketFrame; 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.eclipse.jetty.websocket.server.examples.MyEchoSocket;
import org.junit.AfterClass; import org.junit.AfterClass;
import org.junit.Assert; import org.junit.Assert;
@ -72,7 +73,7 @@ public class WebSocketLoadRFC6455Test
} }
@Override @Override
public void incomingFrame(WebSocketFrame frame) public void incomingFrame(Frame frame)
{ {
} }
}; };

View File

@ -28,6 +28,7 @@ import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.util.Utf8Appendable.NotUtf8Exception; import org.eclipse.jetty.util.Utf8Appendable.NotUtf8Exception;
import org.eclipse.jetty.util.Utf8StringBuilder; import org.eclipse.jetty.util.Utf8StringBuilder;
import org.eclipse.jetty.websocket.api.StatusCode; 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.CloseInfo;
import org.eclipse.jetty.websocket.common.Generator; import org.eclipse.jetty.websocket.common.Generator;
import org.eclipse.jetty.websocket.common.OpCode; import org.eclipse.jetty.websocket.common.OpCode;
@ -102,7 +103,7 @@ public class WebSocketServletRFCTest
// Read frame echo'd back (hopefully a single binary frame) // Read frame echo'd back (hopefully a single binary frame)
IncomingFramesCapture capture = client.readFrames(1,TimeUnit.MILLISECONDS,1000); 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; int expectedSize = buf1.length + buf2.length + buf3.length;
Assert.assertThat("BinaryFrame.payloadLength",binmsg.getPayloadLength(),is(expectedSize)); Assert.assertThat("BinaryFrame.payloadLength",binmsg.getPayloadLength(),is(expectedSize));
@ -225,7 +226,7 @@ public class WebSocketServletRFCTest
// Read frame (hopefully close frame) // Read frame (hopefully close frame)
IncomingFramesCapture capture = client.readFrames(1,TimeUnit.MILLISECONDS,500); 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); CloseInfo close = new CloseInfo(cf);
Assert.assertThat("Close Frame.status code",close.getStatusCode(),is(StatusCode.SERVER_ERROR)); Assert.assertThat("Close Frame.status code",close.getStatusCode(),is(StatusCode.SERVER_ERROR));
} }

View File

@ -32,6 +32,7 @@ import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.api.WebSocketPolicy; 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.CloseInfo;
import org.eclipse.jetty.websocket.common.Generator; import org.eclipse.jetty.websocket.common.Generator;
import org.eclipse.jetty.websocket.common.OpCode; import org.eclipse.jetty.websocket.common.OpCode;
@ -86,7 +87,7 @@ public class Fuzzer
public ByteBuffer asNetworkBuffer(List<WebSocketFrame> send) public ByteBuffer asNetworkBuffer(List<WebSocketFrame> send)
{ {
int buflen = 0; int buflen = 0;
for (WebSocketFrame f : send) for (Frame f : send)
{ {
buflen += f.getPayloadLength() + Generator.OVERHEAD; buflen += f.getPayloadLength() + Generator.OVERHEAD;
} }
@ -213,7 +214,7 @@ public class Fuzzer
if ((sendMode == SendMode.BULK) || (sendMode == SendMode.SLOW)) if ((sendMode == SendMode.BULK) || (sendMode == SendMode.SLOW))
{ {
int buflen = 0; int buflen = 0;
for (WebSocketFrame f : send) for (Frame f : send)
{ {
buflen += f.getPayloadLength() + Generator.OVERHEAD; buflen += f.getPayloadLength() + Generator.OVERHEAD;
} }

View File

@ -29,6 +29,17 @@ import org.junit.Test;
public class TestABCase4 extends AbstractABCase 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) * Send opcode 3 (reserved)
*/ */
@ -36,7 +47,7 @@ public class TestABCase4 extends AbstractABCase
public void testCase4_1_1() throws Exception public void testCase4_1_1() throws Exception
{ {
List<WebSocketFrame> send = new ArrayList<>(); 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<>(); List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame()); expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
@ -64,7 +75,7 @@ public class TestABCase4 extends AbstractABCase
byte payload[] = StringUtil.getUtf8Bytes("reserved payload"); byte payload[] = StringUtil.getUtf8Bytes("reserved payload");
List<WebSocketFrame> send = new ArrayList<>(); 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<>(); List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame()); expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
@ -91,7 +102,7 @@ public class TestABCase4 extends AbstractABCase
{ {
List<WebSocketFrame> send = new ArrayList<>(); List<WebSocketFrame> send = new ArrayList<>();
send.add(WebSocketFrame.text("hello")); 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()); send.add(WebSocketFrame.ping());
List<WebSocketFrame> expect = new ArrayList<>(); List<WebSocketFrame> expect = new ArrayList<>();
@ -120,7 +131,7 @@ public class TestABCase4 extends AbstractABCase
{ {
List<WebSocketFrame> send = new ArrayList<>(); List<WebSocketFrame> send = new ArrayList<>();
send.add(WebSocketFrame.text("hello")); 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()); send.add(WebSocketFrame.ping());
List<WebSocketFrame> expect = new ArrayList<>(); List<WebSocketFrame> expect = new ArrayList<>();
@ -149,7 +160,7 @@ public class TestABCase4 extends AbstractABCase
{ {
List<WebSocketFrame> send = new ArrayList<>(); List<WebSocketFrame> send = new ArrayList<>();
send.add(WebSocketFrame.text("hello")); 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()); send.add(WebSocketFrame.ping());
List<WebSocketFrame> expect = new ArrayList<>(); List<WebSocketFrame> expect = new ArrayList<>();
@ -177,7 +188,7 @@ public class TestABCase4 extends AbstractABCase
public void testCase4_2_1() throws Exception public void testCase4_2_1() throws Exception
{ {
List<WebSocketFrame> send = new ArrayList<>(); 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<>(); List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame()); expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
@ -203,7 +214,7 @@ public class TestABCase4 extends AbstractABCase
public void testCase4_2_2() throws Exception public void testCase4_2_2() throws Exception
{ {
List<WebSocketFrame> send = new ArrayList<>(); 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<>(); List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame()); expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
@ -230,7 +241,7 @@ public class TestABCase4 extends AbstractABCase
{ {
List<WebSocketFrame> send = new ArrayList<>(); List<WebSocketFrame> send = new ArrayList<>();
send.add(WebSocketFrame.text("hello")); 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()); send.add(WebSocketFrame.ping());
List<WebSocketFrame> expect = new ArrayList<>(); List<WebSocketFrame> expect = new ArrayList<>();
@ -259,7 +270,7 @@ public class TestABCase4 extends AbstractABCase
{ {
List<WebSocketFrame> send = new ArrayList<>(); List<WebSocketFrame> send = new ArrayList<>();
send.add(WebSocketFrame.text("hello")); 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()); send.add(WebSocketFrame.ping());
List<WebSocketFrame> expect = new ArrayList<>(); List<WebSocketFrame> expect = new ArrayList<>();
@ -288,7 +299,7 @@ public class TestABCase4 extends AbstractABCase
{ {
List<WebSocketFrame> send = new ArrayList<>(); List<WebSocketFrame> send = new ArrayList<>();
send.add(WebSocketFrame.text("hello")); 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()); send.add(WebSocketFrame.ping());
List<WebSocketFrame> expect = new ArrayList<>(); List<WebSocketFrame> expect = new ArrayList<>();

View File

@ -34,6 +34,8 @@ import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit; 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.WebSocketPolicy;
import org.eclipse.jetty.websocket.api.extensions.Extension; import org.eclipse.jetty.websocket.api.extensions.Extension;
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
import org.eclipse.jetty.websocket.api.extensions.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.CloseInfo;
import org.eclipse.jetty.websocket.common.Generator; import org.eclipse.jetty.websocket.common.Generator;
import org.eclipse.jetty.websocket.common.OpCode; import org.eclipse.jetty.websocket.common.OpCode;
import org.eclipse.jetty.websocket.common.Parser; import org.eclipse.jetty.websocket.common.Parser;
import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.WebSocketFrame;
import org.eclipse.jetty.websocket.common.extensions.WebSocketExtensionRegistry; import org.eclipse.jetty.websocket.common.extensions.WebSocketExtensionFactory;
import org.eclipse.jetty.websocket.common.io.IncomingFrames;
import org.eclipse.jetty.websocket.common.io.OutgoingFrames;
import org.eclipse.jetty.websocket.server.helper.FinishedFuture; import org.eclipse.jetty.websocket.server.helper.FinishedFuture;
import org.eclipse.jetty.websocket.server.helper.IncomingFramesCapture; import org.eclipse.jetty.websocket.server.helper.IncomingFramesCapture;
import org.junit.Assert; import org.junit.Assert;
@ -93,7 +96,7 @@ public class BlockheadClient implements IncomingFrames, OutgoingFrames
private final Generator generator; private final Generator generator;
private final Parser parser; private final Parser parser;
private final IncomingFramesCapture incomingFrames; private final IncomingFramesCapture incomingFrames;
private final WebSocketExtensionRegistry extensionRegistry; private final WebSocketExtensionFactory extensionRegistry;
private Socket socket; private Socket socket;
private OutputStream out; private OutputStream out;
@ -131,7 +134,7 @@ public class BlockheadClient implements IncomingFrames, OutgoingFrames
this.incomingFrames = new IncomingFramesCapture(); this.incomingFrames = new IncomingFramesCapture();
this.extensionRegistry = new WebSocketExtensionRegistry(policy,bufferPool); this.extensionRegistry = new WebSocketExtensionFactory(policy,bufferPool);
} }
public void addExtensions(String xtension) public void addExtensions(String xtension)
@ -220,26 +223,25 @@ public class BlockheadClient implements IncomingFrames, OutgoingFrames
generator.configureFromExtensions(extensions); generator.configureFromExtensions(extensions);
parser.configureFromExtensions(extensions); parser.configureFromExtensions(extensions);
// FIXME Iterator<Extension> extIter;
// Iterator<Extension> extIter; // Connect outgoings
// // Connect outgoings extIter = extensions.iterator();
// extIter = extensions.iterator(); while (extIter.hasNext())
// while (extIter.hasNext()) {
// { Extension ext = extIter.next();
// Extension ext = extIter.next(); ext.setNextOutgoingFrames(outgoing);
// ext.setNextOutgoingFrames(outgoing); outgoing = ext;
// outgoing = ext; }
// }
// // Connect incomings
// // Connect incomings Collections.reverse(extensions);
// Collections.reverse(extensions); extIter = extensions.iterator();
// extIter = extensions.iterator(); while (extIter.hasNext())
// while (extIter.hasNext()) {
// { Extension ext = extIter.next();
// Extension ext = extIter.next(); ext.setNextIncomingFrames(incoming);
// ext.setNextIncomingFrames(incoming); incoming = ext;
// incoming = ext; }
// }
} }
// configure parser // configure parser
@ -309,7 +311,7 @@ public class BlockheadClient implements IncomingFrames, OutgoingFrames
} }
@Override @Override
public void incomingFrame(WebSocketFrame frame) public void incomingFrame(Frame frame)
{ {
LOG.debug("incoming({})",frame); LOG.debug("incoming({})",frame);
int count = parseCount.incrementAndGet(); int count = parseCount.incrementAndGet();
@ -356,7 +358,7 @@ public class BlockheadClient implements IncomingFrames, OutgoingFrames
} }
@Override @Override
public Future<SendResult> outgoingFrame(WebSocketFrame frame) throws IOException public Future<SendResult> outgoingFrame(Frame frame) throws IOException
{ {
ByteBuffer buf = generator.generate(frame); ByteBuffer buf = generator.generate(frame);
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
@ -366,7 +368,7 @@ public class BlockheadClient implements IncomingFrames, OutgoingFrames
BufferUtil.writeTo(buf,out); BufferUtil.writeTo(buf,out);
out.flush(); out.flush();
if (frame.getOpCode() == OpCode.CLOSE) if (frame.getType().getOpCode() == OpCode.CLOSE)
{ {
disconnect(); disconnect();
} }

View File

@ -18,6 +18,7 @@
package org.eclipse.jetty.websocket.server.examples.echo; package org.eclipse.jetty.websocket.server.examples.echo;
import java.nio.ByteBuffer;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -45,8 +46,10 @@ public class EchoBroadcastPingSocket extends EchoBroadcastSocket
while (!latch.await(10,TimeUnit.SECONDS)) while (!latch.await(10,TimeUnit.SECONDS))
{ {
System.err.println("Ping"); System.err.println("Ping");
byte data[] = new byte[] ByteBuffer data = ByteBuffer.allocate(3);
{ (byte)1, (byte)2, (byte)3 }; data.put(new byte[]
{ (byte)1, (byte)2, (byte)3 });
data.flip();
conn.ping(data); conn.ping(data);
} }
} }

View File

@ -26,9 +26,10 @@ import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.api.WebSocketException; 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.OpCode;
import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.WebSocketFrame;
import org.eclipse.jetty.websocket.common.io.IncomingFrames;
import org.junit.Assert; import org.junit.Assert;
public class IncomingFramesCapture implements IncomingFrames public class IncomingFramesCapture implements IncomingFrames
@ -77,7 +78,7 @@ public class IncomingFramesCapture implements IncomingFrames
System.err.printf("Captured %d incoming frames%n",frames.size()); System.err.printf("Captured %d incoming frames%n",frames.size());
for (int i = 0; i < frames.size(); i++) 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("[%3d] %s%n",i,frame);
System.err.printf(" %s%n",BufferUtil.toDetailString(frame.getPayload())); System.err.printf(" %s%n",BufferUtil.toDetailString(frame.getPayload()));
} }
@ -127,7 +128,7 @@ public class IncomingFramesCapture implements IncomingFrames
} }
@Override @Override
public void incomingFrame(WebSocketFrame frame) public void incomingFrame(Frame frame)
{ {
WebSocketFrame copy = new WebSocketFrame(frame); WebSocketFrame copy = new WebSocketFrame(frame);
frames.add(copy); frames.add(copy);

View File

@ -28,9 +28,10 @@ import javax.net.websocket.SendResult;
import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Callback; 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.OpCode;
import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.WebSocketFrame;
import org.eclipse.jetty.websocket.common.io.OutgoingFrames;
import org.junit.Assert; import org.junit.Assert;
public class OutgoingFramesCapture implements OutgoingFrames public class OutgoingFramesCapture implements OutgoingFrames
@ -39,7 +40,7 @@ public class OutgoingFramesCapture implements OutgoingFrames
{ {
public C context; public C context;
public Callback<C> callback; public Callback<C> callback;
public WebSocketFrame frame; public Frame frame;
} }
private LinkedList<WebSocketFrame> frames = new LinkedList<>(); 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()); System.out.printf("Captured %d outgoing writes%n",frames.size());
for (int i = 0; i < frames.size(); i++) 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("[%3d] %s%n",i,frame);
System.out.printf(" %s%n",BufferUtil.toDetailString(frame.getPayload())); System.out.printf(" %s%n",BufferUtil.toDetailString(frame.getPayload()));
} }
@ -94,9 +95,10 @@ public class OutgoingFramesCapture implements OutgoingFrames
} }
@Override @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; return FinishedFuture.INSTANCE;
} }
} }

View File

@ -1,7 +1,7 @@
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
org.eclipse.jetty.LEVEL=WARN org.eclipse.jetty.LEVEL=WARN
# org.eclipse.jetty.websocket.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.LEVEL=DEBUG
# org.eclipse.jetty.websocket.io.WebSocketAsyncConnection.LEVEL=DEBUG # org.eclipse.jetty.websocket.io.WebSocketAsyncConnection.LEVEL=DEBUG
# org.eclipse.jetty.websocket.io.ControlFrameBytes.LEVEL=DEBUG # org.eclipse.jetty.websocket.io.ControlFrameBytes.LEVEL=DEBUG