Skip to content

Commit dcc3db9

Browse files
committed
-added full framing support fot draft 10 including large messages
-tested on Firefox 6.02 and Crome 14.0.835.187
1 parent 507e5ec commit dcc3db9

9 files changed

+276
-60
lines changed

src/net/tootallnate/websocket/Draft.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ public abstract class Draft{
1616
public final static Charset UTF8_CHARSET = Charset.forName ( "UTF-8" );
1717

1818
public abstract boolean acceptHandshakeAsServer( Handshakedata handshakedata ) throws InvalidHandshakeException;
19-
public abstract boolean acceptHandshakeAsClient( Handshakedata request , Handshakedata response );
20-
public abstract List<Framedata> translateFrame( byte[] buffer, int read );
19+
public abstract boolean acceptHandshakeAsClient( Handshakedata request , Handshakedata response ) throws InvalidHandshakeException;
20+
public abstract List<Framedata> translateFrame( ByteBuffer buffer, int read );
2121
public abstract ByteBuffer createBinaryFrame( Framedata framedata ); //TODO Allow to send data on the base of an Iterator or InputStream
2222
public abstract List<Framedata> createFrames( String text , boolean mask );
2323
public abstract List<Framedata> createFrames( byte[] binary , boolean mask );
@@ -31,7 +31,7 @@ public HandshakeBuilder postProcessHandshakeRequestAsClient( HandshakeBuilder re
3131
public HandshakeBuilder postProcessHandshakeResponseAsServer( Handshakedata request , HandshakeBuilder response ) throws InvalidHandshakeException{
3232
//sb.append ( "HTTP/1.1 101 Switching Protocols\r\n" );
3333
response.put ( "Upgrade" , "websocket" );
34-
response.put ( "Connection" , "Upgrade" );
34+
response.put ( "Connection" , /*"Upgrade"*/request.getFieldValue ( "Connection" ) ); //to respond a Connection keep alives
3535
return response;
3636
}
3737

src/net/tootallnate/websocket/FramedataImpl1.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,21 @@
22

33
import java.nio.ByteBuffer;
44

5+
import net.tootallnate.websocket.exeptions.InvalidFrameException;
6+
57
public class FramedataImpl1 implements FrameBuilder {
8+
private static byte[] emptyarray = {};
69
private boolean fin;
710
private Opcode optcode;
811
private ByteBuffer unmaskedpayload;
912
private boolean transferemasked;
1013

1114
public FramedataImpl1() {
1215
}
16+
public FramedataImpl1( Opcode op ) {
17+
this.optcode = op;
18+
unmaskedpayload = ByteBuffer.wrap ( emptyarray );
19+
}
1320

1421
@Override
1522
public boolean isFin( ) {
@@ -56,7 +63,7 @@ public void setTransferemasked( boolean transferemasked ) {
5663

5764

5865
@Override
59-
public void append( Framedata nextframe ) {
66+
public void append( Framedata nextframe ) throws InvalidFrameException {
6067
if( unmaskedpayload == null ){
6168
unmaskedpayload = ByteBuffer.wrap ( nextframe.getPayloadData () );
6269
}
@@ -67,6 +74,9 @@ public void append( Framedata nextframe ) {
6774
}
6875
}
6976

70-
77+
@Override
78+
public String toString( ) {
79+
return "Framedata{ optcode:" + getOpcode() + ", fin:" + isFin() + ", masked:" + getTransfereMasked() +", payload:" + new String ( unmaskedpayload.array () , Draft.UTF8_CHARSET ) + "}" ;
80+
}
7181

7282
}

src/net/tootallnate/websocket/WebSocket.java

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@
77
import java.nio.charset.Charset;
88
import java.security.NoSuchAlgorithmException;
99
import java.util.ArrayList;
10-
import java.util.HashMap;
1110
import java.util.List;
11+
12+
import net.tootallnate.websocket.Framedata.Opcode;
1213
import net.tootallnate.websocket.drafts.*;
1314
import net.tootallnate.websocket.exeptions.InvalidFrameException;
1415
import net.tootallnate.websocket.exeptions.InvalidHandshakeException;
@@ -59,7 +60,7 @@ public enum Role{
5960
*/
6061
public static final byte END_OF_FRAME = (byte)0xFF;
6162

62-
public static final boolean DEBUG = true;
63+
public static final boolean DEBUG = false;
6364

6465

6566
// INSTANCE PROPERTIES /////////////////////////////////////////////////////
@@ -102,6 +103,8 @@ public enum Role{
102103
private Handshakedata handshakerequest = null;
103104

104105
public List<Draft> known_drafts;
106+
107+
private final int maxpayloadsize;
105108

106109

107110
// CONSTRUCTOR /////////////////////////////////////////////////////////////
@@ -115,24 +118,26 @@ public enum Role{
115118
* @param listener The {@link WebSocketListener} to notify of events when
116119
* they occur.
117120
*/
118-
WebSocket(SocketChannel socketChannel, BlockingQueue<ByteBuffer> bufferQueue, WebSocketListener listener, Draft draft) {
121+
WebSocket(SocketChannel socketChannel, BlockingQueue<ByteBuffer> bufferQueue, WebSocketListener listener, Draft draft, int maxpayloadsize) {
119122
this.socketChannel = socketChannel;
120123
this.bufferQueue = bufferQueue;
121124
this.handshakeComplete = false;
122125
this.socketBuffer = ByteBuffer.allocate(8192);
123126
this.wsl = listener;
124127
this.role = Role.CLIENT;
125128
this.draft = draft;
129+
this.maxpayloadsize = maxpayloadsize;
126130
}
127131

128-
WebSocket(SocketChannel socketChannel, BlockingQueue<ByteBuffer> bufferQueue, WebSocketListener listener, List<Draft> drafts ) {
132+
WebSocket(SocketChannel socketChannel, BlockingQueue<ByteBuffer> bufferQueue, WebSocketListener listener, List<Draft> drafts , int maxpayloadsize ) {
129133
this.socketChannel = socketChannel;
130134
this.bufferQueue = bufferQueue;
131135
this.handshakeComplete = false;
132136
this.socketBuffer = ByteBuffer.allocate(8192);
133137
this.wsl = listener;
134138
this.role = Role.SERVER;
135139
this.draft = null;
140+
this.maxpayloadsize = maxpayloadsize;
136141
if( known_drafts == null || known_drafts.isEmpty () ){
137142
known_drafts = new ArrayList<Draft> ( 1 );
138143
known_drafts.add ( new Draft_10 () );
@@ -158,9 +163,14 @@ void handleRead() throws IOException, NoSuchAlgorithmException {
158163
bytesRead = this.socketChannel.read(this.socketBuffer);
159164

160165

161-
if (bytesRead == -1) {
166+
if ( bytesRead == -1 ) {
162167
close();
163-
} else if (bytesRead > 0) {
168+
}
169+
else if( bytesRead > maxpayloadsize ){
170+
wsl.onError ( new RuntimeException("recived packet to big") );
171+
abort ( "recived packet to big" );
172+
}
173+
else if ( bytesRead > 0) {
164174
if(DEBUG) System.out.println( "got: {" + new String( socketBuffer.array() , 0 , bytesRead ) + "}" );
165175
if( !handshakeComplete ){
166176
try{
@@ -199,17 +209,38 @@ else if( role == Role.CLIENT){
199209
}
200210
}
201211
else{
202-
List<Framedata> frames = draft.translateFrame ( socketBuffer.array () , bytesRead );
212+
List<Framedata> frames = draft.translateFrame ( socketBuffer , bytesRead );
203213
for( Framedata f : frames){
214+
Opcode curop = f.getOpcode ();
215+
if( curop == null )// Ignore undefined opcodes
216+
continue;
217+
else if( curop == Opcode.CLOSING){
218+
sendFrame ( new FramedataImpl1 ( Opcode.CLOSING ) );
219+
close();
220+
}
221+
else if( curop == Opcode.PING){
222+
sendFrame ( new FramedataImpl1 ( Opcode.PONG ) );
223+
}
224+
else if( curop == Opcode.PONG){
225+
wsl.onPong ();
226+
}
204227
if( currentframe == null){
205228
if( f.isFin () ){
206-
wsl.onMessage ( this , new String ( f.getPayloadData () , UTF8_CHARSET ) );
229+
if( f.getOpcode () == Opcode.TEXT ){
230+
wsl.onMessage ( this , new String ( f.getPayloadData () , UTF8_CHARSET ) );
231+
}
232+
else if( f.getOpcode () == Opcode.BINARY ){
233+
wsl.onMessage ( this , f.getPayloadData () );
234+
}
235+
else{
236+
if(DEBUG) System.out.println ( "Ignoring frame:" + f.toString() );
237+
}
207238
}
208239
else{
209240
currentframe = f;
210241
}
211242
}
212-
else{
243+
else if( f.getOpcode() == Opcode.CONTINIOUS ){
213244
try {
214245
currentframe.append ( f );
215246
} catch ( InvalidFrameException e ) {

src/net/tootallnate/websocket/WebSocketAdapter.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,12 @@ public void onClose( WebSocket conn ) {
3030
@Override
3131
public void onError( Throwable ex ) {
3232
}
33+
34+
@Override
35+
public void onMessage( WebSocket conn , byte[] blob ) {
36+
}
37+
38+
@Override
39+
public void onPong( ) {
40+
}
3341
}

src/net/tootallnate/websocket/WebSocketClient.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ private boolean tryToConnect(InetSocketAddress remote) {
179179

180180
selector = Selector.open();
181181

182-
this.conn = new WebSocket( client , new LinkedBlockingQueue<ByteBuffer>() , this , draft );
182+
this.conn = new WebSocket( client , new LinkedBlockingQueue<ByteBuffer>() , this , draft , Integer.MAX_VALUE );
183183
// the client/selector can be null when closing the connection before its start
184184
// so we have to call this part inside IF
185185
if (client != null)

src/net/tootallnate/websocket/WebSocketListener.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ interface WebSocketListener {
2626
*/
2727
public void onMessage(WebSocket conn, String message);
2828

29+
public void onMessage( WebSocket conn , byte[] blob );
30+
2931
/**
3032
* Called after <var>onHandshakeRecieved</var> returns <var>true</var>.
3133
* Indicates that a complete WebSocket connection has been established,
@@ -47,4 +49,6 @@ interface WebSocketListener {
4749
* @param ex
4850
*/
4951
public void onError( Throwable ex );
52+
53+
public void onPong();
5054
}

src/net/tootallnate/websocket/WebSocketServer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ public void run() {
221221
if (key.isAcceptable()) {
222222
SocketChannel client = server.accept();
223223
client.configureBlocking(false);
224-
WebSocket c = new WebSocket(client, new LinkedBlockingQueue<ByteBuffer>(), this, Collections.singletonList ( draft ) );
224+
WebSocket c = new WebSocket(client, new LinkedBlockingQueue<ByteBuffer>(), this, Collections.singletonList ( draft ) , Integer.MAX_VALUE );
225225
client.register(selector, SelectionKey.OP_READ, c);
226226
}
227227

0 commit comments

Comments
 (0)