Skip to content

Commit 6dfa503

Browse files
committed
add ReplyError, unify naming and errors
1 parent 9c597b6 commit 6dfa503

File tree

11 files changed

+114
-51
lines changed

11 files changed

+114
-51
lines changed

client/client.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ func (cli *Client) connect(ctx context.Context, proxyconn net.Conn, cmd socks5.C
141141
defer proxyconn.SetDeadline(time.Time{})
142142
}
143143
if err = cli.connectAuth(proxyconn); err == nil {
144-
err = socks5.ErrUnsupportedCommand
144+
err = socks5.ErrReplyCommandNotSupported
145145
switch cmd {
146146
case socks5.CommandConnect:
147147
if addr, err = cli.connectCommand(proxyconn, socks5.CommandConnect, address); err == nil {
@@ -233,7 +233,7 @@ func (cli *Client) readReply(conn net.Conn) (addr socks5.Addr, err error) {
233233
if _, err = io.ReadFull(conn, header[:]); err == nil {
234234
if err = socks5.MustEqual(header[0], socks5.Socks5Version, socks5.ErrVersion); err == nil {
235235
replyCode := socks5.ReplyCode(header[1])
236-
if err = socks5.MustEqual(replyCode, socks5.Success, replyCode.ToError()); err == nil {
236+
if err = socks5.MustEqual(replyCode, socks5.ReplySuccess, replyCode.ToError()); err == nil {
237237
addr, err = socks5.ReadAddr(conn)
238238
}
239239
}

errors.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ var (
1010
ErrVersion = errors.New("invalid SOCKS version")
1111
ErrInvalidPortNumber = errors.New("invalid port number")
1212
ErrBadSOCKSAuthVersion = errors.New("bad SOCKS auth version")
13-
ErrUnsupportedCommand = errors.New("unsupported command")
1413
ErrAuthFailed = errors.New("authentication failed")
1514
ErrInvalidUDPPacket = errors.New("invalid udp packet")
1615
ErrFragmentedUDPPacket = errors.New("fragmented udp packet")

replycode.go

Lines changed: 20 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,39 @@
11
package socks5
22

33
import (
4-
"errors"
54
"fmt"
65
)
76

8-
// ReplyCode are the bytes sent in SOCKS5 packets
9-
// that represent replies from the server to a client
10-
// request.
7+
// ReplyCode is the reply code in SOCKS5 packets sent from the server to a client.
118
type ReplyCode byte
129

13-
// The set of valid SOCKS5 reply types as per the RFC 1928.
1410
const (
15-
Success ReplyCode = 0
16-
GeneralFailure ReplyCode = 1
17-
ConnectionNotAllowed ReplyCode = 2
18-
NetworkUnreachable ReplyCode = 3
19-
HostUnreachable ReplyCode = 4
20-
ConnectionRefused ReplyCode = 5
21-
TtlExpired ReplyCode = 6
22-
CommandNotSupported ReplyCode = 7
23-
AddrTypeNotSupported ReplyCode = 8
24-
)
25-
26-
var (
27-
ErrGeneralFailure = errors.New("general failure")
28-
ErrConnectionNotAllowed = errors.New("connection not allowed")
29-
ErrNetworkUnreachable = errors.New("network unreachable")
30-
ErrHostUnreachable = errors.New("host unreachable")
31-
ErrConnectionRefused = errors.New("connection refused")
32-
ErrTtlExpired = errors.New("ttl expired")
33-
ErrCommandNotSupported = errors.New("command not supported")
34-
ErrAddrTypeNotSupported = errors.New("address type not supported")
11+
ReplySuccess ReplyCode = 0
12+
ReplyGeneralFailure ReplyCode = 1
13+
ReplyConnectionNotAllowed ReplyCode = 2
14+
ReplyNetworkUnreachable ReplyCode = 3
15+
ReplyHostUnreachable ReplyCode = 4
16+
ReplyConnectionRefused ReplyCode = 5
17+
ReplyTTLExpired ReplyCode = 6
18+
ReplyCommandNotSupported ReplyCode = 7
19+
ReplyAddrTypeNotSupported ReplyCode = 8
3520
)
3621

3722
var replyCodeError = map[ReplyCode]error{
38-
Success: nil,
39-
GeneralFailure: ErrGeneralFailure,
40-
ConnectionNotAllowed: ErrConnectionNotAllowed,
41-
NetworkUnreachable: ErrNetworkUnreachable,
42-
HostUnreachable: ErrHostUnreachable,
43-
ConnectionRefused: ErrConnectionRefused,
44-
TtlExpired: ErrTtlExpired,
45-
CommandNotSupported: ErrCommandNotSupported,
46-
AddrTypeNotSupported: ErrAddrTypeNotSupported,
23+
ReplySuccess: nil,
24+
ReplyGeneralFailure: ErrReplyGeneralFailure,
25+
ReplyConnectionNotAllowed: ErrReplyConnectionNotAllowed,
26+
ReplyNetworkUnreachable: ErrReplyNetworkUnreachable,
27+
ReplyHostUnreachable: ErrReplyHostUnreachable,
28+
ReplyConnectionRefused: ErrReplyConnectionRefused,
29+
ReplyTTLExpired: ErrReplyTTLExpired,
30+
ReplyCommandNotSupported: ErrReplyCommandNotSupported,
31+
ReplyAddrTypeNotSupported: ErrReplyAddrTypeNotSupported,
4732
}
4833

4934
func (code ReplyCode) ToError() error {
5035
if err, ok := replyCodeError[code]; ok {
5136
return err
5237
}
53-
return fmt.Errorf("code(%d)", int(code))
38+
return fmt.Errorf("socks5code(%v)", code)
5439
}

replycode_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ func TestReplyCode_ToError(t *testing.T) {
99
}
1010
}
1111
code := ReplyCode(254)
12-
if x := code.ToError().Error(); x != "code(254)" {
12+
if x := code.ToError().Error(); x != "socks5code(254)" {
1313
t.Error(x)
1414
}
1515
}

replyerror.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package socks5
2+
3+
import "fmt"
4+
5+
type ReplyError struct {
6+
ReplyCode
7+
}
8+
9+
var replyErrorText = []string{
10+
ReplySuccess: "success",
11+
ReplyGeneralFailure: "general failure",
12+
ReplyConnectionNotAllowed: "connection not allowed",
13+
ReplyNetworkUnreachable: "network unreachable",
14+
ReplyHostUnreachable: "host unreachable",
15+
ReplyConnectionRefused: "connection refused",
16+
ReplyTTLExpired: "ttl expired",
17+
ReplyCommandNotSupported: "command not supported",
18+
ReplyAddrTypeNotSupported: "address type not supported",
19+
}
20+
21+
var (
22+
ErrReply = ReplyError{ReplyGeneralFailure} // for testing against with errors.Is()
23+
ErrReplySuccess = ReplyError{ReplySuccess}
24+
ErrReplyGeneralFailure = ReplyError{ReplyGeneralFailure}
25+
ErrReplyConnectionNotAllowed = ReplyError{ReplyConnectionNotAllowed}
26+
ErrReplyNetworkUnreachable = ReplyError{ReplyNetworkUnreachable}
27+
ErrReplyHostUnreachable = ReplyError{ReplyHostUnreachable}
28+
ErrReplyConnectionRefused = ReplyError{ReplyConnectionRefused}
29+
ErrReplyTTLExpired = ReplyError{ReplyTTLExpired}
30+
ErrReplyCommandNotSupported = ReplyError{ReplyCommandNotSupported}
31+
ErrReplyAddrTypeNotSupported = ReplyError{ReplyAddrTypeNotSupported}
32+
)
33+
34+
func (re ReplyError) Error() string {
35+
if int(re.ReplyCode) < len(replyErrorText) {
36+
return replyErrorText[re.ReplyCode]
37+
}
38+
return fmt.Sprintf("socks5code(%v)", re.ReplyCode)
39+
}
40+
41+
func (re ReplyError) Is(target error) (yes bool) {
42+
return target == ErrReply
43+
}

replyerror_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package socks5_test
2+
3+
import (
4+
"errors"
5+
"strings"
6+
"testing"
7+
8+
"github.com/linkdata/socks5"
9+
)
10+
11+
func TestReplyError(t *testing.T) {
12+
err := socks5.ErrReplyConnectionRefused
13+
if !strings.Contains(err.Error(), "refused") {
14+
t.Error(err.Error())
15+
}
16+
if !errors.Is(err, socks5.ErrReplyConnectionRefused) {
17+
t.Error(err)
18+
}
19+
if !errors.Is(err, socks5.ErrReply) {
20+
t.Errorf("%#v", err)
21+
}
22+
if errors.Is(err, socks5.ErrReplyHostUnreachable) {
23+
t.Error(err)
24+
}
25+
26+
re := socks5.ReplyError{99}
27+
if x := re.Error(); x != "socks5code(99)" {
28+
t.Error(x)
29+
}
30+
}

server/dialerselector.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,9 @@ import "github.com/linkdata/socks5"
55
// A socks5.DialerSelector returns the ContextDialer to use.
66
type DialerSelector interface {
77
// Socks5SelectDialer returns the ContextDialer to use.
8+
//
9+
// When called, client has already logged in using the given AuthMethod and username.
10+
// In case of error, it is recommended to return one of the socks5.ErrReply... errors,
11+
// as those will be mapped to SOCKS5 error codes in the reply to the client.
812
Socks5SelectDialer(am socks5.AuthMethod, username, network, address string) (cd socks5.ContextDialer, err error)
913
}

server/handleassociate.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ func (sess *session) handleASSOCIATE(ctx context.Context) (err error) {
2626
var bindPort uint16
2727
if bindAddr, bindPort, err = socks5.SplitHostPort(clientUDPConn.LocalAddr().String()); err == nil {
2828
res := &Response{
29-
Reply: socks5.Success,
29+
Reply: socks5.ReplySuccess,
3030
Addr: socks5.AddrFromHostPort(bindAddr, bindPort),
3131
}
3232
var buf []byte
@@ -40,7 +40,7 @@ func (sess *session) handleASSOCIATE(ctx context.Context) (err error) {
4040
}
4141
}
4242
sess.maybeLogError(err, "ASSOCIATE", "session", sess.conn.RemoteAddr())
43-
return sess.fail(socks5.GeneralFailure, err)
43+
return sess.fail(err)
4444
}
4545

4646
func (sess *session) serveUDP(ctx context.Context, clientTCPConn net.Conn, clientUDPConn net.PacketConn) (err error) {

server/handlebind.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,15 @@ func (sess *session) handleBIND(ctx context.Context, bindaddr string) (err error
2424
defer listener.Close()
2525
var addr socks5.Addr
2626
if addr, err = socks5.AddrFromString(listener.Addr().String()); err == nil {
27-
if err = sendReply(sess.conn, socks5.Success, addr); err == nil {
27+
if err = sendReply(sess.conn, socks5.ReplySuccess, addr); err == nil {
2828
_ = sess.Debug && sess.LogDebug("BIND", "session", sess.conn.RemoteAddr(), "listen", addr)
2929
var conn net.Conn
3030
if conn, err = listener.Accept(); err == nil {
3131
defer conn.Close()
3232
var remoteAddr socks5.Addr
3333
if remoteAddr, err = socks5.AddrFromString(conn.RemoteAddr().String()); err == nil {
3434
_ = sess.Debug && sess.LogDebug("BIND", "session", sess.conn.RemoteAddr(), "remote-bound", remoteAddr)
35-
if err = sendReply(sess.conn, socks5.Success, remoteAddr); err == nil {
35+
if err = sendReply(sess.conn, socks5.ReplySuccess, remoteAddr); err == nil {
3636
_ = sess.Debug && sess.LogDebug("BIND", "session", sess.conn.RemoteAddr(), "remote-start", remoteAddr)
3737
ctx, cancel := context.WithCancel(ctx)
3838
go func() {
@@ -53,6 +53,6 @@ func (sess *session) handleBIND(ctx context.Context, bindaddr string) (err error
5353
}
5454
}
5555
sess.maybeLogError(err, "BIND", "session", sess.conn.RemoteAddr(), "adress", bindaddr)
56-
_ = sendReply(sess.conn, socks5.GeneralFailure, socks5.ZeroAddr)
56+
_ = sendReply(sess.conn, socks5.ReplyGeneralFailure, socks5.ZeroAddr)
5757
return
5858
}

server/handleconnect.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ func (sess *session) handleCONNECT(ctx context.Context, addr string) (err error)
2323
var serverPort uint16
2424
if serverAddr, serverPort, err = socks5.SplitHostPort(localAddr); err == nil {
2525
res := &Response{
26-
Reply: socks5.Success,
26+
Reply: socks5.ReplySuccess,
2727
Addr: socks5.AddrFromHostPort(serverAddr, serverPort),
2828
}
2929
var buf []byte
@@ -44,5 +44,5 @@ func (sess *session) handleCONNECT(ctx context.Context, addr string) (err error)
4444
}
4545
}
4646
sess.maybeLogError(err, "CONNECT", "session", sess.conn.RemoteAddr(), "adress", addr)
47-
return sess.fail(socks5.GeneralFailure, err)
47+
return sess.fail(err)
4848
}

0 commit comments

Comments
 (0)