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