diff --git a/src/zoo/websocket/common/src/main/java/org/tio/websocket/common/WsClientDecoder.java b/src/zoo/websocket/common/src/main/java/org/tio/websocket/common/WsClientDecoder.java index 325e782c..bcd643c6 100644 --- a/src/zoo/websocket/common/src/main/java/org/tio/websocket/common/WsClientDecoder.java +++ b/src/zoo/websocket/common/src/main/java/org/tio/websocket/common/WsClientDecoder.java @@ -7,168 +7,102 @@ import org.tio.core.utils.ByteBufferUtils; import java.nio.ByteBuffer; - + public class WsClientDecoder { - public static enum Step { - header, remain_header, data, - } - - private static Logger log = LoggerFactory.getLogger(WsClientDecoder.class); - - public static WsResponse decode(ByteBuffer buf, ChannelContext channelContext) throws AioDecodeException { - // WsSessionContext imSessionContext = (WsSessionContext) channelContext.getAttribute(); - // List<byte[]> lastParts = imSessionContext.getLastParts(); - - // 第一阶段解析 - int initPosition = buf.position(); - int readableLength = buf.limit() - initPosition; - - int headLength = WsPacket.MINIMUM_HEADER_LENGTH; - - if (readableLength < headLength) { - return null; - } - - byte first = buf.get(); - // int b = first & 0xFF; //转换成32位 - boolean fin = (first & 0x80) > 0; // 得到第8位 10000000>0 - @SuppressWarnings("unused") - int rsv = (first & 0x70) >>> 4; // 得到5、6、7 为01110000 然后右移四位为00000111 - byte opCodeByte = (byte) (first & 0x0F); // 后四位为opCode 00001111 - Opcode opcode = Opcode.valueOf(opCodeByte); - if (opcode == Opcode.CLOSE) { - // Tio.remove(channelContext, "收到opcode:" + opcode); - // return null; - } - // if (!fin) { - // log.error("{} 暂时不支持fin为false的请求", channelContext); - // Tio.remove(channelContext, "暂时不支持fin为false的请求"); - // return null; - // //下面这段代码不要删除,以后若支持fin,则需要的 - // // if (lastParts == null) { - // // lastParts = new ArrayList<>(); - // // imSessionContext.setLastParts(lastParts); - // // } - // } else { - // imSessionContext.setLastParts(null); - // } - - byte second = buf.get(); // 向后读取一个字节 - boolean hasMask = (second & 0xFF) >> 7 == 1; // 用于标识PayloadData是否经过掩码处理。如果是1,Masking-key域的数据即是掩码密钥,用于解码PayloadData。客户端发出的数据帧需要进行掩码处理,所以此位是1。 - - // Client data must be masked - if (!hasMask) { // 第9为为mask,必须为1 - // throw new AioDecodeException("websocket client data must be masked"); - } else { - headLength += 4; - } - int payloadLength = second & 0x7F; // 读取后7位 Payload legth,如果<126则payloadLength - - byte[] mask = null; - if (payloadLength == 126) { // 为126读2个字节,后两个字节为payloadLength - headLength += 2; - if (readableLength < headLength) { - return null; - } - payloadLength = ByteBufferUtils.readUB2WithBigEdian(buf); - log.info("{} payloadLengthFlag: 126,payloadLength {}", channelContext, payloadLength); - - } else if (payloadLength == 127) { // 127读8个字节,后8个字节为payloadLength - headLength += 8; - if (readableLength < headLength) { - return null; - } - - payloadLength = (int) buf.getLong(); - log.info("{} payloadLengthFlag: 127,payloadLength {}", channelContext, payloadLength); - } - - if (payloadLength < 0 || payloadLength > WsPacket.MAX_BODY_LENGTH) { - throw new AioDecodeException("body length(" + payloadLength + ") is not right"); - } - - if (readableLength < headLength + payloadLength) { - return null; - } - - if (hasMask) { - mask = ByteBufferUtils.readBytes(buf, 4); - } - - // 第二阶段解析 - WsResponse websocketPacket = new WsResponse(); - websocketPacket.setWsEof(fin); - websocketPacket.setWsHasMask(hasMask); - websocketPacket.setWsMask(mask); - websocketPacket.setWsOpcode(opcode); - websocketPacket.setWsBodyLength(payloadLength); - - if (payloadLength == 0) { - return websocketPacket; - } - - byte[] array = ByteBufferUtils.readBytes(buf, payloadLength); - if (hasMask) { - for (int i = 0; i < array.length; i++) { - array[i] = (byte) (array[i] ^ mask[i % 4]); - } - } - - websocketPacket.setBody(array); - - // if (!fin) { - // //lastParts.add(array); - // log.error("payloadLength {}, lastParts size {}, array length {}", payloadLength, - // lastParts.size(), array.length); - // return websocketPacket; - // } else { - // int allLength = array.length; - // if (lastParts != null) { - // for (byte[] part : lastParts) { - // allLength += part.length; - // } - // byte[] allByte = new byte[allLength]; - // - // int offset = 0; - // for (byte[] part : lastParts) { - // System.arraycopy(part, 0, allByte, offset, part.length); - // offset += part.length; - // } - // System.arraycopy(array, 0, allByte, offset, array.length); - // array = allByte; - // } - // - // websocketPacket.setBody(array); - // - // if (opcode == Opcode.BINARY) { - // - // } else { - // try { - // String text = null; - // text = new String(array, WsPacket.CHARSET_NAME); - // websocketPacket.setWsBodyText(text); - // } catch (UnsupportedEncodingException e) { - // log.error(e.toString(), e); - // } - // } - // } - -// if (fin && opcode != null) { -// if (opcode == Opcode.BINARY) { -// -// } else { -// try { -// String text = new String(array, WsPacket.CHARSET_NAME); -// websocketPacket.setWsBodyText(text); -// } catch (UnsupportedEncodingException e) { -// log.error(e.toString(), e); -// } -// } -// } - return websocketPacket; - } - - /** @author tanyaowu 2017年2月22日 下午4:06:42 */ - public WsClientDecoder() { - } + + private static Logger log = LoggerFactory.getLogger(WsClientDecoder.class); + + public static WsResponse decode(ByteBuffer buf, ChannelContext channelContext) + throws AioDecodeException { + // 第一阶段解析 + int initPosition = buf.position(); + int readableLength = buf.limit() - initPosition; + + int headLength = WsPacket.MINIMUM_HEADER_LENGTH; + + if (readableLength < headLength) { + return null; + } + + byte first = buf.get(); + // int b = first & 0xFF; //转换成32位 + boolean fin = (first & 0x80) > 0; // 得到第8位 10000000>0 + @SuppressWarnings("unused") + int rsv = (first & 0x70) >>> 4; // 得到5、6、7 为01110000 然后右移四位为00000111 + byte opCodeByte = (byte) (first & 0x0F); // 后四位为opCode 00001111 + Opcode opcode = Opcode.valueOf(opCodeByte); + if (opcode == Opcode.CLOSE) { + // Tio.remove(channelContext, "收到opcode:" + opcode); + // return null; + } + + byte second = buf.get(); // 向后读取一个字节 + boolean hasMask = + (second & 0xFF) >> 7 + == 1; // 用于标识PayloadData是否经过掩码处理。如果是1,Masking-key域的数据即是掩码密钥,用于解码PayloadData。客户端发出的数据帧需要进行掩码处理,所以此位是1。 + + // Client data must be masked + if (!hasMask) { // 第9为为mask,必须为1 + // throw new AioDecodeException("websocket client data must be masked"); + } else { + headLength += 4; + } + int payloadLength = second & 0x7F; // 读取后7位 Payload legth,如果<126则payloadLength + + byte[] mask = null; + if (payloadLength == 126) { // 为126读2个字节,后两个字节为payloadLength + headLength += 2; + if (readableLength < headLength) { + return null; + } + payloadLength = ByteBufferUtils.readUB2WithBigEdian(buf); + log.info("{} payloadLengthFlag: 126,payloadLength {}", channelContext, payloadLength); + + } else if (payloadLength == 127) { // 127读8个字节,后8个字节为payloadLength + headLength += 8; + if (readableLength < headLength) { + return null; + } + + payloadLength = (int) buf.getLong(); + log.info("{} payloadLengthFlag: 127,payloadLength {}", channelContext, payloadLength); + } + + if (payloadLength < 0 ) { + throw new AioDecodeException("body length(" + payloadLength + ") is not right"); + } + + if (readableLength < headLength + payloadLength) { + return null; + } + + if (hasMask) { + mask = ByteBufferUtils.readBytes(buf, 4); + } + + // 第二阶段解析 + WsResponse websocketPacket = new WsResponse(); + websocketPacket.setWsEof(fin); + websocketPacket.setWsHasMask(hasMask); + websocketPacket.setWsMask(mask); + websocketPacket.setWsOpcode(opcode); + websocketPacket.setWsBodyLength(payloadLength); + + if (payloadLength == 0) { + return websocketPacket; + } + + byte[] array = ByteBufferUtils.readBytes(buf, payloadLength); + if (hasMask) { + for (int i = 0; i < array.length; i++) { + array[i] = (byte) (array[i] ^ mask[i % 4]); + } + } + + websocketPacket.setBody(array); + return websocketPacket; + } + + /** @author tanyaowu 2017年2月22日 下午4:06:42 */ + public WsClientDecoder() {} } diff --git a/src/zoo/websocket/common/src/main/java/org/tio/websocket/common/WsClientEncoder.java b/src/zoo/websocket/common/src/main/java/org/tio/websocket/common/WsClientEncoder.java index 3632cb38..9a4d9a5d 100644 --- a/src/zoo/websocket/common/src/main/java/org/tio/websocket/common/WsClientEncoder.java +++ b/src/zoo/websocket/common/src/main/java/org/tio/websocket/common/WsClientEncoder.java @@ -33,8 +33,8 @@ public class WsClientEncoder { +---------------------------------------------------------------+ */ public static ByteBuffer encode( - WsRequest packet, GroupContext groupContext, ChannelContext channelContext) { - byte[] wsBody = packet.getBody();//就是ws的body,不包括ws的头 + WsPacket packet, GroupContext groupContext, ChannelContext channelContext) { + byte[] wsBody = packet.getBody(); // 就是ws的body,不包括ws的头 byte[][] wsBodies = packet.getBodys(); int wsBodyLength = 0; if (wsBody != null) { @@ -46,10 +46,9 @@ public static ByteBuffer encode( } } - byte header0 = (byte) (0x8f & (packet.getWsOpcode().getCode() | 0xf0)); - if(!packet.isWsEof()){ - header0 = (byte)(header0 & ~(1)); - } + byte opcode = packet.getWsOpcode().getCode(); + byte header0 = (byte) (packet.isWsEof() ? -128 : 0); + header0 |= opcode; ByteBuffer buf = null; if (wsBodyLength < 126) { @@ -66,7 +65,6 @@ public static ByteBuffer encode( buf.put(header0); buf.put((byte) 127); - // buf.put(new byte[] { 0, 0, 0, 0 }); buf.position(buf.position() + 4); ByteBufferUtils.writeUB4WithBigEdian(buf, wsBodyLength); @@ -82,139 +80,5 @@ public static ByteBuffer encode( } return buf; -// byte byte0 = 0; -// if (packet.isWsEof()) { -// byte0 = (byte) (byte0 | 1); -// switch (packet.getWsOpcode()) { -// case TEXT: -// byte0 = (byte) (byte0 | 0x10); -// break; -// case BINARY: -// byte0 = (byte) (byte0 | 0x20); -// break; -// case CLOSE: -// byte0 = (byte) (byte0 | 0x80); -// break; -// case PING: -// byte0 = (byte) (byte0 | 0x90); -// break; -// case PONG: -// byte0 = (byte) (byte0 | 0xA0); -// break; -// } -// } -// -// byte byte1 = 0; -// if (packet.isWsHasMask()) { -// byte1 = (byte) (byte1 | 1); -// } -// -// byte[] wsBody = packet.getBody();//就是ws的body,不包括ws的头 -// byte[][] wsBodies = packet.getBodys(); -// int wsBodyLength = 0; -// if (wsBody != null) { -// wsBodyLength += wsBody.length; -// } else if (wsBodies != null) { -// for (int i = 0; i < wsBodies.length; i++) { -// byte[] bs = wsBodies[i]; -// wsBodyLength += bs.length; -// } -// } -// -// byte header0 = (byte) (0x8f & (packet.getWsOpcode().getCode() | 0xf0)); -// ByteBuffer buf = null; -// if (wsBodyLength < 126) { -// buf = ByteBuffer.allocate(2 + wsBodyLength); -// buf.put(header0); -// buf.put((byte) wsBodyLength); -// } else if (wsBodyLength < (1 << 16) - 1) { -// buf = ByteBuffer.allocate(4 + wsBodyLength); -// buf.put(header0); -// buf.put((byte) 126); -// ByteBufferUtils.writeUB2WithBigEdian(buf, wsBodyLength); -// } else { -// buf = ByteBuffer.allocate(10 + wsBodyLength); -// buf.put(header0); -// buf.put((byte) 127); -// -// // buf.put(new byte[] { 0, 0, 0, 0 }); -// buf.position(buf.position() + 4); -// -// ByteBufferUtils.writeUB4WithBigEdian(buf, wsBodyLength); -// } -// -// if (wsBody != null && wsBody.length > 0) { -// buf.put(wsBody); -// } else if (wsBodies != null) { -// for (int i = 0; i < wsBodies.length; i++) { -// byte[] bs = wsBodies[i]; -// buf.put(bs); -// } -// } -// -// int frameLength = 16; -// ByteBuffer frame = ByteBuffer.allocate(frameLength); -// frame.put(byte0); -// -// return frame; - } - - public static int set(int num, int i, int bit) { - if (bit == 0) { - return num & ~(1 << i); - } else { - return num | (1 << i); - } - } - - public static int at(byte num, int i) { - return (num & (1 << i)) == 0 ? 0 : 1; - } - - public static void main(String[] args) { - ByteBuffer frame = ByteBuffer.allocate(20 * 4); - for (byte i = 0; i < 20 * 4; i++) { - frame.put(i); - } - int j = 0; - for (byte b : frame.array()) { - System.out.print(j + "\t"); - for (int i = 0; i < 8; i++) { - System.out.print(at(b, i)); - } - System.out.println(); - j++; - } - System.out.println(); - - byte byte0 = 0; - - byte0 = (byte) (byte0 | 1); - switch (Opcode.TEXT) { - case TEXT: - byte0 = (byte) (byte0 | 0x10); - break; - case BINARY: - byte0 = (byte) (byte0 | 0x02); - break; - case CLOSE: - byte0 = (byte) (byte0 | 0x08); - break; - case PING: - byte0 = (byte) (byte0 | 0x09); - break; - case PONG: - byte0 = (byte) (byte0 | 0x0A); - break; - } - - for (int i = 0; i < 8; i++) { - System.out.print(at(byte0, i)); - } - - System.out.println(); - for (int i = 0; i < 8; i++) { - System.out.print(at((byte) 0x8f, i)); - } } } diff --git a/src/zoo/websocket/common/src/main/java/org/tio/websocket/common/WsRequest.java b/src/zoo/websocket/common/src/main/java/org/tio/websocket/common/WsRequest.java index d3420ab6..605b53aa 100644 --- a/src/zoo/websocket/common/src/main/java/org/tio/websocket/common/WsRequest.java +++ b/src/zoo/websocket/common/src/main/java/org/tio/websocket/common/WsRequest.java @@ -22,6 +22,7 @@ public static WsRequest fromText(String text, String charset) { } catch (UnsupportedEncodingException e) { log.error(e.toString(), e); } + wsRequest.setWsEof(true); wsRequest.setWsOpcode(Opcode.TEXT); return wsRequest; } @@ -29,6 +30,7 @@ public static WsRequest fromText(String text, String charset) { public static WsRequest fromBytes(byte[] bytes) { WsRequest wsRequest = new WsRequest(); wsRequest.setBody(bytes); + wsRequest.setWsEof(true); wsRequest.setWsOpcode(Opcode.BINARY); return wsRequest; }