package org.rakam.server.http; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.HttpHeaders; import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame; import io.netty.handler.codec.http.websocketx.PingWebSocketFrame; import io.netty.handler.codec.http.websocketx.PongWebSocketFrame; import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; import io.netty.handler.codec.http.websocketx.WebSocketFrame; import io.netty.handler.codec.http.websocketx.WebSocketServerHandshaker; import io.netty.handler.codec.http.websocketx.WebSocketServerHandshakerFactory; import java.util.List; import java.util.Map; import static io.netty.handler.codec.http.HttpHeaders.Names.HOST; public abstract class WebSocketService implements HttpRequestHandler { private WebSocketServerHandshaker handshaker; public abstract void onOpen(WebSocketRequest request); public abstract void onMessage(ChannelHandlerContext ctx, String message); public abstract void onClose(ChannelHandlerContext ctx); public void handle(ChannelHandlerContext ctx, WebSocketFrame frame) { if (frame instanceof CloseWebSocketFrame) { handshaker.close(ctx.channel(), (CloseWebSocketFrame) frame); onClose(ctx); return; } if (frame instanceof PingWebSocketFrame) { ctx.channel().write(new PongWebSocketFrame(frame.content())); return; } if (!(frame instanceof TextWebSocketFrame)) { throw new UnsupportedOperationException(String.format("%s frame types not supported", frame.getClass() .getName())); } String msg = ((TextWebSocketFrame) frame).text(); onMessage(ctx, msg); } public ChannelFuture send(ChannelHandlerContext ctx, String message) { return ctx.channel().writeAndFlush(new TextWebSocketFrame(message)); } @Override public void handle(RakamHttpRequest request) { WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory( getWebSocketLocation(request), null, true); handshaker = wsFactory.newHandshaker(request.getRequest()); if (handshaker == null) { WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(request.context().channel()); } else { HttpRequest request1 = request.getRequest(); DefaultFullHttpRequest defaultFullHttpRequest = new DefaultFullHttpRequest(request1.getProtocolVersion(), request1.getMethod(), request1.getUri()); defaultFullHttpRequest.headers().set(request1.headers()); handshaker.handshake(request.context().channel(), defaultFullHttpRequest); onOpen(new WebSocketRequest(request)); } } private static String getWebSocketLocation(RakamHttpRequest req) { String location = req.headers().get(HOST) + req.getUri(); // if (WebSocketServer.SSL) { // return "wss://" + location; // } else { return "ws://" + location; // } } public static class WebSocketRequest { private final RakamHttpRequest request; public WebSocketRequest(RakamHttpRequest request) { this.request = request; } public String uri() { return request.getUri(); } public Map<String, List<String>> params() { return request.params(); } public HttpHeaders headers() { return request.headers(); } public ChannelHandlerContext context() { return request.context(); } } }