1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.jboss.netty.handler.codec.socks;
17
18 import org.jboss.netty.buffer.ChannelBuffer;
19 import org.jboss.netty.channel.Channel;
20 import org.jboss.netty.channel.ChannelHandlerContext;
21 import org.jboss.netty.handler.codec.replay.ReplayingDecoder;
22 import org.jboss.netty.util.CharsetUtil;
23
24
25
26
27
28 public class SocksCmdResponseDecoder extends ReplayingDecoder<SocksCmdResponseDecoder.State> {
29 private static final String name = "SOCKS_CMD_RESPONSE_DECODER";
30
31 public static String getName() {
32 return name;
33 }
34
35 private SocksMessage.ProtocolVersion version;
36 private int fieldLength;
37 private SocksMessage.CmdStatus cmdStatus;
38 private SocksMessage.AddressType addressType;
39 private byte reserved;
40 private String host;
41 private int port;
42 private SocksResponse msg = SocksCommonUtils.UNKNOWN_SOCKS_RESPONSE;
43
44 public SocksCmdResponseDecoder() {
45 super(State.CHECK_PROTOCOL_VERSION);
46 }
47
48 @Override
49 protected Object decode(ChannelHandlerContext ctx, Channel channel,
50 ChannelBuffer buffer, State state) throws Exception {
51 switch (state) {
52 case CHECK_PROTOCOL_VERSION: {
53 version = SocksMessage.ProtocolVersion.fromByte(buffer.readByte());
54 if (version != SocksMessage.ProtocolVersion.SOCKS5) {
55 break;
56 }
57 checkpoint(State.READ_CMD_HEADER);
58 }
59 case READ_CMD_HEADER: {
60 cmdStatus = SocksMessage.CmdStatus.fromByte(buffer.readByte());
61 reserved = buffer.readByte();
62 addressType = SocksMessage.AddressType.fromByte(buffer.readByte());
63 checkpoint(State.READ_CMD_ADDRESS);
64 }
65 case READ_CMD_ADDRESS: {
66 switch (addressType) {
67 case IPv4: {
68 host = SocksCommonUtils.intToIp(buffer.readInt());
69 port = buffer.readUnsignedShort();
70 msg = new SocksCmdResponse(cmdStatus, addressType);
71 break;
72 }
73 case DOMAIN: {
74 fieldLength = buffer.readByte();
75 host = buffer.readBytes(fieldLength).toString(CharsetUtil.US_ASCII);
76 port = buffer.readUnsignedShort();
77 msg = new SocksCmdResponse(cmdStatus, addressType);
78 break;
79 }
80 case IPv6: {
81 host = SocksCommonUtils.ipv6toStr(buffer.readBytes(16).array());
82 port = buffer.readUnsignedShort();
83 msg = new SocksCmdResponse(cmdStatus, addressType);
84 break;
85 }
86 case UNKNOWN:
87 break;
88 }
89 }
90 }
91 ctx.getPipeline().remove(this);
92 return msg;
93 }
94
95 public enum State {
96 CHECK_PROTOCOL_VERSION,
97 READ_CMD_HEADER,
98 READ_CMD_ADDRESS
99 }
100 }