ソースを参照

UDP support for dokodemo door

V2Ray 10 年 前
コミット
8597642002
2 ファイル変更106 行追加1 行削除
  1. 44 1
      proxy/dokodemo/dokodemo.go
  2. 62 0
      proxy/dokodemo/dokodemo_test.go

+ 44 - 1
proxy/dokodemo/dokodemo.go

@@ -35,15 +35,59 @@ func NewDokodemoDoor(dispatcher app.PacketDispatcher, config *json.DokodemoConfi
 }
 
 func (this *DokodemoDoor) Listen(port uint16) error {
+	this.accepting = true
+
 	if this.config.Network.HasNetwork(v2net.TCPNetwork) {
 		err := this.ListenTCP(port)
 		if err != nil {
 			return err
 		}
 	}
+	if this.config.Network.HasNetwork(v2net.UDPNetwork) {
+		err := this.ListenUDP(port)
+		if err != nil {
+			return err
+		}
+	}
 	return nil
 }
 
+func (this *DokodemoDoor) ListenUDP(port uint16) error {
+	udpConn, err := net.ListenUDP("udp", &net.UDPAddr{
+		IP:   []byte{0, 0, 0, 0},
+		Port: int(port),
+		Zone: "",
+	})
+	if err != nil {
+		log.Error("Dokodemo failed to listen on port %d: %v", port, err)
+		return err
+	}
+	go this.handleUDPPackets(udpConn)
+	return nil
+}
+
+func (this *DokodemoDoor) handleUDPPackets(udpConn *net.UDPConn) {
+	defer udpConn.Close()
+	for this.accepting {
+		buffer := alloc.NewBuffer()
+		nBytes, addr, err := udpConn.ReadFromUDP(buffer.Value)
+		buffer.Slice(0, nBytes)
+		if err != nil {
+			buffer.Release()
+			log.Error("Dokodemo failed to read from UDP: %v", err)
+			return
+		}
+
+		packet := v2net.NewPacket(v2net.NewUDPDestination(this.address), buffer, false)
+		ray := this.dispatcher.DispatchToOutbound(packet)
+		close(ray.InboundInput())
+
+		for payload := range ray.InboundOutput() {
+			udpConn.WriteToUDP(payload.Value, addr)
+		}
+	}
+}
+
 func (this *DokodemoDoor) ListenTCP(port uint16) error {
 	tcpListener, err := net.ListenTCP("tcp", &net.TCPAddr{
 		IP:   []byte{0, 0, 0, 0},
@@ -54,7 +98,6 @@ func (this *DokodemoDoor) ListenTCP(port uint16) error {
 		log.Error("Dokodemo failed to listen on port %d: %v", port, err)
 		return err
 	}
-	this.accepting = true
 	go this.AcceptTCPConnections(tcpListener)
 	return nil
 }

+ 62 - 0
proxy/dokodemo/dokodemo_test.go

@@ -11,6 +11,7 @@ import (
 	"github.com/v2ray/v2ray-core/proxy/dokodemo/config/json"
 	_ "github.com/v2ray/v2ray-core/proxy/freedom"
 	"github.com/v2ray/v2ray-core/testing/servers/tcp"
+	"github.com/v2ray/v2ray-core/testing/servers/udp"
 	"github.com/v2ray/v2ray-core/testing/unit"
 )
 
@@ -75,3 +76,64 @@ func TestDokodemoTCP(t *testing.T) {
 
 	assert.String("Processed: " + data2Send).Equals(string(response[:nBytes]))
 }
+
+func TestDokodemoUDP(t *testing.T) {
+	assert := unit.Assert(t)
+
+	port := v2nettesting.PickPort()
+
+	data2Send := "Data to be sent to remote."
+
+	udpServer := &udp.Server{
+		Port: port,
+		MsgProcessor: func(data []byte) []byte {
+			buffer := make([]byte, 0, 2048)
+			buffer = append(buffer, []byte("Processed: ")...)
+			buffer = append(buffer, data...)
+			return buffer
+		},
+	}
+	_, err := udpServer.Start()
+	assert.Error(err).IsNil()
+
+	pointPort := v2nettesting.PickPort()
+	networkList := v2netjson.NetworkList([]string{"udp"})
+	config := mocks.Config{
+		PortValue: pointPort,
+		InboundConfigValue: &mocks.ConnectionConfig{
+			ProtocolValue: "dokodemo-door",
+			SettingsValue: &json.DokodemoConfig{
+				Host:    "127.0.0.1",
+				Port:    int(port),
+				Network: &networkList,
+				Timeout: 0,
+			},
+		},
+		OutboundConfigValue: &mocks.ConnectionConfig{
+			ProtocolValue: "freedom",
+			SettingsValue: nil,
+		},
+	}
+
+	point, err := point.NewPoint(&config)
+	assert.Error(err).IsNil()
+
+	err = point.Start()
+	assert.Error(err).IsNil()
+
+	udpClient, err := net.DialUDP("udp", nil, &net.UDPAddr{
+		IP:   []byte{127, 0, 0, 1},
+		Port: int(pointPort),
+		Zone: "",
+	})
+	assert.Error(err).IsNil()
+
+	udpClient.Write([]byte(data2Send))
+
+	response := make([]byte, 1024)
+	nBytes, err := udpClient.Read(response)
+	assert.Error(err).IsNil()
+	udpClient.Close()
+
+	assert.String("Processed: " + data2Send).Equals(string(response[:nBytes]))
+}