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
30 private SocksMessage.ProtocolVersion version;
31 private int fieldLength;
32 private SocksMessage.CmdStatus cmdStatus;
33 private SocksMessage.AddressType addressType;
34 private byte reserved;
35 private String host;
36 private int port;
37 private SocksResponse msg = SocksCommonUtils.UNKNOWN_SOCKS_RESPONSE;
38
39 public SocksCmdResponseDecoder() {
40 super(State.CHECK_PROTOCOL_VERSION);
41 }
42
43 @Override
44 protected Object decode(ChannelHandlerContext ctx, Channel channel,
45 ChannelBuffer buffer, State state) throws Exception {
46 switch (state) {
47 case CHECK_PROTOCOL_VERSION: {
48 version = SocksMessage.ProtocolVersion.fromByte(buffer.readByte());
49 if (version != SocksMessage.ProtocolVersion.SOCKS5) {
50 break;
51 }
52 checkpoint(State.READ_CMD_HEADER);
53 }
54 case READ_CMD_HEADER: {
55 cmdStatus = SocksMessage.CmdStatus.fromByte(buffer.readByte());
56 reserved = buffer.readByte();
57 addressType = SocksMessage.AddressType.fromByte(buffer.readByte());
58 checkpoint(State.READ_CMD_ADDRESS);
59 }
60 case READ_CMD_ADDRESS: {
61 switch (addressType) {
62 case IPv4: {
63 host = SocksCommonUtils.intToIp(buffer.readInt());
64 port = buffer.readUnsignedShort();
65 msg = new SocksCmdResponse(cmdStatus, addressType);
66 break;
67 }
68 case DOMAIN: {
69 fieldLength = buffer.readByte();
70 host = buffer.readBytes(fieldLength).toString(CharsetUtil.US_ASCII);
71 port = buffer.readUnsignedShort();
72 msg = new SocksCmdResponse(cmdStatus, addressType);
73 break;
74 }
75 case IPv6: {
76 host = SocksCommonUtils.ipv6toStr(buffer.readBytes(16).array());
77 port = buffer.readUnsignedShort();
78 msg = new SocksCmdResponse(cmdStatus, addressType);
79 break;
80 }
81 case UNKNOWN:
82 break;
83 }
84 }
85 }
86 ctx.getPipeline().remove(this);
87 return msg;
88 }
89
90 public enum State {
91 CHECK_PROTOCOL_VERSION,
92 READ_CMD_HEADER,
93 READ_CMD_ADDRESS
94 }
95 }