mirror of
https://github.com/VaalaCat/frp-panel.git
synced 2025-11-01 11:12:48 +08:00
refactor: change client manager structure [重构:更改客户端管理器结构适配影子客户端] feat: add proxy config table and dao [添加代理配置独立数据表和DAO层] feat: new proxy config entity [新建的代理配置实体] feat: update and delete proxy config [更新和删除代理配置接口] feat: get config api and beautify proxy item [更新获取配置API并美化代理项] feat: change proxy form style [美化修改代理的表单样式] fix: client edit [修复:编辑客户端的问题] fix: shadow copy status error [修复:影子客户端复制状态错误] fix: http proxy bug [修复:HTTP代理类型的错误] fix: cannot update client [修复:无法更新客户端] feat: record trigger refetch [自动重新获取表格内的数据] fix: filter string length [修复:过滤字符串长度] fix: add client error [修复:添加客户端错误] fix: do not notify client when stopped [修复:停止时不通知客户端] fix: delete when proxy duplicate [修复:代理重复时删除] feat: add http proxy location [添加HTTP代理路由路径] chore: edit style [编辑样式美化] fix: remove expired client [修复:自动移除过期客户端] feat: proxy status [新增代理状态提示] fix: build [修复:构建] fix: refetch trigger [修复:重新获取数据的问题] fix: remove all expired client [修复:移除所有过期客户端] feat: i18n for proxy [代理页面的国际化翻译]
126 lines
2.9 KiB
Go
126 lines
2.9 KiB
Go
package rpc
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
"sync"
|
|
|
|
"github.com/VaalaCat/frp-panel/common"
|
|
"github.com/VaalaCat/frp-panel/logger"
|
|
"github.com/VaalaCat/frp-panel/pb"
|
|
"github.com/google/uuid"
|
|
"github.com/sirupsen/logrus"
|
|
"google.golang.org/protobuf/proto"
|
|
"google.golang.org/protobuf/reflect/protoreflect"
|
|
)
|
|
|
|
func CallClientWrapper[R common.RespType](c context.Context, clientID string, event pb.Event, req proto.Message, resp *R) error {
|
|
cresp, err := CallClient(c, clientID, event, req)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
protoMsgRef, ok := any(resp).(protoreflect.ProtoMessage)
|
|
if !ok {
|
|
return fmt.Errorf("type does not implement protoreflect.ProtoMessage")
|
|
}
|
|
|
|
return proto.Unmarshal(cresp.GetData(), protoMsgRef)
|
|
}
|
|
|
|
func CallClient(c context.Context, clientID string, event pb.Event, msg proto.Message) (*pb.ClientMessage, error) {
|
|
sender := GetClientsManager().Get(clientID)
|
|
if sender == nil {
|
|
logger.Logger(c).Errorf("cannot get client, id: [%s]", clientID)
|
|
return nil, fmt.Errorf("cannot get client, id: [%s]", clientID)
|
|
}
|
|
|
|
data, err := proto.Marshal(msg)
|
|
if err != nil {
|
|
logger.Logger(context.Background()).WithError(err).Errorf("cannot marshal")
|
|
return nil, err
|
|
}
|
|
|
|
req := &pb.ServerMessage{
|
|
Event: event,
|
|
Data: data,
|
|
SessionId: uuid.New().String(),
|
|
ClientId: clientID,
|
|
}
|
|
|
|
recvMap.Store(req.SessionId, make(chan *pb.ClientMessage))
|
|
err = sender.Conn.Send(req)
|
|
if err != nil {
|
|
logger.Logger(context.Background()).WithError(err).Errorf("cannot send")
|
|
GetClientsManager().Remove(clientID)
|
|
return nil, err
|
|
}
|
|
respChAny, ok := recvMap.Load(req.SessionId)
|
|
if !ok {
|
|
logrus.Fatalf("cannot load")
|
|
}
|
|
|
|
respCh, ok := respChAny.(chan *pb.ClientMessage)
|
|
if !ok {
|
|
logrus.Fatalf("cannot cast")
|
|
}
|
|
|
|
resp := <-respCh
|
|
if resp.Event == pb.Event_EVENT_ERROR {
|
|
return nil, fmt.Errorf("client return error: %s", resp.Data)
|
|
}
|
|
|
|
close(respCh)
|
|
recvMap.Delete(req.SessionId)
|
|
return resp, nil
|
|
}
|
|
|
|
var (
|
|
recvMap *sync.Map
|
|
)
|
|
|
|
func init() {
|
|
recvMap = &sync.Map{}
|
|
}
|
|
|
|
func Recv(clientID string) chan bool {
|
|
done := make(chan bool)
|
|
go func() {
|
|
c := context.Background()
|
|
for {
|
|
reciver := GetClientsManager().Get(clientID)
|
|
if reciver == nil {
|
|
logger.Logger(c).Errorf("cannot get client")
|
|
continue
|
|
}
|
|
resp, err := reciver.Conn.Recv()
|
|
if err == io.EOF {
|
|
logger.Logger(c).Infof("finish client recv")
|
|
done <- true
|
|
return
|
|
}
|
|
if err != nil {
|
|
logger.Logger(context.Background()).WithError(err).Errorf("cannot recv, usually means client disconnect")
|
|
done <- true
|
|
return
|
|
}
|
|
|
|
respChAny, ok := recvMap.Load(resp.SessionId)
|
|
if !ok {
|
|
logger.Logger(c).Errorf("cannot load")
|
|
continue
|
|
}
|
|
|
|
respCh, ok := respChAny.(chan *pb.ClientMessage)
|
|
if !ok {
|
|
logger.Logger(c).Errorf("cannot cast")
|
|
continue
|
|
}
|
|
logger.Logger(c).Infof("recv success, resp: %+v", resp)
|
|
respCh <- resp
|
|
}
|
|
}()
|
|
return done
|
|
}
|