github.com/noirx94/tendermintmp@v0.0.1/rpc/jsonrpc/server/rpc_func.go (about)

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