Compare commits

..

4 Commits

Author SHA1 Message Date
TenderIronh
7686af39e0 Improve update mechanism 2022-01-04 15:34:29 +08:00
TenderIronh
16b937ebd7 config doc 2021-12-30 15:14:07 +08:00
TenderIronh
ac454ec694 fix parameters default value 2021-12-30 14:54:45 +08:00
TenderIronh
029d69869f refactor autorunApp and add api for web 2021-12-30 11:18:05 +08:00
16 changed files with 541 additions and 352 deletions

View File

@@ -45,7 +45,7 @@ P2P直连可以让你的设备跑满带宽。不论你的设备在任何网络
![image](/doc/images/officelisten.png)
3. 在家里下载最新的OpenP2P,解压出来,在命令行执行
```
openp2p.exe -d -node HOMEPC123 -user USERNAME1 -password PASSWORD1 --peernode OFFICEPC1 --dstip 127.0.0.1 --dstport 3389 --srcport 23389 --protocol tcp
openp2p.exe -d -node HOMEPC123 -user USERNAME1 -password PASSWORD1 -appname WindowsRemote -peernode OFFICEPC1 -dstip 127.0.0.1 -dstport 3389 -srcport 23389 -protocol tcp
```
> :warning: **切记将标记大写的参数改成自己的**

View File

@@ -56,7 +56,7 @@ Under the outbreak of covid-19 pandemic, surely remote work becomes a fundamenta
3. Download OpenP2P on your home deviceunzip and execute below command line.
```
openp2p.exe -d -node HOMEPC123 -user USERNAME1 -password PASSWORD1 --peernode OFFICEPC1 --dstip 127.0.0.1 --dstport 22 --srcport 22022 --protocol tcp
openp2p.exe -d -node HOMEPC123 -user USERNAME1 -password PASSWORD1 -appname OfficeSSH -peernode OFFICEPC1 -dstip 127.0.0.1 -dstport 22 -srcport 22022 -protocol tcp
```
> :warning: **Must change the parameters marked in UPPERCASE to your own**

View File

@@ -14,24 +14,65 @@
>* -node: 独一无二的节点名字,唯一标识
>* -user: 独一无二的用户名字该节点属于这个user
>* -password: 密码
>* -sharebandwidth: 作为共享节点时提供带宽默认10mbps. 如果是光纤大带宽,设置越大效果越好
>* -sharebandwidth: 作为共享节点时提供带宽默认10mbps. 如果是光纤大带宽,设置越大效果越好. -1表示不共享该节点只在私有的P2P网络使用。不加入共享的P2P网络这样也意味着无法使用别人的共享节点
>* -loglevel: 需要查看更多调试日志设置0默认是1
>* -noshare: 不共享该节点只在私有的P2P网络使用。不加入共享的P2P网络这样也意味着无法使用别人的共享节点
## 连接
```
./openp2p -d -node HOMEPC123 -user USERNAME1 -password PASSWORD1 -peernode OFFICEPC1 -dstip 127.0.0.1 -dstport 3389 -srcport 23389 -protocol tcp
./openp2p -d -node HOMEPC123 -user USERNAME1 -password PASSWORD1 -appname OfficeWindowsRemote -peernode OFFICEPC1 -dstip 127.0.0.1 -dstport 3389 -srcport 23389 -protocol tcp
使用配置文件建立多个P2PApp
./openp2p -d -f
./openp2p -f
```
>* -appname: 这个P2P应用名字
>* -peernode: 目标节点名字
>* -dstip: 目标服务地址默认本机127.0.0.1
>* -dstport: 目标服务端口常见的如windows远程桌面3389Linux ssh 22
>* -protocol: 目标服务协议 tcp、udp
>* -peeruser: 目标用户,如果是同一个用户下的节点,则无需设置
>* -peerpassword: 目标密码,如果是同一个用户下的节点,则无需设置
>* -f: 配置文件,如果希望配置多个P2PApp参考[config.json](/config.json)
## 配置文件
一般保存在当前目录,安装模式下会保存到 `C:\Program Files\OpenP2P\config.json``/usr/local/openp2p/config.json`
希望修改参数或者配置多个P2PApp可手动修改配置文件
配置实例
```
{
"network": {
"Node": "hhd1207-222",
"User": "USERNAME1",
"Password": "PASSWORD1",
"ShareBandwidth": -1,
"ServerHost": "api.openp2p.cn",
"ServerPort": 27182,
"UDPPort1": 27182,
"UDPPort2": 27183
},
"apps": [
{
"AppName": "OfficeWindowsPC",
"Protocol": "tcp",
"SrcPort": 23389,
"PeerNode": "OFFICEPC1",
"DstPort": 3389,
"DstHost": "localhost",
"PeerUser": "",
"PeerPassword": ""
},
{
"AppName": "OfficeServerSSH",
"Protocol": "tcp",
"SrcPort": 22,
"PeerNode": "OFFICEPC1",
"DstPort": 22,
"DstHost": "192.168.1.5",
"PeerUser": "",
"PeerPassword": ""
}
]
}
```
## 升级客户端
```

View File

@@ -15,25 +15,65 @@ Or
>* -node: Unique node name, unique identification
>* -user: Unique user name, the node belongs to this user
>* -password: Password
>* -sharebandwidth: Provides bandwidth when used as a shared node, the default is 10mbps. If it is a large bandwidth of optical fiber, the larger the setting, the better the effect
>* -sharebandwidth: Provides bandwidth when used as a shared node, the default is 10mbps. If it is a large bandwidth of optical fiber, the larger the setting, the better the effect. -1 means not shared, the node is only used in a private P2P network. Do not join the shared P2P network, which also means that you CAN NOT use other peoples shared nodes
>* -loglevel: Need to view more debug logs, set 0; the default is 1
>* -noshare: Not shared, the node is only used in a private P2P network. Do not join the shared P2P network, which also means that you CAN NOT use other peoples shared nodes
## Connect
```
./openp2p -d -node HOMEPC123 -user USERNAME1 -password PASSWORD1 -peernode OFFICEPC1 -dstip 127.0.0.1 -dstport 3389 -srcport 23389 -protocol tcp
./openp2p -d -node HOMEPC123 -user USERNAME1 -password PASSWORD1 -appname OfficeWindowsRemote -peernode OFFICEPC1 -dstip 127.0.0.1 -dstport 3389 -srcport 23389 -protocol tcp
Create multiple P2PApp by config file
./openp2p -d -f
./openp2p -f
```
>* -appname: This P2PApp name
>* -peernode: Target node name
>* -dstip: Target service address, default local 127.0.0.1
>* -dstport: Target service port, such as windows remote desktop 3389, Linux ssh 22
>* -protocol: Target service protocol tcp, udp
>* -peeruser: The target user, if it is a node under the same user, no need to set
>* -peerpassword: The target password, if it is a node under the same user, no need to set
>* -f: Configuration file, if you want to configure multiple P2PApp refer to [config.json](/config.json)
## Config file
Generally saved in the current directory, in installation mode it will be saved to `C:\Program Files\OpenP2P\config.json` or `/usr/local/openp2p/config.json`
If you want to modify the parameters, or configure multiple P2PApps, you can manually modify the configuration file
Configuration example
```
{
"network": {
"Node": "hhd1207-222",
"User": "USERNAME1",
"Password": "PASSWORD1",
"ShareBandwidth": -1,
"ServerHost": "api.openp2p.cn",
"ServerPort": 27182,
"UDPPort1": 27182,
"UDPPort2": 27183
},
"apps": [
{
"AppName": "OfficeWindowsPC",
"Protocol": "tcp",
"SrcPort": 23389,
"PeerNode": "OFFICEPC1",
"DstPort": 3389,
"DstHost": "localhost",
"PeerUser": "",
"PeerPassword": ""
},
{
"AppName": "OfficeServerSSH",
"Protocol": "tcp",
"SrcPort": 22,
"PeerNode": "OFFICEPC1",
"DstPort": 22,
"DstHost": "192.168.1.5",
"PeerUser": "",
"PeerPassword": ""
}
]
}
```
## Client update
```
# update local client

