1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.handler.codec.socks;
17
18 import io.netty.buffer.ByteBuf;
19 import io.netty.channel.ChannelHandlerContext;
20 import io.netty.handler.codec.ReplayingDecoder;
21 import io.netty.handler.codec.socks.SocksCmdResponseDecoder.State;
22
23 import java.util.List;
24
25
26
27
28
29 public class SocksCmdResponseDecoder extends ReplayingDecoder<State> {
30 private static final String name = "SOCKS_CMD_RESPONSE_DECODER";
31
32
33
34
35 @Deprecated
36 public static String getName() {
37 return name;
38 }
39
40 private SocksCmdStatus cmdStatus;
41 private SocksAddressType addressType;
42
43 public SocksCmdResponseDecoder() {
44 super(State.CHECK_PROTOCOL_VERSION);
45 }
46
47 @Override
48 protected void decode(ChannelHandlerContext ctx, ByteBuf byteBuf, List<Object> out) throws Exception {
49 switch (state()) {
50 case CHECK_PROTOCOL_VERSION: {
51 if (byteBuf.readByte() != SocksProtocolVersion.SOCKS5.byteValue()) {
52 out.add(SocksCommonUtils.UNKNOWN_SOCKS_RESPONSE);
53 break;
54 }
55 checkpoint(State.READ_CMD_HEADER);
56 }
57 case READ_CMD_HEADER: {
58 cmdStatus = SocksCmdStatus.valueOf(byteBuf.readByte());
59 byteBuf.skipBytes(1);
60 addressType = SocksAddressType.valueOf(byteBuf.readByte());
61 checkpoint(State.READ_CMD_ADDRESS);
62 }
63 case READ_CMD_ADDRESS: {
64 switch (addressType) {
65 case IPv4: {
66 String host = SocksCommonUtils.intToIp(byteBuf.readInt());
67 int port = byteBuf.readUnsignedShort();
68 out.add(new SocksCmdResponse(cmdStatus, addressType, host, port));
69 break;
70 }
71 case DOMAIN: {
72 int fieldLength = byteBuf.readByte();
73 String host = SocksCommonUtils.readUsAscii(byteBuf, fieldLength);
74 int port = byteBuf.readUnsignedShort();
75 out.add(new SocksCmdResponse(cmdStatus, addressType, host, port));
76 break;
77 }
78 case IPv6: {
79 byte[] bytes = new byte[16];
80 byteBuf.readBytes(bytes);
81 String host = SocksCommonUtils.ipv6toStr(bytes);
82 int port = byteBuf.readUnsignedShort();
83 out.add(new SocksCmdResponse(cmdStatus, addressType, host, port));
84 break;
85 }
86 case UNKNOWN: {
87 out.add(SocksCommonUtils.UNKNOWN_SOCKS_RESPONSE);
88 break;
89 }
90 default: {
91 throw new Error();
92 }
93 }
94 break;
95 }
96 default: {
97 throw new Error();
98 }
99 }
100 ctx.pipeline().remove(this);
101 }
102
103 enum State {
104 CHECK_PROTOCOL_VERSION,
105 READ_CMD_HEADER,
106 READ_CMD_ADDRESS
107 }
108 }