mirror of https://github.com/libp2p/go-libp2p.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
62 lines
1.4 KiB
62 lines
1.4 KiB
package reuseport
|
|
|
|
import (
|
|
"context"
|
|
|
|
ma "github.com/multiformats/go-multiaddr"
|
|
manet "github.com/multiformats/go-multiaddr/net"
|
|
)
|
|
|
|
// Dial dials the given multiaddr, reusing ports we're currently listening on if
|
|
// possible.
|
|
//
|
|
// Dial attempts to be smart about choosing the source port. For example, If
|
|
// we're dialing a loopback address and we're listening on one or more loopback
|
|
// ports, Dial will randomly choose one of the loopback ports and addresses and
|
|
// reuse it.
|
|
func (t *Transport) Dial(raddr ma.Multiaddr) (manet.Conn, error) {
|
|
return t.DialContext(context.Background(), raddr)
|
|
}
|
|
|
|
// DialContext is like Dial but takes a context.
|
|
func (t *Transport) DialContext(ctx context.Context, raddr ma.Multiaddr) (manet.Conn, error) {
|
|
network, addr, err := manet.DialArgs(raddr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var d *dialer
|
|
switch network {
|
|
case "tcp4":
|
|
d = t.v4.getDialer(network)
|
|
case "tcp6":
|
|
d = t.v6.getDialer(network)
|
|
default:
|
|
return nil, ErrWrongProto
|
|
}
|
|
conn, err := d.DialContext(ctx, network, addr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
maconn, err := manet.WrapNetConn(conn)
|
|
if err != nil {
|
|
conn.Close()
|
|
return nil, err
|
|
}
|
|
return maconn, nil
|
|
}
|
|
|
|
func (n *network) getDialer(network string) *dialer {
|
|
n.mu.RLock()
|
|
d := n.dialer
|
|
n.mu.RUnlock()
|
|
if d == nil {
|
|
n.mu.Lock()
|
|
defer n.mu.Unlock()
|
|
|
|
if n.dialer == nil {
|
|
n.dialer = newDialer(n.listeners)
|
|
}
|
|
d = n.dialer
|
|
}
|
|
return d
|
|
}
|
|
|