github.com/sagernet/sing@v0.4.0-beta.19.0.20240518125136-f67a0988a636/common/metadata/addr.go (about) 1 package metadata 2 3 import ( 4 "net" 5 "net/netip" 6 "strconv" 7 "unsafe" 8 9 "github.com/sagernet/sing/common/debug" 10 ) 11 12 type Socksaddr struct { 13 Addr netip.Addr 14 Port uint16 15 Fqdn string 16 } 17 18 func (ap Socksaddr) Network() string { 19 return "socks" 20 } 21 22 func (ap Socksaddr) IsIP() bool { 23 return ap.Addr.IsValid() 24 } 25 26 func (ap Socksaddr) IsIPv4() bool { 27 return ap.Addr.Is4() 28 } 29 30 func (ap Socksaddr) IsIPv6() bool { 31 return ap.Addr.Is6() 32 } 33 34 func (ap Socksaddr) Unwrap() Socksaddr { 35 if ap.Addr.Is4In6() { 36 return Socksaddr{ 37 Addr: netip.AddrFrom4(ap.Addr.As4()), 38 Port: ap.Port, 39 } 40 } 41 return ap 42 } 43 44 func (ap Socksaddr) IsFqdn() bool { 45 return IsDomainName(ap.Fqdn) 46 } 47 48 func (ap Socksaddr) IsValid() bool { 49 return ap.IsIP() || ap.IsFqdn() 50 } 51 52 func (ap Socksaddr) AddrString() string { 53 if debug.Enabled { 54 ap.CheckBadAddr() 55 } 56 if ap.Addr.IsValid() { 57 return ap.Addr.String() 58 } else { 59 return ap.Fqdn 60 } 61 } 62 63 func (ap Socksaddr) IPAddr() *net.IPAddr { 64 if debug.Enabled { 65 ap.CheckBadAddr() 66 } 67 return &net.IPAddr{ 68 IP: ap.Addr.AsSlice(), 69 Zone: ap.Addr.Zone(), 70 } 71 } 72 73 func (ap Socksaddr) TCPAddr() *net.TCPAddr { 74 if debug.Enabled { 75 ap.CheckBadAddr() 76 } 77 return &net.TCPAddr{ 78 IP: ap.Addr.AsSlice(), 79 Port: int(ap.Port), 80 Zone: ap.Addr.Zone(), 81 } 82 } 83 84 func (ap Socksaddr) UDPAddr() *net.UDPAddr { 85 if debug.Enabled { 86 ap.CheckBadAddr() 87 } 88 return &net.UDPAddr{ 89 IP: ap.Addr.AsSlice(), 90 Port: int(ap.Port), 91 Zone: ap.Addr.Zone(), 92 } 93 } 94 95 func (ap Socksaddr) AddrPort() netip.AddrPort { 96 if debug.Enabled { 97 ap.CheckBadAddr() 98 } 99 return *(*netip.AddrPort)(unsafe.Pointer(&ap)) 100 } 101 102 func (ap Socksaddr) String() string { 103 if debug.Enabled { 104 ap.CheckBadAddr() 105 } 106 return net.JoinHostPort(ap.AddrString(), strconv.Itoa(int(ap.Port))) 107 } 108 109 func (ap Socksaddr) CheckBadAddr() { 110 if ap.Addr.Is4In6() || ap.Addr.IsValid() && ap.Fqdn != "" { 111 panic("bad socksaddr") 112 } 113 } 114 115 func AddrPortFrom(ip net.IP, port uint16) netip.AddrPort { 116 return netip.AddrPortFrom(AddrFromIP(ip), port) 117 } 118 119 func SocksaddrFrom(addr netip.Addr, port uint16) Socksaddr { 120 return SocksaddrFromNetIP(netip.AddrPortFrom(addr, port)) 121 } 122 123 func SocksaddrFromNetIP(ap netip.AddrPort) Socksaddr { 124 return Socksaddr{ 125 Addr: ap.Addr(), 126 Port: ap.Port(), 127 } 128 } 129 130 func SocksaddrFromNet(ap net.Addr) Socksaddr { 131 if ap == nil { 132 return Socksaddr{} 133 } 134 if socksAddr, ok := ap.(Socksaddr); ok { 135 return socksAddr 136 } 137 addr := SocksaddrFromNetIP(AddrPortFromNet(ap)) 138 if addr.IsValid() { 139 return addr 140 } 141 return ParseSocksaddr(ap.String()) 142 } 143 144 func AddrFromNet(netAddr net.Addr) netip.Addr { 145 if addr := AddrPortFromNet(netAddr); addr.Addr().IsValid() { 146 return addr.Addr() 147 } 148 switch addr := netAddr.(type) { 149 case Socksaddr: 150 return addr.Addr 151 case *net.IPAddr: 152 return AddrFromIP(addr.IP) 153 case *net.IPNet: 154 return AddrFromIP(addr.IP) 155 default: 156 return netip.Addr{} 157 } 158 } 159 160 func PrefixFromNet(netAddr net.Addr) netip.Prefix { 161 switch addr := netAddr.(type) { 162 case *net.IPNet: 163 bits, _ := addr.Mask.Size() 164 return netip.PrefixFrom(AddrFromIP(addr.IP), bits) 165 default: 166 return netip.Prefix{} 167 } 168 } 169 170 func AddrPortFromNet(netAddr net.Addr) netip.AddrPort { 171 var ip net.IP 172 var port uint16 173 switch addr := netAddr.(type) { 174 case Socksaddr: 175 return addr.AddrPort() 176 case *net.TCPAddr: 177 ip = addr.IP 178 port = uint16(addr.Port) 179 case *net.UDPAddr: 180 ip = addr.IP 181 port = uint16(addr.Port) 182 case *net.IPAddr: 183 ip = addr.IP 184 } 185 return netip.AddrPortFrom(AddrFromIP(ip), port) 186 } 187 188 func AddrFromIP(ip net.IP) netip.Addr { 189 addr, _ := netip.AddrFromSlice(ip) 190 return addr 191 } 192 193 func ParseAddr(address string) netip.Addr { 194 addr, _ := netip.ParseAddr(unwrapIPv6Address(address)) 195 return addr 196 } 197 198 func ParseSocksaddr(address string) Socksaddr { 199 host, port, err := net.SplitHostPort(address) 200 if err != nil { 201 return ParseSocksaddrHostPort(address, 0) 202 } 203 return ParseSocksaddrHostPortStr(host, port) 204 } 205 206 func ParseSocksaddrHostPort(host string, port uint16) Socksaddr { 207 netAddr, err := netip.ParseAddr(unwrapIPv6Address(host)) 208 if err != nil { 209 return Socksaddr{ 210 Fqdn: host, 211 Port: port, 212 } 213 } else { 214 return Socksaddr{ 215 Addr: netAddr, 216 Port: port, 217 } 218 } 219 } 220 221 func ParseSocksaddrHostPortStr(host string, portStr string) Socksaddr { 222 port, _ := strconv.Atoi(portStr) 223 netAddr, err := netip.ParseAddr(unwrapIPv6Address(host)) 224 if err != nil { 225 return Socksaddr{ 226 Fqdn: host, 227 Port: uint16(port), 228 } 229 } else { 230 return Socksaddr{ 231 Addr: netAddr, 232 Port: uint16(port), 233 } 234 } 235 } 236 237 func unwrapIPv6Address(address string) string { 238 if len(address) > 2 && address[0] == '[' && address[len(address)-1] == ']' { 239 return address[1 : len(address)-1] 240 } 241 return address 242 }