Skip to content

Commit

Permalink
Merge pull request #101 from huo-ju/master
Browse files Browse the repository at this point in the history
replace the port number for double NAT mapping
  • Loading branch information
willscott authored Feb 22, 2021
2 parents be059b4 + f9b60bf commit 7c1a12b
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 1 deletion.
66 changes: 65 additions & 1 deletion p2p/host/autonat/svc.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package autonat

import (
"bytes"
"context"
"errors"
"math/rand"
Expand Down Expand Up @@ -123,7 +124,12 @@ func (as *autoNATService) handleDial(p peer.ID, obsaddr ma.Multiaddr, mpi *pb.Me
}

if as.config.dialPolicy.skipDial(addr) {
continue
err, newobsaddr := patchObsaddr(addr, obsaddr)
if err == nil {
addr = newobsaddr
} else {
continue
}
}

if ip, err := manet.ToIP(addr); err != nil || !obsHost.Equal(ip) {
Expand Down Expand Up @@ -228,3 +234,61 @@ func (as *autoNATService) background(ctx context.Context) {
}
}
}

// patchObsaddr replaces obsaddr's port number with the port number of `localaddr`
func patchObsaddr(localaddr, obsaddr ma.Multiaddr) (error, ma.Multiaddr) {
if localaddr == nil || obsaddr == nil {
return errors.New("localaddr and obsaddr can't be nil"), nil
}
var rawport []byte
var code int
var newc ma.Component
isValid := false
ma.ForEach(localaddr, func(c ma.Component) bool {
switch c.Protocol().Code {
case ma.P_UDP, ma.P_TCP:
code = c.Protocol().Code
rawport = c.RawValue()
newc = c
return !isValid
case ma.P_IP4, ma.P_IP6:
isValid = true
}
return true
})

if isValid == true && len(rawport) > 0 {
obsbytes := obsaddr.Bytes()
obsoffset := 0
isObsValid := false
isReplaced := false
var buffer bytes.Buffer
ma.ForEach(obsaddr, func(c ma.Component) bool {
switch c.Protocol().Code {
case ma.P_UDP, ma.P_TCP:
if code == c.Protocol().Code && isObsValid == true { //obsaddr has the same type protocol, and we can replace it.
if bytes.Compare(rawport, c.RawValue()) != 0 {
buffer.Write(obsbytes[:obsoffset])
buffer.Write(newc.Bytes())
tail := obsoffset + len(c.Bytes())
if len(obsbytes)-tail > 0 {
buffer.Write(obsbytes[tail:])
}
isReplaced = true
}
return false
}
case ma.P_IP4, ma.P_IP6:
isObsValid = true
}
obsoffset += len(c.Bytes())
return true
})
if isReplaced == true {
newobsaddr, err := ma.NewMultiaddrBytes(buffer.Bytes())
return err, newobsaddr
}
}

return errors.New("only same protocol address can be patched."), nil
}
22 changes: 22 additions & 0 deletions p2p/host/autonat/svc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,3 +207,25 @@ func TestAutoNATServiceStartup(t *testing.T) {
t.Fatalf("autonat should report public, but didn't")
}
}

func TestMultiaddrPatchSuccess(t *testing.T) {
m1, _ := ma.NewMultiaddr("/ip4/192.168.0.10/tcp/64555")
m2, _ := ma.NewMultiaddr("/ip4/72.53.243.114/tcp/19005")
correctm2, _ := ma.NewMultiaddr("/ip4/72.53.243.114/tcp/64555")
err, newm2 := patchObsaddr(m1, m2)
if err != nil {
t.Fatalf("patchObsaddr failed, was %s error %s", m2, err)
}
if newm2.Equal(correctm2) == false {
t.Fatalf("patchObsaddr success, but new obsaddr is %s should be %s", newm2, correctm2)
}
}

func TestMultiaddrPatchError(t *testing.T) {
m1, _ := ma.NewMultiaddr("/ip4/192.168.0.10/tcp/64555")
m2, _ := ma.NewMultiaddr("/ip4/72.53.243.114/udp/19005")
err, newm2 := patchObsaddr(m1, m2)
if err == nil {
t.Fatalf("this address should not be patched, new address: %s", newm2)
}
}

0 comments on commit 7c1a12b

Please sign in to comment.