package org.voovan.http.client; import org.voovan.http.websocket.WebSocketFrame; import org.voovan.http.websocket.WebSocketRouter; import org.voovan.http.websocket.WebSocketTools; import org.voovan.network.IoHandler; import org.voovan.network.IoSession; import org.voovan.tools.TObject; import java.nio.ByteBuffer; /** * 处理 WebSocket 相关的 IoHandler 事件 * * @author helyho * <p> * Voovan Framework. * WebSite: https://github.com/helyho/Voovan * Licence: Apache v2 License */ public class WebSocketHandler implements IoHandler{ private WebSocketRouter webSocketRouter; private HttpClient httpClient; public WebSocketHandler(HttpClient httpClient, WebSocketRouter webSocketRouter){ this.webSocketRouter = webSocketRouter; this.httpClient = httpClient; } @Override public Object onConnect(IoSession session) { //不会被触发 return null; } @Override public void onDisconnect(IoSession session) { webSocketRouter.onClose(); } @Override public Object onReceive(IoSession session, Object obj) { //分片 (1) fin=0 , opcode=1 //分片 (2) fin=0 , opcode=0 //分片 (3) fin=1 , opcode=0 WebSocketFrame respWebSocketFrame = null; WebSocketFrame reqWebSocketFrame = null; if(obj instanceof WebSocketFrame) { reqWebSocketFrame = TObject.cast(obj); }else{ return null; } if (reqWebSocketFrame.getOpcode() == WebSocketFrame.Opcode.CLOSING) { return WebSocketFrame.newInstance(true, WebSocketFrame.Opcode.CLOSING, false, reqWebSocketFrame.getFrameData()); } // WS_PING 收到 ping 帧则返回 pong 帧 else if (reqWebSocketFrame.getOpcode() == WebSocketFrame.Opcode.PING) { return WebSocketFrame.newInstance(true, WebSocketFrame.Opcode.PONG, false, null); } // WS_PING 收到 pong 帧则返回 ping 帧 else if (reqWebSocketFrame.getOpcode() == WebSocketFrame.Opcode.PONG) { return WebSocketFrame.newInstance(true, WebSocketFrame.Opcode.PING, false, null); } // WS_RECIVE 文本和二进制消息出发 Recived 事件 else if (reqWebSocketFrame.getOpcode() == WebSocketFrame.Opcode.TEXT || reqWebSocketFrame.getOpcode() == WebSocketFrame.Opcode.BINARY) { ByteBuffer respData = webSocketRouter.onRecived(reqWebSocketFrame.getFrameData()); //判断解包是否有错 if (reqWebSocketFrame.getErrorCode() == 0) { respWebSocketFrame = WebSocketFrame.newInstance(true, WebSocketFrame.Opcode.BINARY, true, respData); } else { //解析时出现异常,返回关闭消息 respWebSocketFrame = WebSocketFrame.newInstance(true, WebSocketFrame.Opcode.CLOSING, false, ByteBuffer.wrap(WebSocketTools.intToByteArray(reqWebSocketFrame.getErrorCode(), 2))); } } return respWebSocketFrame; } @Override public void onSent(IoSession session, Object obj) { webSocketRouter.setSession(session); WebSocketFrame webSocketFrame = WebSocketFrame.parse((ByteBuffer)obj); if(webSocketFrame.getOpcode() == WebSocketFrame.Opcode.CLOSING){ session.close(); return; } ByteBuffer data = webSocketFrame.getFrameData(); webSocketRouter.onSent(data); } @Override public void onException(IoSession session, Exception e) { } }