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;
}
public void setHeader(String name, List<String> values)
{
headers.put(name,values);
}
public void setHeader(String name, String value)
{
List<String> values = new ArrayList<>();
values.add(value);
setHeader(name,values);
}
public void setHttpVersion(String httpVersion)
{
this.httpVersion = httpVersion;

View File

@ -39,7 +39,7 @@ public interface WebSocketConnection
* @see StatusCode
* @see #close(int, String)
*/
public void close();
public void close() throws IOException;
/**
* Send a websocket Close frame, with status code.
@ -52,7 +52,7 @@ public interface WebSocketConnection
* the (optional) reason. (can be null for no reason)
* @see StatusCode
*/
public void close(int statusCode, String reason);
public void close(int statusCode, String reason) throws IOException;
/**
* Get the address of the local side.
@ -102,8 +102,11 @@ public interface WebSocketConnection
* NIO style with callbacks, allows for knowledge of successful ping send.
* <p>
* Use @OnWebSocketFrame and monitor Pong frames
*
* @param the
* ping application data
*/
Future<SendResult> ping(byte payload[]) throws IOException;
void ping(ByteBuffer buf) throws IOException;
/**
* Suspend a the incoming read events on the connection.

View File

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

View File

@ -25,28 +25,8 @@ import javax.net.websocket.extensions.FrameHandler;
* <p>
* That work is performed by the two {@link FrameHandler} implementations for incoming and outgoing frame handling.
*/
public interface Extension extends javax.net.websocket.extensions.Extension
public interface Extension extends IncomingFrames, OutgoingFrames
{
/**
* Create an instance of a Incoming {@link FrameHandler} for working with frames destined for the End User WebSocket Object.
*
* @param the
* incoming {@link FrameHandler} to wrap
* @return the frame handler for incoming frames.
*/
@Override
public FrameHandler createIncomingFrameHandler(FrameHandler incoming);
/**
* Create an instance of a Outgoing {@link FrameHandler} for working with frames destined for the Network Bytes Layer.
*
* @param the
* outgoing {@link FrameHandler} to wrap
* @return the frame handler for outgoing frames.
*/
@Override
public FrameHandler createOutgoingFrameHandler(FrameHandler outgoing);
/**
* The active configuration for this extension.
*
@ -59,7 +39,6 @@ public interface Extension extends javax.net.websocket.extensions.Extension
* <p>
* Also known as the <a href="https://tools.ietf.org/html/rfc6455#section-9.1"><code>extension-token</code> per Section 9.1. Negotiating Extensions</a>.
*/
@Override
public String getName();
/**
@ -101,4 +80,20 @@ public interface Extension extends javax.net.websocket.extensions.Extension
* now free to validate the conformance to spec of TEXT Data Frames.
*/
public abstract boolean isTextDataDecoder();
/**
* Set the next {@link IncomingFrames} to call in the chain.
*
* @param nextIncoming
* the next incoming extension
*/
public void setNextIncomingFrames(IncomingFrames nextIncoming);
/**
* Set the next {@link OutgoingFrames} to call in the chain.
*
* @param nextOutgoing
* the next outgoing extension
*/
public void setNextOutgoingFrames(OutgoingFrames nextOutgoing);
}

View File

@ -24,26 +24,26 @@ import java.util.Map;
import java.util.ServiceLoader;
import java.util.Set;
public class ExtensionFactory implements Iterable<Extension>
public abstract class ExtensionFactory implements Iterable<Class<? extends Extension>>
{
private ServiceLoader<Extension> extensionLoader = ServiceLoader.load(Extension.class);
private Map<String, Extension> availableExtensions;
private Map<String, Class<? extends Extension>> availableExtensions;
public ExtensionFactory()
{
availableExtensions = new HashMap<>();
for (Extension ext : extensionLoader)
{
availableExtensions.put(ext.getName(),ext);
availableExtensions.put(ext.getName(),ext.getClass());
}
}
public Map<String, Extension> getAvailableExtensions()
public Map<String, Class<? extends Extension>> getAvailableExtensions()
{
return availableExtensions;
}
public Extension getExtension(String name)
public Class<? extends Extension> getExtension(String name)
{
return availableExtensions.get(name);
}
@ -59,12 +59,14 @@ public class ExtensionFactory implements Iterable<Extension>
}
@Override
public Iterator<Extension> iterator()
public Iterator<Class<? extends Extension>> iterator()
{
return availableExtensions.values().iterator();
}
public void register(String name, Extension extension)
public abstract Extension newInstance(ExtensionConfig config);
public void register(String name, Class<? extends Extension> extension)
{
availableExtensions.put(name,extension);
}

View File

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

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

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.util.concurrent.Future;
import javax.net.websocket.SendResult;
import org.eclipse.jetty.websocket.common.WebSocketFrame;
/**
* Interface for dealing with frames outgoing to the network (eventually)
*/
public interface OutgoingFrames
{
Future<SendResult> outgoingFrame(WebSocketFrame frame) throws IOException;
Future<SendResult> outgoingFrame(Frame frame) throws IOException;
}

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

View File

@ -95,13 +95,20 @@ public class ConnectionManager extends ContainerLifeCycle
clients.add(client);
}
private void closeConnections()
private void closeAllConnections()
{
for (DefaultWebSocketClient client : clients)
{
if (client.getConnection() != null)
{
client.getConnection().close();
try
{
client.getConnection().close();
}
catch (IOException e)
{
LOG.debug("During Close All Connections",e);
}
}
}
}
@ -138,7 +145,7 @@ public class ConnectionManager extends ContainerLifeCycle
@Override
protected void doStop() throws Exception
{
closeConnections();
closeAllConnections();
clients.clear();
super.doStop();
}

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.extensions.Extension;
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
import org.eclipse.jetty.websocket.api.extensions.IncomingFrames;
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
import org.eclipse.jetty.websocket.client.ClientUpgradeResponse;
import org.eclipse.jetty.websocket.client.internal.DefaultWebSocketClient;
import org.eclipse.jetty.websocket.common.AcceptHash;
import org.eclipse.jetty.websocket.common.WebSocketSession;
import org.eclipse.jetty.websocket.common.events.EventDriver;
import org.eclipse.jetty.websocket.common.io.IncomingFrames;
import org.eclipse.jetty.websocket.common.io.OutgoingFrames;
import org.eclipse.jetty.websocket.common.io.WebSocketSession;
/**
* This is the initial connection handling that exists immediately after physical connection is established to destination server.
@ -217,13 +216,17 @@ public class UpgradeConnection extends AbstractConnection
EventDriver websocket = client.getWebSocket();
WebSocketPolicy policy = client.getPolicy();
String acceptedSubProtocol = response.getAcceptedSubProtocol();
WebSocketSession session = new WebSocketSession(websocket,connection,policy,acceptedSubProtocol);
WebSocketSession session = new WebSocketSession(request.getRequestURI(),websocket,connection);
session.setPolicy(policy);
session.setNegotiatedSubprotocol(acceptedSubProtocol);
connection.setSession(session);
List<Extension> extensions = client.getFactory().initExtensions(response.getExtensions());
// Start with default routing.
IncomingFrames incoming = session;
OutgoingFrames outgoing = connection;
// OutgoingFrames outgoing = connection;
// Connect extensions
if (extensions != null)
@ -254,7 +257,7 @@ public class UpgradeConnection extends AbstractConnection
}
// configure session for outgoing flows
session.setOutgoing(outgoing);
// session.setOutgoing(outgoing);
// configure connection for incoming flows
connection.getParser().setIncomingFramesHandler(incoming);

View File

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

View File

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

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

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

View File

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

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.WebSocketPolicy;
import org.eclipse.jetty.websocket.api.extensions.Extension;
import org.eclipse.jetty.websocket.api.extensions.Frame;
/**
* Generating a frame in WebSocket land.
@ -103,7 +104,7 @@ public class Generator
this.validating = validating;
}
public void assertFrameValid(WebSocketFrame frame)
public void assertFrameValid(Frame frame)
{
if (!validating)
{
@ -131,7 +132,7 @@ public class Generator
throw new ProtocolException("RSV3 not allowed to be set");
}
if (frame.isControlFrame())
if (frame.getType().isControl())
{
/*
* RFC 6455 Section 5.5
@ -153,7 +154,7 @@ public class Generator
*
* close frame payload is specially formatted which is checked in CloseInfo
*/
if (frame.getOpCode() == OpCode.CLOSE)
if (frame.getType().getOpCode() == OpCode.CLOSE)
{
ByteBuffer payload = frame.getPayload();
@ -191,11 +192,25 @@ public class Generator
}
}
/**
* generate a byte buffer based on the frame being passed in
*
* bufferSize is determined by the length of the payload + 28 for frame overhead
*
* @param frame
* @return
*/
public ByteBuffer generate(Frame frame)
{
int bufferSize = frame.getPayloadLength() + OVERHEAD;
return generate(bufferSize,frame);
}
/**
* Generate, into a ByteBuffer, no more than bufferSize of contents from the frame. If the frame exceeds the bufferSize, then multiple calls to
* {@link #generate(int, WebSocketFrame)} are required to obtain each window of ByteBuffer to complete the frame.
*/
public ByteBuffer generate(int windowSize, WebSocketFrame frame)
public ByteBuffer generate(int windowSize, Frame frame)
{
if (windowSize < OVERHEAD)
{
@ -204,22 +219,7 @@ public class Generator
if (LOG.isDebugEnabled())
{
StringBuilder dbg = new StringBuilder();
dbg.append(behavior);
dbg.append(" Generate.Frame[");
dbg.append("opcode=").append(frame.getOpCode());
dbg.append(",fin=").append(frame.isFin());
dbg.append(",cont=").append(frame.isContinuation());
dbg.append(",rsv1=").append(frame.isRsv1());
dbg.append(",rsv2=").append(frame.isRsv2());
dbg.append(",rsv3=").append(frame.isRsv3());
dbg.append(",mask=").append(frame.isMasked());
dbg.append(",payloadLength=").append(frame.getPayloadLength());
dbg.append(",payloadStart=").append(frame.getPayloadStart());
dbg.append(",remaining=").append(frame.remaining());
dbg.append(",position=").append(frame.position());
dbg.append(']');
LOG.debug(dbg.toString());
LOG.debug("{} Generate: {}",behavior,frame);
}
/*
@ -260,6 +260,7 @@ public class Generator
b |= 0x10;
}
// NOTE: using .getOpCode() here, not .getType().getOpCode() for testing reasons
byte opcode = frame.getOpCode();
if (frame.isContinuation())
@ -366,20 +367,6 @@ public class Generator
return buffer;
}
/**
* generate a byte buffer based on the frame being passed in
*
* bufferSize is determined by the length of the payload + 28 for frame overhead
*
* @param frame
* @return
*/
public ByteBuffer generate(WebSocketFrame frame)
{
int bufferSize = frame.getPayloadLength() + OVERHEAD;
return generate(bufferSize,frame);
}
public boolean isRsv1InUse()
{
return rsv1InUse;

View File

@ -18,14 +18,33 @@
package org.eclipse.jetty.websocket.common;
import java.io.IOException;
import java.net.InetSocketAddress;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.SuspendToken;
import org.eclipse.jetty.websocket.common.io.OutgoingFrames;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.api.extensions.IncomingFrames;
import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames;
public interface LogicalConnection extends OutgoingFrames
public interface LogicalConnection extends OutgoingFrames, SuspendToken
{
/**
* Perform a quick check that the connection input is open.
*
* @throws IOException
* if the connection input is closed
*/
void assertInputOpen() throws IOException;
/**
* Perform a quick check that the connection output is open.
*
* @throws IOException
* if the connection output is closed
*/
void assertOutputOpen() throws IOException;
/**
* Send a websocket Close frame, without a status code or reason.
* <p>
@ -55,12 +74,36 @@ public interface LogicalConnection extends OutgoingFrames
void disconnect();
/**
* Get the remote Address in use for this connection.
* Get the local {@link InetSocketAddress} in use for this connection.
* <p>
* Note: Non-physical connections, like during the Mux extensions, or during unit testing can result in a InetSocketAddress on port 0 and/or on localhost.
*
* @return the remote address if available. (situations like mux extension and proxying makes this information unreliable)
* @return the local address.
*/
InetSocketAddress getLocalAddress();
/**
* The policy that the connection is running under.
* @return the policy for the connection
*/
WebSocketPolicy getPolicy();
/**
* Get the remote Address in use for this connection.
* <p>
* Note: Non-physical connections, like during the Mux extensions, or during unit testing can result in a InetSocketAddress on port 0 and/or on localhost.
*
* @return the remote address.
*/
InetSocketAddress getRemoteAddress();
/**
* Get the Session for this connection
*
* @return the Session for this connection
*/
WebSocketSession getSession();
/**
* Get the WebSocket connection State.
*
@ -106,6 +149,24 @@ public interface LogicalConnection extends OutgoingFrames
*/
void onCloseHandshake(boolean incoming, CloseInfo close);
/**
* Set where the connection should send the incoming frames to.
* <p>
* Often this is from the Parser to the start of the extension stack, and eventually on to the session.
*
* @param incoming
* the incoming frames handler
*/
void setNextIncomingFrames(IncomingFrames incoming);
/**
* Set the session associated with this connection
*
* @param session
* the session
*/
void setSession(WebSocketSession session);
/**
* Suspend a the incoming read events on the connection.
*

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

View File

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

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

View File

@ -18,20 +18,37 @@
package org.eclipse.jetty.websocket.common.extensions;
import java.util.Map;
import java.io.IOException;
import java.util.concurrent.Future;
import javax.net.websocket.SendResult;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.websocket.api.WebSocketConnection;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.api.WebSocketException;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.api.extensions.Extension;
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
import org.eclipse.jetty.websocket.api.extensions.Frame;
import org.eclipse.jetty.websocket.api.extensions.IncomingFrames;
import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames;
import org.eclipse.jetty.websocket.common.LogicalConnection;
public abstract class AbstractExtension implements Extension
{
private final Logger log;
private WebSocketPolicy policy;
private ByteBufferPool bufferPool;
private ExtensionConfig config;
private WebSocketConnection connection;
private LogicalConnection connection;
private OutgoingFrames nextOutgoing;
private IncomingFrames nextIncoming;
public AbstractExtension()
{
log = Log.getLogger(this.getClass());
}
public ByteBufferPool getBufferPool()
{
@ -44,7 +61,7 @@ public abstract class AbstractExtension implements Extension
return config;
}
public WebSocketConnection getConnection()
public LogicalConnection getConnection()
{
return connection;
}
@ -55,17 +72,17 @@ public abstract class AbstractExtension implements Extension
return config.getName();
}
@Override
public Map<String, String> getParameters()
{
return config.getParameters();
}
public WebSocketPolicy getPolicy()
{
return policy;
}
@Override
public void incomingError(WebSocketException e)
{
nextIncomingError(e);
}
/**
* Used to indicate that the extension makes use of the RSV1 bit of the base websocket framing.
* <p>
@ -122,6 +139,23 @@ public abstract class AbstractExtension implements Extension
return false;
}
protected void nextIncomingError(WebSocketException e)
{
this.nextIncoming.incomingError(e);
}
protected void nextIncomingFrame(Frame frame)
{
log.debug("nextIncomingFrame({})",frame);
this.nextIncoming.incomingFrame(frame);
}
protected Future<SendResult> nextOutgoingFrame(Frame frame) throws IOException
{
log.debug("nextOutgoingFrame({})",frame);
return this.nextOutgoing.outgoingFrame(frame);
}
public void setBufferPool(ByteBufferPool bufferPool)
{
this.bufferPool = bufferPool;
@ -132,11 +166,23 @@ public abstract class AbstractExtension implements Extension
this.config = config;
}
public void setConnection(WebSocketConnection connection)
public void setConnection(LogicalConnection connection)
{
this.connection = connection;
}
@Override
public void setNextIncomingFrames(IncomingFrames nextIncoming)
{
this.nextIncoming = nextIncoming;
}
@Override
public void setNextOutgoingFrames(OutgoingFrames nextOutgoing)
{
this.nextOutgoing = nextOutgoing;
}
public void setPolicy(WebSocketPolicy policy)
{
this.policy = policy;

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

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;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.concurrent.Future;
import javax.net.websocket.SendResult;
import org.eclipse.jetty.websocket.api.WebSocketException;
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
import org.eclipse.jetty.websocket.api.extensions.Frame;
import org.eclipse.jetty.websocket.common.OpCode;
import org.eclipse.jetty.websocket.common.WebSocketFrame;
import org.eclipse.jetty.websocket.common.extensions.AbstractExtension;
import org.eclipse.jetty.websocket.common.extensions.PassthruFrameHandler;
/**
* Fragment Extension
@ -31,16 +40,72 @@ public class FragmentExtension extends AbstractExtension
private int maxLength = -1;
@Override
public javax.net.websocket.extensions.FrameHandler createIncomingFrameHandler(javax.net.websocket.extensions.FrameHandler incoming)
public void incomingError(WebSocketException e)
{
// pass through handler
return new PassthruFrameHandler(incoming);
// Pass thru
nextIncomingError(e);
}
@Override
public javax.net.websocket.extensions.FrameHandler createOutgoingFrameHandler(javax.net.websocket.extensions.FrameHandler outgoing)
public void incomingFrame(Frame frame)
{
return new FragmentHandler(outgoing,maxLength);
// Pass thru
nextIncomingFrame(frame);
}
@Override
public Future<SendResult> outgoingFrame(Frame frame) throws IOException
{
if (frame.getType().isControl())
{
// Cannot fragment Control Frames
return nextOutgoingFrame(frame);
}
int length = frame.getPayloadLength();
byte opcode = frame.getType().getOpCode(); // original opcode
ByteBuffer payload = frame.getPayload().slice();
int originalLimit = payload.limit();
int currentPosition = payload.position();
if (maxLength <= 0)
{
// output original frame
return nextOutgoingFrame(frame);
}
boolean continuation = false;
// break apart payload based on maxLength rules
while (length > maxLength)
{
WebSocketFrame frag = new WebSocketFrame(frame);
frag.setOpCode(opcode);
frag.setFin(false); // always false here
frag.setContinuation(continuation);
payload.position(currentPosition);
payload.limit(Math.min(payload.position() + maxLength,originalLimit));
frag.setPayload(payload);
nextOutgoingFrame(frag);
length -= maxLength;
opcode = OpCode.CONTINUATION;
continuation = true;
currentPosition = payload.limit();
}
// write remaining
WebSocketFrame frag = new WebSocketFrame(frame);
frag.setOpCode(opcode);
frag.setFin(frame.isFin()); // use original fin
frag.setContinuation(continuation);
payload.position(currentPosition);
payload.limit(originalLimit);
frag.setPayload(payload);
return nextOutgoingFrame(frag);
}
@Override

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;
import java.io.IOException;
import java.util.concurrent.Future;
import javax.net.websocket.SendResult;
import org.eclipse.jetty.util.QuotedStringTokenizer;
import org.eclipse.jetty.websocket.api.WebSocketException;
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
import org.eclipse.jetty.websocket.api.extensions.Frame;
import org.eclipse.jetty.websocket.common.extensions.AbstractExtension;
import org.eclipse.jetty.websocket.common.extensions.PassthruFrameHandler;
public class IdentityExtension extends AbstractExtension
{
private String id;
@Override
public javax.net.websocket.extensions.FrameHandler createIncomingFrameHandler(javax.net.websocket.extensions.FrameHandler incoming)
public void incomingError(WebSocketException e)
{
return new PassthruFrameHandler(incoming);
// pass through
nextIncomingError(e);
}
@Override
public javax.net.websocket.extensions.FrameHandler createOutgoingFrameHandler(javax.net.websocket.extensions.FrameHandler outgoing)
public void incomingFrame(Frame frame)
{
return new PassthruFrameHandler(outgoing);
// pass through
nextIncomingFrame(frame);
}
@Override
public Future<SendResult> outgoingFrame(Frame frame) throws IOException
{
// pass through
return nextOutgoingFrame(frame);
}
@Override

View File

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

View File

@ -22,7 +22,6 @@ import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.URI;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicBoolean;
@ -35,20 +34,18 @@ import org.eclipse.jetty.websocket.api.SuspendToken;
import org.eclipse.jetty.websocket.api.WebSocketConnection;
import org.eclipse.jetty.websocket.api.WebSocketException;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.api.extensions.Extension;
import org.eclipse.jetty.websocket.api.extensions.Frame;
import org.eclipse.jetty.websocket.api.extensions.IncomingFrames;
import org.eclipse.jetty.websocket.common.CloseInfo;
import org.eclipse.jetty.websocket.common.ConnectionState;
import org.eclipse.jetty.websocket.common.LogicalConnection;
import org.eclipse.jetty.websocket.common.WebSocketFrame;
import org.eclipse.jetty.websocket.common.extensions.AbstractExtension;
import org.eclipse.jetty.websocket.common.io.IncomingFrames;
import org.eclipse.jetty.websocket.common.io.InternalConnection;
import org.eclipse.jetty.websocket.common.io.OutgoingFrames;
import org.eclipse.jetty.websocket.common.io.WebSocketSession;
import org.eclipse.jetty.websocket.common.WebSocketSession;
/**
* MuxChannel, acts as WebSocketConnection for specific sub-channel.
*/
public class MuxChannel implements WebSocketConnection, InternalConnection, IncomingFrames, OutgoingFrames, SuspendToken
public class MuxChannel implements WebSocketConnection, LogicalConnection, IncomingFrames, SuspendToken
{
private static final Logger LOG = Log.getLogger(MuxChannel.class);
@ -76,6 +73,20 @@ public class MuxChannel implements WebSocketConnection, InternalConnection, Inco
this.outputClosed = new AtomicBoolean(false);
}
@Override
public void assertInputOpen() throws IOException
{
// TODO Auto-generated method stub
}
@Override
public void assertOutputOpen() throws IOException
{
// TODO Auto-generated method stub
}
@Override
public void close()
{
@ -97,12 +108,6 @@ public class MuxChannel implements WebSocketConnection, InternalConnection, Inco
}
}
@Override
public void configureFromExtensions(List<Extension> extensions)
{
/* ignore */
}
@Override
public void disconnect()
{
@ -141,6 +146,7 @@ public class MuxChannel implements WebSocketConnection, InternalConnection, Inco
return null;
}
@Override
public WebSocketSession getSession()
{
return session;
@ -171,7 +177,7 @@ public class MuxChannel implements WebSocketConnection, InternalConnection, Inco
* Incoming frames from Muxer
*/
@Override
public void incomingFrame(WebSocketFrame frame)
public void incomingFrame(Frame frame)
{
incoming.incomingFrame(frame);
}
@ -250,7 +256,7 @@ public class MuxChannel implements WebSocketConnection, InternalConnection, Inco
* Frames destined for the Muxer
*/
@Override
public Future<SendResult> outgoingFrame(WebSocketFrame frame) throws IOException
public Future<SendResult> outgoingFrame(Frame frame) throws IOException
{
return muxer.output(channelId,frame);
}
@ -259,9 +265,9 @@ public class MuxChannel implements WebSocketConnection, InternalConnection, Inco
* Ping frame destined for the Muxer
*/
@Override
public Future<SendResult> ping(byte[] payload) throws IOException
public void ping(ByteBuffer buf) throws IOException
{
return outgoingFrame(WebSocketFrame.ping().setPayload(payload));
outgoingFrame(WebSocketFrame.ping().setPayload(buf));
}
@Override
@ -274,7 +280,7 @@ public class MuxChannel implements WebSocketConnection, InternalConnection, Inco
}
@Override
public void setIncoming(IncomingFrames incoming)
public void setNextIncomingFrames(IncomingFrames incoming)
{
this.incoming = incoming;
}
@ -283,7 +289,7 @@ public class MuxChannel implements WebSocketConnection, InternalConnection, Inco
public void setSession(WebSocketSession session)
{
this.session = session;
session.setOutgoing(this);
// session.setOutgoing(this);
}
public void setSubProtocol(String subProtocol)
@ -299,40 +305,6 @@ public class MuxChannel implements WebSocketConnection, InternalConnection, Inco
return this;
}
public void wireUpExtensions(List<AbstractExtension> extensions)
{
// Start with default routing.
incoming = session;
OutgoingFrames outgoing = this;
if (extensions != null)
{
// FIXME
// Iterator<AbstractExtension> extIter;
// // Connect outgoings
// extIter = extensions.iterator();
// while (extIter.hasNext())
// {
// AbstractExtension ext = extIter.next();
// ext.setNextOutgoingFrames(outgoing);
// outgoing = ext;
// }
//
// // Connect incomings
// Collections.reverse(extensions);
// extIter = extensions.iterator();
// while (extIter.hasNext())
// {
// AbstractExtension ext = extIter.next();
// ext.setNextIncomingFrames(incoming);
// incoming = ext;
// }
}
// set outgoing
this.session.setOutgoing(outgoing);
}
/**
* Generate a binary message, destined for Muxer
*/

View File

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

View File

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

View File

@ -32,10 +32,14 @@ import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.UpgradeRequest;
import org.eclipse.jetty.websocket.api.UpgradeResponse;
import org.eclipse.jetty.websocket.api.WebSocketBehavior;
import org.eclipse.jetty.websocket.api.WebSocketConnection;
import org.eclipse.jetty.websocket.api.WebSocketException;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.api.extensions.Frame;
import org.eclipse.jetty.websocket.api.extensions.IncomingFrames;
import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames;
import org.eclipse.jetty.websocket.common.LogicalConnection;
import org.eclipse.jetty.websocket.common.WebSocketFrame;
import org.eclipse.jetty.websocket.common.extensions.mux.add.MuxAddClient;
import org.eclipse.jetty.websocket.common.extensions.mux.add.MuxAddServer;
@ -44,8 +48,6 @@ import org.eclipse.jetty.websocket.common.extensions.mux.op.MuxAddChannelRespons
import org.eclipse.jetty.websocket.common.extensions.mux.op.MuxDropChannel;
import org.eclipse.jetty.websocket.common.extensions.mux.op.MuxFlowControl;
import org.eclipse.jetty.websocket.common.extensions.mux.op.MuxNewChannelSlot;
import org.eclipse.jetty.websocket.common.io.IncomingFrames;
import org.eclipse.jetty.websocket.common.io.OutgoingFrames;
/**
* Muxer responsible for managing sub-channels.
@ -67,7 +69,7 @@ public class Muxer implements IncomingFrames, MuxParser.Listener
private Map<Long, MuxChannel> channels = new HashMap<Long, MuxChannel>();
private final WebSocketPolicy policy;
private final WebSocketConnection physicalConnection;
private final LogicalConnection physicalConnection;
private InetSocketAddress remoteAddress;
/** Parsing frames destined for sub-channels */
private MuxParser parser;
@ -76,11 +78,11 @@ public class Muxer implements IncomingFrames, MuxParser.Listener
private MuxAddServer addServer;
private MuxAddClient addClient;
/** The original request headers, used for delta encoded AddChannelRequest blocks */
private List<String> physicalRequestHeaders;
private UpgradeRequest physicalRequestHeaders;
/** The original response headers, used for delta encoded AddChannelResponse blocks */
private List<String> physicalResponseHeaders;
private UpgradeResponse physicalResponseHeaders;
public Muxer(final WebSocketConnection connection)
public Muxer(final LogicalConnection connection)
{
this.physicalConnection = connection;
this.policy = connection.getPolicy().clonePolicy();
@ -152,7 +154,7 @@ public class Muxer implements IncomingFrames, MuxParser.Listener
* Incoming mux encapsulated frames.
*/
@Override
public void incomingFrame(WebSocketFrame frame)
public void incomingFrame(Frame frame)
{
parser.parse(frame);
}
@ -383,7 +385,7 @@ public class Muxer implements IncomingFrames, MuxParser.Listener
/**
* Outgoing frame, without mux encapsulated payload.
*/
public Future<SendResult> output(long channelId, WebSocketFrame frame) throws IOException
public Future<SendResult> output(long channelId, Frame frame) throws IOException
{
if (LOG.isDebugEnabled())
{

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

View File

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

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

View File

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

View File

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

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

View File

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

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 org.eclipse.jetty.websocket.common.WebSocketFrame;
import org.eclipse.jetty.websocket.api.extensions.Frame;
public class DeMaskProcessor implements PayloadProcessor
{
@ -45,7 +45,7 @@ public class DeMaskProcessor implements PayloadProcessor
}
@Override
public void reset(WebSocketFrame frame)
public void reset(Frame frame)
{
this.isMasked = frame.isMasked();
if (isMasked)

View File

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

View File

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

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

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;
public interface InternalConnection extends LogicalConnection
public class MessageOutputStream extends OutputStream
{
// TODO: find way to remove
void configureFromExtensions(List<Extension> extensions);
private final LogicalConnection connection;
private final OutgoingFrames outgoing;
void setIncoming(IncomingFrames incoming);
public MessageOutputStream(LogicalConnection connection, OutgoingFrames outgoing)
{
this.connection = connection;
this.outgoing = outgoing;
}
void setSession(WebSocketSession session);
public boolean isClosed()
{
// TODO Auto-generated method stub
return false;
}
@Override
public void write(int b) throws IOException
{
// TODO Auto-generated method stub
}
}

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -20,12 +20,12 @@ package org.eclipse.jetty.websocket.common.extensions.mux;
import java.io.IOException;
import org.eclipse.jetty.websocket.api.extensions.IncomingFrames;
import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames;
import org.eclipse.jetty.websocket.common.WebSocketFrame;
import org.eclipse.jetty.websocket.common.extensions.mux.MuxControlBlock;
import org.eclipse.jetty.websocket.common.extensions.mux.MuxGenerator;
import org.eclipse.jetty.websocket.common.io.FramePipes;
import org.eclipse.jetty.websocket.common.io.IncomingFrames;
import org.eclipse.jetty.websocket.common.io.OutgoingFrames;
/**
* Helpful utility class to send arbitrary mux events into a physical connection's IncomingFrames.

View File

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

View File

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

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

View File

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

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

View File

@ -18,10 +18,11 @@
package org.eclipse.jetty.websocket.common.io;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import java.net.URI;
import org.eclipse.jetty.websocket.common.OutgoingFramesCapture;
import org.eclipse.jetty.websocket.common.WebSocketSession;
import org.eclipse.jetty.websocket.common.events.EventDriver;
import org.eclipse.jetty.websocket.common.io.WebSocketSession;
import org.junit.rules.TestName;
public class LocalWebSocketSession extends WebSocketSession
@ -29,17 +30,12 @@ public class LocalWebSocketSession extends WebSocketSession
private String id;
private OutgoingFramesCapture outgoingCapture;
public LocalWebSocketSession(TestName testname)
{
this(testname,null);
outgoingCapture = new OutgoingFramesCapture();
setOutgoing(outgoingCapture);
}
public LocalWebSocketSession(TestName testname, EventDriver driver)
{
super(driver,new LocalWebSocketConnection(testname),WebSocketPolicy.newServerPolicy(),"testing");
super(URI.create("ws://localhost/LocalWebSocketSesssion/" + testname.getMethodName()),driver,new LocalWebSocketConnection(testname));
this.id = testname.getMethodName();
outgoingCapture = new OutgoingFramesCapture();
setOutgoingHandler(outgoingCapture);
}
public OutgoingFramesCapture getOutgoingCapture()

View File

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

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

View File

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

View File

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

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

View File

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

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.WebSocketPolicy;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
import org.eclipse.jetty.websocket.api.extensions.Extension;
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
import org.eclipse.jetty.websocket.api.extensions.ExtensionFactory;
import org.eclipse.jetty.websocket.api.extensions.IncomingFrames;
import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames;
import org.eclipse.jetty.websocket.common.LogicalConnection;
import org.eclipse.jetty.websocket.common.WebSocketSession;
import org.eclipse.jetty.websocket.common.events.EventDriver;
import org.eclipse.jetty.websocket.common.events.EventDriverFactory;
import org.eclipse.jetty.websocket.common.extensions.WebSocketExtensionRegistry;
import org.eclipse.jetty.websocket.common.io.IncomingFrames;
import org.eclipse.jetty.websocket.common.io.InternalConnection;
import org.eclipse.jetty.websocket.common.io.OutgoingFrames;
import org.eclipse.jetty.websocket.common.io.WebSocketSession;
import org.eclipse.jetty.websocket.common.extensions.WebSocketExtensionFactory;
import org.eclipse.jetty.websocket.server.handshake.HandshakeRFC6455;
/**
@ -90,7 +88,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
private final String supportedVersions;
private final WebSocketPolicy basePolicy;
private final EventDriverFactory eventDriverFactory;
private final WebSocketExtensionRegistry extensionRegistry;
private final WebSocketExtensionFactory extensionFactory;
private WebSocketCreator creator;
private List<Class<?>> registeredSocketClasses;
@ -108,7 +106,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
this.basePolicy = policy;
this.eventDriverFactory = new EventDriverFactory(basePolicy);
this.extensionRegistry = new WebSocketExtensionRegistry(basePolicy,bufferPool);
this.extensionFactory = new WebSocketExtensionFactory(basePolicy,bufferPool);
this.creator = this;
// Create supportedVersions
@ -166,11 +164,18 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
return upgrade(sockreq,sockresp,driver);
}
protected void closeConnections()
protected void closeAllConnections()
{
for (WebSocketSession session : sessions)
{
session.close();
try
{
session.close();
}
catch (IOException e)
{
LOG.warn("CloseAllConnections Close failure",e);
}
}
sessions.clear();
}
@ -205,7 +210,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
@Override
protected void doStop() throws Exception
{
closeConnections();
closeAllConnections();
super.doStop();
}
@ -214,9 +219,9 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
return this.creator;
}
public ExtensionFactory getExtensionRegistry()
public ExtensionFactory getExtensionFactory()
{
return extensionRegistry;
return extensionFactory;
}
/**
@ -231,26 +236,6 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
return basePolicy;
}
public List<Extension> initExtensions(List<ExtensionConfig> requested)
{
List<Extension> extensions = new ArrayList<Extension>();
for (ExtensionConfig cfg : requested)
{
Extension extension = extensionRegistry.newInstance(cfg);
if (extension == null)
{
continue;
}
LOG.debug("added {}",extension);
extensions.add(extension);
}
LOG.debug("extensions={}",extensions);
return extensions;
}
public boolean isUpgradeRequest(HttpServletRequest request, HttpServletResponse response)
{
String upgrade = request.getHeader("Upgrade");
@ -324,7 +309,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
return false;
}
boolean ret = sessions.offer(session);
session.onConnect();
session.open();
return ret;
}
@ -379,7 +364,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
// Create connection
UpgradeContext context = getActiveUpgradeContext();
InternalConnection connection = context.getConnection();
LogicalConnection connection = context.getConnection();
if (connection == null)
{
@ -394,46 +379,26 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
}
// Initialize / Negotiate Extensions
WebSocketSession session = new WebSocketSession(driver,connection,getPolicy(),response.getAcceptedSubProtocol());
WebSocketSession session = new WebSocketSession(request.getRequestURI(),driver,connection);
session.setPolicy(getPolicy().clonePolicy());
session.setNegotiatedSubprotocol(response.getAcceptedSubProtocol());
session.setNegotiatedExtensionConfigs(request.getExtensions());
session.setExtensionFactory(extensionFactory);
connection.setSession(session);
List<Extension> extensions = initExtensions(request.getExtensions());
request.setValidExtensions(extensions);
// Start with default routing.
IncomingFrames incoming = session;
OutgoingFrames outgoing = connection;
// Connect extensions
if (extensions != null)
{
connection.configureFromExtensions(extensions);
// FIXME:
// Iterator<Extension> extIter;
// // Connect outgoings
// extIter = extensions.iterator();
// while (extIter.hasNext())
// {
// Extension ext = extIter.next();
// ext.setNextOutgoingFrames(outgoing);
// outgoing = ext;
// }
//
// // Connect incomings
// Collections.reverse(extensions);
// extIter = extensions.iterator();
// while (extIter.hasNext())
// {
// Extension ext = extIter.next();
// ext.setNextIncomingFrames(incoming);
// incoming = ext;
// }
}
// if (extensions != null)
// {
// // FIXME connection.configureFromExtensions(extensions);
// }
// configure session for outgoing flows
session.setOutgoing(outgoing);
session.setOutgoingHandler(outgoing);
// configure connection for incoming flows
connection.setIncoming(incoming);
connection.setNextIncomingFrames(incoming);
// Tell jetty about the new connection
request.setAttribute(HttpConnection.UPGRADE_CONNECTION_ATTRIBUTE,connection);

View File

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

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

View File

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

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

View File

@ -29,6 +29,17 @@ import org.junit.Test;
public class TestABCase4 extends AbstractABCase
{
// Allow Fuzzer / Generator to create bad frames for testing frame validation
private static class BadFrame extends WebSocketFrame
{
public BadFrame(byte opcode)
{
super();
super.opcode = opcode;
// NOTE: Not setting Frame.Type intentionally
}
}
/**
* Send opcode 3 (reserved)
*/
@ -36,7 +47,7 @@ public class TestABCase4 extends AbstractABCase
public void testCase4_1_1() throws Exception
{
List<WebSocketFrame> send = new ArrayList<>();
send.add(new WebSocketFrame((byte)3)); // intentionally bad
send.add(new BadFrame((byte)3)); // intentionally bad
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
@ -64,7 +75,7 @@ public class TestABCase4 extends AbstractABCase
byte payload[] = StringUtil.getUtf8Bytes("reserved payload");
List<WebSocketFrame> send = new ArrayList<>();
send.add(new WebSocketFrame((byte)4).setPayload(payload)); // intentionally bad
send.add(new BadFrame((byte)4).setPayload(payload)); // intentionally bad
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
@ -91,7 +102,7 @@ public class TestABCase4 extends AbstractABCase
{
List<WebSocketFrame> send = new ArrayList<>();
send.add(WebSocketFrame.text("hello"));
send.add(new WebSocketFrame((byte)5)); // intentionally bad
send.add(new BadFrame((byte)5)); // intentionally bad
send.add(WebSocketFrame.ping());
List<WebSocketFrame> expect = new ArrayList<>();
@ -120,7 +131,7 @@ public class TestABCase4 extends AbstractABCase
{
List<WebSocketFrame> send = new ArrayList<>();
send.add(WebSocketFrame.text("hello"));
send.add(new WebSocketFrame((byte)6).setPayload("bad")); // intentionally bad
send.add(new BadFrame((byte)6).setPayload("bad")); // intentionally bad
send.add(WebSocketFrame.ping());
List<WebSocketFrame> expect = new ArrayList<>();
@ -149,7 +160,7 @@ public class TestABCase4 extends AbstractABCase
{
List<WebSocketFrame> send = new ArrayList<>();
send.add(WebSocketFrame.text("hello"));
send.add(new WebSocketFrame((byte)7).setPayload("bad")); // intentionally bad
send.add(new BadFrame((byte)7).setPayload("bad")); // intentionally bad
send.add(WebSocketFrame.ping());
List<WebSocketFrame> expect = new ArrayList<>();
@ -177,7 +188,7 @@ public class TestABCase4 extends AbstractABCase
public void testCase4_2_1() throws Exception
{
List<WebSocketFrame> send = new ArrayList<>();
send.add(new WebSocketFrame((byte)11)); // intentionally bad
send.add(new BadFrame((byte)11)); // intentionally bad
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
@ -203,7 +214,7 @@ public class TestABCase4 extends AbstractABCase
public void testCase4_2_2() throws Exception
{
List<WebSocketFrame> send = new ArrayList<>();
send.add(new WebSocketFrame((byte)12).setPayload("bad")); // intentionally bad
send.add(new BadFrame((byte)12).setPayload("bad")); // intentionally bad
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
@ -230,7 +241,7 @@ public class TestABCase4 extends AbstractABCase
{
List<WebSocketFrame> send = new ArrayList<>();
send.add(WebSocketFrame.text("hello"));
send.add(new WebSocketFrame((byte)13)); // intentionally bad
send.add(new BadFrame((byte)13)); // intentionally bad
send.add(WebSocketFrame.ping());
List<WebSocketFrame> expect = new ArrayList<>();
@ -259,7 +270,7 @@ public class TestABCase4 extends AbstractABCase
{
List<WebSocketFrame> send = new ArrayList<>();
send.add(WebSocketFrame.text("hello"));
send.add(new WebSocketFrame((byte)14).setPayload("bad")); // intentionally bad
send.add(new BadFrame((byte)14).setPayload("bad")); // intentionally bad
send.add(WebSocketFrame.ping());
List<WebSocketFrame> expect = new ArrayList<>();
@ -288,7 +299,7 @@ public class TestABCase4 extends AbstractABCase
{
List<WebSocketFrame> send = new ArrayList<>();
send.add(WebSocketFrame.text("hello"));
send.add(new WebSocketFrame((byte)15).setPayload("bad")); // intentionally bad
send.add(new BadFrame((byte)15).setPayload("bad")); // intentionally bad
send.add(WebSocketFrame.ping());
List<WebSocketFrame> expect = new ArrayList<>();

View File

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

View File

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

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

View File

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

View File

@ -1,7 +1,7 @@
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
org.eclipse.jetty.LEVEL=WARN
# org.eclipse.jetty.websocket.LEVEL=WARN
# org.eclipse.jetty.websocket.LEVEL=DEBUG
org.eclipse.jetty.websocket.LEVEL=DEBUG
# org.eclipse.jetty.websocket.io.LEVEL=DEBUG
# org.eclipse.jetty.websocket.io.WebSocketAsyncConnection.LEVEL=DEBUG
# org.eclipse.jetty.websocket.io.ControlFrameBytes.LEVEL=DEBUG