Add very tentative UPnP NAT traversal

Relates to #230
This commit is contained in:
Matt Joiner 2018-01-25 13:14:20 +11:00
parent 358c6c8649
commit 51b3374015
4 changed files with 49 additions and 5 deletions

View File

@ -303,6 +303,7 @@ func NewClient(cfg *Config) (cl *Client, err error) {
if err != nil {
return
}
go cl.forwardPort()
if cl.tcpListener != nil {
go cl.acceptConnections(cl.tcpListener, false)
}

View File

@ -33,10 +33,11 @@ import (
func TestingConfig() *Config {
return &Config{
ListenAddr: "localhost:0",
NoDHT: true,
DataDir: tempDir(),
DisableTrackers: true,
ListenAddr: "localhost:0",
NoDHT: true,
DataDir: tempDir(),
DisableTrackers: true,
NoDefaultPortForwarding: true,
// Debug: true,
}
}

View File

@ -33,7 +33,8 @@ type Config struct {
// The address to listen for new uTP and TCP bittorrent protocol
// connections. DHT shares a UDP socket with uTP unless configured
// otherwise.
ListenAddr string `long:"listen-addr" value-name:"HOST:PORT"`
ListenAddr string `long:"listen-addr" value-name:"HOST:PORT"`
NoDefaultPortForwarding bool
// Don't announce to trackers. This only leaves DHT to discover peers.
DisableTrackers bool `long:"disable-trackers"`
DisablePEX bool `long:"disable-pex"`

41
portfwd.go Normal file
View File

@ -0,0 +1,41 @@
package torrent
import (
"log"
"time"
flog "github.com/anacrolix/log"
"github.com/syncthing/syncthing/lib/nat"
"github.com/syncthing/syncthing/lib/upnp"
)
func addPortMapping(d nat.Device, proto nat.Protocol, internalPort int, debug bool) {
externalPort, err := d.AddPortMapping(proto, internalPort, internalPort, "anacrolix/torrent", 0)
if err != nil {
log.Printf("error adding %s port mapping: %s", proto, err)
} else if externalPort != internalPort {
log.Printf("external port %d does not match internal port %d in port mapping", externalPort, internalPort)
} else if debug {
log.Printf("forwarded external %s port %d", proto, externalPort)
}
}
func (cl *Client) forwardPort() {
cl.mu.Lock()
defer cl.mu.Unlock()
if cl.config.NoDefaultPortForwarding {
return
}
cl.mu.Unlock()
ds := upnp.Discover(0, 2*time.Second)
cl.mu.Lock()
flog.Default.Emit(flog.Fmsg("discovered %d upnp devices", len(ds)))
port := cl.incomingPeerPort()
cl.mu.Unlock()
for _, d := range ds {
go addPortMapping(d, nat.TCP, port, cl.config.Debug)
go addPortMapping(d, nat.UDP, port, cl.config.Debug)
}
cl.mu.Lock()
}