1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
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  
22  import java.net.IDN;
23  
24  
25  
26  
27  
28  
29  
30  public final class SocksCmdRequest extends SocksRequest {
31      private final SocksCmdType cmdType;
32      private final SocksAddressType addressType;
33      private final String host;
34      private final int port;
35  
36      public SocksCmdRequest(SocksCmdType cmdType, SocksAddressType addressType, String host, int port) {
37          super(SocksRequestType.CMD);
38          if (cmdType == null) {
39              throw new NullPointerException("cmdType");
40          }
41          if (addressType == null) {
42              throw new NullPointerException("addressType");
43          }
44          if (host == null) {
45              throw new NullPointerException("host");
46          }
47          switch (addressType) {
48              case IPv4:
49                  if (!NetUtil.isValidIpV4Address(host)) {
50                      throw new IllegalArgumentException(host + " is not a valid IPv4 address");
51                  }
52                  break;
53              case DOMAIN:
54                  if (IDN.toASCII(host).length() > 255) {
55                      throw new IllegalArgumentException(host + " IDN: " + IDN.toASCII(host) + " exceeds 255 char limit");
56                  }
57                  break;
58              case IPv6:
59                  if (!NetUtil.isValidIpV6Address(host)) {
60                      throw new IllegalArgumentException(host + " is not a valid IPv6 address");
61                  }
62                  break;
63              case UNKNOWN:
64                  break;
65          }
66          if (port <= 0 || port >= 65536) {
67              throw new IllegalArgumentException(port + " is not in bounds 0 < x < 65536");
68          }
69          this.cmdType = cmdType;
70          this.addressType = addressType;
71          this.host = IDN.toASCII(host);
72          this.port = port;
73      }
74  
75      
76  
77  
78  
79  
80      public SocksCmdType cmdType() {
81          return cmdType;
82      }
83  
84      
85  
86  
87  
88  
89      public SocksAddressType addressType() {
90          return addressType;
91      }
92  
93      
94  
95  
96  
97  
98      public String host() {
99          return IDN.toUnicode(host);
100     }
101 
102     
103 
104 
105 
106 
107     public int port() {
108         return port;
109     }
110 
111     @Override
112     public void encodeAsByteBuf(ByteBuf byteBuf) {
113         byteBuf.writeByte(protocolVersion().byteValue());
114         byteBuf.writeByte(cmdType.byteValue());
115         byteBuf.writeByte(0x00);
116         byteBuf.writeByte(addressType.byteValue());
117         switch (addressType) {
118             case IPv4: {
119                 byteBuf.writeBytes(NetUtil.createByteArrayFromIpAddressString(host));
120                 byteBuf.writeShort(port);
121                 break;
122             }
123 
124             case DOMAIN: {
125                 byteBuf.writeByte(host.length());
126                 byteBuf.writeBytes(host.getBytes(CharsetUtil.US_ASCII));
127                 byteBuf.writeShort(port);
128                 break;
129             }
130 
131             case IPv6: {
132                 byteBuf.writeBytes(NetUtil.createByteArrayFromIpAddressString(host));
133                 byteBuf.writeShort(port);
134                 break;
135             }
136         }
137     }
138 }