From 3563c59b12b0b8b5fd15847bf97d71dfd8416207 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Szil=C3=A1gyi?= Date: Fri, 17 Apr 2015 16:45:44 +0300 Subject: rpc, whisper, xeth: polish whisper RPC interface --- rpc/api.go | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'rpc') diff --git a/rpc/api.go b/rpc/api.go index 5930a4c7b..614e08764 100644 --- a/rpc/api.go +++ b/rpc/api.go @@ -408,18 +408,18 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err *reply = newHexData(res) case "shh_version": *reply = api.xeth().WhisperVersion() + case "shh_post": args := new(WhisperMessageArgs) if err := json.Unmarshal(req.Params, &args); err != nil { return err } - err := api.xeth().Whisper().Post(args.Payload, args.To, args.From, args.Topics, args.Priority, args.Ttl) if err != nil { return err } - *reply = true + case "shh_newIdentity": *reply = api.xeth().Whisper().NewIdentity() // case "shh_removeIdentity": @@ -434,32 +434,35 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err return err } *reply = api.xeth().Whisper().HasIdentity(args.Identity) + case "shh_newGroup", "shh_addToGroup": return NewNotImplementedError(req.Method) + case "shh_newFilter": args := new(WhisperFilterArgs) if err := json.Unmarshal(req.Params, &args); err != nil { return err } - opts := new(xeth.Options) - // opts.From = args.From - opts.To = args.To - opts.Topics = args.Topics - id := api.xeth().NewWhisperFilter(opts) + id := api.xeth().NewWhisperFilter(args.To, args.From, args.Topics) *reply = newHexNum(big.NewInt(int64(id)).Bytes()) + case "shh_uninstallFilter": args := new(FilterIdArgs) if err := json.Unmarshal(req.Params, &args); err != nil { return err } *reply = api.xeth().UninstallWhisperFilter(args.Id) + case "shh_getFilterChanges": + // Retrieve all the new messages arrived since the last request args := new(FilterIdArgs) if err := json.Unmarshal(req.Params, &args); err != nil { return err } *reply = api.xeth().MessagesChanged(args.Id) + case "shh_getMessages": + // Retrieve all the cached messages matching a specific, existing filter args := new(FilterIdArgs) if err := json.Unmarshal(req.Params, &args); err != nil { return err -- cgit v1.2.3 From 7948cc0029db76557d6540341bdfeb818ce32c65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Szil=C3=A1gyi?= Date: Mon, 20 Apr 2015 14:56:38 +0300 Subject: rpc, whisper, xeth: fix RPC message retrieval data race --- rpc/api.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'rpc') diff --git a/rpc/api.go b/rpc/api.go index 614e08764..a73188f07 100644 --- a/rpc/api.go +++ b/rpc/api.go @@ -467,7 +467,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err if err := json.Unmarshal(req.Params, &args); err != nil { return err } - *reply = api.xeth().Whisper().Messages(args.Id) + *reply = api.xeth().Messages(args.Id) // case "eth_register": // // Placeholder for actual type -- cgit v1.2.3 From ae4bfc3cfb3f1debad9dd0211950ce09038ffa90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Szil=C3=A1gyi?= Date: Tue, 21 Apr 2015 18:31:08 +0300 Subject: rpc, ui/qt/qwhisper, whisper, xeth: introduce complex topic filters --- rpc/api.go | 8 ++----- rpc/args.go | 69 +++++++++++++++++++++++++++++++++++++++++++------------- rpc/args_test.go | 2 +- 3 files changed, 56 insertions(+), 23 deletions(-) (limited to 'rpc') diff --git a/rpc/api.go b/rpc/api.go index a73188f07..4da2fb17a 100644 --- a/rpc/api.go +++ b/rpc/api.go @@ -422,12 +422,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err case "shh_newIdentity": *reply = api.xeth().Whisper().NewIdentity() - // case "shh_removeIdentity": - // args := new(WhisperIdentityArgs) - // if err := json.Unmarshal(req.Params, &args); err != nil { - // return err - // } - // *reply = api.xeth().Whisper().RemoveIdentity(args.Identity) + case "shh_hasIdentity": args := new(WhisperIdentityArgs) if err := json.Unmarshal(req.Params, &args); err != nil { @@ -439,6 +434,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err return NewNotImplementedError(req.Method) case "shh_newFilter": + // Create a new filter to watch and match messages with args := new(WhisperFilterArgs) if err := json.Unmarshal(req.Params, &args); err != nil { return err diff --git a/rpc/args.go b/rpc/args.go index 7694a3d3f..8df483f08 100644 --- a/rpc/args.go +++ b/rpc/args.go @@ -1010,25 +1010,27 @@ func (args *WhisperIdentityArgs) UnmarshalJSON(b []byte) (err error) { } type WhisperFilterArgs struct { - To string `json:"to"` + To string From string - Topics []string + Topics [][]string } +// UnmarshalJSON implements the json.Unmarshaler interface, invoked to convert a +// JSON message blob into a WhisperFilterArgs structure. func (args *WhisperFilterArgs) UnmarshalJSON(b []byte) (err error) { + // Unmarshal the JSON message and sanity check var obj []struct { - To interface{} - Topics []interface{} + To interface{} `json:"to"` + From interface{} `json:"from"` + Topics interface{} `json:"topics"` } - - if err = json.Unmarshal(b, &obj); err != nil { + if err := json.Unmarshal(b, &obj); err != nil { return NewDecodeParamError(err.Error()) } - if len(obj) < 1 { return NewInsufficientParamsError(len(obj), 1) } - + // Retrieve the simple data contents of the filter arguments if obj[0].To == nil { args.To = "" } else { @@ -1038,17 +1040,52 @@ func (args *WhisperFilterArgs) UnmarshalJSON(b []byte) (err error) { } args.To = argstr } - - t := make([]string, len(obj[0].Topics)) - for i, j := range obj[0].Topics { - argstr, ok := j.(string) + if obj[0].From == nil { + args.From = "" + } else { + argstr, ok := obj[0].From.(string) if !ok { - return NewInvalidTypeError("topics["+string(i)+"]", "is not a string") + return NewInvalidTypeError("from", "is not a string") } - t[i] = argstr + args.From = argstr + } + // Construct the nested topic array + if obj[0].Topics != nil { + // Make sure we have an actual topic array + list, ok := obj[0].Topics.([]interface{}) + if !ok { + return NewInvalidTypeError("topics", "is not an array") + } + // Iterate over each topic and handle nil, string or array + topics := make([][]string, len(list)) + for idx, field := range list { + switch value := field.(type) { + case nil: + topics[idx] = []string{""} + + case string: + topics[idx] = []string{value} + + case []interface{}: + topics[idx] = make([]string, len(value)) + for i, nested := range value { + switch value := nested.(type) { + case nil: + topics[idx][i] = "" + + case string: + topics[idx][i] = value + + default: + return NewInvalidTypeError(fmt.Sprintf("topic[%d][%d]", idx, i), "is not a string") + } + } + default: + return NewInvalidTypeError(fmt.Sprintf("topic[%d]", idx), "not a string or array") + } + } + args.Topics = topics } - args.Topics = t - return nil } diff --git a/rpc/args_test.go b/rpc/args_test.go index 2f011bfd9..f5949b7a2 100644 --- a/rpc/args_test.go +++ b/rpc/args_test.go @@ -1943,7 +1943,7 @@ func TestWhisperFilterArgs(t *testing.T) { input := `[{"topics": ["0x68656c6c6f20776f726c64"], "to": "0x34ag445g3455b34"}]` expected := new(WhisperFilterArgs) expected.To = "0x34ag445g3455b34" - expected.Topics = []string{"0x68656c6c6f20776f726c64"} + expected.Topics = [][]string{[]string{"0x68656c6c6f20776f726c64"}} args := new(WhisperFilterArgs) if err := json.Unmarshal([]byte(input), &args); err != nil { -- cgit v1.2.3 From e252dae499a8c682c92527262cca01af337438aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Szil=C3=A1gyi?= Date: Wed, 22 Apr 2015 17:24:35 +0300 Subject: rpc: use nil topic wildcards instead of "" --- rpc/args.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'rpc') diff --git a/rpc/args.go b/rpc/args.go index 8df483f08..4bd48e6d6 100644 --- a/rpc/args.go +++ b/rpc/args.go @@ -1061,7 +1061,7 @@ func (args *WhisperFilterArgs) UnmarshalJSON(b []byte) (err error) { for idx, field := range list { switch value := field.(type) { case nil: - topics[idx] = []string{""} + topics[idx] = []string{} case string: topics[idx] = []string{value} -- cgit v1.2.3 From 978ffd3097242a5faeb7b23b9c72590170004dc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Szil=C3=A1gyi?= Date: Wed, 22 Apr 2015 18:35:50 +0300 Subject: rpc, xeth: finish cleaning up xeth --- rpc/api.go | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'rpc') diff --git a/rpc/api.go b/rpc/api.go index 4da2fb17a..4a9eb5963 100644 --- a/rpc/api.go +++ b/rpc/api.go @@ -406,10 +406,13 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err res, _ := api.xeth().DbGet([]byte(args.Database + args.Key)) *reply = newHexData(res) + case "shh_version": + // Retrieves the currently running whisper protocol version *reply = api.xeth().WhisperVersion() case "shh_post": + // Injects a new message into the whisper network args := new(WhisperMessageArgs) if err := json.Unmarshal(req.Params, &args); err != nil { return err @@ -421,18 +424,17 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err *reply = true case "shh_newIdentity": + // Creates a new whisper identity to use for sending/receiving messages *reply = api.xeth().Whisper().NewIdentity() case "shh_hasIdentity": + // Checks if an identity if owned or not args := new(WhisperIdentityArgs) if err := json.Unmarshal(req.Params, &args); err != nil { return err } *reply = api.xeth().Whisper().HasIdentity(args.Identity) - case "shh_newGroup", "shh_addToGroup": - return NewNotImplementedError(req.Method) - case "shh_newFilter": // Create a new filter to watch and match messages with args := new(WhisperFilterArgs) @@ -443,6 +445,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err *reply = newHexNum(big.NewInt(int64(id)).Bytes()) case "shh_uninstallFilter": + // Remove an existing filter watching messages args := new(FilterIdArgs) if err := json.Unmarshal(req.Params, &args); err != nil { return err @@ -455,7 +458,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err if err := json.Unmarshal(req.Params, &args); err != nil { return err } - *reply = api.xeth().MessagesChanged(args.Id) + *reply = api.xeth().WhisperMessagesChanged(args.Id) case "shh_getMessages": // Retrieve all the cached messages matching a specific, existing filter @@ -463,7 +466,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err if err := json.Unmarshal(req.Params, &args); err != nil { return err } - *reply = api.xeth().Messages(args.Id) + *reply = api.xeth().WhisperMessages(args.Id) // case "eth_register": // // Placeholder for actual type -- cgit v1.2.3