|  | @@ -112,7 +112,7 @@ func NewServerSession(validator protocol.UserValidator, sessionHistory *SessionH
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -func (v *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.RequestHeader, error) {
 | 
	
		
			
				|  |  | +func (s *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.RequestHeader, error) {
 | 
	
		
			
				|  |  |  	buffer := make([]byte, 512)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	_, err := io.ReadFull(reader, buffer[:protocol.IDBytesLen])
 | 
	
	
		
			
				|  | @@ -120,7 +120,7 @@ func (v *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Request
 | 
	
		
			
				|  |  |  		return nil, newError("failed to read request header").Base(err)
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	user, timestamp, valid := v.userValidator.Get(buffer[:protocol.IDBytesLen])
 | 
	
		
			
				|  |  | +	user, timestamp, valid := s.userValidator.Get(buffer[:protocol.IDBytesLen])
 | 
	
		
			
				|  |  |  	if !valid {
 | 
	
		
			
				|  |  |  		return nil, newError("invalid user")
 | 
	
		
			
				|  |  |  	}
 | 
	
	
		
			
				|  | @@ -152,18 +152,18 @@ func (v *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Request
 | 
	
		
			
				|  |  |  		return nil, newError("invalid protocol version ", request.Version)
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	v.requestBodyIV = append([]byte(nil), buffer[1:17]...)   // 16 bytes
 | 
	
		
			
				|  |  | -	v.requestBodyKey = append([]byte(nil), buffer[17:33]...) // 16 bytes
 | 
	
		
			
				|  |  | +	s.requestBodyIV = append([]byte(nil), buffer[1:17]...)   // 16 bytes
 | 
	
		
			
				|  |  | +	s.requestBodyKey = append([]byte(nil), buffer[17:33]...) // 16 bytes
 | 
	
		
			
				|  |  |  	var sid sessionId
 | 
	
		
			
				|  |  |  	copy(sid.user[:], vmessAccount.ID.Bytes())
 | 
	
		
			
				|  |  | -	copy(sid.key[:], v.requestBodyKey)
 | 
	
		
			
				|  |  | -	copy(sid.nonce[:], v.requestBodyIV)
 | 
	
		
			
				|  |  | -	if v.sessionHistory.has(sid) {
 | 
	
		
			
				|  |  | +	copy(sid.key[:], s.requestBodyKey)
 | 
	
		
			
				|  |  | +	copy(sid.nonce[:], s.requestBodyIV)
 | 
	
		
			
				|  |  | +	if s.sessionHistory.has(sid) {
 | 
	
		
			
				|  |  |  		return nil, newError("duplicated session id, possibly under replay attack")
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  | -	v.sessionHistory.add(sid)
 | 
	
		
			
				|  |  | +	s.sessionHistory.add(sid)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	v.responseHeader = buffer[33]                       // 1 byte
 | 
	
		
			
				|  |  | +	s.responseHeader = buffer[33]                       // 1 byte
 | 
	
		
			
				|  |  |  	request.Option = protocol.RequestOption(buffer[34]) // 1 byte
 | 
	
		
			
				|  |  |  	padingLen := int(buffer[35] >> 4)
 | 
	
		
			
				|  |  |  	request.Security = protocol.NormSecurity(protocol.Security(buffer[35] & 0x0F))
 | 
	
	
		
			
				|  | @@ -235,10 +235,10 @@ func (v *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Request
 | 
	
		
			
				|  |  |  	return request, nil
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -func (v *ServerSession) DecodeRequestBody(request *protocol.RequestHeader, reader io.Reader) buf.Reader {
 | 
	
		
			
				|  |  | +func (s *ServerSession) DecodeRequestBody(request *protocol.RequestHeader, reader io.Reader) buf.Reader {
 | 
	
		
			
				|  |  |  	var sizeParser crypto.ChunkSizeDecoder = crypto.PlainChunkSizeParser{}
 | 
	
		
			
				|  |  |  	if request.Option.Has(protocol.RequestOptionChunkMasking) {
 | 
	
		
			
				|  |  | -		sizeParser = NewShakeSizeParser(v.requestBodyIV)
 | 
	
		
			
				|  |  | +		sizeParser = NewShakeSizeParser(s.requestBodyIV)
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  	if request.Security.Is(protocol.SecurityType_NONE) {
 | 
	
		
			
				|  |  |  		if request.Option.Has(protocol.RequestOptionChunkStream) {
 | 
	
	
		
			
				|  | @@ -258,7 +258,7 @@ func (v *ServerSession) DecodeRequestBody(request *protocol.RequestHeader, reade
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	if request.Security.Is(protocol.SecurityType_LEGACY) {
 | 
	
		
			
				|  |  | -		aesStream := crypto.NewAesDecryptionStream(v.requestBodyKey, v.requestBodyIV)
 | 
	
		
			
				|  |  | +		aesStream := crypto.NewAesDecryptionStream(s.requestBodyKey, s.requestBodyIV)
 | 
	
		
			
				|  |  |  		cryptionReader := crypto.NewCryptionReader(aesStream, reader)
 | 
	
		
			
				|  |  |  		if request.Option.Has(protocol.RequestOptionChunkStream) {
 | 
	
		
			
				|  |  |  			auth := &crypto.AEADAuthenticator{
 | 
	
	
		
			
				|  | @@ -273,13 +273,13 @@ func (v *ServerSession) DecodeRequestBody(request *protocol.RequestHeader, reade
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	if request.Security.Is(protocol.SecurityType_AES128_GCM) {
 | 
	
		
			
				|  |  | -		block, _ := aes.NewCipher(v.requestBodyKey)
 | 
	
		
			
				|  |  | +		block, _ := aes.NewCipher(s.requestBodyKey)
 | 
	
		
			
				|  |  |  		aead, _ := cipher.NewGCM(block)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  		auth := &crypto.AEADAuthenticator{
 | 
	
		
			
				|  |  |  			AEAD: aead,
 | 
	
		
			
				|  |  |  			NonceGenerator: &ChunkNonceGenerator{
 | 
	
		
			
				|  |  | -				Nonce: append([]byte(nil), v.requestBodyIV...),
 | 
	
		
			
				|  |  | +				Nonce: append([]byte(nil), s.requestBodyIV...),
 | 
	
		
			
				|  |  |  				Size:  aead.NonceSize(),
 | 
	
		
			
				|  |  |  			},
 | 
	
		
			
				|  |  |  			AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
 | 
	
	
		
			
				|  | @@ -288,12 +288,12 @@ func (v *ServerSession) DecodeRequestBody(request *protocol.RequestHeader, reade
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	if request.Security.Is(protocol.SecurityType_CHACHA20_POLY1305) {
 | 
	
		
			
				|  |  | -		aead, _ := chacha20poly1305.New(GenerateChacha20Poly1305Key(v.requestBodyKey))
 | 
	
		
			
				|  |  | +		aead, _ := chacha20poly1305.New(GenerateChacha20Poly1305Key(s.requestBodyKey))
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  		auth := &crypto.AEADAuthenticator{
 | 
	
		
			
				|  |  |  			AEAD: aead,
 | 
	
		
			
				|  |  |  			NonceGenerator: &ChunkNonceGenerator{
 | 
	
		
			
				|  |  | -				Nonce: append([]byte(nil), v.requestBodyIV...),
 | 
	
		
			
				|  |  | +				Nonce: append([]byte(nil), s.requestBodyIV...),
 | 
	
		
			
				|  |  |  				Size:  aead.NonceSize(),
 | 
	
		
			
				|  |  |  			},
 | 
	
		
			
				|  |  |  			AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
 | 
	
	
		
			
				|  | @@ -304,27 +304,27 @@ func (v *ServerSession) DecodeRequestBody(request *protocol.RequestHeader, reade
 | 
	
		
			
				|  |  |  	panic("Unknown security type.")
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -func (v *ServerSession) EncodeResponseHeader(header *protocol.ResponseHeader, writer io.Writer) {
 | 
	
		
			
				|  |  | -	responseBodyKey := md5.Sum(v.requestBodyKey)
 | 
	
		
			
				|  |  | -	responseBodyIV := md5.Sum(v.requestBodyIV)
 | 
	
		
			
				|  |  | -	v.responseBodyKey = responseBodyKey[:]
 | 
	
		
			
				|  |  | -	v.responseBodyIV = responseBodyIV[:]
 | 
	
		
			
				|  |  | +func (s *ServerSession) EncodeResponseHeader(header *protocol.ResponseHeader, writer io.Writer) {
 | 
	
		
			
				|  |  | +	responseBodyKey := md5.Sum(s.requestBodyKey)
 | 
	
		
			
				|  |  | +	responseBodyIV := md5.Sum(s.requestBodyIV)
 | 
	
		
			
				|  |  | +	s.responseBodyKey = responseBodyKey[:]
 | 
	
		
			
				|  |  | +	s.responseBodyIV = responseBodyIV[:]
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	aesStream := crypto.NewAesEncryptionStream(v.responseBodyKey, v.responseBodyIV)
 | 
	
		
			
				|  |  | +	aesStream := crypto.NewAesEncryptionStream(s.responseBodyKey, s.responseBodyIV)
 | 
	
		
			
				|  |  |  	encryptionWriter := crypto.NewCryptionWriter(aesStream, writer)
 | 
	
		
			
				|  |  | -	v.responseWriter = encryptionWriter
 | 
	
		
			
				|  |  | +	s.responseWriter = encryptionWriter
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	encryptionWriter.Write([]byte{v.responseHeader, byte(header.Option)})
 | 
	
		
			
				|  |  | +	encryptionWriter.Write([]byte{s.responseHeader, byte(header.Option)})
 | 
	
		
			
				|  |  |  	err := MarshalCommand(header.Command, encryptionWriter)
 | 
	
		
			
				|  |  |  	if err != nil {
 | 
	
		
			
				|  |  |  		encryptionWriter.Write([]byte{0x00, 0x00})
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -func (v *ServerSession) EncodeResponseBody(request *protocol.RequestHeader, writer io.Writer) buf.Writer {
 | 
	
		
			
				|  |  | +func (s *ServerSession) EncodeResponseBody(request *protocol.RequestHeader, writer io.Writer) buf.Writer {
 | 
	
		
			
				|  |  |  	var sizeParser crypto.ChunkSizeEncoder = crypto.PlainChunkSizeParser{}
 | 
	
		
			
				|  |  |  	if request.Option.Has(protocol.RequestOptionChunkMasking) {
 | 
	
		
			
				|  |  | -		sizeParser = NewShakeSizeParser(v.responseBodyIV)
 | 
	
		
			
				|  |  | +		sizeParser = NewShakeSizeParser(s.responseBodyIV)
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  	if request.Security.Is(protocol.SecurityType_NONE) {
 | 
	
		
			
				|  |  |  		if request.Option.Has(protocol.RequestOptionChunkStream) {
 | 
	
	
		
			
				|  | @@ -350,20 +350,20 @@ func (v *ServerSession) EncodeResponseBody(request *protocol.RequestHeader, writ
 | 
	
		
			
				|  |  |  				NonceGenerator:          crypto.NoOpBytesGenerator{},
 | 
	
		
			
				|  |  |  				AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
 | 
	
		
			
				|  |  |  			}
 | 
	
		
			
				|  |  | -			return crypto.NewAuthenticationWriter(auth, sizeParser, v.responseWriter, request.Command.TransferType())
 | 
	
		
			
				|  |  | +			return crypto.NewAuthenticationWriter(auth, sizeParser, s.responseWriter, request.Command.TransferType())
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -		return buf.NewWriter(v.responseWriter)
 | 
	
		
			
				|  |  | +		return buf.NewWriter(s.responseWriter)
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	if request.Security.Is(protocol.SecurityType_AES128_GCM) {
 | 
	
		
			
				|  |  | -		block, _ := aes.NewCipher(v.responseBodyKey)
 | 
	
		
			
				|  |  | +		block, _ := aes.NewCipher(s.responseBodyKey)
 | 
	
		
			
				|  |  |  		aead, _ := cipher.NewGCM(block)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  		auth := &crypto.AEADAuthenticator{
 | 
	
		
			
				|  |  |  			AEAD: aead,
 | 
	
		
			
				|  |  |  			NonceGenerator: &ChunkNonceGenerator{
 | 
	
		
			
				|  |  | -				Nonce: append([]byte(nil), v.responseBodyIV...),
 | 
	
		
			
				|  |  | +				Nonce: append([]byte(nil), s.responseBodyIV...),
 | 
	
		
			
				|  |  |  				Size:  aead.NonceSize(),
 | 
	
		
			
				|  |  |  			},
 | 
	
		
			
				|  |  |  			AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
 | 
	
	
		
			
				|  | @@ -372,12 +372,12 @@ func (v *ServerSession) EncodeResponseBody(request *protocol.RequestHeader, writ
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	if request.Security.Is(protocol.SecurityType_CHACHA20_POLY1305) {
 | 
	
		
			
				|  |  | -		aead, _ := chacha20poly1305.New(GenerateChacha20Poly1305Key(v.responseBodyKey))
 | 
	
		
			
				|  |  | +		aead, _ := chacha20poly1305.New(GenerateChacha20Poly1305Key(s.responseBodyKey))
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  		auth := &crypto.AEADAuthenticator{
 | 
	
		
			
				|  |  |  			AEAD: aead,
 | 
	
		
			
				|  |  |  			NonceGenerator: &ChunkNonceGenerator{
 | 
	
		
			
				|  |  | -				Nonce: append([]byte(nil), v.responseBodyIV...),
 | 
	
		
			
				|  |  | +				Nonce: append([]byte(nil), s.responseBodyIV...),
 | 
	
		
			
				|  |  |  				Size:  aead.NonceSize(),
 | 
	
		
			
				|  |  |  			},
 | 
	
		
			
				|  |  |  			AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
 |