Appearance
btcd/btcjson 如何管理命令
以debuglevel命令为例来说明btcd对于rpc命令是如何组织的.
1. 注册
通过此方式可以注册一个新的命令,
go
// DebugLevelCmd defines the debuglevel JSON-RPC command. This command is not a
// standard Bitcoin command. It is an extension for btcd.
type DebugLevelCmd struct {
LevelSpec string
}
MustRegisterCmd("debuglevel", (*DebugLevelCmd)(nil), flags)
MustRegisterCmd 最终通过RegisterCmd来实现命令注册,这里面用到了不少反射代码来简化函数的调用.
最终MustRegisterCmd提供信息会保存到三个全局map中,
go
methodToConcreteType = make(map[string]reflect.Type)
methodToInfo = make(map[string]methodInfo)
concreteTypeToMethod = make(map[reflect.Type]string)
其中methodToInfo 的key是debuglevel
,用于对该命令进行描述,为btcctl help 提供信息,也是rpc server检测提供参数格式是否正确的依据.
btcctl help中的信息还有一部分来源就是helpDescsEnUS中,
其中methodToConcreteType和concreteTypeToMethod是互为映射,主要是为了帮助创建DebugLevelCmd结构体.以及根据这个结构体找到对应的命令. 针对这个命令来说,三个map中会写入如下信息
go
methodToConcreteType["debuglevel"]=reflect.TypeOf(&DebugLevelCmd{})
methodToInfo["debuglevel"]="该结构体的信息"
concreteTypeToMethod[reflect.TypeOf(&DebugLevelCmd{})]="debuglevel"
**注意这里面并没有定义如何处理这个命令. **
2. 命令处理
rpc server对一个命令的处理入口主要在rpcserver.go中,还是以debuglevel这个命令为例. 在rpcHandlersBeforeInit可以看到 "debuglevel"对应的处理函数是handleDebugLevel
go
// handleDebugLevel handles debuglevel commands.
func handleDebugLevel(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
c := cmd.(*btcjson.DebugLevelCmd)
// Special show command to list supported subsystems.
if c.LevelSpec == "show" {
return fmt.Sprintf("Supported subsystems %v",
supportedSubsystems()), nil
}
err := parseAndSetDebugLevels(c.LevelSpec)
if err != nil {
return nil, &btcjson.RPCError{
Code: btcjson.ErrRPCInvalidParams.Code,
Message: err.Error(),
}
}
return "Done.", nil
}
走到这里的时候,框架已经做完参数解析以及初步验证,还有就是告诉你如何返回结果. cmd 参数就是DebugLevelCmd结构体.处理完毕以后直接返回结果即可.
需要说明的是closeChan一般不用,如果你处理的是一个长时间不能返回的任务,那么这时候有可能客户端已经停止请求了,这时候处理函数可以通过closeChan检测到这种情况来停止任务,然后返回一个错误信息. 比如return nil, ErrClientQuit
3. 客户端使用
具体见btcctl.go
go
cmd, err := btcjson.NewCmd(method, params...)
marshalledJSON, err := btcjson.MarshalCmd(1, cmd)
result, err := sendPostRequest(marshalledJSON, cfg)
//result就是命令的执行结果,根据情况进行解析
4. 其他
rpcserver是提供了外部使用者如何调控一个正在运行的btcd全节点.
- 提供的接口完全兼容bitcoind.
- 没有钱包相关功能
- 很多命令提供的功能可以在btcd.conf预置
- 比如可以在btcd.conf中指定debuglevel