mirror of
https://github.com/ayflying/p2p.git
synced 2026-03-04 17:29:22 +00:00
增加代理接口
This commit is contained in:
@@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/ayflying/p2p.git
|
git clone https://github.com/ayflying/p2p.git
|
||||||
cd p2p
|
cd message
|
||||||
```
|
```
|
||||||
|
|
||||||
### 安装依赖
|
### 安装依赖
|
||||||
@@ -42,13 +42,13 @@ go mod tidy
|
|||||||
### 构建项目
|
### 构建项目
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
go build -o p2p
|
go build -o message
|
||||||
```
|
```
|
||||||
|
|
||||||
### 运行项目
|
### 运行项目
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./p2p
|
./message
|
||||||
```
|
```
|
||||||
|
|
||||||
## 目录结构
|
## 目录结构
|
||||||
@@ -90,7 +90,7 @@ go build -o p2p
|
|||||||
项目提供了命令行工具,支持节点管理、网络状态查询等功能。
|
项目提供了命令行工具,支持节点管理、网络状态查询等功能。
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./p2p --help # 查看帮助信息
|
./message --help # 查看帮助信息
|
||||||
```
|
```
|
||||||
|
|
||||||
## 开发指南
|
## 开发指南
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package v1
|
|||||||
import "github.com/gogf/gf/v2/frame/g"
|
import "github.com/gogf/gf/v2/frame/g"
|
||||||
|
|
||||||
type ConnectReq struct {
|
type ConnectReq struct {
|
||||||
g.Meta `path:"/p2p/connect" tags:"p2p" method:"get" sm:"连接到目标主机"`
|
g.Meta `path:"/message/connect" tags:"message" method:"get" sm:"连接到目标主机"`
|
||||||
TargetID string `json:"id"`
|
TargetID string `json:"id"`
|
||||||
}
|
}
|
||||||
type ConnectRes struct {
|
type ConnectRes struct {
|
||||||
@@ -11,7 +11,7 @@ type ConnectRes struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type SendReq struct {
|
type SendReq struct {
|
||||||
g.Meta `path:"/p2p/send" tags:"p2p" method:"get" sm:"发送消息"`
|
g.Meta `path:"/message/send" tags:"message" method:"get" sm:"发送消息"`
|
||||||
TargetID string `json:"id"`
|
TargetID string `json:"id"`
|
||||||
Data string `json:"data"`
|
Data string `json:"data"`
|
||||||
}
|
}
|
||||||
@@ -20,8 +20,15 @@ type SendRes struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type IpReq struct {
|
type IpReq struct {
|
||||||
g.Meta `path:"/p2p/ip" tags:"p2p" method:"get" sm:"获取当前主机的IP地址"`
|
g.Meta `path:"/message/ip" tags:"message" method:"get" sm:"获取当前主机的IP地址"`
|
||||||
}
|
}
|
||||||
type IpRes struct {
|
type IpRes struct {
|
||||||
g.Meta `mime:"text/html" example:"string"`
|
g.Meta `mime:"text/html" example:"string"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Message struct {
|
||||||
|
Type string `json:"type" dc:"消息类型"`
|
||||||
|
//Port int `json:"port,omitempty" dc:"请求端口"`
|
||||||
|
Data []byte `json:"data" dc:"消息数据"`
|
||||||
|
From string `json:"from" dc:"发送方ID"`
|
||||||
|
}
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ var (
|
|||||||
}
|
}
|
||||||
msg = res.Export()
|
msg = res.Export()
|
||||||
g.Dump(res.ToNumber())
|
g.Dump(res.ToNumber())
|
||||||
case "p2p":
|
case "message":
|
||||||
// host, err := service.P2P().Start(ctx)
|
// host, err := service.P2P().Start(ctx)
|
||||||
// if err != nil {
|
// if err != nil {
|
||||||
// break
|
// break
|
||||||
@@ -102,9 +102,9 @@ var (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// 重命名正在运行的程序文件(如 p2p.exe → p2p.exe~)
|
// 重命名正在运行的程序文件(如 message.exe → message.exe~)
|
||||||
func renameRunningFile(exePath string) (string, error) {
|
func renameRunningFile(exePath string) (string, error) {
|
||||||
// 目标备份文件名(p2p.exe → p2p.exe~)
|
// 目标备份文件名(message.exe → message.exe~)
|
||||||
backupPath := exePath + "~"
|
backupPath := exePath + "~"
|
||||||
|
|
||||||
// 先删除已存在的备份文件(若有)
|
// 先删除已存在的备份文件(若有)
|
||||||
|
|||||||
@@ -17,15 +17,15 @@ P2P连接工具使用帮助:
|
|||||||
|
|
||||||
模式1: 网关服务器
|
模式1: 网关服务器
|
||||||
功能: 拥有外网IP,接收客户端连接,协助P2P打洞
|
功能: 拥有外网IP,接收客户端连接,协助P2P打洞
|
||||||
命令: p2p -a gateway
|
命令: message -a gateway
|
||||||
|
|
||||||
模式2: 客户端
|
模式2: 客户端
|
||||||
功能: 连接到网关,通过打洞实现与其他客户端的长连接通讯
|
功能: 连接到网关,通过打洞实现与其他客户端的长连接通讯
|
||||||
命令: p2p -a client --gateway 网关ID
|
命令: message -a client --gateway 网关ID
|
||||||
|
|
||||||
高级功能:
|
高级功能:
|
||||||
客户端间连接: p2p --mode client --gateway 网关ID --action connect --target 目标客户端ID
|
客户端间连接: message --mode client --gateway 网关ID --action connect --target 目标客户端ID
|
||||||
发送消息: p2p -mode client --gateway 网关ID --action send --target 目标客户端ID --message "消息内容"
|
发送消息: message -mode client --gateway 网关ID --action send --target 目标客户端ID --message "消息内容"
|
||||||
`
|
`
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -33,9 +33,9 @@ var (
|
|||||||
// 遵循GoFrame的Command对象定义规范,包含名称、用法、简短描述和执行函数
|
// 遵循GoFrame的Command对象定义规范,包含名称、用法、简短描述和执行函数
|
||||||
P2p = gcmd.Command{
|
P2p = gcmd.Command{
|
||||||
// Name 为命令名称
|
// Name 为命令名称
|
||||||
Name: "p2p",
|
Name: "message",
|
||||||
// Usage 描述命令的基本用法
|
// Usage 描述命令的基本用法
|
||||||
Usage: "p2p [options]",
|
Usage: "message [options]",
|
||||||
// Brief 提供命令的简短功能描述
|
// Brief 提供命令的简短功能描述
|
||||||
Brief: "P2P连接工具,支持网关和客户端模式,实现NAT穿透和点对点通信",
|
Brief: "P2P连接工具,支持网关和客户端模式,实现NAT穿透和点对点通信",
|
||||||
// Description 提供命令的详细描述和使用帮助
|
// Description 提供命令的详细描述和使用帮助
|
||||||
@@ -81,16 +81,16 @@ var (
|
|||||||
h, _ := service.P2P().CreateLibp2pHost(ctx, 23333)
|
h, _ := service.P2P().CreateLibp2pHost(ctx, 23333)
|
||||||
|
|
||||||
addr := []string{
|
addr := []string{
|
||||||
"/ip4/192.168.50.243/tcp/23333/p2p/12D3KooWESZtrm6AfqhC3oj5FsAbcSmePwHFFip3F2MPExrxHxwy",
|
"/ip4/192.168.50.243/tcp/23333/message/12D3KooWESZtrm6AfqhC3oj5FsAbcSmePwHFFip3F2MPExrxHxwy",
|
||||||
"/ip4/192.168.50.243/udp/23333/quic-v1/p2p/12D3KooWESZtrm6AfqhC3oj5FsAbcSmePwHFFip3F2MPExrxHxwy",
|
"/ip4/192.168.50.243/udp/23333/quic-v1/message/12D3KooWESZtrm6AfqhC3oj5FsAbcSmePwHFFip3F2MPExrxHxwy",
|
||||||
|
|
||||||
//"/ip4/192.168.50.173/tcp/23333/p2p/12D3KooWKgW8WxncYzZ2h5erMbK3GfLGhNHFapPvhUc1KVmdZeRg",
|
//"/ip4/192.168.50.173/tcp/23333/message/12D3KooWKgW8WxncYzZ2h5erMbK3GfLGhNHFapPvhUc1KVmdZeRg",
|
||||||
//"/ip4/192.168.50.173/udp/23333/quic-v1/p2p/12D3KooWKgW8WxncYzZ2h5erMbK3GfLGhNHFapPvhUc1KVmdZeRg",
|
//"/ip4/192.168.50.173/udp/23333/quic-v1/message/12D3KooWKgW8WxncYzZ2h5erMbK3GfLGhNHFapPvhUc1KVmdZeRg",
|
||||||
|
|
||||||
//"/ip4/192.168.50.173/tcp/23333/p2p/12D3KooWQsb1137nCzqbMMCzwHsyU8aaCZeFnBUBTkWVsfp8gs26",
|
//"/ip4/192.168.50.173/tcp/23333/message/12D3KooWQsb1137nCzqbMMCzwHsyU8aaCZeFnBUBTkWVsfp8gs26",
|
||||||
//"/ip4/192.168.50.173/udp/23333/quic-v1/p2p/12D3KooWQsb1137nCzqbMMCzwHsyU8aaCZeFnBUBTkWVsfp8gs26",
|
//"/ip4/192.168.50.173/udp/23333/quic-v1/message/12D3KooWQsb1137nCzqbMMCzwHsyU8aaCZeFnBUBTkWVsfp8gs26",
|
||||||
//"/ip4/114.132.176.115/tcp/23333/p2p/12D3KooWJQMiYyptqSrx4PPsGLY9hjLbaDdxmBXmGtKmSWuiP79D",
|
//"/ip4/114.132.176.115/tcp/23333/message/12D3KooWJQMiYyptqSrx4PPsGLY9hjLbaDdxmBXmGtKmSWuiP79D",
|
||||||
//"/ip4/114.132.176.115/udp/23333/quic-v1/p2p/12D3KooWJQMiYyptqSrx4PPsGLY9hjLbaDdxmBXmGtKmSWuiP79D",
|
//"/ip4/114.132.176.115/udp/23333/quic-v1/message/12D3KooWJQMiYyptqSrx4PPsGLY9hjLbaDdxmBXmGtKmSWuiP79D",
|
||||||
}
|
}
|
||||||
|
|
||||||
err := service.P2P().DHTStart(h, addr)
|
err := service.P2P().DHTStart(h, addr)
|
||||||
@@ -112,25 +112,25 @@ var (
|
|||||||
h, _ := service.P2P().CreateLibp2pHost(ctx, 23333)
|
h, _ := service.P2P().CreateLibp2pHost(ctx, 23333)
|
||||||
|
|
||||||
//addr := []string{
|
//addr := []string{
|
||||||
// //"/ip4/192.168.50.243/tcp/23333/p2p/12D3KooWESZtrm6AfqhC3oj5FsAbcSmePwHFFip3F2MPExrxHxwy",
|
// //"/ip4/192.168.50.243/tcp/23333/message/12D3KooWESZtrm6AfqhC3oj5FsAbcSmePwHFFip3F2MPExrxHxwy",
|
||||||
// //"/ip4/192.168.50.243/udp/23333/quic-v1/p2p/12D3KooWESZtrm6AfqhC3oj5FsAbcSmePwHFFip3F2MPExrxHxwy",
|
// //"/ip4/192.168.50.243/udp/23333/quic-v1/message/12D3KooWESZtrm6AfqhC3oj5FsAbcSmePwHFFip3F2MPExrxHxwy",
|
||||||
//
|
//
|
||||||
// //肖晓
|
// //肖晓
|
||||||
// "/ip4/192.168.50.244/tcp/23333/p2p/12D3KooWFAt3hTi2SaYNty4gxxBnLRFxJidRDcf4k8HqCUZZRY1W",
|
// "/ip4/192.168.50.244/tcp/23333/message/12D3KooWFAt3hTi2SaYNty4gxxBnLRFxJidRDcf4k8HqCUZZRY1W",
|
||||||
// "/ip4/192.168.50.244/udp/23333/quic-v1/p2p/12D3KooWFAt3hTi2SaYNty4gxxBnLRFxJidRDcf4k8HqCUZZRY1W",
|
// "/ip4/192.168.50.244/udp/23333/quic-v1/message/12D3KooWFAt3hTi2SaYNty4gxxBnLRFxJidRDcf4k8HqCUZZRY1W",
|
||||||
//
|
//
|
||||||
// //廖玉龙
|
// //廖玉龙
|
||||||
// "/ip4/192.168.50.210/tcp/23333/p2p/12D3KooWM8eE3i2EWB2wFVGM1URusBPHJrEQJGxKfKgPdxEMm9hn",
|
// "/ip4/192.168.50.210/tcp/23333/message/12D3KooWM8eE3i2EWB2wFVGM1URusBPHJrEQJGxKfKgPdxEMm9hn",
|
||||||
// "/ip4/192.168.50.210/udp/23333/quic-v1/p2p/12D3KooWM8eE3i2EWB2wFVGM1URusBPHJrEQJGxKfKgPdxEMm9hn",
|
// "/ip4/192.168.50.210/udp/23333/quic-v1/message/12D3KooWM8eE3i2EWB2wFVGM1URusBPHJrEQJGxKfKgPdxEMm9hn",
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// //"/ip4/192.168.50.173/tcp/23333/p2p/12D3KooWKgW8WxncYzZ2h5erMbK3GfLGhNHFapPvhUc1KVmdZeRg",
|
// //"/ip4/192.168.50.173/tcp/23333/message/12D3KooWKgW8WxncYzZ2h5erMbK3GfLGhNHFapPvhUc1KVmdZeRg",
|
||||||
// //"/ip4/192.168.50.173/udp/23333/quic-v1/p2p/12D3KooWKgW8WxncYzZ2h5erMbK3GfLGhNHFapPvhUc1KVmdZeRg",
|
// //"/ip4/192.168.50.173/udp/23333/quic-v1/message/12D3KooWKgW8WxncYzZ2h5erMbK3GfLGhNHFapPvhUc1KVmdZeRg",
|
||||||
//
|
//
|
||||||
// //"/ip4/192.168.50.173/tcp/23333/p2p/12D3KooWQsb1137nCzqbMMCzwHsyU8aaCZeFnBUBTkWVsfp8gs26",
|
// //"/ip4/192.168.50.173/tcp/23333/message/12D3KooWQsb1137nCzqbMMCzwHsyU8aaCZeFnBUBTkWVsfp8gs26",
|
||||||
// //"/ip4/192.168.50.173/udp/23333/quic-v1/p2p/12D3KooWQsb1137nCzqbMMCzwHsyU8aaCZeFnBUBTkWVsfp8gs26",
|
// //"/ip4/192.168.50.173/udp/23333/quic-v1/message/12D3KooWQsb1137nCzqbMMCzwHsyU8aaCZeFnBUBTkWVsfp8gs26",
|
||||||
// //"/ip4/114.132.176.115/tcp/23333/p2p/12D3KooWJQMiYyptqSrx4PPsGLY9hjLbaDdxmBXmGtKmSWuiP79D",
|
// //"/ip4/114.132.176.115/tcp/23333/message/12D3KooWJQMiYyptqSrx4PPsGLY9hjLbaDdxmBXmGtKmSWuiP79D",
|
||||||
// //"/ip4/114.132.176.115/udp/23333/quic-v1/p2p/12D3KooWJQMiYyptqSrx4PPsGLY9hjLbaDdxmBXmGtKmSWuiP79D",
|
// //"/ip4/114.132.176.115/udp/23333/quic-v1/message/12D3KooWJQMiYyptqSrx4PPsGLY9hjLbaDdxmBXmGtKmSWuiP79D",
|
||||||
//}
|
//}
|
||||||
|
|
||||||
addrVar, err := g.Cfg().Get(ctx, "dht.addrs")
|
addrVar, err := g.Cfg().Get(ctx, "dht.addrs")
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ var (
|
|||||||
g.Log().Debugf(ctx, "当前获取到的地址为:%v", filePath)
|
g.Log().Debugf(ctx, "当前获取到的地址为:%v", filePath)
|
||||||
|
|
||||||
versionUrl := service.S3().GetCdnUrl(path.Join(rootDir, name))
|
versionUrl := service.S3().GetCdnUrl(path.Join(rootDir, name))
|
||||||
listVar := g.Cfg().MustGet(ctx, "p2p.list")
|
listVar := g.Cfg().MustGet(ctx, "message.list")
|
||||||
var p2pItem []struct {
|
var p2pItem []struct {
|
||||||
Host string `json:"host"`
|
Host string `json:"host"`
|
||||||
Port int `json:"port"`
|
Port int `json:"port"`
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ func (c *ControllerV1) Update(ctx context.Context, req *v1.UpdateReq) (res *v1.U
|
|||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
}
|
}
|
||||||
|
|
||||||
//var GatewayMessage *p2p.GatewayMessage
|
//var GatewayMessage *message.GatewayMessage
|
||||||
|
|
||||||
var msgData = struct {
|
var msgData = struct {
|
||||||
Files []*DataType `json:"files"`
|
Files []*DataType `json:"files"`
|
||||||
|
|||||||
@@ -9,14 +9,15 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
v1 "github.com/ayflying/p2p/api/p2p/v1"
|
||||||
|
messageFunc "github.com/ayflying/p2p/internal/message"
|
||||||
"github.com/ayflying/p2p/internal/service"
|
"github.com/ayflying/p2p/internal/service"
|
||||||
"github.com/gogf/gf/v2/encoding/gjson"
|
"github.com/gogf/gf/v2/encoding/gjson"
|
||||||
"github.com/gogf/gf/v2/frame/g"
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
"github.com/gogf/gf/v2/net/gtcp"
|
"github.com/gogf/gf/v2/os/gcache"
|
||||||
"github.com/gogf/gf/v2/os/gctx"
|
"github.com/gogf/gf/v2/os/gctx"
|
||||||
"github.com/gogf/gf/v2/os/gfile"
|
"github.com/gogf/gf/v2/os/gfile"
|
||||||
"github.com/gogf/gf/v2/os/glog"
|
"github.com/gogf/gf/v2/os/glog"
|
||||||
"github.com/gogf/gf/v2/os/gtime"
|
|
||||||
"github.com/gogf/gf/v2/os/gtimer"
|
"github.com/gogf/gf/v2/os/gtimer"
|
||||||
"github.com/gogf/gf/v2/util/grand"
|
"github.com/gogf/gf/v2/util/grand"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
@@ -41,19 +42,12 @@ type Client struct {
|
|||||||
//tcp map[string]
|
//tcp map[string]
|
||||||
}
|
}
|
||||||
|
|
||||||
type Message struct {
|
|
||||||
Type string `json:"type" dc:"消息类型"`
|
|
||||||
Port int `json:"port,omitempty" dc:"请求端口"`
|
|
||||||
Data []byte `json:"data" dc:"消息数据"`
|
|
||||||
From string `json:"from" dc:"发送方ID"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// SendP2P 发送格式化消息
|
// SendP2P 发送格式化消息
|
||||||
func (s *sP2P) SendP2P(targetID string, typ string, data []byte) (err error) {
|
func (s *sP2P) SendP2P(targetID string, typ string, data []byte) (err error) {
|
||||||
if typ == "" {
|
if typ == "" {
|
||||||
typ = "message"
|
typ = "message"
|
||||||
}
|
}
|
||||||
message := &Message{
|
message := &v1.Message{
|
||||||
Type: typ,
|
Type: typ,
|
||||||
From: s.client.Id,
|
From: s.client.Id,
|
||||||
Data: data,
|
Data: data,
|
||||||
@@ -199,6 +193,14 @@ func (s *sP2P) register() error {
|
|||||||
|
|
||||||
// 发现并连接目标节点
|
// 发现并连接目标节点
|
||||||
func (s *sP2P) DiscoverAndConnect(targetID string) error {
|
func (s *sP2P) DiscoverAndConnect(targetID string) error {
|
||||||
|
cacheKey := fmt.Sprintf("%s:%s", s.client.Id, targetID)
|
||||||
|
get, _ := gcache.Get(gctx.New(), cacheKey)
|
||||||
|
if !get.IsEmpty() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// 设置缓存,避免重复发现
|
||||||
|
gcache.Set(gctx.New(), cacheKey, targetID, 30*time.Second)
|
||||||
|
|
||||||
// 发送发现请求
|
// 发送发现请求
|
||||||
msg := GatewayMessage{
|
msg := GatewayMessage{
|
||||||
Type: MsgTypeDiscover,
|
Type: MsgTypeDiscover,
|
||||||
@@ -247,45 +249,18 @@ func (s *sP2P) handleStream(stream network.Stream) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 解析消息
|
// 解析消息
|
||||||
var message *Message
|
var message *v1.Message
|
||||||
if err := gjson.DecodeTo(msg, &message); err != nil {
|
if err := gjson.DecodeTo(msg, &message); err != nil {
|
||||||
g.Log().Debugf(ctx, "解析消息失败: %v", msg)
|
g.Log().Debugf(ctx, "解析消息失败: %v", msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
//g.Log().Debugf(ctx, "收到来自 %s 的消息: %v ", peerID, gjson.MustEncodeString(message))
|
//g.Log().Debugf(ctx, "收到来自 %s 的消息: %v ", peerID, gjson.MustEncodeString(message))
|
||||||
switch message.Type {
|
|
||||||
case "proxy":
|
|
||||||
var data *ProxyType
|
|
||||||
gjson.DecodeTo(message.Data, &data)
|
|
||||||
//g.Dump(data)
|
|
||||||
// Client
|
|
||||||
for {
|
|
||||||
if conn, err := gtcp.NewConn(fmt.Sprintf("%s:%v", data.Ip, data.Port)); err == nil {
|
|
||||||
if b, err := conn.SendRecv([]byte(gtime.Datetime()), -1); err == nil {
|
|
||||||
fmt.Println(string(b), conn.LocalAddr(), conn.RemoteAddr())
|
|
||||||
|
|
||||||
err = s.SendP2P(message.From, "proxy_ack", gjson.MustEncode(&ProxyType{
|
if this, ok := messageFunc.Run[message.Type]; ok {
|
||||||
Ip: ip,
|
err := this.Message(message)
|
||||||
Port: message.Port,
|
if err != nil {
|
||||||
Data: b,
|
g.Log().Error(ctx, err)
|
||||||
}))
|
|
||||||
} else {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
conn.Close()
|
|
||||||
} else {
|
|
||||||
//glog.Error(err)
|
|
||||||
}
|
|
||||||
//time.Sleep(time.Second)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//conn, err := gtcp.NewConn(fmt.Sprintf("%s:%v", data.Ip, data.Port))
|
|
||||||
//if err != nil {
|
|
||||||
// g.Log().Errorf(ctx, "连接失败:%v", err)
|
|
||||||
// return
|
|
||||||
//}
|
|
||||||
//defer conn.Close()
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,8 +26,8 @@ type DHTType struct {
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
//bootstrapPeers = []string{
|
//bootstrapPeers = []string{
|
||||||
// "/ip4/192.168.50.173/tcp/53486/p2p/12D3KooWE3v9623SLukT9dKUQLjqAJrPvzoyRjoUh5MAVGDg69Rw",
|
// "/ip4/192.168.50.173/tcp/53486/message/12D3KooWE3v9623SLukT9dKUQLjqAJrPvzoyRjoUh5MAVGDg69Rw",
|
||||||
// "/ip4/192.168.50.173/udp/53486/quic-v1/p2p/12D3KooWE3v9623SLukT9dKUQLjqAJrPvzoyRjoUh5MAVGDg69Rw",
|
// "/ip4/192.168.50.173/udp/53486/quic-v1/message/12D3KooWE3v9623SLukT9dKUQLjqAJrPvzoyRjoUh5MAVGDg69Rw",
|
||||||
//}
|
//}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -40,19 +40,19 @@ func (s *sP2P) DHTStart(h host.Host, bootstrapPeers []string) (err error) {
|
|||||||
|
|
||||||
if len(bootstrapPeers) == 0 {
|
if len(bootstrapPeers) == 0 {
|
||||||
bootstrapPeers = []string{
|
bootstrapPeers = []string{
|
||||||
//"/ip4/192.168.50.243/tcp/23333/p2p/12D3KooWESZtrm6AfqhC3oj5FsAbcSmePwHFFip3F2MPExrxHxwy",
|
//"/ip4/192.168.50.243/tcp/23333/message/12D3KooWESZtrm6AfqhC3oj5FsAbcSmePwHFFip3F2MPExrxHxwy",
|
||||||
//"/ip4/192.168.50.243/udp/23333/quic-v1/p2p/12D3KooWESZtrm6AfqhC3oj5FsAbcSmePwHFFip3F2MPExrxHxwy",
|
//"/ip4/192.168.50.243/udp/23333/quic-v1/message/12D3KooWESZtrm6AfqhC3oj5FsAbcSmePwHFFip3F2MPExrxHxwy",
|
||||||
//
|
//
|
||||||
//"/ip4/192.168.50.173/tcp/23333/p2p/12D3KooWKgW8WxncYzZ2h5erMbK3GfLGhNHFapPvhUc1KVmdZeRg",
|
//"/ip4/192.168.50.173/tcp/23333/message/12D3KooWKgW8WxncYzZ2h5erMbK3GfLGhNHFapPvhUc1KVmdZeRg",
|
||||||
//"/ip4/192.168.50.173/udp/23333/quic-v1/p2p/12D3KooWKgW8WxncYzZ2h5erMbK3GfLGhNHFapPvhUc1KVmdZeRg",
|
//"/ip4/192.168.50.173/udp/23333/quic-v1/message/12D3KooWKgW8WxncYzZ2h5erMbK3GfLGhNHFapPvhUc1KVmdZeRg",
|
||||||
|
|
||||||
//肖晓
|
//肖晓
|
||||||
"/ip4/192.168.50.244/tcp/23333/p2p/12D3KooWFAt3hTi2SaYNty4gxxBnLRFxJidRDcf4k8HqCUZZRY1W",
|
"/ip4/192.168.50.244/tcp/23333/message/12D3KooWFAt3hTi2SaYNty4gxxBnLRFxJidRDcf4k8HqCUZZRY1W",
|
||||||
"/ip4/192.168.50.244/udp/23333/quic-v1/p2p/12D3KooWFAt3hTi2SaYNty4gxxBnLRFxJidRDcf4k8HqCUZZRY1W",
|
"/ip4/192.168.50.244/udp/23333/quic-v1/message/12D3KooWFAt3hTi2SaYNty4gxxBnLRFxJidRDcf4k8HqCUZZRY1W",
|
||||||
|
|
||||||
//廖玉龙
|
//廖玉龙
|
||||||
"/ip4/192.168.50.210/tcp/23333/p2p/12D3KooWM8eE3i2EWB2wFVGM1URusBPHJrEQJGxKfKgPdxEMm9hn",
|
"/ip4/192.168.50.210/tcp/23333/message/12D3KooWM8eE3i2EWB2wFVGM1URusBPHJrEQJGxKfKgPdxEMm9hn",
|
||||||
"/ip4/192.168.50.210/udp/23333/quic-v1/p2p/12D3KooWM8eE3i2EWB2wFVGM1URusBPHJrEQJGxKfKgPdxEMm9hn",
|
"/ip4/192.168.50.210/udp/23333/quic-v1/message/12D3KooWM8eE3i2EWB2wFVGM1URusBPHJrEQJGxKfKgPdxEMm9hn",
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -299,7 +299,7 @@ func (s *sP2P) printRoutingTable(ctx context.Context, kadDHT *dht.IpfsDHT, inter
|
|||||||
func (s *sP2P) printNodeAddrs(host host.Host) {
|
func (s *sP2P) printNodeAddrs(host host.Host) {
|
||||||
fmt.Println("节点地址(公网地址将自动同步到DHT):")
|
fmt.Println("节点地址(公网地址将自动同步到DHT):")
|
||||||
for _, addr := range host.Addrs() {
|
for _, addr := range host.Addrs() {
|
||||||
fullAddr := fmt.Sprintf("%s/p2p/%s", addr, host.ID())
|
fullAddr := fmt.Sprintf("%s/message/%s", addr, host.ID())
|
||||||
ipStr, _ := addr.ValueForProtocol(multiaddr.P_IP4)
|
ipStr, _ := addr.ValueForProtocol(multiaddr.P_IP4)
|
||||||
ipObj := net.ParseIP(ipStr)
|
ipObj := net.ParseIP(ipStr)
|
||||||
if ipObj.IsPrivate() || ipObj.IsLoopback() {
|
if ipObj.IsPrivate() || ipObj.IsLoopback() {
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ var (
|
|||||||
|
|
||||||
// 常量定义
|
// 常量定义
|
||||||
const (
|
const (
|
||||||
ProtocolID string = "/ay/p2p/1.0.0"
|
ProtocolID string = "/ay/message/1.0.0"
|
||||||
//DefaultPort = 51888
|
//DefaultPort = 51888
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -62,6 +62,7 @@ type sP2P struct {
|
|||||||
dht *DHTType
|
dht *DHTType
|
||||||
privKey crypto.PrivKey
|
privKey crypto.PrivKey
|
||||||
client *Client
|
client *Client
|
||||||
|
IdLock map[string]sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// New 创建一个新的 P2P 服务实例
|
// New 创建一个新的 P2P 服务实例
|
||||||
@@ -189,7 +190,7 @@ func (s *sP2P) removeDuplicates(strs []string) []string {
|
|||||||
|
|
||||||
// 生成固定密钥(核心:通过固定种子生成相同密钥)
|
// 生成固定密钥(核心:通过固定种子生成相同密钥)
|
||||||
func (s *sP2P) generateFixedKey() (crypto.PrivKey, error) {
|
func (s *sP2P) generateFixedKey() (crypto.PrivKey, error) {
|
||||||
privKeyPath := "runtime/p2p.key"
|
privKeyPath := "runtime/message.key"
|
||||||
if ok := gfile.Exists(privKeyPath); ok {
|
if ok := gfile.Exists(privKeyPath); ok {
|
||||||
// 从文件读取密钥
|
// 从文件读取密钥
|
||||||
keyBytes := gfile.GetBytes(privKeyPath)
|
keyBytes := gfile.GetBytes(privKeyPath)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package p2p
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/gogf/gf/v2/encoding/gjson"
|
"github.com/gogf/gf/v2/encoding/gjson"
|
||||||
"github.com/gogf/gf/v2/frame/g"
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
@@ -16,22 +17,50 @@ type ProxyType struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *sP2P) ProxyInit() {
|
func (s *sP2P) ProxyInit() {
|
||||||
type cfgType struct {
|
type tcpCfgType struct {
|
||||||
Key string `json:"key"`
|
Key string `json:"key"`
|
||||||
Ip string `json:"ip"`
|
Ip string `json:"ip"`
|
||||||
Port int `json:"port"`
|
Port int `json:"port"`
|
||||||
LocalPort int `json:"local_port"`
|
LocalPort int `json:"local_port"`
|
||||||
}
|
}
|
||||||
var cfgList []*cfgType
|
var tcpCfgList []*tcpCfgType
|
||||||
proxyCfg, err := g.Cfg("proxy").Get(gctx.New(), "tcp")
|
tcpCfg, err := g.Cfg("proxy").Get(gctx.New(), "tcp")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
proxyCfg.Scan(&cfgList)
|
tcpCfg.Scan(&tcpCfgList)
|
||||||
for _, v := range cfgList {
|
for _, v := range tcpCfgList {
|
||||||
go s.Tcp(v.Key, v.Port, v.LocalPort, v.Ip)
|
go s.Tcp(v.Key, v.Port, v.LocalPort, v.Ip)
|
||||||
|
time.Sleep(2 * time.Second)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
type httpCfgType struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
Ip string `json:"ip"`
|
||||||
|
Port int `json:"port"`
|
||||||
|
Cname string `json:"cname"`
|
||||||
|
}
|
||||||
|
var httpCfgList []*httpCfgType
|
||||||
|
httpCfg, err := g.Cfg("proxy").Get(gctx.New(), "tcp")
|
||||||
|
if err == nil {
|
||||||
|
httpCfg.Scan(&httpCfgList)
|
||||||
|
for _, v := range httpCfgList {
|
||||||
|
go s.Http(v.Key, v.Cname, v.Port, v.Ip)
|
||||||
|
time.Sleep(2 * time.Second)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var TcpList = make(map[int]*gtcp.Conn)
|
||||||
|
|
||||||
|
func (s *sP2P) TcpAck(port int) *gtcp.Conn {
|
||||||
|
if v, ok := TcpList[port]; ok {
|
||||||
|
return v
|
||||||
|
} else {
|
||||||
|
g.Log().Errorf(gctx.New(), "端口:%v不存在", port)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sP2P) Tcp(key string, toPort, myPort int, ip string) {
|
func (s *sP2P) Tcp(key string, toPort, myPort int, ip string) {
|
||||||
@@ -42,16 +71,20 @@ func (s *sP2P) Tcp(key string, toPort, myPort int, ip string) {
|
|||||||
// 建立p2p连接
|
// 建立p2p连接
|
||||||
err := s.DiscoverAndConnect(key)
|
err := s.DiscoverAndConnect(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
g.Log().Errorf(gctx.New(), "连接失败:%v", err)
|
||||||
|
time.Sleep(3 * time.Second)
|
||||||
|
s.Tcp(key, toPort, myPort, ip)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
err = gtcp.NewServer(fmt.Sprintf("0.0.0.0:%d", myPort), func(conn *gtcp.Conn) {
|
err = gtcp.NewServer(fmt.Sprintf("0.0.0.0:%d", myPort), func(conn *gtcp.Conn) {
|
||||||
|
TcpList[toPort] = conn
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
for {
|
for {
|
||||||
ctx := gctx.New()
|
ctx := gctx.New()
|
||||||
data, err := conn.Recv(-1)
|
data, err := conn.Recv(-1)
|
||||||
|
|
||||||
if len(data) > 0 {
|
if len(data) > 0 {
|
||||||
g.Log().Debugf(gctx.New(), "内容:%v", string(data))
|
g.Log().Debugf(gctx.New(), "本地接口收到内容:%v", string(data))
|
||||||
err = s.SendP2P(key, "proxy", gjson.MustEncode(&ProxyType{
|
err = s.SendP2P(key, "proxy", gjson.MustEncode(&ProxyType{
|
||||||
Ip: ip,
|
Ip: ip,
|
||||||
Port: toPort,
|
Port: toPort,
|
||||||
@@ -76,3 +109,19 @@ func (s *sP2P) Tcp(key string, toPort, myPort int, ip string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *sP2P) Http(key string, cname string, toPort int, ip string) {
|
||||||
|
if toPort == 0 {
|
||||||
|
toPort = 80
|
||||||
|
}
|
||||||
|
|
||||||
|
// 建立p2p连接
|
||||||
|
err := s.DiscoverAndConnect(key)
|
||||||
|
if err != nil {
|
||||||
|
g.Log().Errorf(gctx.New(), "连接失败:%v", err)
|
||||||
|
time.Sleep(3 * time.Second)
|
||||||
|
s.Http(key, cname, toPort, ip)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -77,9 +77,9 @@ func (s *sSystem) RestartSelf() error {
|
|||||||
return nil // 理论上不会执行到这里
|
return nil // 理论上不会执行到这里
|
||||||
}
|
}
|
||||||
|
|
||||||
// RenameRunningFile 重命名正在运行的程序文件(如 p2p.exe → p2p.exe~)
|
// RenameRunningFile 重命名正在运行的程序文件(如 message.exe → message.exe~)
|
||||||
func (s *sSystem) RenameRunningFile(exePath string) (string, error) {
|
func (s *sSystem) RenameRunningFile(exePath string) (string, error) {
|
||||||
// 目标备份文件名(p2p.exe → p2p.exe~)
|
// 目标备份文件名(message.exe → message.exe~)
|
||||||
backupPath := exePath + "~"
|
backupPath := exePath + "~"
|
||||||
|
|
||||||
// 先删除已存在的备份文件(若有)
|
// 先删除已存在的备份文件(若有)
|
||||||
|
|||||||
18
internal/message/consts.go
Normal file
18
internal/message/consts.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package message
|
||||||
|
|
||||||
|
import (
|
||||||
|
v1 "github.com/ayflying/p2p/api/p2p/v1"
|
||||||
|
"github.com/ayflying/p2p/internal/message/http"
|
||||||
|
"github.com/ayflying/p2p/internal/message/proxy"
|
||||||
|
"github.com/ayflying/p2p/internal/message/proxyAck"
|
||||||
|
)
|
||||||
|
|
||||||
|
type P2PMessage interface {
|
||||||
|
Message(msg *v1.Message) (err error)
|
||||||
|
}
|
||||||
|
|
||||||
|
var Run = map[string]P2PMessage{
|
||||||
|
"proxy": proxy.New,
|
||||||
|
"proxy_ack": proxyAck.New,
|
||||||
|
"http": http.New,
|
||||||
|
}
|
||||||
17
internal/message/http/http.go
Normal file
17
internal/message/http/http.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package http
|
||||||
|
|
||||||
|
import v1 "github.com/ayflying/p2p/api/p2p/v1"
|
||||||
|
|
||||||
|
type Http struct {
|
||||||
|
Ip string `json:"ip"`
|
||||||
|
Port int `json:"port"`
|
||||||
|
Cname string `json:"cname"`
|
||||||
|
Data []byte `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var New = Http{}
|
||||||
|
|
||||||
|
func (h Http) Message(msg *v1.Message) (err error) {
|
||||||
|
//TODO implement me
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
68
internal/message/proxy/proxy.go
Normal file
68
internal/message/proxy/proxy.go
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
package proxy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/ayflying/p2p/api/p2p/v1"
|
||||||
|
"github.com/ayflying/p2p/internal/service"
|
||||||
|
"github.com/gogf/gf/v2/encoding/gjson"
|
||||||
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
|
"github.com/gogf/gf/v2/net/gtcp"
|
||||||
|
"github.com/gogf/gf/v2/os/gctx"
|
||||||
|
"github.com/gogf/gf/v2/os/gtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
var New = Proxy{}
|
||||||
|
|
||||||
|
var (
|
||||||
|
//ip, _ = service.P2P().GetIPv4PublicIP()
|
||||||
|
)
|
||||||
|
|
||||||
|
type Proxy struct {
|
||||||
|
Ip string `json:"ip"`
|
||||||
|
Port int `json:"port"`
|
||||||
|
Data []byte `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Proxy) Message(msg *v1.Message) (err error) {
|
||||||
|
var data *Proxy
|
||||||
|
|
||||||
|
gjson.DecodeTo(msg.Data, &data)
|
||||||
|
//g.Dump(data)
|
||||||
|
// Client
|
||||||
|
go func() {
|
||||||
|
if conn, err := gtcp.NewConn(fmt.Sprintf("%s:%v", data.Ip, data.Port)); err == nil {
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
err = conn.Send(data.Data)
|
||||||
|
if b, err := conn.SendRecv([]byte(gtime.Datetime()), -1); err == nil {
|
||||||
|
//fmt.Println(string(b), conn.LocalAddr(), conn.RemoteAddr())
|
||||||
|
|
||||||
|
err = service.P2P().SendP2P(msg.From, "proxy_ack", gjson.MustEncode(&Proxy{
|
||||||
|
Ip: data.Ip,
|
||||||
|
Port: data.Port,
|
||||||
|
Data: b,
|
||||||
|
}))
|
||||||
|
if err != nil {
|
||||||
|
g.Log().Errorf(gctx.New(), "发送ACK失败:%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
//glog.Error(err)
|
||||||
|
}
|
||||||
|
//time.Sleep(time.Second)
|
||||||
|
|
||||||
|
}()
|
||||||
|
|
||||||
|
//conn, err := gtcp.NewConn(fmt.Sprintf("%s:%v", data.Ip, data.Port))
|
||||||
|
//if err != nil {
|
||||||
|
// g.Log().Errorf(ctx, "连接失败:%v", err)
|
||||||
|
// return
|
||||||
|
//}
|
||||||
|
//defer conn.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
28
internal/message/proxyAck/proxyAck.go
Normal file
28
internal/message/proxyAck/proxyAck.go
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package proxyAck
|
||||||
|
|
||||||
|
import (
|
||||||
|
v1 "github.com/ayflying/p2p/api/p2p/v1"
|
||||||
|
"github.com/ayflying/p2p/internal/service"
|
||||||
|
"github.com/gogf/gf/v2/encoding/gjson"
|
||||||
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
|
"github.com/gogf/gf/v2/os/gctx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ProxyAck struct {
|
||||||
|
Ip string `json:"ip"`
|
||||||
|
Port int `json:"port"`
|
||||||
|
Data []byte `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var New = ProxyAck{}
|
||||||
|
|
||||||
|
func (p ProxyAck) Message(msg *v1.Message) (err error) {
|
||||||
|
var data *ProxyAck
|
||||||
|
gjson.DecodeTo(msg.Data, &data)
|
||||||
|
//g.Dump(data)
|
||||||
|
|
||||||
|
g.Log().Debugf(gctx.New(), "收到ACK发送到端口:%v", data.Port)
|
||||||
|
err = service.P2P().TcpAck(data.Port).Send(data.Data)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/gogf/gf/v2/net/ghttp"
|
"github.com/gogf/gf/v2/net/ghttp"
|
||||||
|
"github.com/gogf/gf/v2/net/gtcp"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"github.com/libp2p/go-libp2p/core/host"
|
"github.com/libp2p/go-libp2p/core/host"
|
||||||
)
|
)
|
||||||
@@ -38,7 +39,9 @@ type (
|
|||||||
// 只获取IPv4公网IP(过滤IPv6结果)
|
// 只获取IPv4公网IP(过滤IPv6结果)
|
||||||
GetIPv4PublicIP() (string, error)
|
GetIPv4PublicIP() (string, error)
|
||||||
ProxyInit()
|
ProxyInit()
|
||||||
|
TcpAck(port int) *gtcp.Conn
|
||||||
Tcp(key string, toPort int, myPort int, ip string)
|
Tcp(key string, toPort int, myPort int, ip string)
|
||||||
|
Http(key string, cname string, toPort int, ip string)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ type (
|
|||||||
Update(ctx context.Context) (err error)
|
Update(ctx context.Context) (err error)
|
||||||
// RestartSelf 实现 Windows 平台下的程序自重启
|
// RestartSelf 实现 Windows 平台下的程序自重启
|
||||||
RestartSelf() error
|
RestartSelf() error
|
||||||
// RenameRunningFile 重命名正在运行的程序文件(如 p2p.exe → p2p.exe~)
|
// RenameRunningFile 重命名正在运行的程序文件(如 message.exe → message.exe~)
|
||||||
RenameRunningFile(exePath string) (string, error)
|
RenameRunningFile(exePath string) (string, error)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
4
runtime/message.key
Normal file
4
runtime/message.key
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
-----BEGIN LIBP2P PRIVATE KEY-----
|
||||||
|
CAESQJTRc7CwETt8Pw4dNOP3Vz5w157n2tbm4qfdHDFSybcLoJwGI5vjuCZJhktH
|
||||||
|
fMuZUxXG/zdvVyv7eLmUIpxNdSI=
|
||||||
|
-----END LIBP2P PRIVATE KEY-----
|
||||||
Reference in New Issue
Block a user