dashboard/pkg/rpcsup/rpcsup.go

104 lines
1.6 KiB
Go

package rpcsup
import (
"context"
"errors"
"net"
"net/rpc"
"net/rpc/jsonrpc"
"strings"
"golang.org/x/sync/errgroup"
)
type RpcServicer interface {
Name() string
}
type RpcService struct {
rpc *rpc.Server
listen net.Listener
handler func(net.Conn)
}
type RpcConfig struct {
Typec string
Network string
Address string
}
func NewRpcService(conf *RpcConfig) (res *RpcService, err error) {
res = new(RpcService)
res.rpc = rpc.NewServer()
res.listen, err = net.Listen(conf.Network, conf.Address)
if err != nil {
return
}
if strings.Contains(conf.Typec, "json") {
res.handler = func(c net.Conn) {
res.rpc.ServeCodec(jsonrpc.NewServerCodec(c))
}
return
}
if strings.Contains(conf.Typec, "grpc") {
return nil, errors.New("currently not supported")
}
res.handler = func(c net.Conn) {
res.rpc.ServeConn(c)
}
return
}
func (r *RpcService) Register(service ...interface{}) error {
for _, ser := range service {
if nser, ok := ser.(RpcServicer); ok {
if err := r.rpc.RegisterName(nser.Name(), nser); err != nil {
return err
}
continue
}
if err := r.rpc.Register(ser); err != nil {
return err
}
}
return nil
}
func (r *RpcService) Run(ctx context.Context) error {
wg, ctxx := errgroup.WithContext(ctx)
wg.Go(func() error {
for {
accept, err := r.listen.Accept()
if err != nil {
if errors.Is(err, net.ErrClosed) {
return err
}
continue
}
go r.handler(accept)
}
})
wg.Go(func() error {
<-ctxx.Done()
r.listen.Close()
return ctxx.Err()
})
if err := wg.Wait(); err != nil {
return err
}
return nil
}