예제 #1
0
func TestNormalChunkWriting(t *testing.T) {
	assert := assert.On(t)

	buffer := alloc.NewLocalBuffer(512).Clear()
	writer := NewChunkWriter(buffer, NewAuthenticator(ChunkKeyGenerator(
		[]byte{21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36})))

	err := writer.Write(alloc.NewLocalBuffer(256).Clear().Append([]byte{11, 12, 13, 14, 15, 16, 17, 18}))
	assert.Error(err).IsNil()
	assert.Bytes(buffer.Value).Equals([]byte{0, 8, 39, 228, 69, 96, 133, 39, 254, 26, 201, 70, 11, 12, 13, 14, 15, 16, 17, 18})
}
예제 #2
0
func TestUDPEncoding(t *testing.T) {
	assert := assert.On(t)

	request := &protocol.RequestHeader{
		Version: Version,
		Command: protocol.RequestCommandUDP,
		Address: v2net.LocalHostIP,
		Port:    1234,
		User: &protocol.User{
			Email: "*****@*****.**",
			Account: loader.NewTypedSettings(&Account{
				Password:   "******",
				CipherType: CipherType_AES_128_CFB,
				Ota:        Account_Disabled,
			}),
		},
	}

	data := alloc.NewLocalBuffer(256).Clear().AppendString("test string")
	encodedData, err := EncodeUDPPacket(request, data)
	assert.Error(err).IsNil()

	decodedRequest, decodedData, err := DecodeUDPPacket(request.User, encodedData)
	assert.Error(err).IsNil()
	assert.Bytes(decodedData.Value).Equals(data.Value)
	assert.Address(decodedRequest.Address).Equals(request.Address)
	assert.Port(decodedRequest.Port).Equals(request.Port)
}
예제 #3
0
func TestResponseWrite(t *testing.T) {
	assert := assert.On(t)

	response := Socks5Response{
		socksVersion,
		ErrorSuccess,
		AddrTypeIPv4,
		[4]byte{0x72, 0x72, 0x72, 0x72},
		"",
		[16]byte{},
		v2net.Port(53),
	}
	buffer := alloc.NewLocalBuffer(2048).Clear()
	defer buffer.Release()

	response.Write(buffer)
	expectedBytes := []byte{
		socksVersion,
		ErrorSuccess,
		byte(0x00),
		AddrTypeIPv4,
		0x72, 0x72, 0x72, 0x72,
		byte(0x00), byte(0x035),
	}
	assert.Bytes(buffer.Value).Equals(expectedBytes)
}
예제 #4
0
func TestTCPRequest(t *testing.T) {
	assert := assert.On(t)

	request := &protocol.RequestHeader{
		Version: Version,
		Command: protocol.RequestCommandTCP,
		Address: v2net.LocalHostIP,
		Option:  RequestOptionOneTimeAuth,
		Port:    1234,
		User: &protocol.User{
			Email: "*****@*****.**",
			Account: loader.NewTypedSettings(&Account{
				Password:   "******",
				CipherType: CipherType_CHACHA20,
			}),
		},
	}

	data := alloc.NewLocalBuffer(256).Clear().AppendString("test string")
	cache := alloc.NewBuffer().Clear()

	writer, err := WriteTCPRequest(request, cache)
	assert.Error(err).IsNil()

	writer.Write(data)

	decodedRequest, reader, err := ReadTCPSession(request.User, cache)
	assert.Error(err).IsNil()
	assert.Address(decodedRequest.Address).Equals(request.Address)
	assert.Port(decodedRequest.Port).Equals(request.Port)

	decodedData, err := reader.Read()
	assert.Error(err).IsNil()
	assert.Bytes(decodedData.Value).Equals([]byte("test string"))
}
예제 #5
0
func (this *VMessOutboundHandler) handleRequest(session *encoding.ClientSession, conn internet.Connection, request *protocol.RequestHeader, payload *alloc.Buffer, input v2io.Reader, finish *sync.Mutex) {
	defer finish.Unlock()

	writer := v2io.NewBufferedWriter(conn)
	defer writer.Release()
	session.EncodeRequestHeader(request, writer)

	bodyWriter := session.EncodeRequestBody(writer)
	var streamWriter v2io.Writer = v2io.NewAdaptiveWriter(bodyWriter)
	if request.Option.Has(protocol.RequestOptionChunkStream) {
		streamWriter = vmessio.NewAuthChunkWriter(streamWriter)
	}
	if !payload.IsEmpty() {
		if err := streamWriter.Write(payload); err != nil {
			conn.SetReusable(false)
		}
	}
	writer.SetCached(false)

	err := v2io.Pipe(input, streamWriter)
	if err != io.EOF {
		conn.SetReusable(false)
	}

	if request.Option.Has(protocol.RequestOptionChunkStream) {
		err := streamWriter.Write(alloc.NewLocalBuffer(32).Clear())
		if err != nil {
			conn.SetReusable(false)
		}
	}
	streamWriter.Release()
	return
}
예제 #6
0
func ReadUserPassRequest(reader io.Reader) (request Socks5UserPassRequest, err error) {
	buffer := alloc.NewLocalBuffer(512)
	defer buffer.Release()

	_, err = reader.Read(buffer.Value[0:2])
	if err != nil {
		return
	}
	request.version = buffer.Value[0]
	nUsername := buffer.Value[1]
	nBytes, err := reader.Read(buffer.Value[:nUsername])
	if err != nil {
		return
	}
	request.username = string(buffer.Value[:nBytes])

	_, err = reader.Read(buffer.Value[0:1])
	if err != nil {
		return
	}
	nPassword := buffer.Value[0]
	nBytes, err = reader.Read(buffer.Value[:nPassword])
	if err != nil {
		return
	}
	request.password = string(buffer.Value[:nBytes])
	return
}
예제 #7
0
파일: ota.go 프로젝트: xyz12810/v2ray-core
func (this *ChunkReader) Read() (*alloc.Buffer, error) {
	buffer := alloc.NewBuffer()
	if _, err := io.ReadFull(this.reader, buffer.Value[:2]); err != nil {
		buffer.Release()
		return nil, err
	}
	// There is a potential buffer overflow here. Large buffer is 64K bytes,
	// while uin16 + 10 will be more than that
	length := serial.BytesToUint16(buffer.Value[:2]) + AuthSize
	if length > alloc.BufferSize {
		// Theoretically the size of a chunk is 64K, but most Shadowsocks implementations used <4K buffer.
		buffer.Release()
		buffer = alloc.NewLocalBuffer(int(length) + 128)
	}
	if _, err := io.ReadFull(this.reader, buffer.Value[:length]); err != nil {
		buffer.Release()
		return nil, err
	}
	buffer.Slice(0, int(length))

	authBytes := buffer.Value[:AuthSize]
	payload := buffer.Value[AuthSize:]

	actualAuthBytes := this.auth.Authenticate(nil, payload)
	if !bytes.Equal(authBytes, actualAuthBytes) {
		buffer.Release()
		return nil, errors.New("Shadowsocks|AuthenticationReader: Invalid auth.")
	}
	buffer.SliceFrom(AuthSize)

	return buffer, nil
}
예제 #8
0
func MarshalCommand(command interface{}, writer io.Writer) error {
	if command == nil {
		return ErrUnknownCommand
	}

	var cmdId byte
	var factory CommandFactory
	switch command.(type) {
	case *protocol.CommandSwitchAccount:
		factory = new(CommandSwitchAccountFactory)
		cmdId = 1
	default:
		return ErrUnknownCommand
	}

	buffer := alloc.NewLocalBuffer(512).Clear()
	defer buffer.Release()

	err := factory.Marshal(command, buffer)
	if err != nil {
		return err
	}

	auth := Authenticate(buffer.Value)
	len := buffer.Len() + 4
	if len > 255 {
		return ErrCommandTooLarge
	}

	writer.Write([]byte{cmdId, byte(len), byte(auth >> 24), byte(auth >> 16), byte(auth >> 8), byte(auth)})
	writer.Write(buffer.Value)
	return nil
}
예제 #9
0
func (this *DefaultDispatcher) DispatchToOutbound(meta *proxy.InboundHandlerMeta, session *proxy.SessionInfo) ray.InboundRay {
	direct := ray.NewRay()
	dispatcher := this.ohm.GetDefaultHandler()
	destination := session.Destination

	if this.router != nil {
		if tag, err := this.router.TakeDetour(destination); err == nil {
			if handler := this.ohm.GetHandler(tag); handler != nil {
				log.Info("DefaultDispatcher: Taking detour [", tag, "] for [", destination, "].")
				dispatcher = handler
			} else {
				log.Warning("DefaultDispatcher: Nonexisting tag: ", tag)
			}
		} else {
			log.Info("DefaultDispatcher: Default route for ", destination)
		}
	}

	if meta.AllowPassiveConnection {
		go dispatcher.Dispatch(destination, alloc.NewLocalBuffer(32).Clear(), direct)
	} else {
		go this.FilterPacketAndDispatch(destination, direct, dispatcher)
	}

	return direct
}
예제 #10
0
func TestSocks4AuthenticationResponseToBytes(t *testing.T) {
	assert := assert.On(t)

	response := NewSocks4AuthenticationResponse(byte(0x10), 443, []byte{1, 2, 3, 4})

	buffer := alloc.NewLocalBuffer(2048).Clear()
	defer buffer.Release()

	response.Write(buffer)
	assert.Bytes(buffer.Value).Equals([]byte{0x00, 0x10, 0x01, 0xBB, 0x01, 0x02, 0x03, 0x04})
}
예제 #11
0
func TestSRTPOpenSeal(t *testing.T) {
	assert := assert.On(t)

	content := []byte{'a', 'b', 'c', 'd', 'e', 'f', 'g'}
	payload := alloc.NewLocalBuffer(2048).Clear().Append(content)
	srtp := SRTP{}
	srtp.Seal(payload)
	assert.Int(payload.Len()).GreaterThan(len(content))
	assert.Bool(srtp.Open(payload)).IsTrue()
	assert.Bytes(content).Equals(payload.Bytes())
}
예제 #12
0
func TestSetIPv6(t *testing.T) {
	assert := assert.On(t)

	response := NewSocks5Response()
	response.SetIPv6([]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15})

	buffer := alloc.NewLocalBuffer(2048).Clear()
	defer buffer.Release()
	response.Write(buffer)
	assert.Bytes(buffer.Value).Equals([]byte{
		socksVersion, 0, 0, AddrTypeIPv6, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0})
}
예제 #13
0
func TestSetDomain(t *testing.T) {
	assert := assert.On(t)

	response := NewSocks5Response()
	response.SetDomain("v2ray.com")

	buffer := alloc.NewLocalBuffer(2048).Clear()
	defer buffer.Release()
	response.Write(buffer)
	assert.Bytes(buffer.Value).Equals([]byte{
		socksVersion, 0, 0, AddrTypeDomain, 9, 118, 50, 114, 97, 121, 46, 99, 111, 109, 0, 0})
}
예제 #14
0
func TestSimpleAuthenticator2(t *testing.T) {
	assert := assert.On(t)

	buffer := alloc.NewLocalBuffer(512).Clear()
	buffer.AppendBytes('1', '2')

	auth := NewSimpleAuthenticator()
	auth.Seal(buffer)

	assert.Bool(auth.Open(buffer)).IsTrue()
	assert.Bytes(buffer.Value).Equals([]byte{'1', '2'})
}
예제 #15
0
func BenchmarkSimpleAuthenticator(b *testing.B) {
	buffer := alloc.NewLocalBuffer(2048).Clear()
	buffer.Slice(0, 1024)
	rand.Read(buffer.Value)

	auth := NewSimpleAuthenticator()
	b.SetBytes(int64(buffer.Len()))
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		auth.Seal(buffer)
		auth.Open(buffer)
	}
}
예제 #16
0
func TestReaderWriter(t *testing.T) {
	assert := assert.On(t)

	cache := alloc.NewBuffer()
	writer := NewHeaderWriter(alloc.NewLocalBuffer(256).Clear().AppendString("abcd" + ENDING))
	writer.Write(cache)
	cache.Write([]byte{'e', 'f', 'g'})

	reader := &HeaderReader{}
	buffer, err := reader.Read(cache)
	assert.Error(err).IsNil()
	assert.Bytes(buffer.Value).Equals([]byte{'e', 'f', 'g'})
}
예제 #17
0
func ReadRequest(reader io.Reader) (request *Socks5Request, err error) {
	buffer := alloc.NewLocalBuffer(512)
	defer buffer.Release()

	_, err = io.ReadFull(reader, buffer.Value[:4])
	if err != nil {
		return
	}

	request = &Socks5Request{
		Version: buffer.Value[0],
		Command: buffer.Value[1],
		// buffer[2] is a reserved field
		AddrType: buffer.Value[3],
	}
	switch request.AddrType {
	case AddrTypeIPv4:
		_, err = io.ReadFull(reader, request.IPv4[:])
		if err != nil {
			return
		}
	case AddrTypeDomain:
		_, err = io.ReadFull(reader, buffer.Value[0:1])
		if err != nil {
			return
		}
		domainLength := buffer.Value[0]
		_, err = io.ReadFull(reader, buffer.Value[:domainLength])
		if err != nil {
			return
		}

		request.Domain = string(append([]byte(nil), buffer.Value[:domainLength]...))
	case AddrTypeIPv6:
		_, err = io.ReadFull(reader, request.IPv6[:])
		if err != nil {
			return
		}
	default:
		err = fmt.Errorf("Socks: Unexpected address type %d", request.AddrType)
		return
	}

	_, err = io.ReadFull(reader, buffer.Value[:2])
	if err != nil {
		return
	}

	request.Port = v2net.PortFromBytes(buffer.Value[:2])
	return
}
예제 #18
0
파일: http.go 프로젝트: xyz12810/v2ray-core
func (this HttpAuthenticator) GetClientWriter() *HeaderWriter {
	header := alloc.NewLocalBuffer(2048).Clear()
	config := this.config.Request
	header.AppendString(config.Method.GetValue()).AppendString(" ").AppendString(config.PickUri()).AppendString(" ").AppendString(config.GetFullVersion()).AppendString(CRLF)

	headers := config.PickHeaders()
	for _, h := range headers {
		header.AppendString(h).AppendString(CRLF)
	}
	header.AppendString(CRLF)
	return &HeaderWriter{
		header: header,
	}
}
예제 #19
0
func (this *Server) handleUDPPayload(payload *alloc.Buffer, session *proxy.SessionInfo) {
	source := session.Source
	log.Info("Socks: Client UDP connection from ", source)
	request, err := protocol.ReadUDPRequest(payload.Value)
	payload.Release()

	if err != nil {
		log.Error("Socks: Failed to parse UDP request: ", err)
		return
	}
	if request.Data.Len() == 0 {
		request.Data.Release()
		return
	}
	if request.Fragment != 0 {
		log.Warning("Socks: Dropping fragmented UDP packets.")
		// TODO handle fragments
		request.Data.Release()
		return
	}

	log.Info("Socks: Send packet to ", request.Destination(), " with ", request.Data.Len(), " bytes")
	log.Access(source, request.Destination, log.AccessAccepted, "")
	this.udpServer.Dispatch(&proxy.SessionInfo{Source: source, Destination: request.Destination()}, request.Data, func(destination v2net.Destination, payload *alloc.Buffer) {
		response := &protocol.Socks5UDPRequest{
			Fragment: 0,
			Address:  request.Destination().Address(),
			Port:     request.Destination().Port(),
			Data:     payload,
		}
		log.Info("Socks: Writing back UDP response with ", payload.Len(), " bytes to ", destination)

		udpMessage := alloc.NewLocalBuffer(2048).Clear()
		response.Write(udpMessage)

		this.udpMutex.RLock()
		if !this.accepting {
			this.udpMutex.RUnlock()
			return
		}
		nBytes, err := this.udpHub.WriteTo(udpMessage.Value, destination)
		this.udpMutex.RUnlock()
		udpMessage.Release()
		response.Data.Release()
		if err != nil {
			log.Error("Socks: failed to write UDP message (", nBytes, " bytes) to ", destination, ": ", err)
		}
	})
}
예제 #20
0
func (this *UDPReader) Read() (*alloc.Buffer, error) {
	buffer := alloc.NewLocalBuffer(2048)
	nBytes, err := this.Reader.Read(buffer.Value)
	if err != nil {
		buffer.Release()
		return nil, err
	}
	buffer.Slice(0, nBytes)
	_, payload, err := DecodeUDPPacket(this.User, buffer)
	if err != nil {
		buffer.Release()
		return nil, err
	}
	return payload, nil
}
예제 #21
0
func (this *BufferedSegmentWriter) Write(seg Segment) {
	this.Lock()
	defer this.Unlock()

	nBytes := seg.ByteSize()
	if uint32(this.buffer.Len()+nBytes) > this.mtu {
		this.FlushWithoutLock()
	}

	if this.buffer == nil {
		this.buffer = alloc.NewLocalBuffer(2048).Clear()
	}

	this.buffer.Value = seg.Bytes(this.buffer.Value)
}
예제 #22
0
func EncodeUDPPacket(request *protocol.RequestHeader, payload *alloc.Buffer) (*alloc.Buffer, error) {
	user := request.User
	rawAccount, err := user.GetTypedAccount()
	if err != nil {
		return nil, errors.New("Shadowsocks|UDP: Failed to parse account: " + err.Error())
	}
	account := rawAccount.(*ShadowsocksAccount)

	buffer := alloc.NewLocalBuffer(2048)
	ivLen := account.Cipher.IVSize()
	buffer.Slice(0, ivLen)
	rand.Read(buffer.Value)
	iv := buffer.Value

	switch request.Address.Family() {
	case v2net.AddressFamilyIPv4:
		buffer.AppendBytes(AddrTypeIPv4)
		buffer.Append([]byte(request.Address.IP()))
	case v2net.AddressFamilyIPv6:
		buffer.AppendBytes(AddrTypeIPv6)
		buffer.Append([]byte(request.Address.IP()))
	case v2net.AddressFamilyDomain:
		buffer.AppendBytes(AddrTypeDomain, byte(len(request.Address.Domain())))
		buffer.Append([]byte(request.Address.Domain()))
	default:
		return nil, errors.New("Shadowsocks|UDP: Unsupported address type. ")
	}

	buffer.AppendUint16(uint16(request.Port))
	buffer.Append(payload.Value)

	if request.Option.Has(RequestOptionOneTimeAuth) {
		authenticator := NewAuthenticator(HeaderKeyGenerator(account.Key, iv))
		buffer.Value[ivLen] |= 0x10

		buffer.Value = authenticator.Authenticate(buffer.Value, buffer.Value[ivLen:])
	}

	stream, err := account.Cipher.NewEncodingStream(account.Key, iv)
	if err != nil {
		return nil, errors.New("Shadowsocks|TCP: Failed to create encoding stream: " + err.Error())
	}

	stream.XORKeyStream(buffer.Value[ivLen:], buffer.Value[ivLen:])
	return buffer, nil
}
예제 #23
0
파일: http.go 프로젝트: xyz12810/v2ray-core
func (this HttpAuthenticator) GetServerWriter() *HeaderWriter {
	header := alloc.NewLocalBuffer(2048).Clear()
	config := this.config.Response
	header.AppendString(config.GetFullVersion()).AppendString(" ").AppendString(config.Status.GetCode()).AppendString(" ").AppendString(config.Status.GetReason()).AppendString(CRLF)

	headers := config.PickHeaders()
	for _, h := range headers {
		header.AppendString(h).AppendString(CRLF)
	}
	if !config.HasHeader("Date") {
		header.AppendString("Date: ").AppendString(time.Now().Format(http.TimeFormat)).AppendString(CRLF)
	}
	header.AppendString(CRLF)
	return &HeaderWriter{
		header: header,
	}
}
예제 #24
0
func (this *Connection) FetchInputFrom(conn io.Reader) {
	go func() {
		payload := alloc.NewLocalBuffer(2048)
		defer payload.Release()
		for this.State() != StateTerminated {
			payload.Reset()
			nBytes, err := conn.Read(payload.Value)
			if err != nil {
				return
			}
			payload.Slice(0, nBytes)
			if this.block.Open(payload) {
				this.Input(payload.Value)
			}
		}
	}()
}
예제 #25
0
func TestUnreachableDestination(t *testing.T) {
	assert := assert.On(t)

	freedom := NewFreedomConnection(
		&Config{},
		app.NewSpace(),
		&proxy.OutboundHandlerMeta{
			Address: v2net.AnyIP,
			StreamSettings: &internet.StreamConfig{
				Network: v2net.Network_RawTCP,
			},
		})
	traffic := ray.NewRay()
	data2Send := "Data to be sent to remote"
	payload := alloc.NewLocalBuffer(2048).Clear().Append([]byte(data2Send))

	err := freedom.Dispatch(v2net.TCPDestination(v2net.IPAddress([]byte{127, 0, 0, 1}), 128), payload, traffic)
	assert.Error(err).IsNotNil()
}
예제 #26
0
파일: http.go 프로젝트: xyz12810/v2ray-core
func (*HeaderReader) Read(reader io.Reader) (*alloc.Buffer, error) {
	buffer := alloc.NewLocalBuffer(2048)
	for {
		_, err := buffer.FillFrom(reader)
		if err != nil {
			return nil, err
		}
		if n := bytes.Index(buffer.Value, []byte(ENDING)); n != -1 {
			buffer.SliceFrom(n + len(ENDING))
			break
		}
		if buffer.Len() >= len(ENDING) {
			copy(buffer.Value, buffer.Value[buffer.Len()-len(ENDING):])
			buffer.Slice(0, len(ENDING))
		}
	}
	if buffer.IsEmpty() {
		buffer.Release()
		return nil, nil
	}
	return buffer, nil
}
예제 #27
0
func TestSinglePacket(t *testing.T) {
	assert := assert.On(t)

	tcpServer := &tcp.Server{
		MsgProcessor: func(data []byte) []byte {
			buffer := make([]byte, 0, 2048)
			buffer = append(buffer, []byte("Processed: ")...)
			buffer = append(buffer, data...)
			return buffer
		},
	}
	_, err := tcpServer.Start()
	assert.Error(err).IsNil()

	space := app.NewSpace()
	freedom := NewFreedomConnection(
		&Config{},
		space,
		&proxy.OutboundHandlerMeta{
			Address: v2net.AnyIP,
			StreamSettings: &internet.StreamConfig{
				Network: v2net.Network_RawTCP,
			},
		})
	space.Initialize()

	traffic := ray.NewRay()
	data2Send := "Data to be sent to remote"
	payload := alloc.NewLocalBuffer(2048).Clear().Append([]byte(data2Send))

	go freedom.Dispatch(v2net.TCPDestination(v2net.LocalHostIP, tcpServer.Port), payload, traffic)
	traffic.InboundInput().Close()

	respPayload, err := traffic.InboundOutput().Read()
	assert.Error(err).IsNil()
	assert.Bytes(respPayload.Value).Equals([]byte("Processed: Data to be sent to remote"))

	tcpServer.Close()
}
예제 #28
0
func TestDataSegment(t *testing.T) {
	assert := assert.On(t)

	seg := &DataSegment{
		Conv:        1,
		Timestamp:   3,
		Number:      4,
		SendingNext: 5,
		Data:        alloc.NewLocalBuffer(512).Clear().Append([]byte{'a', 'b', 'c', 'd'}),
	}

	nBytes := seg.ByteSize()
	bytes := seg.Bytes(nil)

	assert.Int(len(bytes)).Equals(nBytes)

	iseg, _ := ReadSegment(bytes)
	seg2 := iseg.(*DataSegment)
	assert.Uint16(seg2.Conv).Equals(seg.Conv)
	assert.Uint32(seg2.Timestamp).Equals(seg.Timestamp)
	assert.Uint32(seg2.SendingNext).Equals(seg.SendingNext)
	assert.Uint32(seg2.Number).Equals(seg.Number)
	assert.Bytes(seg2.Data.Value).Equals(seg.Data.Value)
}
예제 #29
0
func (this *HTTPResponse) WriteTo(writer v2io.Writer) {
	writer.Write(alloc.NewLocalBuffer(512).Clear().AppendString(http403response))
}
예제 #30
0
func (this *VMessInboundHandler) HandleConnection(connection internet.Connection) {
	defer connection.Close()

	if !this.accepting {
		return
	}

	connReader := v2net.NewTimeOutReader(8, connection)
	defer connReader.Release()

	reader := v2io.NewBufferedReader(connReader)
	defer reader.Release()

	this.RLock()
	if !this.accepting {
		this.RUnlock()
		return
	}
	session := encoding.NewServerSession(this.clients)
	defer session.Release()

	request, err := session.DecodeRequestHeader(reader)
	this.RUnlock()

	if err != nil {
		if err != io.EOF {
			log.Access(connection.RemoteAddr(), "", log.AccessRejected, err)
			log.Warning("VMessIn: Invalid request from ", connection.RemoteAddr(), ": ", err)
		}
		connection.SetReusable(false)
		return
	}
	log.Access(connection.RemoteAddr(), request.Destination(), log.AccessAccepted, "")
	log.Info("VMessIn: Received request for ", request.Destination())

	connection.SetReusable(request.Option.Has(protocol.RequestOptionConnectionReuse))

	ray := this.packetDispatcher.DispatchToOutbound(this.meta, &proxy.SessionInfo{
		Source:      v2net.DestinationFromAddr(connection.RemoteAddr()),
		Destination: request.Destination(),
	})
	input := ray.InboundInput()
	output := ray.InboundOutput()
	defer input.Close()
	defer output.Release()

	var readFinish sync.Mutex
	readFinish.Lock()

	userSettings := protocol.GetUserSettings(request.User.Level)
	connReader.SetTimeOut(userSettings.PayloadReadTimeout)
	reader.SetCached(false)

	go func() {
		bodyReader := session.DecodeRequestBody(reader)
		var requestReader v2io.Reader
		if request.Option.Has(protocol.RequestOptionChunkStream) {
			requestReader = vmessio.NewAuthChunkReader(bodyReader)
		} else {
			requestReader = v2io.NewAdaptiveReader(bodyReader)
		}
		err := v2io.Pipe(requestReader, input)
		if err != io.EOF {
			connection.SetReusable(false)
		}

		requestReader.Release()
		input.Close()
		readFinish.Unlock()
	}()

	writer := v2io.NewBufferedWriter(connection)
	defer writer.Release()

	response := &protocol.ResponseHeader{
		Command: this.generateCommand(request),
	}

	if connection.Reusable() {
		response.Option.Set(protocol.ResponseOptionConnectionReuse)
	}

	session.EncodeResponseHeader(response, writer)

	bodyWriter := session.EncodeResponseBody(writer)
	var v2writer v2io.Writer = v2io.NewAdaptiveWriter(bodyWriter)
	if request.Option.Has(protocol.RequestOptionChunkStream) {
		v2writer = vmessio.NewAuthChunkWriter(v2writer)
	}

	// Optimize for small response packet
	if data, err := output.Read(); err == nil {
		if err := v2writer.Write(data); err != nil {
			connection.SetReusable(false)
		}

		writer.SetCached(false)

		err = v2io.Pipe(output, v2writer)
		if err != io.EOF {
			connection.SetReusable(false)
		}

	}
	output.Release()
	if request.Option.Has(protocol.RequestOptionChunkStream) {
		if err := v2writer.Write(alloc.NewLocalBuffer(32).Clear()); err != nil {
			connection.SetReusable(false)
		}
	}
	writer.Flush()
	v2writer.Release()

	readFinish.Lock()
}