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 org.jboss.netty.buffer.ChannelBuffer;
19 import org.jboss.netty.channel.Channel;
20 import org.jboss.netty.channel.ChannelHandlerContext;
21 import org.jboss.netty.channel.ChannelPipeline;
22 import org.jboss.netty.example.factorial.BigIntegerDecoder;
23 import org.jboss.netty.example.factorial.FactorialServerHandler;
24 import org.jboss.netty.example.factorial.NumberEncoder;
25 import org.jboss.netty.example.http.snoop.HttpSnoopServerHandler;
26 import org.jboss.netty.handler.codec.compression.ZlibDecoder;
27 import org.jboss.netty.handler.codec.compression.ZlibEncoder;
28 import org.jboss.netty.handler.codec.compression.ZlibWrapper;
29 import org.jboss.netty.handler.codec.frame.FrameDecoder;
30 import org.jboss.netty.handler.codec.http.HttpContentCompressor;
31 import org.jboss.netty.handler.codec.http.HttpRequestDecoder;
32 import org.jboss.netty.handler.codec.http.HttpResponseEncoder;
33 import org.jboss.netty.handler.ssl.SslContext;
34 import org.jboss.netty.handler.ssl.SslHandler;
35
36
37
38
39
40 public class PortUnificationServerHandler extends FrameDecoder {
41
42 private final SslContext sslCtx;
43 private final boolean detectSsl;
44 private final boolean detectGzip;
45
46 public PortUnificationServerHandler(SslContext sslCtx) {
47 this(sslCtx, true, true);
48 }
49
50 private PortUnificationServerHandler(SslContext sslCtx, boolean detectSsl, boolean detectGzip) {
51 this.sslCtx = sslCtx;
52 this.detectSsl = detectSsl;
53 this.detectGzip = detectGzip;
54 }
55
56 @Override
57 protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) {
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 p.addLast("ssl", sslCtx.newHandler());
120 p.addLast("unificationA", new PortUnificationServerHandler(sslCtx, false, detectGzip));
121 p.remove(this);
122 }
123
124 private void enableGzip(ChannelHandlerContext ctx) {
125 ChannelPipeline p = ctx.getPipeline();
126 p.addLast("gzipdeflater", new ZlibEncoder(ZlibWrapper.GZIP));
127 p.addLast("gzipinflater", new ZlibDecoder(ZlibWrapper.GZIP));
128 p.addLast("unificationB", new PortUnificationServerHandler(sslCtx, detectSsl, false));
129 p.remove(this);
130 }
131
132 private void switchToHttp(ChannelHandlerContext ctx) {
133 ChannelPipeline p = ctx.getPipeline();
134 p.addLast("decoder", new HttpRequestDecoder());
135 p.addLast("encoder", new HttpResponseEncoder());
136 p.addLast("deflater", new HttpContentCompressor());
137 p.addLast("handler", new HttpSnoopServerHandler());
138 p.remove(this);
139 }
140
141 private void switchToFactorial(ChannelHandlerContext ctx) {
142 ChannelPipeline p = ctx.getPipeline();
143 p.addLast("decoder", new BigIntegerDecoder());
144 p.addLast("encoder", new NumberEncoder());
145 p.addLast("handler", new FactorialServerHandler());
146 p.remove(this);
147 }
148 }