View Javadoc
1   /*
2    * Copyright 2012 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
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   * Decodes {@link ChannelBuffer}s into {@link SocksCmdResponse}.
26   * Before returning SocksResponse decoder removes itself from pipeline.
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  }