Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 1 | package rt |
| 2 | |
| 3 | import ( |
| 4 | "fmt" |
Suharsh Sivakumar | 628a8ee | 2015-01-14 11:38:56 -0800 | [diff] [blame] | 5 | "os" |
| 6 | "os/signal" |
| 7 | "path/filepath" |
| 8 | "strings" |
Suharsh Sivakumar | 628a8ee | 2015-01-14 11:38:56 -0800 | [diff] [blame] | 9 | "syscall" |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 10 | "time" |
| 11 | |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 12 | "v.io/core/veyron2" |
| 13 | "v.io/core/veyron2/context" |
Suharsh Sivakumar | 628a8ee | 2015-01-14 11:38:56 -0800 | [diff] [blame] | 14 | "v.io/core/veyron2/i18n" |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 15 | "v.io/core/veyron2/ipc" |
| 16 | "v.io/core/veyron2/ipc/stream" |
| 17 | "v.io/core/veyron2/naming" |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 18 | "v.io/core/veyron2/security" |
Suharsh Sivakumar | 628a8ee | 2015-01-14 11:38:56 -0800 | [diff] [blame] | 19 | "v.io/core/veyron2/verror2" |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 20 | "v.io/core/veyron2/vlog" |
Suharsh Sivakumar | 628a8ee | 2015-01-14 11:38:56 -0800 | [diff] [blame] | 21 | "v.io/core/veyron2/vtrace" |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 22 | |
Suharsh Sivakumar | 628a8ee | 2015-01-14 11:38:56 -0800 | [diff] [blame] | 23 | "v.io/core/veyron/lib/flags" |
| 24 | _ "v.io/core/veyron/lib/stats/sysstats" |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 25 | iipc "v.io/core/veyron/runtimes/google/ipc" |
| 26 | imanager "v.io/core/veyron/runtimes/google/ipc/stream/manager" |
| 27 | "v.io/core/veyron/runtimes/google/ipc/stream/vc" |
Matt Rosencrantz | 5dbfbef | 2015-01-26 12:40:56 -0800 | [diff] [blame] | 28 | "v.io/core/veyron/runtimes/google/lib/dependency" |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 29 | inaming "v.io/core/veyron/runtimes/google/naming" |
| 30 | "v.io/core/veyron/runtimes/google/naming/namespace" |
Suharsh Sivakumar | 628a8ee | 2015-01-14 11:38:56 -0800 | [diff] [blame] | 31 | ivtrace "v.io/core/veyron/runtimes/google/vtrace" |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 32 | ) |
| 33 | |
| 34 | type contextKey int |
| 35 | |
| 36 | const ( |
| 37 | streamManagerKey = contextKey(iota) |
| 38 | clientKey |
| 39 | namespaceKey |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 40 | principalKey |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 41 | reservedNameKey |
Suharsh Sivakumar | 033a30e | 2015-01-07 13:54:43 -0800 | [diff] [blame] | 42 | profileKey |
| 43 | appCycleKey |
| 44 | listenSpecKey |
Suharsh Sivakumar | ba56393 | 2015-01-06 15:15:50 -0800 | [diff] [blame] | 45 | protocolsKey |
Matt Rosencrantz | 3838c55 | 2015-01-15 13:04:53 -0800 | [diff] [blame] | 46 | backgroundKey |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 47 | ) |
| 48 | |
Matt Rosencrantz | fa3082c | 2015-01-22 21:39:04 -0800 | [diff] [blame] | 49 | type vtraceDependency struct{} |
| 50 | |
Matt Rosencrantz | ba470a5 | 2015-01-26 13:36:13 -0800 | [diff] [blame] | 51 | // Runtime implements the veyron2.Runtime interface. |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 52 | // Please see the interface definition for documentation of the |
| 53 | // individiual methods. |
Matt Rosencrantz | ba470a5 | 2015-01-26 13:36:13 -0800 | [diff] [blame] | 54 | type Runtime struct { |
Matt Rosencrantz | 5dbfbef | 2015-01-26 12:40:56 -0800 | [diff] [blame] | 55 | deps *dependency.Graph |
Matt Rosencrantz | aeed5d5 | 2015-01-14 15:18:34 -0800 | [diff] [blame] | 56 | } |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 57 | |
Suharsh Sivakumar | d5049b7 | 2015-01-21 14:11:35 -0800 | [diff] [blame] | 58 | type reservedNameDispatcher struct { |
| 59 | dispatcher ipc.Dispatcher |
| 60 | opts []ipc.ServerOpt |
| 61 | } |
| 62 | |
Suharsh Sivakumar | 79bec0e | 2015-01-27 18:59:36 -0800 | [diff] [blame] | 63 | // TODO(mattr,suharshs): Decide if Options would be better than this. |
Suharsh Sivakumar | d68949c | 2015-01-26 10:32:23 -0800 | [diff] [blame] | 64 | func Init(ctx *context.T, appCycle veyron2.AppCycle, protocols []string, listenSpec *ipc.ListenSpec, flags flags.RuntimeFlags, |
Matt Rosencrantz | ba470a5 | 2015-01-26 13:36:13 -0800 | [diff] [blame] | 65 | reservedDispatcher ipc.Dispatcher, dispatcherOpts ...ipc.ServerOpt) (*Runtime, *context.T, veyron2.Shutdown, error) { |
| 66 | r := &Runtime{deps: dependency.NewGraph()} |
Matt Rosencrantz | 96d952a | 2015-01-15 09:18:38 -0800 | [diff] [blame] | 67 | |
Matt Rosencrantz | 97d67a9 | 2015-01-27 21:03:12 -0800 | [diff] [blame] | 68 | err := vlog.ConfigureLibraryLoggerFromFlags() |
| 69 | if err != nil { |
| 70 | return nil, nil, nil, err |
| 71 | } |
Matt Rosencrantz | 96d952a | 2015-01-15 09:18:38 -0800 | [diff] [blame] | 72 | |
Matt Rosencrantz | fa3082c | 2015-01-22 21:39:04 -0800 | [diff] [blame] | 73 | // Setup the initial trace. |
| 74 | ctx, err = ivtrace.Init(ctx, flags.Vtrace) |
| 75 | if err != nil { |
| 76 | return nil, nil, nil, err |
| 77 | } |
| 78 | ctx, _ = vtrace.SetNewTrace(ctx) |
| 79 | r.addChild(ctx, vtraceDependency{}, func() { |
| 80 | vtrace.FormatTraces(os.Stderr, vtrace.GetStore(ctx).TraceRecords(), nil) |
| 81 | }) |
| 82 | |
Suharsh Sivakumar | d5049b7 | 2015-01-21 14:11:35 -0800 | [diff] [blame] | 83 | if reservedDispatcher != nil { |
| 84 | ctx = context.WithValue(ctx, reservedNameKey, &reservedNameDispatcher{reservedDispatcher, dispatcherOpts}) |
| 85 | } |
| 86 | |
| 87 | if appCycle != nil { |
| 88 | ctx = context.WithValue(ctx, appCycleKey, appCycle) |
| 89 | } |
| 90 | |
Matt Rosencrantz | 96d952a | 2015-01-15 09:18:38 -0800 | [diff] [blame] | 91 | if len(protocols) > 0 { |
| 92 | ctx = context.WithValue(ctx, protocolsKey, protocols) |
| 93 | } |
| 94 | |
Suharsh Sivakumar | d5049b7 | 2015-01-21 14:11:35 -0800 | [diff] [blame] | 95 | if listenSpec != nil { |
| 96 | ctx = context.WithValue(ctx, listenSpecKey, listenSpec) |
| 97 | } |
| 98 | |
Matt Rosencrantz | 96d952a | 2015-01-15 09:18:38 -0800 | [diff] [blame] | 99 | // Setup i18n. |
| 100 | ctx = i18n.ContextWithLangID(ctx, i18n.LangIDFromEnv()) |
| 101 | if len(flags.I18nCatalogue) != 0 { |
| 102 | cat := i18n.Cat() |
| 103 | for _, filename := range strings.Split(flags.I18nCatalogue, ",") { |
| 104 | err := cat.MergeFromFile(filename) |
| 105 | if err != nil { |
| 106 | fmt.Fprintf(os.Stderr, "%s: i18n: error reading i18n catalogue file %q: %s\n", os.Args[0], filename, err) |
| 107 | } |
| 108 | } |
| 109 | } |
| 110 | |
| 111 | // Setup the program name. |
| 112 | ctx = verror2.ContextWithComponentName(ctx, filepath.Base(os.Args[0])) |
| 113 | |
Matt Rosencrantz | 96d952a | 2015-01-15 09:18:38 -0800 | [diff] [blame] | 114 | // Enable signal handling. |
| 115 | r.initSignalHandling(ctx) |
| 116 | |
| 117 | // Set the initial namespace. |
| 118 | ctx, _, err = r.setNewNamespace(ctx, flags.NamespaceRoots...) |
| 119 | if err != nil { |
| 120 | return nil, nil, nil, err |
| 121 | } |
| 122 | |
| 123 | // Set the initial stream manager. |
| 124 | ctx, _, err = r.setNewStreamManager(ctx) |
| 125 | if err != nil { |
| 126 | return nil, nil, nil, err |
| 127 | } |
| 128 | |
Matt Rosencrantz | 99cc06e | 2015-01-16 10:25:11 -0800 | [diff] [blame] | 129 | // The client we create here is incomplete (has a nil principal) and only works |
Matt Rosencrantz | 96d952a | 2015-01-15 09:18:38 -0800 | [diff] [blame] | 130 | // because the agent uses anonymous unix sockets and VCSecurityNone. |
Suharsh Sivakumar | d5049b7 | 2015-01-21 14:11:35 -0800 | [diff] [blame] | 131 | // After security is initialized we attach a real client. |
Matt Rosencrantz | 99cc06e | 2015-01-16 10:25:11 -0800 | [diff] [blame] | 132 | _, client, err := r.SetNewClient(ctx) |
Matt Rosencrantz | 96d952a | 2015-01-15 09:18:38 -0800 | [diff] [blame] | 133 | if err != nil { |
| 134 | return nil, nil, nil, err |
| 135 | } |
| 136 | |
| 137 | // Initialize security. |
Matt Rosencrantz | 3199588 | 2015-01-27 20:00:48 -0800 | [diff] [blame] | 138 | principal, err := initSecurity(ctx, flags.Credentials, client) |
Matt Rosencrantz | 96d952a | 2015-01-15 09:18:38 -0800 | [diff] [blame] | 139 | if err != nil { |
| 140 | return nil, nil, nil, err |
| 141 | } |
| 142 | ctx = context.WithValue(ctx, principalKey, principal) |
| 143 | |
| 144 | // Set up secure client. |
| 145 | ctx, _, err = r.SetNewClient(ctx) |
| 146 | if err != nil { |
| 147 | return nil, nil, nil, err |
| 148 | } |
| 149 | |
Matt Rosencrantz | 3838c55 | 2015-01-15 13:04:53 -0800 | [diff] [blame] | 150 | ctx = r.SetBackgroundContext(ctx) |
| 151 | |
Matt Rosencrantz | 96d952a | 2015-01-15 09:18:38 -0800 | [diff] [blame] | 152 | // TODO(suharshs,mattr): Go through the rt.Cleanup function and make sure everything |
| 153 | // gets cleaned up. |
| 154 | |
Matt Rosencrantz | 5dbfbef | 2015-01-26 12:40:56 -0800 | [diff] [blame] | 155 | return r, ctx, r.shutdown, nil |
Matt Rosencrantz | 96d952a | 2015-01-15 09:18:38 -0800 | [diff] [blame] | 156 | } |
| 157 | |
Matt Rosencrantz | ba470a5 | 2015-01-26 13:36:13 -0800 | [diff] [blame] | 158 | func (r *Runtime) addChild(ctx *context.T, me interface{}, stop func(), dependsOn ...interface{}) error { |
Matt Rosencrantz | 5dbfbef | 2015-01-26 12:40:56 -0800 | [diff] [blame] | 159 | if err := r.deps.Depend(me, dependsOn...); err != nil { |
Matt Rosencrantz | aeed5d5 | 2015-01-14 15:18:34 -0800 | [diff] [blame] | 160 | stop() |
Matt Rosencrantz | fa3082c | 2015-01-22 21:39:04 -0800 | [diff] [blame] | 161 | return err |
Matt Rosencrantz | 5dbfbef | 2015-01-26 12:40:56 -0800 | [diff] [blame] | 162 | } else if done := ctx.Done(); done != nil { |
Matt Rosencrantz | aeed5d5 | 2015-01-14 15:18:34 -0800 | [diff] [blame] | 163 | go func() { |
| 164 | <-done |
Matt Rosencrantz | 5dbfbef | 2015-01-26 12:40:56 -0800 | [diff] [blame] | 165 | finish := r.deps.CloseAndWait(me) |
Matt Rosencrantz | aeed5d5 | 2015-01-14 15:18:34 -0800 | [diff] [blame] | 166 | stop() |
Matt Rosencrantz | 5dbfbef | 2015-01-26 12:40:56 -0800 | [diff] [blame] | 167 | finish() |
Matt Rosencrantz | aeed5d5 | 2015-01-14 15:18:34 -0800 | [diff] [blame] | 168 | }() |
| 169 | } |
| 170 | return nil |
| 171 | } |
| 172 | |
Matt Rosencrantz | 3199588 | 2015-01-27 20:00:48 -0800 | [diff] [blame] | 173 | func (r *Runtime) Init(ctx *context.T) error { |
| 174 | return r.initMgmt(ctx) |
| 175 | } |
| 176 | |
Matt Rosencrantz | ba470a5 | 2015-01-26 13:36:13 -0800 | [diff] [blame] | 177 | func (r *Runtime) shutdown() { |
Matt Rosencrantz | 5dbfbef | 2015-01-26 12:40:56 -0800 | [diff] [blame] | 178 | r.deps.CloseAndWaitForAll() |
Matt Rosencrantz | aeed5d5 | 2015-01-14 15:18:34 -0800 | [diff] [blame] | 179 | vlog.FlushLog() |
| 180 | } |
| 181 | |
Matt Rosencrantz | ba470a5 | 2015-01-26 13:36:13 -0800 | [diff] [blame] | 182 | func (r *Runtime) initSignalHandling(ctx *context.T) { |
Suharsh Sivakumar | 628a8ee | 2015-01-14 11:38:56 -0800 | [diff] [blame] | 183 | // TODO(caprita): Given that our device manager implementation is to |
| 184 | // kill all child apps when the device manager dies, we should |
| 185 | // enable SIGHUP on apps by default. |
| 186 | |
| 187 | // Automatically handle SIGHUP to prevent applications started as |
| 188 | // daemons from being killed. The developer can choose to still listen |
| 189 | // on SIGHUP and take a different action if desired. |
Matt Rosencrantz | cf714c6 | 2015-01-22 16:15:56 -0800 | [diff] [blame] | 190 | signals := make(chan os.Signal, 1) |
Suharsh Sivakumar | 628a8ee | 2015-01-14 11:38:56 -0800 | [diff] [blame] | 191 | signal.Notify(signals, syscall.SIGHUP) |
| 192 | go func() { |
| 193 | for { |
Matt Rosencrantz | aeed5d5 | 2015-01-14 15:18:34 -0800 | [diff] [blame] | 194 | sig, ok := <-signals |
| 195 | if !ok { |
| 196 | break |
| 197 | } |
| 198 | vlog.Infof("Received signal %v", sig) |
Suharsh Sivakumar | 628a8ee | 2015-01-14 11:38:56 -0800 | [diff] [blame] | 199 | } |
| 200 | }() |
Matt Rosencrantz | fa3082c | 2015-01-22 21:39:04 -0800 | [diff] [blame] | 201 | r.addChild(ctx, signals, func() { |
Matt Rosencrantz | aeed5d5 | 2015-01-14 15:18:34 -0800 | [diff] [blame] | 202 | signal.Stop(signals) |
| 203 | close(signals) |
| 204 | }) |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 205 | } |
| 206 | |
Matt Rosencrantz | ba470a5 | 2015-01-26 13:36:13 -0800 | [diff] [blame] | 207 | func (*Runtime) NewEndpoint(ep string) (naming.Endpoint, error) { |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 208 | return inaming.NewEndpoint(ep) |
| 209 | } |
| 210 | |
Matt Rosencrantz | ba470a5 | 2015-01-26 13:36:13 -0800 | [diff] [blame] | 211 | func (r *Runtime) NewServer(ctx *context.T, opts ...ipc.ServerOpt) (ipc.Server, error) { |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 212 | // Create a new RoutingID (and StreamManager) for each server. |
Suharsh Sivakumar | d5049b7 | 2015-01-21 14:11:35 -0800 | [diff] [blame] | 213 | sm, err := newStreamManager() |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 214 | if err != nil { |
| 215 | return nil, fmt.Errorf("failed to create ipc/stream/Manager: %v", err) |
| 216 | } |
| 217 | |
| 218 | ns, _ := ctx.Value(namespaceKey).(naming.Namespace) |
| 219 | principal, _ := ctx.Value(principalKey).(security.Principal) |
Matt Rosencrantz | fa3082c | 2015-01-22 21:39:04 -0800 | [diff] [blame] | 220 | client, _ := ctx.Value(clientKey).(ipc.Client) |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 221 | |
| 222 | otherOpts := append([]ipc.ServerOpt{}, opts...) |
| 223 | otherOpts = append(otherOpts, vc.LocalPrincipal{principal}) |
| 224 | if reserved, ok := ctx.Value(reservedNameKey).(*reservedNameDispatcher); ok { |
Suharsh Sivakumar | d7a6519 | 2015-01-27 22:57:15 -0800 | [diff] [blame] | 225 | otherOpts = append(otherOpts, iipc.ReservedNameDispatcher{reserved.dispatcher}) |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 226 | otherOpts = append(otherOpts, reserved.opts...) |
| 227 | } |
Matt Rosencrantz | 9db8bc3 | 2015-01-13 09:01:55 -0800 | [diff] [blame] | 228 | if protocols, ok := ctx.Value(protocolsKey).([]string); ok { |
| 229 | otherOpts = append(otherOpts, iipc.PreferredServerResolveProtocols(protocols)) |
| 230 | } |
Suharsh Sivakumar | af99c97 | 2015-01-28 15:28:49 -0800 | [diff] [blame^] | 231 | server, err := iipc.InternalNewServer(ctx, sm, ns, r.GetClient(ctx), otherOpts...) |
Matt Rosencrantz | aeed5d5 | 2015-01-14 15:18:34 -0800 | [diff] [blame] | 232 | if err != nil { |
| 233 | return nil, err |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 234 | } |
Matt Rosencrantz | aeed5d5 | 2015-01-14 15:18:34 -0800 | [diff] [blame] | 235 | stop := func() { |
| 236 | if err := server.Stop(); err != nil { |
| 237 | vlog.Errorf("A server could not be stopped: %v", err) |
| 238 | } |
Suharsh Sivakumar | d5049b7 | 2015-01-21 14:11:35 -0800 | [diff] [blame] | 239 | sm.Shutdown() |
Matt Rosencrantz | aeed5d5 | 2015-01-14 15:18:34 -0800 | [diff] [blame] | 240 | } |
Matt Rosencrantz | fa3082c | 2015-01-22 21:39:04 -0800 | [diff] [blame] | 241 | if err = r.addChild(ctx, server, stop, client, vtraceDependency{}); err != nil { |
Matt Rosencrantz | aeed5d5 | 2015-01-14 15:18:34 -0800 | [diff] [blame] | 242 | return nil, err |
| 243 | } |
| 244 | return server, nil |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 245 | } |
| 246 | |
Suharsh Sivakumar | d5049b7 | 2015-01-21 14:11:35 -0800 | [diff] [blame] | 247 | func newStreamManager(opts ...stream.ManagerOpt) (stream.Manager, error) { |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 248 | rid, err := naming.NewRoutingID() |
| 249 | if err != nil { |
Suharsh Sivakumar | d5049b7 | 2015-01-21 14:11:35 -0800 | [diff] [blame] | 250 | return nil, err |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 251 | } |
| 252 | sm := imanager.InternalNew(rid) |
Suharsh Sivakumar | d5049b7 | 2015-01-21 14:11:35 -0800 | [diff] [blame] | 253 | return sm, nil |
| 254 | } |
| 255 | |
Matt Rosencrantz | ba470a5 | 2015-01-26 13:36:13 -0800 | [diff] [blame] | 256 | func (r *Runtime) setNewStreamManager(ctx *context.T, opts ...stream.ManagerOpt) (*context.T, stream.Manager, error) { |
Suharsh Sivakumar | d5049b7 | 2015-01-21 14:11:35 -0800 | [diff] [blame] | 257 | sm, err := newStreamManager(opts...) |
Matt Rosencrantz | aeed5d5 | 2015-01-14 15:18:34 -0800 | [diff] [blame] | 258 | newctx := context.WithValue(ctx, streamManagerKey, sm) |
Matt Rosencrantz | fa3082c | 2015-01-22 21:39:04 -0800 | [diff] [blame] | 259 | if err = r.addChild(ctx, sm, sm.Shutdown); err != nil { |
Matt Rosencrantz | aeed5d5 | 2015-01-14 15:18:34 -0800 | [diff] [blame] | 260 | return ctx, nil, err |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 261 | } |
Suharsh Sivakumar | d5049b7 | 2015-01-21 14:11:35 -0800 | [diff] [blame] | 262 | return newctx, sm, err |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 263 | } |
| 264 | |
Matt Rosencrantz | ba470a5 | 2015-01-26 13:36:13 -0800 | [diff] [blame] | 265 | func (r *Runtime) SetNewStreamManager(ctx *context.T, opts ...stream.ManagerOpt) (*context.T, stream.Manager, error) { |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 266 | newctx, sm, err := r.setNewStreamManager(ctx, opts...) |
| 267 | if err != nil { |
| 268 | return ctx, nil, err |
| 269 | } |
| 270 | |
| 271 | // Create a new client since it depends on the stream manager. |
| 272 | newctx, _, err = r.SetNewClient(newctx) |
| 273 | if err != nil { |
| 274 | return ctx, nil, err |
| 275 | } |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 276 | return newctx, sm, nil |
| 277 | } |
| 278 | |
Matt Rosencrantz | ba470a5 | 2015-01-26 13:36:13 -0800 | [diff] [blame] | 279 | func (*Runtime) GetStreamManager(ctx *context.T) stream.Manager { |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 280 | cl, _ := ctx.Value(streamManagerKey).(stream.Manager) |
| 281 | return cl |
| 282 | } |
| 283 | |
Matt Rosencrantz | ba470a5 | 2015-01-26 13:36:13 -0800 | [diff] [blame] | 284 | func (r *Runtime) SetPrincipal(ctx *context.T, principal security.Principal) (*context.T, error) { |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 285 | var err error |
| 286 | newctx := ctx |
| 287 | |
| 288 | newctx = context.WithValue(newctx, principalKey, principal) |
| 289 | |
| 290 | // TODO(mattr, suharshs): The stream manager holds a cache of vifs |
| 291 | // which were negotiated with the principal, so we replace it here when the |
| 292 | // principal changes. However we should negotiate the vif with a |
| 293 | // random principal and then we needn't replace this here. |
| 294 | if newctx, _, err = r.setNewStreamManager(newctx); err != nil { |
| 295 | return ctx, err |
| 296 | } |
Suharsh Sivakumar | 033a30e | 2015-01-07 13:54:43 -0800 | [diff] [blame] | 297 | if newctx, _, err = r.setNewNamespace(newctx, r.GetNamespace(ctx).Roots()...); err != nil { |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 298 | return ctx, err |
| 299 | } |
| 300 | if newctx, _, err = r.SetNewClient(newctx); err != nil { |
| 301 | return ctx, err |
| 302 | } |
| 303 | |
| 304 | return newctx, nil |
| 305 | } |
| 306 | |
Matt Rosencrantz | ba470a5 | 2015-01-26 13:36:13 -0800 | [diff] [blame] | 307 | func (*Runtime) GetPrincipal(ctx *context.T) security.Principal { |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 308 | p, _ := ctx.Value(principalKey).(security.Principal) |
| 309 | return p |
| 310 | } |
| 311 | |
Matt Rosencrantz | ba470a5 | 2015-01-26 13:36:13 -0800 | [diff] [blame] | 312 | func (r *Runtime) SetNewClient(ctx *context.T, opts ...ipc.ClientOpt) (*context.T, ipc.Client, error) { |
Matt Rosencrantz | 9db8bc3 | 2015-01-13 09:01:55 -0800 | [diff] [blame] | 313 | otherOpts := append([]ipc.ClientOpt{}, opts...) |
| 314 | |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 315 | // TODO(mattr, suharshs): Currently there are a lot of things that can come in as opts. |
| 316 | // Some of them will be removed as opts and simply be pulled from the context instead |
| 317 | // these are: |
Matt Rosencrantz | 9db8bc3 | 2015-01-13 09:01:55 -0800 | [diff] [blame] | 318 | // stream.Manager, Namespace, LocalPrincipal, preferred protocols. |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 319 | sm, _ := ctx.Value(streamManagerKey).(stream.Manager) |
| 320 | ns, _ := ctx.Value(namespaceKey).(naming.Namespace) |
| 321 | p, _ := ctx.Value(principalKey).(security.Principal) |
Matt Rosencrantz | 9db8bc3 | 2015-01-13 09:01:55 -0800 | [diff] [blame] | 322 | otherOpts = append(otherOpts, vc.LocalPrincipal{p}, &imanager.DialTimeout{5 * time.Minute}) |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 323 | |
Matt Rosencrantz | 9db8bc3 | 2015-01-13 09:01:55 -0800 | [diff] [blame] | 324 | if protocols, ok := ctx.Value(protocolsKey).([]string); ok { |
Suharsh Sivakumar | d7a6519 | 2015-01-27 22:57:15 -0800 | [diff] [blame] | 325 | otherOpts = append(otherOpts, iipc.PreferredProtocols(protocols)) |
Matt Rosencrantz | 9db8bc3 | 2015-01-13 09:01:55 -0800 | [diff] [blame] | 326 | } |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 327 | |
| 328 | client, err := iipc.InternalNewClient(sm, ns, otherOpts...) |
Matt Rosencrantz | aeed5d5 | 2015-01-14 15:18:34 -0800 | [diff] [blame] | 329 | if err != nil { |
| 330 | return ctx, nil, err |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 331 | } |
Matt Rosencrantz | 1932912 | 2015-01-23 22:18:49 -0800 | [diff] [blame] | 332 | newctx := context.WithValue(ctx, clientKey, client) |
Matt Rosencrantz | fa3082c | 2015-01-22 21:39:04 -0800 | [diff] [blame] | 333 | if err = r.addChild(ctx, client, client.Close, sm, vtraceDependency{}); err != nil { |
Matt Rosencrantz | aeed5d5 | 2015-01-14 15:18:34 -0800 | [diff] [blame] | 334 | return ctx, nil, err |
| 335 | } |
| 336 | return newctx, client, err |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 337 | } |
| 338 | |
Matt Rosencrantz | ba470a5 | 2015-01-26 13:36:13 -0800 | [diff] [blame] | 339 | func (*Runtime) GetClient(ctx *context.T) ipc.Client { |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 340 | cl, _ := ctx.Value(clientKey).(ipc.Client) |
| 341 | return cl |
| 342 | } |
| 343 | |
Matt Rosencrantz | ba470a5 | 2015-01-26 13:36:13 -0800 | [diff] [blame] | 344 | func (*Runtime) setNewNamespace(ctx *context.T, roots ...string) (*context.T, naming.Namespace, error) { |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 345 | ns, err := namespace.New(roots...) |
Matt Rosencrantz | fa3082c | 2015-01-22 21:39:04 -0800 | [diff] [blame] | 346 | // TODO(mattr): Copy cache settings. |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 347 | if err == nil { |
| 348 | ctx = context.WithValue(ctx, namespaceKey, ns) |
| 349 | } |
| 350 | return ctx, ns, err |
| 351 | } |
| 352 | |
Matt Rosencrantz | ba470a5 | 2015-01-26 13:36:13 -0800 | [diff] [blame] | 353 | func (r *Runtime) SetNewNamespace(ctx *context.T, roots ...string) (*context.T, naming.Namespace, error) { |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 354 | newctx, ns, err := r.setNewNamespace(ctx, roots...) |
| 355 | if err != nil { |
| 356 | return ctx, nil, err |
| 357 | } |
| 358 | |
| 359 | // Replace the client since it depends on the namespace. |
| 360 | newctx, _, err = r.SetNewClient(newctx) |
| 361 | if err != nil { |
| 362 | return ctx, nil, err |
| 363 | } |
| 364 | |
| 365 | return newctx, ns, err |
| 366 | } |
| 367 | |
Matt Rosencrantz | ba470a5 | 2015-01-26 13:36:13 -0800 | [diff] [blame] | 368 | func (*Runtime) GetNamespace(ctx *context.T) naming.Namespace { |
Matt Rosencrantz | 5845bf1 | 2015-01-06 13:05:21 -0800 | [diff] [blame] | 369 | ns, _ := ctx.Value(namespaceKey).(naming.Namespace) |
| 370 | return ns |
| 371 | } |
| 372 | |
Matt Rosencrantz | ba470a5 | 2015-01-26 13:36:13 -0800 | [diff] [blame] | 373 | func (*Runtime) GetAppCycle(ctx *context.T) veyron2.AppCycle { |
Suharsh Sivakumar | 033a30e | 2015-01-07 13:54:43 -0800 | [diff] [blame] | 374 | appCycle, _ := ctx.Value(appCycleKey).(veyron2.AppCycle) |
| 375 | return appCycle |
| 376 | } |
| 377 | |
Matt Rosencrantz | ba470a5 | 2015-01-26 13:36:13 -0800 | [diff] [blame] | 378 | func (*Runtime) GetListenSpec(ctx *context.T) ipc.ListenSpec { |
Suharsh Sivakumar | d5049b7 | 2015-01-21 14:11:35 -0800 | [diff] [blame] | 379 | listenSpec, _ := ctx.Value(listenSpecKey).(*ipc.ListenSpec) |
| 380 | return *listenSpec |
Suharsh Sivakumar | ac9feed | 2015-01-08 10:58:37 -0800 | [diff] [blame] | 381 | } |
Matt Rosencrantz | 3838c55 | 2015-01-15 13:04:53 -0800 | [diff] [blame] | 382 | |
Matt Rosencrantz | ba470a5 | 2015-01-26 13:36:13 -0800 | [diff] [blame] | 383 | func (*Runtime) SetBackgroundContext(ctx *context.T) *context.T { |
Matt Rosencrantz | 3838c55 | 2015-01-15 13:04:53 -0800 | [diff] [blame] | 384 | // Note we add an extra context with a nil value here. |
| 385 | // This prevents users from travelling back through the |
| 386 | // chain of background contexts. |
| 387 | ctx = context.WithValue(ctx, backgroundKey, nil) |
| 388 | return context.WithValue(ctx, backgroundKey, ctx) |
| 389 | } |
| 390 | |
Matt Rosencrantz | ba470a5 | 2015-01-26 13:36:13 -0800 | [diff] [blame] | 391 | func (*Runtime) GetBackgroundContext(ctx *context.T) *context.T { |
Matt Rosencrantz | 3838c55 | 2015-01-15 13:04:53 -0800 | [diff] [blame] | 392 | bctx, _ := ctx.Value(backgroundKey).(*context.T) |
| 393 | if bctx == nil { |
| 394 | // There should always be a background context. If we don't find |
| 395 | // it, that means that the user passed us the background context |
| 396 | // in hopes of following the chain. Instead we just give them |
| 397 | // back what they sent in, which is correct. |
| 398 | return ctx |
| 399 | } |
| 400 | return bctx |
| 401 | } |