github.com/number571/tendermint@v0.34.11-gost/rpc/jsonrpc/server/rpc_func.go (about)

     1  package server
     2  
     3  import (
     4  	"net/http"
     5  	"reflect"
     6  	"strings"
     7  
     8  	"github.com/number571/tendermint/libs/log"
     9  )
    10  
    11  // RegisterRPCFuncs adds a route for each function in the funcMap, as well as
    12  // general jsonrpc and websocket handlers for all functions. "result" is the
    13  // interface on which the result objects are registered, and is popualted with
    14  // every RPCResponse
    15  func RegisterRPCFuncs(mux *http.ServeMux, funcMap map[string]*RPCFunc, logger log.Logger) {
    16  	// HTTP endpoints
    17  	for funcName, rpcFunc := range funcMap {
    18  		mux.HandleFunc("/"+funcName, makeHTTPHandler(rpcFunc, logger))
    19  	}
    20  
    21  	// JSONRPC endpoints
    22  	mux.HandleFunc("/", handleInvalidJSONRPCPaths(makeJSONRPCHandler(funcMap, logger)))
    23  }
    24  
    25  // Function introspection
    26  
    27  // RPCFunc contains the introspected type information for a function
    28  type RPCFunc struct {
    29  	f        reflect.Value  // underlying rpc function
    30  	args     []reflect.Type // type of each function arg
    31  	returns  []reflect.Type // type of each return arg
    32  	argNames []string       // name of each argument
    33  	ws       bool           // websocket only
    34  	cache    bool           // allow the RPC response can be cached by the proxy cache server
    35  }
    36  
    37  // NewRPCFunc wraps a function for introspection.
    38  // f is the function, args are comma separated argument names
    39  // cache is a bool value to allow the client proxy server to cache the RPC results
    40  func NewRPCFunc(f interface{}, args string, cache bool) *RPCFunc {
    41  	return newRPCFunc(f, args, false, cache)
    42  }
    43  
    44  // NewWSRPCFunc wraps a function for introspection and use in the websockets.
    45  func NewWSRPCFunc(f interface{}, args string) *RPCFunc {
    46  	return newRPCFunc(f, args, true, false)
    47  }
    48  
    49  func newRPCFunc(f interface{}, args string, ws bool, c bool) *RPCFunc {
    50  	var argNames []string
    51  	if args != "" {
    52  		argNames = strings.Split(args, ",")
    53  	}
    54  	return &RPCFunc{
    55  		f:        reflect.ValueOf(f),
    56  		args:     funcArgTypes(f),
    57  		returns:  funcReturnTypes(f),
    58  		argNames: argNames,
    59  		ws:       ws,
    60  		cache:    c,
    61  	}
    62  }
    63  
    64  // return a function's argument types
    65  func funcArgTypes(f interface{}) []reflect.Type {
    66  	t := reflect.TypeOf(f)
    67  	n := t.NumIn()
    68  	typez := make([]reflect.Type, n)
    69  	for i := 0; i < n; i++ {
    70  		typez[i] = t.In(i)
    71  	}
    72  	return typez
    73  }
    74  
    75  // return a function's return types
    76  func funcReturnTypes(f interface{}) []reflect.Type {
    77  	t := reflect.TypeOf(f)
    78  	n := t.NumOut()
    79  	typez := make([]reflect.Type, n)
    80  	for i := 0; i < n; i++ {
    81  		typez[i] = t.Out(i)
    82  	}
    83  	return typez
    84  }
    85  
    86  //-------------------------------------------------------------
    87  
    88  // NOTE: assume returns is result struct and error. If error is not nil, return it
    89  func unreflectResult(returns []reflect.Value) (interface{}, error) {
    90  	errV := returns[1]
    91  	if err, ok := errV.Interface().(error); ok && err != nil {
    92  		return nil, err
    93  	}
    94  	rv := returns[0]
    95  	// the result is a registered interface,
    96  	// we need a pointer to it so we can marshal with type byte
    97  	rvp := reflect.New(rv.Type())
    98  	rvp.Elem().Set(rv)
    99  	return rvp.Interface(), nil
   100  }