diff --git a/core/config.go b/core/config.go index 8af489c..24f24c3 100644 --- a/core/config.go +++ b/core/config.go @@ -58,9 +58,10 @@ func (c *Config) switchApp(app AppConfig, enabled int) { c.Apps[i].Enabled = enabled c.Apps[i].retryNum = 0 c.Apps[i].nextRetryTime = time.Now() - return + break } } + c.save() } func (c *Config) retryApp(peerNode string) { c.mtx.Lock() @@ -76,6 +77,7 @@ func (c *Config) retryApp(peerNode string) { func (c *Config) add(app AppConfig, override bool) { c.mtx.Lock() defer c.mtx.Unlock() + defer c.save() if app.SrcPort == 0 || app.DstPort == 0 { gLog.Println(LvERROR, "invalid app ", app) return @@ -97,17 +99,19 @@ func (c *Config) delete(app AppConfig) { } c.mtx.Lock() defer c.mtx.Unlock() + defer c.save() for i := 0; i < len(c.Apps); i++ { if c.Apps[i].Protocol == app.Protocol && c.Apps[i].SrcPort == app.SrcPort { c.Apps = append(c.Apps[:i], c.Apps[i+1:]...) return } } + } func (c *Config) save() { - c.mtx.Lock() - defer c.mtx.Unlock() + // c.mtx.Lock() + // defer c.mtx.Unlock() // internal call data, _ := json.MarshalIndent(c, "", " ") err := ioutil.WriteFile("config.json", data, 0644) if err != nil { @@ -142,6 +146,7 @@ func (c *Config) load() error { func (c *Config) setToken(token uint64) { c.mtx.Lock() defer c.mtx.Unlock() + defer c.save() if token != 0 { c.Network.Token = token } @@ -149,16 +154,19 @@ func (c *Config) setToken(token uint64) { func (c *Config) setUser(user string) { c.mtx.Lock() defer c.mtx.Unlock() + defer c.save() c.Network.User = user } func (c *Config) setNode(node string) { c.mtx.Lock() defer c.mtx.Unlock() + defer c.save() c.Network.Node = node } func (c *Config) setShareBandwidth(bw int) { c.mtx.Lock() defer c.mtx.Unlock() + defer c.save() c.Network.ShareBandwidth = bw } diff --git a/core/errorcode.go b/core/errorcode.go index 6ff3f03..1bb7480 100644 --- a/core/errorcode.go +++ b/core/errorcode.go @@ -14,6 +14,7 @@ var ( ErrorLogin = errors.New("user or password not correct") ErrNodeTooShort = errors.New("node name too short, it must >=8 charaters") ErrPeerOffline = errors.New("peer offline") + ErrNetwork = errors.New("network error") ErrMsgFormat = errors.New("message format wrong") ErrVersionNotCompatible = errors.New("version not compatible") ErrOverlayConnDisconnect = errors.New("overlay connection is disconnected") diff --git a/core/handlepush.go b/core/handlepush.go index 4b6fa81..a50d972 100644 --- a/core/handlepush.go +++ b/core/handlepush.go @@ -241,7 +241,6 @@ func handlePush(pn *P2PNetwork, subType uint16, msg []byte) error { newConf.Protocol = newApp.Protocol newConf.SrcPort = newApp.SrcPort gConf.add(newConf, false) - gConf.save() // save quickly for the next request reportApplist pn.DeleteApp(oldConf) // DeleteApp may cost some times, execute at the end // autoReconnect will auto AddApp // pn.AddApp(config) @@ -256,7 +255,6 @@ func handlePush(pn *P2PNetwork, subType uint16, msg []byte) error { } gConf.setNode(req.NewName) gConf.setShareBandwidth(req.Bandwidth) - gConf.save() // TODO: hot reload os.Exit(0) case MsgPushSwitchApp: diff --git a/core/holepunch.go b/core/holepunch.go index 5fc0db1..07774cb 100644 --- a/core/holepunch.go +++ b/core/holepunch.go @@ -23,11 +23,11 @@ func handshakeC2C(t *P2PTunnel) (err error) { gLog.Println(LvDEBUG, "handshakeC2C write MsgPunchHandshake error:", err) return err } - ra, head, _, _, err := UDPRead(conn, 5000) + ra, head, _, _, err := UDPRead(conn, SymmetricHandshakeAckTimeout) if err != nil { time.Sleep(time.Millisecond * 200) gLog.Println(LvDEBUG, err, ", return this error when ip was not reachable, retry read") - ra, head, _, _, err = UDPRead(conn, 5000) + ra, head, _, _, err = UDPRead(conn, SymmetricHandshakeAckTimeout) if err != nil { gLog.Println(LvDEBUG, "handshakeC2C read MsgPunchHandshake error:", err) return err @@ -38,7 +38,7 @@ func handshakeC2C(t *P2PTunnel) (err error) { if head.MainType == MsgP2P && head.SubType == MsgPunchHandshake { gLog.Printf(LvDEBUG, "read %d handshake ", t.id) UDPWrite(conn, t.ra, MsgP2P, MsgPunchHandshakeAck, P2PHandshakeReq{ID: t.id}) - _, head, _, _, err = UDPRead(conn, 5000) + _, head, _, _, err = UDPRead(conn, SymmetricHandshakeAckTimeout) if err != nil { gLog.Println(LvDEBUG, "handshakeC2C write MsgPunchHandshakeAck error", err) return err @@ -140,7 +140,7 @@ func handshakeS2C(t *P2PTunnel) error { } defer conn.Close() UDPWrite(conn, t.ra, MsgP2P, MsgPunchHandshake, P2PHandshakeReq{ID: t.id}) - _, head, _, _, err := UDPRead(conn, 10000) + _, head, _, _, err := UDPRead(conn, SymmetricHandshakeAckTimeout) if err != nil { // gLog.Println(LevelDEBUG, "one of the handshake error:", err) return err @@ -155,7 +155,7 @@ func handshakeS2C(t *P2PTunnel) error { if head.MainType == MsgP2P && head.SubType == MsgPunchHandshake { gLog.Printf(LvDEBUG, "handshakeS2C read %d handshake ", t.id) UDPWrite(conn, t.ra, MsgP2P, MsgPunchHandshakeAck, P2PHandshakeReq{ID: t.id}) - _, head, _, _, err = UDPRead(conn, 5000) + _, head, _, _, err = UDPRead(conn, SymmetricHandshakeAckTimeout) if err != nil { gLog.Println(LvDEBUG, "handshakeS2C handshake error") return err diff --git a/core/nat.go b/core/nat.go index 4e93aba..198b545 100644 --- a/core/nat.go +++ b/core/nat.go @@ -34,7 +34,7 @@ func natTCP(serverHost string, serverPort int, localPort int) (publicIP string, return } b := make([]byte, 1000) - conn.SetReadDeadline(time.Now().Add(time.Second * 5)) + conn.SetReadDeadline(time.Now().Add(NatTestTimeout)) n, rderr := conn.Read(b) if rderr != nil { fmt.Printf("Read error: %s\n", rderr) @@ -153,12 +153,12 @@ func publicIPTest(publicIP string, echoPort int) (hasPublicIP int, hasUPNPorNATP } log.Println("PublicIP:", ext) - externalPort, err := nat.AddPortMapping("udp", echoPort, echoPort, "openp2p", 30) + externalPort, err := nat.AddPortMapping("udp", echoPort, echoPort, "openp2p", 604800) // 7 days, upnp will perform failed when os start if err != nil { gLog.Println(LvDEBUG, "could not add udp UPNP port mapping", externalPort) break } else { - nat.AddPortMapping("tcp", echoPort, echoPort, "openp2p", 604800) + nat.AddPortMapping("tcp", echoPort, echoPort, "openp2p", 604800) // 7 days } } gLog.Printf(LvDEBUG, "public ip test start %s:%d", publicIP, echoPort) diff --git a/core/overlay.go b/core/overlay.go index 517951c..c8908f8 100644 --- a/core/overlay.go +++ b/core/overlay.go @@ -116,7 +116,7 @@ func (oConn *overlayConn) Read(reuseBuff []byte) (buff []byte, dataLen int, err err = ErrDeadlineExceeded } } else { // as client - oConn.connUDP.SetReadDeadline(time.Now().Add(5 * time.Second)) + oConn.connUDP.SetReadDeadline(time.Now().Add(UDPReadTimeout)) dataLen, _, err = oConn.connUDP.ReadFrom(reuseBuff) if err == nil { oConn.lastReadUDPTs = time.Now() @@ -126,7 +126,7 @@ func (oConn *overlayConn) Read(reuseBuff []byte) (buff []byte, dataLen int, err return } if oConn.connTCP != nil { - oConn.connTCP.SetReadDeadline(time.Now().Add(time.Second * 5)) + oConn.connTCP.SetReadDeadline(time.Now().Add(UDPReadTimeout)) dataLen, err = oConn.connTCP.Read(reuseBuff) buff = reuseBuff } diff --git a/core/p2papp.go b/core/p2papp.go index 6985195..e7d33c5 100644 --- a/core/p2papp.go +++ b/core/p2papp.go @@ -120,7 +120,7 @@ func (app *p2pApp) listenUDP() error { buffer := make([]byte, 64*1024+PaddingSize) udpID := make([]byte, 8) for { - app.listenerUDP.SetReadDeadline(time.Now().Add(time.Second * 10)) + app.listenerUDP.SetReadDeadline(time.Now().Add(UDPReadTimeout)) len, remoteAddr, err := app.listenerUDP.ReadFrom(buffer) if err != nil { if ne, ok := err.(net.Error); ok && ne.Timeout() { diff --git a/core/p2pnetwork.go b/core/p2pnetwork.go index 276bb6b..b42a215 100644 --- a/core/p2pnetwork.go +++ b/core/p2pnetwork.go @@ -167,7 +167,7 @@ func (pn *P2PNetwork) addRelayTunnel(config AppConfig) (*P2PTunnel, uint64, stri defer gLog.Printf(LvINFO, "addRelayTunnel to %s end", config.PeerNode) // request a relay node or specify manually(TODO) pn.write(MsgRelay, MsgRelayNodeReq, &RelayNodeReq{config.PeerNode}) - head, body := pn.read("", MsgRelay, MsgRelayNodeRsp, time.Second*10) + head, body := pn.read("", MsgRelay, MsgRelayNodeRsp, ClientAPITimeout) if head == nil { return nil, 0, "", errors.New("read MsgRelayNodeRsp error") } @@ -408,6 +408,7 @@ func (pn *P2PNetwork) addDirectTunnel(config AppConfig, tid uint64) (*P2PTunnel, t.config.linkMode = LinkModeTCPPunch t.config.isUnderlayServer = 0 if err = pn.newTunnel(t, tid, isClient); err == nil { + gLog.Println(LvINFO, "TCP4 Punch ok") return t, nil } } @@ -469,7 +470,7 @@ func (pn *P2PNetwork) init() error { } gLog.Println(LvDEBUG, "detect NAT type:", pn.config.natType, " publicIP:", pn.config.publicIP) gatewayURL := fmt.Sprintf("%s:%d", pn.config.ServerHost, pn.config.ServerPort) - uri := "/openp2p/v1/login" + uri := "/api/v1/login" config := tls.Config{InsecureSkipVerify: true} // let's encrypt root cert "DST Root CA X3" expired at 2021/09/29. many old system(windows server 2008 etc) will not trust our cert websocket.DefaultDialer.TLSClientConfig = &config u := url.URL{Scheme: "wss", Host: gatewayURL, Path: uri} @@ -561,7 +562,6 @@ func (pn *P2PNetwork) handleMessage(t int, msg []byte) { gConf.setNode(rsp.Node) pn.config.Node = rsp.Node } - gConf.save() pn.localTs = time.Now().Unix() gLog.Printf(LvINFO, "login ok. user=%s,node=%s,Server ts=%d, local ts=%d", rsp.User, rsp.Node, rsp.Ts, pn.localTs) } @@ -703,6 +703,7 @@ func (pn *P2PNetwork) updateAppHeartbeat(appID uint64) { }) } +// ipv6 will expired need to refresh. func (pn *P2PNetwork) refreshIPv6(force bool) { if !force && !IsIPv6(pn.config.publicIPv6) { // not support ipv6, not refresh return diff --git a/core/p2ptunnel.go b/core/p2ptunnel.go index 43acf9d..6ac1ded 100644 --- a/core/p2ptunnel.go +++ b/core/p2ptunnel.go @@ -36,7 +36,7 @@ func (t *P2PTunnel) requestPeerInfo() error { t.pn.write(MsgQuery, MsgQueryPeerInfoReq, &QueryPeerInfoReq{t.config.peerToken, t.config.PeerNode}) head, body := t.pn.read("", MsgQuery, MsgQueryPeerInfoRsp, time.Second*10) if head == nil { - return ErrPeerOffline + return ErrNetwork // network error, should not be ErrPeerOffline } rsp := QueryPeerInfoRsp{} err := json.Unmarshal(body, &rsp) diff --git a/core/protocol.go b/core/protocol.go index f133de1..184aba0 100644 --- a/core/protocol.go +++ b/core/protocol.go @@ -10,7 +10,7 @@ import ( "time" ) -const OpenP2PVersion = "3.6.11" +const OpenP2PVersion = "3.8.0" const ProductName string = "openp2p" const LeastSupportVersion = "3.0.0" @@ -139,7 +139,7 @@ const ( SymmetricHandshakeNum = 800 // 0.992379 // SymmetricHandshakeNum = 1000 // 0.999510 SymmetricHandshakeInterval = time.Millisecond - SymmetricHandshakeAckTimeout = time.Second * 11 + SymmetricHandshakeAckTimeout = time.Second * 5 PeerAddRelayTimeount = time.Second * 20 CheckActiveTimeout = time.Second * 5 PaddingSize = 16 @@ -148,6 +148,7 @@ const ( RetryInterval = time.Second * 30 PublicIPEchoTimeout = time.Second * 1 NatTestTimeout = time.Second * 5 + UDPReadTimeout = time.Second * 5 ClientAPITimeout = time.Second * 10 MaxDirectTry = 3 ) diff --git a/core/udp.go b/core/udp.go index 991af2c..c2a8281 100644 --- a/core/udp.go +++ b/core/udp.go @@ -18,9 +18,9 @@ func UDPWrite(conn *net.UDPConn, dst net.Addr, mainType uint16, subType uint16, return conn.WriteTo(msg, dst) } -func UDPRead(conn *net.UDPConn, timeout int) (ra net.Addr, head *openP2PHeader, result []byte, len int, err error) { +func UDPRead(conn *net.UDPConn, timeout time.Duration) (ra net.Addr, head *openP2PHeader, result []byte, len int, err error) { if timeout > 0 { - deadline := time.Now().Add(time.Millisecond * time.Duration(timeout)) + deadline := time.Now().Add(timeout) err = conn.SetReadDeadline(deadline) if err != nil { gLog.Println(LvERROR, "SetReadDeadline error") diff --git a/core/underlay_tcp.go b/core/underlay_tcp.go index 18e445b..af9d3e5 100644 --- a/core/underlay_tcp.go +++ b/core/underlay_tcp.go @@ -69,7 +69,7 @@ func (conn *underlayTCP) Close() error { func listenTCP(host string, port int, localPort int, mode string) (*underlayTCP, error) { if mode == LinkModeTCPPunch { - c, err := reuse.DialTimeout("tcp", fmt.Sprintf("0.0.0.0:%d", localPort), fmt.Sprintf("%s:%d", host, port), SymmetricHandshakeAckTimeout) // TODO: timeout + c, err := reuse.DialTimeout("tcp", fmt.Sprintf("0.0.0.0:%d", localPort), fmt.Sprintf("%s:%d", host, port), SymmetricHandshakeAckTimeout) if err != nil { gLog.Println(LvDEBUG, "send tcp punch: ", err) return nil, err