Skip to content

Commit 53395cc

Browse files
committed
-better approximation towards the standard
-fixed draft10 framing of big messages -organized imports -minor changes
1 parent 816e384 commit 53395cc

7 files changed

Lines changed: 52 additions & 38 deletions

File tree

‎src/net/tootallnate/websocket/Draft.java‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import java.util.Collections;
77
import java.util.Iterator;
88
import java.util.List;
9+
import java.util.Locale;
910

1011
import net.tootallnate.websocket.WebSocket.Role;
1112
import net.tootallnate.websocket.exeptions.InvalidHandshakeException;
@@ -38,6 +39,7 @@ public static int findNewLine( byte[] arr , int offset ) {
3839
return i;
3940
return i;//the end of input will be handled like newline
4041
}
42+
4143
public static boolean isFlashEdgeCase( byte[] request , int requestsize ){
4244
for( int i = 0 ; i < requestsize && i < FLASH_POLICY_REQUEST.length ; i++ ){
4345
if( FLASH_POLICY_REQUEST[i] != request[i] ){
@@ -46,6 +48,7 @@ public static boolean isFlashEdgeCase( byte[] request , int requestsize ){
4648
}
4749
return requestsize >= FLASH_POLICY_REQUEST.length;
4850
}
51+
4952
public static HandshakeBuilder translateHandshakeHttp( byte[] buffer, int readcount ) throws InvalidHandshakeException{
5053
HandshakedataImpl1 draft = new HandshakedataImpl1();
5154

@@ -85,10 +88,20 @@ public static HandshakeBuilder translateHandshakeHttp( byte[] buffer, int readco
8588
draft.setContent ( ByteBuffer.allocate ( length ).put ( lines, previndex , length ).array () );
8689
return draft;
8790
}
91+
8892
public abstract HandshakeState acceptHandshakeAsClient( Handshakedata request , Handshakedata response ) throws InvalidHandshakeException;
93+
8994
public abstract HandshakeState acceptHandshakeAsServer( Handshakedata handshakedata ) throws InvalidHandshakeException;
95+
96+
protected boolean basicAccept( Handshakedata handshakedata ){
97+
return handshakedata.getFieldValue( "Upgrade" ).equalsIgnoreCase( "websocket" )
98+
&& handshakedata.getFieldValue( "Connection" ).toLowerCase( Locale.ENGLISH ).contains( "upgrade" );
99+
}
100+
90101
public abstract ByteBuffer createBinaryFrame( Framedata framedata ); //TODO Allow to send data on the base of an Iterator or InputStream
102+
91103
public abstract List<Framedata> createFrames( byte[] binary , boolean mask );
104+
92105
public abstract List<Framedata> createFrames( String text , boolean mask );
93106

94107
public List<ByteBuffer> createHandshake( Handshakedata handshakedata , Role ownrole ){

‎src/net/tootallnate/websocket/FramedataImpl1.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ public void append( Framedata nextframe ) throws InvalidFrameException {
7676

7777
@Override
7878
public String toString( ) {
79-
return "Framedata{ optcode:" + getOpcode() + ", fin:" + isFin() + ", masked:" + getTransfereMasked() +", payload:" + new String ( unmaskedpayload.array () , Draft.UTF8_CHARSET ) + "}" ;
79+
return "Framedata{ optcode:" + getOpcode() + ", fin:" + isFin() + ", masked:" + getTransfereMasked() +", payloadlength:"+unmaskedpayload.limit()+", payload:" + new String ( unmaskedpayload.array () , Draft.UTF8_CHARSET ) + "}" ;
8080
}
8181

8282
}

‎src/net/tootallnate/websocket/WebSocket.java‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ public enum Role{
125125
* @param listener The {@link WebSocketListener} to notify of events when
126126
* they occur.
127127
*/
128-
WebSocket(SocketChannel socketChannel, BlockingQueue<ByteBuffer> bufferQueue, WebSocketListener listener, Draft draft, int maxpayloadsize) {
128+
public WebSocket(SocketChannel socketChannel, BlockingQueue<ByteBuffer> bufferQueue, WebSocketListener listener, Draft draft, int maxpayloadsize) {
129129
this.socketChannel = socketChannel;
130130
this.bufferQueue = bufferQueue;
131131
this.handshakeComplete = false;
@@ -136,7 +136,7 @@ public enum Role{
136136
this.maxpayloadsize = maxpayloadsize;
137137
}
138138

139-
WebSocket(SocketChannel socketChannel, BlockingQueue<ByteBuffer> bufferQueue, WebSocketListener listener, List<Draft> drafts , int maxpayloadsize ) {
139+
public WebSocket(SocketChannel socketChannel, BlockingQueue<ByteBuffer> bufferQueue, WebSocketListener listener, List<Draft> drafts , int maxpayloadsize ) {
140140
this.socketChannel = socketChannel;
141141
this.bufferQueue = bufferQueue;
142142
this.handshakeComplete = false;
@@ -147,6 +147,7 @@ public enum Role{
147147
this.maxpayloadsize = maxpayloadsize;
148148
if( known_drafts == null || known_drafts.isEmpty () ){
149149
known_drafts = new ArrayList<Draft> ( 1 );
150+
known_drafts.add ( new Draft_17 () );
150151
known_drafts.add ( new Draft_10 () );
151152
known_drafts.add ( new Draft_76 () );
152153
known_drafts.add ( new Draft_75 () );
@@ -162,7 +163,7 @@ public enum Role{
162163
* @throws IOException When socket related I/O errors occur.
163164
* @throws NoSuchAlgorithmException
164165
*/
165-
void handleRead() throws IOException, NoSuchAlgorithmException {
166+
public void handleRead() throws IOException, NoSuchAlgorithmException {
166167

167168
int bytesRead = -1;
168169

@@ -303,6 +304,7 @@ else if( f.getOpcode() == Opcode.CONTINIOUS ){
303304
public void abort( ) throws IOException {
304305
abort ( "" );
305306
}
307+
306308
public void abort( String problemmessage ) throws IOException {
307309
if(DEBUG){
308310
System.out.println ( "Aborting: " + problemmessage );

‎src/net/tootallnate/websocket/drafts/Draft_10.java‎

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package net.tootallnate.websocket.drafts;
22
import java.math.BigInteger;
3-
import java.nio.Buffer;
43
import java.nio.ByteBuffer;
5-
import java.nio.charset.Charset;
64
import java.security.MessageDigest;
75
import java.security.NoSuchAlgorithmException;
86
import java.util.Collections;
@@ -46,12 +44,13 @@ public static int readVersion(Handshakedata handshakedata){
4644
}
4745
return -1;
4846
}
47+
4948
private ByteBuffer incompleteframe;
5049

5150
@Override
5251
public HandshakeState acceptHandshakeAsClient( Handshakedata request , Handshakedata response ) throws InvalidHandshakeException {
5352
if ( !request.hasFieldValue( "Sec-WebSocket-Key" ) || !response.hasFieldValue( "Sec-WebSocket-Accept" ) )
54-
throw new InvalidHandshakeException ( "missing Sec-WebSocket-Key" );
53+
return HandshakeState.NOT_MATCHED;
5554

5655
String seckey_answere = response.getFieldValue ( "Sec-WebSocket-Accept" );
5756
String seckey_challenge = request.getFieldValue ( "Sec-WebSocket-Key" );
@@ -64,10 +63,10 @@ public HandshakeState acceptHandshakeAsClient( Handshakedata request , Handshake
6463

6564
@Override
6665
public HandshakeState acceptHandshakeAsServer( Handshakedata handshakedata ) throws InvalidHandshakeException {
67-
//TODO Do a more detailed formal handshake test
66+
//Sec-WebSocket-Origin is only required for browser clients
6867
int v = readVersion( handshakedata );
6968
if( v == 7 || v == 8 )//g
70-
return HandshakeState.MATCHED;
69+
return basicAccept( handshakedata ) ? HandshakeState.MATCHED : HandshakeState.NOT_MATCHED;
7170
return HandshakeState.NOT_MATCHED;
7271
}
7372

@@ -105,7 +104,7 @@ else if( sizebytes == 8 ){
105104

106105
if( mask ){
107106
ByteBuffer maskkey = ByteBuffer.allocate ( 4 );
108-
maskkey.putInt ( Integer.MIN_VALUE );
107+
maskkey.putInt ( new Random().nextInt() );
109108
buf.put ( maskkey.array () );
110109
for( int i = 0 ; i < mes.length ; i++){
111110
buf.put( ( byte ) ( mes[i] ^ maskkey.get ( i % 4 ) ) );
@@ -170,7 +169,7 @@ public HandshakeBuilder postProcessHandshakeRequestAsClient( HandshakeBuilder re
170169

171170
byte[] random = new byte[16];
172171
new Random().nextBytes( random );
173-
request.put( "Sec-WebSocket-Key" , new BASE64Encoder ().encode ( random ) );
172+
request.put( "Sec-WebSocket-Key" , new BASE64Encoder().encode ( random ) );
174173

175174
return request;
176175
}
@@ -223,18 +222,26 @@ public List<Framedata> translateFrame( ByteBuffer buffer , int available ) {
223222
Framedata cur;
224223

225224
if( incompleteframe != null){
226-
int keptformlastsegment = incompleteframe.limit(); //the number of bytes kept from the previous segments, belonging to incomplete frame
227225
while(true){
228226
try {
229-
int ext = incompleteframe.limit () - keptformlastsegment; //the growth of this incomplete frame
230-
if( incompleteframe.remaining () > buffer.limit () - ext ){
231-
return frames; //the given segment is to small to complete the incomplete frame ; awaiting more segments
227+
int available_next_byte_count = available;// The number of bytes received
228+
int expected_next_byte_count = incompleteframe.remaining();// The number of bytes to complete the incomplete frame
229+
230+
if( expected_next_byte_count > available_next_byte_count ){
231+
//did not receive enough bytes to complete the frame
232+
incompleteframe.put( buffer.array() , 0 , available_next_byte_count );
233+
//assert( buffer.limit() == available_next_byte_count + buffer.position() );
234+
//buffer.position( available );
235+
return frames;
232236
}
233-
int frombuffer = incompleteframe.remaining();
234-
incompleteframe.put( buffer.array() , ext , frombuffer );
237+
238+
incompleteframe.put( buffer.array() , 0 , expected_next_byte_count );
239+
//buffer.position( buffer.position() + expected_next_byte_count );
240+
235241
cur = translateSingleFrame ( incompleteframe , 0 , incompleteframe.limit () );
242+
System.out.println(cur);
236243
frames.add ( cur );
237-
offset = ext + frombuffer;
244+
offset = expected_next_byte_count;
238245
incompleteframe = null;
239246
break; // go on with the normal frame receival
240247
} catch ( IncompleteException e ) {

‎src/net/tootallnate/websocket/drafts/Draft_17.java‎

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
package net.tootallnate.websocket.drafts;
22

3-
import java.util.Random;
4-
5-
import com.sun.org.apache.regexp.internal.recompile;
3+
import java.nio.ByteBuffer;
64

5+
import net.tootallnate.websocket.Framedata;
76
import net.tootallnate.websocket.HandshakeBuilder;
87
import net.tootallnate.websocket.Handshakedata;
9-
import net.tootallnate.websocket.Draft.HandshakeState;
108
import net.tootallnate.websocket.exeptions.InvalidHandshakeException;
11-
import sun.misc.BASE64Encoder;
129

1310
public class Draft_17 extends Draft_10 {
1411
@Override
@@ -25,4 +22,5 @@ public HandshakeBuilder postProcessHandshakeRequestAsClient( HandshakeBuilder re
2522
request.put ( "Sec-WebSocket-Version" , "13" );//overwriting the previous
2623
return request;
2724
}
25+
2826
}

‎src/net/tootallnate/websocket/drafts/Draft_75.java‎

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,17 @@
22

33

44
import java.nio.ByteBuffer;
5-
import java.nio.charset.Charset;
6-
75
import java.util.Collections;
8-
import java.util.Iterator;
96
import java.util.LinkedList;
107
import java.util.List;
118

129
import net.tootallnate.websocket.Draft;
1310
import net.tootallnate.websocket.FrameBuilder;
1411
import net.tootallnate.websocket.Framedata;
1512
import net.tootallnate.websocket.Framedata.Opcode;
13+
import net.tootallnate.websocket.FramedataImpl1;
1614
import net.tootallnate.websocket.HandshakeBuilder;
1715
import net.tootallnate.websocket.Handshakedata;
18-
import net.tootallnate.websocket.FramedataImpl1;
1916
import net.tootallnate.websocket.exeptions.InvalidHandshakeException;
2017

2118
public class Draft_75 extends Draft {
@@ -44,18 +41,16 @@ public class Draft_75 extends Draft {
4441
@Override
4542
public HandshakeState acceptHandshakeAsClient( Handshakedata request , Handshakedata response ) {
4643
return request.getFieldValue( "WebSocket-Origin" ).equals( response.getFieldValue( "Origin" ) )
47-
&& response.getFieldValue( "Upgrade" ).equals( "WebSocket" )
48-
&& response.getFieldValue( "Connection" ).contains( "Upgrade"
49-
)?
50-
HandshakeState.MATCHED
51-
:HandshakeState.NOT_MATCHED;
44+
&& basicAccept( response )
45+
?
46+
HandshakeState.MATCHED
47+
:HandshakeState.NOT_MATCHED;
5248
}
5349

5450
@Override
5551
public HandshakeState acceptHandshakeAsServer( Handshakedata handshakedata ) {
56-
if( handshakedata.getFieldValue( "Upgrade" ).equals( "WebSocket" )
57-
&& handshakedata.getFieldValue( "Connection" ).contains( "Upgrade" )
58-
&& handshakedata.hasFieldValue( "Origin" )
52+
if( handshakedata.hasFieldValue( "Origin" )
53+
&& basicAccept( handshakedata )
5954
){
6055
return HandshakeState.MATCHED;
6156
}

‎src/net/tootallnate/websocket/drafts/Draft_76.java‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,8 @@ public HandshakeState acceptHandshakeAsClient( Handshakedata request , Handshake
101101
}
102102

103103
try {
104-
if( !response.getFieldValue( "Upgrade" ).equals( "WebSocket" )
105-
&& !response.getFieldValue( "Connection" ).contains( "Upgrade" )
106-
&& !response.getFieldValue( "Sec-WebSocket-Origin" ).equals( request.getFieldValue( "Origin" ) )
104+
if( !response.getFieldValue( "Sec-WebSocket-Origin" ).equals( request.getFieldValue( "Origin" ) )
105+
|| !basicAccept( response )
107106
){
108107
return HandshakeState.NOT_MATCHED;
109108
}

0 commit comments

Comments
 (0)