github.com/aergoio/aergo@v1.3.1/polaris/server/prpc.go (about)

     1  /*
     2   * @file
     3   * @copyright defined in aergo/LICENSE.txt
     4   */
     5  
     6  package server
     7  
     8  import (
     9  	"context"
    10  	"encoding/binary"
    11  	"encoding/json"
    12  	"fmt"
    13  	"net"
    14  	"reflect"
    15  	"time"
    16  
    17  	"github.com/aergoio/aergo-actor/actor"
    18  	"github.com/aergoio/aergo-lib/log"
    19  	"github.com/aergoio/aergo/config"
    20  	"github.com/aergoio/aergo/message"
    21  	"github.com/aergoio/aergo/p2p/p2pcommon"
    22  	"github.com/aergoio/aergo/pkg/component"
    23  	"github.com/aergoio/aergo/types"
    24  	"github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc"
    25  	"github.com/opentracing/opentracing-go"
    26  	"github.com/soheilhy/cmux"
    27  	"google.golang.org/grpc"
    28  )
    29  
    30  var NotSupportError = fmt.Errorf("not supported cmd")
    31  
    32  type PolarisRPC struct {
    33  	*component.BaseComponent
    34  
    35  	conf   *config.Config
    36  	logger *log.Logger
    37  
    38  	actorHelper p2pcommon.ActorService
    39  
    40  	grpcServer   *grpc.Server
    41  	actualServer *PRPCServer
    42  }
    43  
    44  func NewPolarisRPC(cfg *config.Config) *PolarisRPC {
    45  	logger := log.NewLogger("prpc")
    46  	actualServer := &PRPCServer{
    47  		logger: logger,
    48  	}
    49  	tracer := opentracing.GlobalTracer()
    50  	opts := []grpc.ServerOption{
    51  		grpc.MaxRecvMsgSize(1024 * 1024 * 8),
    52  	}
    53  
    54  	if cfg.RPC.NetServiceTrace {
    55  		opts = append(opts, grpc.UnaryInterceptor(otgrpc.OpenTracingServerInterceptor(tracer)))
    56  		opts = append(opts, grpc.StreamInterceptor(otgrpc.OpenTracingStreamServerInterceptor(tracer)))
    57  	}
    58  	grpcServer := grpc.NewServer(opts...)
    59  
    60  	rpc := &PolarisRPC{
    61  		conf:         cfg,
    62  		logger:       logger,
    63  		grpcServer:   grpcServer,
    64  		actualServer: actualServer,
    65  	}
    66  	rpc.BaseComponent = component.NewBaseComponent(message.PolarisRPCSvc, rpc, logger)
    67  	actualServer.actorHelper = rpc
    68  
    69  	return rpc
    70  }
    71  
    72  func (rpc *PolarisRPC) SetHub(hub *component.ComponentHub) {
    73  	rpc.actualServer.hub = hub
    74  	rpc.BaseComponent.SetHub(hub)
    75  }
    76  
    77  // Start start rpc service.
    78  func (rpc *PolarisRPC) BeforeStart() {
    79  	types.RegisterPolarisRPCServiceServer(rpc.grpcServer, rpc.actualServer)
    80  }
    81  
    82  func (rpc *PolarisRPC) AfterStart() {
    83  	go rpc.serve()
    84  }
    85  
    86  // Stop stops rpc service.
    87  func (rpc *PolarisRPC) BeforeStop() {
    88  	rpc.grpcServer.Stop()
    89  }
    90  
    91  // Statistics show statistic information of p2p module. NOTE: It it not implemented yet
    92  func (rpc *PolarisRPC) Statistics() *map[string]interface{} {
    93  	return nil
    94  }
    95  
    96  func (rpc *PolarisRPC) Receive(context actor.Context) {
    97  	switch msg := context.Message().(type) {
    98  	default:
    99  		rpc.Warn().Msgf("unknown msg received in rpc %s", reflect.TypeOf(msg).String())
   100  	}
   101  }
   102  
   103  // Serve TCP multiplexer
   104  func (rpc *PolarisRPC) serve() {
   105  	ipAddr := net.ParseIP(rpc.conf.RPC.NetServiceAddr)
   106  	if ipAddr == nil {
   107  		panic("Wrong IP address format in RPC.NetServiceAddr")
   108  	}
   109  
   110  	addr := fmt.Sprintf("%s:%d", ipAddr, rpc.conf.RPC.NetServicePort)
   111  
   112  	l, err := net.Listen("tcp", addr)
   113  	if err != nil {
   114  		panic(err)
   115  	}
   116  
   117  	rpc.Info().Msg(fmt.Sprintf("Starting RPC server listening on %s, with TLS: %v", addr, rpc.conf.RPC.NSEnableTLS))
   118  	if rpc.conf.RPC.NSEnableTLS {
   119  		rpc.Warn().Msg("TLS is enabled in configuration, but currently not supported")
   120  	}
   121  
   122  	// Server both servers
   123  	go rpc.serveGRPC(l, rpc.grpcServer)
   124  
   125  	return
   126  }
   127  
   128  // Serve GRPC server over TCP
   129  func (rpc *PolarisRPC) serveGRPC(l net.Listener, server *grpc.Server) {
   130  	if err := server.Serve(l); err != nil {
   131  		switch err {
   132  		case cmux.ErrListenerClosed:
   133  			// Server killed, usually by ctrl-c signal
   134  		default:
   135  			panic(err)
   136  		}
   137  	}
   138  }
   139  
   140  const defaultTTL = time.Second * 4
   141  
   142  // TellRequest implement interface method of ActorService
   143  func (rpc *PolarisRPC) TellRequest(actor string, msg interface{}) {
   144  	rpc.TellTo(actor, msg)
   145  }
   146  
   147  // SendRequest implement interface method of ActorService
   148  func (rpc *PolarisRPC) SendRequest(actor string, msg interface{}) {
   149  	rpc.RequestTo(actor, msg)
   150  }
   151  
   152  // FutureRequest implement interface method of ActorService
   153  func (rpc *PolarisRPC) FutureRequest(actor string, msg interface{}, timeout time.Duration) *actor.Future {
   154  	return rpc.RequestToFuture(actor, msg, timeout)
   155  }
   156  
   157  // FutureRequestDefaultTimeout implement interface method of ActorService
   158  func (rpc *PolarisRPC) FutureRequestDefaultTimeout(actor string, msg interface{}) *actor.Future {
   159  	return rpc.RequestToFuture(actor, msg, defaultTTL)
   160  }
   161  
   162  // CallRequest implement interface method of ActorService
   163  func (rpc *PolarisRPC) CallRequest(actor string, msg interface{}, timeout time.Duration) (interface{}, error) {
   164  	future := rpc.RequestToFuture(actor, msg, timeout)
   165  	return future.Result()
   166  }
   167  
   168  // CallRequest implement interface method of ActorService
   169  func (rpc *PolarisRPC) CallRequestDefaultTimeout(actor string, msg interface{}) (interface{}, error) {
   170  	future := rpc.RequestToFuture(actor, msg, defaultTTL)
   171  	return future.Result()
   172  }
   173  func (rpc *PolarisRPC) GetChainAccessor() types.ChainAccessor {
   174  	return nil
   175  }
   176  
   177  type PRPCServer struct {
   178  	logger *log.Logger
   179  
   180  	hub         *component.ComponentHub
   181  	actorHelper p2pcommon.ActorService
   182  }
   183  
   184  func (rs *PRPCServer) NodeState(ctx context.Context, in *types.NodeReq) (*types.SingleBytes, error) {
   185  	timeout := int64(binary.LittleEndian.Uint64(in.Timeout))
   186  	component := string(in.Component)
   187  
   188  	rs.logger.Debug().Str("comp", component).Int64("timeout", timeout).Msg("nodestate")
   189  
   190  	statics, err := rs.hub.Statistics(time.Duration(timeout)*time.Second, component)
   191  	if err != nil {
   192  		return nil, err
   193  	}
   194  
   195  	data, err := json.MarshalIndent(statics, "", "\t")
   196  	if err != nil {
   197  		return nil, err
   198  	}
   199  	return &types.SingleBytes{Value: data}, nil
   200  }
   201  
   202  func (rs *PRPCServer) Metric(ctx context.Context, in *types.MetricsRequest) (*types.Metrics, error) {
   203  	// TODO: change types.Metrics to support polaris metric informations or refactor to make more generalized structure (i.e change aergo-protobuf first)
   204  	result := &types.Metrics{}
   205  
   206  	return result, nil
   207  }
   208  
   209  func (rs *PRPCServer) CurrentList(ctx context.Context, p1 *types.Paginations) (*types.PolarisPeerList, error) {
   210  	result, err := rs.actorHelper.CallRequestDefaultTimeout(PolarisSvc,
   211  		&CurrentListMsg{p1.Ref, p1.Size})
   212  	if err != nil {
   213  		return nil, err
   214  	}
   215  	list, ok := result.(*types.PolarisPeerList)
   216  	if !ok {
   217  		return nil, fmt.Errorf("unkown error")
   218  	}
   219  	return list, nil
   220  }
   221  
   222  func (rs *PRPCServer) WhiteList(ctx context.Context, p1 *types.Paginations) (*types.PolarisPeerList, error) {
   223  	result, err := rs.actorHelper.CallRequestDefaultTimeout(PolarisSvc,
   224  		&WhiteListMsg{p1.Ref, p1.Size})
   225  	if err == nil {
   226  		list := result.(*types.PolarisPeerList)
   227  		return list, nil
   228  	} else {
   229  		return nil, err
   230  	}
   231  }
   232  
   233  func (rs *PRPCServer) BlackList(ctx context.Context, p1 *types.Paginations) (*types.PolarisPeerList, error) {
   234  	result, err := rs.actorHelper.CallRequestDefaultTimeout(PolarisSvc,
   235  		&BlackListMsg{p1.Ref, p1.Size})
   236  	if err == nil {
   237  		list := result.(*types.PolarisPeerList)
   238  		return list, nil
   239  	} else {
   240  		return nil, err
   241  	}
   242  }
   243  
   244  func (rs *PRPCServer) ListBLEntries(ctx context.Context, entInfo *types.Empty) (*types.BLConfEntries, error) {
   245  	result, err := rs.actorHelper.CallRequestDefaultTimeout(PolarisSvc,	ListEntriesMsg{})
   246  	if err != nil {
   247  		return nil, err
   248  	}
   249  	list, ok := result.(*types.BLConfEntries)
   250  	if !ok {
   251  		return nil, fmt.Errorf("unkown error")
   252  	}
   253  	return list, nil
   254  }
   255  
   256  func (rs *PRPCServer) AddBLEntry(ctx context.Context,entInfo *types.AddEntryParams) (*types.SingleString, error) {
   257  	ret := &types.SingleString{}
   258  
   259  	if len(entInfo.PeerID) == 0 && len(entInfo.Cidr) == 0 && len(entInfo.Address) == 0 {
   260  		ret.Value = "at least one flags is required"
   261  		return ret, types.RPCErrInvalidArgument
   262  	} else if len(entInfo.Cidr) > 0 && len(entInfo.Address) > 0 {
   263  		ret.Value = "either address or cidr is allowed, not both "
   264  		return ret, types.RPCErrInvalidArgument
   265  	}
   266  
   267  	result, err := rs.actorHelper.CallRequestDefaultTimeout(PolarisSvc, entInfo)
   268  	if err != nil {
   269  		ret.Value = err.Error()
   270  		return ret, types.RPCErrInternalError
   271  	}
   272  	if result != nil {
   273  		ret.Value = result.(error).Error()
   274  		return ret, types.RPCErrInvalidArgument
   275  	}
   276  	return ret, nil
   277  }
   278  
   279  func (rs *PRPCServer) RemoveBLEntry(ctx context.Context, msg *types.RmEntryParams) (*types.SingleString, error) {
   280  	ret := &types.SingleString{}
   281  	result, err := rs.actorHelper.CallRequestDefaultTimeout(PolarisSvc, msg)
   282  	if err != nil {
   283  		ret.Value = err.Error()
   284  		return ret, types.RPCErrInternalError
   285  	}
   286  	removed := result.(bool)
   287  	if !removed {
   288  		ret.Value = "index out of range"
   289  		return ret, types.RPCErrInvalidArgument
   290  	}
   291  	return ret, nil
   292  
   293  }
   294