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.util.NetUtil;
20  import org.jboss.netty.util.internal.DetectionUtil;
21  
22  import java.net.IDN;
23  
24  /**
25   * An socks cmd request.
26   *
27   * @see {@link SocksCmdResponse}
28   * @see {@link SocksCmdRequestDecoder}
29   */
30  public final class SocksCmdRequest extends SocksRequest {
31      private final CmdType cmdType;
32      private final AddressType addressType;
33      private final String host;
34      private final int port;
35  
36      public SocksCmdRequest(CmdType cmdType, AddressType addressType, String host, int port) {
37          super(SocksRequestType.CMD);
38          if (DetectionUtil.javaVersion() < 6) {
39              throw new IllegalStateException("Only supported with Java version 6+");
40          }
41          if (cmdType == null) {
42              throw new NullPointerException("cmdType");
43          }
44          if (addressType == null) {
45              throw new NullPointerException("addressType");
46          }
47          if (host == null) {
48              throw new NullPointerException("host");
49          }
50          switch (addressType) {
51              case IPv4:
52                  if (!NetUtil.isValidIpV4Address(host)) {
53                      throw new IllegalArgumentException(host + " is not a valid IPv4 address");
54                  }
55                  break;
56              case DOMAIN:
57                  if (IDN.toASCII(host).length() > 255) {
58                      throw new IllegalArgumentException(host + " IDN: " + IDN.toASCII(host) + " exceeds 255 char limit");
59                  }
60                  break;
61              case IPv6:
62                  if (!NetUtil.isValidIpV6Address(host)) {
63                      throw new IllegalArgumentException(host + " is not a valid IPv6 address");
64                  }
65                  break;
66              case UNKNOWN:
67                  break;
68          }
69          if (port <= 0 || port >= 65536) {
70              throw new IllegalArgumentException(port + " is not in bounds 0 < x < 65536");
71          }
72          this.cmdType = cmdType;
73          this.addressType = addressType;
74          this.host = IDN.toASCII(host);
75          this.port = port;
76      }
77  
78      /**
79       * Returns the {@link SocksMessage.CmdType} of this {@link SocksCmdRequest}
80       */
81      public CmdType getCmdType() {
82          return cmdType;
83      }
84  
85      /**
86       * Returns the {@link AddressType} of this {@link SocksCmdRequest}
87       */
88      public AddressType getAddressType() {
89          return addressType;
90      }
91  
92      /**
93       * Returns host that is used as a parameter in {@link SocksMessage.CmdType}
94       */
95      public String getHost() {
96          return IDN.toUnicode(host);
97      }
98  
99      /**
100      * Returns port that is used as a parameter in {@link SocksMessage.CmdType}
101      */
102     public int getPort() {
103         return port;
104     }
105 
106     @Override
107     public void encodeAsByteBuf(ChannelBuffer channelBuffer) throws Exception {
108         channelBuffer.writeByte(getProtocolVersion().getByteValue());
109         channelBuffer.writeByte(cmdType.getByteValue());
110         channelBuffer.writeByte(0x00);
111         channelBuffer.writeByte(addressType.getByteValue());
112         switch (addressType) {
113             case IPv4: {
114                 channelBuffer.writeBytes(NetUtil.createByteArrayFromIpAddressString(host));
115                 channelBuffer.writeShort(port);
116                 break;
117             }
118 
119             case DOMAIN: {
120                 channelBuffer.writeByte(host.length());
121                 channelBuffer.writeBytes(host.getBytes("US-ASCII"));
122                 channelBuffer.writeShort(port);
123                 break;
124             }
125 
126             case IPv6: {
127                 channelBuffer.writeBytes(NetUtil.createByteArrayFromIpAddressString(host));
128                 channelBuffer.writeShort(port);
129                 break;
130             }
131         }
132     }
133 }