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.HttpRequestHandler;
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
43
44
45
46
47 public class PortUnificationServerHandler extends FrameDecoder {
48
49 private final boolean detectSsl;
50 private final boolean detectGzip;
51
52 public PortUnificationServerHandler() {
53 this(true, true);
54 }
55
56 private PortUnificationServerHandler(boolean detectSsl, boolean detectGzip) {
57 this.detectSsl = detectSsl;
58 this.detectGzip = detectGzip;
59 }
60
61 @Override
62 protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {
63
64
65 if (buffer.readableBytes() < 2) {
66 return null;
67 }
68
69 final int magic1 = buffer.getUnsignedByte(buffer.readerIndex());
70 final int magic2 = buffer.getUnsignedByte(buffer.readerIndex() + 1);
71
72 if (isSsl(magic1)) {
73 enableSsl(ctx);
74 } else if (isGzip(magic1, magic2)) {
75 enableGzip(ctx);
76 } else if (isHttp(magic1, magic2)) {
77 switchToHttp(ctx);
78 } else if (isFactorial(magic1)) {
79 switchToFactorial(ctx);
80 } else {
81
82 buffer.skipBytes(buffer.readableBytes());
83 ctx.getChannel().close();
84 return null;
85 }
86
87
88 return buffer.readBytes(buffer.readableBytes());
89 }
90
91 private boolean isSsl(int magic1) {
92 if (detectSsl) {
93 switch (magic1) {
94 case 20: case 21: case 22: case 23: case 255:
95 return true;
96 default:
97 return magic1 >= 128;
98 }
99 }
100 return false;
101 }
102
103 private boolean isGzip(int magic1, int magic2) {
104 if (detectGzip) {
105 return magic1 == 31 && magic2 == 139;
106 }
107 return false;
108 }
109
110 private boolean isHttp(int magic1, int magic2) {
111 return
112 magic1 == 'G' && magic2 == 'E' ||
113 magic1 == 'P' && magic2 == 'O' ||
114 magic1 == 'P' && magic2 == 'U' ||
115 magic1 == 'H' && magic2 == 'E' ||
116 magic1 == 'O' && magic2 == 'P' ||
117 magic1 == 'P' && magic2 == 'A' ||
118 magic1 == 'D' && magic2 == 'E' ||
119 magic1 == 'T' && magic2 == 'R' ||
120 magic1 == 'C' && magic2 == 'O';
121 }
122
123 private boolean isFactorial(int magic1) {
124 return magic1 == 'F';
125 }
126
127 private void enableSsl(ChannelHandlerContext ctx) {
128 ChannelPipeline p = ctx.getPipeline();
129
130 SSLEngine engine =
131 SecureChatSslContextFactory.getServerContext().createSSLEngine();
132 engine.setUseClientMode(false);
133
134 p.addLast("ssl", new SslHandler(engine));
135 p.addLast("unificationA", new PortUnificationServerHandler(false, detectGzip));
136 p.remove(this);
137 }
138
139 private void enableGzip(ChannelHandlerContext ctx) {
140 ChannelPipeline p = ctx.getPipeline();
141 p.addLast("gzipdeflater", new ZlibEncoder(ZlibWrapper.GZIP));
142 p.addLast("gzipinflater", new ZlibDecoder(ZlibWrapper.GZIP));
143 p.addLast("unificationB", new PortUnificationServerHandler(detectSsl, false));
144 p.remove(this);
145 }
146
147 private void switchToHttp(ChannelHandlerContext ctx) {
148 ChannelPipeline p = ctx.getPipeline();
149 p.addLast("decoder", new HttpRequestDecoder());
150 p.addLast("encoder", new HttpResponseEncoder());
151 p.addLast("deflater", new HttpContentCompressor());
152 p.addLast("handler", new HttpRequestHandler());
153 p.remove(this);
154 }
155
156 private void switchToFactorial(ChannelHandlerContext ctx) {
157 ChannelPipeline p = ctx.getPipeline();
158 p.addLast("decoder", new BigIntegerDecoder());
159 p.addLast("encoder", new NumberEncoder());
160 p.addLast("handler", new FactorialServerHandler());
161 p.remove(this);
162 }
163 }