package exchange

import (
	
	

	

	
	
	
	
	
)

type unencryptedWriter struct {
	clock   clock.Clock
	conn    transport.Conn
	timeout time.Duration
	input   proto.MessageType
	output  proto.MessageType
}

func ( unencryptedWriter) ( context.Context,  *bin.Buffer,  bin.Encoder) error {
	.Reset()

	if  := .Encode();  != nil {
		return 
	}
	 := proto.UnencryptedMessage{
		MessageID:   int64(proto.NewMessageID(.clock.Now(), .output)),
		MessageData: .Copy(),
	}
	.Reset()
	if  := .Encode();  != nil {
		return 
	}

	,  := context.WithTimeout(, .timeout)
	defer ()
	return .conn.Send(, )
}

func ( unencryptedWriter) ( context.Context,  *bin.Buffer) error {
	,  := context.WithTimeout(, .timeout)
	defer ()

	if  := .conn.Recv(, );  != nil {
		return 
	}

	return nil
}

func ( unencryptedWriter) () bool {
	return .output == proto.MessageFromClient
}

func ( unencryptedWriter) ( context.Context,  *bin.Buffer,  bin.Decoder) error {
	.Reset()

	for {
		if  := .tryRead(, );  != nil {
			var  *codec.ProtocolErr
			if .isClient() &&
				errors.As(, &) &&
				.Code == codec.CodeAuthKeyNotFound {
				continue
			}
			return 
		}

		break
	}

	// Server side: a frame whose leading auth_key_id is non-zero is an encrypted
	// message, not an unencrypted key-exchange message. The peer is reusing an
	// already established auth key rather than performing key exchange. Surface
	// the raw frame so the caller can resolve the key and handle it as a normal
	// encrypted message, instead of failing the exchange (which would drop the
	// connection or reply -404 and make clients discard a still-valid key).
	if !.isClient() {
		var  [8]byte
		if  := .PeekN([:], len());  == nil &&  != ([8]byte{}) {
			return &UnexpectedEncryptedError{
				AuthKeyID: ,
				Frame:     append([]byte(nil), .Buf...),
			}
		}
	}

	var  proto.UnencryptedMessage
	if  := .Decode();  != nil {
		return 
	}
	if  := .checkMsgID(.MessageID);  != nil {
		return 
	}
	.ResetTo(.MessageData)

	return .Decode()
}

func ( unencryptedWriter) ( int64) error {
	if proto.MessageID().Type() != .input {
		return errors.New("bad msg type")
	}
	return nil
}