@Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { if (msg instanceof org.vertx.java.core.http.impl.ws.WebSocketFrame) { org.vertx.java.core.http.impl.ws.WebSocketFrame frame = (org.vertx.java.core.http.impl.ws.WebSocketFrame) msg; ByteBuf buf = ((org.vertx.java.core.http.impl.ws.WebSocketFrame) msg).getBinaryData(); if (buf != Unpooled.EMPTY_BUFFER) { buf = safeBuffer(buf); } switch (frame.getType()) { case BINARY: msg = new BinaryWebSocketFrame(buf); break; case TEXT: msg = new TextWebSocketFrame(buf); break; case CLOSE: msg = new CloseWebSocketFrame(true, 0, buf); break; case CONTINUATION: msg = new ContinuationWebSocketFrame(buf); break; case PONG: msg = new PongWebSocketFrame(buf); break; case PING: msg = new PingWebSocketFrame(buf); break; default: throw new IllegalStateException("Unsupported websocket msg " + msg); } } ctx.write(msg, promise); }
@Override protected void doMessageReceived(ClientConnection conn, ChannelHandlerContext ctx, Object msg) { if (conn == null || conn.isClosed()) { return; } boolean valid = false; if (msg instanceof HttpResponse) { HttpResponse response = (HttpResponse) msg; conn.handleResponse(response); valid = true; } if (msg instanceof HttpContent) { HttpContent chunk = (HttpContent) msg; if (chunk.content().isReadable()) { Buffer buff = new Buffer(chunk.content().slice()); conn.handleResponseChunk(buff); } if (chunk instanceof LastHttpContent) { conn.handleResponseEnd((LastHttpContent) chunk); } valid = true; } else if (msg instanceof WebSocketFrame) { WebSocketFrame frame = (WebSocketFrame) msg; switch (frame.getType()) { case BINARY: case TEXT: conn.handleWsFrame(frame); break; case PING: // Echo back the content of the PING frame as PONG frame as specified in RFC 6455 // Section 5.5.2 ctx.writeAndFlush( new DefaultWebSocketFrame(WebSocketFrame.FrameType.PONG, frame.getBinaryData())); break; case CLOSE: if (!closeFrameSent) { // Echo back close frame and close the connection once it was written. // This is specified in the WebSockets RFC 6455 Section 5.4.1 ctx.writeAndFlush(frame).addListener(ChannelFutureListener.CLOSE); closeFrameSent = true; } break; } valid = true; } if (!valid) { throw new IllegalStateException("Invalid object " + msg); } }
@Override protected Object encode(ChannelHandlerContext ctx, Channel channel, Object msg) throws Exception { if (msg instanceof WebSocketFrame) { WebSocketFrame frame = (WebSocketFrame) msg; FrameType frameType = frame.getType(); int opcode = encodeOpcode(frameType); ChannelBuffer data = frame.getBinaryData(); int dataLen = data.readableBytes(); ChannelBuffer encoded = ChannelBuffers.dynamicBuffer(ByteOrder.BIG_ENDIAN, data.readableBytes() + 32); byte firstByte = (byte) opcode; firstByte = (byte) (firstByte | 0x80); encoded.writeByte(firstByte); if (dataLen <= 125) { encoded.writeByte(applyMaskBit(dataLen)); } else if (dataLen < 0xFFFF) { encoded.writeByte(applyMaskBit(0x7E)); encoded.writeShort(dataLen); } else { encoded.writeByte(applyMaskBit(0x7F)); encoded.writeLong(dataLen); } if (shouldMask()) { byte[] mask = getMask(); encoded.writeBytes(mask); applyDataMask(mask, data); } encoded.writeBytes(data); return encoded; } return msg; }