Files
v2ray_simple/netLayer/addr.go
2022-03-22 16:46:05 +08:00

240 lines
4.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package netLayer
import (
"math/rand"
"net"
"net/url"
"strconv"
"strings"
"unsafe"
)
// Atyp, for vless and vmess; 注意与 trojan和socks5的区别trojan和socks5的相同含义的值是134
const (
AtypIP4 byte = 1
AtypDomain byte = 2
AtypIP6 byte = 3
)
// Addr represents a address that you want to access by proxy. Either Name or IP is used exclusively.
// Addr完整地表示了一个 传输层的目标,同时用 Network 字段 来记录网络层协议名
// Addr 还可以用Dial 方法直接进行拨号
type Addr struct {
Name string // domain name, 或者 unix domain socket 的 文件路径
IP net.IP
Port int
//IsUDP bool
Network string
}
func RandPortStr() string {
return strconv.Itoa(rand.Intn(60000) + 4096)
}
func GetRandLocalAddr() string {
return "0.0.0.0:" + RandPortStr()
}
func NewAddrFromUDPAddr(addr *net.UDPAddr) *Addr {
return &Addr{
IP: addr.IP,
Port: addr.Port,
Network: "udp",
}
}
//addrStr格式一般为 host:port 的格式;如果不含冒号,将直接认为该字符串是域名或文件名
func NewAddr(addrStr string) (*Addr, error) {
if !strings.Contains(addrStr, ":") {
//unix domain socket, 或者域名默认端口的情况
return &Addr{Name: addrStr}, nil
}
host, portStr, err := net.SplitHostPort(addrStr)
if err != nil {
return nil, err
}
if host == "" {
host = "127.0.0.1"
}
port, err := strconv.Atoi(portStr)
a := &Addr{Port: port}
if ip := net.ParseIP(host); ip != nil {
a.IP = ip
} else {
a.Name = host
}
return a, nil
}
// 如 tcp://127.0.0.1:443
func NewAddrByURL(addrStr string) (*Addr, error) {
u, err := url.Parse(addrStr)
if err != nil {
return nil, err
}
addrStr = u.Host
host, portStr, err := net.SplitHostPort(addrStr)
if err != nil {
return nil, err
}
if host == "" {
host = "127.0.0.1"
}
port, err := strconv.Atoi(portStr)
a := &Addr{Port: port}
if ip := net.ParseIP(host); ip != nil {
a.IP = ip
} else {
a.Name = host
}
a.Network = u.Scheme
return a, nil
}
// Return host:port string
func (a *Addr) String() string {
if a.Network == "unix" {
return a.Name
} else {
port := strconv.Itoa(a.Port)
if a.IP == nil {
return net.JoinHostPort(a.Name, port)
}
return net.JoinHostPort(a.IP.String(), port)
}
}
func (a *Addr) UrlString() string {
str := a.String()
return a.Network + "://" + str
}
func (a *Addr) ToUDPAddr() *net.UDPAddr {
if a.Network != "udp" {
return nil
}
ua, err := net.ResolveUDPAddr("udp", a.String())
if err != nil {
return nil
}
return ua
}
// Returned host string
func (a *Addr) HostStr() string {
if a.IP == nil {
return a.Name
}
return a.IP.String()
}
func (addr *Addr) Dial() (net.Conn, error) {
//log.Println("Dial called", addr, addr.Network)
switch addr.Network {
case "":
return net.Dial("tcp", addr.String())
case "udp":
return DialUDP(addr.ToUDPAddr())
default:
return net.Dial(addr.Network, addr.String())
}
}
// Returned address bytes and type
func (a *Addr) AddressBytes() ([]byte, byte) {
var addr []byte
var atyp byte
if a.IP != nil {
if ip4 := a.IP.To4(); ip4 != nil {
addr = make([]byte, net.IPv4len)
atyp = AtypIP4
copy(addr[:], ip4)
} else {
addr = make([]byte, net.IPv6len)
atyp = AtypIP6
copy(addr[:], a.IP)
}
} else {
if len(a.Name) > 255 {
return nil, 0
}
addr = make([]byte, 1+len(a.Name))
atyp = AtypDomain
addr[0] = byte(len(a.Name))
copy(addr[1:], a.Name)
}
return addr, atyp
}
// ParseAddr parses the address in string s
func ParseStrToAddr(s string) (atyp byte, addr []byte, port_uint16 uint16, err error) {
var host string
var portStr string
host, portStr, err = net.SplitHostPort(s)
if err != nil {
return
}
if ip := net.ParseIP(host); ip != nil {
if ip4 := ip.To4(); ip4 != nil {
addr = make([]byte, net.IPv4len)
atyp = AtypIP4
copy(addr[:], ip4)
} else {
addr = make([]byte, net.IPv6len)
atyp = AtypIP6
copy(addr[:], ip)
}
} else {
if len(host) > 255 {
return
}
addr = make([]byte, 1+len(host))
atyp = AtypDomain
addr[0] = byte(len(host))
copy(addr[1:], host)
}
var portUint64 uint64
portUint64, err = strconv.ParseUint(portStr, 10, 16)
if err != nil {
return
}
port_uint16 = uint16(portUint64)
return
}
func UDPAddr2Byte(addr *net.UDPAddr) [6]byte {
ip := addr.IP.To4()
port := uint16(addr.Port)
var allByte [6]byte
abs := allByte[:]
copy(abs, ip)
copy(abs[4:], (*(*[2]byte)(unsafe.Pointer(&port)))[:])
return allByte
}