refactor update and fix token loss bug
This commit is contained in:
+114
-3
@@ -2,18 +2,22 @@ package openp2p
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"crypto/aes"
|
"crypto/aes"
|
||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"math"
|
||||||
"math/big"
|
"math/big"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -128,19 +132,19 @@ func netInfo() *NetInfo {
|
|||||||
client := &http.Client{Transport: tr, Timeout: time.Second * 10}
|
client := &http.Client{Transport: tr, Timeout: time.Second * 10}
|
||||||
r, err := client.Get("https://ifconfig.co/json")
|
r, err := client.Get("https://ifconfig.co/json")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
gLog.Println(LvDEBUG, "netInfo error:", err)
|
gLog.d("netInfo error:%s", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
defer r.Body.Close()
|
defer r.Body.Close()
|
||||||
buf := make([]byte, 1024*64)
|
buf := make([]byte, 1024*64)
|
||||||
n, err := r.Body.Read(buf)
|
n, err := r.Body.Read(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
gLog.Println(LvDEBUG, "netInfo error:", err)
|
gLog.d("netInfo error:%s", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
rsp := NetInfo{}
|
rsp := NetInfo{}
|
||||||
if err = json.Unmarshal(buf[:n], &rsp); err != nil {
|
if err = json.Unmarshal(buf[:n], &rsp); err != nil {
|
||||||
gLog.Printf(LvERROR, "wrong NetInfo:%s", err)
|
gLog.e("wrong NetInfo:%s", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return &rsp
|
return &rsp
|
||||||
@@ -280,3 +284,110 @@ func calculateChecksum(data []byte) uint16 {
|
|||||||
|
|
||||||
return uint16(^sum)
|
return uint16(^sum)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func min(nums ...int32) int32 {
|
||||||
|
if len(nums) == 0 {
|
||||||
|
return 0 // 如果没有输入,返回最大值
|
||||||
|
}
|
||||||
|
|
||||||
|
minVal := nums[0]
|
||||||
|
for _, num := range nums[1:] {
|
||||||
|
if num < minVal {
|
||||||
|
minVal = num
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return minVal
|
||||||
|
}
|
||||||
|
|
||||||
|
func calcRetryTimeRelay(x float64) float64 {
|
||||||
|
return 10 + math.Exp(0.8*(x-3.6))
|
||||||
|
}
|
||||||
|
func calcRetryTimeDirect(x float64) float64 {
|
||||||
|
return 10 + math.Exp(2.8*(x-4))
|
||||||
|
}
|
||||||
|
|
||||||
|
func isAndroid() bool {
|
||||||
|
if runtime.GOOS == "android" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
data, err := os.ReadFile("/proc/version")
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return strings.Contains(string(data), "Android")
|
||||||
|
}
|
||||||
|
|
||||||
|
func moveFile(src, dst string) error {
|
||||||
|
err := os.Rename(src, dst)
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// windows could not rename running executable, so copy then delete
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
err = copyFile(src, dst)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
os.Remove(src)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func copyFile(src, dst string) error {
|
||||||
|
sourceFile, err := os.Open(src)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer sourceFile.Close()
|
||||||
|
|
||||||
|
destFile, err := os.Create(dst)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer destFile.Close()
|
||||||
|
|
||||||
|
_, err = io.Copy(destFile, sourceFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return destFile.Sync()
|
||||||
|
}
|
||||||
|
|
||||||
|
func resolveServerIP(host string) ([]string, error) {
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
// 先系统 DNS
|
||||||
|
ips, err := net.DefaultResolver.LookupHost(ctx, host)
|
||||||
|
if err == nil && len(ips) > 0 {
|
||||||
|
gLog.i("system dns resolved %s -> %v", host, ips)
|
||||||
|
return ips, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
gLog.e("system dns resolve failed for %s: %v", host, err)
|
||||||
|
gLog.i("retry with fallback dns...")
|
||||||
|
|
||||||
|
// 再 fallback dns
|
||||||
|
return lookupWithCustomDNS(ctx, host)
|
||||||
|
}
|
||||||
|
func lookupWithCustomDNS(ctx context.Context, domain string) ([]string, error) {
|
||||||
|
resolver := &net.Resolver{
|
||||||
|
PreferGo: true,
|
||||||
|
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
|
||||||
|
dialer := &net.Dialer{Timeout: 5 * time.Second}
|
||||||
|
|
||||||
|
// 先 119.29.29.29
|
||||||
|
conn, err := dialer.DialContext(ctx, network, "119.29.29.29:53")
|
||||||
|
if err == nil {
|
||||||
|
return conn, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 再 8.8.8.8
|
||||||
|
return dialer.DialContext(ctx, network, "8.8.8.8:53")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return resolver.LookupHost(ctx, domain)
|
||||||
|
}
|
||||||
|
|||||||
+48
-48
@@ -77,14 +77,17 @@ type Config struct {
|
|||||||
Network NetworkConfig `json:"network"`
|
Network NetworkConfig `json:"network"`
|
||||||
Apps []*AppConfig `json:"apps"`
|
Apps []*AppConfig `json:"apps"`
|
||||||
|
|
||||||
LogLevel int
|
LogLevel int
|
||||||
MaxLogSize int
|
MaxLogSize int
|
||||||
daemonMode bool
|
TLSInsecureSkipVerify bool
|
||||||
mtx sync.Mutex
|
Forcev6 bool
|
||||||
sdwanMtx sync.Mutex
|
daemonMode bool
|
||||||
sdwan SDWANInfo
|
mtx sync.RWMutex
|
||||||
delNodes []*SDWANNode
|
fileMtx sync.Mutex
|
||||||
addNodes []*SDWANNode
|
sdwanMtx sync.Mutex
|
||||||
|
sdwan SDWANInfo
|
||||||
|
delNodes []*SDWANNode
|
||||||
|
addNodes []*SDWANNode
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) getSDWAN() SDWANInfo {
|
func (c *Config) getSDWAN() SDWANInfo {
|
||||||
@@ -251,31 +254,42 @@ func (c *Config) delete(app AppConfig) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) save() {
|
func (c *Config) save() {
|
||||||
// c.mtx.Lock()
|
c.fileMtx.Lock()
|
||||||
// defer c.mtx.Unlock() // internal call
|
defer c.fileMtx.Unlock()
|
||||||
if c.Network.Token == 0 {
|
if c.Network.Token == 0 {
|
||||||
|
gLog.e("c.Network.Token == 0 skip save")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
data, _ := json.MarshalIndent(c, "", " ")
|
data, err := json.MarshalIndent(c, "", " ")
|
||||||
err := os.WriteFile("config.json", data, 0644)
|
if err != nil || len(data) < 16 {
|
||||||
if err != nil {
|
gLog.e("MarshalIndent config.json error:%v, len=%d", err, len(data))
|
||||||
gLog.Println(LvERROR, "save config.json error:", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Config) saveCache() {
|
|
||||||
// c.mtx.Lock()
|
|
||||||
// defer c.mtx.Unlock() // internal call
|
|
||||||
if c.Network.Token == 0 {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
data, _ := json.MarshalIndent(c, "", " ")
|
err = os.WriteFile("config.json0", data, 0644)
|
||||||
err := os.WriteFile("config.json0", data, 0644)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
gLog.Println(LvERROR, "save config.json0 error:", err)
|
gLog.e("save config.json error:%v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// verify if the file is written correctly
|
||||||
|
data, err = os.ReadFile("config.json0")
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var tmpConfig Config
|
||||||
|
err = json.Unmarshal(data, &tmpConfig)
|
||||||
|
if err != nil {
|
||||||
|
gLog.e("parse config.json error:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = os.Rename("config.json0", "config.json")
|
||||||
|
if err != nil {
|
||||||
|
gLog.e("rename config file error:%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -d run, then worker serverport always WsPort.
|
||||||
|
// func init() {
|
||||||
func init() {
|
func init() {
|
||||||
gConf.LogLevel = int(LvINFO)
|
gConf.LogLevel = int(LvINFO)
|
||||||
gConf.MaxLogSize = 1024 * 1024
|
gConf.MaxLogSize = 1024 * 1024
|
||||||
@@ -286,19 +300,19 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) load() error {
|
func (c *Config) load() error {
|
||||||
c.mtx.Lock()
|
c.fileMtx.Lock()
|
||||||
defer c.mtx.Unlock()
|
defer c.fileMtx.Unlock()
|
||||||
data, err := os.ReadFile("config.json")
|
data, err := os.ReadFile("config.json")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.loadCache()
|
return err
|
||||||
}
|
}
|
||||||
|
c.mtx.Lock()
|
||||||
|
defer c.mtx.Unlock()
|
||||||
err = json.Unmarshal(data, &c)
|
err = json.Unmarshal(data, &c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
gLog.Println(LvERROR, "parse config.json error:", err)
|
gLog.e("parse config.json error:", err)
|
||||||
// try cache
|
return err
|
||||||
return c.loadCache()
|
|
||||||
}
|
}
|
||||||
// load ok. cache it
|
|
||||||
var filteredApps []*AppConfig // filter memapp
|
var filteredApps []*AppConfig // filter memapp
|
||||||
for _, app := range c.Apps {
|
for _, app := range c.Apps {
|
||||||
if app.SrcPort != 0 {
|
if app.SrcPort != 0 {
|
||||||
@@ -306,19 +320,7 @@ func (c *Config) load() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.Apps = filteredApps
|
c.Apps = filteredApps
|
||||||
c.saveCache()
|
c.Network.natType = NATUnknown
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Config) loadCache() error {
|
|
||||||
data, err := os.ReadFile("config.json0")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = json.Unmarshal(data, &c)
|
|
||||||
if err != nil {
|
|
||||||
gLog.Println(LvERROR, "parse config.json0 error:", err)
|
|
||||||
}
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -326,7 +328,6 @@ func (c *Config) loadCache() error {
|
|||||||
func (c *Config) setToken(token uint64) {
|
func (c *Config) setToken(token uint64) {
|
||||||
c.mtx.Lock()
|
c.mtx.Lock()
|
||||||
defer c.mtx.Unlock()
|
defer c.mtx.Unlock()
|
||||||
defer c.save()
|
|
||||||
if token != 0 {
|
if token != 0 {
|
||||||
c.Network.Token = token
|
c.Network.Token = token
|
||||||
}
|
}
|
||||||
@@ -334,13 +335,11 @@ func (c *Config) setToken(token uint64) {
|
|||||||
func (c *Config) setUser(user string) {
|
func (c *Config) setUser(user string) {
|
||||||
c.mtx.Lock()
|
c.mtx.Lock()
|
||||||
defer c.mtx.Unlock()
|
defer c.mtx.Unlock()
|
||||||
defer c.save()
|
|
||||||
c.Network.User = user
|
c.Network.User = user
|
||||||
}
|
}
|
||||||
func (c *Config) setNode(node string) {
|
func (c *Config) setNode(node string) {
|
||||||
c.mtx.Lock()
|
c.mtx.Lock()
|
||||||
defer c.mtx.Unlock()
|
defer c.mtx.Unlock()
|
||||||
defer c.save()
|
|
||||||
c.Network.Node = node
|
c.Network.Node = node
|
||||||
c.Network.nodeID = NodeNameToID(c.Network.Node)
|
c.Network.nodeID = NodeNameToID(c.Network.Node)
|
||||||
}
|
}
|
||||||
@@ -379,6 +378,7 @@ type NetworkConfig struct {
|
|||||||
mac string
|
mac string
|
||||||
os string
|
os string
|
||||||
publicIP string
|
publicIP string
|
||||||
|
previousIP string // for publicIP change detect
|
||||||
natType int
|
natType int
|
||||||
hasIPv4 int
|
hasIPv4 int
|
||||||
publicIPv6 string // must lowwer-case not save json
|
publicIPv6 string // must lowwer-case not save json
|
||||||
@@ -505,9 +505,9 @@ func parseParams(subCommand string, cmd string) {
|
|||||||
gConf.Network.UDPPort1 = UDPPort1
|
gConf.Network.UDPPort1 = UDPPort1
|
||||||
gConf.Network.UDPPort2 = UDPPort2
|
gConf.Network.UDPPort2 = UDPPort2
|
||||||
gLog.setLevel(LogLevel(gConf.LogLevel))
|
gLog.setLevel(LogLevel(gConf.LogLevel))
|
||||||
|
gLog.setMaxSize(int64(gConf.MaxLogSize))
|
||||||
if *notVerbose {
|
if *notVerbose {
|
||||||
gLog.setMode(LogFile)
|
gLog.setMode(LogFile)
|
||||||
}
|
}
|
||||||
// gConf.mtx.Unlock()
|
|
||||||
gConf.save()
|
gConf.save()
|
||||||
}
|
}
|
||||||
|
|||||||
+78
-15
@@ -74,7 +74,7 @@ func encodeHeader(mainType uint16, subType uint16, len uint32) []byte {
|
|||||||
return headBuf.Bytes()
|
return headBuf.Bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Message type
|
// Message main type
|
||||||
const (
|
const (
|
||||||
MsgLogin = 0
|
MsgLogin = 0
|
||||||
MsgHeartbeat = 1
|
MsgHeartbeat = 1
|
||||||
@@ -109,6 +109,8 @@ const (
|
|||||||
MsgPushReportMemApps = 17
|
MsgPushReportMemApps = 17
|
||||||
MsgPushServerSideSaveMemApp = 18
|
MsgPushServerSideSaveMemApp = 18
|
||||||
MsgPushCheckRemoteService = 19
|
MsgPushCheckRemoteService = 19
|
||||||
|
MsgPushSpecTunnel = 20
|
||||||
|
MsgPushReportHeap = 21
|
||||||
)
|
)
|
||||||
|
|
||||||
// MsgP2P sub type message
|
// MsgP2P sub type message
|
||||||
@@ -128,6 +130,9 @@ const (
|
|||||||
MsgRelayHeartbeatAck
|
MsgRelayHeartbeatAck
|
||||||
MsgNodeData
|
MsgNodeData
|
||||||
MsgRelayNodeData
|
MsgRelayNodeData
|
||||||
|
MsgNodeDataMP
|
||||||
|
MsgNodeDataMPAck
|
||||||
|
MsgRelayHeartbeatAck2
|
||||||
)
|
)
|
||||||
|
|
||||||
// MsgRelay sub type message
|
// MsgRelay sub type message
|
||||||
@@ -243,6 +248,21 @@ func newMessage(mainType uint16, subType uint16, packet interface{}) ([]byte, er
|
|||||||
return writeBytes, nil
|
return writeBytes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newMessageWithBuff(mainType uint16, subType uint16, data []byte) ([]byte, error) {
|
||||||
|
head := openP2PHeader{
|
||||||
|
uint32(len(data)),
|
||||||
|
mainType,
|
||||||
|
subType,
|
||||||
|
}
|
||||||
|
headBuf := new(bytes.Buffer)
|
||||||
|
err := binary.Write(headBuf, binary.LittleEndian, head)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
writeBytes := append(headBuf.Bytes(), data...)
|
||||||
|
return writeBytes, nil
|
||||||
|
}
|
||||||
|
|
||||||
func NodeNameToID(name string) uint64 {
|
func NodeNameToID(name string) uint64 {
|
||||||
return crc64.Checksum([]byte(name), crc64.MakeTable(crc64.ISO))
|
return crc64.Checksum([]byte(name), crc64.MakeTable(crc64.ISO))
|
||||||
}
|
}
|
||||||
@@ -339,13 +359,15 @@ type RelayNodeRsp struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type AddRelayTunnelReq struct {
|
type AddRelayTunnelReq struct {
|
||||||
From string `json:"from,omitempty"`
|
From string `json:"from,omitempty"`
|
||||||
RelayName string `json:"relayName,omitempty"`
|
RelayName string `json:"relayName,omitempty"`
|
||||||
RelayTunnelID uint64 `json:"relayTunnelID,omitempty"`
|
RelayTunnelID uint64 `json:"relayTunnelID,omitempty"`
|
||||||
RelayToken uint64 `json:"relayToken,omitempty"`
|
RelayToken uint64 `json:"relayToken,omitempty"`
|
||||||
RelayMode string `json:"relayMode,omitempty"`
|
RelayMode string `json:"relayMode,omitempty"`
|
||||||
AppID uint64 `json:"appID,omitempty"` // deprecated
|
AppID uint64 `json:"appID,omitempty"` // deprecated
|
||||||
AppKey uint64 `json:"appKey,omitempty"` // deprecated
|
AppKey uint64 `json:"appKey,omitempty"` // deprecated
|
||||||
|
UnderlayProtocol string `json:"underlayProtocol,omitempty"` // quic or kcp, default quic
|
||||||
|
PunchPriority int `json:"punchPriority,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type APPKeySync struct {
|
type APPKeySync struct {
|
||||||
@@ -354,9 +376,10 @@ type APPKeySync struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type RelayHeartbeat struct {
|
type RelayHeartbeat struct {
|
||||||
From string `json:"from,omitempty"`
|
From string `json:"from,omitempty"`
|
||||||
RelayTunnelID uint64 `json:"relayTunnelID,omitempty"`
|
RelayTunnelID uint64 `json:"relayTunnelID,omitempty"`
|
||||||
AppID uint64 `json:"appID,omitempty"`
|
RelayTunnelID2 uint64 `json:"relayTunnelID2,omitempty"`
|
||||||
|
AppID uint64 `json:"appID,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ReportBasic struct {
|
type ReportBasic struct {
|
||||||
@@ -415,13 +438,16 @@ type AppInfo struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ReportApps struct {
|
type ReportApps struct {
|
||||||
Apps []AppInfo
|
Apps []AppInfo
|
||||||
|
TunError string `json:"tunError,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ReportLogReq struct {
|
type ReportLogReq struct {
|
||||||
FileName string `json:"fileName,omitempty"`
|
FileName string `json:"fileName,omitempty"`
|
||||||
Offset int64 `json:"offset,omitempty"`
|
Offset int64 `json:"offset,omitempty"`
|
||||||
Len int64 `json:"len,omitempty"`
|
Len int64 `json:"len,omitempty"`
|
||||||
|
IsSetLogLevel int64 `json:"isSetLogLevel,omitempty"`
|
||||||
|
LogLevel int64 `json:"loglevel,omitempty"`
|
||||||
}
|
}
|
||||||
type ReportLogRsp struct {
|
type ReportLogRsp struct {
|
||||||
FileName string `json:"fileName,omitempty"`
|
FileName string `json:"fileName,omitempty"`
|
||||||
@@ -434,6 +460,7 @@ type UpdateInfo struct {
|
|||||||
Error int `json:"error,omitempty"`
|
Error int `json:"error,omitempty"`
|
||||||
ErrorDetail string `json:"errorDetail,omitempty"`
|
ErrorDetail string `json:"errorDetail,omitempty"`
|
||||||
Url string `json:"url,omitempty"`
|
Url string `json:"url,omitempty"`
|
||||||
|
Url2 string `json:"url2,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type NetInfo struct {
|
type NetInfo struct {
|
||||||
@@ -467,6 +494,7 @@ type ProfileInfo struct {
|
|||||||
type EditNode struct {
|
type EditNode struct {
|
||||||
NewName string `json:"newName,omitempty"`
|
NewName string `json:"newName,omitempty"`
|
||||||
Bandwidth int `json:"bandwidth,omitempty"`
|
Bandwidth int `json:"bandwidth,omitempty"`
|
||||||
|
Forcev6 int `json:"forcev6,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type QueryPeerInfoReq struct {
|
type QueryPeerInfoReq struct {
|
||||||
@@ -501,6 +529,8 @@ type SDWANInfo struct {
|
|||||||
ForceRelay int32 `json:"forceRelay,omitempty"`
|
ForceRelay int32 `json:"forceRelay,omitempty"`
|
||||||
PunchPriority int32 `json:"punchPriority,omitempty"`
|
PunchPriority int32 `json:"punchPriority,omitempty"`
|
||||||
Enable int32 `json:"enable,omitempty"`
|
Enable int32 `json:"enable,omitempty"`
|
||||||
|
TunnelNum int32 `json:"tunnelNum,omitempty"`
|
||||||
|
Mtu int32 `json:"mtu,omitempty"`
|
||||||
Nodes []*SDWANNode
|
Nodes []*SDWANNode
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -516,6 +546,10 @@ type ServerSideSaveMemApp struct {
|
|||||||
RelayTunnelID uint64 `json:"relayTunnelID,omitempty"` // rtid, if not 0 relay
|
RelayTunnelID uint64 `json:"relayTunnelID,omitempty"` // rtid, if not 0 relay
|
||||||
RelayMode string `json:"relayMode,omitempty"`
|
RelayMode string `json:"relayMode,omitempty"`
|
||||||
AppID uint64 `json:"appID,omitempty"`
|
AppID uint64 `json:"appID,omitempty"`
|
||||||
|
AppKey uint64 `json:"appKey,omitempty"`
|
||||||
|
RelayIndex uint32 `json:"relayIndex,omitempty"`
|
||||||
|
TunnelNum uint32 `json:"tunnelNum,omitempty"`
|
||||||
|
SrcPort uint32 `json:"srcPort,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type CheckRemoteService struct {
|
type CheckRemoteService struct {
|
||||||
@@ -523,6 +557,10 @@ type CheckRemoteService struct {
|
|||||||
Port uint32 `json:"port,omitempty"`
|
Port uint32 `json:"port,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SpecTunnel struct {
|
||||||
|
TunnelIndex uint32 `json:"tunnelIndex,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
const rootCA = `-----BEGIN CERTIFICATE-----
|
const rootCA = `-----BEGIN CERTIFICATE-----
|
||||||
MIIDhTCCAm0CFHm0cd8dnGCbUW/OcS56jf0gvRk7MA0GCSqGSIb3DQEBCwUAMH4x
|
MIIDhTCCAm0CFHm0cd8dnGCbUW/OcS56jf0gvRk7MA0GCSqGSIb3DQEBCwUAMH4x
|
||||||
CzAJBgNVBAYTAkNOMQswCQYDVQQIDAJHRDETMBEGA1UECgwKb3BlbnAycC5jbjET
|
CzAJBgNVBAYTAkNOMQswCQYDVQQIDAJHRDETMBEGA1UECgwKb3BlbnAycC5jbjET
|
||||||
@@ -545,6 +583,31 @@ RVtXS+DplMClQ5QSlv3StwcWOsjyiAimNfLEU5xoEfq17yOJUTU1OTL4YOt16QUc
|
|||||||
C1tnzFr3k/ioqFR7cnyzNrbjlfPOmO9l2WReEbMP3bvaSHm6EcpJKS8=
|
C1tnzFr3k/ioqFR7cnyzNrbjlfPOmO9l2WReEbMP3bvaSHm6EcpJKS8=
|
||||||
-----END CERTIFICATE-----`
|
-----END CERTIFICATE-----`
|
||||||
|
|
||||||
|
const rootEdgeCA = `-----BEGIN CERTIFICATE-----
|
||||||
|
MIID/zCCAuegAwIBAgIUI53UqyuJSa74NFIKherg5WTjtl4wDQYJKoZIhvcNAQEL
|
||||||
|
BQAwgYYxCzAJBgNVBAYTAkNOMQswCQYDVQQIDAJHRDETMBEGA1UECgwKb3BlbnAy
|
||||||
|
cC5jbjETMBEGA1UECwwKb3BlbnAycC5jbjEbMBkGA1UEAwwSb3BlbnAycC5jbiBS
|
||||||
|
b290IENBMSMwIQYJKoZIhvcNAQkBFhRvcGVucDJwLmNuQGdtYWlsLmNvbTAeFw0y
|
||||||
|
NTA5MDMwNTExMTBaFw0zNTA5MDEwNTExMTBaMIGGMQswCQYDVQQGEwJDTjELMAkG
|
||||||
|
A1UECAwCR0QxEzARBgNVBAoMCm9wZW5wMnAuY24xEzARBgNVBAsMCm9wZW5wMnAu
|
||||||
|
Y24xGzAZBgNVBAMMEm9wZW5wMnAuY24gUm9vdCBDQTEjMCEGCSqGSIb3DQEJARYU
|
||||||
|
b3BlbnAycC5jbkBnbWFpbC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
|
||||||
|
AoIBAQC/aHC0opWx1MFkXYI+Mm0CkMi7nB5XaD3K/DGGtA/kadhayFSWb6Y2+UWW
|
||||||
|
s6OYBy7NmQRJgTedS4siQA6JEG4H3FBbz8URLt4TH/EP9+6QB0Z+P0arvUXNkl4k
|
||||||
|
7cALmblaiqjq2M199+FWKhDWH2vMr1htY9Y3ldivLRMeH76diKgf8NvsX+wGR8bZ
|
||||||
|
4MlJMFln0UeUYKIbekK7DmA5/9f2A/2Nrmi84PKGHU+0ZjB7gik/slW5zH0k7e+S
|
||||||
|
wNtTuf8+6+t/LcJK9dWsS6f5+DOWmLcIWs6s/VMP9ODEzlY/hKMFk53+H+AjAZY/
|
||||||
|
J/qhOxLXMNlNjdjwSEFPBY/vwVEnAgMBAAGjYzBhMB0GA1UdDgQWBBTXSSeIvz/R
|
||||||
|
6A1pz0H4xBlV1Vu9kTAfBgNVHSMEGDAWgBTXSSeIvz/R6A1pz0H4xBlV1Vu9kTAP
|
||||||
|
BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOC
|
||||||
|
AQEABqvvKwM+k2NfIFf9tzo1EsD4rQunyn6K5Zhf/kspb9++2Onw/lDlOErxSLLz
|
||||||
|
C5aXn+B48honQeYEL/cYhH4duVQb0Zk71iF/PKDxYvF79Xbx9k7Kzg6RryaH8ZfQ
|
||||||
|
pyEao+Uc6O895F+SLBog5aHIbz8gFNCRVaSAv3xpUIyQ/haxyHHapaLqt/ueNFVP
|
||||||
|
qEG+9R41q55rEYb2ltINhumS3gb4qOcKI5pHuAw42pF8SShqaBIfFXSZ4u9ib7/k
|
||||||
|
CvHN0kDYavV6NRiCSRF6wMxmaF70WpfqQhGdw0WyIzJfMOtSdvctjfNCoaWy2V2s
|
||||||
|
nLaJXgiPehxIVGNC9dk/ZZzI2g==
|
||||||
|
-----END CERTIFICATE-----`
|
||||||
|
|
||||||
const ISRGRootX1 = `-----BEGIN CERTIFICATE-----
|
const ISRGRootX1 = `-----BEGIN CERTIFICATE-----
|
||||||
MIIEJjCCAw6gAwIBAgISAztStWq026ej0RCsk3ErbUdPMA0GCSqGSIb3DQEBCwUA
|
MIIEJjCCAw6gAwIBAgISAztStWq026ej0RCsk3ErbUdPMA0GCSqGSIb3DQEBCwUA
|
||||||
MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD
|
MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD
|
||||||
|
|||||||
+61
-40
@@ -19,21 +19,21 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func update(host string, port int) error {
|
func update(host string, port int) error {
|
||||||
gLog.Println(LvINFO, "update start")
|
gLog.i("update start")
|
||||||
defer gLog.Println(LvINFO, "update end")
|
defer gLog.i("update end")
|
||||||
caCertPool, err := x509.SystemCertPool()
|
caCertPool, err := x509.SystemCertPool()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
gLog.Println(LvERROR, "Failed to load system root CAs:", err)
|
gLog.e("Failed to load system root CAs:%s", err)
|
||||||
} else {
|
|
||||||
caCertPool = x509.NewCertPool()
|
caCertPool = x509.NewCertPool()
|
||||||
}
|
}
|
||||||
caCertPool.AppendCertsFromPEM([]byte(rootCA))
|
caCertPool.AppendCertsFromPEM([]byte(rootCA))
|
||||||
|
caCertPool.AppendCertsFromPEM([]byte(rootEdgeCA))
|
||||||
caCertPool.AppendCertsFromPEM([]byte(ISRGRootX1))
|
caCertPool.AppendCertsFromPEM([]byte(ISRGRootX1))
|
||||||
|
|
||||||
c := http.Client{
|
c := http.Client{
|
||||||
Transport: &http.Transport{
|
Transport: &http.Transport{
|
||||||
TLSClientConfig: &tls.Config{RootCAs: caCertPool,
|
TLSClientConfig: &tls.Config{RootCAs: caCertPool,
|
||||||
InsecureSkipVerify: false},
|
InsecureSkipVerify: gConf.TLSInsecureSkipVerify},
|
||||||
},
|
},
|
||||||
Timeout: time.Second * 30,
|
Timeout: time.Second * 30,
|
||||||
}
|
}
|
||||||
@@ -41,32 +41,36 @@ func update(host string, port int) error {
|
|||||||
goarch := runtime.GOARCH
|
goarch := runtime.GOARCH
|
||||||
rsp, err := c.Get(fmt.Sprintf("https://%s:%d/api/v1/update?fromver=%s&os=%s&arch=%s&user=%s&node=%s", host, port, OpenP2PVersion, goos, goarch, url.QueryEscape(gConf.Network.User), url.QueryEscape(gConf.Network.Node)))
|
rsp, err := c.Get(fmt.Sprintf("https://%s:%d/api/v1/update?fromver=%s&os=%s&arch=%s&user=%s&node=%s", host, port, OpenP2PVersion, goos, goarch, url.QueryEscape(gConf.Network.User), url.QueryEscape(gConf.Network.Node)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
gLog.Println(LvERROR, "update:query update list failed:", err)
|
gLog.e("update:query update list failed:%s", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer rsp.Body.Close()
|
defer rsp.Body.Close()
|
||||||
if rsp.StatusCode != http.StatusOK {
|
if rsp.StatusCode != http.StatusOK {
|
||||||
gLog.Println(LvERROR, "get update info error:", rsp.Status)
|
gLog.e("get update info error:%s", rsp.Status)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
rspBuf, err := ioutil.ReadAll(rsp.Body)
|
rspBuf, err := ioutil.ReadAll(rsp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
gLog.Println(LvERROR, "update:read update list failed:", err)
|
gLog.e("update:read update list failed:%s", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
updateInfo := UpdateInfo{}
|
updateInfo := UpdateInfo{}
|
||||||
if err = json.Unmarshal(rspBuf, &updateInfo); err != nil {
|
if err = json.Unmarshal(rspBuf, &updateInfo); err != nil {
|
||||||
gLog.Println(LvERROR, rspBuf, " update info decode error:", err)
|
gLog.e("%s update info decode error:%s", string(rspBuf), err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if updateInfo.Error != 0 {
|
if updateInfo.Error != 0 {
|
||||||
gLog.Println(LvERROR, "update error:", updateInfo.Error, updateInfo.ErrorDetail)
|
gLog.e("update error:%d,%s", updateInfo.Error, updateInfo.ErrorDetail)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = updateFile(updateInfo.Url, "", "openp2p")
|
err = updateFile(updateInfo.Url, "", "openp2p")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
gLog.Println(LvERROR, "update: download failed:", err)
|
gLog.e("update: download failed:%s, retry...", err)
|
||||||
return err
|
err = updateFile(updateInfo.Url2, "", "openp2p")
|
||||||
|
if err != nil {
|
||||||
|
gLog.e("update: download failed:%s", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -74,66 +78,79 @@ func update(host string, port int) error {
|
|||||||
func downloadFile(url string, checksum string, dstFile string) error {
|
func downloadFile(url string, checksum string, dstFile string) error {
|
||||||
output, err := os.OpenFile(dstFile, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0776)
|
output, err := os.OpenFile(dstFile, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0776)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
gLog.Printf(LvERROR, "OpenFile %s error:%s", dstFile, err)
|
gLog.e("OpenFile %s error:%s", dstFile, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
caCertPool, err := x509.SystemCertPool()
|
caCertPool, err := x509.SystemCertPool()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
gLog.Println(LvERROR, "Failed to load system root CAs:", err)
|
gLog.e("Failed to load system root CAs:%s", err)
|
||||||
} else {
|
|
||||||
caCertPool = x509.NewCertPool()
|
caCertPool = x509.NewCertPool()
|
||||||
}
|
}
|
||||||
caCertPool.AppendCertsFromPEM([]byte(rootCA))
|
caCertPool.AppendCertsFromPEM([]byte(rootCA))
|
||||||
|
caCertPool.AppendCertsFromPEM([]byte(rootEdgeCA))
|
||||||
caCertPool.AppendCertsFromPEM([]byte(ISRGRootX1))
|
caCertPool.AppendCertsFromPEM([]byte(ISRGRootX1))
|
||||||
tr := &http.Transport{
|
tr := &http.Transport{
|
||||||
TLSClientConfig: &tls.Config{
|
TLSClientConfig: &tls.Config{
|
||||||
RootCAs: caCertPool,
|
RootCAs: caCertPool,
|
||||||
InsecureSkipVerify: false},
|
InsecureSkipVerify: gConf.TLSInsecureSkipVerify},
|
||||||
}
|
}
|
||||||
client := &http.Client{Transport: tr}
|
client := &http.Client{Transport: tr}
|
||||||
response, err := client.Get(url)
|
response, err := client.Get(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
gLog.Printf(LvERROR, "download url %s error:%s", url, err)
|
gLog.e("download url %s error:%s", url, err)
|
||||||
output.Close()
|
output.Close()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer response.Body.Close()
|
defer response.Body.Close()
|
||||||
n, err := io.Copy(output, response.Body)
|
n, err := io.Copy(output, response.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
gLog.Printf(LvERROR, "io.Copy error:%s", err)
|
gLog.e("io.Copy error:%s", err)
|
||||||
output.Close()
|
output.Close()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
output.Sync()
|
output.Sync()
|
||||||
output.Close()
|
output.Close()
|
||||||
gLog.Println(LvINFO, "download ", url, " ok")
|
gLog.i("download %s ok", url)
|
||||||
gLog.Printf(LvINFO, "size: %d bytes", n)
|
gLog.i("size: %d bytes", n)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateFile(url string, checksum string, dst string) error {
|
func updateFile(url string, checksum string, dst string) error {
|
||||||
gLog.Println(LvINFO, "download ", url)
|
gLog.i("download %s", url)
|
||||||
tmpFile := filepath.Dir(os.Args[0]) + "/openp2p.tmp"
|
tempDir := os.TempDir()
|
||||||
|
tmpFile := filepath.Join(tempDir, "openp2p.tmp")
|
||||||
err := downloadFile(url, checksum, tmpFile)
|
err := downloadFile(url, checksum, tmpFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
backupFile := os.Args[0] + "0"
|
backupBase := filepath.Base(os.Args[0])
|
||||||
err = os.Rename(os.Args[0], backupFile) // the old daemon process was using the 0 file, so it will prevent override it
|
var backupFile string
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
backupFile = filepath.Join(tempDir, backupBase+"0")
|
||||||
|
} else {
|
||||||
|
backupFile = os.Args[0] + "0" // linux can not mv running executable to /tmp, because they are different volumns
|
||||||
|
}
|
||||||
|
gLog.i("backup file %s --> %s", os.Args[0], backupFile)
|
||||||
|
err = moveFile(os.Args[0], backupFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
gLog.Printf(LvINFO, " rename %s error:%s, retry 1", os.Args[0], err)
|
if runtime.GOOS == "windows" {
|
||||||
backupFile = os.Args[0] + "1"
|
backupFile = filepath.Join(tempDir, backupBase+"1")
|
||||||
err = os.Rename(os.Args[0], backupFile)
|
} else {
|
||||||
|
backupFile = os.Args[0] + "1" // 1st update will mv deamon process to 0, 2nd update mv to 0 will failed, mv to 1
|
||||||
|
}
|
||||||
|
gLog.i("backup file %s --> %s", os.Args[0], backupFile)
|
||||||
|
err = moveFile(os.Args[0], backupFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
gLog.Printf(LvINFO, " rename %s error:%s", os.Args[0], err)
|
gLog.e(" rename %s error:%s", os.Args[0], err)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// extract
|
// extract
|
||||||
gLog.Println(LvINFO, "extract files")
|
gLog.i("extract files")
|
||||||
err = extract(filepath.Dir(os.Args[0]), tmpFile)
|
err = extract(filepath.Dir(os.Args[0]), tmpFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
gLog.Printf(LvERROR, "extract error:%s. revert rename", err)
|
gLog.e("extract error:%s. revert rename", err)
|
||||||
os.Rename(backupFile, os.Args[0])
|
moveFile(backupFile, os.Args[0])
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
os.Remove(tmpFile)
|
os.Remove(tmpFile)
|
||||||
@@ -224,16 +241,20 @@ func extractTgz(dst, src string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func cleanTempFiles() {
|
func cleanTempFiles() {
|
||||||
tmpFile := os.Args[0] + "0"
|
tempDir := os.TempDir()
|
||||||
if _, err := os.Stat(tmpFile); err == nil {
|
backupBase := filepath.Base(os.Args[0])
|
||||||
if err := os.Remove(tmpFile); err != nil {
|
for i := 0; i < 2; i++ {
|
||||||
gLog.Printf(LvDEBUG, " remove %s error:%s", tmpFile, err)
|
tmpFile := fmt.Sprintf("%s%d", os.Args[0], i)
|
||||||
|
if _, err := os.Stat(tmpFile); err == nil {
|
||||||
|
if err := os.Remove(tmpFile); err != nil {
|
||||||
|
gLog.d(" remove %s error:%s", tmpFile, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
tmpFile = fmt.Sprintf("%s%s%d", tempDir, backupBase, i)
|
||||||
tmpFile = os.Args[0] + "1"
|
if _, err := os.Stat(tmpFile); err == nil {
|
||||||
if _, err := os.Stat(tmpFile); err == nil {
|
if err := os.Remove(tmpFile); err != nil {
|
||||||
if err := os.Remove(tmpFile); err != nil {
|
gLog.d(" remove %s error:%s", tmpFile, err)
|
||||||
gLog.Printf(LvDEBUG, " remove %s error:%s", tmpFile, err)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user