summaryrefslogtreecommitdiff
path: root/chapter18/src
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2024-12-04 14:17:02 -0800
committerCliff Click <cliffc@acm.org>2025-01-15 15:07:30 -0800
commit38f6455c83dd68c80b2f667388d45cf6a28688ee (patch)
treef3f3662706928fc95398354a3268973b13075179 /chapter18/src
parentd2df2a776bf2bd2d382de948d1ad83e54eb38ffc (diff)
downloadSimple-38f6455c83dd68c80b2f667388d45cf6a28688ee.tar.gz
Simple-38f6455c83dd68c80b2f667388d45cf6a28688ee.zip
Better websocket reader
fix bug double-render
Diffstat (limited to 'chapter18/src')
-rw-r--r--chapter18/src/main/java/com/seaofnodes/simple/SimpleWebSocket.java36
1 files changed, 32 insertions, 4 deletions
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/SimpleWebSocket.java b/chapter18/src/main/java/com/seaofnodes/simple/SimpleWebSocket.java
index f9a85d19..1ce766ff 100644
--- a/chapter18/src/main/java/com/seaofnodes/simple/SimpleWebSocket.java
+++ b/chapter18/src/main/java/com/seaofnodes/simple/SimpleWebSocket.java
@@ -55,15 +55,35 @@ class SimpleWebSocket extends ServerSocket {
int _x, _len;
private int rawget() { assert _x<_len; return _ins[_x++]&0xFF; }
+ // TODO: Flip to Direct Byte Buffer, this is just a poor-mans version
+ private void flipRead() throws IOException {
+ // Move _x to _len to offset 0
+ System.arraycopy(_ins,_x,_ins,0,(_len-_x));
+ _len = _len-_x;
+ _x=0;
+ // Read more
+ int len = _in.read(_ins,_len,_ins.length-_len);
+ if( len == -1 )
+ throw Utils.TODO(); // EOF
+ _len += len;
+ }
+ // Block until you read at least len
+ private void atLeast(int len) throws IOException {
+ if( _x+len <= _len ) return;
+ flipRead();
+ }
+
+
// Classic read from browser client. Encoded, so decoded here
public String get() throws IOException {
- _len = _in.read(_ins); _x=0;
+ atLeast(1); // Need 1 byte for opcode
int op = rawget();
- if( (op&0x80)!=0x80 ) // FIN bit not set?
- throw Utils.TODO("Multi-part from client: "+op); // Multipart message
- op &= 0x7F; // Strip FIN bit
+ if( (op&0x80)!=0x80 ) // FIN bit not set?
+ throw Utils.TODO( "Multi-part from client: " + op ); // Multipart message
+ op &= 0x7F; // Strip FIN bit
switch( op&15) {
case 1: {
+ atLeast(5); // Min message length
// Message length
int len = rawget()-128;
if( len > 125 ) {
@@ -71,11 +91,13 @@ class SimpleWebSocket extends ServerSocket {
throw Utils.TODO(); // Multi-byte length
len = (rawget()<<8) | rawget();
}
+ atLeast(len+4); // Rest of message
// Encoding key
_key[0] = (byte)rawget();
_key[1] = (byte)rawget();
_key[2] = (byte)rawget();
_key[3] = (byte)rawget();
+
// Decode bytes
for( int i=0; i<len; i++ )
_str[i] = (byte)(rawget() ^ _key[i & 3]);
@@ -84,6 +106,12 @@ class SimpleWebSocket extends ServerSocket {
}
// Client closes
case 8: return null;
+ // Ping
+ case 9:
+ // Send a PONG back. TODO: echo PING data in the PONG
+ _out.write(0x8A); // FIN + PONG
+ _out.write(0x00); // LENGTH==0
+ return get();
// Not (yet) implemented: continuation frames, ping/pong
default:
throw Utils.TODO("Unexpected op from client: "+op); // Multi-part message