diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/WebSocketUpgradeTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/WebSocketUpgradeTest.java index fd1974edf35..02d2469181f 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/WebSocketUpgradeTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/WebSocketUpgradeTest.java @@ -94,6 +94,10 @@ public class WebSocketUpgradeTest extends TestCase public void onMessage(byte frame, byte[] data, int offset, int length) { } + + public void onFragment(boolean more, byte opcode, byte[] data, int offset, int length) + { + } }; @@ -245,5 +249,9 @@ public class WebSocketUpgradeTest extends TestCase { _outbound.sendMessage(msg); } + + public void onFragment(boolean more, byte opcode, byte[] data, int offset, int length) + { + } } } diff --git a/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocket.java b/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocket.java index 05a5106c2e1..c94d2f2b56d 100644 --- a/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocket.java +++ b/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocket.java @@ -7,16 +7,17 @@ public interface WebSocket public final byte LENGTH_FRAME=(byte)0x80; public final byte SENTINEL_FRAME=(byte)0x00; void onConnect(Outbound outbound); - void onMessage(byte frame,String data); - void onMessage(byte frame,byte[] data, int offset, int length); + void onMessage(byte opcode,String data); + void onFragment(boolean more,byte opcode,byte[] data, int offset, int length); + void onMessage(byte opcode,byte[] data, int offset, int length); void onDisconnect(); public interface Outbound { void sendMessage(String data) throws IOException; - void sendMessage(byte frame,String data) throws IOException; - void sendMessage(byte frame,byte[] data) throws IOException; - void sendMessage(byte frame,byte[] data, int offset, int length) throws IOException; + void sendMessage(byte opcode,String data) throws IOException; + void sendMessage(byte opcode,byte[] data, int offset, int length) throws IOException; + void sendFragment(boolean more,byte opcode,byte[] data, int offset, int length) throws IOException; void disconnect(); boolean isOpen(); } diff --git a/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketConnection.java b/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketConnection.java index bb1ff2359d0..edc7c2b1973 100644 --- a/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketConnection.java +++ b/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketConnection.java @@ -3,10 +3,7 @@ package org.eclipse.jetty.websocket; import java.io.IOException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.util.zip.Checksum; -import org.eclipse.jetty.http.HttpParser; -import org.eclipse.jetty.http.security.Credential.MD5; import org.eclipse.jetty.io.AsyncEndPoint; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.ByteArrayBuffer; @@ -14,10 +11,8 @@ import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.nio.IndirectNIOBuffer; import org.eclipse.jetty.io.nio.SelectChannelEndPoint; -import org.eclipse.jetty.util.TypeUtil; import org.eclipse.jetty.util.Utf8StringBuilder; import org.eclipse.jetty.util.log.Log; -import org.eclipse.jetty.util.thread.Timeout; public class WebSocketConnection implements Connection, WebSocket.Outbound { @@ -51,6 +46,7 @@ public class WebSocketConnection implements Connection, WebSocket.Outbound _websocket = websocket; final WebSocketParser.FrameHandler handler = new WebSocketParser.FrameHandler() { + boolean _fragmented=false; Utf8StringBuilder _utf8 = new Utf8StringBuilder(); public void onFrame(boolean more, byte flags, byte opcode, Buffer buffer) @@ -62,21 +58,36 @@ public class WebSocketConnection implements Connection, WebSocket.Outbound if (opcode==0) { if (more) + { _utf8.append(buffer.array(),buffer.getIndex(),buffer.length()); - else if (_utf8.length()==0) - _websocket.onMessage(opcode,buffer.toString("utf-8")); - else + _fragmented=true; + } + else if (_fragmented) { _utf8.append(buffer.array(),buffer.getIndex(),buffer.length()); _websocket.onMessage(opcode,_utf8.toString()); _utf8.reset(); + _fragmented=false; + } + else + { + _websocket.onMessage(opcode,buffer.toString("utf-8")); } } else { if (more) - throw new IllegalStateException("not implemented"); - _websocket.onMessage(opcode,array,buffer.getIndex(),buffer.length()); + { + _websocket.onFragment(true,opcode,array,buffer.getIndex(),buffer.length()); + } + else if (_fragmented) + { + _websocket.onFragment(false,opcode,array,buffer.getIndex(),buffer.length()); + } + else + { + _websocket.onMessage(opcode,array,buffer.getIndex(),buffer.length()); + } } } catch(ThreadDeath th) @@ -262,14 +273,17 @@ public class WebSocketConnection implements Connection, WebSocket.Outbound _idle.access(_endp); } - public void sendMessage(byte frame, byte[] content) throws IOException + public void sendMessage(byte opcode, byte[] content, int offset, int length) throws IOException { - sendMessage(frame, content, 0, content.length); + _generator.addFrame(opcode,content,offset,length,_endp.getMaxIdleTime()); + _generator.flush(); + checkWriteable(); + _idle.access(_endp); } - public void sendMessage(byte frame, byte[] content, int offset, int length) throws IOException + public void sendFragment(boolean more,byte opcode, byte[] content, int offset, int length) throws IOException { - _generator.addFrame(frame,content,offset,length,_endp.getMaxIdleTime()); + _generator.addFragment(more,opcode,content,offset,length,_endp.getMaxIdleTime()); _generator.flush(); checkWriteable(); _idle.access(_endp); diff --git a/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketGenerator.java b/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketGenerator.java index a081b1061a7..b00e02de3d6 100644 --- a/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketGenerator.java +++ b/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketGenerator.java @@ -13,6 +13,6 @@ public interface WebSocketGenerator boolean isBufferEmpty(); void addFrame(byte opcode, String content, int maxIdleTime) throws IOException; void addFrame(byte opcode, byte[] content, int offset, int length, int maxIdleTime) throws IOException; - void addFrame(byte opcode, byte[] content, int maxIdleTime)throws IOException; + void addFragment(boolean more,byte opcode, byte[] content, int offset, int length, int maxIdleTime) throws IOException; int flush(int maxIdleTime) throws IOException; } diff --git a/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketGeneratorD00.java b/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketGeneratorD00.java index 94925f576fe..c4be5dd0b6c 100644 --- a/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketGeneratorD00.java +++ b/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketGeneratorD00.java @@ -28,12 +28,7 @@ public class WebSocketGeneratorD00 implements WebSocketGenerator _buffers=buffers; _endp=endp; } - - public synchronized void addFrame(byte frame,byte[] content, int blockFor) throws IOException - { - addFrame(frame,content,0,content.length,blockFor); - } - + public synchronized void addFrame(byte opcode,byte[] content, int offset, int length, int blockFor) throws IOException { if (_buffer==null) @@ -164,5 +159,12 @@ public class WebSocketGeneratorD00 implements WebSocketGenerator { return _buffer==null || _buffer.length()==0; } + + public void addFragment(boolean more, byte opcode, byte[] content, int offset, int length, int maxIdleTime) throws IOException + { + if (more) + throw new UnsupportedOperationException("fragmented"); + addFrame(opcode,content,offset,length,maxIdleTime); + } } diff --git a/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketGeneratorD01.java b/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketGeneratorD01.java index 485bd2e3ea5..fc4c35a1940 100644 --- a/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketGeneratorD01.java +++ b/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketGeneratorD01.java @@ -35,8 +35,14 @@ public class WebSocketGeneratorD01 implements WebSocketGenerator { addFrame(opcode,content,0,content.length,blockFor); } + public synchronized void addFrame(byte opcode,byte[] content, int offset, int length, int blockFor) throws IOException + { + addFragment(false,opcode,content,offset,length,blockFor); + } + + public synchronized void addFragment(boolean more, byte opcode, byte[] content, int offset, int length, int blockFor) throws IOException { if (_buffer==null) _buffer=_buffers.getDirectBuffer(); @@ -55,6 +61,8 @@ public class WebSocketGeneratorD01 implements WebSocketGenerator fragment=_buffer.capacity()-10; bufferPut((byte)(0x80|opcode), blockFor); } + else if (more) + bufferPut((byte)(0x80|opcode), blockFor); else bufferPut(opcode, blockFor); @@ -178,4 +186,5 @@ public class WebSocketGeneratorD01 implements WebSocketGenerator { return _buffer==null || _buffer.length()==0; } + } diff --git a/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketGeneratorD00Test.java b/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketGeneratorD00Test.java index f31bf14aebd..31bea9e67ef 100644 --- a/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketGeneratorD00Test.java +++ b/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketGeneratorD00Test.java @@ -56,7 +56,7 @@ public class WebSocketGeneratorD00Test for (int i=0;i