1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package io.netty.handler.codec.socksx.v5;
18
19 import io.netty.buffer.ByteBuf;
20 import io.netty.buffer.ByteBufUtil;
21 import io.netty.channel.ChannelHandlerContext;
22 import io.netty.handler.codec.DecoderException;
23 import io.netty.handler.codec.DecoderResult;
24 import io.netty.handler.codec.ReplayingDecoder;
25 import io.netty.handler.codec.socksx.SocksVersion;
26 import io.netty.handler.codec.socksx.v5.Socks5CommandRequestDecoder.State;
27 import io.netty.util.internal.ObjectUtil;
28 import io.netty.util.internal.UnstableApi;
29
30 import java.util.List;
31
32
33
34
35
36
37
38 public class Socks5CommandRequestDecoder extends ReplayingDecoder<State> {
39
40 @UnstableApi
41 public enum State {
42 INIT,
43 SUCCESS,
44 FAILURE
45 }
46
47 private final Socks5AddressDecoder addressDecoder;
48
49 public Socks5CommandRequestDecoder() {
50 this(Socks5AddressDecoder.DEFAULT);
51 }
52
53 public Socks5CommandRequestDecoder(Socks5AddressDecoder addressDecoder) {
54 super(State.INIT);
55 this.addressDecoder = ObjectUtil.checkNotNull(addressDecoder, "addressDecoder");
56 }
57
58 @Override
59 protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
60 try {
61 switch (state()) {
62 case INIT: {
63 final byte version = in.readByte();
64 if (version != SocksVersion.SOCKS5.byteValue()) {
65 throw new DecoderException(
66 "unsupported version: " + version + " (expected: " + SocksVersion.SOCKS5.byteValue() + ')');
67 }
68
69 final Socks5CommandType type = Socks5CommandType.valueOf(in.readByte());
70 in.skipBytes(1);
71 final Socks5AddressType dstAddrType = Socks5AddressType.valueOf(in.readByte());
72 final String dstAddr = addressDecoder.decodeAddress(dstAddrType, in);
73 final int dstPort = ByteBufUtil.readUnsignedShortBE(in);
74
75 out.add(new DefaultSocks5CommandRequest(type, dstAddrType, dstAddr, dstPort));
76 checkpoint(State.SUCCESS);
77 }
78 case SUCCESS: {
79 int readableBytes = actualReadableBytes();
80 if (readableBytes > 0) {
81 out.add(in.readRetainedSlice(readableBytes));
82 }
83 break;
84 }
85 case FAILURE: {
86 in.skipBytes(actualReadableBytes());
87 break;
88 }
89 }
90 } catch (Exception e) {
91 fail(out, e);
92 }
93 }
94
95 private void fail(List<Object> out, Exception cause) {
96 if (!(cause instanceof DecoderException)) {
97 cause = new DecoderException(cause);
98 }
99
100 checkpoint(State.FAILURE);
101
102 Socks5Message m = new DefaultSocks5CommandRequest(
103 Socks5CommandType.CONNECT, Socks5AddressType.IPv4, "0.0.0.0", 1);
104 m.setDecoderResult(DecoderResult.failure(cause));
105 out.add(m);
106 }
107 }