1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package io.netty.handler.codec.socksx;
18
19 import io.netty.buffer.ByteBuf;
20 import io.netty.channel.ChannelHandlerContext;
21 import io.netty.channel.ChannelPipeline;
22 import io.netty.handler.codec.ByteToMessageDecoder;
23 import io.netty.handler.codec.socksx.v4.Socks4ServerDecoder;
24 import io.netty.handler.codec.socksx.v4.Socks4ServerEncoder;
25 import io.netty.handler.codec.socksx.v5.Socks5AddressEncoder;
26 import io.netty.handler.codec.socksx.v5.Socks5InitialRequestDecoder;
27 import io.netty.handler.codec.socksx.v5.Socks5ServerEncoder;
28 import io.netty.util.internal.ObjectUtil;
29 import io.netty.util.internal.logging.InternalLogger;
30 import io.netty.util.internal.logging.InternalLoggerFactory;
31
32 import java.util.List;
33
34
35
36
37
38 public class SocksPortUnificationServerHandler extends ByteToMessageDecoder {
39
40 private static final InternalLogger logger =
41 InternalLoggerFactory.getInstance(SocksPortUnificationServerHandler.class);
42
43 private final Socks5ServerEncoder socks5encoder;
44
45
46
47
48 public SocksPortUnificationServerHandler() {
49 this(Socks5ServerEncoder.DEFAULT);
50 }
51
52
53
54
55
56 public SocksPortUnificationServerHandler(Socks5ServerEncoder socks5encoder) {
57 this.socks5encoder = ObjectUtil.checkNotNull(socks5encoder, "socks5encoder");
58 }
59
60 @Override
61 protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
62 final int readerIndex = in.readerIndex();
63 if (in.writerIndex() == readerIndex) {
64 return;
65 }
66
67 ChannelPipeline p = ctx.pipeline();
68 final byte versionVal = in.getByte(readerIndex);
69 SocksVersion version = SocksVersion.valueOf(versionVal);
70
71 switch (version) {
72 case SOCKS4a:
73 logKnownVersion(ctx, version);
74 p.addAfter(ctx.name(), null, Socks4ServerEncoder.INSTANCE);
75 p.addAfter(ctx.name(), null, new Socks4ServerDecoder());
76 break;
77 case SOCKS5:
78 logKnownVersion(ctx, version);
79 p.addAfter(ctx.name(), null, socks5encoder);
80 p.addAfter(ctx.name(), null, new Socks5InitialRequestDecoder());
81 break;
82 default:
83 logUnknownVersion(ctx, versionVal);
84 in.skipBytes(in.readableBytes());
85 ctx.close();
86 return;
87 }
88
89 p.remove(this);
90 }
91
92 private static void logKnownVersion(ChannelHandlerContext ctx, SocksVersion version) {
93 logger.debug("{} Protocol version: {}({})", ctx.channel(), version);
94 }
95
96 private static void logUnknownVersion(ChannelHandlerContext ctx, byte versionVal) {
97 if (logger.isDebugEnabled()) {
98 logger.debug("{} Unknown protocol version: {}", ctx.channel(), versionVal & 0xFF);
99 }
100 }
101 }