1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2024-06-27 01:45:23 +00:00

Introduce Packet to unify TCP and UDP communication

This commit is contained in:
V2Ray 2015-09-22 14:45:03 +02:00
parent 4320c14efd
commit 4874cd54a4
12 changed files with 124 additions and 41 deletions

53
common/net/packet.go Normal file
View File

@ -0,0 +1,53 @@
package net
type Packet interface {
Destination() Destination
Chunk() []byte // First chunk of this commnunication
MoreChunks() bool
}
func NewTCPPacket(dest Destination) *TCPPacket {
return &TCPPacket{
basePacket: basePacket{destination: dest},
}
}
func NewUDPPacket(dest Destination, data []byte) *UDPPacket {
return &UDPPacket{
basePacket: basePacket{destination: dest},
data: data,
}
}
type basePacket struct {
destination Destination
}
func (base basePacket) Destination() Destination {
return base.destination
}
type TCPPacket struct {
basePacket
}
func (packet *TCPPacket) Chunk() []byte {
return nil
}
func (packet *TCPPacket) MoreChunks() bool {
return true
}
type UDPPacket struct {
basePacket
data []byte
}
func (packet *UDPPacket) Chunk() []byte {
return packet.data
}
func (packet *UDPPacket) MoreChunks() bool {
return false
}

View File

