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