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