mirror of
https://github.com/ayflying/p2p.git
synced 2026-03-04 17:29:22 +00:00
增加更新重启逻辑
This commit is contained in:
@@ -2,7 +2,6 @@ package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/ayflying/p2p/internal/controller/p2p"
|
||||
@@ -23,6 +22,8 @@ func init() {
|
||||
}
|
||||
|
||||
var (
|
||||
s = g.Server()
|
||||
|
||||
Main = gcmd.Command{
|
||||
Name: "main",
|
||||
Usage: "main",
|
||||
@@ -38,7 +39,6 @@ var (
|
||||
ws := parser.GetOpt("ws", addr).String()
|
||||
//port := parser.GetOpt("port", 0).Int()
|
||||
|
||||
s := g.Server()
|
||||
s.Group("/", func(group *ghttp.RouterGroup) {
|
||||
group.Middleware(ghttp.MiddlewareHandlerResponse)
|
||||
group.Bind(
|
||||
@@ -64,12 +64,12 @@ var (
|
||||
err = service.P2P().Start(ctx, ws)
|
||||
|
||||
g.Log().Debugf(ctx, "当前监听端口:%v", s.GetListenedPort())
|
||||
addrs, _ := net.InterfaceAddrs()
|
||||
for _, addr := range addrs {
|
||||
if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() && ipnet.IP.To4() != nil {
|
||||
g.Log().Infof(ctx, "访问地址:http://%v:%d", ipnet.IP.String(), s.GetListenedPort())
|
||||
}
|
||||
}
|
||||
//addrs, _ := net.InterfaceAddrs()
|
||||
//for _, addr := range addrs {
|
||||
// if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() && ipnet.IP.To4() != nil {
|
||||
// g.Log().Infof(ctx, "访问地址:http://%v:%d", ipnet.IP.String(), s.GetListenedPort())
|
||||
// }
|
||||
//}
|
||||
|
||||
})
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package cmd
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/ayflying/p2p/internal/service"
|
||||
"github.com/dop251/goja"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gcmd"
|
||||
@@ -50,11 +51,13 @@ var (
|
||||
msg = res.Export()
|
||||
g.Dump(res.ToNumber())
|
||||
case "p2p":
|
||||
// host, err := service.P2P().Start(ctx)
|
||||
// if err != nil {
|
||||
// break
|
||||
// }
|
||||
// g.Dump(host.ID().String(), host.Addrs())
|
||||
// host, err := service.P2P().Start(ctx)
|
||||
// if err != nil {
|
||||
// break
|
||||
// }
|
||||
// g.Dump(host.ID().String(), host.Addrs())
|
||||
case "update":
|
||||
service.OS().Update("v1.0.0", "http://127.0.0.1:8080")
|
||||
}
|
||||
g.Log().Debug(ctx, msg)
|
||||
return
|
||||
|
||||
@@ -84,9 +84,7 @@ var (
|
||||
|
||||
publicIp, err := service.P2P().GetIPv4PublicIP()
|
||||
err = service.P2P().StoreAddrToDHT(ctx, "ip", publicIp)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
case "dht2":
|
||||
h, _ := service.P2P().CreateLibp2pHost(ctx, 0)
|
||||
err := service.P2P().DHTStart(ctx, h)
|
||||
@@ -95,7 +93,7 @@ var (
|
||||
}
|
||||
get, _ := service.P2P().FindAddrFromDHT(ctx, "ip")
|
||||
g.Dump(get)
|
||||
|
||||
s.SetPort(0)
|
||||
default:
|
||||
// 显示帮助信息
|
||||
g.Log().Info(ctx, p2pHelpDescription)
|
||||
|
||||
@@ -1 +1,6 @@
|
||||
package consts
|
||||
|
||||
const (
|
||||
// 应用名称
|
||||
Name = "P2P"
|
||||
)
|
||||
|
||||
@@ -8,6 +8,6 @@ import (
|
||||
)
|
||||
|
||||
func (c *ControllerV1) Send(ctx context.Context, req *v1.SendReq) (res *v1.SendRes, err error) {
|
||||
err = service.P2P().SendData(req.TargetID, []byte(req.Data))
|
||||
err = service.P2P().SendP2P(req.TargetID, "message", []byte(req.Data))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -5,5 +5,6 @@
|
||||
package logic
|
||||
|
||||
import (
|
||||
_ "github.com/ayflying/p2p/internal/logic/os"
|
||||
_ "github.com/ayflying/p2p/internal/logic/p2p"
|
||||
)
|
||||
|
||||
11
internal/logic/os/linux.go
Normal file
11
internal/logic/os/linux.go
Normal file
@@ -0,0 +1,11 @@
|
||||
//go:build !windows
|
||||
|
||||
package os
|
||||
|
||||
func (s *sOS) start() {
|
||||
|
||||
}
|
||||
|
||||
func (s *sOS) update(version, server string) {
|
||||
|
||||
}
|
||||
45
internal/logic/os/os.go
Normal file
45
internal/logic/os/os.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package os
|
||||
|
||||
import (
|
||||
"github.com/ayflying/p2p/internal/service"
|
||||
"github.com/gogf/gf/v2/os/gcmd"
|
||||
)
|
||||
|
||||
type systrayType struct {
|
||||
Icon string `json:"icon" dc:"图标"`
|
||||
Title string `json:"title" dc:"标题"`
|
||||
Tooltip string `json:"tooltip" dc:"提示"`
|
||||
}
|
||||
|
||||
type sOS struct {
|
||||
systray *systrayType
|
||||
}
|
||||
|
||||
func New() *sOS {
|
||||
return &sOS{
|
||||
systray: &systrayType{},
|
||||
}
|
||||
}
|
||||
func init() {
|
||||
service.RegisterOS(New())
|
||||
}
|
||||
|
||||
func (s *sOS) Load(title string, tooltip string, ico string) {
|
||||
if title == "" {
|
||||
title = gcmd.GetArg(0).String()
|
||||
}
|
||||
if tooltip == "" {
|
||||
tooltip = gcmd.GetArg(0).String()
|
||||
}
|
||||
|
||||
s.systray = &systrayType{
|
||||
Icon: ico,
|
||||
Title: title,
|
||||
Tooltip: tooltip,
|
||||
}
|
||||
s.start()
|
||||
}
|
||||
|
||||
func (s *sOS) Update(version, server string) {
|
||||
s.update(version, server)
|
||||
}
|
||||
64
internal/logic/os/windows.go
Normal file
64
internal/logic/os/windows.go
Normal file
@@ -0,0 +1,64 @@
|
||||
//go:build windows
|
||||
|
||||
package os
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"syscall"
|
||||
|
||||
"github.com/getlantern/systray"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gcmd"
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
)
|
||||
|
||||
func (s *sOS) start() {
|
||||
|
||||
// 系统托盘初始化(设置图标、右键菜单)
|
||||
go systray.Run(s.onSystrayReady, s.onSystrayExit)
|
||||
}
|
||||
|
||||
// 系统托盘初始化(设置图标、右键菜单)
|
||||
func (s *sOS) onSystrayReady() {
|
||||
|
||||
iconByte := gfile.GetBytes(s.systray.Icon)
|
||||
systray.SetIcon(iconByte)
|
||||
systray.SetTitle(s.systray.Title)
|
||||
systray.SetTooltip(s.systray.Tooltip)
|
||||
|
||||
mQuit := systray.AddMenuItem("退出", "退出应用")
|
||||
systray.AddMenuItemCheckbox("隐藏窗口", "隐藏窗口", false)
|
||||
// Sets the icon of a menu item. Only available on Mac and Windows.
|
||||
//mQuit.SetIcon(iconByte)
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-mQuit.ClickedCh:
|
||||
systray.Quit()
|
||||
}
|
||||
|
||||
}
|
||||
}()
|
||||
|
||||
}
|
||||
|
||||
func (s *sOS) onSystrayExit() {
|
||||
// clean up here
|
||||
g.Log().Debugf(gctx.New(), "系统托盘退出")
|
||||
defer os.Exit(0)
|
||||
|
||||
}
|
||||
|
||||
func (s *sOS) update(version, server string) {
|
||||
updaterPath := gcmd.GetArg(0).String()
|
||||
// 启动更新器,传递主程序路径和当前版本作为参数
|
||||
cmd := exec.Command(updaterPath, version, server)
|
||||
// 将更新器与主程序的控制台分离
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: false} // Windows特定设置
|
||||
|
||||
if err := cmd.Start(); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -4,9 +4,11 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"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"
|
||||
@@ -33,6 +35,41 @@ type Client struct {
|
||||
host host.Host
|
||||
wsConn *websocket.Conn // WebSocket连接
|
||||
peers map[string]peer.ID // 存储已连接的节点
|
||||
//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 发送格式化消息
|
||||
func (s *sP2P) SendP2P(targetID string, typ string, data []byte) (err error) {
|
||||
message := &Message{
|
||||
Type: "message",
|
||||
From: s.client.Id,
|
||||
Data: data,
|
||||
}
|
||||
err = s.sendData(targetID, gjson.MustEncode(message))
|
||||
return
|
||||
}
|
||||
|
||||
func (s *sP2P) linkTcp(addr string) {
|
||||
//conn, err := gtcp.Dial(addr)
|
||||
|
||||
// 使用标准库 net.Dial 建立连接
|
||||
stdConn, err := net.Dial("tcp", addr)
|
||||
if err != nil {
|
||||
fmt.Printf("Dial error: %v\n", err)
|
||||
return
|
||||
}
|
||||
defer stdConn.Close()
|
||||
|
||||
//// 将标准库的 net.Conn 封装为 gtcp.Conn
|
||||
//gtcpConn := gtcp.NewConn(stdConn)
|
||||
//defer gtcpConn.Close()
|
||||
}
|
||||
|
||||
func (s *sP2P) Start(ctx context.Context, wsStr string) (err error) {
|
||||
@@ -177,7 +214,7 @@ func (s *sP2P) handleStream(stream network.Stream) {
|
||||
defer stream.Close()
|
||||
|
||||
peerID := stream.Conn().RemotePeer().String()
|
||||
glog.Infof(ctx, "收到来自 %s 的连接", peerID)
|
||||
//glog.Infof(ctx, "收到来自 %s 的连接", peerID)
|
||||
|
||||
// 读取数据
|
||||
buf := make([]byte, 1024)
|
||||
@@ -187,11 +224,15 @@ func (s *sP2P) handleStream(stream network.Stream) {
|
||||
return
|
||||
}
|
||||
|
||||
g.Log().Debugf(ctx, "收到来自 %s 的消息: %v> ", peerID, string(buf[:n]))
|
||||
var msg = buf[:n]
|
||||
// 解析消息
|
||||
var message *Message
|
||||
err = gjson.DecodeTo(msg, &message)
|
||||
g.Log().Debugf(ctx, "收到来自 %s 的消息: %v ", peerID, gjson.MustEncodeString(message))
|
||||
}
|
||||
|
||||
// 发送数据到目标节点
|
||||
func (s *sP2P) SendData(targetID string, data []byte) error {
|
||||
func (s *sP2P) sendData(targetID string, data []byte) error {
|
||||
peerID, exists := s.client.peers[targetID]
|
||||
if !exists {
|
||||
return fmt.Errorf("未找到目标节点 %s 的连接", targetID)
|
||||
@@ -325,6 +366,8 @@ func (s *sP2P) receiveGatewayMessages() {
|
||||
continue
|
||||
}
|
||||
|
||||
g.Log().Infof(ctx, "准备开始打洞到目标节点:%v", msgData.TargetID)
|
||||
|
||||
addrs := make([]multiaddr.Multiaddr, len(msgData.Addrs))
|
||||
for i, addrStr := range msgData.Addrs {
|
||||
addr, err := multiaddr.NewMultiaddr(addrStr)
|
||||
@@ -361,6 +404,21 @@ func (s *sP2P) receiveGatewayMessages() {
|
||||
}
|
||||
json.Unmarshal(msg.Data, &data)
|
||||
glog.Errorf(ctx, "网关错误: %s", data.Error)
|
||||
case MsgUpdate: //更新节点信息
|
||||
var msgData struct {
|
||||
Server string `json:"server"`
|
||||
Version string `json:"version"`
|
||||
}
|
||||
//var msgData *dataType
|
||||
json.Unmarshal(msg.Data, &msgData)
|
||||
// 更新器路径(假设与主程序同目录)
|
||||
//updaterPath := filepath.Join(filepath.Dir(selfPath), "updater.exe")
|
||||
|
||||
g.Log().Infof(ctx, "更新节点信息: %v", data)
|
||||
|
||||
// 调用不同系统的更新服务
|
||||
service.OS().Update(msgData.Version, msgData.Server)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
//"github.com/ipfs/boxo/ipns"
|
||||
dht "github.com/libp2p/go-libp2p-kad-dht"
|
||||
"github.com/libp2p/go-libp2p/core/host"
|
||||
@@ -73,7 +74,8 @@ func (s *sP2P) StoreAddrToDHT(ctx context.Context, key string, addr string) (err
|
||||
if err = s.dht.KadDHT.PutValue(ctx, key, value); err != nil {
|
||||
return fmt.Errorf("key=%s,存储地址到DHT失败: %v", key, err)
|
||||
}
|
||||
fmt.Printf("成功存储地址到DHT,Key=%s, Value=%s\n", key, addr)
|
||||
|
||||
g.Log().Info(ctx, "成功存储地址到DHT,Key=%s, Value=%s", key, addr)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -83,6 +85,7 @@ func (s *sP2P) FindAddrFromDHT(ctx context.Context, key string) (string, error)
|
||||
//key = s.generateStringDHTKey(key)
|
||||
//key = "/ipns/" + key
|
||||
key = fmt.Sprintf("%s/%s", ProtocolID, key)
|
||||
g.Log().Debugf(ctx, "从DHT查找地址中...,Key=%s", key)
|
||||
value, err := s.dht.KadDHT.GetValue(ctx, key)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("从DHT查找地址失败: %v", err)
|
||||
|
||||
@@ -39,8 +39,9 @@ const (
|
||||
MsgTypeDiscover = "discover" // 发现目标客户端
|
||||
MsgTypeDiscoverAck = "discover_ack" // 发现响应
|
||||
MsgTypeConnectionReq = "connection_req" // 连接请求通知
|
||||
MsgTypePunchRequest = "punch_request"
|
||||
MsgTypeError = "error" // 错误消息
|
||||
MsgTypePunchRequest = "punch_request" // 打洞请求
|
||||
MsgTypeError = "error" // 错误消息
|
||||
MsgUpdate = "update" // 更新节点信息
|
||||
)
|
||||
|
||||
// 注册请求数据
|
||||
|
||||
28
internal/service/os.go
Normal file
28
internal/service/os.go
Normal file
@@ -0,0 +1,28 @@
|
||||
// ================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// You can delete these comments if you wish manually maintain this interface file.
|
||||
// ================================================================================
|
||||
|
||||
package service
|
||||
|
||||
type (
|
||||
IOS interface {
|
||||
Load(title string, tooltip string, ico string)
|
||||
Update(version string, server string)
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
localOS IOS
|
||||
)
|
||||
|
||||
func OS() IOS {
|
||||
if localOS == nil {
|
||||
panic("implement not found for interface IOS, forgot register?")
|
||||
}
|
||||
return localOS
|
||||
}
|
||||
|
||||
func RegisterOS(i IOS) {
|
||||
localOS = i
|
||||
}
|
||||
@@ -14,13 +14,13 @@ import (
|
||||
|
||||
type (
|
||||
IP2P interface {
|
||||
// SendP2P 发送格式化消息
|
||||
SendP2P(targetID string, typ string, data []byte) (err error)
|
||||
Start(ctx context.Context, wsStr string) (err error)
|
||||
// 创建libp2p主机
|
||||
CreateLibp2pHost(ctx context.Context, port int) (host.Host, error)
|
||||
// 发现并连接目标节点
|
||||
DiscoverAndConnect(targetID string) error
|
||||
// 发送数据到目标节点
|
||||
SendData(targetID string, data []byte) error
|
||||
// 初始化无服务器DHT(作为节点加入DHT网络)
|
||||
DHTStart(ctx context.Context, h host.Host) (err error)
|
||||
// 存储数据到DHT(比如存储“目标节点ID-公网地址”的映射)
|
||||
|
||||
Reference in New Issue
Block a user