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      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 }