wsprd: Pass method tags from JS to WSPR.
The go changes are pretty much what we'd expect. The signature passed
from JS to go has tags for the methods. vom2 signature have method
tags, so this should be fine going forward. This resulted in more vom2
encoding from Go to JS and one spot where we vom encoded data from JS
to go.
labels 1/2
Change-Id: I1559d2b344d808095ef6b901d4ec2e7652de1917
diff --git a/services/wsprd/app/app_test.go b/services/wsprd/app/app_test.go
index e00ec6d..6c2b950 100644
--- a/services/wsprd/app/app_test.go
+++ b/services/wsprd/app/app_test.go
@@ -1,8 +1,6 @@
package app
import (
- "bytes"
- "encoding/hex"
"encoding/json"
"fmt"
"reflect"
@@ -18,7 +16,6 @@
"veyron.io/veyron/veyron2/verror2"
"veyron.io/veyron/veyron2/vom"
vom_wiretype "veyron.io/veyron/veyron2/vom/wiretype"
- "veyron.io/veyron/veyron2/vom2"
"veyron.io/veyron/veyron2/wiretype"
"veyron.io/wspr/veyron/services/wsprd/lib"
"veyron.io/wspr/veyron/services/wsprd/lib/testwriter"
@@ -269,18 +266,12 @@
}
}
-func vomEncode(i interface{}) string {
- var buf bytes.Buffer
- encoder, err := vom2.NewBinaryEncoder(&buf)
+func vomEncodeOrDie(v interface{}) string {
+ s, err := lib.VomEncode(v)
if err != nil {
panic(err)
}
-
- if err := encoder.Encode(i); err != nil {
- panic(err)
- }
- return hex.EncodeToString(buf.Bytes())
-
+ return s
}
func TestCallingGoServer(t *testing.T) {
runGoServerTestCase(t, goServerTestCase{
@@ -289,7 +280,7 @@
numOutArgs: 2,
expectedStream: []testwriter.Response{
testwriter.Response{
- Message: vomEncode([]interface{}{int32(5)}),
+ Message: vomEncodeOrDie([]interface{}{int32(5)}),
Type: lib.ResponseFinal,
},
},
@@ -314,19 +305,19 @@
numOutArgs: 2,
expectedStream: []testwriter.Response{
testwriter.Response{
- Message: vomEncode(int32(1)),
+ Message: vomEncodeOrDie(int32(1)),
Type: lib.ResponseStream,
},
testwriter.Response{
- Message: vomEncode(int32(3)),
+ Message: vomEncodeOrDie(int32(3)),
Type: lib.ResponseStream,
},
testwriter.Response{
- Message: vomEncode(int32(6)),
+ Message: vomEncodeOrDie(int32(6)),
Type: lib.ResponseStream,
},
testwriter.Response{
- Message: vomEncode(int32(10)),
+ Message: vomEncodeOrDie(int32(10)),
Type: lib.ResponseStream,
},
testwriter.Response{
@@ -334,7 +325,7 @@
Type: lib.ResponseStreamClose,
},
testwriter.Response{
- Message: vomEncode([]interface{}{int32(10)}),
+ Message: vomEncodeOrDie([]interface{}{int32(10)}),
Type: lib.ResponseFinal,
},
},
@@ -527,7 +518,7 @@
vomClientStream := []string{}
for _, m := range test.clientStream {
- vomClientStream = append(vomClientStream, vomEncode(m))
+ vomClientStream = append(vomClientStream, vomEncodeOrDie(m))
}
mock := &mockJSServer{
controller: rt.controller,
@@ -538,7 +529,7 @@
serverStream: test.serverStream,
hasAuthorizer: test.hasAuthorizer,
authError: test.authError,
- inArgs: vomEncode(test.inArgs),
+ inArgs: test.inArgs,
finalResponse: test.finalResponse,
finalError: test.err,
}
diff --git a/services/wsprd/app/mock_jsServer_test.go b/services/wsprd/app/mock_jsServer_test.go
index 8240df3..d347f10 100644
--- a/services/wsprd/app/mock_jsServer_test.go
+++ b/services/wsprd/app/mock_jsServer_test.go
@@ -2,13 +2,19 @@
import (
"bytes"
+ "encoding/hex"
"encoding/json"
"fmt"
"reflect"
"sync"
"testing"
+ "veyron.io/veyron/veyron2/vdl"
+ "veyron.io/veyron/veyron2/vdl/valconv"
+ "veyron.io/veyron/veyron2/vom2"
+ "veyron.io/wspr/veyron/services/wsprd/ipc/server"
"veyron.io/wspr/veyron/services/wsprd/lib"
+ "veyron.io/wspr/veyron/services/wsprd/principal"
"veyron.io/wspr/veyron/services/wsprd/signature"
)
@@ -22,7 +28,7 @@
serverStream []string
hasAuthorizer bool
authError error
- inArgs string
+ inArgs []interface{}
finalResponse interface{}
finalError error
hasCalledAuth bool
@@ -65,6 +71,19 @@
panic(err)
}
+func vomDecode(s string, v interface{}) error {
+ b, err := hex.DecodeString(s)
+ if err != nil {
+ return err
+ }
+ decoder, err := vom2.NewDecoder(bytes.NewBuffer(b))
+ if err != nil {
+ return err
+ }
+
+ return decoder.Decode(v)
+}
+
func normalize(msg interface{}) (map[string]interface{}, error) {
// We serialize and deserialize the reponse so that we can do deep equal with
// messages that contain non-exported structs.
@@ -97,7 +116,7 @@
}
bytes, err := json.Marshal(map[string]interface{}{
"handle": 0,
- "signature": m.serviceSignature,
+ "signature": vomEncodeOrDie(m.serviceSignature),
"hasAuthorizer": m.hasAuthorizer,
})
if err != nil {
@@ -109,18 +128,14 @@
}
// Returns false if the blessing is malformed
-func validateBlessing(v interface{}) bool {
- blessings, ok := v.(map[string]interface{})
- return ok && blessings["Handle"] != nil && blessings["PublicKey"] != nil
+func validateBlessing(blessings principal.BlessingsHandle) bool {
+ return blessings.Handle != 0 && blessings.PublicKey != ""
}
-func validateEndpoint(v interface{}) bool {
- if v == nil {
- return false
- }
- ep, ok := v.(string)
- return ok && ep != ""
+func validateEndpoint(ep string) bool {
+ return ep != ""
}
+
func (m *mockJSServer) handleAuthRequest(v interface{}) error {
defer func() {
m.flowCount += 2
@@ -132,53 +147,55 @@
return nil
}
- msg, err := normalize(v)
- if err != nil {
- m.controller.HandleAuthResponse(m.flowCount, internalErrJSON(err))
- return nil
-
- }
- if msg["handle"] != 0.0 {
- m.controller.HandleAuthResponse(m.flowCount, internalErrJSON(fmt.Sprintf("unexpected handled: %f", msg["handle"])))
+ var msg server.AuthRequest
+ if err := vomDecode(v.(string), &msg); err != nil {
+ m.controller.HandleAuthResponse(m.flowCount, internalErrJSON(fmt.Sprintf("error decoding %v:", err)))
return nil
}
- // Do an exact match on keys in this map for the context structure.
- // For keys not in this map, we can't do an exact equality check and
- // we'll verify them later.
- expectedContextValues := map[string]interface{}{
- "method": lib.LowercaseFirstCharacter(m.method),
- "name": "adder",
- "suffix": "adder",
+ if msg.Handle != 0 {
+ m.controller.HandleAuthResponse(m.flowCount, internalErrJSON(fmt.Sprintf("unexpected handled: %f", msg.Handle)))
+ return nil
}
- context := msg["context"].(map[string]interface{})
- for key, value := range expectedContextValues {
- if !reflect.DeepEqual(context[key], value) {
- m.controller.HandleAuthResponse(m.flowCount, internalErrJSON(fmt.Sprintf("unexpected value for %s: got %v, want %v", key, context[key], value)))
- return nil
+ context := msg.Context
+ if field, got, want := "Method", context.Method, lib.LowercaseFirstCharacter(m.method); got != want {
+ m.controller.HandleAuthResponse(m.flowCount, internalErrJSON(fmt.Sprintf("unexpected value for %s: got %v, want %v", field, got, want)))
+ return nil
- }
}
+
+ if field, got, want := "Name", context.Name, "adder"; got != want {
+ m.controller.HandleAuthResponse(m.flowCount, internalErrJSON(fmt.Sprintf("unexpected value for %s: got %v, want %v", field, got, want)))
+ return nil
+
+ }
+
+ if field, got, want := "Suffix", context.Suffix, "adder"; got != want {
+ m.controller.HandleAuthResponse(m.flowCount, internalErrJSON(fmt.Sprintf("unexpected value for %s: got %v, want %v", field, got, want)))
+ return nil
+
+ }
+
// We expect localBlessings and remoteBlessings to be set and the publicKey be a string
- if !validateBlessing(context["localBlessings"]) {
- m.controller.HandleAuthResponse(m.flowCount, internalErrJSON(fmt.Sprintf("bad localblessing:%v", context["localBlessing"])))
+ if !validateBlessing(context.LocalBlessings) {
+ m.controller.HandleAuthResponse(m.flowCount, internalErrJSON(fmt.Sprintf("bad localblessing:%v", context.LocalBlessings)))
return nil
}
- if !validateBlessing(context["remoteBlessings"]) {
- m.controller.HandleAuthResponse(m.flowCount, internalErrJSON(fmt.Sprintf("bad remoteblessing:%v", context["remoteBlessings"])))
+ if !validateBlessing(context.RemoteBlessings) {
+ m.controller.HandleAuthResponse(m.flowCount, internalErrJSON(fmt.Sprintf("bad remoteblessing:%v", context.RemoteBlessings)))
return nil
}
// We expect endpoints to be set
- if !validateEndpoint(context["localEndpoint"]) {
- m.controller.HandleAuthResponse(m.flowCount, internalErrJSON(fmt.Sprintf("bad endpoint:%v", context["localEndpoint"])))
+ if !validateEndpoint(context.LocalEndpoint) {
+ m.controller.HandleAuthResponse(m.flowCount, internalErrJSON(fmt.Sprintf("bad endpoint:%v", context.LocalEndpoint)))
return nil
}
- if !validateEndpoint(context["remoteEndpoint"]) {
- m.controller.HandleAuthResponse(m.flowCount, internalErrJSON(fmt.Sprintf("bad endpoint:%v", context["remoteEndpoint"])))
+ if !validateEndpoint(context.RemoteEndpoint) {
+ m.controller.HandleAuthResponse(m.flowCount, internalErrJSON(fmt.Sprintf("bad endpoint:%v", context.RemoteEndpoint)))
return nil
}
@@ -205,46 +222,55 @@
return nil
}
- msg, err := normalize(v)
- if err != nil {
+ var msg server.ServerRPCRequest
+ if err := vomDecode(v.(string), &msg); err != nil {
m.controller.HandleServerResponse(m.flowCount, internalErrJSON(err))
return nil
}
- // Do an exact match on keys in this map for the request structure.
- // For keys not in this map, we can't do an exact equality check and
- // we'll verify them later.
- expectedRequestValues := map[string]interface{}{
- "Method": lib.LowercaseFirstCharacter(m.method),
- "Handle": 0.0,
- "Args": m.inArgs,
+ if field, got, want := "Method", msg.Method, lib.LowercaseFirstCharacter(m.method); got != want {
+ m.controller.HandleServerResponse(m.flowCount, internalErrJSON(fmt.Sprintf("unexpected value for %s: got %v, want %v", field, got, want)))
+ return nil
+
}
- for key, value := range expectedRequestValues {
- if !reflect.DeepEqual(msg[key], value) {
- m.controller.HandleServerResponse(m.flowCount, internalErrJSON(fmt.Sprintf("unexpected value for %s: got %v, want %v", key, msg[key], value)))
- return nil
+ if field, got, want := "Handle", msg.Handle, int64(0); got != want {
+ m.controller.HandleServerResponse(m.flowCount, internalErrJSON(fmt.Sprintf("unexpected value for %s: got %v, want %v", field, got, want)))
+ return nil
+ }
+
+ vdlArgs := []interface{}{}
+ for _, v := range m.inArgs {
+ var vdlArg *vdl.Value
+ if err := valconv.Convert(&vdlArg, v); err != nil {
+ fmt.Println("Failed to convert", err)
}
+ vdlArgs = append(vdlArgs, vdlArg)
+ }
+ if field, got, want := "Args", msg.Args, vdlArgs; !reflect.DeepEqual(got, want) {
+ fmt.Printf("type %T %T\n", got[0], want[0])
+ m.controller.HandleServerResponse(m.flowCount, internalErrJSON(fmt.Sprintf("unexpected value for %s: got %v, want %v", field, got, want)))
+ return nil
+
}
- context := msg["Context"].(map[string]interface{})
- expectedContextValues := map[string]interface{}{
- "Name": "adder",
- "Suffix": "adder",
+ context := msg.Context
+ if field, got, want := "Name", context.Name, "adder"; got != want {
+ m.controller.HandleServerResponse(m.flowCount, internalErrJSON(fmt.Sprintf("unexpected value for %s: got %v, want %v", field, got, want)))
+ return nil
+
}
- for key, value := range expectedContextValues {
- if !reflect.DeepEqual(context[key], value) {
- m.controller.HandleServerResponse(m.flowCount, internalErrJSON(fmt.Sprintf("unexpected value for %s: got %v, want %v", key, context[key], value)))
- return nil
+ if field, got, want := "Suffix", context.Suffix, "adder"; got != want {
+ m.controller.HandleServerResponse(m.flowCount, internalErrJSON(fmt.Sprintf("unexpected value for %s: got %v, want %v", field, got, want)))
+ return nil
- }
}
- if !validateBlessing(context["RemoteBlessings"]) {
- m.controller.HandleServerResponse(m.flowCount, internalErrJSON(fmt.Sprintf("bad Remoteblessing:%v", context["RemoteBlessings"])))
+ if !validateBlessing(context.RemoteBlessings) {
+ m.controller.HandleServerResponse(m.flowCount, internalErrJSON(fmt.Sprintf("bad Remoteblessing:%v", context.RemoteBlessings)))
return nil
}
diff --git a/services/wsprd/ipc/server/dispatcher.go b/services/wsprd/ipc/server/dispatcher.go
index 632c053..9cb48f2 100644
--- a/services/wsprd/ipc/server/dispatcher.go
+++ b/services/wsprd/ipc/server/dispatcher.go
@@ -2,6 +2,7 @@
import (
"bytes"
+ "encoding/hex"
"encoding/json"
"sync"
@@ -12,6 +13,7 @@
"veyron.io/veyron/veyron2/security"
"veyron.io/veyron/veyron2/verror2"
"veyron.io/veyron/veyron2/vlog"
+ "veyron.io/veyron/veyron2/vom2"
)
type flowFactory interface {
@@ -20,7 +22,7 @@
}
type invokerFactory interface {
- createInvoker(handle int64, signature signature.JSONServiceSignature, label security.Label) (ipc.Invoker, error)
+ createInvoker(handle int64, signature signature.JSONServiceSignature) (ipc.Invoker, error)
}
type authFactory interface {
@@ -30,8 +32,7 @@
type lookupReply struct {
Handle int64
HasAuthorizer bool
- Label security.Label
- Signature signature.JSONServiceSignature
+ Signature string
Err *verror2.Standard
}
@@ -96,7 +97,22 @@
return nil, nil, verror2.Make(verror2.NoExist, nil, "Dispatcher", suffix)
}
- invoker, err := d.invokerFactory.createInvoker(request.Handle, request.Signature, request.Label)
+ var sig signature.JSONServiceSignature
+ b, err := hex.DecodeString(request.Signature)
+ if err != nil {
+ return nil, nil, verror2.Convert(verror2.Internal, nil, err)
+ }
+ buf := bytes.NewBuffer(b)
+ decoder, err := vom2.NewDecoder(buf)
+ if err != nil {
+ return nil, nil, verror2.Convert(verror2.Internal, nil, err)
+ }
+
+ if err := decoder.Decode(&sig); err != nil {
+ return nil, nil, verror2.Convert(verror2.Internal, nil, err)
+ }
+
+ invoker, err := d.invokerFactory.createInvoker(request.Handle, sig)
if err != nil {
return nil, nil, err
}
@@ -120,7 +136,8 @@
var request lookupReply
decoder := json.NewDecoder(bytes.NewBufferString(data))
if err := decoder.Decode(&request); err != nil {
- request = lookupReply{Err: verror2.Convert(verror2.Internal, nil, err).(*verror2.Standard)}
+ err2 := verror2.Convert(verror2.Internal, nil, err).(verror2.Standard)
+ request = lookupReply{Err: &err2}
d.logger.Errorf("unmarshaling invoke request failed: %v, %s", err, data)
}
ch <- request
diff --git a/services/wsprd/ipc/server/dispatcher_test.go b/services/wsprd/ipc/server/dispatcher_test.go
index b70640d..51b80ca 100644
--- a/services/wsprd/ipc/server/dispatcher_test.go
+++ b/services/wsprd/ipc/server/dispatcher_test.go
@@ -27,11 +27,10 @@
type mockInvoker struct {
handle int64
sig signature.JSONServiceSignature
- label security.Label
}
func (m mockInvoker) Prepare(string, int) ([]interface{}, []interface{}, error) {
- return nil, []interface{}{m.label}, nil
+ return nil, []interface{}{}, nil
}
func (mockInvoker) Invoke(string, ipc.ServerCall, []interface{}) ([]interface{}, error) {
@@ -52,8 +51,8 @@
type mockInvokerFactory struct{}
-func (mockInvokerFactory) createInvoker(handle int64, sig signature.JSONServiceSignature, label security.Label) (ipc.Invoker, error) {
- return &mockInvoker{handle: handle, sig: sig, label: label}, nil
+func (mockInvokerFactory) createInvoker(handle int64, sig signature.JSONServiceSignature) (ipc.Invoker, error) {
+ return &mockInvoker{handle: handle, sig: sig}, nil
}
type mockAuthorizer struct {
@@ -73,16 +72,31 @@
rt.Init()
}
+func vomEncodeOrDie(v interface{}) string {
+ s, err := lib.VomEncode(v)
+ if err != nil {
+ panic(err)
+ }
+ return s
+}
+
func TestSuccessfulLookup(t *testing.T) {
flowFactory := &mockFlowFactory{}
d := newDispatcher(0, flowFactory, mockInvokerFactory{}, mockAuthorizerFactory{}, rt.R().Logger())
+ expectedSig := signature.JSONServiceSignature{
+ "add": signature.JSONMethodSignature{
+ InArgs: []string{"foo", "bar"},
+ NumOutArgs: 1,
+ Tags: []interface{}{},
+ },
+ }
+
go func() {
if err := flowFactory.writer.WaitForMessage(1); err != nil {
t.Errorf("failed to get dispatch request %v", err)
t.Fail()
}
- signature := `{"add":{"inArgs":["foo","bar"],"numOutArgs":1,"isStreaming":false}}`
- jsonResponse := fmt.Sprintf(`{"handle":1,"hasAuthorizer":false,"label":%d,"signature":%s}`, security.WriteLabel, signature)
+ jsonResponse := fmt.Sprintf(`{"handle":1,"hasAuthorizer":false,"signature":"%s"}`, vomEncodeOrDie(expectedSig))
d.handleLookupResponse(0, jsonResponse)
}()
@@ -92,15 +106,9 @@
t.Errorf("Unexpected error: %v", err)
}
- expectedSig := signature.JSONServiceSignature{
- "add": signature.JSONMethodSignature{
- InArgs: []string{"foo", "bar"},
- NumOutArgs: 1,
- },
- }
- expectedInvoker := &mockInvoker{handle: 1, sig: expectedSig, label: security.WriteLabel}
+ expectedInvoker := &mockInvoker{handle: 1, sig: expectedSig}
if !reflect.DeepEqual(invoker, expectedInvoker) {
- t.Errorf("wrong invoker returned, expected: %v, got :%v", expectedInvoker, invoker)
+ t.Errorf("wrong invoker returned, expected: %#v, got :%#v", expectedInvoker, invoker)
}
expectedAuth := mockAuthorizer{handle: 1, hasAuthorizer: false}
@@ -125,13 +133,20 @@
func TestSuccessfulLookupWithAuthorizer(t *testing.T) {
flowFactory := &mockFlowFactory{}
d := newDispatcher(0, flowFactory, mockInvokerFactory{}, mockAuthorizerFactory{}, rt.R().Logger())
+ expectedSig := signature.JSONServiceSignature{
+ "add": signature.JSONMethodSignature{
+ InArgs: []string{"foo", "bar"},
+ NumOutArgs: 1,
+ Tags: []interface{}{},
+ },
+ }
+
go func() {
if err := flowFactory.writer.WaitForMessage(1); err != nil {
t.Errorf("failed to get dispatch request %v", err)
t.Fail()
}
- signature := `{"add":{"inArgs":["foo","bar"],"numOutArgs":1,"isStreaming":false}}`
- jsonResponse := fmt.Sprintf(`{"handle":1,"hasAuthorizer":true,"label":%d,"signature":%s}`, security.ReadLabel, signature)
+ jsonResponse := fmt.Sprintf(`{"handle":1,"hasAuthorizer":true,"signature":"%s"}`, vomEncodeOrDie(expectedSig))
d.handleLookupResponse(0, jsonResponse)
}()
@@ -141,13 +156,7 @@
t.Errorf("Unexpected error: %v", err)
}
- expectedSig := signature.JSONServiceSignature{
- "add": signature.JSONMethodSignature{
- InArgs: []string{"foo", "bar"},
- NumOutArgs: 1,
- },
- }
- expectedInvoker := &mockInvoker{handle: 1, sig: expectedSig, label: security.ReadLabel}
+ expectedInvoker := &mockInvoker{handle: 1, sig: expectedSig}
if !reflect.DeepEqual(invoker, expectedInvoker) {
t.Errorf("wrong invoker returned, expected: %v, got :%v", expectedInvoker, invoker)
}
diff --git a/services/wsprd/ipc/server/invoker.go b/services/wsprd/ipc/server/invoker.go
index f60dfb0..95a3c47 100644
--- a/services/wsprd/ipc/server/invoker.go
+++ b/services/wsprd/ipc/server/invoker.go
@@ -2,8 +2,10 @@
import (
"veyron.io/veyron/veyron2/ipc"
- "veyron.io/veyron/veyron2/security"
"veyron.io/veyron/veyron2/verror"
+
+ "veyron.io/wspr/veyron/services/wsprd/lib"
+ "veyron.io/wspr/veyron/services/wsprd/signature"
)
var typedNil []int
@@ -18,32 +20,33 @@
// map of special methods like "Signature" which invoker handles on behalf of the actual service
predefinedInvokers map[string]ipc.Invoker
- label security.Label
+ // This is to get the method tags. TODO(bjornick): Remove this when vom2 signatures
+ // has tags.
+ jsonSig signature.JSONServiceSignature
}
var _ ipc.Invoker = (*invoker)(nil)
// newInvoker is an invoker factory
-func newInvoker(sig ipc.ServiceSignature, label security.Label, invokeFunc remoteInvokeFunc) ipc.Invoker {
+func newInvoker(sig ipc.ServiceSignature, jsonSig signature.JSONServiceSignature, invokeFunc remoteInvokeFunc) ipc.Invoker {
predefinedInvokers := make(map[string]ipc.Invoker)
// Special handling for predefined "signature" method
predefinedInvokers["Signature"] = newSignatureInvoker(sig)
- i := &invoker{sig, invokeFunc, predefinedInvokers, label}
+ i := &invoker{sig, invokeFunc, predefinedInvokers, jsonSig}
return i
}
// Prepare implements the Invoker interface.
func (i *invoker) Prepare(methodName string, numArgs int) ([]interface{}, []interface{}, error) {
-
if pi := i.predefinedInvokers[methodName]; pi != nil {
return pi.Prepare(methodName, numArgs)
}
- method, ok := i.sig.Methods[methodName]
+ method, ok := i.jsonSig[lib.LowercaseFirstCharacter(methodName)]
if !ok {
- return nil, []interface{}{security.AdminLabel}, verror.NoExistf("method name not found in IDL: %s", methodName)
+ return nil, nil, verror.NoExistf("method name not found in IDL: %s", methodName)
}
argptrs := make([]interface{}, len(method.InArgs))
@@ -53,13 +56,7 @@
argptrs[ix] = &x // Accept AnyData
}
- securityLabel := i.label
-
- if !security.IsValidLabel(securityLabel) {
- securityLabel = security.AdminLabel
- }
-
- return argptrs, []interface{}{securityLabel}, nil
+ return argptrs, method.Tags, nil
}
// Invoke implements the Invoker interface.
diff --git a/services/wsprd/ipc/server/server.go b/services/wsprd/ipc/server/server.go
index e3cb87e..a92e710 100644
--- a/services/wsprd/ipc/server/server.go
+++ b/services/wsprd/ipc/server/server.go
@@ -27,21 +27,23 @@
}
// A request from the proxy to javascript to handle an RPC
-type serverRPCRequest struct {
+type ServerRPCRequest struct {
ServerId uint64
Handle int64
Method string
- Args string
- Context serverRPCRequestContext
+ Args []interface{}
+ Context ServerRPCRequestContext
}
-// call context for a serverRPCRequest
-type serverRPCRequestContext struct {
+// TODO(bjornick): Merge this with the context used by the security code.
+// call context for a ServerRPCRequest
+type ServerRPCRequestContext struct {
Suffix string
Name string
RemoteBlessings principal.BlessingsHandle
RemoteBlessingStrings []string
Timeout int64 // The time period (in ns) between now and the deadline.
+ MethodTags []interface{}
}
// The response from the javascript server to the proxy.
@@ -74,11 +76,13 @@
Err *verror2.Standard
}
-type context struct {
+// Contex is the security context passed to Javascript.
+// This is exported to make the app test easier.
+type Context struct {
Method string `json:"method"`
Name string `json:"name"`
Suffix string `json:"suffix"`
- Label security.Label `json:"label"` // TODO(bjornick,ashankar): This should be method tags!
+ MethodTags []interface{} `json:"methodTags"`
LocalBlessings principal.BlessingsHandle `json:"localBlessings"`
LocalBlessingStrings []string `json:"localBlessingStrings"`
RemoteBlessings principal.BlessingsHandle `json:"remoteBlessings"`
@@ -87,10 +91,12 @@
RemoteEndpoint string `json:"remoteEndpoint"`
}
-type authRequest struct {
+// AuthRequest is a request for a javascript authorizer to run
+// This is exported to make the app test easier.
+type AuthRequest struct {
ServerID uint64 `json:"serverID"`
Handle int64 `json:"handle"`
- Context context `json:"context"`
+ Context Context `json:"context"`
}
type Server struct {
@@ -151,14 +157,6 @@
timeout = lib.GoToJSDuration(deadline.Sub(time.Now()))
}
- context := serverRPCRequestContext{
- Suffix: call.Suffix(),
- Name: call.Name(),
- Timeout: timeout,
- RemoteBlessings: s.convertBlessingsToHandle(call.RemoteBlessings()),
- RemoteBlessingStrings: call.RemoteBlessings().ForContext(call),
- }
-
errHandler := func(err error) <-chan *serverRPCReply {
if ch := s.popServerRequest(flow.ID); ch != nil {
stdErr := verror2.Convert(verror2.Internal, call, err).(verror2.Standard)
@@ -168,26 +166,32 @@
return replyChan
}
- var buf bytes.Buffer
- encoder, err := vom2.NewBinaryEncoder(&buf)
+
+ context := ServerRPCRequestContext{
+ Suffix: call.Suffix(),
+ Name: call.Name(),
+ Timeout: timeout,
+ RemoteBlessings: s.convertBlessingsToHandle(call.RemoteBlessings()),
+ RemoteBlessingStrings: call.RemoteBlessings().ForContext(call),
+ MethodTags: call.MethodTags(),
+ }
+
+ // Send a invocation request to JavaScript
+ message := ServerRPCRequest{
+ ServerId: s.id,
+ Handle: handle,
+ Method: lib.LowercaseFirstCharacter(methodName),
+ Args: args,
+ Context: context,
+ }
+
+ vomMessage, err := lib.VomEncode(message)
+
if err != nil {
return errHandler(err)
}
- if err := encoder.Encode(args); err != nil {
- return errHandler(err)
- }
-
- // Send a invocation request to JavaScript
- message := serverRPCRequest{
- ServerId: s.id,
- Handle: handle,
- Method: lib.LowercaseFirstCharacter(methodName),
- Args: hex.EncodeToString(buf.Bytes()),
- Context: context,
- }
-
- if err := flow.Writer.Send(lib.ResponseServerRequest, message); err != nil {
+ if err := flow.Writer.Send(lib.ResponseServerRequest, vomMessage); err != nil {
return errHandler(err)
}
@@ -257,14 +261,14 @@
s.mu.Lock()
s.outstandingAuthRequests[flow.ID] = replyChan
s.mu.Unlock()
- message := authRequest{
+ message := AuthRequest{
ServerID: s.id,
Handle: handle,
- Context: context{
+ Context: Context{
Method: lib.LowercaseFirstCharacter(ctx.Method()),
Name: ctx.Name(),
Suffix: ctx.Suffix(),
- Label: labelFromMethodTags(ctx.MethodTags()),
+ MethodTags: ctx.MethodTags(),
LocalEndpoint: ctx.LocalEndpoint().String(),
RemoteEndpoint: ctx.RemoteEndpoint().String(),
LocalBlessings: s.convertBlessingsToHandle(ctx.LocalBlessings()),
@@ -275,11 +279,14 @@
}
s.helper.GetLogger().VI(0).Infof("Sending out auth request for %v, %v", flow.ID, message)
- if err := flow.Writer.Send(lib.ResponseAuthRequest, message); err != nil {
+ vomMessage, err := lib.VomEncode(message)
+ if err != nil {
+ replyChan <- verror2.Convert(verror2.Internal, nil, err)
+ } else if err := flow.Writer.Send(lib.ResponseAuthRequest, vomMessage); err != nil {
replyChan <- verror2.Convert(verror2.Internal, nil, err)
}
- err := <-replyChan
+ err = <-replyChan
s.helper.GetLogger().VI(0).Infof("going to respond with %v", err)
s.mu.Lock()
delete(s.outstandingAuthRequests, flow.ID)
@@ -383,14 +390,14 @@
s.helper.CleanupFlow(id)
}
-func (s *Server) createInvoker(handle int64, sig signature.JSONServiceSignature, label security.Label) (ipc.Invoker, error) {
+func (s *Server) createInvoker(handle int64, sig signature.JSONServiceSignature) (ipc.Invoker, error) {
serviceSig, err := sig.ServiceSignature()
if err != nil {
return nil, err
}
remoteInvokeFunc := s.createRemoteInvokerFunc(handle)
- return newInvoker(serviceSig, label, remoteInvokeFunc), nil
+ return newInvoker(serviceSig, sig, remoteInvokeFunc), nil
}
func (s *Server) createAuthorizer(handle int64, hasAuthorizer bool) (security.Authorizer, error) {
diff --git a/services/wsprd/lib/vom.go b/services/wsprd/lib/vom.go
new file mode 100644
index 0000000..b145009
--- /dev/null
+++ b/services/wsprd/lib/vom.go
@@ -0,0 +1,20 @@
+package lib
+
+import (
+ "bytes"
+ "encoding/hex"
+ "veyron.io/veyron/veyron2/vom2"
+)
+
+func VomEncode(v interface{}) (string, error) {
+ var buf bytes.Buffer
+ encoder, err := vom2.NewBinaryEncoder(&buf)
+ if err != nil {
+ return "", err
+ }
+
+ if err := encoder.Encode(v); err != nil {
+ return "", err
+ }
+ return hex.EncodeToString(buf.Bytes()), nil
+}
diff --git a/services/wsprd/signature/signature.go b/services/wsprd/signature/signature.go
index d32dac1..5c89bfc 100644
--- a/services/wsprd/signature/signature.go
+++ b/services/wsprd/signature/signature.go
@@ -28,6 +28,7 @@
InArgs []string // InArgs is a list of argument names.
NumOutArgs int
IsStreaming bool
+ Tags []interface{}
}
// NewJSONServiceSignature converts an ipc service signature to the format used by JSON.