 5978a0b8f5
			
		
	
	5978a0b8f5
	
	
	
		
			
			- Agent roles and coordination features - Chat API integration testing - New configuration and workspace management 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
		
			
				
	
	
		
			123 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			123 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package autonat
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"fmt"
 | |
| 	"time"
 | |
| 
 | |
| 	"github.com/libp2p/go-libp2p/core/host"
 | |
| 	"github.com/libp2p/go-libp2p/core/network"
 | |
| 	"github.com/libp2p/go-libp2p/core/peer"
 | |
| 	"github.com/libp2p/go-libp2p/p2p/host/autonat/pb"
 | |
| 
 | |
| 	"github.com/libp2p/go-msgio/pbio"
 | |
| )
 | |
| 
 | |
| // NewAutoNATClient creates a fresh instance of an AutoNATClient
 | |
| // If addrFunc is nil, h.Addrs will be used
 | |
| func NewAutoNATClient(h host.Host, addrFunc AddrFunc, mt MetricsTracer) Client {
 | |
| 	if addrFunc == nil {
 | |
| 		addrFunc = h.Addrs
 | |
| 	}
 | |
| 	return &client{h: h, addrFunc: addrFunc, mt: mt}
 | |
| }
 | |
| 
 | |
| type client struct {
 | |
| 	h        host.Host
 | |
| 	addrFunc AddrFunc
 | |
| 	mt       MetricsTracer
 | |
| }
 | |
| 
 | |
| // DialBack asks peer p to dial us back on all addresses returned by the addrFunc.
 | |
| // It blocks until we've received a response from the peer.
 | |
| //
 | |
| // Note: A returned error Message_E_DIAL_ERROR does not imply that the server
 | |
| // actually performed a dial attempt. Servers that run a version < v0.20.0 also
 | |
| // return Message_E_DIAL_ERROR if the dial was skipped due to the dialPolicy.
 | |
| func (c *client) DialBack(ctx context.Context, p peer.ID) error {
 | |
| 	s, err := c.h.NewStream(ctx, p, AutoNATProto)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	if err := s.Scope().SetService(ServiceName); err != nil {
 | |
| 		log.Debugf("error attaching stream to autonat service: %s", err)
 | |
| 		s.Reset()
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	if err := s.Scope().ReserveMemory(maxMsgSize, network.ReservationPriorityAlways); err != nil {
 | |
| 		log.Debugf("error reserving memory for autonat stream: %s", err)
 | |
| 		s.Reset()
 | |
| 		return err
 | |
| 	}
 | |
| 	defer s.Scope().ReleaseMemory(maxMsgSize)
 | |
| 
 | |
| 	s.SetDeadline(time.Now().Add(streamTimeout))
 | |
| 	// Might as well just reset the stream. Once we get to this point, we
 | |
| 	// don't care about being nice.
 | |
| 	defer s.Close()
 | |
| 
 | |
| 	r := pbio.NewDelimitedReader(s, maxMsgSize)
 | |
| 	w := pbio.NewDelimitedWriter(s)
 | |
| 
 | |
| 	req := newDialMessage(peer.AddrInfo{ID: c.h.ID(), Addrs: c.addrFunc()})
 | |
| 	if err := w.WriteMsg(req); err != nil {
 | |
| 		s.Reset()
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	var res pb.Message
 | |
| 	if err := r.ReadMsg(&res); err != nil {
 | |
| 		s.Reset()
 | |
| 		return err
 | |
| 	}
 | |
| 	if res.GetType() != pb.Message_DIAL_RESPONSE {
 | |
| 		s.Reset()
 | |
| 		return fmt.Errorf("unexpected response: %s", res.GetType().String())
 | |
| 	}
 | |
| 
 | |
| 	status := res.GetDialResponse().GetStatus()
 | |
| 	if c.mt != nil {
 | |
| 		c.mt.ReceivedDialResponse(status)
 | |
| 	}
 | |
| 	switch status {
 | |
| 	case pb.Message_OK:
 | |
| 		return nil
 | |
| 	default:
 | |
| 		return Error{Status: status, Text: res.GetDialResponse().GetStatusText()}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // Error wraps errors signalled by AutoNAT services
 | |
| type Error struct {
 | |
| 	Status pb.Message_ResponseStatus
 | |
| 	Text   string
 | |
| }
 | |
| 
 | |
| func (e Error) Error() string {
 | |
| 	return fmt.Sprintf("AutoNAT error: %s (%s)", e.Text, e.Status.String())
 | |
| }
 | |
| 
 | |
| // IsDialError returns true if the error was due to a dial back failure
 | |
| func (e Error) IsDialError() bool {
 | |
| 	return e.Status == pb.Message_E_DIAL_ERROR
 | |
| }
 | |
| 
 | |
| // IsDialRefused returns true if the error was due to a refusal to dial back
 | |
| func (e Error) IsDialRefused() bool {
 | |
| 	return e.Status == pb.Message_E_DIAL_REFUSED
 | |
| }
 | |
| 
 | |
| // IsDialError returns true if the AutoNAT peer signalled an error dialing back
 | |
| func IsDialError(e error) bool {
 | |
| 	ae, ok := e.(Error)
 | |
| 	return ok && ae.IsDialError()
 | |
| }
 | |
| 
 | |
| // IsDialRefused returns true if the AutoNAT peer signalled refusal to dial back
 | |
| func IsDialRefused(e error) bool {
 | |
| 	ae, ok := e.(Error)
 | |
| 	return ok && ae.IsDialRefused()
 | |
| }
 |