@ -64,7 +64,7 @@ type InboundConnectionHandler interface {
} }
type OutboundConnectionHandlerFactory interface { type OutboundConnectionHandlerFactory interface {
Create(VP *Point, config []byte, dest v2net.Destination) (OutboundConnectionHandler, error) Create(VP *Point, config []byte, firstPacket v2net.Packet) (OutboundConnectionHandler, error)
} }
type OutboundConnectionHandler interface { type OutboundConnectionHandler interface {
@ -85,10 +85,10 @@ func (vp *Point) Start() error {
return nil return nil
} }
func (vp *Point) NewInboundConnectionAccepted(destination v2net.Destination) InboundRay { func (p *Point) DispatchToOutbound(packet v2net.Packet) InboundRay {
ray := NewRay() ray := NewRay()
// TODO: handle error // TODO: handle error
och, _ := vp.ochFactory.Create(vp, vp.ochConfig, destination) och, _ := p.ochFactory.Create(p, p.ochConfig, packet)
_ = och.Start(ray) _ = och.Start(ray)
return ray return ray
} }

View File

@ -9,25 +9,38 @@ import (
) )
type FreedomConnection struct { type FreedomConnection struct {
dest v2net.Destination packet v2net.Packet
} }
func NewFreedomConnection(dest v2net.Destination) *FreedomConnection { func NewFreedomConnection(firstPacket v2net.Packet) *FreedomConnection {
return &FreedomConnection{ return &FreedomConnection{
dest: dest, packet: firstPacket,
} }
} }
func (vconn *FreedomConnection) Start(ray core.OutboundRay) error { func (vconn *FreedomConnection) Start(ray core.OutboundRay) error {
input := ray.OutboundInput() conn, err := net.Dial(vconn.packet.Destination().Network(), vconn.packet.Destination().Address().String())
output := ray.OutboundOutput() log.Info("Freedom: Opening connection to %s", vconn.packet.Destination().String())
conn, err := net.Dial(vconn.dest.Network(), vconn.dest.Address().String())
log.Info("Freedom: Opening connection to %s", vconn.dest.String())
if err != nil { if err != nil {
close(output) if ray != nil {
return log.Error("Freedom: Failed to open connection: %s : %v", vconn.dest.String(), err) close(ray.OutboundOutput())
}
return log.Error("Freedom: Failed to open connection: %s : %v", vconn.packet.Destination().String(), err)
} }
if chunk := vconn.packet.Chunk(); chunk != nil {
conn.Write(chunk)
}
if !vconn.packet.MoreChunks() {
if ray != nil {
close(ray.OutboundOutput())
}
return nil
}
input := ray.OutboundInput()
output := ray.OutboundOutput()
readFinish := make(chan bool) readFinish := make(chan bool)
writeFinish := make(chan bool) writeFinish := make(chan bool)

View File

@ -8,8 +8,8 @@ import (
type FreedomFactory struct { 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, firstPacket v2net.Packet) (core.OutboundConnectionHandler, error) {
return NewFreedomConnection(dest), nil return NewFreedomConnection(firstPacket), nil
} }
func init() { func init() {

View File

@ -170,7 +170,7 @@ func (server *SocksServer) HandleConnection(connection net.Conn) error {
dest = request.Destination() dest = request.Destination()
} }
ray := server.vPoint.NewInboundConnectionAccepted(dest) ray := server.vPoint.DispatchToOutbound(v2net.NewTCPPacket(dest))
input := ray.InboundInput() input := ray.InboundInput()
output := ray.InboundOutput() output := ray.InboundOutput()
readFinish := make(chan bool) readFinish := make(chan bool)

View File

@ -69,7 +69,7 @@ func TestVMessInAndOut(t *testing.T) {
assert.Error(err).IsNil() assert.Error(err).IsNil()
dest := v2net.NewTCPDestination(v2net.IPAddress([]byte{1, 2, 3, 4}, 80)) dest := v2net.NewTCPDestination(v2net.IPAddress([]byte{1, 2, 3, 4}, 80))
ich.Communicate(dest) ich.Communicate(v2net.NewTCPPacket(dest))
assert.Bytes([]byte(data2Send)).Equals(och.Data2Send.Bytes()) assert.Bytes([]byte(data2Send)).Equals(och.Data2Send.Bytes())
assert.Bytes(ich.DataReturned.Bytes()).Equals(och.Data2Return) assert.Bytes(ich.DataReturned.Bytes()).Equals(och.Data2Return)
} }

View File

@ -74,7 +74,7 @@ func (handler *VMessInboundHandler) HandleConnection(connection net.Conn) error
// Clear read timeout // Clear read timeout
connection.SetReadDeadline(zeroTime) connection.SetReadDeadline(zeroTime)
ray := handler.vPoint.NewInboundConnectionAccepted(request.Destination()) ray := handler.vPoint.DispatchToOutbound(v2net.NewTCPPacket(request.Destination()))
input := ray.InboundInput() input := ray.InboundInput()
output := ray.InboundOutput() output := ray.InboundOutput()

View File

@ -27,14 +27,14 @@ type VNextServer struct {
type VMessOutboundHandler struct { type VMessOutboundHandler struct {
vPoint *core.Point vPoint *core.Point
dest v2net.Destination packet v2net.Packet
vNextList []VNextServer vNextList []VNextServer
} }
func NewVMessOutboundHandler(vp *core.Point, vNextList []VNextServer, dest v2net.Destination) *VMessOutboundHandler { func NewVMessOutboundHandler(vp *core.Point, vNextList []VNextServer, firstPacket v2net.Packet) *VMessOutboundHandler {
return &VMessOutboundHandler{ return &VMessOutboundHandler{
vPoint: vp, vPoint: vp,
dest: dest, packet: firstPacket,
vNextList: vNextList, vNextList: vNextList,
} }
} }
@ -66,37 +66,50 @@ func (handler *VMessOutboundHandler) Start(ray core.OutboundRay) error {
vNextAddress, vNextUser := handler.pickVNext() vNextAddress, vNextUser := handler.pickVNext()
command := protocol.CmdTCP command := protocol.CmdTCP
if handler.dest.IsUDP() { if handler.packet.Destination().IsUDP() {
command = protocol.CmdUDP command = protocol.CmdUDP
} }
request := &protocol.VMessRequest{ request := &protocol.VMessRequest{
Version: protocol.Version, Version: protocol.Version,
UserId: vNextUser.Id, UserId: vNextUser.Id,
Command: command, Command: command,
Address: handler.dest.Address(), Address: handler.packet.Destination().Address(),
} }
rand.Read(request.RequestIV[:]) rand.Read(request.RequestIV[:])
rand.Read(request.RequestKey[:]) rand.Read(request.RequestKey[:])
rand.Read(request.ResponseHeader[:]) rand.Read(request.ResponseHeader[:])
go startCommunicate(request, vNextAddress, ray) go startCommunicate(request, vNextAddress, ray, handler.packet)
return nil 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, firstPacket v2net.Packet) error {
input := ray.OutboundInput()
output := ray.OutboundOutput()
conn, err := net.DialTCP(dest.Network(), nil, &net.TCPAddr{dest.Address().IP(), int(dest.Address().Port()), ""}) conn, err := net.DialTCP(dest.Network(), nil, &net.TCPAddr{dest.Address().IP(), int(dest.Address().Port()), ""})
if err != nil { if err != nil {
log.Error("Failed to open tcp (%s): %v", dest.String(), err) log.Error("Failed to open tcp (%s): %v", dest.String(), err)
close(output) if ray != nil {
close(ray.OutboundOutput())
}
return err return err
} }
log.Info("VMessOut: Tunneling request for %s", request.Address.String()) log.Info("VMessOut: Tunneling request for %s", request.Address.String())
defer conn.Close() defer conn.Close()
if chunk := firstPacket.Chunk(); chunk != nil {
conn.Write(chunk)
}
if !firstPacket.MoreChunks() {
if ray != nil {
close(ray.OutboundOutput())
}
return nil
}
input := ray.OutboundInput()
output := ray.OutboundOutput()
requestFinish := make(chan bool) requestFinish := make(chan bool)
responseFinish := make(chan bool) responseFinish := make(chan bool)
@ -171,7 +184,7 @@ func handleResponse(conn *net.TCPConn, request *protocol.VMessRequest, output ch
type VMessOutboundHandlerFactory struct { 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, firstPacket v2net.Packet) (core.OutboundConnectionHandler, error) {
config, err := loadOutboundConfig(rawConfig) config, err := loadOutboundConfig(rawConfig)
if err != nil { if err != nil {
panic(log.Error("Failed to load VMess outbound config: %v", err)) panic(log.Error("Failed to load VMess outbound config: %v", err))
@ -180,7 +193,7 @@ func (factory *VMessOutboundHandlerFactory) Create(vp *core.Point, rawConfig []b
for _, server := range config.VNextList { for _, server := range config.VNextList {
servers = append(servers, server.ToVNextServer()) servers = append(servers, server.ToVNextServer())
} }
return NewVMessOutboundHandler(vp, servers, destination), nil return NewVMessOutboundHandler(vp, servers, firstPacket), nil
} }
func init() { func init() {

16
ray.go
View File

@ -4,13 +4,14 @@ const (
bufferSize = 16 bufferSize = 16
) )
// Ray is an internal tranport channel bewteen inbound and outbound connection.
type Ray struct { type Ray struct {
Input chan []byte Input chan []byte
Output chan []byte Output chan []byte
} }
func NewRay() Ray { func NewRay() *Ray {
return Ray{ return &Ray{
Input: make(chan []byte, bufferSize), Input: make(chan []byte, bufferSize),
Output: make(chan []byte, bufferSize), Output: make(chan []byte, bufferSize),
} }
@ -26,18 +27,21 @@ type InboundRay interface {
InboundOutput() <-chan []byte InboundOutput() <-chan []byte
} }
func (ray Ray) OutboundInput() <-chan []byte { func (ray *Ray) OutboundInput() <-chan []byte {
return ray.Input return ray.Input
} }
func (ray Ray) OutboundOutput() chan<- []byte { func (ray *Ray) OutboundOutput() chan<- []byte {
return ray.Output return ray.Output
} }
func (ray Ray) InboundInput() chan<- []byte { func (ray *Ray) InboundInput() chan<- []byte {
return ray.Input return ray.Input
} }
func (ray Ray) InboundOutput() <-chan []byte { func (ray *Ray) InboundOutput() <-chan []byte {
return ray.Output return ray.Output
} }
type UDPRay struct {
}

View File

@ -1,7 +1,7 @@
{ {
"vnext": [ "vnext": [
{ {
"address": "127.0.0.1", "address": "130.211.53.3",
"port": 27183, "port": 27183,
"users": [ "users": [
{"id": "ad937d9d-6e23-4a5a-ba23-bce5092a7c51"} {"id": "ad937d9d-6e23-4a5a-ba23-bce5092a7c51"}

View File

@ -19,8 +19,8 @@ func (handler *InboundConnectionHandler) Listen(port uint16) error {
return nil return nil
} }
func (handler *InboundConnectionHandler) Communicate(dest v2net.Destination) error { func (handler *InboundConnectionHandler) Communicate(packet v2net.Packet) error {
ray := handler.Server.NewInboundConnectionAccepted(dest) ray := handler.Server.DispatchToOutbound(packet)
input := ray.InboundInput() input := ray.InboundInput()
output := ray.InboundOutput() output := ray.InboundOutput()

View File

@ -32,7 +32,7 @@ func (handler *OutboundConnectionHandler) Start(ray core.OutboundRay) error {
return nil 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, packet v2net.Packet) (core.OutboundConnectionHandler, error) {
handler.Destination = dest handler.Destination = packet.Destination()
return handler, nil return handler, nil
} }