2021-11-22 16:05:02 +00:00

136 lines
2.8 KiB
Go

package socks5
import (
"bytes"
"encoding/binary"
"errors"
"net"
"strconv"
)
// ParseAddress format address x.x.x.x:xx to raw address.
// addr contains domain length
func ParseAddress(address string) (a byte, addr []byte, port []byte, err error) {
var h, p string
h, p, err = net.SplitHostPort(address)
if err != nil {
return
}
ip := net.ParseIP(h)
if ip4 := ip.To4(); ip4 != nil {
a = ATYPIPv4
addr = []byte(ip4)
} else if ip6 := ip.To16(); ip6 != nil {
a = ATYPIPv6
addr = []byte(ip6)
} else {
a = ATYPDomain
addr = []byte{byte(len(h))}
addr = append(addr, []byte(h)...)
}
i, _ := strconv.Atoi(p)
port = make([]byte, 2)
binary.BigEndian.PutUint16(port, uint16(i))
return
}
// bytes to address
// addr contains domain length
func ParseBytesAddress(b []byte) (a byte, addr []byte, port []byte, err error) {
if len(b) < 1 {
err = errors.New("Invalid address")
return
}
a = b[0]
if a == ATYPIPv4 {
if len(b) < 1+4+2 {
err = errors.New("Invalid address")
return
}
addr = b[1 : 1+4]
port = b[1+4 : 1+4+2]
return
}
if a == ATYPIPv6 {
if len(b) < 1+16+2 {
err = errors.New("Invalid address")
return
}
addr = b[1 : 1+16]
port = b[1+16 : 1+16+2]
return
}
if a == ATYPDomain {
if len(b) < 1+1 {
err = errors.New("Invalid address")
return
}
l := int(b[1])
if len(b) < 1+1+l+2 {
err = errors.New("Invalid address")
return
}
addr = b[1 : 1+1+l]
port = b[1+1+l : 1+1+l+2]
return
}
err = errors.New("Invalid address")
return
}
// ToAddress format raw address to x.x.x.x:xx
// addr contains domain length
func ToAddress(a byte, addr []byte, port []byte) string {
var h, p string
if a == ATYPIPv4 || a == ATYPIPv6 {
h = net.IP(addr).String()
}
if a == ATYPDomain {
if len(addr) < 1 {
return ""
}
if len(addr) < int(addr[0])+1 {
return ""
}
h = string(addr[1:])
}
p = strconv.Itoa(int(binary.BigEndian.Uint16(port)))
return net.JoinHostPort(h, p)
}
// Address return request address like ip:xx
func (r *Request) Address() string {
var s string
if r.Atyp == ATYPDomain {
s = bytes.NewBuffer(r.DstAddr[1:]).String()
} else {
s = net.IP(r.DstAddr).String()
}
p := strconv.Itoa(int(binary.BigEndian.Uint16(r.DstPort)))
return net.JoinHostPort(s, p)
}
// Address return request address like ip:xx
func (r *Reply) Address() string {
var s string
if r.Atyp == ATYPDomain {
s = bytes.NewBuffer(r.BndAddr[1:]).String()
} else {
s = net.IP(r.BndAddr).String()
}
p := strconv.Itoa(int(binary.BigEndian.Uint16(r.BndPort)))
return net.JoinHostPort(s, p)
}
// Address return datagram address like ip:xx
func (d *Datagram) Address() string {
var s string
if d.Atyp == ATYPDomain {
s = bytes.NewBuffer(d.DstAddr[1:]).String()
} else {
s = net.IP(d.DstAddr).String()
}
p := strconv.Itoa(int(binary.BigEndian.Uint16(d.DstPort)))
return net.JoinHostPort(s, p)
}