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