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