1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2025-01-17 14:57:44 -05:00

completely move away from net package

This commit is contained in:
Darien Raymond 2017-08-29 14:32:54 +02:00
parent 815019f6da
commit 52ad41cda3
11 changed files with 78 additions and 78 deletions

View File

@ -2,11 +2,10 @@ package router
import ( import (
"context" "context"
"net"
"regexp" "regexp"
"strings" "strings"
v2net "v2ray.com/core/common/net" "v2ray.com/core/common/net"
"v2ray.com/core/common/protocol" "v2ray.com/core/common/protocol"
"v2ray.com/core/proxy" "v2ray.com/core/proxy"
) )
@ -159,7 +158,7 @@ func (v *CIDRMatcher) Apply(ctx context.Context) bool {
} }
} }
var dest v2net.Destination var dest net.Destination
var ok bool var ok bool
if v.onSource { if v.onSource {
dest, ok = proxy.SourceFromContext(ctx) dest, ok = proxy.SourceFromContext(ctx)
@ -180,11 +179,11 @@ func (v *CIDRMatcher) Apply(ctx context.Context) bool {
} }
type IPv4Matcher struct { type IPv4Matcher struct {
ipv4net *v2net.IPNetTable ipv4net *net.IPNetTable
onSource bool onSource bool
} }
func NewIPv4Matcher(ipnet *v2net.IPNetTable, onSource bool) *IPv4Matcher { func NewIPv4Matcher(ipnet *net.IPNetTable, onSource bool) *IPv4Matcher {
return &IPv4Matcher{ return &IPv4Matcher{
ipv4net: ipnet, ipv4net: ipnet,
onSource: onSource, onSource: onSource,
@ -202,7 +201,7 @@ func (v *IPv4Matcher) Apply(ctx context.Context) bool {
} }
} }
var dest v2net.Destination var dest net.Destination
var ok bool var ok bool
if v.onSource { if v.onSource {
dest, ok = proxy.SourceFromContext(ctx) dest, ok = proxy.SourceFromContext(ctx)
@ -223,10 +222,10 @@ func (v *IPv4Matcher) Apply(ctx context.Context) bool {
} }
type PortMatcher struct { type PortMatcher struct {
port v2net.PortRange port net.PortRange
} }
func NewPortMatcher(portRange v2net.PortRange) *PortMatcher { func NewPortMatcher(portRange net.PortRange) *PortMatcher {
return &PortMatcher{ return &PortMatcher{
port: portRange, port: portRange,
} }
@ -241,10 +240,10 @@ func (v *PortMatcher) Apply(ctx context.Context) bool {
} }
type NetworkMatcher struct { type NetworkMatcher struct {
network *v2net.NetworkList network *net.NetworkList
} }
func NewNetworkMatcher(network *v2net.NetworkList) *NetworkMatcher { func NewNetworkMatcher(network *net.NetworkList) *NetworkMatcher {
return &NetworkMatcher{ return &NetworkMatcher{
network: network, network: network,
} }

View File

@ -2,9 +2,8 @@ package router
import ( import (
"context" "context"
"net"
v2net "v2ray.com/core/common/net" "v2ray.com/core/common/net"
) )
type Rule struct { type Rule struct {
@ -17,7 +16,7 @@ func (r *Rule) Apply(ctx context.Context) bool {
} }
func cidrToCondition(cidr []*CIDR, source bool) (Condition, error) { func cidrToCondition(cidr []*CIDR, source bool) (Condition, error) {
ipv4Net := v2net.NewIPNetTable() ipv4Net := net.NewIPNetTable()
ipv6Cond := NewAnyCondition() ipv6Cond := NewAnyCondition()
hasIpv6 := false hasIpv6 := false

View File

@ -2,14 +2,13 @@ package unix
import ( import (
"context" "context"
"net"
"os" "os"
"sync" "sync"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
"v2ray.com/core/app/vpndialer" "v2ray.com/core/app/vpndialer"
"v2ray.com/core/common" "v2ray.com/core/common"
v2net "v2ray.com/core/common/net" "v2ray.com/core/common/net"
"v2ray.com/core/common/serial" "v2ray.com/core/common/serial"
"v2ray.com/core/transport/internet" "v2ray.com/core/transport/internet"
) )
@ -161,19 +160,19 @@ type Dialer struct {
protect func(fd int) error protect func(fd int) error
} }
func socket(dest v2net.Destination) (int, error) { func socket(dest net.Destination) (int, error) {
switch dest.Network { switch dest.Network {
case v2net.Network_TCP: case net.Network_TCP:
return unix.Socket(unix.AF_INET6, unix.SOCK_STREAM, unix.IPPROTO_TCP) return unix.Socket(unix.AF_INET6, unix.SOCK_STREAM, unix.IPPROTO_TCP)
case v2net.Network_UDP: case net.Network_UDP:
return unix.Socket(unix.AF_INET6, unix.SOCK_DGRAM, unix.IPPROTO_UDP) return unix.Socket(unix.AF_INET6, unix.SOCK_DGRAM, unix.IPPROTO_UDP)
default: default:
return 0, newError("unknown network ", dest.Network) return 0, newError("unknown network ", dest.Network)
} }
} }
func getIP(addr v2net.Address) (net.IP, error) { func getIP(addr net.Address) (net.IP, error) {
if addr.Family().Either(v2net.AddressFamilyIPv4, v2net.AddressFamilyIPv6) { if addr.Family().Either(net.AddressFamilyIPv4, net.AddressFamilyIPv6) {
return addr.IP(), nil return addr.IP(), nil
} }
ips, err := net.LookupIP(addr.Domain()) ips, err := net.LookupIP(addr.Domain())
@ -183,7 +182,7 @@ func getIP(addr v2net.Address) (net.IP, error) {
return ips[0], nil return ips[0], nil
} }
func (d *Dialer) Dial(ctx context.Context, source v2net.Address, dest v2net.Destination) (net.Conn, error) { func (d *Dialer) Dial(ctx context.Context, source net.Address, dest net.Destination) (net.Conn, error) {
fd, err := socket(dest) fd, err := socket(dest)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -4,16 +4,21 @@ import "net"
var DialTCP = net.DialTCP var DialTCP = net.DialTCP
var DialUDP = net.DialUDP var DialUDP = net.DialUDP
var DialUnix = net.DialUnix
var Listen = net.Listen var Listen = net.Listen
var ListenTCP = net.ListenTCP var ListenTCP = net.ListenTCP
var ListenUDP = net.ListenUDP var ListenUDP = net.ListenUDP
var FileConn = net.FileConn
var LookupIP = net.LookupIP var LookupIP = net.LookupIP
var ParseIP = net.ParseIP var ParseIP = net.ParseIP
var SplitHostPort = net.SplitHostPort var SplitHostPort = net.SplitHostPort
var CIDRMask = net.CIDRMask
type Addr = net.Addr type Addr = net.Addr
type Conn = net.Conn type Conn = net.Conn
@ -23,6 +28,7 @@ type TCPConn = net.TCPConn
type UDPAddr = net.UDPAddr type UDPAddr = net.UDPAddr
type UDPConn = net.UDPConn type UDPConn = net.UDPConn
type UnixAddr = net.UnixAddr
type UnixConn = net.UnixConn type UnixConn = net.UnixConn
type IP = net.IP type IP = net.IP

View File

@ -3,24 +3,23 @@ package tcp
import ( import (
"fmt" "fmt"
"io" "io"
"net"
v2net "v2ray.com/core/common/net" "v2ray.com/core/common/net"
) )
type Server struct { type Server struct {
Port v2net.Port Port net.Port
MsgProcessor func(msg []byte) []byte MsgProcessor func(msg []byte) []byte
SendFirst []byte SendFirst []byte
Listen v2net.Address Listen net.Address
accepting bool accepting bool
listener *net.TCPListener listener *net.TCPListener
} }
func (server *Server) Start() (v2net.Destination, error) { func (server *Server) Start() (net.Destination, error) {
listenerAddr := server.Listen listenerAddr := server.Listen
if listenerAddr == nil { if listenerAddr == nil {
listenerAddr = v2net.LocalHostIP listenerAddr = net.LocalHostIP
} }
listener, err := net.ListenTCP("tcp", &net.TCPAddr{ listener, err := net.ListenTCP("tcp", &net.TCPAddr{
IP: listenerAddr.IP(), IP: listenerAddr.IP(),
@ -28,13 +27,13 @@ func (server *Server) Start() (v2net.Destination, error) {
Zone: "", Zone: "",
}) })
if err != nil { if err != nil {
return v2net.Destination{}, err return net.Destination{}, err
} }
server.Port = v2net.Port(listener.Addr().(*v2net.TCPAddr).Port) server.Port = net.Port(listener.Addr().(*net.TCPAddr).Port)
server.listener = listener server.listener = listener
go server.acceptConnections(listener) go server.acceptConnections(listener)
localAddr := listener.Addr().(*v2net.TCPAddr) localAddr := listener.Addr().(*net.TCPAddr)
return v2net.TCPDestination(v2net.IPAddress(localAddr.IP), v2net.Port(localAddr.Port)), nil return net.TCPDestination(net.IPAddress(localAddr.IP), net.Port(localAddr.Port)), nil
} }
func (server *Server) acceptConnections(listener *net.TCPListener) { func (server *Server) acceptConnections(listener *net.TCPListener) {

View File

@ -3,11 +3,10 @@ package tcp
import ( import (
"context" "context"
gotls "crypto/tls" gotls "crypto/tls"
"net"
"v2ray.com/core/app/log" "v2ray.com/core/app/log"
"v2ray.com/core/common" "v2ray.com/core/common"
v2net "v2ray.com/core/common/net" "v2ray.com/core/common/net"
"v2ray.com/core/common/retry" "v2ray.com/core/common/retry"
"v2ray.com/core/transport/internet" "v2ray.com/core/transport/internet"
"v2ray.com/core/transport/internet/tls" "v2ray.com/core/transport/internet/tls"
@ -22,8 +21,8 @@ type TCPListener struct {
addConn internet.AddConnection addConn internet.AddConnection
} }
func ListenTCP(ctx context.Context, address v2net.Address, port v2net.Port, addConn internet.AddConnection) (internet.Listener, error) { func ListenTCP(ctx context.Context, address net.Address, port net.Port, addConn internet.AddConnection) (internet.Listener, error) {
listener, err := net.ListenTCP("tcp", &v2net.TCPAddr{ listener, err := net.ListenTCP("tcp", &net.TCPAddr{
IP: address.IP(), IP: address.IP(),
Port: int(port), Port: int(port),
}) })

View File

@ -6,37 +6,37 @@ import (
"syscall" "syscall"
"v2ray.com/core/app/log" "v2ray.com/core/app/log"
v2net "v2ray.com/core/common/net" "v2ray.com/core/common/net"
"v2ray.com/core/transport/internet" "v2ray.com/core/transport/internet"
) )
const SO_ORIGINAL_DST = 80 const SO_ORIGINAL_DST = 80
func GetOriginalDestination(conn internet.Connection) (v2net.Destination, error) { func GetOriginalDestination(conn internet.Connection) (net.Destination, error) {
sysrawconn, f := conn.(syscall.Conn) sysrawconn, f := conn.(syscall.Conn)
if !f { if !f {
return v2net.Destination{}, newError("unable to get syscall.Conn") return net.Destination{}, newError("unable to get syscall.Conn")
} }
rawConn, err := sysrawconn.SyscallConn() rawConn, err := sysrawconn.SyscallConn()
if err != nil { if err != nil {
return v2net.Destination{}, newError("failed to get sys fd").Base(err) return net.Destination{}, newError("failed to get sys fd").Base(err)
} }
var dest v2net.Destination var dest net.Destination
err = rawConn.Control(func(fd uintptr) { err = rawConn.Control(func(fd uintptr) {
addr, err := syscall.GetsockoptIPv6Mreq(int(fd), syscall.IPPROTO_IP, SO_ORIGINAL_DST) addr, err := syscall.GetsockoptIPv6Mreq(int(fd), syscall.IPPROTO_IP, SO_ORIGINAL_DST)
if err != nil { if err != nil {
log.Trace(newError("failed to call getsockopt").Base(err)) log.Trace(newError("failed to call getsockopt").Base(err))
return return
} }
ip := v2net.IPAddress(addr.Multiaddr[4:8]) ip := net.IPAddress(addr.Multiaddr[4:8])
port := uint16(addr.Multiaddr[2])<<8 + uint16(addr.Multiaddr[3]) port := uint16(addr.Multiaddr[2])<<8 + uint16(addr.Multiaddr[3])
dest = v2net.TCPDestination(ip, v2net.Port(port)) dest = net.TCPDestination(ip, net.Port(port))
}) })
if err != nil { if err != nil {
return v2net.Destination{}, newError("failed to control connection").Base(err) return net.Destination{}, newError("failed to control connection").Base(err)
} }
if !dest.IsValid() { if !dest.IsValid() {
return v2net.Destination{}, newError("failed to call getsockopt") return net.Destination{}, newError("failed to call getsockopt")
} }
return dest, nil return dest, nil
} }

View File

@ -2,23 +2,22 @@ package udp
import ( import (
"context" "context"
"net"
"v2ray.com/core/app/log" "v2ray.com/core/app/log"
"v2ray.com/core/common/buf" "v2ray.com/core/common/buf"
"v2ray.com/core/common/dice" "v2ray.com/core/common/dice"
v2net "v2ray.com/core/common/net" "v2ray.com/core/common/net"
) )
// Payload represents a single UDP payload. // Payload represents a single UDP payload.
type Payload struct { type Payload struct {
payload *buf.Buffer payload *buf.Buffer
source v2net.Destination source net.Destination
originalDest v2net.Destination originalDest net.Destination
} }
// PayloadHandler is function to handle Payload. // PayloadHandler is function to handle Payload.
type PayloadHandler func(payload *buf.Buffer, source v2net.Destination, originalDest v2net.Destination) type PayloadHandler func(payload *buf.Buffer, source net.Destination, originalDest net.Destination)
// PayloadQueue is a queue of Payload. // PayloadQueue is a queue of Payload.
type PayloadQueue struct { type PayloadQueue struct {
@ -80,7 +79,7 @@ type Hub struct {
option ListenOption option ListenOption
} }
func ListenUDP(address v2net.Address, port v2net.Port, option ListenOption) (*Hub, error) { func ListenUDP(address net.Address, port net.Port, option ListenOption) (*Hub, error) {
if option.Concurrency < 1 { if option.Concurrency < 1 {
option.Concurrency = 1 option.Concurrency = 1
} }
@ -122,7 +121,7 @@ func (v *Hub) Close() {
v.conn.Close() v.conn.Close()
} }
func (v *Hub) WriteTo(payload []byte, dest v2net.Destination) (int, error) { func (v *Hub) WriteTo(payload []byte, dest net.Destination) (int, error) {
return v.conn.WriteToUDP(payload, &net.UDPAddr{ return v.conn.WriteToUDP(payload, &net.UDPAddr{
IP: dest.Address.IP(), IP: dest.Address.IP(),
Port: int(dest.Port), Port: int(dest.Port),
@ -158,7 +157,7 @@ L:
payload := Payload{ payload := Payload{
payload: buffer, payload: buffer,
} }
payload.source = v2net.UDPDestination(v2net.IPAddress(addr.IP), v2net.Port(addr.Port)) payload.source = net.UDPDestination(net.IPAddress(addr.IP), net.Port(addr.Port))
if v.option.ReceiveOriginalDest && noob > 0 { if v.option.ReceiveOriginalDest && noob > 0 {
payload.originalDest = RetrieveOriginalDest(oobBytes[:noob]) payload.originalDest = RetrieveOriginalDest(oobBytes[:noob])
} }

View File

@ -5,7 +5,7 @@ package udp
import ( import (
"syscall" "syscall"
v2net "v2ray.com/core/common/net" "v2ray.com/core/common/net"
) )
func SetOriginalDestOptions(fd int) error { func SetOriginalDestOptions(fd int) error {
@ -18,25 +18,25 @@ func SetOriginalDestOptions(fd int) error {
return nil return nil
} }
func RetrieveOriginalDest(oob []byte) v2net.Destination { func RetrieveOriginalDest(oob []byte) net.Destination {
msgs, err := syscall.ParseSocketControlMessage(oob) msgs, err := syscall.ParseSocketControlMessage(oob)
if err != nil { if err != nil {
return v2net.Destination{} return net.Destination{}
} }
for _, msg := range msgs { for _, msg := range msgs {
if msg.Header.Level == syscall.SOL_IP && msg.Header.Type == syscall.IP_RECVORIGDSTADDR { if msg.Header.Level == syscall.SOL_IP && msg.Header.Type == syscall.IP_RECVORIGDSTADDR {
ip := v2net.IPAddress(msg.Data[4:8]) ip := net.IPAddress(msg.Data[4:8])
port := v2net.PortFromBytes(msg.Data[2:4]) port := net.PortFromBytes(msg.Data[2:4])
return v2net.UDPDestination(ip, port) return net.UDPDestination(ip, port)
} else if msg.Header.Level == syscall.SOL_IPV6 && msg.Header.Type == syscall.IP_RECVORIGDSTADDR { } else if msg.Header.Level == syscall.SOL_IPV6 && msg.Header.Type == syscall.IP_RECVORIGDSTADDR {
ip := v2net.IPAddress(msg.Data[8:24]) ip := net.IPAddress(msg.Data[8:24])
port := v2net.PortFromBytes(msg.Data[2:4]) port := net.PortFromBytes(msg.Data[2:4])
return v2net.UDPDestination(ip, port) return net.UDPDestination(ip, port)
} }
} }
return v2net.Destination{} return net.Destination{}
} }
func ReadUDPMsg(conn *v2net.UDPConn, payload []byte, oob []byte) (int, int, int, *v2net.UDPAddr, error) { func ReadUDPMsg(conn *net.UDPConn, payload []byte, oob []byte) (int, int, int, *net.UDPAddr, error) {
return conn.ReadMsgUDP(payload, oob) return conn.ReadMsgUDP(payload, oob)
} }

View File

@ -6,7 +6,7 @@ import (
"testing" "testing"
"time" "time"
v2net "v2ray.com/core/common/net" "v2ray.com/core/common/net"
"v2ray.com/core/testing/assert" "v2ray.com/core/testing/assert"
tlsgen "v2ray.com/core/testing/tls" tlsgen "v2ray.com/core/testing/tls"
"v2ray.com/core/transport/internet" "v2ray.com/core/transport/internet"
@ -18,7 +18,7 @@ func Test_listenWSAndDial(t *testing.T) {
assert := assert.On(t) assert := assert.On(t)
listen, err := ListenWS(internet.ContextWithTransportSettings(context.Background(), &Config{ listen, err := ListenWS(internet.ContextWithTransportSettings(context.Background(), &Config{
Path: "ws", Path: "ws",
}), v2net.DomainAddress("localhost"), 13146, func(ctx context.Context, conn internet.Connection) bool { }), net.DomainAddress("localhost"), 13146, func(ctx context.Context, conn internet.Connection) bool {
go func(c internet.Connection) { go func(c internet.Connection) {
defer c.Close() defer c.Close()
@ -38,7 +38,7 @@ func Test_listenWSAndDial(t *testing.T) {
assert.Error(err).IsNil() assert.Error(err).IsNil()
ctx := internet.ContextWithTransportSettings(context.Background(), &Config{Path: "ws"}) ctx := internet.ContextWithTransportSettings(context.Background(), &Config{Path: "ws"})
conn, err := Dial(ctx, v2net.TCPDestination(v2net.DomainAddress("localhost"), 13146)) conn, err := Dial(ctx, net.TCPDestination(net.DomainAddress("localhost"), 13146))
assert.Error(err).IsNil() assert.Error(err).IsNil()
_, err = conn.Write([]byte("Test connection 1")) _, err = conn.Write([]byte("Test connection 1"))
@ -51,7 +51,7 @@ func Test_listenWSAndDial(t *testing.T) {
assert.Error(conn.Close()).IsNil() assert.Error(conn.Close()).IsNil()
<-time.After(time.Second * 5) <-time.After(time.Second * 5)
conn, err = Dial(ctx, v2net.TCPDestination(v2net.DomainAddress("localhost"), 13146)) conn, err = Dial(ctx, net.TCPDestination(net.DomainAddress("localhost"), 13146))
assert.Error(err).IsNil() assert.Error(err).IsNil()
_, err = conn.Write([]byte("Test connection 2")) _, err = conn.Write([]byte("Test connection 2"))
assert.Error(err).IsNil() assert.Error(err).IsNil()
@ -60,7 +60,7 @@ func Test_listenWSAndDial(t *testing.T) {
assert.String(string(b[:n])).Equals("Response") assert.String(string(b[:n])).Equals("Response")
assert.Error(conn.Close()).IsNil() assert.Error(conn.Close()).IsNil()
<-time.After(time.Second * 15) <-time.After(time.Second * 15)
conn, err = Dial(ctx, v2net.TCPDestination(v2net.DomainAddress("localhost"), 13146)) conn, err = Dial(ctx, net.TCPDestination(net.DomainAddress("localhost"), 13146))
assert.Error(err).IsNil() assert.Error(err).IsNil()
_, err = conn.Write([]byte("Test connection 3")) _, err = conn.Write([]byte("Test connection 3"))
assert.Error(err).IsNil() assert.Error(err).IsNil()
@ -86,7 +86,7 @@ func Test_listenWSAndDial_TLS(t *testing.T) {
AllowInsecure: true, AllowInsecure: true,
Certificate: []*v2tls.Certificate{tlsgen.GenerateCertificateForTest()}, Certificate: []*v2tls.Certificate{tlsgen.GenerateCertificateForTest()},
}) })
listen, err := ListenWS(ctx, v2net.DomainAddress("localhost"), 13143, func(ctx context.Context, conn internet.Connection) bool { listen, err := ListenWS(ctx, net.DomainAddress("localhost"), 13143, func(ctx context.Context, conn internet.Connection) bool {
go func() { go func() {
conn.Close() conn.Close()
}() }()
@ -95,7 +95,7 @@ func Test_listenWSAndDial_TLS(t *testing.T) {
assert.Error(err).IsNil() assert.Error(err).IsNil()
defer listen.Close() defer listen.Close()
conn, err := Dial(ctx, v2net.TCPDestination(v2net.DomainAddress("localhost"), 13143)) conn, err := Dial(ctx, net.TCPDestination(net.DomainAddress("localhost"), 13143))
assert.Error(err).IsNil() assert.Error(err).IsNil()
conn.Close() conn.Close()
} }

View File

@ -6,7 +6,7 @@ import (
. "v2ray.com/core" . "v2ray.com/core"
"v2ray.com/core/app/proxyman" "v2ray.com/core/app/proxyman"
"v2ray.com/core/common/dice" "v2ray.com/core/common/dice"
v2net "v2ray.com/core/common/net" "v2ray.com/core/common/net"
"v2ray.com/core/common/protocol" "v2ray.com/core/common/protocol"
"v2ray.com/core/common/serial" "v2ray.com/core/common/serial"
"v2ray.com/core/common/uuid" "v2ray.com/core/common/uuid"
@ -20,19 +20,19 @@ import (
func TestV2RayClose(t *testing.T) { func TestV2RayClose(t *testing.T) {
assert := assert.On(t) assert := assert.On(t)
port := v2net.Port(dice.RollUint16()) port := net.Port(dice.RollUint16())
config := &Config{ config := &Config{
Inbound: []*proxyman.InboundHandlerConfig{ Inbound: []*proxyman.InboundHandlerConfig{
{ {
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
PortRange: v2net.SinglePortRange(port), PortRange: net.SinglePortRange(port),
Listen: v2net.NewIPOrDomain(v2net.LocalHostIP), Listen: net.NewIPOrDomain(net.LocalHostIP),
}), }),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: v2net.NewIPOrDomain(v2net.LocalHostIP), Address: net.NewIPOrDomain(net.LocalHostIP),
Port: uint32(0), Port: uint32(0),
NetworkList: &v2net.NetworkList{ NetworkList: &net.NetworkList{
Network: []v2net.Network{v2net.Network_TCP, v2net.Network_UDP}, Network: []net.Network{net.Network_TCP, net.Network_UDP},
}, },
}), }),
}, },
@ -42,7 +42,7 @@ func TestV2RayClose(t *testing.T) {
ProxySettings: serial.ToTypedMessage(&outbound.Config{ ProxySettings: serial.ToTypedMessage(&outbound.Config{
Receiver: []*protocol.ServerEndpoint{ Receiver: []*protocol.ServerEndpoint{
{ {
Address: v2net.NewIPOrDomain(v2net.LocalHostIP), Address: net.NewIPOrDomain(net.LocalHostIP),
Port: uint32(0), Port: uint32(0),
User: []*protocol.User{ User: []*protocol.User{
{ {