344059 extension framework for websockets
git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@3052 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
parent
f7ca15c499
commit
a70bbc004d
|
@ -7,8 +7,8 @@ jetty-7.4.1-SNAPSHOT
|
|||
+ 343482 refactored overlay deployer layout to use WAR layout
|
||||
+ 343923 flush timeouts applied to outer loop
|
||||
+ 344059 Websockets draft-07
|
||||
+ JETTY-954 WebAppContext eats any start exceptions instead of stopping the server load
|
||||
+ 344067 - Add support for OSGi fragment bundles to add static resources to web-bundles
|
||||
+ JETTY-954 WebAppContext eats any start exceptions instead of stopping the server load
|
||||
|
||||
jetty-7.4.0.v20110414
|
||||
+ 342504 Scanner Listener
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
package org.eclipse.jetty.websocket;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.jetty.io.Buffer;
|
||||
import org.eclipse.jetty.websocket.WebSocketParser.FrameHandler;
|
||||
|
||||
public class AbstractExtension implements Extension
|
||||
{
|
||||
private final String _name;
|
||||
private final byte[] _dataOpcodes;
|
||||
private final byte[] _controlOpcodes;
|
||||
private final byte[] _bitMasks;
|
||||
private FrameHandler _inbound;
|
||||
private WebSocketGenerator _outbound;
|
||||
|
||||
public AbstractExtension(String name,int dataCodes, int controlCodes, int flags)
|
||||
{
|
||||
_name = name;
|
||||
_dataOpcodes=new byte[dataCodes];
|
||||
_controlOpcodes=new byte[controlCodes];
|
||||
_bitMasks=new byte[flags];
|
||||
}
|
||||
|
||||
public int getDataOpcodes()
|
||||
{
|
||||
return _dataOpcodes.length;
|
||||
}
|
||||
|
||||
public int getControlOpcodes()
|
||||
{
|
||||
return _controlOpcodes.length;
|
||||
}
|
||||
|
||||
public int getReservedBits()
|
||||
{
|
||||
return _bitMasks.length;
|
||||
}
|
||||
|
||||
public void init(FrameHandler incoming, WebSocketGenerator outgoing, byte[] dataOpcodes, byte[] controlOpcodes, byte[] bitMasks)
|
||||
{
|
||||
_inbound=incoming;
|
||||
_outbound=outgoing;
|
||||
if (dataOpcodes!=null)
|
||||
System.arraycopy(dataOpcodes,0,_dataOpcodes,0,dataOpcodes.length);
|
||||
if (controlOpcodes!=null)
|
||||
System.arraycopy(controlOpcodes,0,_dataOpcodes,0,controlOpcodes.length);
|
||||
if (bitMasks!=null)
|
||||
System.arraycopy(bitMasks,0,_bitMasks,0,bitMasks.length);
|
||||
}
|
||||
|
||||
public String getExtensionName()
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
public void onFrame(byte flags, byte opcode, Buffer buffer)
|
||||
{
|
||||
// System.err.printf("onFrame %s %x %x %d\n",getExtensionName(),flags,opcode,buffer.length());
|
||||
_inbound.onFrame(flags,opcode,buffer);
|
||||
}
|
||||
|
||||
public void close(int code, String message)
|
||||
{
|
||||
_inbound.close(code,message);
|
||||
}
|
||||
|
||||
public int flush() throws IOException
|
||||
{
|
||||
return _outbound.flush();
|
||||
}
|
||||
|
||||
public boolean isBufferEmpty()
|
||||
{
|
||||
return _outbound.isBufferEmpty();
|
||||
}
|
||||
|
||||
public void addFrame(byte flags, byte opcode, byte[] content, int offset, int length) throws IOException
|
||||
{
|
||||
// System.err.printf("addFrame %s %x %x %d\n",getExtensionName(),flags,opcode,length);
|
||||
_outbound.addFrame(flags,opcode,content,offset,length);
|
||||
}
|
||||
|
||||
public byte dataOpcode(int i)
|
||||
{
|
||||
return _dataOpcodes[i];
|
||||
}
|
||||
|
||||
public int dataIndex(byte op)
|
||||
{
|
||||
for (int i=0;i<_dataOpcodes.length;i++)
|
||||
if (_dataOpcodes[i]==op)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
public byte controlOpcode(int i)
|
||||
{
|
||||
return _dataOpcodes[i];
|
||||
}
|
||||
|
||||
public int controlIndex(byte op)
|
||||
{
|
||||
for (int i=0;i<_controlOpcodes.length;i++)
|
||||
if (_controlOpcodes[i]==op)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
public byte setFlag(byte flags,int flag)
|
||||
{
|
||||
return (byte)(flags | _bitMasks[flag]);
|
||||
}
|
||||
|
||||
public byte clearFlag(byte flags,int flag)
|
||||
{
|
||||
return (byte)(flags & ~_bitMasks[flag]);
|
||||
}
|
||||
|
||||
public boolean isFlag(byte flags,int flag)
|
||||
{
|
||||
return (flags & _bitMasks[flag])!=0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package org.eclipse.jetty.websocket;
|
||||
|
||||
public interface Extension extends WebSocketParser.FrameHandler, WebSocketGenerator
|
||||
{
|
||||
public String getExtensionName();
|
||||
public int getDataOpcodes();
|
||||
public int getControlOpcodes();
|
||||
public int getReservedBits();
|
||||
|
||||
public void init(WebSocketParser.FrameHandler inbound, WebSocketGenerator outbound,byte[] dataOpCodes, byte[] controlOpcodes, byte[] bitMasks);
|
||||
|
||||
}
|
|
@ -63,16 +63,16 @@ public class TestClient
|
|||
{
|
||||
byte[] data=buffer.asArray();
|
||||
// System.err.println("CLOSED: "+((0xff&data[0])*0x100+(0xff&data[1]))+" "+new String(data,2,data.length-2,StringUtil.__UTF8));
|
||||
_generator.addFrame((byte)0x8,WebSocketConnectionD07.OP_CLOSE,data,0,data.length,_socket.getSoTimeout());
|
||||
_generator.flush(_socket.getSoTimeout());
|
||||
_generator.addFrame((byte)0x8,WebSocketConnectionD07.OP_CLOSE,data,0,data.length);
|
||||
_generator.flush();
|
||||
_socket.shutdownOutput();
|
||||
_socket.close();
|
||||
return;
|
||||
}
|
||||
else if (opcode == WebSocketConnectionD07.OP_PING)
|
||||
{
|
||||
_generator.addFrame((byte)0x8,WebSocketConnectionD07.OP_PONG,buffer.array(),buffer.getIndex(),buffer.length(),_socket.getSoTimeout());
|
||||
_generator.flush(_socket.getSoTimeout());
|
||||
_generator.addFrame((byte)0x8,WebSocketConnectionD07.OP_PONG,buffer.array(),buffer.getIndex(),buffer.length());
|
||||
_generator.flush();
|
||||
}
|
||||
|
||||
_messageBytes+=buffer.length();
|
||||
|
@ -232,7 +232,7 @@ public class TestClient
|
|||
|
||||
if (_verbose)
|
||||
System.err.printf("%s#addFrame %s|%s %s\n",this.getClass().getSimpleName(),TypeUtil.toHexString(flags),TypeUtil.toHexString(op),TypeUtil.toHexString(data,off,len));
|
||||
_generator.addFrame(flags,op,data,off,len,_socket.getSoTimeout());
|
||||
_generator.addFrame(flags,op,data,off,len);
|
||||
|
||||
off+=len;
|
||||
if(data.length-off>len)
|
||||
|
@ -241,7 +241,7 @@ public class TestClient
|
|||
len=fragment;
|
||||
}
|
||||
|
||||
_generator.flush(_socket.getSoTimeout());
|
||||
_generator.flush();
|
||||
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
|
@ -258,7 +258,7 @@ public class TestClient
|
|||
{
|
||||
if (_messagesSent==_messagesReceived)
|
||||
break;
|
||||
_generator.flush(10);
|
||||
_generator.flush();
|
||||
Thread.sleep(100);
|
||||
}
|
||||
|
||||
|
|
|
@ -231,7 +231,7 @@ public class WebSocketConnectionD00 extends AbstractConnection implements WebSoc
|
|||
public void sendMessage(String content) throws IOException
|
||||
{
|
||||
byte[] data = content.getBytes(StringUtil.__UTF8);
|
||||
_generator.addFrame((byte)0,SENTINEL_FRAME,data,0,data.length,_endp.getMaxIdleTime());
|
||||
_generator.addFrame((byte)0,SENTINEL_FRAME,data,0,data.length);
|
||||
_generator.flush();
|
||||
checkWriteable();
|
||||
_idle.access(_endp);
|
||||
|
@ -240,7 +240,7 @@ public class WebSocketConnectionD00 extends AbstractConnection implements WebSoc
|
|||
/* ------------------------------------------------------------ */
|
||||
public void sendMessage(byte[] data, int offset, int length) throws IOException
|
||||
{
|
||||
_generator.addFrame((byte)0,LENGTH_FRAME,data,offset,length,_endp.getMaxIdleTime());
|
||||
_generator.addFrame((byte)0,LENGTH_FRAME,data,offset,length);
|
||||
_generator.flush();
|
||||
checkWriteable();
|
||||
_idle.access(_endp);
|
||||
|
@ -263,7 +263,7 @@ public class WebSocketConnectionD00 extends AbstractConnection implements WebSoc
|
|||
/* ------------------------------------------------------------ */
|
||||
public void sendFrame(byte flags,byte opcode, byte[] content, int offset, int length) throws IOException
|
||||
{
|
||||
_generator.addFrame((byte)0,opcode,content,offset,length,_endp.getMaxIdleTime());
|
||||
_generator.addFrame((byte)0,opcode,content,offset,length);
|
||||
_generator.flush();
|
||||
checkWriteable();
|
||||
_idle.access(_endp);
|
||||
|
@ -280,7 +280,7 @@ public class WebSocketConnectionD00 extends AbstractConnection implements WebSoc
|
|||
{
|
||||
try
|
||||
{
|
||||
_generator.flush(_endp.getMaxIdleTime());
|
||||
_generator.flush();
|
||||
_endp.close();
|
||||
}
|
||||
catch(IOException e)
|
||||
|
@ -289,12 +289,14 @@ public class WebSocketConnectionD00 extends AbstractConnection implements WebSoc
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void fillBuffersFrom(Buffer buffer)
|
||||
{
|
||||
_parser.fill(buffer);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
private void checkWriteable()
|
||||
{
|
||||
if (!_generator.isBufferEmpty() && _endp instanceof AsyncEndPoint)
|
||||
|
|
|
@ -271,7 +271,7 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
|
|||
byte[] bytes = ("xx"+(message==null?"":message)).getBytes(StringUtil.__ISO_8859_1);
|
||||
bytes[0]=(byte)(code/0x100);
|
||||
bytes[1]=(byte)(code%0x100);
|
||||
_generator.addFrame((byte)0x8,WebSocketConnectionD06.OP_CLOSE,bytes,0,bytes.length,_endp.getMaxIdleTime());
|
||||
_generator.addFrame((byte)0x8,WebSocketConnectionD06.OP_CLOSE,bytes,0,bytes.length);
|
||||
}
|
||||
_generator.flush();
|
||||
|
||||
|
@ -319,7 +319,7 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
|
|||
if (_closedOut)
|
||||
throw new IOException("closing");
|
||||
byte[] data = content.getBytes(StringUtil.__UTF8);
|
||||
_generator.addFrame((byte)0x8,WebSocketConnectionD06.OP_TEXT,data,0,data.length,_endp.getMaxIdleTime());
|
||||
_generator.addFrame((byte)0x8,WebSocketConnectionD06.OP_TEXT,data,0,data.length);
|
||||
_generator.flush();
|
||||
checkWriteable();
|
||||
_idle.access(_endp);
|
||||
|
@ -333,7 +333,7 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
|
|||
{
|
||||
if (_closedOut)
|
||||
throw new IOException("closing");
|
||||
_generator.addFrame((byte)0x8,WebSocketConnectionD06.OP_BINARY,content,offset,length,_endp.getMaxIdleTime());
|
||||
_generator.addFrame((byte)0x8,WebSocketConnectionD06.OP_BINARY,content,offset,length);
|
||||
_generator.flush();
|
||||
checkWriteable();
|
||||
_idle.access(_endp);
|
||||
|
@ -347,7 +347,7 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
|
|||
{
|
||||
if (_closedOut)
|
||||
throw new IOException("closing");
|
||||
_generator.addFrame(flags,opcode,content,offset,length,_endp.getMaxIdleTime());
|
||||
_generator.addFrame(flags,opcode,content,offset,length);
|
||||
_generator.flush();
|
||||
checkWriteable();
|
||||
_idle.access(_endp);
|
||||
|
@ -358,7 +358,7 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
|
|||
{
|
||||
if (_closedOut)
|
||||
throw new IOException("closing");
|
||||
_generator.addFrame((byte)0x8,control,data,offset,length,_endp.getMaxIdleTime());
|
||||
_generator.addFrame((byte)0x8,control,data,offset,length);
|
||||
_generator.flush();
|
||||
checkWriteable();
|
||||
_idle.access(_endp);
|
||||
|
|
|
@ -41,10 +41,12 @@ public class WebSocketConnectionD07 extends AbstractConnection implements WebSoc
|
|||
final static byte OP_CONTINUATION = 0x00;
|
||||
final static byte OP_TEXT = 0x01;
|
||||
final static byte OP_BINARY = 0x02;
|
||||
final static byte OP_EXT_DATA = 0x03;
|
||||
|
||||
final static byte OP_CLOSE = 0x08;
|
||||
final static byte OP_PING = 0x09;
|
||||
final static byte OP_PONG = 0x0A;
|
||||
final static byte OP_EXT_CTRL = 0x0B;
|
||||
|
||||
final static int CLOSE_NORMAL=1000;
|
||||
final static int CLOSE_SHUTDOWN=1001;
|
||||
|
@ -62,11 +64,12 @@ public class WebSocketConnectionD07 extends AbstractConnection implements WebSoc
|
|||
return (opcode&0x8)!=0;
|
||||
}
|
||||
|
||||
|
||||
private final static byte[] MAGIC;
|
||||
private final IdleCheck _idle;
|
||||
private final WebSocketParser _parser;
|
||||
private final WebSocketGenerator _generator;
|
||||
private final WebSocketParserD07 _parser;
|
||||
private final WebSocketParser.FrameHandler _inbound;
|
||||
private final WebSocketGeneratorD07 _generator;
|
||||
private final WebSocketGenerator _outbound;
|
||||
private final WebSocket _webSocket;
|
||||
private final OnFrame _onFrame;
|
||||
private final OnBinaryMessage _onBinaryMessage;
|
||||
|
@ -99,7 +102,7 @@ public class WebSocketConnectionD07 extends AbstractConnection implements WebSoc
|
|||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public WebSocketConnectionD07(WebSocket websocket, EndPoint endpoint, WebSocketBuffers buffers, long timestamp, int maxIdleTime, String protocol)
|
||||
public WebSocketConnectionD07(WebSocket websocket, EndPoint endpoint, WebSocketBuffers buffers, long timestamp, int maxIdleTime, String protocol, Extension[] extensions)
|
||||
throws IOException
|
||||
{
|
||||
super(endpoint,timestamp);
|
||||
|
@ -116,7 +119,39 @@ public class WebSocketConnectionD07 extends AbstractConnection implements WebSoc
|
|||
_onBinaryMessage=_webSocket instanceof OnBinaryMessage ? (OnBinaryMessage)_webSocket : null;
|
||||
_onControl=_webSocket instanceof OnControl ? (OnControl)_webSocket : null;
|
||||
_generator = new WebSocketGeneratorD07(buffers, _endp,null);
|
||||
_parser = new WebSocketParserD07(buffers, endpoint, _frameHandler,true);
|
||||
|
||||
if (extensions!=null)
|
||||
{
|
||||
byte data_op=OP_EXT_DATA;
|
||||
byte ctrl_op=OP_EXT_CTRL;
|
||||
byte flag_mask=0x4;
|
||||
for (int e=0;e<extensions.length;e++)
|
||||
{
|
||||
byte[] data_ops=new byte[extensions[e].getDataOpcodes()];
|
||||
for (int i=0;i<data_ops.length;i++)
|
||||
data_ops[i]=data_op++;
|
||||
byte[] ctrl_ops=new byte[extensions[e].getControlOpcodes()];
|
||||
for (int i=0;i<ctrl_ops.length;i++)
|
||||
ctrl_ops[i]=ctrl_op++;
|
||||
byte[] flag_masks=new byte[extensions[e].getReservedBits()];
|
||||
for (int i=0;i<flag_masks.length;i++)
|
||||
{
|
||||
flag_masks[i]=flag_mask;
|
||||
flag_mask= (byte)(flag_mask>>1);
|
||||
}
|
||||
|
||||
extensions[e].init(
|
||||
e==extensions.length-1?_frameHandler:extensions[e+1],
|
||||
e==0?_generator:extensions[e-1],
|
||||
data_ops,ctrl_ops,flag_masks);
|
||||
}
|
||||
}
|
||||
|
||||
_outbound=(extensions==null || extensions.length==0)?_generator:extensions[extensions.length-1];
|
||||
_inbound=(extensions==null || extensions.length==0)?_frameHandler:extensions[0];
|
||||
|
||||
_parser = new WebSocketParserD07(buffers, endpoint,_inbound,true);
|
||||
|
||||
_protocol=protocol;
|
||||
|
||||
// TODO should these be AsyncEndPoint checks/calls?
|
||||
|
@ -162,7 +197,7 @@ public class WebSocketConnectionD07 extends AbstractConnection implements WebSoc
|
|||
|
||||
while (progress)
|
||||
{
|
||||
int flushed=_generator.flush();
|
||||
int flushed=_generator.flushBuffer();
|
||||
int filled=_parser.parseNext();
|
||||
|
||||
progress = flushed>0 || filled>0;
|
||||
|
@ -190,8 +225,9 @@ public class WebSocketConnectionD07 extends AbstractConnection implements WebSoc
|
|||
{
|
||||
if (_endp.isOpen())
|
||||
{
|
||||
_generator.idle();
|
||||
_idle.access(_endp);
|
||||
if (_closedIn && _closedOut && _generator.isBufferEmpty())
|
||||
if (_closedIn && _closedOut && _outbound.isBufferEmpty())
|
||||
_endp.close();
|
||||
else if (_endp.isInputShutdown() && !_closedIn)
|
||||
closeIn(CLOSE_PROTOCOL,null);
|
||||
|
@ -206,7 +242,7 @@ public class WebSocketConnectionD07 extends AbstractConnection implements WebSoc
|
|||
/* ------------------------------------------------------------ */
|
||||
public boolean isIdle()
|
||||
{
|
||||
return _parser.isBufferEmpty() && _generator.isBufferEmpty();
|
||||
return _parser.isBufferEmpty() && _outbound.isBufferEmpty();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -264,9 +300,9 @@ public class WebSocketConnectionD07 extends AbstractConnection implements WebSoc
|
|||
byte[] bytes = ("xx"+(message==null?"":message)).getBytes(StringUtil.__ISO_8859_1);
|
||||
bytes[0]=(byte)(code/0x100);
|
||||
bytes[1]=(byte)(code%0x100);
|
||||
_generator.addFrame((byte)0x8,WebSocketConnectionD07.OP_CLOSE,bytes,0,bytes.length,_endp.getMaxIdleTime());
|
||||
_outbound.addFrame((byte)0x8,WebSocketConnectionD07.OP_CLOSE,bytes,0,bytes.length);
|
||||
}
|
||||
_generator.flush();
|
||||
_outbound.flush();
|
||||
|
||||
}
|
||||
catch(IOException e)
|
||||
|
@ -288,7 +324,7 @@ public class WebSocketConnectionD07 extends AbstractConnection implements WebSoc
|
|||
/* ------------------------------------------------------------ */
|
||||
private void checkWriteable()
|
||||
{
|
||||
if (!_generator.isBufferEmpty() && _endp instanceof AsyncEndPoint)
|
||||
if (!_outbound.isBufferEmpty() && _endp instanceof AsyncEndPoint)
|
||||
{
|
||||
((AsyncEndPoint)_endp).scheduleWrite();
|
||||
}
|
||||
|
@ -312,8 +348,7 @@ public class WebSocketConnectionD07 extends AbstractConnection implements WebSoc
|
|||
if (_closedOut)
|
||||
throw new IOException("closing");
|
||||
byte[] data = content.getBytes(StringUtil.__UTF8);
|
||||
_generator.addFrame((byte)0x8,WebSocketConnectionD07.OP_TEXT,data,0,data.length,_endp.getMaxIdleTime());
|
||||
_generator.flush();
|
||||
_outbound.addFrame((byte)0x8,WebSocketConnectionD07.OP_TEXT,data,0,data.length);
|
||||
checkWriteable();
|
||||
_idle.access(_endp);
|
||||
}
|
||||
|
@ -326,8 +361,7 @@ public class WebSocketConnectionD07 extends AbstractConnection implements WebSoc
|
|||
{
|
||||
if (_closedOut)
|
||||
throw new IOException("closing");
|
||||
_generator.addFrame((byte)0x8,WebSocketConnectionD07.OP_BINARY,content,offset,length,_endp.getMaxIdleTime());
|
||||
_generator.flush();
|
||||
_outbound.addFrame((byte)0x8,WebSocketConnectionD07.OP_BINARY,content,offset,length);
|
||||
checkWriteable();
|
||||
_idle.access(_endp);
|
||||
}
|
||||
|
@ -340,19 +374,17 @@ public class WebSocketConnectionD07 extends AbstractConnection implements WebSoc
|
|||
{
|
||||
if (_closedOut)
|
||||
throw new IOException("closing");
|
||||
_generator.addFrame(flags,opcode,content,offset,length,_endp.getMaxIdleTime());
|
||||
_generator.flush();
|
||||
_outbound.addFrame(flags,opcode,content,offset,length);
|
||||
checkWriteable();
|
||||
_idle.access(_endp);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void sendControl(byte control, byte[] data, int offset, int length) throws IOException
|
||||
public void sendControl(byte ctrl, byte[] data, int offset, int length) throws IOException
|
||||
{
|
||||
if (_closedOut)
|
||||
throw new IOException("closing");
|
||||
_generator.addFrame((byte)0x8,control,data,offset,length,_endp.getMaxIdleTime());
|
||||
_generator.flush();
|
||||
_outbound.addFrame((byte)0x8,ctrl,data,offset,length);
|
||||
checkWriteable();
|
||||
_idle.access(_endp);
|
||||
}
|
||||
|
|
|
@ -129,7 +129,7 @@ public class WebSocketFactory
|
|||
connection = new WebSocketConnectionD06(websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol);
|
||||
break;
|
||||
case 7:
|
||||
connection = new WebSocketConnectionD07(websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol);
|
||||
connection = new WebSocketConnectionD07(websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol,null);
|
||||
break;
|
||||
default:
|
||||
Log.warn("Unsupported Websocket version: "+draft);
|
||||
|
|
|
@ -24,6 +24,5 @@ public interface WebSocketGenerator
|
|||
{
|
||||
int flush() throws IOException;
|
||||
boolean isBufferEmpty();
|
||||
void addFrame(byte flags,byte opcode, byte[] content, int offset, int length, int maxIdleTime) throws IOException;
|
||||
int flush(int maxIdleTime) throws IOException;
|
||||
void addFrame(byte flags,byte opcode, byte[] content, int offset, int length) throws IOException;
|
||||
}
|
||||
|
|
|
@ -40,8 +40,10 @@ public class WebSocketGeneratorD00 implements WebSocketGenerator
|
|||
_endp=endp;
|
||||
}
|
||||
|
||||
public synchronized void addFrame(byte flags, byte opcode,byte[] content, int offset, int length, int blockFor) throws IOException
|
||||
public synchronized void addFrame(byte flags, byte opcode,byte[] content, int offset, int length) throws IOException
|
||||
{
|
||||
long blockFor=_endp.getMaxIdleTime();
|
||||
|
||||
if (_buffer==null)
|
||||
_buffer=_buffers.getDirectBuffer();
|
||||
|
||||
|
|
|
@ -109,10 +109,12 @@ public class WebSocketGeneratorD06 implements WebSocketGenerator
|
|||
_maskGen=maskGen;
|
||||
}
|
||||
|
||||
public synchronized void addFrame(byte flags, byte opcode, byte[] content, int offset, int length, int blockFor) throws IOException
|
||||
public synchronized void addFrame(byte flags, byte opcode, byte[] content, int offset, int length) throws IOException
|
||||
{
|
||||
// System.err.printf("<< %s %s %s\n",TypeUtil.toHexString(flags),TypeUtil.toHexString(opcode),length);
|
||||
|
||||
long blockFor=_endp.getMaxIdleTime();
|
||||
|
||||
if (_buffer==null)
|
||||
_buffer=(_maskGen!=null)?_buffers.getBuffer():_buffers.getDirectBuffer();
|
||||
|
||||
|
|
|
@ -109,7 +109,7 @@ public class WebSocketGeneratorD07 implements WebSocketGenerator
|
|||
_maskGen=maskGen;
|
||||
}
|
||||
|
||||
public synchronized void addFrame(byte flags, byte opcode, byte[] content, int offset, int length, int blockFor) throws IOException
|
||||
public synchronized void addFrame(byte flags, byte opcode, byte[] content, int offset, int length) throws IOException
|
||||
{
|
||||
// System.err.printf("<< %s %s %s\n",TypeUtil.toHexString(flags),TypeUtil.toHexString(opcode),length);
|
||||
|
||||
|
@ -140,7 +140,11 @@ public class WebSocketGeneratorD07 implements WebSocketGenerator
|
|||
|
||||
// ensure there is space for header
|
||||
if (_buffer.space() <= space)
|
||||
expelBuffer(blockFor);
|
||||
{
|
||||
flushBuffer();
|
||||
if (_buffer.space() <= space)
|
||||
flush();
|
||||
}
|
||||
|
||||
// write the opcode and length
|
||||
if (payload>0xffff)
|
||||
|
@ -205,7 +209,7 @@ public class WebSocketGeneratorD07 implements WebSocketGenerator
|
|||
else
|
||||
{
|
||||
// Forcibly flush the data, issuing a blocking write
|
||||
expelBuffer(blockFor);
|
||||
flush();
|
||||
if (remaining == 0)
|
||||
{
|
||||
// Gently flush the data, issuing a non-blocking write
|
||||
|
@ -218,25 +222,15 @@ public class WebSocketGeneratorD07 implements WebSocketGenerator
|
|||
}
|
||||
while (length>0);
|
||||
_opsent=!last;
|
||||
}
|
||||
|
||||
public synchronized int flush(int blockFor) throws IOException
|
||||
{
|
||||
return expelBuffer(blockFor);
|
||||
}
|
||||
|
||||
public synchronized int flush() throws IOException
|
||||
{
|
||||
int flushed = flushBuffer();
|
||||
|
||||
if (_buffer!=null && _buffer.length()==0)
|
||||
{
|
||||
_buffers.returnBuffer(_buffer);
|
||||
_buffer=null;
|
||||
}
|
||||
return flushed;
|
||||
}
|
||||
|
||||
private synchronized int flushBuffer() throws IOException
|
||||
public synchronized int flushBuffer() throws IOException
|
||||
{
|
||||
if (!_endp.isOpen())
|
||||
throw new EofException();
|
||||
|
@ -247,26 +241,31 @@ public class WebSocketGeneratorD07 implements WebSocketGenerator
|
|||
return 0;
|
||||
}
|
||||
|
||||
private synchronized int expelBuffer(long blockFor) throws IOException
|
||||
public synchronized int flush() throws IOException
|
||||
{
|
||||
if (_buffer==null)
|
||||
return 0;
|
||||
int result = flushBuffer();
|
||||
_buffer.compact();
|
||||
|
||||
if (!_endp.isBlocking())
|
||||
{
|
||||
while (_buffer.space()==0)
|
||||
long now = System.currentTimeMillis();
|
||||
long end=now+_endp.getMaxIdleTime();
|
||||
while (_buffer.length()>0)
|
||||
{
|
||||
// TODO: in case the I/O system signals write ready, but when we attempt to write we cannot
|
||||
// TODO: we should decrease the blockFor timeout instead of waiting again the whole timeout
|
||||
boolean ready = _endp.blockWritable(blockFor);
|
||||
boolean ready = _endp.blockWritable(end-now);
|
||||
if (!ready)
|
||||
{
|
||||
now = System.currentTimeMillis();
|
||||
if (now<end)
|
||||
continue;
|
||||
throw new IOException("Write timeout");
|
||||
}
|
||||
|
||||
result += flushBuffer();
|
||||
_buffer.compact();
|
||||
}
|
||||
}
|
||||
_buffer.compact();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -275,4 +274,13 @@ public class WebSocketGeneratorD07 implements WebSocketGenerator
|
|||
return _buffer==null || _buffer.length()==0;
|
||||
}
|
||||
|
||||
public synchronized void idle()
|
||||
{
|
||||
if (_buffer!=null && _buffer.length()==0)
|
||||
{
|
||||
_buffers.returnBuffer(_buffer);
|
||||
_buffer=null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ public class WebSocketGeneratorD00Test
|
|||
public void testOneString() throws Exception
|
||||
{
|
||||
byte[] data="Hell\uFF4F W\uFF4Frld".getBytes(StringUtil.__UTF8);
|
||||
_generator.addFrame((byte)0x0,(byte)0x04,data,0,data.length,0);
|
||||
_generator.addFrame((byte)0x0,(byte)0x04,data,0,data.length);
|
||||
_generator.flush();
|
||||
assertEquals((byte)0x04,_out.get());
|
||||
assertEquals('H',_out.get());
|
||||
|
@ -55,7 +55,7 @@ public class WebSocketGeneratorD00Test
|
|||
public void testOneBinaryString() throws Exception
|
||||
{
|
||||
byte[] data="Hell\uFF4F W\uFF4Frld".getBytes(StringUtil.__UTF8);
|
||||
_generator.addFrame((byte)0x0,(byte)0x84,data,0,data.length,0);
|
||||
_generator.addFrame((byte)0x0,(byte)0x84,data,0,data.length);
|
||||
_generator.flush();
|
||||
assertEquals((byte)0x84,_out.get());
|
||||
assertEquals(15,_out.get());
|
||||
|
|
|
@ -45,7 +45,7 @@ public class WebSocketGeneratorD06Test
|
|||
_generator = new WebSocketGeneratorD06(_buffers, _endPoint,null);
|
||||
|
||||
byte[] data = "Hell\uFF4F W\uFF4Frld".getBytes(StringUtil.__UTF8);
|
||||
_generator.addFrame((byte)0x8,(byte)0x04,data,0,data.length,0);
|
||||
_generator.addFrame((byte)0x8,(byte)0x04,data,0,data.length);
|
||||
_generator.flush();
|
||||
assertEquals((byte)0x84,_out.get());
|
||||
assertEquals(15,0xff&_out.get());
|
||||
|
@ -73,7 +73,7 @@ public class WebSocketGeneratorD06Test
|
|||
|
||||
String string = "Hell\uFF4F W\uFF4Frld";
|
||||
byte[] bytes=string.getBytes(StringUtil.__UTF8);
|
||||
_generator.addFrame((byte)0x8,(byte)0x04,bytes,0,bytes.length,0);
|
||||
_generator.addFrame((byte)0x8,(byte)0x04,bytes,0,bytes.length);
|
||||
_generator.flush();
|
||||
assertEquals((byte)0x84,_out.get());
|
||||
assertEquals(15,0xff&_out.get());
|
||||
|
@ -103,7 +103,7 @@ public class WebSocketGeneratorD06Test
|
|||
for (int i=0;i<b.length;i++)
|
||||
b[i]=(byte)('0'+(i%10));
|
||||
|
||||
_generator.addFrame((byte)0x8,(byte)0x4,b,0,b.length,0);
|
||||
_generator.addFrame((byte)0x8,(byte)0x4,b,0,b.length);
|
||||
|
||||
_generator.flush();
|
||||
assertEquals((byte)0x84,_out.get());
|
||||
|
@ -121,7 +121,7 @@ public class WebSocketGeneratorD06Test
|
|||
_generator = new WebSocketGeneratorD06(_buffers, _endPoint,_maskGen);
|
||||
|
||||
byte[] data = "Hell\uFF4F W\uFF4Frld".getBytes(StringUtil.__UTF8);
|
||||
_generator.addFrame((byte)0x8,(byte)0x04,data,0,data.length,0);
|
||||
_generator.addFrame((byte)0x8,(byte)0x04,data,0,data.length);
|
||||
_generator.flush();
|
||||
|
||||
_out.get(_mask,0,4);
|
||||
|
@ -152,7 +152,7 @@ public class WebSocketGeneratorD06Test
|
|||
|
||||
String string = "Hell\uFF4F W\uFF4Frld";
|
||||
byte[] bytes=string.getBytes(StringUtil.__UTF8);
|
||||
_generator.addFrame((byte)0x8,(byte)0x04,bytes,0,bytes.length,0);
|
||||
_generator.addFrame((byte)0x8,(byte)0x04,bytes,0,bytes.length);
|
||||
_generator.flush();
|
||||
|
||||
_out.get(_mask,0,4);
|
||||
|
@ -185,7 +185,7 @@ public class WebSocketGeneratorD06Test
|
|||
for (int i=0;i<b.length;i++)
|
||||
b[i]=(byte)('0'+(i%10));
|
||||
|
||||
_generator.addFrame((byte)0x8,(byte)0x04,b,0,b.length,0);
|
||||
_generator.addFrame((byte)0x8,(byte)0x04,b,0,b.length);
|
||||
_generator.flush();
|
||||
|
||||
_out.get(_mask,0,4);
|
||||
|
|
|
@ -45,7 +45,7 @@ public class WebSocketGeneratorD07Test
|
|||
_generator = new WebSocketGeneratorD07(_buffers, _endPoint,null);
|
||||
|
||||
byte[] data = "Hell\uFF4F W\uFF4Frld".getBytes(StringUtil.__UTF8);
|
||||
_generator.addFrame((byte)0x8,(byte)0x04,data,0,data.length,0);
|
||||
_generator.addFrame((byte)0x8,(byte)0x04,data,0,data.length);
|
||||
_generator.flush();
|
||||
assertEquals((byte)0x84,_out.get());
|
||||
assertEquals(15,0xff&_out.get());
|
||||
|
@ -73,7 +73,7 @@ public class WebSocketGeneratorD07Test
|
|||
|
||||
String string = "Hell\uFF4F W\uFF4Frld";
|
||||
byte[] bytes=string.getBytes(StringUtil.__UTF8);
|
||||
_generator.addFrame((byte)0x8,(byte)0x04,bytes,0,bytes.length,0);
|
||||
_generator.addFrame((byte)0x8,(byte)0x04,bytes,0,bytes.length);
|
||||
_generator.flush();
|
||||
assertEquals((byte)0x84,_out.get());
|
||||
assertEquals(15,0xff&_out.get());
|
||||
|
@ -103,7 +103,7 @@ public class WebSocketGeneratorD07Test
|
|||
for (int i=0;i<b.length;i++)
|
||||
b[i]=(byte)('0'+(i%10));
|
||||
|
||||
_generator.addFrame((byte)0x8,(byte)0x4,b,0,b.length,0);
|
||||
_generator.addFrame((byte)0x8,(byte)0x4,b,0,b.length);
|
||||
|
||||
_generator.flush();
|
||||
assertEquals((byte)0x84,_out.get());
|
||||
|
@ -121,7 +121,7 @@ public class WebSocketGeneratorD07Test
|
|||
_generator = new WebSocketGeneratorD07(_buffers, _endPoint,_maskGen);
|
||||
|
||||
byte[] data = "Hell\uFF4F W\uFF4Frld".getBytes(StringUtil.__UTF8);
|
||||
_generator.addFrame((byte)0x8,(byte)0x04,data,0,data.length,0);
|
||||
_generator.addFrame((byte)0x8,(byte)0x04,data,0,data.length);
|
||||
_generator.flush();
|
||||
|
||||
assertEquals((byte)0x84,_out.get());
|
||||
|
@ -151,7 +151,7 @@ public class WebSocketGeneratorD07Test
|
|||
|
||||
String string = "Hell\uFF4F W\uFF4Frld";
|
||||
byte[] bytes=string.getBytes(StringUtil.__UTF8);
|
||||
_generator.addFrame((byte)0x8,(byte)0x04,bytes,0,bytes.length,0);
|
||||
_generator.addFrame((byte)0x8,(byte)0x04,bytes,0,bytes.length);
|
||||
_generator.flush();
|
||||
|
||||
assertEquals((byte)0x84,_out.get());
|
||||
|
@ -183,7 +183,7 @@ public class WebSocketGeneratorD07Test
|
|||
for (int i=0;i<b.length;i++)
|
||||
b[i]=(byte)('0'+(i%10));
|
||||
|
||||
_generator.addFrame((byte)0x8,(byte)0x04,b,0,b.length,0);
|
||||
_generator.addFrame((byte)0x8,(byte)0x04,b,0,b.length);
|
||||
_generator.flush();
|
||||
|
||||
assertEquals((byte)0x84,_out.get());
|
||||
|
|
|
@ -202,7 +202,7 @@ public class WebSocketLoadTest
|
|||
for (int i = 0; i < iterations; ++i)
|
||||
{
|
||||
byte[] data = message.getBytes(StringUtil.__UTF8);
|
||||
_generator.addFrame((byte)0x8,WebSocketConnectionD06.OP_TEXT,data,0,data.length,10000);
|
||||
_generator.addFrame((byte)0x8,WebSocketConnectionD06.OP_TEXT,data,0,data.length);
|
||||
_generator.flush(10000);
|
||||
|
||||
//System.err.println("-> "+message);
|
||||
|
|
|
@ -634,7 +634,7 @@ public class WebSocketMessageD06Test
|
|||
WebSocketGeneratorD06 gen = new WebSocketGeneratorD06(new WebSocketBuffers(8096),endp,null);
|
||||
|
||||
byte[] data = message.getBytes(StringUtil.__UTF8);
|
||||
gen.addFrame((byte)0x8,(byte)0x4,data,0,data.length,1000);
|
||||
gen.addFrame((byte)0x8,(byte)0x4,data,0,data.length);
|
||||
|
||||
endp = new ByteArrayEndPoint(endp.getOut().asArray(),4096);
|
||||
|
||||
|
@ -667,7 +667,7 @@ public class WebSocketMessageD06Test
|
|||
|
||||
WebSocketGeneratorD06 gen = new WebSocketGeneratorD06(new WebSocketBuffers(8096),endp,maskGen);
|
||||
byte[] data = message.getBytes(StringUtil.__UTF8);
|
||||
gen.addFrame((byte)0x8,(byte)0x4,data,0,data.length,1000);
|
||||
gen.addFrame((byte)0x8,(byte)0x4,data,0,data.length);
|
||||
|
||||
endp = new ByteArrayEndPoint(endp.getOut().asArray(),4096);
|
||||
|
||||
|
|
|
@ -636,7 +636,7 @@ public class WebSocketMessageD07Test
|
|||
WebSocketGeneratorD07 gen = new WebSocketGeneratorD07(new WebSocketBuffers(8096),endp,null);
|
||||
|
||||
byte[] data = message.getBytes(StringUtil.__UTF8);
|
||||
gen.addFrame((byte)0x8,(byte)0x4,data,0,data.length,1000);
|
||||
gen.addFrame((byte)0x8,(byte)0x4,data,0,data.length);
|
||||
|
||||
endp = new ByteArrayEndPoint(endp.getOut().asArray(),4096);
|
||||
|
||||
|
@ -669,7 +669,7 @@ public class WebSocketMessageD07Test
|
|||
|
||||
WebSocketGeneratorD07 gen = new WebSocketGeneratorD07(new WebSocketBuffers(8096),endp,maskGen);
|
||||
byte[] data = message.getBytes(StringUtil.__UTF8);
|
||||
gen.addFrame((byte)0x8,(byte)0x1,data,0,data.length,1000);
|
||||
gen.addFrame((byte)0x8,(byte)0x1,data,0,data.length);
|
||||
|
||||
endp = new ByteArrayEndPoint(endp.getOut().asArray(),4096);
|
||||
|
||||
|
|
Loading…
Reference in New Issue