package pnet

import (
	
	
	
	
	

	

	
	pool 
)

// we are using buffer pool as user needs their slice back
// so we can't do XOR cripter in place
var (
	errShortNonce  = pnet.NewError("could not read full nonce")
	errInsecureNil = pnet.NewError("insecure is nil")
	errPSKNil      = pnet.NewError("pre-shread key is nil")
)

type pskConn struct {
	net.Conn
	psk *[32]byte

	writeS20 cipher.Stream
	readS20  cipher.Stream
}

func ( *pskConn) ( []byte) (int, error) {
	if .readS20 == nil {
		 := make([]byte, 24)
		,  := io.ReadFull(.Conn, )
		if  != nil {
			return 0, fmt.Errorf("%w: %w", errShortNonce, )
		}
		.readS20 = salsa20.New(.psk, )
	}

	,  := .Conn.Read() // read to in
	if  > 0 {
		.readS20.XORKeyStream([:], [:]) // decrypt to out buffer
	}
	return , 
}

func ( *pskConn) ( []byte) (int, error) {
	if .writeS20 == nil {
		 := make([]byte, 24)
		,  := rand.Read()
		if  != nil {
			return 0, 
		}
		_,  = .Conn.Write()
		if  != nil {
			return 0, 
		}

		.writeS20 = salsa20.New(.psk, )
	}
	 := pool.Get(len())
	defer pool.Put()

	.writeS20.XORKeyStream(, ) // encrypt

	return .Conn.Write() // send
}

var _ net.Conn = (*pskConn)(nil)

func newPSKConn( *[32]byte,  net.Conn) (net.Conn, error) {
	if  == nil {
		return nil, errInsecureNil
	}
	if  == nil {
		return nil, errPSKNil
	}
	return &pskConn{
		Conn: ,
		psk:  ,
	}, nil
}