mirror of
https://github.com/status-im/status-go.git
synced 2025-01-10 06:36:32 +00:00
eeca435064
Update vendor Integrate rendezvous into status node Add a test with failover using rendezvous Use multiple servers in client Use discovery V5 by default and test that node can be started with rendezvous discovet Fix linter Update rendezvous client to one with instrumented stream Address feedback Fix test with updated topic limits Apply several suggestions Change log to debug for request errors because we continue execution Remove web3js after rebase Update rendezvous package
144 lines
2.8 KiB
Go
144 lines
2.8 KiB
Go
package nat
|
|
|
|
import (
|
|
"fmt"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/jbenet/goprocess"
|
|
ma "github.com/multiformats/go-multiaddr"
|
|
manet "github.com/multiformats/go-multiaddr-net"
|
|
)
|
|
|
|
// Mapping represents a port mapping in a NAT.
|
|
type Mapping interface {
|
|
// NAT returns the NAT object this Mapping belongs to.
|
|
NAT() *NAT
|
|
|
|
// Protocol returns the protocol of this port mapping. This is either
|
|
// "tcp" or "udp" as no other protocols are likely to be NAT-supported.
|
|
Protocol() string
|
|
|
|
// InternalPort returns the internal device port. Mapping will continue to
|
|
// try to map InternalPort() to an external facing port.
|
|
InternalPort() int
|
|
|
|
// ExternalPort returns the external facing port. If the mapping is not
|
|
// established, port will be 0
|
|
ExternalPort() int
|
|
|
|
// InternalAddr returns the internal address.
|
|
InternalAddr() ma.Multiaddr
|
|
|
|
// ExternalAddr returns the external facing address. If the mapping is not
|
|
// established, addr will be nil, and and ErrNoMapping will be returned.
|
|
ExternalAddr() (addr ma.Multiaddr, err error)
|
|
|
|
// Close closes the port mapping
|
|
Close() error
|
|
}
|
|
|
|
// keeps republishing
|
|
type mapping struct {
|
|
sync.Mutex // guards all fields
|
|
|
|
nat *NAT
|
|
proto string
|
|
intport int
|
|
extport int
|
|
permanent bool
|
|
intaddr ma.Multiaddr
|
|
proc goprocess.Process
|
|
|
|
comment string
|
|
|
|
cached ma.Multiaddr
|
|
cacheTime time.Time
|
|
cacheLk sync.Mutex
|
|
}
|
|
|
|
func (m *mapping) NAT() *NAT {
|
|
m.Lock()
|
|
defer m.Unlock()
|
|
return m.nat
|
|
}
|
|
|
|
func (m *mapping) Protocol() string {
|
|
m.Lock()
|
|
defer m.Unlock()
|
|
return m.proto
|
|
}
|
|
|
|
func (m *mapping) InternalPort() int {
|
|
m.Lock()
|
|
defer m.Unlock()
|
|
return m.intport
|
|
}
|
|
|
|
func (m *mapping) ExternalPort() int {
|
|
m.Lock()
|
|
defer m.Unlock()
|
|
return m.extport
|
|
}
|
|
|
|
func (m *mapping) setExternalPort(p int) {
|
|
m.Lock()
|
|
defer m.Unlock()
|
|
m.extport = p
|
|
}
|
|
|
|
func (m *mapping) InternalAddr() ma.Multiaddr {
|
|
m.Lock()
|
|
defer m.Unlock()
|
|
return m.intaddr
|
|
}
|
|
|
|
func (m *mapping) ExternalAddr() (ma.Multiaddr, error) {
|
|
m.cacheLk.Lock()
|
|
ctime := m.cacheTime
|
|
cval := m.cached
|
|
m.cacheLk.Unlock()
|
|
if time.Since(ctime) < CacheTime {
|
|
return cval, nil
|
|
}
|
|
|
|
if m.ExternalPort() == 0 { // dont even try right now.
|
|
return nil, ErrNoMapping
|
|
}
|
|
|
|
m.nat.natmu.Lock()
|
|
ip, err := m.nat.nat.GetExternalAddress()
|
|
m.nat.natmu.Unlock()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
ipmaddr, err := manet.FromIP(ip)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error parsing ip")
|
|
}
|
|
|
|
// call m.ExternalPort again, as mapping may have changed under our feet. (tocttou)
|
|
extport := m.ExternalPort()
|
|
if extport == 0 {
|
|
return nil, ErrNoMapping
|
|
}
|
|
|
|
tcp, err := ma.NewMultiaddr(fmt.Sprintf("/%s/%d", m.Protocol(), extport))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
maddr2 := ipmaddr.Encapsulate(tcp)
|
|
|
|
m.cacheLk.Lock()
|
|
m.cached = maddr2
|
|
m.cacheTime = time.Now()
|
|
m.cacheLk.Unlock()
|
|
return maddr2, nil
|
|
}
|
|
|
|
func (m *mapping) Close() error {
|
|
return m.proc.Close()
|
|
}
|