/* ************************************************************************ # # DivConq # # http://divconq.com/ # # Copyright: # Copyright 2014 eTimeline, LLC. All rights reserved. # # License: # See the license.txt file in the project's top-level directory for details. # # Authors: # * Andy White # ************************************************************************ */ package divconq.bus.net; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.websocketx.WebSocketServerHandshaker; import io.netty.handler.codec.http.websocketx.WebSocketServerHandshakerFactory; import io.netty.util.CharsetUtil; import static io.netty.handler.codec.http.HttpHeaders.Names.*; import io.netty.handler.codec.http.HttpHeaders; import io.netty.handler.codec.http.HttpMethod; import static io.netty.handler.codec.http.HttpResponseStatus.*; import static io.netty.handler.codec.http.HttpVersion.*; /** * Handles handshakes and messages */ public class ServerHandler extends CommonHandler { protected WebSocketServerHandshaker handshaker = null; public ServerHandler(SocketInfo info) { super(info, true); } @Override public void handleHttpRequest(ChannelHandlerContext ctx, FullHttpRequest req) throws Exception { // Handle a bad request. if (!req.getDecoderResult().isSuccess()) { sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HTTP_1_1, BAD_REQUEST)); return; } // Allow only GET methods. if (req.getMethod() != HttpMethod.GET) { sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HTTP_1_1, FORBIDDEN)); return; } // Send the demo page and favicon.ico if ("/".equals(req.getUri())) { ByteBuf content = WebSocketServerIndexPage.getContent(getWebSocketLocation(req)); FullHttpResponse res = new DefaultFullHttpResponse(HTTP_1_1, OK, content); res.headers().set(CONTENT_TYPE, "text/html; charset=UTF-8"); HttpHeaders.setContentLength(res, content.readableBytes()); sendHttpResponse(ctx, req, res); return; } if ("/favicon.ico".equals(req.getUri())) { FullHttpResponse res = new DefaultFullHttpResponse(HTTP_1_1, NOT_FOUND); sendHttpResponse(ctx, req, res); return; } if (CommonHandler.BUS_PATH.equals(req.getUri())) { // Handshake WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory( getWebSocketLocation(req), null, false); this.handshaker = wsFactory.newHandshaker(req); if (this.handshaker == null) WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(ctx.channel()); else this.handshaker.handshake(ctx.channel(), req); return; } FullHttpResponse res = new DefaultFullHttpResponse(HTTP_1_1, NOT_FOUND); this.sendHttpResponse(ctx, req, res); } public void sendHttpResponse(ChannelHandlerContext ctx, FullHttpRequest req, FullHttpResponse res) { // Generate an error page if response getStatus code is not OK (200). if (res.getStatus().code() != 200) { ByteBuf buf = Unpooled.copiedBuffer(res.getStatus().toString(), CharsetUtil.UTF_8); res.content().writeBytes(buf); buf.release(); HttpHeaders.setContentLength(res, res.content().readableBytes()); } // Send the response and close the connection if necessary. ChannelFuture f = ctx.channel().writeAndFlush(res); if (!HttpHeaders.isKeepAlive(req) || res.getStatus().code() != 200) f.addListener(ChannelFutureListener.CLOSE); } }