1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.jboss.netty.example.portunification;
17
18 import javax.net.ssl.SSLEngine;
19
20 import org.jboss.netty.buffer.ChannelBuffer;
21 import org.jboss.netty.channel.Channel;
22 import org.jboss.netty.channel.ChannelHandlerContext;
23 import org.jboss.netty.channel.ChannelPipeline;
24 import org.jboss.netty.example.factorial.BigIntegerDecoder;
25 import org.jboss.netty.example.factorial.FactorialServerHandler;
26 import org.jboss.netty.example.factorial.NumberEncoder;
27 import org.jboss.netty.example.http.snoop.HttpSnoopServerHandler;
28 import org.jboss.netty.example.securechat.SecureChatSslContextFactory;
29 import org.jboss.netty.handler.codec.compression.ZlibDecoder;
30 import org.jboss.netty.handler.codec.compression.ZlibEncoder;
31 import org.jboss.netty.handler.codec.compression.ZlibWrapper;
32 import org.jboss.netty.handler.codec.frame.FrameDecoder;
33 import org.jboss.netty.handler.codec.http.HttpContentCompressor;
34 import org.jboss.netty.handler.codec.http.HttpRequestDecoder;
35 import org.jboss.netty.handler.codec.http.HttpResponseEncoder;
36 import org.jboss.netty.handler.ssl.SslHandler;
37
38
39
40
41
42 public class PortUnificationServerHandler extends FrameDecoder {
43
44 private final boolean detectSsl;
45 private final boolean detectGzip;
46
47 public PortUnificationServerHandler() {
48 this(true, true);
49 }
50
51 private PortUnificationServerHandler(boolean detectSsl, boolean detectGzip) {
52 this.detectSsl = detectSsl;
53 this.detectGzip = detectGzip;
54 }
55
56 @Override
57 protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {
58
59 if (buffer.readableBytes() < 5) {
60 return null;
61 }
62
63 if (isSsl(buffer)) {
64 enableSsl(ctx);
65 } else {
66 final int magic1 = buffer.getUnsignedByte(buffer.readerIndex());
67 final int magic2 = buffer.getUnsignedByte(buffer.readerIndex() + 1);
68 if (isGzip(magic1, magic2)) {
69 enableGzip(ctx);
70 } else if (isHttp(magic1, magic2)) {
71 switchToHttp(ctx);
72 } else if (isFactorial(magic1)) {
73 switchToFactorial(ctx);
74 } else {
75
76 buffer.skipBytes(buffer.readableBytes());
77 ctx.getChannel().close();
78 return null;
79 }
80 }
81
82
83 return buffer.readBytes(buffer.readableBytes());
84 }
85
86 private boolean isSsl(ChannelBuffer buffer) {
87 if (detectSsl) {
88 return SslHandler.isEncrypted(buffer);
89 }
90 return false;
91 }
92
93 private boolean isGzip(int magic1, int magic2) {
94 if (detectGzip) {
95 return magic1 == 31 && magic2 == 139;
96 }
97 return false;
98 }
99
100 private static boolean isHttp(int magic1, int magic2) {
101 return
102 magic1 == 'G' && magic2 == 'E' ||
103 magic1 == 'P' && magic2 == 'O' ||
104 magic1 == 'P' && magic2 == 'U' ||
105 magic1 == 'H' && magic2 == 'E' ||
106 magic1 == 'O' && magic2 == 'P' ||
107 magic1 == 'P' && magic2 == 'A' ||
108 magic1 == 'D' && magic2 == 'E' ||
109 magic1 == 'T' && magic2 == 'R' ||
110 magic1 == 'C' && magic2 == 'O';
111 }
112
113 private static boolean isFactorial(int magic1) {
114 return magic1 == 'F';
115 }
116
117 private void enableSsl(ChannelHandlerContext ctx) {
118 ChannelPipeline p = ctx.getPipeline();
119
120 SSLEngine engine =
121 SecureChatSslContextFactory.getServerContext().createSSLEngine();
122 engine.setUseClientMode(false);
123
124 p.addLast("ssl", new SslHandler(engine));
125 p.addLast("unificationA", new PortUnificationServerHandler(false, detectGzip));
126 p.remove(this);
127 }
128
129 private void enableGzip(ChannelHandlerContext ctx) {
130 ChannelPipeline p = ctx.getPipeline();
131 p.addLast("gzipdeflater", new ZlibEncoder(ZlibWrapper.GZIP));
132 p.addLast("gzipinflater", new ZlibDecoder(ZlibWrapper.GZIP));
133 p.addLast("unificationB", new PortUnificationServerHandler(detectSsl, false));
134 p.remove(this);
135 }
136
137 private void switchToHttp(ChannelHandlerContext ctx) {
138 ChannelPipeline p = ctx.getPipeline();
139 p.addLast("decoder", new HttpRequestDecoder());
140 p.addLast("encoder", new HttpResponseEncoder());
141 p.addLast("deflater", new HttpContentCompressor());
142 p.addLast("handler", new HttpSnoopServerHandler());
143 p.remove(this);
144 }
145
146 private void switchToFactorial(ChannelHandlerContext ctx) {
147 ChannelPipeline p = ctx.getPipeline();
148 p.addLast("decoder", new BigIntegerDecoder());
149 p.addLast("encoder", new NumberEncoder());
150 p.addLast("handler", new FactorialServerHandler());
151 p.remove(this);
152 }
153 }