Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3653ec19cd | ||
|
|
c733a2a4a1 | ||
|
|
b54fa2c6be |
@@ -1,7 +1,8 @@
|
||||
# [English](/README.md)|中文
|
||||
网站: [openp2p.cn](https://openp2p.cn)
|
||||
## OpenP2P是什么
|
||||
它是一个开源、免费、轻量级的P2P共享网络。任何设备接入OpenP2P,随时随地访问它们。相比BT网络用来共享文件,OpenP2P网络用来共享带宽。
|
||||
它是一个开源、免费、轻量级的P2P共享网络。你的设备将组成一个私有P2P网络,里面的设备可以直接访问其它成员,或者通过其它成员转发数据间接访问。如果私有网络无法完成通信,将会到公有P2P网络寻找共享节点协助通信。
|
||||
相比BT网络用来共享文件,OpenP2P网络用来共享带宽。
|
||||
我们的目标是:充分利用带宽,利用共享节点转发数据,建设一个远程连接的通用基础设施。
|
||||
|
||||
## 为什么选择OpenP2P
|
||||
@@ -39,11 +40,6 @@ P2P直连可以让你的设备跑满带宽。不论你的设备在任何网络
|
||||
|
||||

|
||||
|
||||
Windows默认会阻止没有花钱买它家证书签名过的程序,选择“仍要运行”即可。
|
||||
|
||||

|
||||
|
||||

|
||||
### 3.新建P2P应用
|
||||
|
||||

|
||||
|
||||
24
README.md
@@ -1,7 +1,8 @@
|
||||
# English|[中文](/README-ZH.md)
|
||||
Website: [openp2p.cn](https://openp2p.cn)
|
||||
## What is OpenP2P
|
||||
It is an open source, free, and lightweight P2P sharing network. As long as any device joins in, you can access them anywhere. Compared with the BT network used to share files, the OpenP2P network is used to share bandwidth.
|
||||
It is an open source, free, and lightweight P2P sharing network. Your devices will form a private P2P network, in which devices can directly access other members, or indirectly access through other members forwarding data.
|
||||
If the private network cannot complete the communication, it will go to the public P2P network to find a shared node to assist in the communication. Compared with the BT network used to share files, the OpenP2P network is used to share bandwidth.
|
||||
Our goal is to make full use of bandwidth, use shared nodes to relay data, and build a common infrastructure for remote connections.
|
||||
## Why OpenP2P
|
||||
### 1. Free
|
||||
@@ -36,35 +37,30 @@ Here's an example of remote work: connecting to an office Windows computer at ho
|
||||
### 1.Register
|
||||
Go to <https://console.openp2p.cn> register a new user
|
||||
|
||||

|
||||

|
||||
### 2.Install
|
||||
Download on local and remote computers and double-click to run, one-click installation
|
||||
|
||||

|
||||

|
||||
|
||||
By default, Windows will block programs that have not been signed by the Microsoft's certificate, and you can select "Run anyway".
|
||||
|
||||

|
||||
|
||||

|
||||
### 3.New P2PApp
|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||
### 4.Use P2PApp
|
||||
You can see the P2P application you just created on the "MyHomePC" device, just connect to the "local listening port" shown in the figure below.
|
||||
|
||||

|
||||

|
||||
|
||||
On MyHomePC, press Win+R and enter MSTSC to open the remote desktop, input `127.0.0.1:23389 /admin`
|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
10
USAGE-ZH.md
@@ -14,9 +14,15 @@
|
||||
>* -d: daemon模式。发现worker进程意外退出就会自动启动新的worker进程
|
||||
>* -node: 独一无二的节点名字,唯一标识
|
||||
>* -token: 在<console.openp2p.cn>“我的”里面找到
|
||||
>* -sharebandwidth: 作为共享节点时提供带宽,默认10mbps. 如果是光纤大带宽,设置越大效果越好. -1表示不共享,该节点只在私有的P2P网络使用。不加入共享的P2P网络,这样也意味着无法使用别人的共享节点
|
||||
>* -sharebandwidth: 作为共享节点时提供带宽,默认10mbps. 如果是光纤大带宽,设置越大效果越好. 0表示不共享,该节点只在私有的P2P网络使用。不加入共享的P2P网络,这样也意味着无法使用别人的共享节点
|
||||
>* -loglevel: 需要查看更多调试日志,设置0;默认是1
|
||||
|
||||
### 在docker容器里运行openp2p
|
||||
我们暂时还没提供官方docker镜像,你可以在随便一个容器里运行
|
||||
```
|
||||
nohup ./openp2p -d -node OFFICEPC1 -token TOKEN &
|
||||
#这里由于一般的镜像都精简过,install系统服务会失败,所以使用直接daemon模式后台运行
|
||||
```
|
||||
## 连接
|
||||
```
|
||||
./openp2p -d -node HOMEPC123 -token TOKEN -appname OfficeWindowsRemote -peernode OFFICEPC1 -dstip 127.0.0.1 -dstport 3389 -srcport 23389
|
||||
@@ -39,7 +45,7 @@
|
||||
"network": {
|
||||
"Node": "hhd1207-222",
|
||||
"Token": "TOKEN",
|
||||
"ShareBandwidth": -1,
|
||||
"ShareBandwidth": 0,
|
||||
"ServerHost": "api.openp2p.cn",
|
||||
"ServerPort": 27183,
|
||||
"UDPPort1": 27182,
|
||||
|
||||
11
USAGE.md
@@ -16,9 +16,16 @@ Or
|
||||
>* -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
|
||||
>* -token: See <console.openp2p.cn> "Profile"
|
||||
>* -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 people’s shared nodes
|
||||
>* -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. 0 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 people’s shared nodes
|
||||
>* -loglevel: Need to view more debug logs, set 0; the default is 1
|
||||
|
||||
### Run in Docker container
|
||||
We don't provide official docker image yet, you can run it in any container
|
||||
```
|
||||
nohup ./openp2p -d -node OFFICEPC1 -token TOKEN &
|
||||
# Since many docker images have been simplified, the install system service will fail, so the daemon mode is used to run in the background
|
||||
```
|
||||
|
||||
## Connect
|
||||
```
|
||||
./openp2p -d -node HOMEPC123 -token TOKEN -appname OfficeWindowsRemote -peernode OFFICEPC1 -dstip 127.0.0.1 -dstport 3389 -srcport 23389
|
||||
@@ -41,7 +48,7 @@ Configuration example
|
||||
"network": {
|
||||
"Node": "hhd1207-222",
|
||||
"Token": "TOKEN",
|
||||
"ShareBandwidth": -1,
|
||||
"ShareBandwidth": 0,
|
||||
"ServerHost": "api.openp2p.cn",
|
||||
"ServerPort": 27183,
|
||||
"UDPPort1": 27182,
|
||||
|
||||
10
common.go
@@ -7,8 +7,10 @@ import (
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"time"
|
||||
)
|
||||
@@ -148,3 +150,11 @@ func execOutput(name string, args ...string) string {
|
||||
cmdGetOsName.Run()
|
||||
return cmdOut.String()
|
||||
}
|
||||
|
||||
func defaultNodeName() string {
|
||||
name, _ := os.Hostname()
|
||||
for len(name) < 8 {
|
||||
name = fmt.Sprintf("%s%d", name, rand.Int()%10)
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
29
config.go
@@ -30,13 +30,14 @@ type AppConfig struct {
|
||||
peerConeNatPort int
|
||||
retryNum int
|
||||
retryTime time.Time
|
||||
nextRetryTime time.Time
|
||||
shareBandwidth int
|
||||
}
|
||||
|
||||
// TODO: add loglevel, maxlogfilesize
|
||||
type Config struct {
|
||||
Network NetworkConfig `json:"network"`
|
||||
Apps []AppConfig `json:"apps"`
|
||||
Apps []*AppConfig `json:"apps"`
|
||||
LogLevel int
|
||||
|
||||
mtx sync.Mutex
|
||||
@@ -48,27 +49,29 @@ func (c *Config) switchApp(app AppConfig, enabled int) {
|
||||
for i := 0; i < len(c.Apps); i++ {
|
||||
if c.Apps[i].Protocol == app.Protocol && c.Apps[i].SrcPort == app.SrcPort {
|
||||
c.Apps[i].Enabled = enabled
|
||||
c.Apps[i].retryNum = 0
|
||||
c.Apps[i].nextRetryTime = time.Now()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Config) add(app AppConfig, force bool) {
|
||||
func (c *Config) add(app AppConfig, override bool) {
|
||||
c.mtx.Lock()
|
||||
defer c.mtx.Unlock()
|
||||
if app.SrcPort == 0 || app.DstPort == 0 {
|
||||
gLog.Println(LevelERROR, "invalid app ", app)
|
||||
return
|
||||
}
|
||||
for i := 0; i < len(c.Apps); i++ {
|
||||
if c.Apps[i].Protocol == app.Protocol && c.Apps[i].SrcPort == app.SrcPort {
|
||||
if force {
|
||||
c.Apps[i] = app
|
||||
if override {
|
||||
for i := 0; i < len(c.Apps); i++ {
|
||||
if c.Apps[i].Protocol == app.Protocol && c.Apps[i].SrcPort == app.SrcPort {
|
||||
c.Apps[i] = &app // override it
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
c.Apps = append(c.Apps, app)
|
||||
c.Apps = append(c.Apps, &app)
|
||||
}
|
||||
|
||||
func (c *Config) delete(app AppConfig) {
|
||||
@@ -119,7 +122,6 @@ type NetworkConfig struct {
|
||||
User string
|
||||
localIP string
|
||||
ipv6 string
|
||||
hostName string
|
||||
mac string
|
||||
os string
|
||||
publicIP string
|
||||
@@ -143,11 +145,8 @@ func parseParams() {
|
||||
srcPort := flag.Int("srcport", 0, "source port ")
|
||||
protocol := flag.String("protocol", "tcp", "tcp or udp")
|
||||
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")
|
||||
flag.Bool("f", false, "deprecated. config file") // Deprecated, rm later
|
||||
shareBandwidth := flag.Int("sharebandwidth", 10, "N mbps share bandwidth limit, private network no limit")
|
||||
daemonMode := flag.Bool("d", false, "daemonMode")
|
||||
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()
|
||||
|
||||
@@ -184,6 +183,10 @@ func parseParams() {
|
||||
gConf.Network.ServerHost = *serverHost
|
||||
}
|
||||
if gConf.Network.Node == "" {
|
||||
if *node == "" { // config and param's node both empty
|
||||
hostname := defaultNodeName()
|
||||
node = &hostname
|
||||
}
|
||||
gConf.Network.Node = *node
|
||||
}
|
||||
if *token != 0 {
|
||||
|
||||
14
daemon.go
@@ -106,10 +106,12 @@ func (d *daemon) Control(ctrlComm string, exeAbsPath string, args []string) erro
|
||||
|
||||
// examples:
|
||||
// listen:
|
||||
// ./openp2p install -node hhd1207-222 -token YOUR-TOKEN -sharebandwidth -1
|
||||
// ./openp2p install -node hhd1207-222 -token YOUR-TOKEN -sharebandwidth 0
|
||||
// listen and build p2papp:
|
||||
// ./openp2p install -node hhd1207-222 -token YOUR-TOKEN -sharebandwidth -1 -peernode hhdhome-n1 -dstip 127.0.0.1 -dstport 50022 -protocol tcp -srcport 22
|
||||
// ./openp2p install -node hhd1207-222 -token YOUR-TOKEN -sharebandwidth 0 -peernode hhdhome-n1 -dstip 127.0.0.1 -dstport 50022 -protocol tcp -srcport 22
|
||||
func install() {
|
||||
gLog.Println(LevelINFO, "openp2p start. version: ", OpenP2PVersion)
|
||||
gLog.Println(LevelINFO, "Contact: QQ Group: 16947733, Email: openp2p.cn@gmail.com")
|
||||
gLog.Println(LevelINFO, "install start")
|
||||
defer gLog.Println(LevelINFO, "install end")
|
||||
// auto uninstall
|
||||
@@ -127,16 +129,15 @@ func install() {
|
||||
srcPort := installFlag.Int("srcport", 0, "source port ")
|
||||
protocol := installFlag.String("protocol", "tcp", "tcp or udp")
|
||||
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")
|
||||
shareBandwidth := installFlag.Int("sharebandwidth", 10, "N mbps share bandwidth limit, private network no limit")
|
||||
logLevel := installFlag.Int("loglevel", 1, "0:debug 1:info 2:warn 3:error")
|
||||
installFlag.Parse(os.Args[2:])
|
||||
if *node != "" && len(*node) < 8 {
|
||||
gLog.Println(LevelERROR, "node name too short, it must >=8 charaters")
|
||||
gLog.Println(LevelERROR, ErrNodeTooShort)
|
||||
os.Exit(9)
|
||||
}
|
||||
if *node == "" { // if node name not set. use os.Hostname
|
||||
hostname, _ := os.Hostname()
|
||||
hostname := defaultNodeName()
|
||||
node = &hostname
|
||||
}
|
||||
gConf.load() // load old config. otherwise will clear all apps
|
||||
@@ -195,7 +196,6 @@ func install() {
|
||||
dst.Close()
|
||||
|
||||
// install system service
|
||||
// args := []string{""}
|
||||
gLog.Println(LevelINFO, "targetPath:", targetPath)
|
||||
err = d.Control("install", targetPath, []string{"-d"})
|
||||
if err == nil {
|
||||
|
||||
BIN
doc/images/afterconnect_en.png
Normal file
|
After Width: | Height: | Size: 5.6 MiB |
BIN
doc/images/devices_en.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
doc/images/install_en.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
doc/images/mstscconnect_en.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
doc/images/newapp_en.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
doc/images/newappedit_en.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
doc/images/p2pappok_en.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 119 KiB After Width: | Height: | Size: 98 KiB |
BIN
doc/images/register_en.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 19 KiB |
BIN
doc/images/stillrun_en.png
Normal file
|
After Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 15 KiB |
BIN
doc/images/win10warn_en.png
Normal file
|
After Width: | Height: | Size: 6.8 KiB |
@@ -8,6 +8,9 @@ import (
|
||||
var (
|
||||
// ErrorS2S string = "s2s is not supported"
|
||||
// ErrorHandshake string = "handshake error"
|
||||
ErrorS2S = errors.New("s2s is not supported")
|
||||
ErrorHandshake = errors.New("handshake error")
|
||||
ErrorS2S = errors.New("s2s is not supported")
|
||||
ErrorHandshake = errors.New("handshake error")
|
||||
ErrorNewUser = errors.New("new user")
|
||||
ErrorLogin = errors.New("user or password not correct")
|
||||
ErrNodeTooShort = errors.New("node name too short, it must >=8 charaters")
|
||||
)
|
||||
|
||||
@@ -115,18 +115,23 @@ func handlePush(pn *P2PNetwork, subType uint16, msg []byte) error {
|
||||
defer gConf.mtx.Unlock()
|
||||
for _, config := range gConf.Apps {
|
||||
appActive := 0
|
||||
relayNode := ""
|
||||
relayMode := ""
|
||||
i, ok := pn.apps.Load(fmt.Sprintf("%s%d", config.Protocol, config.SrcPort))
|
||||
if ok {
|
||||
app := i.(*p2pApp)
|
||||
if app.isActive() {
|
||||
appActive = 1
|
||||
}
|
||||
relayNode = app.relayNode
|
||||
relayMode = app.relayMode
|
||||
}
|
||||
appInfo := AppInfo{
|
||||
AppName: config.AppName,
|
||||
Protocol: config.Protocol,
|
||||
SrcPort: config.SrcPort,
|
||||
// RelayNode: relayNode,
|
||||
AppName: config.AppName,
|
||||
Protocol: config.Protocol,
|
||||
SrcPort: config.SrcPort,
|
||||
RelayNode: relayNode,
|
||||
RelayMode: relayMode,
|
||||
PeerNode: config.PeerNode,
|
||||
DstHost: config.DstHost,
|
||||
DstPort: config.DstPort,
|
||||
|
||||
@@ -13,7 +13,7 @@ func main() {
|
||||
binDir := filepath.Dir(os.Args[0])
|
||||
os.Chdir(binDir) // for system service
|
||||
gLog = InitLogger(binDir, "openp2p", LevelDEBUG, 1024*1024, LogFileAndConsole)
|
||||
gLog.Println(LevelINFO, "openp2p start. version: ", OpenP2PVersion)
|
||||
|
||||
// TODO: install sub command, deamon process
|
||||
if len(os.Args) > 1 {
|
||||
switch os.Args[1] {
|
||||
@@ -41,7 +41,8 @@ func main() {
|
||||
} else {
|
||||
installByFilename()
|
||||
}
|
||||
|
||||
gLog.Println(LevelINFO, "openp2p start. version: ", OpenP2PVersion)
|
||||
gLog.Println(LevelINFO, "Contact: QQ Group: 16947733, Email: openp2p.cn@gmail.com")
|
||||
parseParams()
|
||||
gLog.Println(LevelINFO, &gConf)
|
||||
setFirewall()
|
||||
|
||||
17
p2papp.go
@@ -16,6 +16,7 @@ type p2pApp struct {
|
||||
tunnel *P2PTunnel
|
||||
rtid uint64
|
||||
relayNode string
|
||||
relayMode string
|
||||
hbTime time.Time
|
||||
hbMtx sync.Mutex
|
||||
running bool
|
||||
@@ -45,7 +46,12 @@ func (app *p2pApp) updateHeartbeat() {
|
||||
|
||||
func (app *p2pApp) listenTCP() error {
|
||||
var err error
|
||||
app.listener, err = net.Listen("tcp4", fmt.Sprintf("0.0.0.0:%d", app.config.SrcPort))
|
||||
if app.config.Protocol == "udp" {
|
||||
app.listener, err = net.Listen("udp4", fmt.Sprintf("0.0.0.0:%d", app.config.SrcPort))
|
||||
} else {
|
||||
app.listener, err = net.Listen("tcp4", fmt.Sprintf("0.0.0.0:%d", app.config.SrcPort))
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
gLog.Printf(LevelERROR, "listen error:%s", err)
|
||||
return err
|
||||
@@ -108,13 +114,10 @@ func (app *p2pApp) listen() error {
|
||||
go app.relayHeartbeatLoop()
|
||||
}
|
||||
for app.running {
|
||||
if app.config.Protocol == "udp" {
|
||||
app.listenTCP()
|
||||
} else {
|
||||
app.listenTCP()
|
||||
}
|
||||
|
||||
app.listenTCP()
|
||||
|
||||
time.Sleep(time.Second * 5)
|
||||
// TODO: listen UDP
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -7,10 +7,10 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"math/rand"
|
||||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -97,6 +97,9 @@ func (pn *P2PNetwork) runAll() {
|
||||
gConf.mtx.Lock()
|
||||
defer gConf.mtx.Unlock()
|
||||
for _, config := range gConf.Apps {
|
||||
if config.nextRetryTime.After(time.Now()) {
|
||||
continue
|
||||
}
|
||||
if config.Enabled == 0 {
|
||||
continue
|
||||
}
|
||||
@@ -117,19 +120,22 @@ func (pn *P2PNetwork) runAll() {
|
||||
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()) {
|
||||
pn.DeleteApp(*config)
|
||||
}
|
||||
if config.retryNum > 0 {
|
||||
gLog.Printf(LevelINFO, "detect app %s disconnect, reconnecting the %d times...", config.AppName, config.retryNum)
|
||||
if time.Now().Add(-time.Minute * 15).After(config.retryTime) { // normal lasts 15min
|
||||
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)
|
||||
config.retryNum++
|
||||
config.retryTime = time.Now()
|
||||
increase := math.Pow(1.3, float64(config.retryNum))
|
||||
if increase > 900 {
|
||||
increase = 900
|
||||
}
|
||||
config.nextRetryTime = time.Now().Add(time.Second * time.Duration(increase)) // exponential increase retry time. 1.3^x
|
||||
go pn.AddApp(*config)
|
||||
}
|
||||
}
|
||||
func (pn *P2PNetwork) autorunApp() {
|
||||
@@ -146,23 +152,23 @@ func (pn *P2PNetwork) autorunApp() {
|
||||
gLog.Println(LevelINFO, "autorunApp end")
|
||||
}
|
||||
|
||||
func (pn *P2PNetwork) addRelayTunnel(config AppConfig, appid uint64, appkey uint64) (*P2PTunnel, uint64, error) {
|
||||
func (pn *P2PNetwork) addRelayTunnel(config AppConfig, appid uint64, appkey uint64) (*P2PTunnel, uint64, string, error) {
|
||||
gLog.Printf(LevelINFO, "addRelayTunnel to %s start", config.PeerNode)
|
||||
defer gLog.Printf(LevelINFO, "addRelayTunnel to %s end", config.PeerNode)
|
||||
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")
|
||||
return nil, 0, "", errors.New("read MsgRelayNodeRsp error")
|
||||
}
|
||||
rsp := RelayNodeRsp{}
|
||||
err := json.Unmarshal(body, &rsp)
|
||||
if err != nil {
|
||||
gLog.Printf(LevelERROR, "wrong RelayNodeRsp:%s", err)
|
||||
return nil, 0, errors.New("unmarshal MsgRelayNodeRsp error")
|
||||
return nil, 0, "", errors.New("unmarshal MsgRelayNodeRsp error")
|
||||
}
|
||||
if rsp.RelayName == "" || rsp.RelayToken == 0 {
|
||||
gLog.Printf(LevelERROR, "MsgRelayNodeReq error")
|
||||
return nil, 0, errors.New("MsgRelayNodeReq error")
|
||||
return nil, 0, "", errors.New("MsgRelayNodeReq error")
|
||||
}
|
||||
gLog.Printf(LevelINFO, "got relay node:%s", rsp.RelayName)
|
||||
relayConfig := config
|
||||
@@ -171,7 +177,7 @@ func (pn *P2PNetwork) addRelayTunnel(config AppConfig, appid uint64, appkey uint
|
||||
t, err := pn.addDirectTunnel(relayConfig, 0)
|
||||
if err != nil {
|
||||
gLog.Println(LevelERROR, "direct connect error:", err)
|
||||
return nil, 0, err
|
||||
return nil, 0, "", err
|
||||
}
|
||||
// notify peer addRelayTunnel
|
||||
req := AddRelayTunnelReq{
|
||||
@@ -188,15 +194,15 @@ func (pn *P2PNetwork) addRelayTunnel(config AppConfig, appid uint64, appkey uint
|
||||
head, body = pn.read(config.PeerNode, MsgPush, MsgPushAddRelayTunnelRsp, PeerAddRelayTimeount) // TODO: const value
|
||||
if head == nil {
|
||||
gLog.Printf(LevelERROR, "read MsgPushAddRelayTunnelRsp error")
|
||||
return nil, 0, errors.New("read MsgPushAddRelayTunnelRsp error")
|
||||
return nil, 0, "", errors.New("read MsgPushAddRelayTunnelRsp error")
|
||||
}
|
||||
rspID := TunnelMsg{}
|
||||
err = json.Unmarshal(body, &rspID)
|
||||
if err != nil {
|
||||
gLog.Printf(LevelERROR, "wrong RelayNodeRsp:%s", err)
|
||||
return nil, 0, errors.New("unmarshal MsgRelayNodeRsp error")
|
||||
return nil, 0, "", errors.New("unmarshal MsgRelayNodeRsp error")
|
||||
}
|
||||
return t, rspID.ID, err
|
||||
return t, rspID.ID, rsp.Mode, err
|
||||
}
|
||||
|
||||
func (pn *P2PNetwork) AddApp(config AppConfig) error {
|
||||
@@ -216,24 +222,26 @@ func (pn *P2PNetwork) AddApp(config AppConfig) error {
|
||||
}
|
||||
appID := rand.Uint64()
|
||||
appKey := uint64(0)
|
||||
t, err := pn.addDirectTunnel(config, 0)
|
||||
var rtid uint64
|
||||
relayNode := ""
|
||||
relayMode := ""
|
||||
peerNatType := NATUnknown
|
||||
peerIP := ""
|
||||
errMsg := ""
|
||||
if err != nil && err == ErrorHandshake {
|
||||
gLog.Println(LevelERROR, "direct connect failed, try to relay")
|
||||
appKey = rand.Uint64()
|
||||
t, rtid, err = pn.addRelayTunnel(config, appID, appKey)
|
||||
if t != nil {
|
||||
relayNode = t.config.PeerNode
|
||||
}
|
||||
}
|
||||
t, err := pn.addDirectTunnel(config, 0)
|
||||
if t != nil {
|
||||
peerNatType = t.config.peerNatType
|
||||
peerIP = t.config.peerIP
|
||||
}
|
||||
if err != nil && err == ErrorHandshake {
|
||||
gLog.Println(LevelERROR, "direct connect failed, try to relay")
|
||||
appKey = rand.Uint64()
|
||||
t, rtid, relayMode, err = pn.addRelayTunnel(config, appID, appKey)
|
||||
if t != nil {
|
||||
relayNode = t.config.PeerNode
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
errMsg = err.Error()
|
||||
}
|
||||
@@ -262,6 +270,7 @@ func (pn *P2PNetwork) AddApp(config AppConfig) error {
|
||||
config: config,
|
||||
rtid: rtid,
|
||||
relayNode: relayNode,
|
||||
relayMode: relayMode,
|
||||
hbTime: time.Now()}
|
||||
pn.apps.Store(fmt.Sprintf("%s%d", config.Protocol, config.SrcPort), &app)
|
||||
if err == nil {
|
||||
@@ -361,11 +370,6 @@ func (pn *P2PNetwork) init() error {
|
||||
gLog.Println(LevelINFO, "init start")
|
||||
var err error
|
||||
for {
|
||||
pn.config.hostName, err = os.Hostname()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
// detect nat type
|
||||
pn.config.publicIP, pn.config.natType, err = getNATType(pn.config.ServerHost, pn.config.UDPPort1, pn.config.UDPPort2)
|
||||
// TODO rm test s2s
|
||||
|
||||
53
p2ptunnel.go
@@ -333,32 +333,35 @@ func (t *P2PTunnel) readLoop() {
|
||||
|
||||
overlayID := req.ID
|
||||
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 {
|
||||
gLog.Println(LevelERROR, err)
|
||||
continue
|
||||
}
|
||||
otcp := overlayTCP{
|
||||
tunnel: t,
|
||||
conn: conn,
|
||||
id: overlayID,
|
||||
isClient: false,
|
||||
rtid: req.RelayTunnelID,
|
||||
appID: req.AppID,
|
||||
appKey: GetKey(req.AppID),
|
||||
}
|
||||
// calc key bytes for encrypt
|
||||
if otcp.appKey != 0 {
|
||||
encryptKey := make([]byte, 16)
|
||||
binary.LittleEndian.PutUint64(encryptKey, otcp.appKey)
|
||||
binary.LittleEndian.PutUint64(encryptKey[8:], otcp.appKey)
|
||||
otcp.appKeyBytes = encryptKey
|
||||
}
|
||||
|
||||
t.overlayConns.Store(otcp.id, &otcp)
|
||||
go otcp.run()
|
||||
var conn net.Conn
|
||||
if req.Protocol == "udp" {
|
||||
conn, err = net.DialTimeout("udp", fmt.Sprintf("%s:%d", req.DstIP, req.DstPort), time.Second*5)
|
||||
} else {
|
||||
conn, err = net.DialTimeout("tcp", fmt.Sprintf("%s:%d", req.DstIP, req.DstPort), time.Second*5)
|
||||
}
|
||||
if err != nil {
|
||||
gLog.Println(LevelERROR, err)
|
||||
continue
|
||||
}
|
||||
otcp := overlayTCP{
|
||||
tunnel: t,
|
||||
conn: conn,
|
||||
id: overlayID,
|
||||
isClient: false,
|
||||
rtid: req.RelayTunnelID,
|
||||
appID: req.AppID,
|
||||
appKey: GetKey(req.AppID),
|
||||
}
|
||||
// calc key bytes for encrypt
|
||||
if otcp.appKey != 0 {
|
||||
encryptKey := make([]byte, 16)
|
||||
binary.LittleEndian.PutUint64(encryptKey, otcp.appKey)
|
||||
binary.LittleEndian.PutUint64(encryptKey[8:], otcp.appKey)
|
||||
otcp.appKeyBytes = encryptKey
|
||||
}
|
||||
|
||||
t.overlayConns.Store(otcp.id, &otcp)
|
||||
go otcp.run()
|
||||
case MsgOverlayDisconnectReq:
|
||||
req := OverlayDisconnectReq{}
|
||||
err := json.Unmarshal(body, &req)
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
const OpenP2PVersion = "1.0.0"
|
||||
const OpenP2PVersion = "1.2.0"
|
||||
const ProducnName string = "openp2p"
|
||||
|
||||
type openP2PHeader struct {
|
||||
@@ -236,6 +236,7 @@ type RelayNodeReq struct {
|
||||
}
|
||||
|
||||
type RelayNodeRsp struct {
|
||||
Mode string `json:"mode,omitempty"` // private,public
|
||||
RelayName string `json:"relayName,omitempty"`
|
||||
RelayToken uint64 `json:"relayToken,omitempty"`
|
||||
}
|
||||
@@ -294,6 +295,7 @@ type AppInfo struct {
|
||||
PeerIP string `json:"peerIP,omitempty"`
|
||||
ShareBandwidth int `json:"shareBandWidth,omitempty"`
|
||||
RelayNode string `json:"relayNode,omitempty"`
|
||||
RelayMode string `json:"relayMode,omitempty"`
|
||||
Version string `json:"version,omitempty"`
|
||||
RetryTime string `json:"retryTime,omitempty"`
|
||||
IsActive int `json:"isActive,omitempty"`
|
||||
|
||||