1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.jboss.netty.example.http.websocketx.autobahn;
17
18 import org.jboss.netty.buffer.ChannelBuffers;
19 import org.jboss.netty.channel.ChannelFuture;
20 import org.jboss.netty.channel.ChannelFutureListener;
21 import org.jboss.netty.channel.ChannelHandlerContext;
22 import org.jboss.netty.channel.ExceptionEvent;
23 import org.jboss.netty.channel.MessageEvent;
24 import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
25 import org.jboss.netty.handler.codec.http.DefaultHttpResponse;
26 import org.jboss.netty.handler.codec.http.HttpHeaders;
27 import org.jboss.netty.handler.codec.http.HttpRequest;
28 import org.jboss.netty.handler.codec.http.HttpResponse;
29 import org.jboss.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
30 import org.jboss.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
31 import org.jboss.netty.handler.codec.http.websocketx.ContinuationWebSocketFrame;
32 import org.jboss.netty.handler.codec.http.websocketx.PingWebSocketFrame;
33 import org.jboss.netty.handler.codec.http.websocketx.PongWebSocketFrame;
34 import org.jboss.netty.handler.codec.http.websocketx.TextWebSocketFrame;
35 import org.jboss.netty.handler.codec.http.websocketx.WebSocketFrame;
36 import org.jboss.netty.handler.codec.http.websocketx.WebSocketServerHandshaker;
37 import org.jboss.netty.handler.codec.http.websocketx.WebSocketServerHandshakerFactory;
38 import org.jboss.netty.logging.InternalLogger;
39 import org.jboss.netty.logging.InternalLoggerFactory;
40 import org.jboss.netty.util.CharsetUtil;
41
42 import static org.jboss.netty.handler.codec.http.HttpHeaders.*;
43 import static org.jboss.netty.handler.codec.http.HttpMethod.*;
44 import static org.jboss.netty.handler.codec.http.HttpResponseStatus.*;
45 import static org.jboss.netty.handler.codec.http.HttpVersion.*;
46
47
48
49
50 public class AutobahnServerHandler extends SimpleChannelUpstreamHandler {
51 private static final InternalLogger logger = InternalLoggerFactory.getInstance(AutobahnServerHandler.class);
52
53 private WebSocketServerHandshaker handshaker;
54
55 @Override
56 public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
57 Object msg = e.getMessage();
58 if (msg instanceof HttpRequest) {
59 handleHttpRequest(ctx, (HttpRequest) msg);
60 } else if (msg instanceof WebSocketFrame) {
61 handleWebSocketFrame(ctx, (WebSocketFrame) msg);
62 }
63 }
64
65 private void handleHttpRequest(ChannelHandlerContext ctx, HttpRequest req) {
66
67 if (req.getMethod() != GET) {
68 sendHttpResponse(ctx, req, new DefaultHttpResponse(HTTP_1_1, FORBIDDEN));
69 return;
70 }
71
72
73 WebSocketServerHandshakerFactory wsFactory =
74 new WebSocketServerHandshakerFactory(getWebSocketLocation(req), null, false);
75 handshaker = wsFactory.newHandshaker(req);
76 if (handshaker == null) {
77 wsFactory.sendUnsupportedWebSocketVersionResponse(ctx.getChannel());
78 } else {
79 handshaker.handshake(ctx.getChannel(), req).addListener(WebSocketServerHandshaker.HANDSHAKE_LISTENER);
80 }
81 }
82
83 private void handleWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame) {
84 if (logger.isDebugEnabled()) {
85 logger.debug(String.format(
86 "Channel %s received %s", ctx.getChannel().getId(), frame.getClass().getSimpleName()));
87 }
88
89 if (frame instanceof CloseWebSocketFrame) {
90 handshaker.close(ctx.getChannel(), (CloseWebSocketFrame) frame);
91 } else if (frame instanceof PingWebSocketFrame) {
92 ctx.getChannel().write(
93 new PongWebSocketFrame(frame.isFinalFragment(), frame.getRsv(), frame.getBinaryData()));
94 } else if (frame instanceof TextWebSocketFrame) {
95
96 ctx.getChannel().write(
97 new TextWebSocketFrame(frame.isFinalFragment(), frame.getRsv(), frame.getBinaryData()));
98 } else if (frame instanceof BinaryWebSocketFrame) {
99 ctx.getChannel().write(
100 new BinaryWebSocketFrame(frame.isFinalFragment(), frame.getRsv(), frame.getBinaryData()));
101 } else if (frame instanceof ContinuationWebSocketFrame) {
102 ctx.getChannel().write(
103 new ContinuationWebSocketFrame(frame.isFinalFragment(), frame.getRsv(), frame.getBinaryData()));
104 } else if (frame instanceof PongWebSocketFrame) {
105
106 } else {
107 throw new UnsupportedOperationException(String.format("%s frame types not supported", frame.getClass()
108 .getName()));
109 }
110 }
111
112 private static void sendHttpResponse(ChannelHandlerContext ctx, HttpRequest req, HttpResponse res) {
113
114 if (res.getStatus().getCode() != 200) {
115 res.setContent(ChannelBuffers.copiedBuffer(res.getStatus().toString(), CharsetUtil.UTF_8));
116 setContentLength(res, res.getContent().readableBytes());
117 }
118
119
120 ChannelFuture f = ctx.getChannel().write(res);
121 if (!isKeepAlive(req) || res.getStatus().getCode() != 200) {
122 f.addListener(ChannelFutureListener.CLOSE);
123 }
124 }
125
126 @Override
127 public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
128 e.getCause().printStackTrace();
129 e.getChannel().close();
130 }
131
132 private static String getWebSocketLocation(HttpRequest req) {
133 return "ws://" + req.headers().get(HttpHeaders.Names.HOST);
134 }
135 }