1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.example.portunification;
17
18 import io.netty.buffer.ByteBuf;
19 import io.netty.channel.ChannelHandlerContext;
20 import io.netty.channel.ChannelPipeline;
21 import io.netty.example.factorial.BigIntegerDecoder;
22 import io.netty.example.factorial.FactorialServerHandler;
23 import io.netty.example.factorial.NumberEncoder;
24 import io.netty.example.http.snoop.HttpSnoopServerHandler;
25 import io.netty.handler.codec.ByteToMessageDecoder;
26 import io.netty.handler.codec.compression.ZlibCodecFactory;
27 import io.netty.handler.codec.compression.ZlibWrapper;
28 import io.netty.handler.codec.http.HttpContentCompressor;
29 import io.netty.handler.codec.http.HttpRequestDecoder;
30 import io.netty.handler.codec.http.HttpResponseEncoder;
31 import io.netty.handler.ssl.SslContext;
32 import io.netty.handler.ssl.SslHandler;
33
34 import java.util.List;
35
36
37
38
39
40 public class PortUnificationServerHandler extends ByteToMessageDecoder {
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 void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
58
59 if (in.readableBytes() < 5) {
60 return;
61 }
62
63 if (isSsl(in)) {
64 enableSsl(ctx);
65 } else {
66 final int magic1 = in.getUnsignedByte(in.readerIndex());
67 final int magic2 = in.getUnsignedByte(in.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 in.clear();
77 ctx.close();
78 }
79 }
80 }
81
82 private boolean isSsl(ByteBuf buf) {
83 if (detectSsl) {
84 return SslHandler.isEncrypted(buf);
85 }
86 return false;
87 }
88
89 private boolean isGzip(int magic1, int magic2) {
90 if (detectGzip) {
91 return magic1 == 31 && magic2 == 139;
92 }
93 return false;
94 }
95
96 private static boolean isHttp(int magic1, int magic2) {
97 return
98 magic1 == 'G' && magic2 == 'E' ||
99 magic1 == 'P' && magic2 == 'O' ||
100 magic1 == 'P' && magic2 == 'U' ||
101 magic1 == 'H' && magic2 == 'E' ||
102 magic1 == 'O' && magic2 == 'P' ||
103 magic1 == 'P' && magic2 == 'A' ||
104 magic1 == 'D' && magic2 == 'E' ||
105 magic1 == 'T' && magic2 == 'R' ||
106 magic1 == 'C' && magic2 == 'O';
107 }
108
109 private static boolean isFactorial(int magic1) {
110 return magic1 == 'F';
111 }
112
113 private void enableSsl(ChannelHandlerContext ctx) {
114 ChannelPipeline p = ctx.pipeline();
115 p.addLast("ssl", sslCtx.newHandler(ctx.alloc()));
116 p.addLast("unificationA", new PortUnificationServerHandler(sslCtx, false, detectGzip));
117 p.remove(this);
118 }
119
120 private void enableGzip(ChannelHandlerContext ctx) {
121 ChannelPipeline p = ctx.pipeline();
122 p.addLast("gzipdeflater", ZlibCodecFactory.newZlibEncoder(ZlibWrapper.GZIP));
123 p.addLast("gzipinflater", ZlibCodecFactory.newZlibDecoder(ZlibWrapper.GZIP));
124 p.addLast("unificationB", new PortUnificationServerHandler(sslCtx, detectSsl, false));
125 p.remove(this);
126 }
127
128 private void switchToHttp(ChannelHandlerContext ctx) {
129 ChannelPipeline p = ctx.pipeline();
130 p.addLast("decoder", new HttpRequestDecoder());
131 p.addLast("encoder", new HttpResponseEncoder());
132 p.addLast("deflater", new HttpContentCompressor());
133 p.addLast("handler", new HttpSnoopServerHandler());
134 p.remove(this);
135 }
136
137 private void switchToFactorial(ChannelHandlerContext ctx) {
138 ChannelPipeline p = ctx.pipeline();
139 p.addLast("decoder", new BigIntegerDecoder());
140 p.addLast("encoder", new NumberEncoder());
141 p.addLast("handler", new FactorialServerHandler());
142 p.remove(this);
143 }
144 }