blob: 90e86e9cd9456c1231238622d250c25dd3b0e52f [file] [log] [blame]
Jiri Simsad7616c92015-03-24 23:44:30 -07001// Copyright 2015 The Vanadium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
Jiri Simsa78b646f2014-10-08 10:23:05 -07005package server
6
7import (
Jiri Simsa1f1302c2015-02-23 16:18:34 -08008 "v.io/v23/context"
Jiri Simsa1f1302c2015-02-23 16:18:34 -08009 "v.io/v23/naming"
Matt Rosencrantz94502cf2015-03-18 09:43:44 -070010 "v.io/v23/rpc"
Jiri Simsa1f1302c2015-02-23 16:18:34 -080011 "v.io/v23/vdl"
Todd Wangac9e1902015-02-25 01:58:01 -080012 "v.io/v23/vdlroot/signature"
Jiri Simsa1f1302c2015-02-23 16:18:34 -080013 "v.io/v23/verror"
Matt Rosencrantze7bf2bc2015-03-13 09:54:27 -070014 "v.io/v23/vtrace"
Jiri Simsa78b646f2014-10-08 10:23:05 -070015)
16
17var typedNil []int
18
Todd Wang5b77a342015-04-06 18:31:37 -070019const pkgPath = "v.io/x/ref/services/wspr/internal/rpc/server"
Mike Burrowscb04a6b2014-12-18 13:58:10 -080020
21// Errors.
22var (
Nicolas LaCassed7ab8a12015-02-03 11:46:29 -080023 ErrWrongNumberOfArgs = verror.Register(pkgPath+".ErrWrongNumberOfArgs", verror.NoRetry, "{1:}{2:} Method {3} got {4} args, want {5}{:_}")
24 ErrMethodNotFoundInSignature = verror.Register(pkgPath+".ErrMethodNotFoundInSignature", verror.NoRetry, "{1:}{2:} Method {3} not found in signature{:_}")
Mike Burrowscb04a6b2014-12-18 13:58:10 -080025)
26
Jiri Simsa78b646f2014-10-08 10:23:05 -070027// invoker holds a delegate function to call on invoke and a list of methods that
28// are available for be called.
29type invoker struct {
Jiri Simsa78b646f2014-10-08 10:23:05 -070030 // delegate function to call when an invoke request comes in
31 invokeFunc remoteInvokeFunc
Jiri Simsa78b646f2014-10-08 10:23:05 -070032
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -080033 signature []signature.Interface
Shyam Jayaramaneb10b9b2015-01-12 12:23:20 -080034
35 globFunc remoteGlobFunc
Jiri Simsa78b646f2014-10-08 10:23:05 -070036}
37
Matt Rosencrantz94502cf2015-03-18 09:43:44 -070038var _ rpc.Invoker = (*invoker)(nil)
Jiri Simsa78b646f2014-10-08 10:23:05 -070039
40// newInvoker is an invoker factory
Matt Rosencrantz94502cf2015-03-18 09:43:44 -070041func newInvoker(signature []signature.Interface, invokeFunc remoteInvokeFunc, globFunc remoteGlobFunc) rpc.Invoker {
Shyam Jayaramaneb10b9b2015-01-12 12:23:20 -080042 i := &invoker{invokeFunc, signature, globFunc}
Jiri Simsa78b646f2014-10-08 10:23:05 -070043 return i
44}
45
46// Prepare implements the Invoker interface.
Todd Wang5ab03662015-02-19 21:03:01 -080047func (i *invoker) Prepare(methodName string, numArgs int) ([]interface{}, []*vdl.Value, error) {
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -080048 method, err := i.MethodSignature(nil, methodName)
49 if err != nil {
50 return nil, nil, err
Jiri Simsa78b646f2014-10-08 10:23:05 -070051 }
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -080052 if got, want := numArgs, len(method.InArgs); got != want {
Todd Wangb63e9eb2015-02-10 19:57:39 -080053 return nil, nil, verror.New(ErrWrongNumberOfArgs, nil, methodName, got, want)
Jiri Simsa78b646f2014-10-08 10:23:05 -070054 }
Jiri Simsa78b646f2014-10-08 10:23:05 -070055 argptrs := make([]interface{}, len(method.InArgs))
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -080056 for ix, arg := range method.InArgs {
57 argptrs[ix] = vdl.ZeroValue(arg.Type)
Jiri Simsa78b646f2014-10-08 10:23:05 -070058 }
Todd Wang5ab03662015-02-19 21:03:01 -080059 return argptrs, method.Tags, nil
Jiri Simsa78b646f2014-10-08 10:23:05 -070060}
61
62// Invoke implements the Invoker interface.
Matt Rosencrantz94502cf2015-03-18 09:43:44 -070063func (i *invoker) Invoke(methodName string, call rpc.StreamServerCall, argptrs []interface{}) ([]interface{}, error) {
Jiri Simsa78b646f2014-10-08 10:23:05 -070064 replychan := i.invokeFunc(methodName, argptrs, call)
65
66 // Wait for the result
67 reply := <-replychan
68
Jiri Simsa78b646f2014-10-08 10:23:05 -070069 if reply.Err != nil {
Todd Wangf21e1552015-02-18 13:21:52 -080070 return nil, reply.Err
Jiri Simsa78b646f2014-10-08 10:23:05 -070071 }
72
Matt Rosencrantze7bf2bc2015-03-13 09:54:27 -070073 vtrace.GetStore(call.Context()).Merge(reply.TraceResponse)
74
Todd Wang5ab03662015-02-19 21:03:01 -080075 // Convert the reply.Results from []*vdl.Value to []interface{}
Todd Wangf21e1552015-02-18 13:21:52 -080076 results := make([]interface{}, len(reply.Results))
Alex Fandriantoaa5af7c2015-01-29 15:20:02 -080077 for i, r := range reply.Results {
Todd Wang5ab03662015-02-19 21:03:01 -080078 results[i] = r
Alex Fandriantoaa5af7c2015-01-29 15:20:02 -080079 }
Jiri Simsa78b646f2014-10-08 10:23:05 -070080 return results, nil
81}
Robin Thellend0215a5b2014-11-05 18:12:41 -080082
83// TODO(bjornick,rthellend): Find a reasonable way to implement this for JS.
Matt Rosencrantz94502cf2015-03-18 09:43:44 -070084func (i *invoker) Globber() *rpc.GlobState {
Shyam Jayaramaneb10b9b2015-01-12 12:23:20 -080085 if i.globFunc == nil {
86 return nil
87 }
Matt Rosencrantz94502cf2015-03-18 09:43:44 -070088 return &rpc.GlobState{AllGlobber: i}
Shyam Jayaramaneb10b9b2015-01-12 12:23:20 -080089}
90
Matt Rosencrantz94502cf2015-03-18 09:43:44 -070091func (i *invoker) Glob__(call rpc.ServerCall, pattern string) (<-chan naming.GlobReply, error) {
Matt Rosencrantz9dce9b22015-03-02 10:48:37 -080092 return i.globFunc(pattern, call)
Robin Thellend0215a5b2014-11-05 18:12:41 -080093}
Todd Wang531a5e32014-11-16 22:38:49 -080094
Matt Rosencrantz94502cf2015-03-18 09:43:44 -070095func (i *invoker) Signature(call rpc.ServerCall) ([]signature.Interface, error) {
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -080096 return i.signature, nil
Todd Wang531a5e32014-11-16 22:38:49 -080097}
98
Matt Rosencrantz94502cf2015-03-18 09:43:44 -070099func (i *invoker) MethodSignature(call rpc.ServerCall, method string) (signature.Method, error) {
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800100 if methodSig, ok := signature.FirstMethod(i.signature, method); ok {
101 return methodSig, nil
102 }
Nicolas LaCassed7ab8a12015-02-03 11:46:29 -0800103
104 var innerContext *context.T
Matt Rosencrantz9dce9b22015-03-02 10:48:37 -0800105 if call != nil {
106 innerContext = call.Context()
Nicolas LaCassed7ab8a12015-02-03 11:46:29 -0800107 }
108
Todd Wangb63e9eb2015-02-10 19:57:39 -0800109 return signature.Method{}, verror.New(ErrMethodNotFoundInSignature, innerContext, method)
Todd Wang531a5e32014-11-16 22:38:49 -0800110}