View File

@@ -3,13 +3,17 @@ package main
import (
"encoding/json"
"io/ioutil"
"sync"
"time"
)
var gConf Config
const IntValueNotSet int = -99999999
type AppConfig struct {
// required
AppName string
Protocol string
SrcPort int
PeerNode string
@@ -29,12 +33,16 @@ type AppConfig struct {
// TODO: add loglevel, maxlogfilesize
type Config struct {
Network NetworkConfig `json:"network"`
Apps []AppConfig `json:"apps"`
daemonMode bool
Network NetworkConfig `json:"network"`
Apps []AppConfig `json:"apps"`
LogLevel int
mtx sync.Mutex
}
func (c *Config) add(app AppConfig) {
c.mtx.Lock()
defer c.mtx.Unlock()
if app.SrcPort == 0 || app.DstPort == 0 {
return
}
@@ -46,8 +54,24 @@ func (c *Config) add(app AppConfig) {
c.Apps = append(c.Apps, app)
}
func (c *Config) delete(app AppConfig) {
if app.SrcPort == 0 || app.DstPort == 0 {
return
}
c.mtx.Lock()
defer c.mtx.Unlock()
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() {
data, _ := json.MarshalIndent(c, "", "")
c.mtx.Lock()
defer c.mtx.Unlock()
data, _ := json.MarshalIndent(c, "", " ")
err := ioutil.WriteFile("config.json", data, 0644)
if err != nil {
gLog.Println(LevelERROR, "save config.json error:", err)
@@ -55,6 +79,10 @@ func (c *Config) save() {
}
func (c *Config) load() error {
c.mtx.Lock()
c.LogLevel = IntValueNotSet
c.Network.ShareBandwidth = IntValueNotSet
defer c.mtx.Unlock()
data, err := ioutil.ReadFile("config.json")
if err != nil {
gLog.Println(LevelERROR, "read config.json error:", err)
@@ -72,7 +100,6 @@ type NetworkConfig struct {
Node string
User string
Password string
NoShare bool
localIP string
ipv6 string
hostName string

View File

@@ -38,7 +38,6 @@ func (d *daemon) Stop(s service.Service) error {
func (d *daemon) run() {
gLog.Println(LevelINFO, "daemon run start")
defer gLog.Println(LevelINFO, "daemon run end")
os.Chdir(filepath.Dir(os.Args[0])) // for system service
d.running = true
binPath, _ := os.Executable()
mydir, err := os.Getwd()
@@ -63,7 +62,6 @@ func (d *daemon) run() {
break
}
}
args = append(args, "-bydaemon")
for {
// start worker
gLog.Println(LevelINFO, "start worker process")
@@ -106,9 +104,9 @@ func (d *daemon) Control(ctrlComm string, exeAbsPath string, args []string) erro
// examples:
// listen:
// ./openp2p install -node hhd1207-222 -user tenderiron -password 13760636579 -noshare
// ./openp2p install -node hhd1207-222 -user tenderiron -password 13760636579 -sharebandwidth 0
// listen and build p2papp:
// ./openp2p install -node hhd1207-222 -user tenderiron -password 13760636579 -noshare -peernode hhdhome-n1 -dstip 127.0.0.1 -dstport 50022 -protocol tcp -srcport 22
// ./openp2p install -node hhd1207-222 -user tenderiron -password 13760636579 -sharebandwidth 0 -peernode hhdhome-n1 -dstip 127.0.0.1 -dstport 50022 -protocol tcp -srcport 22
func install() {
gLog = InitLogger(filepath.Dir(os.Args[0]), "openp2p-install", LevelDEBUG, 1024*1024, LogConsole)
// save config file
@@ -125,11 +123,13 @@ func install() {
dstPort := installFlag.Int("dstport", 0, "destination port ")
srcPort := installFlag.Int("srcport", 0, "source port ")
protocol := installFlag.String("protocol", "tcp", "tcp or udp")
noShare := installFlag.Bool("noshare", false, "disable using the huge numbers of shared nodes in OpenP2P network, your connectivity will be weak. also this node will not shared with others")
appName := flag.String("appname", "", "app name")
installFlag.Bool("noshare", false, "deprecated. uses -sharebandwidth -1")
shareBandwidth := installFlag.Int("sharebandwidth", 10, "N mbps share bandwidth limit, private node no limit")
// logLevel := installFlag.Int("loglevel", 1, "0:debug 1:info 2:warn 3:error")
logLevel := installFlag.Int("loglevel", 1, "0:debug 1:info 2:warn 3:error")
installFlag.Parse(os.Args[2:])
checkParams(*node, *user, *password)
gConf.LogLevel = *logLevel
gConf.Network.ServerHost = *serverHost
gConf.Network.User = *user
gConf.Network.Node = *node
@@ -137,7 +137,6 @@ func install() {
gConf.Network.ServerPort = 27182
gConf.Network.UDPPort1 = 27182
gConf.Network.UDPPort2 = 27183
gConf.Network.NoShare = *noShare
gConf.Network.ShareBandwidth = *shareBandwidth
config := AppConfig{}
config.PeerNode = *peerNode
@@ -147,6 +146,7 @@ func install() {
config.DstPort = *dstPort
config.SrcPort = *srcPort
config.Protocol = *protocol
config.AppName = *appName
gConf.add(config)
os.MkdirAll(defaultInstallPath, 0775)
err := os.Chdir(defaultInstallPath)
@@ -184,14 +184,14 @@ func install() {
// args := []string{""}
gLog.Println(LevelINFO, "targetPath:", targetPath)
err = d.Control("install", targetPath, []string{"-d", "-f"})
err = d.Control("install", targetPath, []string{"-d"})
if err != nil {
gLog.Println(LevelERROR, "install system service error:", err)
} else {
gLog.Println(LevelINFO, "install system service ok.")
}
time.Sleep(time.Second * 2)
err = d.Control("start", targetPath, []string{"-d", "-f"})
err = d.Control("start", targetPath, []string{"-d"})
if err != nil {
gLog.Println(LevelERROR, "start openp2p service error:", err)
} else {

191
handlepush.go Normal file
View File

@@ -0,0 +1,191 @@
package main
import (
"bytes"
"encoding/binary"
"encoding/json"
"fmt"
"os"
"os/exec"
"path/filepath"
"runtime"
"syscall"
"time"
)
func handlePush(pn *P2PNetwork, subType uint16, msg []byte) error {
pushHead := PushHeader{}
err := binary.Read(bytes.NewReader(msg[openP2PHeaderSize:openP2PHeaderSize+PushHeaderSize]), binary.LittleEndian, &pushHead)
if err != nil {
return err
}
gLog.Printf(LevelDEBUG, "handle push msg type:%d, push header:%+v", subType, pushHead)
switch subType {
case MsgPushConnectReq:
req := PushConnectReq{}
err := json.Unmarshal(msg[openP2PHeaderSize+PushHeaderSize:], &req)
if err != nil {
gLog.Printf(LevelERROR, "wrong MsgPushConnectReq:%s", err)
return err
}
gLog.Printf(LevelINFO, "%s is connecting...", req.From)
gLog.Println(LevelDEBUG, "push connect response to ", req.From)
// verify token or name&password
if VerifyTOTP(req.Token, pn.config.User, pn.config.Password, time.Now().Unix()+(pn.serverTs-pn.localTs)) || // localTs may behind, auto adjust ts
VerifyTOTP(req.Token, pn.config.User, pn.config.Password, time.Now().Unix()) ||
(req.User == pn.config.User && req.Password == pn.config.Password) {
gLog.Printf(LevelINFO, "Access Granted\n")
config := AppConfig{}
config.peerNatType = req.NatType
config.peerConeNatPort = req.ConeNatPort
config.peerIP = req.FromIP
config.PeerNode = req.From
// share relay node will limit bandwidth
if req.User != pn.config.User || req.Password != pn.config.Password {
gLog.Printf(LevelINFO, "set share bandwidth %d mbps", pn.config.ShareBandwidth)
config.shareBandwidth = pn.config.ShareBandwidth
}
// go pn.AddTunnel(config, req.ID)
go pn.addDirectTunnel(config, req.ID)
break
}
gLog.Println(LevelERROR, "Access Denied:", req.From)
rsp := PushConnectRsp{
Error: 1,
Detail: fmt.Sprintf("connect to %s error: Access Denied", pn.config.Node),
To: req.From,
From: pn.config.Node,
}
pn.push(req.From, MsgPushConnectRsp, rsp)
case MsgPushRsp:
rsp := PushRsp{}
err := json.Unmarshal(msg[openP2PHeaderSize:], &rsp)
if err != nil {
gLog.Printf(LevelERROR, "wrong pushRsp:%s", err)
return err
}
if rsp.Error == 0 {
gLog.Printf(LevelDEBUG, "push ok, detail:%s", rsp.Detail)
} else {
gLog.Printf(LevelERROR, "push error:%d, detail:%s", rsp.Error, rsp.Detail)
}
case MsgPushAddRelayTunnelReq:
req := AddRelayTunnelReq{}
err := json.Unmarshal(msg[openP2PHeaderSize+PushHeaderSize:], &req)
if err != nil {
gLog.Printf(LevelERROR, "wrong RelayNodeRsp:%s", err)
return err
}
config := AppConfig{}
config.PeerNode = req.RelayName
config.peerToken = req.RelayToken
// set user password, maybe the relay node is your private node
config.PeerUser = pn.config.User
config.PeerPassword = pn.config.Password
go func(r AddRelayTunnelReq) {
t, errDt := pn.addDirectTunnel(config, 0)
if errDt == nil {
// notify peer relay ready
msg := TunnelMsg{ID: t.id}
pn.push(r.From, MsgPushAddRelayTunnelRsp, msg)
SaveKey(req.AppID, req.AppKey)
}
}(req)
case MsgPushUpdate:
targetPath := filepath.Join(defaultInstallPath, defaultBinName)
args := []string{"update"}
env := os.Environ()
// Windows does not support exec syscall.
if runtime.GOOS == "windows" {
cmd := exec.Command(targetPath, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
cmd.Env = env
err := cmd.Run()
if err == nil {
os.Exit(0)
}
return err
}
return syscall.Exec(targetPath, args, env)
case MsgPushReportApps:
gLog.Println(LevelINFO, "MsgPushReportApps")
req := ReportApps{}
// TODO: add the retrying apps
gConf.mtx.Lock()
defer gConf.mtx.Unlock()
for _, config := range gConf.Apps {
appInfo := AppInfo{
AppName: config.AppName,
Protocol: config.Protocol,
SrcPort: config.SrcPort,
// RelayNode: relayNode,
PeerNode: config.PeerNode,
DstHost: config.DstHost,
DstPort: config.DstPort,
PeerUser: config.PeerUser,
PeerIP: config.peerIP,
PeerNatType: config.peerNatType,
RetryTime: config.retryTime.String(),
IsActive: 1,
}
req.Apps = append(req.Apps, appInfo)
}
// pn.apps.Range(func(_, i interface{}) bool {
// app := i.(*p2pApp)
// appInfo := AppInfo{
// AppName: app.config.AppName,
// Protocol: app.config.Protocol,
// SrcPort: app.config.SrcPort,
// RelayNode: app.relayNode,
// PeerNode: app.config.PeerNode,
// DstHost: app.config.DstHost,
// DstPort: app.config.DstPort,
// PeerUser: app.config.PeerUser,
// PeerIP: app.config.peerIP,
// PeerNatType: app.config.peerNatType,
// RetryTime: app.config.retryTime.String(),
// IsActive: 1,
// }
// req.Apps = append(req.Apps, appInfo)
// return true
// })
pn.write(MsgReport, MsgReportApps, &req)
case MsgPushEditApp:
gLog.Println(LevelINFO, "MsgPushEditApp")
newApp := AppInfo{}
err := json.Unmarshal(msg[openP2PHeaderSize:], &newApp)
if err != nil {
gLog.Printf(LevelERROR, "wrong MsgPushEditApp:%s %s", err, string(msg[openP2PHeaderSize:]))
return err
}
var oldConf AppConfig
// protocol0+srcPort0 exist, delApp
oldConf.AppName = newApp.AppName
oldConf.Protocol = newApp.Protocol0
oldConf.SrcPort = newApp.SrcPort0
oldConf.PeerNode = newApp.PeerNode
oldConf.DstHost = newApp.DstHost
oldConf.DstPort = newApp.DstPort
gConf.delete(oldConf)
// AddApp
newConf := oldConf
newConf.Protocol = newApp.Protocol
newConf.SrcPort = newApp.SrcPort
gConf.add(newConf)
gConf.save()
pn.DeleteApp(oldConf) // save quickly for the next request reportApplist
// autoReconnect will auto AddApp
// pn.AddApp(config)
// TODO: report result
default:
pn.msgMapMtx.Lock()
ch := pn.msgMap[pushHead.From]
pn.msgMapMtx.Unlock()
ch <- msg
}
return nil
}

21
log.go
View File

@@ -47,7 +47,7 @@ const (
type V8log struct {
loggers map[LogLevel]*log.Logger
files map[LogLevel]*os.File
llevel LogLevel
level LogLevel
stopSig chan bool
logDir string
mtx *sync.Mutex
@@ -92,17 +92,10 @@ func InitLogger(path string, filePrefix string, level LogLevel, maxLogSize int64
return pLog
}
// UninitLogger ...
func (vl *V8log) UninitLogger() {
if !vl.stoped {
vl.stoped = true
close(vl.stopSig)
for l := range logFileNames {
if l >= vl.llevel {
vl.files[l].Close()
}
}
}
func (vl *V8log) setLevel(level LogLevel) {
vl.mtx.Lock()
defer vl.mtx.Unlock()
vl.level = level
}
func (vl *V8log) checkFile() {
@@ -150,7 +143,7 @@ func (vl *V8log) Printf(level LogLevel, format string, params ...interface{}) {
if vl.stoped {
return
}
if level < vl.llevel {
if level < vl.level {
return
}
pidAndLevel := []interface{}{vl.pid, loglevel[level]}
@@ -170,7 +163,7 @@ func (vl *V8log) Println(level LogLevel, params ...interface{}) {
if vl.stoped {
return
}
if level < vl.llevel {
if level < vl.level {
return
}
pidAndLevel := []interface{}{vl.pid, " ", loglevel[level], " "}

6
nat.go
View File

@@ -43,7 +43,7 @@ func natTest(serverHost string, serverPort int, localPort int, echoPort int) (pu
// testing for public ip
if echoPort != 0 {
for {
gLog.Printf(LevelINFO, "public ip test start %s:%d", natRsp.IP, echoPort)
gLog.Printf(LevelDEBUG, "public ip test start %s:%d", natRsp.IP, echoPort)
conn, err := net.ListenUDP("udp", nil)
if err != nil {
break
@@ -60,10 +60,10 @@ func natTest(serverHost string, serverPort int, localPort int, echoPort int) (pu
conn.SetReadDeadline(time.Now().Add(PublicIPEchoTimeout))
_, _, err = conn.ReadFromUDP(buf)
if err == nil {
gLog.Println(LevelINFO, "public ip:YES")
gLog.Println(LevelDEBUG, "public ip:YES")
natRsp.IsPublicIP = 1
} else {
gLog.Println(LevelINFO, "public ip:NO")
gLog.Println(LevelDEBUG, "public ip:NO")
}
break
}

View File

@@ -11,6 +11,9 @@ import (
func main() {
rand.Seed(time.Now().UnixNano())
binDir := filepath.Dir(os.Args[0])
os.Chdir(binDir) // for system service
gLog = InitLogger(binDir, "openp2p", LevelDEBUG, 1024*1024, LogFileAndConsole)
// TODO: install sub command, deamon process
// groups := flag.String("groups", "", "you could join in several groups. like: GroupName1:Password1;GroupName2:Password2; group name 8-31 characters")
@@ -24,7 +27,7 @@ func main() {
update()
targetPath := filepath.Join(defaultInstallPath, defaultBinName)
d := daemon{}
err := d.Control("restart", targetPath, []string{"-d", "-f"})
err := d.Control("restart", targetPath, nil)
if err != nil {
gLog.Println(LevelERROR, "restart service error:", err)
} else {
@@ -51,36 +54,15 @@ func main() {
dstPort := flag.Int("dstport", 0, "destination port ")
srcPort := flag.Int("srcport", 0, "source port ")
protocol := flag.String("protocol", "tcp", "tcp or udp")
noShare := flag.Bool("noshare", false, "disable using the huge numbers of shared nodes in OpenP2P network, your connectivity will be weak. also this node will not shared with others")
appName := flag.String("appname", "", "app name")
flag.Bool("noshare", false, "deprecated. uses -sharebandwidth -1") // Deprecated, rm later
shareBandwidth := flag.Int("sharebandwidth", 10, "N mbps share bandwidth limit, private node no limit")
configFile := flag.Bool("f", false, "config file")
flag.Bool("f", false, "deprecated. config file") // Deprecated, rm later
daemonMode := flag.Bool("d", false, "daemonMode")
byDaemon := flag.Bool("bydaemon", false, "start by daemon")
flag.Bool("bydaemon", false, "start by daemon") // Deprecated, rm later
logLevel := flag.Int("loglevel", 1, "0:debug 1:info 2:warn 3:error")
flag.Parse()
gLog = InitLogger(filepath.Dir(os.Args[0]), "openp2p", LogLevel(*logLevel), 1024*1024, LogFileAndConsole)
gLog.Println(LevelINFO, "openp2p start. version: ", OpenP2PVersion)
if *daemonMode {
d := daemon{}
d.run()
return
}
if !*configFile {
// validate cmd params
checkParams(*node, *user, *password)
if *peerNode != "" {
if *dstPort == 0 {
gLog.Println(LevelERROR, "dstPort not set")
return
}
if *srcPort == 0 {
gLog.Println(LevelERROR, "srcPort not set")
return
}
}
}
config := AppConfig{}
config.PeerNode = *peerNode
config.PeerUser = *peerUser
@@ -89,73 +71,72 @@ func main() {
config.DstPort = *dstPort
config.SrcPort = *srcPort
config.Protocol = *protocol
gLog.Println(LevelINFO, config)
if *configFile {
if err := gConf.load(); err != nil {
gLog.Println(LevelERROR, "load config error. exit.")
return
}
} else {
gConf.add(config)
gConf.Network = NetworkConfig{
Node: *node,
User: *user,
Password: *password,
NoShare: *noShare,
ServerHost: *serverHost,
ServerPort: 27182,
UDPPort1: 27182,
UDPPort2: 27183,
ipv6: "240e:3b7:621:def0:fda4:dd7f:36a1:2803", // TODO: detect real ipv6
ShareBandwidth: *shareBandwidth,
}
}
// gConf.save() // not change config file
gConf.daemonMode = *byDaemon
config.AppName = *appName
// add command config first
gConf.add(config)
gConf.load()
gConf.mtx.Lock()
gLog.Println(LevelINFO, gConf)
// spec paramters in commandline will always be used
flag.Visit(func(f *flag.Flag) {
if f.Name == "sharebandwidth" {
gConf.Network.ShareBandwidth = *shareBandwidth
}
if f.Name == "node" {
gConf.Network.Node = *node
}
if f.Name == "user" {
gConf.Network.User = *user
}
if f.Name == "password" {
gConf.Network.Password = *password
}
if f.Name == "serverhost" {
gConf.Network.ServerHost = *serverHost
}
if f.Name == "loglevel" {
gConf.LogLevel = *logLevel
}
})
if gConf.Network.ServerHost == "" {
gConf.Network.ServerHost = *serverHost
}
if gConf.Network.Node == "" {
gConf.Network.Node = *node
}
if gConf.Network.User == "" {
gConf.Network.User = *user
}
if gConf.Network.Password == "" {
gConf.Network.Password = *password
}
if gConf.LogLevel == IntValueNotSet {
gConf.LogLevel = *logLevel
}
if gConf.Network.ShareBandwidth == IntValueNotSet {
gConf.Network.ShareBandwidth = *shareBandwidth
}
gConf.Network.ServerPort = 27182
gConf.Network.UDPPort1 = 27182
gConf.Network.UDPPort2 = 27183
gLog.Println(LevelINFO, "openp2p start. version: ", OpenP2PVersion)
gLog.setLevel(LogLevel(gConf.LogLevel))
gConf.mtx.Unlock()
gConf.save()
if *daemonMode {
d := daemon{}
d.run()
return
}
gLog.Println(LevelINFO, &gConf)
setFirewall()
network := P2PNetworkInstance(&gConf.Network)
if ok := network.Connect(30000); !ok {
gLog.Println(LevelERROR, "P2PNetwork login error")
return
}
for _, app := range gConf.Apps {
// set default peer user password
if app.PeerPassword == "" {
app.PeerPassword = gConf.Network.Password
}
if app.PeerUser == "" {
app.PeerUser = gConf.Network.User
}
err := network.AddApp(app)
if err != nil {
gLog.Println(LevelERROR, "addTunnel error")
}
}
// test
// go func() {
// time.Sleep(time.Second * 30)
// config := AppConfig{}
// config.PeerNode = *peerNode
// config.PeerUser = *peerUser
// config.PeerPassword = *peerPassword
// config.DstHost = *dstIP
// config.DstPort = *dstPort
// config.SrcPort = 32
// config.Protocol = *protocol
// network.AddApp(config)
// // time.Sleep(time.Second * 30)
// // network.DeleteTunnel(config)
// // time.Sleep(time.Second * 30)
// // network.DeleteTunnel(config)
// }()
// // TODO: http api
// api := ClientAPI{}
// go api.run()
gLog.Println(LevelINFO, "waiting for connection...")
forever := make(chan bool)
<-forever

View File

@@ -21,8 +21,8 @@ type overlayTCP struct {
}
func (otcp *overlayTCP) run() {
gLog.Printf(LevelINFO, "%d overlayTCP run start", otcp.id)
defer gLog.Printf(LevelINFO, "%d overlayTCP run end", otcp.id)
gLog.Printf(LevelDEBUG, "%d overlayTCP run start", otcp.id)
defer gLog.Printf(LevelDEBUG, "%d overlayTCP run end", otcp.id)
otcp.running = true
buffer := make([]byte, ReadBuffLen+PaddingSize)
readBuf := buffer[:ReadBuffLen]

View File

@@ -11,16 +11,17 @@ import (
)
type p2pApp struct {
config AppConfig
listener net.Listener
tunnel *P2PTunnel
rtid uint64
hbTime time.Time
hbMtx sync.Mutex
running bool
id uint64
key uint64
wg sync.WaitGroup
config AppConfig
listener net.Listener
tunnel *P2PTunnel
rtid uint64
relayNode string
hbTime time.Time
hbMtx sync.Mutex
running bool
id uint64
key uint64
wg sync.WaitGroup
}
func (app *p2pApp) isActive() bool {
@@ -72,7 +73,7 @@ func (app *p2pApp) listenTCP() error {
otcp.appKeyBytes = encryptKey
}
app.tunnel.overlayConns.Store(otcp.id, &otcp)
gLog.Printf(LevelINFO, "Accept overlayID:%d", otcp.id)
gLog.Printf(LevelDEBUG, "Accept overlayID:%d", otcp.id)
// tell peer connect
req := OverlayConnectReq{ID: otcp.id,
User: app.config.PeerUser,

View File

@@ -37,7 +37,7 @@ type P2PNetwork struct {
msgMapMtx sync.Mutex
config NetworkConfig
allTunnels sync.Map
apps sync.Map
apps sync.Map //key: protocol+srcport; value: p2pApp
limiter *BandwidthLimiter
}
@@ -63,7 +63,7 @@ func P2PNetworkInstance(config *NetworkConfig) *P2PNetwork {
}
func (pn *P2PNetwork) run() {
go pn.autoReconnectApp()
go pn.autorunApp()
heartbeatTimer := time.NewTicker(NetworkHeartbeatTime)
for pn.running {
select {
@@ -93,55 +93,61 @@ func (pn *P2PNetwork) Connect(timeout int) bool {
return false
}
func (pn *P2PNetwork) autoReconnectApp() {
gLog.Println(LevelINFO, "autoReconnectApp start")
retryApps := make([]AppConfig, 0)
func (pn *P2PNetwork) runAll() {
gConf.mtx.Lock()
defer gConf.mtx.Unlock()
for _, config := range gConf.Apps {
// set default peer user password
if config.PeerPassword == "" {
config.PeerPassword = gConf.Network.Password
}
if config.PeerUser == "" {
config.PeerUser = gConf.Network.User
}
if config.AppName == "" {
config.AppName = fmt.Sprintf("%s%d", config.Protocol, config.SrcPort)
}
appExist := false
appActive := false
i, ok := pn.apps.Load(fmt.Sprintf("%s%d", config.Protocol, config.SrcPort))
if ok {
app := i.(*p2pApp)
appExist = true
if app.isActive() {
appActive = true
}
}
if appExist && appActive {
continue
}
if appExist && !appActive {
gLog.Printf(LevelINFO, "detect app %s disconnect, reconnecting...", config.AppName)
pn.DeleteApp(config)
if config.retryTime.Add(time.Minute * 15).Before(time.Now()) {
config.retryNum = 0
}
config.retryNum++
config.retryTime = time.Now()
if config.retryNum > MaxRetry {
gLog.Printf(LevelERROR, "app %s%d retry more than %d times, exit.", config.Protocol, config.SrcPort, MaxRetry)
continue
}
}
go pn.AddApp(config)
}
}
func (pn *P2PNetwork) autorunApp() {
gLog.Println(LevelINFO, "autorunApp start")
// TODO: use gConf to check reconnect
for pn.running {
time.Sleep(time.Second)
if !pn.online {
continue
}
if len(retryApps) > 0 {
gLog.Printf(LevelINFO, "retryApps len=%d", len(retryApps))
thisRound := make([]AppConfig, 0)
for i := 0; i < len(retryApps); i++ {
// reset retryNum when running 15min continuously
if retryApps[i].retryTime.Add(time.Minute * 15).Before(time.Now()) {
retryApps[i].retryNum = 0
}
retryApps[i].retryNum++
retryApps[i].retryTime = time.Now()
if retryApps[i].retryNum > MaxRetry {
gLog.Printf(LevelERROR, "app %s%d retry more than %d times, exit.", retryApps[i].Protocol, retryApps[i].SrcPort, MaxRetry)
continue
}
pn.DeleteApp(retryApps[i])
if err := pn.AddApp(retryApps[i]); err != nil {
gLog.Printf(LevelERROR, "AddApp %s%d error:%s", retryApps[i].Protocol, retryApps[i].SrcPort, err)
thisRound = append(thisRound, retryApps[i])
time.Sleep(RetryInterval)
}
}
retryApps = thisRound
}
pn.apps.Range(func(_, i interface{}) bool {
app := i.(*p2pApp)
if app.isActive() {
return true
}
gLog.Printf(LevelINFO, "detect app %s%d disconnect,last hb %s reconnecting...", app.config.Protocol, app.config.SrcPort, app.hbTime)
config := app.config
// clear peerinfo
config.peerConeNatPort = 0
config.peerIP = ""
config.peerNatType = 0
config.peerToken = 0
pn.DeleteApp(config)
retryApps = append(retryApps, config)
return true
})
pn.runAll()
time.Sleep(time.Second * 10)
}
gLog.Println(LevelINFO, "autoReconnectApp end")
gLog.Println(LevelINFO, "autorunApp end")
}
func (pn *P2PNetwork) addRelayTunnel(config AppConfig, appid uint64, appkey uint64) (*P2PTunnel, uint64, error) {
@@ -198,21 +204,17 @@ func (pn *P2PNetwork) addRelayTunnel(config AppConfig, appid uint64, appkey uint
}
func (pn *P2PNetwork) AddApp(config AppConfig) error {
gLog.Printf(LevelINFO, "addApp %s%d to %s:%s:%d start", config.Protocol, config.SrcPort, config.PeerNode, config.DstHost, config.DstPort)
defer gLog.Printf(LevelINFO, "addApp %s%d to %s:%s:%d end", config.Protocol, config.SrcPort, config.PeerNode, config.DstHost, config.DstPort)
gLog.Printf(LevelINFO, "addApp %s to %s:%s:%d start", config.AppName, config.PeerNode, config.DstHost, config.DstPort)
defer gLog.Printf(LevelINFO, "addApp %s to %s:%s:%d end", config.AppName, config.PeerNode, config.DstHost, config.DstPort)
if !pn.online {
return errors.New("P2PNetwork offline")
}
// check if app already exist?
appExist := false
pn.apps.Range(func(_, i interface{}) bool {
app := i.(*p2pApp)
if app.config.Protocol == config.Protocol && app.config.SrcPort == config.SrcPort {
appExist = true
return false
}
return true
})
_, ok := pn.apps.Load(fmt.Sprintf("%s%d", config.Protocol, config.SrcPort))
if ok {
appExist = true
}
if appExist {
return errors.New("P2PApp already exist")
}
@@ -221,7 +223,7 @@ func (pn *P2PNetwork) AddApp(config AppConfig) error {
t, err := pn.addDirectTunnel(config, 0)
var rtid uint64
relayNode := ""
peerNatType := 100
peerNatType := NATUnknown
peerIP := ""
errMsg := ""
if err != nil && err == ErrorHandshake {
@@ -257,13 +259,14 @@ func (pn *P2PNetwork) AddApp(config AppConfig) error {
pn.write(MsgReport, MsgReportConnect, &req)
app := p2pApp{
id: appID,
key: appKey,
tunnel: t,
config: config,
rtid: rtid,
hbTime: time.Now()}
pn.apps.Store(appID, &app)
id: appID,
key: appKey,
tunnel: t,
config: config,
rtid: rtid,
relayNode: relayNode,
hbTime: time.Now()}
pn.apps.Store(fmt.Sprintf("%s%d", config.Protocol, config.SrcPort), &app)
if err == nil {
go app.listen()
}
@@ -274,22 +277,18 @@ func (pn *P2PNetwork) DeleteApp(config AppConfig) {
gLog.Printf(LevelINFO, "DeleteApp %s%d start", config.Protocol, config.SrcPort)
defer gLog.Printf(LevelINFO, "DeleteApp %s%d end", config.Protocol, config.SrcPort)
// close the apps of this config
pn.apps.Range(func(_, i interface{}) bool {
i, ok := pn.apps.Load(fmt.Sprintf("%s%d", config.Protocol, config.SrcPort))
if ok {
app := i.(*p2pApp)
if app.config.Protocol == config.Protocol && app.config.SrcPort == config.SrcPort {
gLog.Printf(LevelINFO, "app %s exist, delete it", fmt.Sprintf("%s%d", config.Protocol, config.SrcPort))
app := i.(*p2pApp)
app.close()
pn.apps.Delete(app.id)
return false
}
return true
})
gLog.Printf(LevelINFO, "app %s exist, delete it", fmt.Sprintf("%s%d", config.Protocol, config.SrcPort))
app.close()
pn.apps.Delete(fmt.Sprintf("%s%d", config.Protocol, config.SrcPort))
}
}
func (pn *P2PNetwork) addDirectTunnel(config AppConfig, tid uint64) (*P2PTunnel, error) {
gLog.Printf(LevelINFO, "addDirectTunnel %s%d to %s:%s:%d start", config.Protocol, config.SrcPort, config.PeerNode, config.DstHost, config.DstPort)
defer gLog.Printf(LevelINFO, "addDirectTunnel %s%d to %s:%s:%d end", config.Protocol, config.SrcPort, config.PeerNode, config.DstHost, config.DstPort)
gLog.Printf(LevelDEBUG, "addDirectTunnel %s%d to %s:%s:%d start", config.Protocol, config.SrcPort, config.PeerNode, config.DstHost, config.DstPort)
defer gLog.Printf(LevelDEBUG, "addDirectTunnel %s%d to %s:%s:%d end", config.Protocol, config.SrcPort, config.PeerNode, config.DstHost, config.DstPort)
isClient := false
// client side tid=0, assign random uint64
if tid == 0 {
@@ -377,10 +376,10 @@ func (pn *P2PNetwork) init() error {
pn.config.natType = NATSymmetric
}
if err != nil {
gLog.Println(LevelINFO, "detect NAT type error:", err)
gLog.Println(LevelDEBUG, "detect NAT type error:", err)
break
}
gLog.Println(LevelINFO, "detect NAT type:", pn.config.natType, " publicIP:", pn.config.publicIP)
gLog.Println(LevelDEBUG, "detect NAT type:", pn.config.natType, " publicIP:", pn.config.publicIP)
gatewayURL := fmt.Sprintf("%s:%d", pn.config.ServerHost, pn.config.ServerPort)
forwardPath := "/openp2p/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
@@ -392,12 +391,7 @@ func (pn *P2PNetwork) init() error {
q.Add("password", pn.config.Password)
q.Add("version", OpenP2PVersion)
q.Add("nattype", fmt.Sprintf("%d", pn.config.natType))
noShareStr := "false"
if pn.config.NoShare {
noShareStr = "true"
}
q.Add("noshare", noShareStr)
q.Add("sharebandwidth", fmt.Sprintf("%d", pn.config.ShareBandwidth))
u.RawQuery = q.Encode()
var ws *websocket.Conn
ws, _, err = websocket.DefaultDialer.Dial(u.String(), nil)
@@ -425,7 +419,7 @@ func (pn *P2PNetwork) init() error {
Version: OpenP2PVersion,
}
rsp := netInfo()
gLog.Println(LevelINFO, rsp)
gLog.Println(LevelDEBUG, "netinfo:", rsp)
if rsp != nil && rsp.Country != "" {
if len(rsp.IP) == net.IPv6len {
pn.config.ipv6 = rsp.IP.String()
@@ -434,7 +428,7 @@ func (pn *P2PNetwork) init() error {
req.NetInfo = *rsp
}
pn.write(MsgReport, MsgReportBasic, &req)
gLog.Println(LevelINFO, "P2PNetwork init ok")
gLog.Println(LevelDEBUG, "P2PNetwork init ok")
break
}
if err != nil {
@@ -472,7 +466,7 @@ func (pn *P2PNetwork) handleMessage(t int, msg []byte) {
case MsgHeartbeat:
gLog.Printf(LevelDEBUG, "P2PNetwork heartbeat ok")
case MsgPush:
pn.handlePush(head.SubType, msg)
handlePush(pn, head.SubType, msg)
default:
pn.msgMapMtx.Lock()
ch := pn.msgMap[0]
@@ -483,7 +477,7 @@ func (pn *P2PNetwork) handleMessage(t int, msg []byte) {
}
func (pn *P2PNetwork) readLoop() {
gLog.Printf(LevelINFO, "P2PNetwork readLoop start")
gLog.Printf(LevelDEBUG, "P2PNetwork readLoop start")
pn.wg.Add(1)
defer pn.wg.Done()
for pn.running {
@@ -497,7 +491,7 @@ func (pn *P2PNetwork) readLoop() {
}
pn.handleMessage(t, msg)
}
gLog.Printf(LevelINFO, "P2PNetwork readLoop end")
gLog.Printf(LevelDEBUG, "P2PNetwork readLoop end")
}
func (pn *P2PNetwork) write(mainType uint16, subType uint16, packet interface{}) error {
@@ -592,106 +586,12 @@ func (pn *P2PNetwork) read(node string, mainType uint16, subType uint16, timeout
}
}
func (pn *P2PNetwork) handlePush(subType uint16, msg []byte) error {
pushHead := PushHeader{}
err := binary.Read(bytes.NewReader(msg[openP2PHeaderSize:openP2PHeaderSize+PushHeaderSize]), binary.LittleEndian, &pushHead)
if err != nil {
return err
}
gLog.Printf(LevelDEBUG, "handle push msg type:%d, push header:%+v", subType, pushHead)
switch subType {
case MsgPushConnectReq:
req := PushConnectReq{}
err := json.Unmarshal(msg[openP2PHeaderSize+PushHeaderSize:], &req)
if err != nil {
gLog.Printf(LevelERROR, "wrong MsgPushConnectReq:%s", err)
return err
}
gLog.Printf(LevelINFO, "%s is connecting...", req.From)
gLog.Println(LevelDEBUG, "push connect response to ", req.From)
// verify token or name&password
if VerifyTOTP(req.Token, pn.config.User, pn.config.Password, time.Now().Unix()+(pn.serverTs-pn.localTs)) || // localTs may behind, auto adjust ts
VerifyTOTP(req.Token, pn.config.User, pn.config.Password, time.Now().Unix()) ||
(req.User == pn.config.User && req.Password == pn.config.Password) {
gLog.Printf(LevelINFO, "Access Granted\n")
config := AppConfig{}
config.peerNatType = req.NatType
config.peerConeNatPort = req.ConeNatPort
config.peerIP = req.FromIP
config.PeerNode = req.From
// share relay node will limit bandwidth
if req.User != pn.config.User || req.Password != pn.config.Password {
gLog.Printf(LevelINFO, "set share bandwidth %d mbps", pn.config.ShareBandwidth)
config.shareBandwidth = pn.config.ShareBandwidth
}
// go pn.AddTunnel(config, req.ID)
go pn.addDirectTunnel(config, req.ID)
break
}
gLog.Println(LevelERROR, "Access Denied:", req.From)
rsp := PushConnectRsp{
Error: 1,
Detail: fmt.Sprintf("connect to %s error: Access Denied", pn.config.Node),
To: req.From,
From: pn.config.Node,
}
pn.push(req.From, MsgPushConnectRsp, rsp)
case MsgPushRsp:
rsp := PushRsp{}
err := json.Unmarshal(msg[openP2PHeaderSize:], &rsp)
if err != nil {
gLog.Printf(LevelERROR, "wrong pushRsp:%s", err)
return err
}
if rsp.Error == 0 {
gLog.Printf(LevelDEBUG, "push ok, detail:%s", rsp.Detail)
} else {
gLog.Printf(LevelERROR, "push error:%d, detail:%s", rsp.Error, rsp.Detail)
}
case MsgPushAddRelayTunnelReq:
req := AddRelayTunnelReq{}
err := json.Unmarshal(msg[openP2PHeaderSize+PushHeaderSize:], &req)
if err != nil {
gLog.Printf(LevelERROR, "wrong RelayNodeRsp:%s", err)
return err
}
config := AppConfig{}
config.PeerNode = req.RelayName
config.peerToken = req.RelayToken
// set user password, maybe the relay node is your private node
config.PeerUser = pn.config.User
config.PeerPassword = pn.config.Password
go func(r AddRelayTunnelReq) {
t, errDt := pn.addDirectTunnel(config, 0)
if errDt == nil {
// notify peer relay ready
msg := TunnelMsg{ID: t.id}
pn.push(r.From, MsgPushAddRelayTunnelRsp, msg)
SaveKey(req.AppID, req.AppKey)
}
}(req)
case MsgPushUpdate:
update()
if gConf.daemonMode {
os.Exit(0)
}
default:
pn.msgMapMtx.Lock()
ch := pn.msgMap[pushHead.From]
pn.msgMapMtx.Unlock()
ch <- msg
}
return nil
}
func (pn *P2PNetwork) updateAppHeartbeat(appID uint64) {
pn.apps.Range(func(id, i interface{}) bool {
key := id.(uint64)
if key != appID {
app := i.(*p2pApp)
if app.id != appID {
return true
}
app := i.(*p2pApp)
app.updateHeartbeat()
return false
})

View File

@@ -52,7 +52,7 @@ func (t *P2PTunnel) init() {
}
func (t *P2PTunnel) connect() error {
gLog.Printf(LevelINFO, "start p2pTunnel to %s ", t.config.PeerNode)
gLog.Printf(LevelDEBUG, "start p2pTunnel to %s ", t.config.PeerNode)
t.isServer = false
req := PushConnectReq{
User: t.config.PeerUser,
@@ -144,7 +144,7 @@ func (t *P2PTunnel) handshake() error {
return err
}
}
gLog.Println(LevelINFO, "handshake to ", t.config.PeerNode)
gLog.Println(LevelDEBUG, "handshake to ", t.config.PeerNode)
var err error
// TODO: handle NATNone, nodes with public ip has no punching
if (t.pn.config.natType == NATCone && t.config.peerNatType == NATCone) || (t.pn.config.natType == NATNone || t.config.peerNatType == NATNone) {
@@ -163,7 +163,7 @@ func (t *P2PTunnel) handshake() error {
gLog.Println(LevelERROR, "punch handshake error:", err)
return err
}
gLog.Printf(LevelINFO, "handshake to %s ok", t.config.PeerNode)
gLog.Printf(LevelDEBUG, "handshake to %s ok", t.config.PeerNode)
err = t.run()
if err != nil {
gLog.Println(LevelERROR, err)
@@ -198,7 +198,7 @@ func (t *P2PTunnel) run() error {
gLog.Println(LevelDEBUG, string(buff))
}
qConn.WriteBytes(MsgP2P, MsgTunnelHandshakeAck, []byte("OpenP2P,hello2"))
gLog.Println(LevelINFO, "quic connection ok")
gLog.Println(LevelDEBUG, "quic connection ok")
t.conn = qConn
t.setRun(true)
go t.readLoop()
@@ -216,7 +216,7 @@ func (t *P2PTunnel) run() error {
}
}
t.pn.read(t.config.PeerNode, MsgPush, MsgPushQuicConnect, time.Second*5)
gLog.Println(LevelINFO, "quic dial to ", t.ra.String())
gLog.Println(LevelDEBUG, "quic dial to ", t.ra.String())
qConn, e := dialQuic(conn, t.ra, TunnelIdleTimeout)
if e != nil {
return fmt.Errorf("quic dial to %s error:%s", t.ra.String(), e)
@@ -233,7 +233,7 @@ func (t *P2PTunnel) run() error {
}
gLog.Println(LevelINFO, "rtt=", time.Since(handshakeBegin))
gLog.Println(LevelINFO, "quic connection ok")
gLog.Println(LevelDEBUG, "quic connection ok")
t.conn = qConn
t.setRun(true)
go t.readLoop()
@@ -243,7 +243,7 @@ func (t *P2PTunnel) run() error {
func (t *P2PTunnel) readLoop() {
decryptData := make([]byte, ReadBuffLen+PaddingSize) // 16 bytes for padding
gLog.Printf(LevelINFO, "%d tunnel readloop start", t.id)
gLog.Printf(LevelDEBUG, "%d tunnel readloop start", t.id)
for t.isRuning() {
t.conn.SetReadDeadline(time.Now().Add(TunnelIdleTimeout))
head, body, err := t.conn.ReadMessage()
@@ -333,7 +333,7 @@ func (t *P2PTunnel) readLoop() {
}
overlayID := req.ID
gLog.Printf(LevelINFO, "App:%d overlayID:%d connect %+v", req.AppID, overlayID, req)
gLog.Printf(LevelDEBUG, "App:%d overlayID:%d connect %+v", req.AppID, overlayID, req)
if req.Protocol == "tcp" {
conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", req.DstIP, req.DstPort), time.Second*5)
if err != nil {
@@ -368,7 +368,7 @@ func (t *P2PTunnel) readLoop() {
continue
}
overlayID := req.ID
gLog.Printf(LevelINFO, "%d disconnect overlay connection %d", t.id, overlayID)
gLog.Printf(LevelDEBUG, "%d disconnect overlay connection %d", t.id, overlayID)
i, ok := t.overlayConns.Load(overlayID)
if ok {
otcp := i.(*overlayTCP)
@@ -379,13 +379,13 @@ func (t *P2PTunnel) readLoop() {
}
t.setRun(false)
t.conn.Close()
gLog.Printf(LevelINFO, "%d tunnel readloop end", t.id)
gLog.Printf(LevelDEBUG, "%d tunnel readloop end", t.id)
}
func (t *P2PTunnel) writeLoop() {
tc := time.NewTicker(TunnelHeartbeatTime)
defer tc.Stop()
defer gLog.Printf(LevelINFO, "%d tunnel writeloop end", t.id)
defer gLog.Printf(LevelDEBUG, "%d tunnel writeloop end", t.id)
for t.isRuning() {
select {
case <-tc.C:
@@ -402,7 +402,7 @@ func (t *P2PTunnel) writeLoop() {
}
func (t *P2PTunnel) listen() error {
gLog.Printf(LevelINFO, "p2ptunnel wait for connecting")
gLog.Printf(LevelDEBUG, "p2ptunnel wait for connecting")
t.isServer = true
return t.handshake()
}

View File

@@ -10,7 +10,7 @@ import (
"time"
)
const OpenP2PVersion = "0.97.1"
const OpenP2PVersion = "0.99.0"
const ProducnName string = "openp2p"
type openP2PHeader struct {
@@ -79,6 +79,7 @@ const (
MsgPushUpdate = 6
MsgPushReportApps = 7
MsgPushQuicConnect = 8
MsgPushEditApp = 9
)
// MsgP2P sub type message
@@ -109,6 +110,7 @@ const (
MsgReportBasic = iota
MsgReportQuery
MsgReportConnect
MsgReportApps
)
const (
@@ -128,6 +130,7 @@ const (
RetryInterval = time.Second * 30
PublicIPEchoTimeout = time.Second * 3
NatTestTimeout = time.Second * 10
ClientAPITimeout = time.Second * 10
)
// NATNone has public ip
@@ -135,6 +138,7 @@ const (
NATNone = 0
NATCone = 1
NATSymmetric = 2
NATUnknown = 314
)
func newMessage(mainType uint16, subType uint16, packet interface{}) ([]byte, error) {
@@ -271,6 +275,31 @@ type ReportConnect struct {
Version string `json:"version,omitempty"`
}
type AppInfo struct {
AppName string `json:"appName,omitempty"`
Error string `json:"error,omitempty"`
Protocol string `json:"protocol,omitempty"`
SrcPort int `json:"srcPort,omitempty"`
Protocol0 string `json:"protocol0,omitempty"`
SrcPort0 int `json:"srcPort0,omitempty"`
NatType int `json:"natType,omitempty"`
PeerNode string `json:"peerNode,omitempty"`
DstPort int `json:"dstPort,omitempty"`
DstHost string `json:"dstHost,omitempty"`
PeerUser string `json:"peerUser,omitempty"`
PeerNatType int `json:"peerNatType,omitempty"`
PeerIP string `json:"peerIP,omitempty"`
ShareBandwidth int `json:"shareBandWidth,omitempty"`
RelayNode string `json:"relayNode,omitempty"`
Version string `json:"version,omitempty"`
RetryTime string `json:"retryTime,omitempty"`
IsActive int `json:"isActive,omitempty"`
}
type ReportApps struct {
Apps []AppInfo
}
type UpdateInfo struct {
Error int `json:"error,omitempty"`
ErrorDetail string `json:"errorDetail,omitempty"`

View File

@@ -16,18 +16,9 @@ import (
"time"
)
// type updateFileInfo struct {
// Name string `json:"name,omitempty"`
// RelativePath string `json:"relativePath,omitempty"`
// Length int64 `json:"length,omitempty"`
// URL string `json:"url,omitempty"`
// Hash string `json:"hash,omitempty"`
// }
func update() {
gLog.Println(LevelINFO, "update start")
defer gLog.Println(LevelINFO, "update end")
// TODO: download from gitee. save flow
c := http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
@@ -61,7 +52,6 @@ func update() {
gLog.Println(LevelERROR, "update error:", updateInfo.Error, updateInfo.ErrorDetail)
return
}
os.MkdirAll("download", 0666)
err = updateFile(updateInfo.Url, "", "openp2p")
if err != nil {
gLog.Println(LevelERROR, "update: download failed:", err)
@@ -112,6 +102,7 @@ func updateFile(url string, checksum string, dst string) error {
os.Rename(os.Args[0]+"0", os.Args[0])
return err
}
os.Remove(tmpFile)
return nil
}
@@ -133,11 +124,6 @@ func unzip(dst, src string) (err error) {
for _, f := range archive.File {
filePath := filepath.Join(dst, f.Name)
fmt.Println("unzipping file ", filePath)
// if !strings.HasPrefix(filePath, filepath.Clean(dst)+string(os.PathSeparator)) {
// fmt.Println("invalid file path")
// return
// }
if f.FileInfo().IsDir() {
fmt.Println("creating directory...")
os.MkdirAll(filePath, os.ModePerm)