1 /*
2 * Copyright 2025 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.socksx.v5;
17
18 import io.netty.util.internal.ObjectUtil;
19
20 /**
21 * The status of a SOCKS5 private authentication response.
22 * <p>
23 * RFC 1928 reserves method codes 0x80-0xFE for private authentication methods but does not
24 * specify the format of their subnegotiation. This class provides standard status codes
25 * for the private authentication response that follow the pattern established by the
26 * username/password authentication method in RFC 1929.
27 * </p>
28 *
29 * @see <a href="https://www.ietf.org/rfc/rfc1928.txt">RFC 1928 Section 3</a>
30 * @see <a href="https://www.ietf.org/rfc/rfc1929.txt">RFC 1929</a>
31 */
32 public final class Socks5PrivateAuthStatus implements Comparable<Socks5PrivateAuthStatus> {
33
34 public static final Socks5PrivateAuthStatus SUCCESS = new Socks5PrivateAuthStatus(0x00, "SUCCESS");
35 public static final Socks5PrivateAuthStatus FAILURE = new Socks5PrivateAuthStatus(0xFF, "FAILURE");
36
37 /**
38 * Returns the {@link Socks5PrivateAuthStatus} instance that corresponds to the specified byte value.
39 * <p>
40 * This method returns a singleton instance for standard status codes:
41 * <ul>
42 * <li>0x00: {@link #SUCCESS}</li>
43 * <li>0xFF: {@link #FAILURE}</li>
44 * </ul>
45 * For any other values, a new instance is created.
46 *
47 * @param b The byte value of the SOCKS5 private authentication status
48 * @return The corresponding {@link Socks5PrivateAuthStatus} instance
49 */
50 public static Socks5PrivateAuthStatus valueOf(byte b) {
51 switch (b) {
52 case 0x00:
53 return SUCCESS;
54 case (byte) 0xFF:
55 return FAILURE;
56 }
57
58 return new Socks5PrivateAuthStatus(b);
59 }
60
61 private final byte byteValue;
62 private final String name;
63 private String text;
64
65 private Socks5PrivateAuthStatus(int byteValue) {
66 this(byteValue, "UNKNOWN");
67 }
68
69 /**
70 * Creates a new SOCKS5 private authentication status.
71 *
72 * @param byteValue The byte value representing the authentication status
73 * (0x00 for success, 0xFF for failure, or custom values)
74 * @param name The descriptive name of this status, must not be null
75 * @throws NullPointerException if the name is null
76 */
77 public Socks5PrivateAuthStatus(int byteValue, String name) {
78 this.name = ObjectUtil.checkNotNull(name, "name");
79 this.byteValue = (byte) byteValue;
80 }
81
82 public byte byteValue() {
83 return byteValue;
84 }
85
86 public boolean isSuccess() {
87 return byteValue == 0;
88 }
89
90 @Override
91 public int hashCode() {
92 return byteValue;
93 }
94
95 @Override
96 public boolean equals(Object obj) {
97 if (!(obj instanceof Socks5PrivateAuthStatus)) {
98 return false;
99 }
100
101 return byteValue == ((Socks5PrivateAuthStatus) obj).byteValue;
102 }
103
104 @Override
105 public int compareTo(Socks5PrivateAuthStatus o) {
106 return byteValue - o.byteValue;
107 }
108
109 @Override
110 public String toString() {
111 String text = this.text;
112 if (text == null) {
113 this.text = text = name + '(' + (byteValue & 0xFF) + ')';
114 }
115 return text;
116 }
117 }