From c5716de70485a0c80bfa9f1fa67ca5ce1758bfad Mon Sep 17 00:00:00 2001 From: saji <9110284+kschamplin@users.noreply.github.com> Date: Sun, 30 Apr 2023 14:49:18 -0500 Subject: [PATCH] add rpc skeleton --- internal/gotelem/rpc.go | 84 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 internal/gotelem/rpc.go diff --git a/internal/gotelem/rpc.go b/internal/gotelem/rpc.go new file mode 100644 index 0000000..6a24aae --- /dev/null +++ b/internal/gotelem/rpc.go @@ -0,0 +1,84 @@ +package gotelem + +import "github.com/tinylib/msgp/msgp" + +// this file is a simple implementation of the msgpack-rpc data format. + +type RPCType int + +const ( + RequestType RPCType = 0 + ResponseType RPCType = 1 + NotificationType RPCType = 2 +) + +//go:generate msgp +//msgp:tuple Request +//msgp:tuple Response +//msgp:tuple Notification + +// A request is a function call that expects a Response. +type Request struct { + // should always be zero. + msgtype int `msg:"type"` + MsgId uint32 `msg:"msgid"` + Method string `msg:"method"` + Params interface{} `msg:"params,allownil"` +} + +func NewRequest(msgid uint32, method string, params interface{}) *Request { + return &Request{ + msgtype: 0, + MsgId: msgid, + Method: method, + Params: params, + } +} + +// A response is the result of a function call, or an error. +type Response struct { + // should always be one. + msgtype int `msg:"type"` + MsgId uint32 `msg:"msgid"` + Error interface{} `msg:"error,allownil"` + Result interface{} `msg:"result,allownil"` +} + +// A notification is a function call that does not care if the call +// succeeds and ignores responses. +type Notification struct { + // should always be *2* + msgtype int `msg:"type"` + Method string `msg:"method"` + Params interface{} `msg:"params,allownil"` +} + +// todo: should these be functions instead, since they're arrays? and we need to determine the type beforehand. + +func getMsgType(b []byte) RPCType { + size, next, err := msgp.ReadArrayHeaderBytes(b) + if err != nil { + panic(err) + } + if size == 3 { // hot path for notifications. + return NotificationType + } + + vtype, _, err := msgp.ReadIntBytes(next) + + if err != nil { + panic(err) + } + + // todo: use readIntf instead? returns a []interface{} and we can map it ourselves... + return RPCType(vtype) +} + +func parseRPC(raw msgp.Raw) interface{} { + t := getMsgType(raw) + + if t == RequestType { + + } + return nil +}