status-go/vendor/github.com/libp2p/go-libp2p/p2p/host/autonat/client.go

122 lines
3.3 KiB
Go
Raw Normal View History

2019-06-09 07:24:20 +00:00
package autonat
import (
"context"
"fmt"
2022-04-01 16:16:46 +00:00
"time"
pb "github.com/libp2p/go-libp2p/p2p/host/autonat/pb"
2019-06-09 07:24:20 +00:00
"github.com/libp2p/go-libp2p-core/host"
"github.com/libp2p/go-libp2p-core/network"
"github.com/libp2p/go-libp2p-core/peer"
2022-04-01 16:16:46 +00:00
"github.com/libp2p/go-msgio/protoio"
2019-06-09 07:24:20 +00:00
ma "github.com/multiformats/go-multiaddr"
)
// NewAutoNATClient creates a fresh instance of an AutoNATClient
// If addrFunc is nil, h.Addrs will be used
func NewAutoNATClient(h host.Host, addrFunc AddrFunc) Client {
if addrFunc == nil {
addrFunc = h.Addrs
2019-06-09 07:24:20 +00:00
}
return &client{h: h, addrFunc: addrFunc}
2019-06-09 07:24:20 +00:00
}
type client struct {
h host.Host
addrFunc AddrFunc
2019-06-09 07:24:20 +00:00
}
2022-04-01 16:16:46 +00:00
// 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.
2019-06-09 07:24:20 +00:00
func (c *client) DialBack(ctx context.Context, p peer.ID) (ma.Multiaddr, error) {
s, err := c.h.NewStream(ctx, p, AutoNATProto)
if err != nil {
return nil, err
}
2022-04-01 16:16:46 +00:00
if err := s.Scope().SetService(ServiceName); err != nil {
log.Debugf("error attaching stream to autonat service: %s", err)
s.Reset()
return nil, err
}
if err := s.Scope().ReserveMemory(maxMsgSize, network.ReservationPriorityAlways); err != nil {
log.Debugf("error reserving memory for autonat stream: %s", err)
s.Reset()
return nil, err
}
defer s.Scope().ReleaseMemory(maxMsgSize)
s.SetDeadline(time.Now().Add(streamTimeout))
2019-06-09 07:24:20 +00:00
// Might as well just reset the stream. Once we get to this point, we
// don't care about being nice.
defer s.Close()
2019-06-09 07:24:20 +00:00
2022-04-01 16:16:46 +00:00
r := protoio.NewDelimitedReader(s, maxMsgSize)
w := protoio.NewDelimitedWriter(s)
2019-06-09 07:24:20 +00:00
req := newDialMessage(peer.AddrInfo{ID: c.h.ID(), Addrs: c.addrFunc()})
2022-04-01 16:16:46 +00:00
if err := w.WriteMsg(req); err != nil {
2019-06-09 07:24:20 +00:00
s.Reset()
return nil, err
}
var res pb.Message
2022-04-01 16:16:46 +00:00
if err := r.ReadMsg(&res); err != nil {
2019-06-09 07:24:20 +00:00
s.Reset()
return nil, err
}
if res.GetType() != pb.Message_DIAL_RESPONSE {
2022-04-01 16:16:46 +00:00
s.Reset()
return nil, fmt.Errorf("unexpected response: %s", res.GetType().String())
2019-06-09 07:24:20 +00:00
}
status := res.GetDialResponse().GetStatus()
switch status {
case pb.Message_OK:
addr := res.GetDialResponse().GetAddr()
return ma.NewMultiaddrBytes(addr)
default:
return nil, Error{Status: status, Text: res.GetDialResponse().GetStatusText()}
2019-06-09 07:24:20 +00:00
}
}
2022-04-01 16:16:46 +00:00
// Error wraps errors signalled by AutoNAT services
type Error struct {
Status pb.Message_ResponseStatus
Text string
}
func (e Error) Error() string {
2019-06-09 07:24:20 +00:00
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 {
2019-06-09 07:24:20 +00:00
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 {
2019-06-09 07:24:20 +00:00
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)
2019-06-09 07:24:20 +00:00
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)
2019-06-09 07:24:20 +00:00
return ok && ae.IsDialRefused()
}