Matt Rosencrantz | d4b9001 | 2015-06-09 12:40:58 -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 | |
| 5 | // Package xserver provides an alternate RPC server API with the goal of |
| 6 | // being simpler to use and understand. |
| 7 | package xrpc |
| 8 | |
| 9 | import ( |
| 10 | "v.io/v23" |
| 11 | "v.io/v23/context" |
| 12 | "v.io/v23/rpc" |
| 13 | "v.io/v23/security" |
| 14 | ) |
| 15 | |
Matt Rosencrantz | 4517d12 | 2015-08-28 07:00:04 -0700 | [diff] [blame] | 16 | type server struct { |
Matt Rosencrantz | d4b9001 | 2015-06-09 12:40:58 -0700 | [diff] [blame] | 17 | s rpc.Server |
| 18 | } |
| 19 | |
| 20 | // NewServer creates a new Server instance to serve a service object. |
| 21 | // |
| 22 | // The server will listen for network connections as specified by the |
| 23 | // ListenSpec attached to ctx. Depending on your RuntimeFactory, 'roaming' |
| 24 | // support may be enabled. In this mode the server will listen for |
| 25 | // changes in the network configuration using a Stream created on the |
| 26 | // supplied Publisher and change the set of Endpoints it publishes to |
| 27 | // the mount table accordingly. |
| 28 | // |
| 29 | // The server associates object with name by publishing the address of |
| 30 | // this server in the namespace under the supplied name and using |
| 31 | // authorizer to authorize access to it. RPCs invoked on the supplied |
| 32 | // name will be delivered to methods implemented by the supplied |
| 33 | // object. Reflection is used to match requests to the object's |
| 34 | // method set. As a special-case, if the object implements the |
| 35 | // Invoker interface, the Invoker is used to invoke methods directly, |
| 36 | // without reflection. If name is an empty string, no attempt will |
| 37 | // made to publish. |
Matt Rosencrantz | 4517d12 | 2015-08-28 07:00:04 -0700 | [diff] [blame] | 38 | func NewServer(ctx *context.T, name string, object interface{}, auth security.Authorizer, opts ...rpc.ServerOpt) (rpc.XServer, error) { |
Matt Rosencrantz | d4b9001 | 2015-06-09 12:40:58 -0700 | [diff] [blame] | 39 | s, err := v23.NewServer(ctx, opts...) |
| 40 | if err != nil { |
| 41 | return nil, err |
| 42 | } |
| 43 | if _, err = s.Listen(v23.GetListenSpec(ctx)); err != nil { |
Matt Rosencrantz | bb6295d | 2015-06-19 15:13:58 -0700 | [diff] [blame] | 44 | s.Stop() |
Matt Rosencrantz | d4b9001 | 2015-06-09 12:40:58 -0700 | [diff] [blame] | 45 | return nil, err |
| 46 | } |
| 47 | if err = s.Serve(name, object, auth); err != nil { |
Matt Rosencrantz | bb6295d | 2015-06-19 15:13:58 -0700 | [diff] [blame] | 48 | s.Stop() |
Matt Rosencrantz | d4b9001 | 2015-06-09 12:40:58 -0700 | [diff] [blame] | 49 | return nil, err |
| 50 | } |
Matt Rosencrantz | 4517d12 | 2015-08-28 07:00:04 -0700 | [diff] [blame] | 51 | return &server{s: s}, nil |
Matt Rosencrantz | d4b9001 | 2015-06-09 12:40:58 -0700 | [diff] [blame] | 52 | } |
| 53 | |
| 54 | // NewDispatchingServer creates a new Server instance to serve a given dispatcher. |
| 55 | // |
| 56 | // The server will listen for network connections as specified by the |
| 57 | // ListenSpec attached to ctx. Depending on your RuntimeFactory, 'roaming' |
| 58 | // support may be enabled. In this mode the server will listen for |
| 59 | // changes in the network configuration using a Stream created on the |
| 60 | // supplied Publisher and change the set of Endpoints it publishes to |
| 61 | // the mount table accordingly. |
| 62 | // |
| 63 | // The server associates dispatcher with the portion of the namespace |
| 64 | // for which name is a prefix by publishing the address of this server |
| 65 | // to the namespace under the supplied name. If name is an empty |
| 66 | // string, no attempt will made to publish. RPCs invoked on the |
| 67 | // supplied name will be delivered to the supplied Dispatcher's Lookup |
| 68 | // method which will in turn return the object and security.Authorizer |
| 69 | // used to serve the actual RPC call. If name is an empty string, no |
| 70 | // attempt will made to publish that name to a mount table. |
Matt Rosencrantz | 4517d12 | 2015-08-28 07:00:04 -0700 | [diff] [blame] | 71 | func NewDispatchingServer(ctx *context.T, name string, disp rpc.Dispatcher, opts ...rpc.ServerOpt) (rpc.XServer, error) { |
Matt Rosencrantz | d4b9001 | 2015-06-09 12:40:58 -0700 | [diff] [blame] | 72 | s, err := v23.NewServer(ctx, opts...) |
| 73 | if err != nil { |
| 74 | return nil, err |
| 75 | } |
| 76 | if _, err = s.Listen(v23.GetListenSpec(ctx)); err != nil { |
| 77 | return nil, err |
| 78 | } |
| 79 | if err = s.ServeDispatcher(name, disp); err != nil { |
| 80 | return nil, err |
| 81 | } |
Matt Rosencrantz | 4517d12 | 2015-08-28 07:00:04 -0700 | [diff] [blame] | 82 | return &server{s: s}, nil |
Matt Rosencrantz | d4b9001 | 2015-06-09 12:40:58 -0700 | [diff] [blame] | 83 | } |
| 84 | |
| 85 | // AddName adds the specified name to the mount table for this server. |
| 86 | // AddName may be called multiple times. |
Matt Rosencrantz | 4517d12 | 2015-08-28 07:00:04 -0700 | [diff] [blame] | 87 | func (s *server) AddName(name string) error { |
Matt Rosencrantz | d4b9001 | 2015-06-09 12:40:58 -0700 | [diff] [blame] | 88 | return s.s.AddName(name) |
| 89 | } |
| 90 | |
| 91 | // RemoveName removes the specified name from the mount table. |
| 92 | // RemoveName may be called multiple times. |
Matt Rosencrantz | 4517d12 | 2015-08-28 07:00:04 -0700 | [diff] [blame] | 93 | func (s *server) RemoveName(name string) { |
Matt Rosencrantz | d4b9001 | 2015-06-09 12:40:58 -0700 | [diff] [blame] | 94 | s.s.RemoveName(name) |
| 95 | } |
| 96 | |
| 97 | // Status returns the current status of the server, see ServerStatus |
| 98 | // for details. |
Matt Rosencrantz | 4517d12 | 2015-08-28 07:00:04 -0700 | [diff] [blame] | 99 | func (s *server) Status() rpc.ServerStatus { |
Matt Rosencrantz | d4b9001 | 2015-06-09 12:40:58 -0700 | [diff] [blame] | 100 | return s.s.Status() |
| 101 | } |
| 102 | |
| 103 | // WatchNetwork registers a channel over which NetworkChange's will |
| 104 | // be sent. The Server will not block sending data over this channel |
| 105 | // and hence change events may be lost if the caller doesn't ensure |
| 106 | // there is sufficient buffering in the channel. |
Matt Rosencrantz | 4517d12 | 2015-08-28 07:00:04 -0700 | [diff] [blame] | 107 | func (s *server) WatchNetwork(ch chan<- rpc.NetworkChange) { |
Matt Rosencrantz | d4b9001 | 2015-06-09 12:40:58 -0700 | [diff] [blame] | 108 | s.s.WatchNetwork(ch) |
| 109 | } |
| 110 | |
| 111 | // UnwatchNetwork unregisters a channel previously registered using |
| 112 | // WatchNetwork. |
Matt Rosencrantz | 4517d12 | 2015-08-28 07:00:04 -0700 | [diff] [blame] | 113 | func (s *server) UnwatchNetwork(ch chan<- rpc.NetworkChange) { |
Matt Rosencrantz | d4b9001 | 2015-06-09 12:40:58 -0700 | [diff] [blame] | 114 | s.s.UnwatchNetwork(ch) |
| 115 | } |
| 116 | |
| 117 | // Stop gracefully stops all services on this Server. New calls are |
| 118 | // rejected, but any in-flight calls are allowed to complete. All |
| 119 | // published mountpoints are unmounted. This call waits for this |
| 120 | // process to complete, and returns once the server has been shut down. |
Matt Rosencrantz | 4517d12 | 2015-08-28 07:00:04 -0700 | [diff] [blame] | 121 | func (s *server) Stop() error { |
Matt Rosencrantz | d4b9001 | 2015-06-09 12:40:58 -0700 | [diff] [blame] | 122 | return s.s.Stop() |
| 123 | } |