mirror of https://github.com/poanetwork/gecko.git
NAT test
This commit is contained in:
parent
aaa00b3488
commit
96cfcc0b5b
16
nat/nat.go
16
nat/nat.go
|
@ -22,7 +22,10 @@ type NATRouter interface {
|
|||
|
||||
func GetNATRouter() NATRouter {
|
||||
//TODO other protocol
|
||||
return getUPnPRouter()
|
||||
if r := getUPnPRouter(); r != nil {
|
||||
return r
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Router struct {
|
||||
|
@ -61,13 +64,13 @@ func (dev *Router) mapPort(protocol string, intport, extport uint16, desc string
|
|||
}()
|
||||
|
||||
if err := dev.r.MapPort(protocol, intport, extport, desc, mapTimeout); err != nil {
|
||||
dev.log.Warn("Map port failed. Protocol %s Internal %d External %d. %s",
|
||||
dev.log.Error("Map port failed. Protocol %s Internal %d External %d. %s",
|
||||
protocol, intport, extport, err)
|
||||
dev.errLock.Lock()
|
||||
dev.errs.Add(err)
|
||||
dev.errLock.Unlock()
|
||||
} else {
|
||||
dev.log.Info("Mapped Protocol %s Internal %d External %d. %s", protocol,
|
||||
dev.log.Info("Mapped Protocol %s Internal %d External %d.", protocol,
|
||||
intport, extport)
|
||||
}
|
||||
|
||||
|
@ -75,14 +78,16 @@ func (dev *Router) mapPort(protocol string, intport, extport uint16, desc string
|
|||
select {
|
||||
case <-updater.C:
|
||||
if err := dev.r.MapPort(protocol, intport, extport, desc, mapTimeout); err != nil {
|
||||
dev.log.Warn("Renew port mapping failed. Protocol %s Internal %d External %d. %s",
|
||||
dev.log.Error("Renew port mapping failed. Protocol %s Internal %d External %d. %s",
|
||||
protocol, intport, extport, err)
|
||||
} else {
|
||||
dev.log.Info("Renew port mapping Protocol %s Internal %d External %d. %s", protocol,
|
||||
dev.log.Info("Renew port mapping Protocol %s Internal %d External %d.", protocol,
|
||||
intport, extport)
|
||||
}
|
||||
|
||||
updater.Reset(mapUpdate)
|
||||
case _, _ = <-dev.closer:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -90,5 +95,6 @@ func (dev *Router) mapPort(protocol string, intport, extport uint16, desc string
|
|||
func (dev *Router) UnmapAllPorts() error {
|
||||
close(dev.closer)
|
||||
dev.wg.Wait()
|
||||
dev.log.Info("Unmapped all ports")
|
||||
return dev.errs.Err
|
||||
}
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
package nat
|
||||
|
||||
// go test -run 'HTTP'
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ava-labs/gecko/utils/logging"
|
||||
)
|
||||
|
||||
const (
|
||||
externalPort = 9876
|
||||
localPort = 8080
|
||||
)
|
||||
|
||||
func TestHTTP(t *testing.T) {
|
||||
config, err := logging.DefaultConfig()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
factory := logging.NewFactory(config)
|
||||
defer factory.Close()
|
||||
|
||||
log, err := factory.Make()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer log.Stop()
|
||||
defer log.StopOnPanic()
|
||||
|
||||
log.Info("Logger Initialized")
|
||||
|
||||
n := GetNATRouter()
|
||||
if n == nil {
|
||||
log.Error("Unable to get UPnP Device")
|
||||
return
|
||||
}
|
||||
|
||||
ip, err := n.ExternalIP()
|
||||
if err != nil {
|
||||
log.Error("Unable to get external IP: %v", err)
|
||||
return
|
||||
}
|
||||
log.Info("External Address %s:%d", ip.String(), externalPort)
|
||||
|
||||
r := NewRouter(log, n)
|
||||
defer r.UnmapAllPorts()
|
||||
|
||||
r.Map("TCP", localPort, externalPort, "AVA UPnP Test")
|
||||
|
||||
log.Info("Starting HTTP Service")
|
||||
server := &http.Server{Addr: ":" + strconv.Itoa(localPort)}
|
||||
http.HandleFunc("/", hello)
|
||||
go func() {
|
||||
server.ListenAndServe()
|
||||
}()
|
||||
|
||||
stop := make(chan os.Signal, 1)
|
||||
signal.Notify(stop, os.Interrupt)
|
||||
|
||||
<-stop
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
server.Shutdown(ctx)
|
||||
}
|
||||
|
||||
func hello(w http.ResponseWriter, req *http.Request) {
|
||||
fmt.Fprintf(w, "AVA UPnP Test\n")
|
||||
}
|
51
nat/upnp.go
51
nat/upnp.go
|
@ -10,7 +10,10 @@ import (
|
|||
"github.com/huin/goupnp/dcps/internetgateway2"
|
||||
)
|
||||
|
||||
const soapRequestTimeout = 3 * time.Second
|
||||
const (
|
||||
soapRequestTimeout = 3 * time.Second
|
||||
mapRetry = 20
|
||||
)
|
||||
|
||||
// upnpClient is the interface used by goupnp for their client implementations
|
||||
type upnpClient interface {
|
||||
|
@ -79,7 +82,6 @@ func (r *upnpRouter) localIP() (net.IP, error) {
|
|||
}
|
||||
}
|
||||
return nil, fmt.Errorf("couldn't find the local address in the same network as %s", deviceIP)
|
||||
|
||||
}
|
||||
|
||||
func (r *upnpRouter) ExternalIP() (net.IP, error) {
|
||||
|
@ -95,14 +97,26 @@ func (r *upnpRouter) ExternalIP() (net.IP, error) {
|
|||
return ip, nil
|
||||
}
|
||||
|
||||
func (r *upnpRouter) MapPort(protocol string, intport, extport uint16, desc string, duration time.Duration) error {
|
||||
func (r *upnpRouter) MapPort(protocol string, intport, extport uint16,
|
||||
desc string, duration time.Duration) error {
|
||||
ip, err := r.localIP()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
lifetime := uint32(duration / time.Second)
|
||||
r.UnmapPort(protocol, extport)
|
||||
return r.client.AddPortMapping("", extport, protocol, intport, ip.String(), true, desc, lifetime)
|
||||
|
||||
for i := 0; i < mapRetry; i++ {
|
||||
externalPort := extport + uint16(i)
|
||||
err = r.client.AddPortMapping("", externalPort, protocol, intport,
|
||||
ip.String(), true, desc, lifetime)
|
||||
if err == nil {
|
||||
fmt.Printf("Mapped external port %d to local %s:%d\n", externalPort,
|
||||
ip.String(), intport)
|
||||
return nil
|
||||
}
|
||||
fmt.Printf("Unable to map port, retry with port %d\n", externalPort+1)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *upnpRouter) UnmapPort(protocol string, extport uint16) error {
|
||||
|
@ -184,17 +198,24 @@ func discover(target string) *upnpRouter {
|
|||
}
|
||||
|
||||
func getUPnPRouter() *upnpRouter {
|
||||
r := discover(internetgateway1.URN_WANConnectionDevice_1)
|
||||
if r != nil {
|
||||
return r
|
||||
targets := []string{
|
||||
internetgateway1.URN_WANConnectionDevice_1,
|
||||
internetgateway2.URN_WANConnectionDevice_2,
|
||||
}
|
||||
return discover(internetgateway2.URN_WANConnectionDevice_2)
|
||||
}
|
||||
|
||||
func GetUPnP() *upnpRouter {
|
||||
r := discover(internetgateway1.URN_WANConnectionDevice_1)
|
||||
if r != nil {
|
||||
return r
|
||||
routers := make(chan *upnpRouter, len(targets))
|
||||
|
||||
for _, urn := range targets {
|
||||
go func(urn string) {
|
||||
routers <- discover(urn)
|
||||
}(urn)
|
||||
}
|
||||
return discover(internetgateway2.URN_WANConnectionDevice_2)
|
||||
|
||||
for i := 0; i < len(targets); i++ {
|
||||
if r := <-routers; r != nil {
|
||||
return r
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue