Bläddra i källkod

Combine VMess response with first packet for performance

V2Ray 10 år sedan
förälder
incheckning
1b2b5b6cb1
4 ändrade filer med 47 tillägg och 38 borttagningar
  1. 3 1
      net/address.go
  2. 1 0
      net/freedom/freedom.go
  3. 32 29
      net/vmess/vmessin.go
  4. 11 8
      net/vmess/vmessout.go

+ 3 - 1
net/address.go

@@ -18,10 +18,12 @@ type Address struct {
 }
 
 func IPAddress(ip []byte, port uint16) Address {
+	ipCopy := make([]byte, len(ip))
+	copy(ipCopy, ip)
 	// TODO: check IP length
 	return Address{
 		Type:   AddrTypeIP,
-		IP:     net.IP(ip),
+		IP:     net.IP(ipCopy),
 		Domain: "",
 		Port:   port,
 	}

+ 1 - 0
net/freedom/freedom.go

@@ -23,6 +23,7 @@ func (vconn *FreedomConnection) Start(ray core.OutboundRay) error {
 	output := ray.OutboundOutput()
 	conn, err := net.Dial("tcp", vconn.dest.String())
 	if err != nil {
+		close(output)
 		return log.Error("Failed to open tcp: %s : %v", vconn.dest.String(), err)
 	}
 	log.Debug("Sending outbound tcp: %s", vconn.dest.String())

+ 32 - 29
net/vmess/vmessin.go

@@ -60,36 +60,34 @@ func (handler *VMessInboundHandler) HandleConnection(connection net.Conn) error
 	}
 	log.Debug("Received request for %s", request.Address.String())
 
-	response := vmessio.NewVMessResponse(request)
-	nBytes, err := connection.Write(response[:])
-	if err != nil {
-		return log.Error("Failed to write VMess response (%d bytes): %v", nBytes, err)
-	}
+	ray := handler.vPoint.NewInboundConnectionAccepted(request.Address)
+	input := ray.InboundInput()
+	output := ray.InboundOutput()
 
-	requestKey := request.RequestKey[:]
-	requestIV := request.RequestIV[:]
-	responseKey := md5.Sum(requestKey)
-	responseIV := md5.Sum(requestIV)
+	readFinish := make(chan bool)
+	writeFinish := make(chan bool)
 
-	requestReader, err := v2io.NewAesDecryptReader(requestKey, requestIV, connection)
-	if err != nil {
-		return log.Error("Failed to create decrypt reader: %v", err)
-	}
+	go handleInput(request, connection, input, readFinish)
+
+	responseKey := md5.Sum(request.RequestKey[:])
+	responseIV := md5.Sum(request.RequestIV[:])
 
+	response := vmessio.NewVMessResponse(request)
 	responseWriter, err := v2io.NewAesEncryptWriter(responseKey[:], responseIV[:], connection)
 	if err != nil {
 		return log.Error("Failed to create encrypt writer: %v", err)
 	}
 
-	ray := handler.vPoint.NewInboundConnectionAccepted(request.Address)
-	input := ray.InboundInput()
-	output := ray.InboundOutput()
-
-	readFinish := make(chan bool)
-	writeFinish := make(chan bool)
+	// Optimize for small response packet
+	buffer := make([]byte, 0, 1024)
+	buffer = append(buffer, response[:]...)
+	data, open := <-output
+	if open {
+		buffer = append(buffer, data...)
+	}
+	responseWriter.Write(buffer)
 
-	go handler.dumpInput(requestReader, input, readFinish)
-	go handler.dumpOutput(responseWriter, output, writeFinish)
+	go handleOutput(request, responseWriter, output, writeFinish)
 
 	<-writeFinish
 	if tcpConn, ok := connection.(*net.TCPConn); ok {
@@ -101,17 +99,22 @@ func (handler *VMessInboundHandler) HandleConnection(connection net.Conn) error
 	return nil
 }
 
-func (handler *VMessInboundHandler) dumpInput(reader io.Reader, input chan<- []byte, finish chan<- bool) {
-	v2net.ReaderToChan(input, reader)
-	close(input)
-	log.Debug("VMessIn closing input")
-	finish <- true
+func handleInput(request *vmessio.VMessRequest, reader io.Reader, input chan<- []byte, finish chan<- bool) {
+	defer close(input)
+	defer close(finish)
+
+	requestReader, err := v2io.NewAesDecryptReader(request.RequestKey[:], request.RequestIV[:], reader)
+	if err != nil {
+		log.Error("Failed to create decrypt reader: %v", err)
+		return
+	}
+
+	v2net.ReaderToChan(input, requestReader)
 }
 
-func (handler *VMessInboundHandler) dumpOutput(writer io.Writer, output <-chan []byte, finish chan<- bool) {
+func handleOutput(request *vmessio.VMessRequest, writer io.Writer, output <-chan []byte, finish chan<- bool) {
 	v2net.ChanToWriter(writer, output)
-	log.Debug("VMessOut closing output")
-	finish <- true
+	close(finish)
 }
 
 type VMessInboundHandlerFactory struct {

+ 11 - 8
net/vmess/vmessout.go

@@ -79,8 +79,10 @@ func startCommunicate(request *vmessio.VMessRequest, dest v2net.Address, ray cor
 		close(output)
 		return err
 	}
+
+	log.Debug("VMessOut: Tunneling request for %s", request.Address.String())
+
 	defer conn.Close()
-	defer close(output)
 
 	requestFinish := make(chan bool)
 	responseFinish := make(chan bool)
@@ -115,23 +117,24 @@ func handleRequest(conn *net.TCPConn, request *vmessio.VMessRequest, input <-cha
 
 func handleResponse(conn *net.TCPConn, request *vmessio.VMessRequest, output chan<- []byte, finish chan<- bool) error {
 	defer close(finish)
+	defer close(output)
 	responseKey := md5.Sum(request.RequestKey[:])
 	responseIV := md5.Sum(request.RequestIV[:])
 
-	response := vmessio.VMessResponse{}
-	nBytes, err := conn.Read(response[:])
+	decryptResponseReader, err := v2io.NewAesDecryptReader(responseKey[:], responseIV[:], conn)
 	if err != nil {
-		log.Error("Failed to read VMess response (%d bytes): %v", nBytes, err)
+		log.Error("Failed to create decrypt reader: %v", err)
 		return err
 	}
-	log.Debug("Got response %v", response)
-	// TODO: check response
 
-	decryptResponseReader, err := v2io.NewAesDecryptReader(responseKey[:], responseIV[:], conn)
+	response := vmessio.VMessResponse{}
+	nBytes, err := decryptResponseReader.Read(response[:])
 	if err != nil {
-		log.Error("Failed to create decrypt reader: %v", err)
+		log.Error("Failed to read VMess response (%d bytes): %v", nBytes, err)
 		return err
 	}
+	log.Debug("Got response %v", response)
+	// TODO: check response
 
 	v2net.ReaderToChan(output, decryptResponseReader)
 	return nil