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 }