From f12059d889dd84c87f5181597e5a60680b89bab8 Mon Sep 17 00:00:00 2001 From: TenderIronh Date: Thu, 9 Dec 2021 18:54:46 +0800 Subject: [PATCH] install mode and improve relay --- README-ZH.md | 8 ++- README.md | 5 +- USAGE-ZH.md | 50 ++++++++----- USAGE.md | 51 ++++++++----- config.go | 9 +-- daemon.go | 182 ++++++++++++++++++++++++++++++++++++++++++++++- go.mod | 1 + log.go | 21 ++---- nat.go | 21 +++--- openp2p.go | 16 +++-- p2pnetwork.go | 11 ++- p2ptunnel.go | 2 +- protocol.go | 6 +- sysinfodarwin.go | 5 ++ sysinfolinux.go | 5 ++ sysinfowin.go | 5 ++ 16 files changed, 309 insertions(+), 89 deletions(-) diff --git a/README-ZH.md b/README-ZH.md index 6d66a0b..85efc7b 100644 --- a/README-ZH.md +++ b/README-ZH.md @@ -20,12 +20,16 @@ P2P直连可以让你的设备跑满带宽。不论你的设备在任何网络 基于OpenP2P只需数行代码,就能让原来只能局域网通信的程序,变成任何内网都能通信 ## 快速入门 + +> :warning: 本文所有命令, Windows环境使用"openp2p.exe", Linux环境使用"./openp2p" + + 以一个最常见的例子说明OpenP2P如何使用:远程办公,在家里连入办公室Windows电脑。 相信很多人在疫情下远程办公是刚需。 1. 先确认办公室电脑已开启远程桌面功能(如何开启参考官方说明https://docs.microsoft.com/zh-cn/windows-server/remote/remote-desktop-services/clients/remote-desktop-allow-access) 2. 在办公室下载最新的[OpenP2P](https://gitee.com/tenderiron/openp2p/releases/),解压出来,在命令行执行 ``` - openp2p.exe -d -node OFFICEPC1 -user USERNAME1 -password PASSWORD1 + openp2p.exe install -node OFFICEPC1 -user USERNAME1 -password PASSWORD1 ``` > :warning: **切记将标记大写的参数改成自己的** @@ -114,7 +118,7 @@ TODO或ISSUE里如果有你擅长的领域,或者你有特别好的主意, 它是一个中国人发起的项目,更懂国内网络环境,更懂用户需求,更好的企业级支持 ## 技术交流 QQ群:16947733 -邮箱:openp2p.cn@gmail.com 271357901@qq.com +邮箱:openp2p.cn@gmail.com tenderiron@139.com ## 免责声明 本项目开源供大家学习和免费使用,禁止用于非法用途,任何不当使用本项目或意外造成的损失,本项目及相关人员不会承担任何责任。 diff --git a/README.md b/README.md index 55a885c..37780ab 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,9 @@ Your applicaiton can call OpenP2P with a few code to make any internal networks A common scenario to introduce OpenP2P: remote work. At home connects to office's Linux PC . Under the outbreak of covid-19 pandemic, surely remote work becomes a fundamental demand. +> :warning: all commands in this doc, Windows env uses "openp2p.exe", Linux env uses "./openp2p" + + 1. Make sure your office device(Linux) has opened the access of ssh. ``` netstat -nl | grep 22 @@ -36,7 +39,7 @@ Under the outbreak of covid-19 pandemic, surely remote work becomes a fundamenta 2. Download the latest version of [OpenP2P](https://github.com/openp2p-cn/openp2p/releases),unzip the downloaded package, and execute below command line. ``` tar xvf openp2p0.95.3.linux-amd64.tar.gz - openp2p -d -node OFFICEPC1 -user USERNAME1 -password PASSWORD1 + ./openp2p install -node OFFICEPC1 -user USERNAME1 -password PASSWORD1 ``` > :warning: **Must change the parameters marked in uppercase to your own** diff --git a/USAGE-ZH.md b/USAGE-ZH.md index f3accf0..2d39f0b 100644 --- a/USAGE-ZH.md +++ b/USAGE-ZH.md @@ -1,33 +1,42 @@ # 详细运行参数说明 +> :warning: 本文所有命令, Windows环境使用"openp2p.exe", Linux环境使用"./openp2p" -## 监听 + +## 安装和监听 ``` -openp2p.exe -d -node OFFICEPC1 -user USERNAME1 -password PASSWORD1 +./openp2p install -node OFFICEPC1 -user USERNAME1 -password PASSWORD1 +或 +./openp2p -d -node OFFICEPC1 -user USERNAME1 -password PASSWORD1 +# 注意Windows系统把“./openp2p” 换成“openp2p.exe” ``` ->* -d daemon模式,推荐使用。发现worker进程意外退出就会自动启动新的worker进程 ->* -node 独一无二的节点名字,唯一标识 ->* -user 独一无二的用户名字,该节点属于这个user ->* -password 密码 ->* -sharebandwidth 作为共享节点时提供带宽,默认10mbps. 如果是光纤大带宽,设置越大效果越好 ->* -loglevel 需要查看更多调试日志,设置0;默认是1 ->* -noshare 不共享,该节点只在私有的P2P网络使用。不加入共享的P2P网络,这样也意味着无法使用别人的共享节点 +>* install: 安装模式【推荐】,会安装成系统服务,这样它就能随系统自动启动 +>* -d: daemon模式。发现worker进程意外退出就会自动启动新的worker进程 +>* -node: 独一无二的节点名字,唯一标识 +>* -user: 独一无二的用户名字,该节点属于这个user +>* -password: 密码 +>* -sharebandwidth: 作为共享节点时提供带宽,默认10mbps. 如果是光纤大带宽,设置越大效果越好 +>* -loglevel: 需要查看更多调试日志,设置0;默认是1 +>* -noshare: 不共享,该节点只在私有的P2P网络使用。不加入共享的P2P网络,这样也意味着无法使用别人的共享节点 ## 连接 ``` -openp2p.exe -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 -peernode OFFICEPC1 -dstip 127.0.0.1 -dstport 3389 -srcport 23389 -protocol tcp +使用配置文件,建立多个P2PApp +./openp2p -d -f +./openp2p -f ``` ->* -peernode 目标节点名字 ->* -dstip 目标服务地址,默认本机127.0.0.1 ->* -dstport 目标服务端口,常见的如windows远程桌面3389,Linux ssh 22 ->* -protocol 目标服务协议 tcp、udp ->* -peeruser 目标用户,如果是同一个用户下的节点,则无需设置 ->* -peerpassword 目标密码,如果是同一个用户下的节点,则无需设置 ->* -f 配置文件,如果希望配置多个P2PApp参考[config.json](/config.json) +>* -peernode: 目标节点名字 +>* -dstip: 目标服务地址,默认本机127.0.0.1 +>* -dstport: 目标服务端口,常见的如windows远程桌面3389,Linux ssh 22 +>* -protocol: 目标服务协议 tcp、udp +>* -peeruser: 目标用户,如果是同一个用户下的节点,则无需设置 +>* -peerpassword: 目标密码,如果是同一个用户下的节点,则无需设置 +>* -f: 配置文件,如果希望配置多个P2PApp参考[config.json](/config.json) ## 升级客户端 ``` # update local client -openp2p update +./openp2p update # update remote client curl --insecure 'https://openp2p.cn:27182/api/v1/device/YOUR-NODE-NAME/update?user=&password=' ``` @@ -38,4 +47,9 @@ Linux系统(Ubuntu和CentOS7)的防火墙默认配置均不会有影响, systemctl stop firewalld.service systemctl start firewalld.service firewall-cmd --state +``` + +## 卸载 +``` +./openp2p uninstall ``` \ No newline at end of file diff --git a/USAGE.md b/USAGE.md index e31c597..9d38b48 100644 --- a/USAGE.md +++ b/USAGE.md @@ -1,33 +1,43 @@ # Parameters details -## Listen +> :warning: all commands in this doc, Windows env uses "openp2p.exe", Linux env uses "./openp2p" + + +## Install and Listen ``` -openp2p.exe -d -node OFFICEPC1 -user USERNAME1 -password PASSWORD1 +./openp2p install -node OFFICEPC1 -user USERNAME1 -password PASSWORD1 +Or +./openp2p -d -node OFFICEPC1 -user USERNAME1 -password PASSWORD1 + ``` ->* -d daemon mode is recommand. When the worker process is found to exit unexpectedly, a new worker process will be automatically started ->* -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 ->* -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 people’s shared nodes +>* install: [recommand] will install as system service. So it will autorun when system booting. +>* -d: daemon mode run once. When the worker process is found to exit unexpectedly, a new worker process will be automatically started +>* -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 +>* -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 people’s shared nodes ## Connect ``` -openp2p.exe -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 -peernode OFFICEPC1 -dstip 127.0.0.1 -dstport 3389 -srcport 23389 -protocol tcp +Create multiple P2PApp by config file +./openp2p -d -f +./openp2p -f ``` ->* -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) +>* -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) ## Client update ``` # update local client -openp2p update +./openp2p update # update remote client curl --insecure 'https://openp2p.cn:27182/api/v1/device/YOUR-NODE-NAME/update?user=&password=' ``` @@ -38,4 +48,9 @@ The default firewall configuration of Linux system (Ubuntu and CentOS7) will not systemctl stop firewalld.service systemctl start firewalld.service firewall-cmd --state +``` + +## Uninstall +``` +./openp2p uninstall ``` \ No newline at end of file diff --git a/config.go b/config.go index 3f220ec..bc3a72c 100644 --- a/config.go +++ b/config.go @@ -27,6 +27,7 @@ type AppConfig struct { shareBandwidth int } +// TODO: add loglevel, maxlogfilesize type Config struct { Network NetworkConfig `json:"network"` Apps []AppConfig `json:"apps"` @@ -45,10 +46,10 @@ func (c *Config) add(app AppConfig) { c.Apps = append(c.Apps, app) } -// func (c *Config) save() { -// data, _ := json.MarshalIndent(c, "", "") -// ioutil.WriteFile("config.json", data, 0644) -// } +func (c *Config) save() { + data, _ := json.MarshalIndent(c, "", "") + ioutil.WriteFile("config.json", data, 0644) +} func (c *Config) load() error { data, err := ioutil.ReadFile("config.json") diff --git a/daemon.go b/daemon.go index f767af9..81c7e38 100644 --- a/daemon.go +++ b/daemon.go @@ -1,16 +1,60 @@ package main import ( + "flag" + "fmt" + "io" "os" + "path/filepath" "time" + + "github.com/kardianos/service" ) type daemon struct { + running bool + proc *os.Process +} + +func (d *daemon) Start(s service.Service) error { + gLog.Println(LevelINFO, "daemon start") + return nil +} + +func (d *daemon) Stop(s service.Service) error { + gLog.Println(LevelINFO, "service stop") + d.running = false + if d.proc != nil { + gLog.Println(LevelINFO, "stop worker") + d.proc.Kill() + } + if service.Interactive() { + gLog.Println(LevelINFO, "stop daemon") + os.Exit(0) + } + return nil } func (d *daemon) run() { - gLog.Println(LevelINFO, "daemon start") - defer gLog.Println(LevelINFO, "daemon end") + 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() + if err != nil { + fmt.Println(err) + } + gLog.Println(LevelINFO, mydir) + conf := &service.Config{ + Name: ProducnName, + DisplayName: ProducnName, + Description: ProducnName, + Executable: binPath, + } + + s, _ := service.New(d, conf) + go s.Run() var args []string // rm -d parameter for i := 0; i < len(os.Args); i++ { @@ -24,13 +68,145 @@ func (d *daemon) run() { // start worker gLog.Println(LevelINFO, "start worker process") execSpec := &os.ProcAttr{Files: []*os.File{os.Stdin, os.Stdout, os.Stderr}} - p, err := os.StartProcess(os.Args[0], args, execSpec) + p, err := os.StartProcess(binPath, args, execSpec) if err != nil { gLog.Printf(LevelERROR, "start worker error:%s", err) return } + d.proc = p _, _ = p.Wait() + if !d.running { + return + } gLog.Printf(LevelERROR, "worker stop, restart it after 10s") time.Sleep(time.Second * 10) } } + +func (d *daemon) Control(ctrlComm string, exeAbsPath string, args []string) error { + svcConfig := &service.Config{ + Name: ProducnName, + DisplayName: ProducnName, + Description: ProducnName, + Executable: exeAbsPath, + Arguments: args, + } + + s, e := service.New(d, svcConfig) + if e != nil { + return e + } + e = service.Control(s, ctrlComm) + if e != nil { + return e + } + + return nil +} + +// examples: +// listen: +// ./openp2p install -node hhd1207-222 -user tenderiron -password 13760636579 -noshare +// 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 +func install() { + gLog = InitLogger(filepath.Dir(os.Args[0]), "openp2p-install", LevelDEBUG, 1024*1024, LogConsole) + // save config file + installFlag := flag.NewFlagSet("install", flag.ExitOnError) + serverHost := installFlag.String("serverhost", "api.openp2p.cn", "server host ") + // serverHost := flag.String("serverhost", "127.0.0.1", "server host ") // for debug + user := installFlag.String("user", "", "user name. 8-31 characters") + node := installFlag.String("node", "", "node name. 8-31 characters") + password := installFlag.String("password", "", "user password. 8-31 characters") + peerNode := installFlag.String("peernode", "", "peer node name that you want to connect") + peerUser := installFlag.String("peeruser", "", "peer node user (default peeruser=user)") + peerPassword := installFlag.String("peerpassword", "", "peer node password (default peerpassword=password)") + dstIP := installFlag.String("dstip", "127.0.0.1", "destination ip ") + 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") + 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") + installFlag.Parse(os.Args[2:]) + + // copy files + os.MkdirAll(defaultInstallPath, 0775) + targetPath := filepath.Join(defaultInstallPath, defaultBinName) + binPath, _ := os.Executable() + src, errFiles := os.Open(binPath) // can not use args[0], on Windows call openp2p is ok(=openp2p.exe) + if errFiles != nil { + gLog.Printf(LevelERROR, "os.OpenFile %s error:%s", os.Args[0], errFiles) + return + } + + dst, errFiles := os.OpenFile(targetPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0775) + if errFiles != nil { + gLog.Printf(LevelERROR, "os.OpenFile %s error:%s", targetPath, errFiles) + return + } + + _, errFiles = io.Copy(dst, src) + if errFiles != nil { + gLog.Printf(LevelERROR, "io.Copy error:%s", errFiles) + return + } + src.Close() + dst.Close() + gConf.Network.ServerHost = *serverHost + gConf.Network.User = *user + gConf.Network.Node = *node + gConf.Network.Password = *password + 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 + config.PeerUser = *peerUser + config.PeerPassword = *peerPassword + config.DstHost = *dstIP + config.DstPort = *dstPort + config.SrcPort = *srcPort + config.Protocol = *protocol + gConf.add(config) + // TODO other params + os.Chdir(defaultInstallPath) + gConf.save() + + // install system service + d := daemon{} + + // args := []string{""} + gLog.Println(LevelINFO, "targetPath:", targetPath) + err := d.Control("install", targetPath, []string{"-d", "-f"}) + 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"}) + if err != nil { + gLog.Println(LevelERROR, "start openp2p service error:", err) + } else { + gLog.Println(LevelINFO, "start openp2p service ok.") + } +} + +func uninstall() { + gLog = InitLogger(filepath.Dir(os.Args[0]), "openp2p-install", LevelDEBUG, 1024*1024, LogFileAndConsole) + d := daemon{} + d.Control("stop", "", nil) + err := d.Control("uninstall", "", nil) + if err != nil { + gLog.Println(LevelERROR, "uninstall system service error:", err) + } else { + gLog.Println(LevelINFO, "uninstall system service ok.") + } + binPath := filepath.Join(defaultInstallPath, defaultBinName) + os.Remove(binPath + "0") + os.Rename(binPath, binPath+"0") + os.RemoveAll(defaultInstallPath) +} diff --git a/go.mod b/go.mod index fc5c46d..58de87e 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.16 require ( github.com/gorilla/websocket v1.4.2 + github.com/kardianos/service v1.2.0 github.com/lucas-clemente/quic-go v0.24.0 golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34 ) diff --git a/log.go b/log.go index ba2a1e9..6295ea9 100644 --- a/log.go +++ b/log.go @@ -1,7 +1,6 @@ package main import ( - "fmt" "log" "os" "runtime" @@ -55,7 +54,6 @@ type V8log struct { stoped bool lineEnding string pid int - lastError string maxLogSize int64 mode int } @@ -89,7 +87,7 @@ func InitLogger(path string, filePrefix string, level LogLevel, maxLogSize int64 } else { le = "\n" } - pLog := &V8log{logger, openedfile, level, make(chan bool, 10), logdir, &sync.Mutex{}, false, le, os.Getpid(), "", maxLogSize, mode} + pLog := &V8log{logger, openedfile, level, make(chan bool, 10), logdir, &sync.Mutex{}, false, le, os.Getpid(), maxLogSize, mode} go pLog.checkFile() return pLog } @@ -155,15 +153,11 @@ func (vl *V8log) Printf(level LogLevel, format string, params ...interface{}) { if level < vl.llevel { return } - if level == LevelERROR { - vl.lastError = fmt.Sprintf(format, params...) - } pidAndLevel := []interface{}{vl.pid, loglevel[level]} params = append(pidAndLevel, params...) if vl.mode == LogFile || vl.mode == LogFileAndConsole { vl.loggers[0].Printf("%d %s "+format+vl.lineEnding, params...) } - if vl.mode == LogConsole || vl.mode == LogFileAndConsole { log.Printf("%d %s "+format+vl.lineEnding, params...) } @@ -179,20 +173,13 @@ func (vl *V8log) Println(level LogLevel, params ...interface{}) { if level < vl.llevel { return } - if level == LevelERROR { - vl.lastError = fmt.Sprint(params...) - } pidAndLevel := []interface{}{vl.pid, " ", loglevel[level], " "} params = append(pidAndLevel, params...) params = append(params, vl.lineEnding) - vl.loggers[0].Print(params...) + if vl.mode == LogFile || vl.mode == LogFileAndConsole { + vl.loggers[0].Print(params...) + } if vl.mode == LogConsole || vl.mode == LogFileAndConsole { log.Print(params...) } } - -func (vl *V8log) getLastError() string { - vl.mtx.Lock() - defer vl.mtx.Unlock() - return vl.lastError -} diff --git a/nat.go b/nat.go index a00a69d..3ebbe8b 100644 --- a/nat.go +++ b/nat.go @@ -8,7 +8,7 @@ import ( "time" ) -func natTest(serverHost string, serverPort int, localPort int) (publicIP string, isPublicIP int, publicPort int, err error) { +func natTest(serverHost string, serverPort int, localPort int, echoPort int) (publicIP string, isPublicIP int, publicPort int, err error) { conn, err := net.ListenPacket("udp", fmt.Sprintf(":%d", localPort)) if err != nil { return "", 0, 0, err @@ -21,7 +21,7 @@ func natTest(serverHost string, serverPort int, localPort int) (publicIP string, } // The connection can write data to the desired address. - msg, err := newMessage(MsgNATDetect, 0, &NatDetectReq{SrcPort: localPort, EchoPort: EchoPort}) + msg, err := newMessage(MsgNATDetect, 0, &NatDetectReq{SrcPort: localPort, EchoPort: echoPort}) _, err = conn.WriteTo(msg, dst) if err != nil { return "", 0, 0, err @@ -44,9 +44,10 @@ func natTest(serverHost string, serverPort int, localPort int) (publicIP string, func getNATType(host string, udp1 int, udp2 int) (publicIP string, NATType int, err error) { // the random local port may be used by other. - go echo() localPort := int(rand.Uint32()%10000 + 50000) - ip1, isPublicIP, port1, err := natTest(host, udp1, localPort) + echoPort := int(rand.Uint32()%10000 + 50000) + go echo(echoPort) + ip1, isPublicIP, port1, err := natTest(host, udp1, localPort, echoPort) gLog.Printf(LevelDEBUG, "local port:%d nat port:%d", localPort, port1) if err != nil { return "", 0, err @@ -54,7 +55,7 @@ func getNATType(host string, udp1 int, udp2 int) (publicIP string, NATType int, if isPublicIP == 1 { return ip1, NATNone, nil } - ip2, _, port2, err := natTest(host, udp2, localPort) + ip2, _, port2, err := natTest(host, udp2, localPort, 0) // 2rd nat test not need testing publicip gLog.Printf(LevelDEBUG, "local port:%d nat port:%d", localPort, port2) if err != nil { return "", 0, err @@ -70,14 +71,8 @@ func getNATType(host string, udp1 int, udp2 int) (publicIP string, NATType int, return ip1, natType, nil } -const ( - UDPPort1 = 27182 - UDPPort2 = 27183 - EchoPort = 31415 -) - -func echo() { - conn, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.IPv4zero, Port: EchoPort}) +func echo(echoPort int) { + conn, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.IPv4zero, Port: echoPort}) if err != nil { gLog.Println(LevelERROR, "echo server listen error:", err) return diff --git a/openp2p.go b/openp2p.go index 3e14bc8..27e2d68 100644 --- a/openp2p.go +++ b/openp2p.go @@ -11,6 +11,7 @@ import ( func main() { rand.Seed(time.Now().UnixNano()) + // 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") if len(os.Args) > 1 { @@ -19,12 +20,19 @@ func main() { fmt.Println(OpenP2PVersion) return case "update": - gLog = InitLogger(filepath.Dir(os.Args[0]), "openp2p", LevelDEBUG, 1024*1024, LogConsole) + gLog = InitLogger(filepath.Dir(os.Args[0]), "openp2p", LevelDEBUG, 1024*1024, LogFileAndConsole) update() return + case "install": + install() + return + case "uninstall": + uninstall() + return } } - + serverHost := flag.String("serverhost", "api.openp2p.cn", "server host ") + // serverHost := flag.String("serverhost", "127.0.0.1", "server host ") // for debug user := flag.String("user", "", "user name. 8-31 characters") node := flag.String("node", "", "node name. 8-31 characters") password := flag.String("password", "", "user password. 8-31 characters") @@ -32,8 +40,6 @@ func main() { peerUser := flag.String("peeruser", "", "peer node user (default peeruser=user)") peerPassword := flag.String("peerpassword", "", "peer node password (default peerpassword=password)") dstIP := flag.String("dstip", "127.0.0.1", "destination ip ") - serverHost := flag.String("serverhost", "openp2p.cn", "server host ") - // serverHost := flag.String("serverhost", "127.0.0.1", "server host ") // for debug dstPort := flag.Int("dstport", 0, "destination port ") srcPort := flag.Int("srcport", 0, "source port ") protocol := flag.String("protocol", "tcp", "tcp or udp") @@ -44,7 +50,7 @@ func main() { byDaemon := flag.Bool("bydaemon", false, "start by daemon") 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, LogConsole) + gLog = InitLogger(filepath.Dir(os.Args[0]), "openp2p", LogLevel(*logLevel), 1024*1024, LogFileAndConsole) gLog.Println(LevelINFO, "openp2p start. version: ", OpenP2PVersion) if *daemonMode { d := daemon{} diff --git a/p2pnetwork.go b/p2pnetwork.go index bdc89a7..58f4bef 100644 --- a/p2pnetwork.go +++ b/p2pnetwork.go @@ -146,7 +146,7 @@ func (pn *P2PNetwork) autoReconnectApp() { func (pn *P2PNetwork) addRelayTunnel(config AppConfig, appid uint64, appkey uint64) (*P2PTunnel, uint64, error) { gLog.Printf(LevelINFO, "addRelayTunnel to %s start", config.PeerNode) defer gLog.Printf(LevelINFO, "addRelayTunnel to %s end", config.PeerNode) - pn.write(MsgRelay, MsgRelayNodeReq, nil) + pn.write(MsgRelay, MsgRelayNodeReq, &RelayNodeReq{config.PeerNode}) head, body := pn.read("", MsgRelay, MsgRelayNodeRsp, time.Second*10) if head == nil { return nil, 0, errors.New("read MsgRelayNodeRsp error") @@ -254,9 +254,6 @@ func (pn *P2PNetwork) AddApp(config AppConfig) error { Version: OpenP2PVersion, } pn.write(MsgReport, MsgReportConnect, &req) - if err != nil { - return err - } app := p2pApp{ id: appID, @@ -266,7 +263,9 @@ func (pn *P2PNetwork) AddApp(config AppConfig) error { rtid: rtid, hbTime: time.Now()} pn.apps.Store(appID, &app) - go app.listen() + if err == nil { + go app.listen() + } return err } @@ -373,7 +372,7 @@ func (pn *P2PNetwork) init() error { // detect nat type pn.config.publicIP, pn.config.natType, err = getNATType(pn.config.ServerHost, pn.config.UDPPort1, pn.config.UDPPort2) // TODO rm test s2s - if pn.config.Node == "hhd1207-222S2S" { + if strings.Contains(pn.config.Node, "openp2pS2STest") { pn.config.natType = NATSymmetric } if err != nil { diff --git a/p2ptunnel.go b/p2ptunnel.go index 18fca56..794bbcd 100644 --- a/p2ptunnel.go +++ b/p2ptunnel.go @@ -39,7 +39,7 @@ func (t *P2PTunnel) init() { localPort := int(rand.Uint32()%10000 + 50000) if t.pn.config.natType == NATCone { // prepare one random cone hole - _, _, port1, _ := natTest(t.pn.config.ServerHost, t.pn.config.UDPPort1, localPort) + _, _, port1, _ := natTest(t.pn.config.ServerHost, t.pn.config.UDPPort1, localPort, 0) t.coneLocalPort = localPort t.coneNatPort = port1 t.la = &net.UDPAddr{IP: net.ParseIP(t.pn.config.localIP), Port: t.coneLocalPort} diff --git a/protocol.go b/protocol.go index 4cc575f..d59abf8 100644 --- a/protocol.go +++ b/protocol.go @@ -11,7 +11,7 @@ import ( "time" ) -const OpenP2PVersion = "0.95.5" +const OpenP2PVersion = "0.96.0" const ProducnName string = "openp2p" type openP2PHeader struct { @@ -233,6 +233,10 @@ type TunnelMsg struct { ID uint64 `json:"id,omitempty"` } +type RelayNodeReq struct { + PeerNode string `json:"peerNode,omitempty"` +} + type RelayNodeRsp struct { RelayName string `json:"relayName,omitempty"` RelayToken uint64 `json:"relayToken,omitempty"` diff --git a/sysinfodarwin.go b/sysinfodarwin.go index 5a11b6e..3054fb8 100644 --- a/sysinfodarwin.go +++ b/sysinfodarwin.go @@ -8,6 +8,11 @@ import ( "syscall" ) +const ( + defaultInstallPath = "/usr/local/openp2p" + defaultBinName = "openp2p" +) + func getOsName() (osName string) { output := execOutput("sw_vers", "-productVersion") osName = "Mac OS X " + strings.TrimSpace(output) diff --git a/sysinfolinux.go b/sysinfolinux.go index 3a6e8c6..686b7c0 100644 --- a/sysinfolinux.go +++ b/sysinfolinux.go @@ -12,6 +12,11 @@ import ( "syscall" ) +const ( + defaultInstallPath = "/usr/local/openp2p" + defaultBinName = "openp2p" +) + func getOsName() (osName string) { var sysnamePath string sysnamePath = "/etc/redhat-release" diff --git a/sysinfowin.go b/sysinfowin.go index 1779fa8..c8c99c1 100644 --- a/sysinfowin.go +++ b/sysinfowin.go @@ -13,6 +13,11 @@ import ( "golang.org/x/sys/windows/registry" ) +const ( + defaultInstallPath = "C:\\Program Files\\OpenP2P" + defaultBinName = "openp2p.exe" +) + func getOsName() (osName string) { k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE|registry.WOW64_64KEY) if err != nil {