Jiri Simsa | d7616c9 | 2015-03-24 23:44:30 -0700 | [diff] [blame] | 1 | // 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 Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 5 | package server |
| 6 | |
| 7 | import ( |
Jiri Simsa | 1f1302c | 2015-02-23 16:18:34 -0800 | [diff] [blame] | 8 | "v.io/v23/context" |
Jiri Simsa | 1f1302c | 2015-02-23 16:18:34 -0800 | [diff] [blame] | 9 | "v.io/v23/naming" |
Matt Rosencrantz | 94502cf | 2015-03-18 09:43:44 -0700 | [diff] [blame] | 10 | "v.io/v23/rpc" |
Jiri Simsa | 1f1302c | 2015-02-23 16:18:34 -0800 | [diff] [blame] | 11 | "v.io/v23/vdl" |
Todd Wang | ac9e190 | 2015-02-25 01:58:01 -0800 | [diff] [blame] | 12 | "v.io/v23/vdlroot/signature" |
Jiri Simsa | 1f1302c | 2015-02-23 16:18:34 -0800 | [diff] [blame] | 13 | "v.io/v23/verror" |
Matt Rosencrantz | e7bf2bc | 2015-03-13 09:54:27 -0700 | [diff] [blame] | 14 | "v.io/v23/vtrace" |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 15 | ) |
| 16 | |
| 17 | var typedNil []int |
| 18 | |
Todd Wang | 5b77a34 | 2015-04-06 18:31:37 -0700 | [diff] [blame^] | 19 | const pkgPath = "v.io/x/ref/services/wspr/internal/rpc/server" |
Mike Burrows | cb04a6b | 2014-12-18 13:58:10 -0800 | [diff] [blame] | 20 | |
| 21 | // Errors. |
| 22 | var ( |
Nicolas LaCasse | d7ab8a1 | 2015-02-03 11:46:29 -0800 | [diff] [blame] | 23 | 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 Burrows | cb04a6b | 2014-12-18 13:58:10 -0800 | [diff] [blame] | 25 | ) |
| 26 | |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 27 | // invoker holds a delegate function to call on invoke and a list of methods that |
| 28 | // are available for be called. |
| 29 | type invoker struct { |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 30 | // delegate function to call when an invoke request comes in |
| 31 | invokeFunc remoteInvokeFunc |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 32 | |
Benjamin Prosnitz | a2ac3b3 | 2014-12-12 11:40:31 -0800 | [diff] [blame] | 33 | signature []signature.Interface |
Shyam Jayaraman | eb10b9b | 2015-01-12 12:23:20 -0800 | [diff] [blame] | 34 | |
| 35 | globFunc remoteGlobFunc |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 36 | } |
| 37 | |
Matt Rosencrantz | 94502cf | 2015-03-18 09:43:44 -0700 | [diff] [blame] | 38 | var _ rpc.Invoker = (*invoker)(nil) |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 39 | |
| 40 | // newInvoker is an invoker factory |
Matt Rosencrantz | 94502cf | 2015-03-18 09:43:44 -0700 | [diff] [blame] | 41 | func newInvoker(signature []signature.Interface, invokeFunc remoteInvokeFunc, globFunc remoteGlobFunc) rpc.Invoker { |
Shyam Jayaraman | eb10b9b | 2015-01-12 12:23:20 -0800 | [diff] [blame] | 42 | i := &invoker{invokeFunc, signature, globFunc} |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 43 | return i |
| 44 | } |
| 45 | |
| 46 | // Prepare implements the Invoker interface. |
Todd Wang | 5ab0366 | 2015-02-19 21:03:01 -0800 | [diff] [blame] | 47 | func (i *invoker) Prepare(methodName string, numArgs int) ([]interface{}, []*vdl.Value, error) { |
Benjamin Prosnitz | a2ac3b3 | 2014-12-12 11:40:31 -0800 | [diff] [blame] | 48 | method, err := i.MethodSignature(nil, methodName) |
| 49 | if err != nil { |
| 50 | return nil, nil, err |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 51 | } |
Benjamin Prosnitz | a2ac3b3 | 2014-12-12 11:40:31 -0800 | [diff] [blame] | 52 | if got, want := numArgs, len(method.InArgs); got != want { |
Todd Wang | b63e9eb | 2015-02-10 19:57:39 -0800 | [diff] [blame] | 53 | return nil, nil, verror.New(ErrWrongNumberOfArgs, nil, methodName, got, want) |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 54 | } |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 55 | argptrs := make([]interface{}, len(method.InArgs)) |
Benjamin Prosnitz | a2ac3b3 | 2014-12-12 11:40:31 -0800 | [diff] [blame] | 56 | for ix, arg := range method.InArgs { |
| 57 | argptrs[ix] = vdl.ZeroValue(arg.Type) |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 58 | } |
Todd Wang | 5ab0366 | 2015-02-19 21:03:01 -0800 | [diff] [blame] | 59 | return argptrs, method.Tags, nil |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 60 | } |
| 61 | |
| 62 | // Invoke implements the Invoker interface. |
Matt Rosencrantz | 94502cf | 2015-03-18 09:43:44 -0700 | [diff] [blame] | 63 | func (i *invoker) Invoke(methodName string, call rpc.StreamServerCall, argptrs []interface{}) ([]interface{}, error) { |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 64 | replychan := i.invokeFunc(methodName, argptrs, call) |
| 65 | |
| 66 | // Wait for the result |
| 67 | reply := <-replychan |
| 68 | |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 69 | if reply.Err != nil { |
Todd Wang | f21e155 | 2015-02-18 13:21:52 -0800 | [diff] [blame] | 70 | return nil, reply.Err |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 71 | } |
| 72 | |
Matt Rosencrantz | e7bf2bc | 2015-03-13 09:54:27 -0700 | [diff] [blame] | 73 | vtrace.GetStore(call.Context()).Merge(reply.TraceResponse) |
| 74 | |
Todd Wang | 5ab0366 | 2015-02-19 21:03:01 -0800 | [diff] [blame] | 75 | // Convert the reply.Results from []*vdl.Value to []interface{} |
Todd Wang | f21e155 | 2015-02-18 13:21:52 -0800 | [diff] [blame] | 76 | results := make([]interface{}, len(reply.Results)) |
Alex Fandrianto | aa5af7c | 2015-01-29 15:20:02 -0800 | [diff] [blame] | 77 | for i, r := range reply.Results { |
Todd Wang | 5ab0366 | 2015-02-19 21:03:01 -0800 | [diff] [blame] | 78 | results[i] = r |
Alex Fandrianto | aa5af7c | 2015-01-29 15:20:02 -0800 | [diff] [blame] | 79 | } |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 80 | return results, nil |
| 81 | } |
Robin Thellend | 0215a5b | 2014-11-05 18:12:41 -0800 | [diff] [blame] | 82 | |
| 83 | // TODO(bjornick,rthellend): Find a reasonable way to implement this for JS. |
Matt Rosencrantz | 94502cf | 2015-03-18 09:43:44 -0700 | [diff] [blame] | 84 | func (i *invoker) Globber() *rpc.GlobState { |
Shyam Jayaraman | eb10b9b | 2015-01-12 12:23:20 -0800 | [diff] [blame] | 85 | if i.globFunc == nil { |
| 86 | return nil |
| 87 | } |
Matt Rosencrantz | 94502cf | 2015-03-18 09:43:44 -0700 | [diff] [blame] | 88 | return &rpc.GlobState{AllGlobber: i} |
Shyam Jayaraman | eb10b9b | 2015-01-12 12:23:20 -0800 | [diff] [blame] | 89 | } |
| 90 | |
Matt Rosencrantz | 94502cf | 2015-03-18 09:43:44 -0700 | [diff] [blame] | 91 | func (i *invoker) Glob__(call rpc.ServerCall, pattern string) (<-chan naming.GlobReply, error) { |
Matt Rosencrantz | 9dce9b2 | 2015-03-02 10:48:37 -0800 | [diff] [blame] | 92 | return i.globFunc(pattern, call) |
Robin Thellend | 0215a5b | 2014-11-05 18:12:41 -0800 | [diff] [blame] | 93 | } |
Todd Wang | 531a5e3 | 2014-11-16 22:38:49 -0800 | [diff] [blame] | 94 | |
Matt Rosencrantz | 94502cf | 2015-03-18 09:43:44 -0700 | [diff] [blame] | 95 | func (i *invoker) Signature(call rpc.ServerCall) ([]signature.Interface, error) { |
Benjamin Prosnitz | a2ac3b3 | 2014-12-12 11:40:31 -0800 | [diff] [blame] | 96 | return i.signature, nil |
Todd Wang | 531a5e3 | 2014-11-16 22:38:49 -0800 | [diff] [blame] | 97 | } |
| 98 | |
Matt Rosencrantz | 94502cf | 2015-03-18 09:43:44 -0700 | [diff] [blame] | 99 | func (i *invoker) MethodSignature(call rpc.ServerCall, method string) (signature.Method, error) { |
Benjamin Prosnitz | a2ac3b3 | 2014-12-12 11:40:31 -0800 | [diff] [blame] | 100 | if methodSig, ok := signature.FirstMethod(i.signature, method); ok { |
| 101 | return methodSig, nil |
| 102 | } |
Nicolas LaCasse | d7ab8a1 | 2015-02-03 11:46:29 -0800 | [diff] [blame] | 103 | |
| 104 | var innerContext *context.T |
Matt Rosencrantz | 9dce9b2 | 2015-03-02 10:48:37 -0800 | [diff] [blame] | 105 | if call != nil { |
| 106 | innerContext = call.Context() |
Nicolas LaCasse | d7ab8a1 | 2015-02-03 11:46:29 -0800 | [diff] [blame] | 107 | } |
| 108 | |
Todd Wang | b63e9eb | 2015-02-10 19:57:39 -0800 | [diff] [blame] | 109 | return signature.Method{}, verror.New(ErrMethodNotFoundInSignature, innerContext, method) |
Todd Wang | 531a5e3 | 2014-11-16 22:38:49 -0800 | [diff] [blame] | 110 | } |