func handleRequest(conn *net.TCPConn, request *protocol.VMessRequest, input <-chan []byte, finish *sync.Mutex) { defer finish.Unlock() encryptRequestWriter, err := v2io.NewAesEncryptWriter(request.RequestKey[:], request.RequestIV[:], conn) if err != nil { log.Error("VMessOut: Failed to create encrypt writer: %v", err) return } buffer := make([]byte, 0, 2*1024) buffer, err = request.ToBytes(user.NewTimeHash(user.HMACHash{}), user.GenerateRandomInt64InRange, buffer) if err != nil { log.Error("VMessOut: Failed to serialize VMess request: %v", err) return } // Send first packet of payload together with request, in favor of small requests. payload, open := <-input if open { encryptRequestWriter.Crypt(payload) buffer = append(buffer, payload...) _, err = conn.Write(buffer) if err != nil { log.Error("VMessOut: Failed to write VMess request: %v", err) return } v2net.ChanToWriter(encryptRequestWriter, input) } return }
func (handler *VMessInboundHandler) handlePacket(conn *net.UDPConn, request *protocol.VMessRequest, packet v2net.Packet, clientAddr *net.UDPAddr) { ray := handler.vPoint.DispatchToOutbound(packet) close(ray.InboundInput()) responseKey := md5.Sum(request.RequestKey) responseIV := md5.Sum(request.RequestIV) buffer := alloc.NewBuffer().Clear() defer buffer.Release() responseWriter, err := v2io.NewAesEncryptWriter(responseKey[:], responseIV[:], buffer) if err != nil { log.Error("VMessIn: Failed to create encrypt writer: %v", err) return } responseWriter.Write(request.ResponseHeader) hasData := false if data, ok := <-ray.InboundOutput(); ok { hasData = true responseWriter.Write(data.Value) data.Release() } if hasData { conn.WriteToUDP(buffer.Value, clientAddr) log.Info("VMessIn sending %d bytes to %s", buffer.Len(), clientAddr.String()) } }
func (handler *VMessInboundHandler) handlePacket(conn *net.UDPConn, request *protocol.VMessRequest, packet v2net.Packet, clientAddr *net.UDPAddr) { ray := handler.vPoint.DispatchToOutbound(packet) close(ray.InboundInput()) responseKey := md5.Sum(request.RequestKey[:]) responseIV := md5.Sum(request.RequestIV[:]) buffer := bytes.NewBuffer(make([]byte, 0, bufferSize)) response := protocol.NewVMessResponse(request) responseWriter, err := v2io.NewAesEncryptWriter(responseKey[:], responseIV[:], buffer) if err != nil { log.Error("VMessIn: Failed to create encrypt writer: %v", err) return } responseWriter.Write(response[:]) hasData := false if data, ok := <-ray.InboundOutput(); ok { hasData = true responseWriter.Write(data) } if hasData { conn.WriteToUDP(buffer.Bytes(), clientAddr) log.Info("VMessIn sending %d bytes to %s", len(buffer.Bytes()), clientAddr.String()) } }
func (handler *VMessInboundHandler) HandleConnection(connection *net.TCPConn) error { defer connection.Close() connReader := v2net.NewTimeOutReader(16, connection) requestReader := protocol.NewVMessRequestReader(handler.clients) request, err := requestReader.Read(connReader) if err != nil { log.Access(connection.RemoteAddr().String(), "", log.AccessRejected, err.Error()) log.Warning("VMessIn: Invalid request from (%s): %v", connection.RemoteAddr().String(), err) return err } log.Access(connection.RemoteAddr().String(), request.Address.String(), log.AccessAccepted, "") log.Debug("VMessIn: Received request for %s", request.Address.String()) ray := handler.dispatcher.DispatchToOutbound(v2net.NewPacket(request.Destination(), nil, true)) input := ray.InboundInput() output := ray.InboundOutput() var readFinish, writeFinish sync.Mutex readFinish.Lock() writeFinish.Lock() userSettings := config.GetUserSettings(request.User.Level()) connReader.SetTimeOut(userSettings.PayloadReadTimeout) go handleInput(request, connReader, input, &readFinish) responseKey := md5.Sum(request.RequestKey) responseIV := md5.Sum(request.RequestIV) responseWriter, err := v2io.NewAesEncryptWriter(responseKey[:], responseIV[:], connection) if err != nil { log.Error("VMessIn: Failed to create encrypt writer: %v", err) return err } // Optimize for small response packet buffer := alloc.NewLargeBuffer().Clear() buffer.Append(request.ResponseHeader) if data, open := <-output; open { buffer.Append(data.Value) data.Release() responseWriter.Write(buffer.Value) buffer.Release() go handleOutput(request, responseWriter, output, &writeFinish) writeFinish.Lock() } connection.CloseWrite() readFinish.Lock() return nil }
func (handler *VMessInboundHandler) HandleConnection(connection net.Conn) error { defer connection.Close() reader := protocol.NewVMessRequestReader(handler.clients) // Timeout 4 seconds to prevent DoS attack connection.SetReadDeadline(time.Now().Add(requestReadTimeOut)) request, err := reader.Read(connection) if err != nil { log.Warning("VMessIn: Invalid request from (%s): %v", connection.RemoteAddr().String(), err) return err } log.Debug("VMessIn: Received request for %s", request.Address.String()) // Clear read timeout connection.SetReadDeadline(zeroTime) ray := handler.vPoint.NewInboundConnectionAccepted(request.Destination()) input := ray.InboundInput() output := ray.InboundOutput() readFinish := make(chan bool) writeFinish := make(chan bool) go handleInput(request, connection, input, readFinish) responseKey := md5.Sum(request.RequestKey[:]) responseIV := md5.Sum(request.RequestIV[:]) response := protocol.NewVMessResponse(request) responseWriter, err := v2io.NewAesEncryptWriter(responseKey[:], responseIV[:], connection) if err != nil { return log.Error("VMessIn: Failed to create encrypt writer: %v", err) } // Optimize for small response packet buffer := make([]byte, 0, 1024) buffer = append(buffer, response[:]...) if data, open := <-output; open { buffer = append(buffer, data...) responseWriter.Write(buffer) go handleOutput(request, responseWriter, output, writeFinish) <-writeFinish } if tcpConn, ok := connection.(*net.TCPConn); ok { tcpConn.CloseWrite() } <-readFinish return nil }
func (handler *VMessInboundHandler) HandleConnection(connection net.Conn) error { defer connection.Close() connReader := v2net.NewTimeOutReader(4, connection) requestReader := protocol.NewVMessRequestReader(handler.clients) request, err := requestReader.Read(connReader) if err != nil { log.Warning("VMessIn: Invalid request from (%s): %v", connection.RemoteAddr().String(), err) return err } log.Debug("VMessIn: Received request for %s", request.Address.String()) ray := handler.vPoint.DispatchToOutbound(v2net.NewPacket(request.Destination(), nil, true)) input := ray.InboundInput() output := ray.InboundOutput() var readFinish, writeFinish sync.Mutex readFinish.Lock() writeFinish.Lock() go handleInput(request, connReader, input, &readFinish) responseKey := md5.Sum(request.RequestKey[:]) responseIV := md5.Sum(request.RequestIV[:]) response := protocol.NewVMessResponse(request) responseWriter, err := v2io.NewAesEncryptWriter(responseKey[:], responseIV[:], connection) if err != nil { return log.Error("VMessIn: Failed to create encrypt writer: %v", err) } // Optimize for small response packet buffer := make([]byte, 0, 2*1024) buffer = append(buffer, response[:]...) if data, open := <-output; open { buffer = append(buffer, data...) responseWriter.Write(buffer) go handleOutput(request, responseWriter, output, &writeFinish) writeFinish.Lock() } if tcpConn, ok := connection.(*net.TCPConn); ok { tcpConn.CloseWrite() } readFinish.Lock() return nil }
func handleRequest(conn net.Conn, request *protocol.VMessRequest, firstPacket v2net.Packet, input <-chan *alloc.Buffer, finish *sync.Mutex) { defer finish.Unlock() encryptRequestWriter, err := v2io.NewAesEncryptWriter(request.RequestKey[:], request.RequestIV[:], conn) if err != nil { log.Error("VMessOut: Failed to create encrypt writer: %v", err) return } buffer := alloc.NewBuffer() buffer.Clear() requestBytes, err := request.ToBytes(user.NewTimeHash(user.HMACHash{}), user.GenerateRandomInt64InRange, buffer.Value) if err != nil { log.Error("VMessOut: Failed to serialize VMess request: %v", err) return } // Send first packet of payload together with request, in favor of small requests. firstChunk := firstPacket.Chunk() moreChunks := firstPacket.MoreChunks() if firstChunk == nil && moreChunks { firstChunk, moreChunks = <-input } if firstChunk != nil { encryptRequestWriter.Crypt(firstChunk.Value) requestBytes = append(requestBytes, firstChunk.Value...) firstChunk.Release() _, err = conn.Write(requestBytes) buffer.Release() if err != nil { log.Error("VMessOut: Failed to write VMess request: %v", err) return } } if moreChunks { v2net.ChanToWriter(encryptRequestWriter, input) } return }