mirror of
https://github.com/ayflying/p2p.git
synced 2026-03-04 17:29:22 +00:00
首次提交
This commit is contained in:
0
internal/logic/.gitkeep
Normal file
0
internal/logic/.gitkeep
Normal file
9
internal/logic/logic.go
Normal file
9
internal/logic/logic.go
Normal file
@@ -0,0 +1,9 @@
|
||||
// ==========================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// ==========================================================================
|
||||
|
||||
package logic
|
||||
|
||||
import (
|
||||
_ "github.com/ayflying/p2p/internal/logic/p2p"
|
||||
)
|
||||
326
internal/logic/p2p/client.go
Normal file
326
internal/logic/p2p/client.go
Normal file
@@ -0,0 +1,326 @@
|
||||
package p2p
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/v2/encoding/gjson"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
"github.com/gogf/gf/v2/os/glog"
|
||||
"github.com/google/uuid"
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/libp2p/go-libp2p"
|
||||
"github.com/libp2p/go-libp2p/core/host"
|
||||
"github.com/libp2p/go-libp2p/core/network"
|
||||
"github.com/libp2p/go-libp2p/core/peer"
|
||||
"github.com/libp2p/go-libp2p/core/peerstore"
|
||||
"github.com/libp2p/go-libp2p/core/protocol"
|
||||
"github.com/multiformats/go-multiaddr"
|
||||
)
|
||||
|
||||
// 客户端
|
||||
type Client struct {
|
||||
ctx context.Context
|
||||
Id string
|
||||
gatewayURL string
|
||||
host host.Host
|
||||
wsConn *websocket.Conn // WebSocket连接
|
||||
peers map[string]peer.ID // 存储已连接的节点
|
||||
}
|
||||
|
||||
func (s *sP2P) Start(ctx context.Context, wsStr string) (err error) {
|
||||
|
||||
hostObj, err := s.createLibp2pHost(ctx, 0)
|
||||
if err != nil {
|
||||
g.Log().Error(ctx, err)
|
||||
}
|
||||
//defer hostObj.Close()
|
||||
|
||||
// 创建客户端实例
|
||||
s.client = &Client{
|
||||
ctx: ctx,
|
||||
Id: uuid.New().String(),
|
||||
gatewayURL: wsStr,
|
||||
host: hostObj,
|
||||
peers: make(map[string]peer.ID),
|
||||
}
|
||||
|
||||
// 设置流处理函数(处理P2P消息)
|
||||
hostObj.SetStreamHandler(ProtocolID, s.handleStream)
|
||||
|
||||
// 连接网关(WebSocket)
|
||||
if err = s.connectGateway(); err != nil {
|
||||
glog.Fatalf(ctx, "连接网关失败: %v", err)
|
||||
}
|
||||
|
||||
// 注册到网关
|
||||
if err = s.register(); err != nil {
|
||||
glog.Fatalf(ctx, "注册到网关失败: %v", err)
|
||||
}
|
||||
|
||||
// 启动网关消息接收协程
|
||||
go s.receiveGatewayMessages()
|
||||
|
||||
g.Log().Infof(ctx, "已连接网关成功,客户端ID: %s", s.client.Id)
|
||||
//g.Log().Infof(ctx,"当前地址:http://127.0.0.1/")
|
||||
|
||||
//select {
|
||||
//case <-ctx.Done():
|
||||
//}
|
||||
return
|
||||
}
|
||||
|
||||
// 创建libp2p主机
|
||||
func (s *sP2P) createLibp2pHost(ctx context.Context, port int) (host.Host, error) {
|
||||
// 配置监听地址
|
||||
listenAddr := fmt.Sprintf("/ip4/0.0.0.0/tcp/%d", port)
|
||||
|
||||
// 创建主机
|
||||
h, err := libp2p.New(
|
||||
libp2p.ListenAddrStrings(listenAddr),
|
||||
libp2p.DefaultTransports,
|
||||
libp2p.DefaultMuxers,
|
||||
libp2p.DefaultSecurity,
|
||||
)
|
||||
return h, err
|
||||
}
|
||||
|
||||
// 连接网关(WebSocket)
|
||||
func (s *sP2P) connectGateway() (err error) {
|
||||
conn, _, err := websocket.DefaultDialer.Dial(s.client.gatewayURL, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("WebSocket连接失败: %v", err)
|
||||
}
|
||||
//defer conn.Close()
|
||||
|
||||
s.client.wsConn = conn
|
||||
return
|
||||
}
|
||||
|
||||
// 注册到网关
|
||||
func (s *sP2P) register() error {
|
||||
// 收集地址信息
|
||||
addrs := make([]string, len(s.client.host.Addrs()))
|
||||
for i, addr := range s.client.host.Addrs() {
|
||||
addrs[i] = addr.String()
|
||||
}
|
||||
|
||||
// 构建注册消息
|
||||
msg := GatewayMessage{
|
||||
Type: MsgTypeRegister,
|
||||
From: s.client.Id,
|
||||
Data: gjson.MustEncode(g.Map{
|
||||
"peer_id": s.client.host.ID().String(),
|
||||
"addrs": addrs,
|
||||
}),
|
||||
}
|
||||
|
||||
return s.sendToGateway(msg)
|
||||
}
|
||||
|
||||
// 发现并连接目标节点
|
||||
func (s *sP2P) DiscoverAndConnect(targetID string) error {
|
||||
// 发送发现请求
|
||||
msg := GatewayMessage{
|
||||
Type: MsgTypeDiscover,
|
||||
From: s.client.Id, // 发送方是自己
|
||||
To: "gateway", // 接收方是网关
|
||||
Data: gjson.MustEncode(g.Map{
|
||||
"target_id": targetID,
|
||||
}),
|
||||
}
|
||||
if err := s.sendToGateway(msg); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 处理P2P流
|
||||
func (s *sP2P) handleStream(stream network.Stream) {
|
||||
defer stream.Close()
|
||||
|
||||
peerID := stream.Conn().RemotePeer().String()
|
||||
glog.Infof(ctx, "收到来自 %s 的连接", peerID)
|
||||
|
||||
// 读取数据
|
||||
buf := make([]byte, 1024)
|
||||
n, err := stream.Read(buf)
|
||||
if err != nil {
|
||||
glog.Errorf(ctx, "读取流数据失败: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
g.Log().Debugf(ctx, "收到来自 %s 的消息: %v> ", peerID, string(buf[:n]))
|
||||
}
|
||||
|
||||
// 发送数据到目标节点
|
||||
func (s *sP2P) SendData(targetID string, data []byte) error {
|
||||
peerID, exists := s.client.peers[targetID]
|
||||
if !exists {
|
||||
return fmt.Errorf("未找到目标节点 %s 的连接", targetID)
|
||||
}
|
||||
|
||||
// 创建流
|
||||
stream, err := s.client.host.NewStream(gctx.New(), peerID, protocol.ID("/p2p-chat/1.0.0"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer stream.Close()
|
||||
|
||||
// 发送数据
|
||||
_, err = stream.Write(data)
|
||||
return err
|
||||
}
|
||||
|
||||
// 处理网关的打洞请求
|
||||
func (s *sP2P) handlePunchRequest(data json.RawMessage) error {
|
||||
var punchData struct {
|
||||
FromID string `json:"from_id"`
|
||||
PeerID string `json:"peer_id"`
|
||||
Addrs []string `json:"addrs"`
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(data, &punchData); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 解析PeerID
|
||||
peerID, err := peer.Decode(punchData.PeerID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 解析地址
|
||||
addrs := make([]multiaddr.Multiaddr, len(punchData.Addrs))
|
||||
for i, addrStr := range punchData.Addrs {
|
||||
addr, err := multiaddr.NewMultiaddr(addrStr)
|
||||
if err != nil {
|
||||
glog.Errorf(ctx, "解析地址失败: %v", err)
|
||||
continue
|
||||
}
|
||||
addrs[i] = addr
|
||||
}
|
||||
|
||||
// 添加到peerstore
|
||||
s.client.host.Peerstore().AddAddrs(peerID, addrs, peerstore.PermanentAddrTTL)
|
||||
|
||||
// 立即尝试连接(关键:协调时机)
|
||||
glog.Infof(ctx, "收到打洞请求,尝试连接 %s", punchData.FromID)
|
||||
go func() {
|
||||
time.Sleep(500 * time.Millisecond) // 稍微延迟,确保双方都准备好
|
||||
if err := s.client.host.Connect(ctx, peer.AddrInfo{
|
||||
ID: peerID,
|
||||
Addrs: addrs,
|
||||
}); err != nil {
|
||||
glog.Errorf(ctx, "打洞连接失败: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
glog.Infof(ctx, "成功连接到 %s", punchData.FromID)
|
||||
s.client.peers[punchData.FromID] = peerID
|
||||
}()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 发送消息到网关
|
||||
func (s *sP2P) sendToGateway(msg GatewayMessage) (err error) {
|
||||
data, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = s.client.wsConn.WriteMessage(websocket.TextMessage, data)
|
||||
return
|
||||
}
|
||||
|
||||
// 接收网关消息
|
||||
func (s *sP2P) receiveGatewayMessages() {
|
||||
for {
|
||||
_, data, err := s.client.wsConn.ReadMessage()
|
||||
if err != nil {
|
||||
glog.Errorf(ctx, "接收网关消息失败: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
var msg GatewayMessage
|
||||
if err = json.Unmarshal(data, &msg); err != nil {
|
||||
glog.Errorf(ctx, "解析网关消息失败: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
// 验证消息是否发给自己(to必须是当前客户端ID或空)
|
||||
if msg.To != "" && msg.To != s.client.Id {
|
||||
g.Log().Debugf(ctx, "忽略非本客户端的消息,from=%s, to=%s", msg.From, msg.To)
|
||||
continue
|
||||
}
|
||||
|
||||
// 处理不同类型消息
|
||||
switch msg.Type {
|
||||
case MsgTypeRegisterAck:
|
||||
glog.Infof(ctx, "注册成功")
|
||||
|
||||
case MsgTypeDiscoverAck:
|
||||
var msgData struct {
|
||||
Found bool `json:"found"`
|
||||
PeerID string `json:"peer_id,omitempty"`
|
||||
Addrs []string `json:"addrs,omitempty"`
|
||||
}
|
||||
if err = gjson.DecodeTo(msg.Data, &msgData); err != nil {
|
||||
g.Log().Errorf(ctx, "解析发现响应失败: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
if !msgData.Found {
|
||||
fmt.Println("未找到目标节点")
|
||||
continue
|
||||
}
|
||||
|
||||
// 解析并连接目标节点
|
||||
peerID, err := peer.Decode(msgData.PeerID)
|
||||
if err != nil {
|
||||
glog.Errorf(ctx, "解析PeerID失败: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
addrs := make([]multiaddr.Multiaddr, len(msgData.Addrs))
|
||||
for i, addrStr := range msgData.Addrs {
|
||||
addr, err := multiaddr.NewMultiaddr(addrStr)
|
||||
if err != nil {
|
||||
glog.Errorf(ctx, "解析地址失败: %v", err)
|
||||
continue
|
||||
}
|
||||
addrs[i] = addr
|
||||
}
|
||||
|
||||
s.client.host.Peerstore().AddAddrs(peerID, addrs, peerstore.PermanentAddrTTL)
|
||||
|
||||
// 立即尝试连接
|
||||
go func(targetPeerID peer.ID, targetID string) {
|
||||
time.Sleep(500 * time.Millisecond) // 协调时机
|
||||
if err = s.client.host.Connect(ctx, peer.AddrInfo{
|
||||
ID: targetPeerID,
|
||||
Addrs: addrs,
|
||||
}); err != nil {
|
||||
g.Log().Errorf(ctx, "连接失败: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
g.Log().Infof(ctx, "成功连接到目标节点:%v", targetID)
|
||||
s.client.peers[targetID] = targetPeerID
|
||||
}(peerID, msg.To)
|
||||
|
||||
case MsgTypePunchRequest:
|
||||
err = s.handlePunchRequest(msg.Data)
|
||||
|
||||
case MsgTypeError:
|
||||
var data struct {
|
||||
Error string `json:"error"`
|
||||
}
|
||||
json.Unmarshal(msg.Data, &data)
|
||||
glog.Errorf(ctx, "网关错误: %s", data.Error)
|
||||
}
|
||||
}
|
||||
}
|
||||
1
internal/logic/p2p/dht.go
Normal file
1
internal/logic/p2p/dht.go
Normal file
@@ -0,0 +1 @@
|
||||
package p2p
|
||||
268
internal/logic/p2p/gateway.go
Normal file
268
internal/logic/p2p/gateway.go
Normal file
@@ -0,0 +1,268 @@
|
||||
package p2p
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/v2/encoding/gjson"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
"github.com/gogf/gf/v2/os/glog"
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
var (
|
||||
Ws *websocket.Conn
|
||||
)
|
||||
|
||||
// 客户端连接信息
|
||||
type ClientConn struct {
|
||||
ID string
|
||||
PeerID string
|
||||
Addrs []string
|
||||
Conn *websocket.Conn
|
||||
LastActive time.Time
|
||||
}
|
||||
|
||||
// 消息结构
|
||||
type GatewayMessage struct {
|
||||
Type MsgType `json:"type"`
|
||||
From string `json:"from"`
|
||||
To string `json:"to,omitempty"`
|
||||
Data json.RawMessage `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
func (s *sP2P) GatewayStart(ctx context.Context, group *ghttp.RouterGroup) (err error) {
|
||||
var wsUpGrader = websocket.Upgrader{
|
||||
ReadBufferSize: 1024,
|
||||
WriteBufferSize: 1024,
|
||||
//// CheckOrigin allows any origin in development
|
||||
//// In production, implement proper origin checking for security
|
||||
//CheckOrigin: func(r *http.Request) bool {
|
||||
// return true
|
||||
//},
|
||||
//// Error handler for upgrade failures
|
||||
//Error: func(w http.ResponseWriter, r *http.Request, status int, reason error) {
|
||||
// // Implement error handling logic here
|
||||
//},
|
||||
}
|
||||
|
||||
group.Bind(func(r *ghttp.Request) {
|
||||
// Upgrade HTTP connection to WebSocket
|
||||
ws, err2 := wsUpGrader.Upgrade(r.Response.Writer, r.Request, nil)
|
||||
if err2 != nil {
|
||||
r.Response.Write(err2.Error())
|
||||
return
|
||||
}
|
||||
defer ws.Close()
|
||||
|
||||
// Message handling loop
|
||||
for {
|
||||
_, data, _err := ws.ReadMessage()
|
||||
if _err != nil {
|
||||
//g.Log().Errorf(ctx, "读取消息失败: %v", err)
|
||||
//s.sendError(ws, err.Error())
|
||||
break
|
||||
}
|
||||
|
||||
var msg GatewayMessage
|
||||
if err = json.Unmarshal(data, &msg); err != nil {
|
||||
//g.Log().Error(ctx, "消息格式错误")
|
||||
s.sendError(ws, "消息格式错误")
|
||||
continue
|
||||
}
|
||||
|
||||
// 处理不同类型的消息
|
||||
switch msg.Type {
|
||||
case MsgTypeRegister:
|
||||
s.handleRegister(ws, msg)
|
||||
case MsgTypeDiscover:
|
||||
s.handleDiscover(ws, msg)
|
||||
default:
|
||||
g.Log().Error(ctx, "未知消息类型: %s", msg.Type)
|
||||
}
|
||||
}
|
||||
// Log connection closure
|
||||
g.Log().Infof(ctx, "websocket %v connection closed", ws.RemoteAddr())
|
||||
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 处理注册请求
|
||||
func (s *sP2P) handleRegister(conn *websocket.Conn, msg GatewayMessage) {
|
||||
if msg.From == "" {
|
||||
g.Log().Error(ctx, "客户端ID不能为空")
|
||||
return
|
||||
}
|
||||
|
||||
var data struct {
|
||||
PeerID string `json:"peer_id"`
|
||||
Addrs []string `json:"addrs"`
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(msg.Data, &data); err != nil {
|
||||
s.sendError(conn, "注册数据格式错误")
|
||||
return
|
||||
}
|
||||
|
||||
// 保存客户端信息
|
||||
client := &ClientConn{
|
||||
ID: msg.From,
|
||||
PeerID: data.PeerID,
|
||||
Addrs: data.Addrs,
|
||||
Conn: conn,
|
||||
LastActive: time.Now(),
|
||||
}
|
||||
|
||||
s.lock.Lock()
|
||||
s.Clients[msg.From] = client
|
||||
s.lock.Unlock()
|
||||
|
||||
glog.Infof(ctx, "客户端 ip=%s,%s 注册成功,PeerID: %s", conn.RemoteAddr(), msg.From, data.PeerID)
|
||||
|
||||
// 发送注册成功响应
|
||||
err := s.sendMessage(conn, GatewayMessage{
|
||||
Type: MsgTypeRegisterAck,
|
||||
Data: json.RawMessage(`{"success": true, "message": "注册成功"}`),
|
||||
})
|
||||
if err != nil {
|
||||
s.sendError(conn, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// 清理超时客户端
|
||||
func (s *sP2P) cleanupClients(ctx context.Context) {
|
||||
ticker := time.NewTicker(30 * time.Second)
|
||||
defer ticker.Stop()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case <-ticker.C:
|
||||
now := time.Now()
|
||||
s.lock.Lock()
|
||||
for id, client := range s.Clients {
|
||||
if now.Sub(client.LastActive) > 60*time.Second {
|
||||
client.Conn.Close()
|
||||
delete(s.Clients, id)
|
||||
glog.Infof(ctx, "清理超时客户端: %s", id)
|
||||
}
|
||||
}
|
||||
s.lock.Unlock()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 发送错误消息
|
||||
func (s *sP2P) sendError(conn *websocket.Conn, errMsg string) {
|
||||
s.sendMessage(conn, GatewayMessage{
|
||||
Type: "error",
|
||||
Data: json.RawMessage(fmt.Sprintf(`{"error": "%s"}`, errMsg)),
|
||||
})
|
||||
}
|
||||
|
||||
// 发送消息
|
||||
func (s *sP2P) sendMessage(conn *websocket.Conn, msg GatewayMessage) error {
|
||||
data, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
glog.Errorf(gctx.New(), "序列化消息失败: %v", err)
|
||||
return err
|
||||
}
|
||||
return conn.WriteMessage(websocket.TextMessage, data)
|
||||
}
|
||||
|
||||
// 处理发现请求
|
||||
func (s *sP2P) handleDiscover(conn *websocket.Conn, msg GatewayMessage) {
|
||||
if msg.From == "" {
|
||||
s.sendError(conn, "消息缺少发送方ID(from)")
|
||||
return
|
||||
}
|
||||
|
||||
var data struct {
|
||||
TargetID string `json:"target_id"`
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(msg.Data, &data); err != nil {
|
||||
s.sendError(conn, "发现请求格式错误,需包含target_id")
|
||||
return
|
||||
}
|
||||
|
||||
if data.TargetID == "" {
|
||||
s.sendError(conn, "目标ID不能为空")
|
||||
return
|
||||
}
|
||||
|
||||
// 获取请求方和目标方信息
|
||||
s.lock.RLock()
|
||||
//fromClient, fromExists := s.Clients[msg.From]
|
||||
//targetClient, targetExists := s.Clients[data.TargetID]
|
||||
fromClient := s.Clients[msg.From] // 发送方:msg.From
|
||||
targetClient := s.Clients[data.TargetID] // 目标方:data.TargetID
|
||||
s.lock.RUnlock()
|
||||
|
||||
//if !fromExists {
|
||||
// s.sendError(conn, "请先注册")
|
||||
// return
|
||||
//}
|
||||
|
||||
// 更新活动时间
|
||||
s.lock.Lock()
|
||||
fromClient.LastActive = time.Now()
|
||||
s.lock.Unlock()
|
||||
|
||||
if targetClient != nil {
|
||||
// 目标不存在
|
||||
s.sendMessage(conn, GatewayMessage{
|
||||
Type: MsgTypeDiscoverAck,
|
||||
From: "gateway",
|
||||
To: msg.From,
|
||||
//Data: json.RawMessage(`{"found": false}`),
|
||||
Data: gjson.MustEncode(g.Map{
|
||||
"found": false,
|
||||
}),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 向请求方发送目标信息
|
||||
s.sendMessage(conn, GatewayMessage{
|
||||
Type: MsgTypeDiscoverAck,
|
||||
From: "gateway", // 发送方是网关
|
||||
To: msg.From, // 接收方是原请求方
|
||||
Data: gjson.MustEncode(g.Map{
|
||||
"found": true,
|
||||
"peer_id": targetClient.PeerID,
|
||||
//"addrs": s.getAddrsJSON(targetClient.Addrs),
|
||||
"addrs": targetClient.Addrs,
|
||||
}),
|
||||
})
|
||||
|
||||
// 向目标方发送打洞请求(协调时机)
|
||||
s.sendMessage(targetClient.Conn, GatewayMessage{
|
||||
Type: MsgTypePunchRequest,
|
||||
From: msg.From, // 发送方是原请求方
|
||||
To: data.TargetID, // 接收方是目标方
|
||||
Data: gjson.MustEncode(g.Map{
|
||||
"from_id": msg.From,
|
||||
"peer_id": fromClient.PeerID,
|
||||
//"addrs": s.getAddrsJSON(fromClient.Addrs),
|
||||
"addrs": targetClient.Addrs,
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
// 获取地址JSON字符串
|
||||
func (s *sP2P) getAddrsJSON(addrs []string) string {
|
||||
strs := make([]string, len(addrs))
|
||||
for i, addr := range addrs {
|
||||
strs[i] = fmt.Sprintf("%q", addr)
|
||||
}
|
||||
return fmt.Sprintf("[%s]", strings.Join(strs, ","))
|
||||
}
|
||||
56
internal/logic/p2p/p2p.go
Normal file
56
internal/logic/p2p/p2p.go
Normal file
@@ -0,0 +1,56 @@
|
||||
package p2p
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/ayflying/p2p/internal/service"
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
"github.com/libp2p/go-libp2p/core/protocol"
|
||||
)
|
||||
|
||||
var (
|
||||
ctx = gctx.New()
|
||||
)
|
||||
|
||||
// 常量定义
|
||||
const (
|
||||
ProtocolID protocol.ID = "/ay/1.0.0"
|
||||
DefaultPort = 51888
|
||||
)
|
||||
|
||||
type MsgType string
|
||||
|
||||
const (
|
||||
MsgTypeRegister = "register" // 客户端注册
|
||||
MsgTypeRegisterAck = "register_ack" // 注册响应
|
||||
MsgTypeDiscover = "discover" // 发现目标客户端
|
||||
MsgTypeDiscoverAck = "discover_ack" // 发现响应
|
||||
MsgTypeConnectionReq = "connection_req" // 连接请求通知
|
||||
MsgTypePunchRequest = "punch_request"
|
||||
MsgTypeError = "error" // 错误消息
|
||||
)
|
||||
|
||||
// 注册请求数据
|
||||
type RegisterData struct {
|
||||
ClientID string `json:"client_id"`
|
||||
}
|
||||
|
||||
// sP2P 结构体实现 IP2P 接口
|
||||
type sP2P struct {
|
||||
Clients map[string]*ClientConn // 客户端ID -> 连接
|
||||
lock sync.RWMutex
|
||||
|
||||
client *Client
|
||||
}
|
||||
|
||||
// New 创建一个新的 P2P 服务实例
|
||||
func New() *sP2P {
|
||||
return &sP2P{
|
||||
Clients: make(map[string]*ClientConn),
|
||||
client: &Client{},
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
service.RegisterP2P(New())
|
||||
}
|
||||
Reference in New Issue
Block a user