mirror of https://github.com/v2ray/v2ray-core
Introduce Packet to unify TCP and UDP communication
parent
4320c14efd
commit
4874cd54a4
|
@ -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
|
||||||
|
}
|
6
point.go
6
point.go
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
|
|
||||||
|
|
|
@ -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
16
ray.go
|
@ -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 {
|
||||||
|
}
|
||||||
|
|
|
@ -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"}
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue