fix system service bug and docker run path and nat detect bug
This commit is contained in:
+91
-72
@@ -12,50 +12,55 @@ import (
|
||||
reuse "github.com/openp2p-cn/go-reuseport"
|
||||
)
|
||||
|
||||
func natTCP(serverHost string, serverPort int) (publicIP string, publicPort int, localPort int) {
|
||||
// dialer := &net.Dialer{
|
||||
// LocalAddr: &net.TCPAddr{
|
||||
// IP: net.ParseIP("0.0.0.0"),
|
||||
// Port: localPort,
|
||||
// },
|
||||
// }
|
||||
conn, err := reuse.DialTimeout("tcp4", fmt.Sprintf("%s:%d", "0.0.0.0", 0), fmt.Sprintf("%s:%d", serverHost, serverPort), NatTestTimeout)
|
||||
// conn, err := net.Dial("tcp4", fmt.Sprintf("%s:%d", serverHost, serverPort))
|
||||
// log.Println(LvINFO, conn.LocalAddr())
|
||||
func natDetectTCP(serverHost string, serverPort int, lp int) (publicIP string, publicPort int, localPort int, err error) {
|
||||
gLog.d("natDetectTCP start")
|
||||
defer gLog.d("natDetectTCP end")
|
||||
conn, err := reuse.DialTimeout("tcp4", fmt.Sprintf("0.0.0.0:%d", lp), fmt.Sprintf("%s:%d", serverHost, serverPort), NatDetectTimeout)
|
||||
if err != nil {
|
||||
fmt.Printf("Dial tcp4 %s:%d error:%s", serverHost, serverPort, err)
|
||||
err = fmt.Errorf("dial tcp4 %s:%d error: %w", serverHost, serverPort, err)
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
localPort, _ = strconv.Atoi(strings.Split(conn.LocalAddr().String(), ":")[1])
|
||||
_, wrerr := conn.Write([]byte("1"))
|
||||
if wrerr != nil {
|
||||
fmt.Printf("Write error: %s\n", wrerr)
|
||||
return
|
||||
}
|
||||
b := make([]byte, 1000)
|
||||
conn.SetReadDeadline(time.Now().Add(NatTestTimeout))
|
||||
n, rderr := conn.Read(b)
|
||||
if rderr != nil {
|
||||
fmt.Printf("Read error: %s\n", rderr)
|
||||
return
|
||||
}
|
||||
arr := strings.Split(string(b[:n]), ":")
|
||||
if len(arr) < 2 {
|
||||
return
|
||||
}
|
||||
publicIP = arr[0]
|
||||
port, _ := strconv.ParseInt(arr[1], 10, 32)
|
||||
publicPort = int(port)
|
||||
return
|
||||
|
||||
localAddr := conn.LocalAddr().(*net.TCPAddr)
|
||||
localPort = localAddr.Port
|
||||
|
||||
if _, err = conn.Write([]byte("1")); err != nil {
|
||||
err = fmt.Errorf("write error: %w", err)
|
||||
return
|
||||
}
|
||||
|
||||
b := make([]byte, 1000)
|
||||
conn.SetReadDeadline(time.Now().Add(NatDetectTimeout))
|
||||
n, err := conn.Read(b)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("read error: %w", err)
|
||||
return
|
||||
}
|
||||
|
||||
response := strings.Split(string(b[:n]), ":")
|
||||
if len(response) < 2 {
|
||||
err = fmt.Errorf("invalid response format: %s", string(b[:n]))
|
||||
return
|
||||
}
|
||||
|
||||
publicIP = response[0]
|
||||
port, err := strconv.Atoi(response[1])
|
||||
if err != nil {
|
||||
err = fmt.Errorf("invalid port format: %w", err)
|
||||
return
|
||||
}
|
||||
publicPort = port
|
||||
|
||||
return
|
||||
}
|
||||
func natTest(serverHost string, serverPort int, localPort int) (publicIP string, publicPort int, err error) {
|
||||
gLog.Println(LvDEBUG, "natTest start")
|
||||
defer gLog.Println(LvDEBUG, "natTest end")
|
||||
|
||||
func natDetectUDP(serverHost string, serverPort int, localPort int) (publicIP string, publicPort int, err error) {
|
||||
gLog.d("natDetectUDP start")
|
||||
defer gLog.d("natDetectUDP end")
|
||||
conn, err := net.ListenPacket("udp", fmt.Sprintf(":%d", localPort))
|
||||
if err != nil {
|
||||
gLog.Println(LvERROR, "natTest listen udp error:", err)
|
||||
gLog.e("natDetectUDP listen udp error:%s", err)
|
||||
return "", 0, err
|
||||
}
|
||||
defer conn.Close()
|
||||
@@ -71,7 +76,7 @@ func natTest(serverHost string, serverPort int, localPort int) (publicIP string,
|
||||
if err != nil {
|
||||
return "", 0, err
|
||||
}
|
||||
deadline := time.Now().Add(NatTestTimeout)
|
||||
deadline := time.Now().Add(NatDetectTimeout)
|
||||
err = conn.SetReadDeadline(deadline)
|
||||
if err != nil {
|
||||
return "", 0, err
|
||||
@@ -79,7 +84,7 @@ func natTest(serverHost string, serverPort int, localPort int) (publicIP string,
|
||||
buffer := make([]byte, 1024)
|
||||
nRead, _, err := conn.ReadFrom(buffer)
|
||||
if err != nil {
|
||||
gLog.Println(LvERROR, "NAT detect error:", err)
|
||||
gLog.e("NAT detect error:%s", err)
|
||||
return "", 0, err
|
||||
}
|
||||
natRsp := NatDetectRsp{}
|
||||
@@ -88,19 +93,27 @@ func natTest(serverHost string, serverPort int, localPort int) (publicIP string,
|
||||
return natRsp.IP, natRsp.Port, nil
|
||||
}
|
||||
|
||||
func getNATType(host string, udp1 int, udp2 int) (publicIP string, NATType int, err error) {
|
||||
func getNATType(host string, detectPort1 int, detectPort2 int) (publicIP string, NATType int, err error) {
|
||||
setUPNP(gConf.Network.PublicIPPort)
|
||||
// the random local port may be used by other.
|
||||
localPort := int(rand.Uint32()%15000 + 50000)
|
||||
|
||||
ip1, port1, err := natTest(host, udp1, localPort)
|
||||
ip1, port1, err := natDetectUDP(host, detectPort1, localPort)
|
||||
if err != nil {
|
||||
return "", 0, err
|
||||
// udp block try tcp
|
||||
gLog.w("udp block, try tcp nat detect")
|
||||
if ip1, port1, _, err = natDetectTCP(host, detectPort1, localPort); err != nil {
|
||||
return "", 0, err
|
||||
}
|
||||
}
|
||||
_, port2, err := natTest(host, udp2, localPort) // 2rd nat test not need testing publicip
|
||||
gLog.Printf(LvDEBUG, "local port:%d nat port:%d", localPort, port2)
|
||||
_, port2, err := natDetectUDP(host, detectPort2, localPort) // 2rd nat test not need testing publicip
|
||||
if err != nil {
|
||||
return "", 0, err
|
||||
gLog.w("udp block, try tcp nat detect")
|
||||
if _, port2, _, err = natDetectTCP(host, detectPort2, localPort); err != nil {
|
||||
return "", 0, err
|
||||
}
|
||||
}
|
||||
gLog.d("local port:%d nat port:%d", localPort, port2)
|
||||
natType := NATSymmetric
|
||||
if port1 == port2 {
|
||||
natType = NATCone
|
||||
@@ -113,11 +126,11 @@ func publicIPTest(publicIP string, echoPort int) (hasPublicIP int, hasUPNPorNATP
|
||||
return
|
||||
}
|
||||
var echoConn *net.UDPConn
|
||||
gLog.Println(LvDEBUG, "echo server start")
|
||||
gLog.d("echo server start")
|
||||
var err error
|
||||
echoConn, err = net.ListenUDP("udp", &net.UDPAddr{IP: net.IPv4zero, Port: echoPort})
|
||||
if err != nil { // listen error
|
||||
gLog.Println(LvERROR, "echo server listen error:", err)
|
||||
gLog.e("echo server listen error:%s", err)
|
||||
return
|
||||
}
|
||||
defer echoConn.Close()
|
||||
@@ -125,34 +138,18 @@ func publicIPTest(publicIP string, echoPort int) (hasPublicIP int, hasUPNPorNATP
|
||||
for i := 0; i < 2; i++ {
|
||||
if i == 1 {
|
||||
// test upnp or nat-pmp
|
||||
gLog.Println(LvDEBUG, "upnp test start")
|
||||
nat, err := Discover()
|
||||
if err != nil || nat == nil {
|
||||
gLog.Println(LvDEBUG, "could not perform UPNP discover:", err)
|
||||
break
|
||||
}
|
||||
ext, err := nat.GetExternalAddress()
|
||||
if err != nil {
|
||||
gLog.Println(LvDEBUG, "could not perform UPNP external address:", err)
|
||||
break
|
||||
}
|
||||
gLog.Println(LvINFO, "PublicIP:", ext)
|
||||
|
||||
externalPort, err := nat.AddPortMapping("udp", echoPort, echoPort, "openp2p", 30) // 30 seconds fot upnp testing
|
||||
if err != nil {
|
||||
gLog.Println(LvDEBUG, "could not add udp UPNP port mapping", externalPort)
|
||||
break
|
||||
} else {
|
||||
nat.AddPortMapping("tcp", echoPort, echoPort, "openp2p", 604800) // 7 days for tcp connection
|
||||
}
|
||||
gLog.d("upnp test start")
|
||||
// 7 days for udp connection
|
||||
// 7 days for tcp connection
|
||||
setUPNP(echoPort)
|
||||
}
|
||||
gLog.Printf(LvDEBUG, "public ip test start %s:%d", publicIP, echoPort)
|
||||
gLog.d("public ip test start %s:%d", publicIP, echoPort)
|
||||
conn, err := net.ListenUDP("udp", nil)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
defer conn.Close()
|
||||
dst, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", gConf.Network.ServerHost, gConf.Network.ServerPort))
|
||||
dst, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", gConf.Network.ServerIP, gConf.Network.ServerPort))
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
@@ -169,21 +166,21 @@ func publicIPTest(publicIP string, echoPort int) (hasPublicIP int, hasUPNPorNATP
|
||||
echoConn.SetReadDeadline(time.Now().Add(PublicIPEchoTimeout))
|
||||
nRead, _, err := echoConn.ReadFromUDP(buf)
|
||||
if err != nil {
|
||||
gLog.Println(LvDEBUG, "PublicIP detect error:", err)
|
||||
gLog.d("publicIPTest echoConn read timeout:%s", err)
|
||||
continue
|
||||
}
|
||||
natRsp := NatDetectRsp{}
|
||||
err = json.Unmarshal(buf[openP2PHeaderSize:nRead], &natRsp)
|
||||
if err != nil {
|
||||
gLog.Println(LvDEBUG, "PublicIP detect error:", err)
|
||||
gLog.d("publicIPTest Unmarshal error:%s", err)
|
||||
continue
|
||||
}
|
||||
if natRsp.Port == echoPort {
|
||||
if i == 1 {
|
||||
gLog.Println(LvDEBUG, "UPNP or NAT-PMP:YES")
|
||||
gLog.d("UPNP or NAT-PMP:YES")
|
||||
hasUPNPorNATPMP = 1
|
||||
} else {
|
||||
gLog.Println(LvDEBUG, "public ip:YES")
|
||||
gLog.d("public ip:YES")
|
||||
hasPublicIP = 1
|
||||
}
|
||||
break
|
||||
@@ -191,3 +188,25 @@ func publicIPTest(publicIP string, echoPort int) (hasPublicIP int, hasUPNPorNATP
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func setUPNP(echoPort int) {
|
||||
nat, err := Discover()
|
||||
if err != nil || nat == nil {
|
||||
gLog.d("could not perform UPNP discover:%s", err)
|
||||
return
|
||||
}
|
||||
ext, err := nat.GetExternalAddress()
|
||||
if err != nil {
|
||||
gLog.d("could not perform UPNP external address:%s", err)
|
||||
return
|
||||
}
|
||||
gLog.i("PublicIP:%v", ext)
|
||||
|
||||
externalPort, err := nat.AddPortMapping("udp", echoPort, echoPort, "openp2p", 604800)
|
||||
if err != nil {
|
||||
gLog.d("could not add udp UPNP port mapping %d", externalPort)
|
||||
return
|
||||
} else {
|
||||
nat.AddPortMapping("tcp", echoPort, echoPort, "openp2p", 604800)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user