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 import io.netty.util.NetUtil;
23 import io.netty.util.internal.UnstableApi;
24
25 import java.util.List;
26
27
28
29
30
31 public class SocksCmdResponseDecoder extends ReplayingDecoder<State> {
32
33 private SocksCmdStatus cmdStatus;
34 private SocksAddressType addressType;
35
36 public SocksCmdResponseDecoder() {
37 super(State.CHECK_PROTOCOL_VERSION);
38 }
39
40 @Override
41 protected void decode(ChannelHandlerContext ctx, ByteBuf byteBuf, List<Object> out) throws Exception {
42 switch (state()) {
43 case CHECK_PROTOCOL_VERSION: {
44 if (byteBuf.readByte() != SocksProtocolVersion.SOCKS5.byteValue()) {
45 out.add(SocksCommonUtils.UNKNOWN_SOCKS_RESPONSE);
46 break;
47 }
48 checkpoint(State.READ_CMD_HEADER);
49 }
50 case READ_CMD_HEADER: {
51 cmdStatus = SocksCmdStatus.valueOf(byteBuf.readByte());
52 byteBuf.skipBytes(1);
53 addressType = SocksAddressType.valueOf(byteBuf.readByte());
54 checkpoint(State.READ_CMD_ADDRESS);
55 }
56 case READ_CMD_ADDRESS: {
57 switch (addressType) {
58 case IPv4: {
59 String host = NetUtil.intToIpAddress(byteBuf.readInt());
60 int port = byteBuf.readUnsignedShort();
61 out.add(new SocksCmdResponse(cmdStatus, addressType, host, port));
62 break;
63 }
64 case DOMAIN: {
65 int fieldLength = byteBuf.readByte();
66 String host = SocksCommonUtils.readUsAscii(byteBuf, fieldLength);
67 int port = byteBuf.readUnsignedShort();
68 out.add(new SocksCmdResponse(cmdStatus, addressType, host, port));
69 break;
70 }
71 case IPv6: {
72 byte[] bytes = new byte[16];
73 byteBuf.readBytes(bytes);
74 String host = SocksCommonUtils.ipv6toStr(bytes);
75 int port = byteBuf.readUnsignedShort();
76 out.add(new SocksCmdResponse(cmdStatus, addressType, host, port));
77 break;
78 }
79 case UNKNOWN: {
80 out.add(SocksCommonUtils.UNKNOWN_SOCKS_RESPONSE);
81 break;
82 }
83 default: {
84 throw new Error();
85 }
86 }
87 break;
88 }
89 default: {
90 throw new Error();
91 }
92 }
93 ctx.pipeline().remove(this);
94 }
95
96 @UnstableApi
97 public enum State {
98 CHECK_PROTOCOL_VERSION,
99 READ_CMD_HEADER,
100 READ_CMD_ADDRESS
101 }
102 }