package client

import (
	
	
	

	
	
	
	

	logging 
)

var log = logging.Logger("p2p-circuit")

// Client implements the client-side of the p2p-circuit/v2 protocol:
// - it implements dialing through v2 relays
// - it listens for incoming connections through v2 relays.
//
// For backwards compatibility with v1 relays and older nodes, the client will
// also accept relay connections through v1 relays and fallback dial peers using p2p-circuit/v1.
// This allows us to use the v2 code as drop in replacement for v1 in a host without breaking
// existing code and interoperability with older nodes.
type Client struct {
	ctx       context.Context
	ctxCancel context.CancelFunc
	host      host.Host
	upgrader  transport.Upgrader

	incoming chan accept

	mx          sync.Mutex
	activeDials map[peer.ID]*completion
	hopCount    map[peer.ID]int
}

var _ io.Closer = &Client{}
var _ transport.Transport = &Client{}

type accept struct {
	conn          *Conn
	writeResponse func() error
}

type completion struct {
	ch    chan struct{}
	relay peer.ID
	err   error
}

// New constructs a new p2p-circuit/v2 client, attached to the given host and using the given
// upgrader to perform connection upgrades.
func ( host.Host,  transport.Upgrader) (*Client, error) {
	 := &Client{
		host:        ,
		upgrader:    ,
		incoming:    make(chan accept),
		activeDials: make(map[peer.ID]*completion),
		hopCount:    make(map[peer.ID]int),
	}
	.ctx, .ctxCancel = context.WithCancel(context.Background())
	return , nil
}

// Start registers the circuit (client) protocol stream handlers
func ( *Client) () {
	.host.SetStreamHandler(proto.ProtoIDv2Stop, .handleStreamV2)
}

func ( *Client) () error {
	.ctxCancel()
	.host.RemoveStreamHandler(proto.ProtoIDv2Stop)
	return nil
}