package noise

import (
	
	

	
	
	
	
	

	manet 
)

type SessionOption = func(*SessionTransport) error

// Prologue sets a prologue for the Noise session.
// The handshake will only complete successfully if both parties set the same prologue.
// See https://noiseprotocol.org/noise.html#prologue for details.
func ( []byte) SessionOption {
	return func( *SessionTransport) error {
		.prologue = 
		return nil
	}
}

// EarlyDataHandler defines what the application payload is for either the second
// (if responder) or third (if initiator) handshake message, and defines the
// logic for handling the other side's early data. Note the early data in the
// second handshake message is encrypted, but the peer is not authenticated at that point.
type EarlyDataHandler interface {
	// Send for the initiator is called for the client before sending the third
	// handshake message. Defines the application payload for the third message.
	// Send for the responder is called before sending the second handshake message.
	Send(context.Context, net.Conn, peer.ID) *pb.NoiseExtensions
	// Received for the initiator is called when the second handshake message
	// from the responder is received.
	// Received for the responder is called when the third handshake message
	// from the initiator is received.
	Received(context.Context, net.Conn, *pb.NoiseExtensions) error
}

// EarlyData sets the `EarlyDataHandler` for the initiator and responder roles.
// See `EarlyDataHandler` for more details.
func (,  EarlyDataHandler) SessionOption {
	return func( *SessionTransport) error {
		.initiatorEarlyDataHandler = 
		.responderEarlyDataHandler = 
		return nil
	}
}

// DisablePeerIDCheck disables checking the remote peer ID for a noise connection.
// For outbound connections, this is the equivalent of calling `SecureInbound` with an empty
// peer ID. This is susceptible to MITM attacks since we do not verify the identity of the remote
// peer.
func () SessionOption {
	return func( *SessionTransport) error {
		.disablePeerIDCheck = true
		return nil
	}
}

var _ sec.SecureTransport = &SessionTransport{}

// SessionTransport can be used
// to provide per-connection options
type SessionTransport struct {
	t *Transport
	// options
	prologue           []byte
	disablePeerIDCheck bool

	protocolID protocol.ID

	initiatorEarlyDataHandler, responderEarlyDataHandler EarlyDataHandler
}

// SecureInbound runs the Noise handshake as the responder.
// If p is empty, connections from any peer are accepted.
func ( *SessionTransport) ( context.Context,  net.Conn,  peer.ID) (sec.SecureConn, error) {
	 := !.disablePeerIDCheck &&  != ""
	,  := newSecureSession(.t, , , , .prologue, .initiatorEarlyDataHandler, .responderEarlyDataHandler, false, )
	if  != nil {
		,  := manet.FromNetAddr(.RemoteAddr())
		if  == nil {
			canonicallog.LogPeerStatus(100, , , "handshake_failure", "noise", "err", .Error())
		}
	}
	return , 
}

// SecureOutbound runs the Noise handshake as the initiator.
func ( *SessionTransport) ( context.Context,  net.Conn,  peer.ID) (sec.SecureConn, error) {
	return newSecureSession(.t, , , , .prologue, .initiatorEarlyDataHandler, .responderEarlyDataHandler, true, !.disablePeerIDCheck)
}

func ( *SessionTransport) () protocol.ID {
	return .protocolID
}