From cb16047cf002a9b29ec2e231c58a73c98f0dbb7f Mon Sep 17 00:00:00 2001 From: V2Ray Date: Sun, 20 Sep 2015 18:22:29 +0200 Subject: [PATCH] prefer interface over struct --- common/net/destination.go | 86 ++++++++++++++++++++------------ point.go | 4 +- proxy/freedom/freedom.go | 4 +- proxy/freedom/freedomfactory.go | 2 +- proxy/socks/protocol/socks.go | 4 +- proxy/socks/socks.go | 4 +- proxy/vmess/config.go | 7 +-- proxy/vmess/protocol/vmess.go | 8 ++- proxy/vmess/vmess_test.go | 2 +- proxy/vmess/vmessout.go | 20 +++++--- testing/mocks/inboundhandler.go | 2 +- testing/mocks/outboundhandler.go | 4 +- 12 files changed, 88 insertions(+), 59 deletions(-) diff --git a/common/net/destination.go b/common/net/destination.go index bf88f753b..d9626645d 100644 --- a/common/net/destination.go +++ b/common/net/destination.go @@ -1,46 +1,66 @@ package net -import ( - "github.com/v2ray/v2ray-core/common/log" -) +type Destination interface { + Network() string + Address() Address + String() string -const ( - NetTCP = byte(0x01) - NetUDP = byte(0x02) -) + IsTCP() bool + IsUDP() bool +} -type Destination struct { - network byte +func NewTCPDestination(address Address) Destination { + return TCPDestination{address: address} +} + +func NewUDPDestination(address Address) Destination { + return UDPDestination{address: address} +} + +type TCPDestination struct { address Address } -func NewDestination(network byte, address Address) *Destination { - return &Destination{ - network: network, - address: address, - } +func (dest TCPDestination) Network() string { + return "tcp" } -func (dest *Destination) Network() string { - switch dest.network { - case NetTCP: - return "tcp" - case NetUDP: - return "udp" - default: - log.Warning("Unknown network %d", dest.network) - return "tcp" - } -} - -func (dest *Destination) NetworkByte() byte { - return dest.network -} - -func (dest *Destination) Address() Address { +func (dest TCPDestination) Address() Address { return dest.address } -func (dest *Destination) String() string { - return dest.address.String() + " (" + dest.Network() + ")" +func (dest TCPDestination) String() string { + return "tcp:" + dest.address.String() +} + +func (dest TCPDestination) IsTCP() bool { + return true +} + +func (dest TCPDestination) IsUDP() bool { + return false +} + +type UDPDestination struct { + address Address +} + +func (dest UDPDestination) Network() string { + return "udp" +} + +func (dest UDPDestination) Address() Address { + return dest.address +} + +func (dest UDPDestination) String() string { + return "udp:" + dest.address.String() +} + +func (dest UDPDestination) IsTCP() bool { + return false +} + +func (dest UDPDestination) IsUDP() bool { + return true } diff --git a/point.go b/point.go index 2b0765b18..7713a1833 100644 --- a/point.go +++ b/point.go @@ -64,7 +64,7 @@ type InboundConnectionHandler interface { } type OutboundConnectionHandlerFactory interface { - Create(VP *Point, config []byte, dest *v2net.Destination) (OutboundConnectionHandler, error) + Create(VP *Point, config []byte, dest v2net.Destination) (OutboundConnectionHandler, error) } type OutboundConnectionHandler interface { @@ -85,7 +85,7 @@ func (vp *Point) Start() error { return nil } -func (vp *Point) NewInboundConnectionAccepted(destination *v2net.Destination) InboundRay { +func (vp *Point) NewInboundConnectionAccepted(destination v2net.Destination) InboundRay { ray := NewRay() // TODO: handle error och, _ := vp.ochFactory.Create(vp, vp.ochConfig, destination) diff --git a/proxy/freedom/freedom.go b/proxy/freedom/freedom.go index aa2f95ed0..3d965cbfe 100644 --- a/proxy/freedom/freedom.go +++ b/proxy/freedom/freedom.go @@ -9,10 +9,10 @@ import ( ) type FreedomConnection struct { - dest *v2net.Destination + dest v2net.Destination } -func NewFreedomConnection(dest *v2net.Destination) *FreedomConnection { +func NewFreedomConnection(dest v2net.Destination) *FreedomConnection { return &FreedomConnection{ dest: dest, } diff --git a/proxy/freedom/freedomfactory.go b/proxy/freedom/freedomfactory.go index 31d15d8aa..fcdd449fe 100644 --- a/proxy/freedom/freedomfactory.go +++ b/proxy/freedom/freedomfactory.go @@ -8,7 +8,7 @@ import ( type FreedomFactory struct { } -func (factory FreedomFactory) Create(vp *core.Point, config []byte, dest *v2net.Destination) (core.OutboundConnectionHandler, error) { +func (factory FreedomFactory) Create(vp *core.Point, config []byte, dest v2net.Destination) (core.OutboundConnectionHandler, error) { return NewFreedomConnection(dest), nil } diff --git a/proxy/socks/protocol/socks.go b/proxy/socks/protocol/socks.go index e4c71e945..1b5caa391 100644 --- a/proxy/socks/protocol/socks.go +++ b/proxy/socks/protocol/socks.go @@ -278,7 +278,7 @@ func ReadRequest(reader io.Reader) (request *Socks5Request, err error) { return } -func (request *Socks5Request) Destination() *v2net.Destination { +func (request *Socks5Request) Destination() v2net.Destination { var address v2net.Address switch request.AddrType { case AddrTypeIPv4: @@ -290,7 +290,7 @@ func (request *Socks5Request) Destination() *v2net.Destination { default: panic("Unknown address type") } - return v2net.NewDestination(v2net.NetTCP, address) + return v2net.NewTCPDestination(address) } const ( diff --git a/proxy/socks/socks.go b/proxy/socks/socks.go index a21736af1..eaeba062f 100644 --- a/proxy/socks/socks.go +++ b/proxy/socks/socks.go @@ -70,7 +70,7 @@ func (server *SocksServer) HandleConnection(connection net.Conn) error { return err } - var dest *v2net.Destination + var dest v2net.Destination // TODO refactor this part if err == protocol.ErrorSocksVersion4 { @@ -85,7 +85,7 @@ func (server *SocksServer) HandleConnection(connection net.Conn) error { return ErrorCommandNotSupported } - dest = v2net.NewDestination(v2net.NetTCP, v2net.IPAddress(auth4.IP[:], auth4.Port)) + dest = v2net.NewTCPDestination(v2net.IPAddress(auth4.IP[:], auth4.Port)) } else { expectedAuthMethod := protocol.AuthNotRequired if server.config.AuthMethod == JsonAuthMethodUserPass { diff --git a/proxy/vmess/config.go b/proxy/vmess/config.go index 43e7f0863..228642962 100644 --- a/proxy/vmess/config.go +++ b/proxy/vmess/config.go @@ -51,12 +51,13 @@ func (config VNextConfig) ToVNextServer() VNextServer { if ip == nil { panic(log.Error("Unable to parse VNext IP: %s", config.Address)) } - network := v2net.NetTCP + address := v2net.IPAddress(ip, config.Port) + dest := v2net.NewTCPDestination(address) if config.Network == "udp" { - network = v2net.NetUDP + dest = v2net.NewUDPDestination(address) } return VNextServer{ - Destination: v2net.NewDestination(network, v2net.IPAddress(ip, config.Port)), + Destination: dest, Users: users, } } diff --git a/proxy/vmess/protocol/vmess.go b/proxy/vmess/protocol/vmess.go index 13012521f..f4a2bfe25 100644 --- a/proxy/vmess/protocol/vmess.go +++ b/proxy/vmess/protocol/vmess.go @@ -50,8 +50,12 @@ type VMessRequest struct { Address v2net.Address } -func (request *VMessRequest) Destination() *v2net.Destination { - return v2net.NewDestination(request.Command, request.Address) +func (request *VMessRequest) Destination() v2net.Destination { + if request.Command == CmdTCP { + return v2net.NewTCPDestination(request.Address) + } else { + return v2net.NewUDPDestination(request.Address) + } } type VMessRequestReader struct { diff --git a/proxy/vmess/vmess_test.go b/proxy/vmess/vmess_test.go index 2b577bd27..d70dd3ec5 100644 --- a/proxy/vmess/vmess_test.go +++ b/proxy/vmess/vmess_test.go @@ -68,7 +68,7 @@ func TestVMessInAndOut(t *testing.T) { err = pointB.Start() assert.Error(err).IsNil() - dest := v2net.NewDestination(v2net.NetTCP, v2net.IPAddress([]byte{1, 2, 3, 4}, 80)) + dest := v2net.NewTCPDestination(v2net.IPAddress([]byte{1, 2, 3, 4}, 80)) ich.Communicate(dest) assert.Bytes([]byte(data2Send)).Equals(och.Data2Send.Bytes()) assert.Bytes(ich.DataReturned.Bytes()).Equals(och.Data2Return) diff --git a/proxy/vmess/vmessout.go b/proxy/vmess/vmessout.go index 4248801ef..d51dbc1f3 100644 --- a/proxy/vmess/vmessout.go +++ b/proxy/vmess/vmessout.go @@ -17,17 +17,17 @@ import ( // VNext is the next Point server in the connection chain. type VNextServer struct { - Destination *v2net.Destination // Address of VNext server - Users []user.User // User accounts for accessing VNext. + Destination v2net.Destination // Address of VNext server + Users []user.User // User accounts for accessing VNext. } type VMessOutboundHandler struct { vPoint *core.Point - dest *v2net.Destination + dest v2net.Destination vNextList []VNextServer } -func NewVMessOutboundHandler(vp *core.Point, vNextList []VNextServer, dest *v2net.Destination) *VMessOutboundHandler { +func NewVMessOutboundHandler(vp *core.Point, vNextList []VNextServer, dest v2net.Destination) *VMessOutboundHandler { return &VMessOutboundHandler{ vPoint: vp, dest: dest, @@ -35,7 +35,7 @@ func NewVMessOutboundHandler(vp *core.Point, vNextList []VNextServer, dest *v2ne } } -func (handler *VMessOutboundHandler) pickVNext() (*v2net.Destination, user.User) { +func (handler *VMessOutboundHandler) pickVNext() (v2net.Destination, user.User) { vNextLen := len(handler.vNextList) if vNextLen == 0 { panic("VMessOut: Zero vNext is configured.") @@ -54,10 +54,14 @@ func (handler *VMessOutboundHandler) pickVNext() (*v2net.Destination, user.User) func (handler *VMessOutboundHandler) Start(ray core.OutboundRay) error { vNextAddress, vNextUser := handler.pickVNext() + command := protocol.CmdTCP + if handler.dest.IsUDP() { + command = protocol.CmdUDP + } request := &protocol.VMessRequest{ Version: protocol.Version, UserId: vNextUser.Id, - Command: handler.dest.NetworkByte(), + Command: command, Address: handler.dest.Address(), } rand.Read(request.RequestIV[:]) @@ -68,7 +72,7 @@ func (handler *VMessOutboundHandler) Start(ray core.OutboundRay) error { return nil } -func startCommunicate(request *protocol.VMessRequest, dest *v2net.Destination, ray core.OutboundRay) error { +func startCommunicate(request *protocol.VMessRequest, dest v2net.Destination, ray core.OutboundRay) error { input := ray.OutboundInput() output := ray.OutboundOutput() @@ -155,7 +159,7 @@ func handleResponse(conn *net.TCPConn, request *protocol.VMessRequest, output ch type VMessOutboundHandlerFactory struct { } -func (factory *VMessOutboundHandlerFactory) Create(vp *core.Point, rawConfig []byte, destination *v2net.Destination) (core.OutboundConnectionHandler, error) { +func (factory *VMessOutboundHandlerFactory) Create(vp *core.Point, rawConfig []byte, destination v2net.Destination) (core.OutboundConnectionHandler, error) { config, err := loadOutboundConfig(rawConfig) if err != nil { panic(log.Error("Failed to load VMess outbound config: %v", err)) diff --git a/testing/mocks/inboundhandler.go b/testing/mocks/inboundhandler.go index 70f746933..202dbc8cb 100644 --- a/testing/mocks/inboundhandler.go +++ b/testing/mocks/inboundhandler.go @@ -19,7 +19,7 @@ func (handler *InboundConnectionHandler) Listen(port uint16) error { return nil } -func (handler *InboundConnectionHandler) Communicate(dest *v2net.Destination) error { +func (handler *InboundConnectionHandler) Communicate(dest v2net.Destination) error { ray := handler.Server.NewInboundConnectionAccepted(dest) input := ray.InboundInput() diff --git a/testing/mocks/outboundhandler.go b/testing/mocks/outboundhandler.go index a48593415..2117f95cd 100644 --- a/testing/mocks/outboundhandler.go +++ b/testing/mocks/outboundhandler.go @@ -10,7 +10,7 @@ import ( type OutboundConnectionHandler struct { Data2Send *bytes.Buffer Data2Return []byte - Destination *v2net.Destination + Destination v2net.Destination } func (handler *OutboundConnectionHandler) Start(ray core.OutboundRay) error { @@ -32,7 +32,7 @@ func (handler *OutboundConnectionHandler) Start(ray core.OutboundRay) error { return nil } -func (handler *OutboundConnectionHandler) Create(point *core.Point, config []byte, dest *v2net.Destination) (core.OutboundConnectionHandler, error) { +func (handler *OutboundConnectionHandler) Create(point *core.Point, config []byte, dest v2net.Destination) (core.OutboundConnectionHandler, error) { handler.Destination = dest return handler, nil }