func doStartCall(context *context.T, name, method string, skipServerAuth bool, client rpc.Client, args []interface{}) (rpc.ClientCall, error) { var opts []rpc.CallOpt if skipServerAuth { opts = append(opts, options.NameResolutionAuthorizer{security.AllowEveryone()}, options.ServerAuthorizer{security.AllowEveryone()}) } // Invoke StartCall call, err := client.StartCall(context, name, method, args, opts...) if err != nil { return nil, err } return call, nil }
func NewV23Manager( chatty bool, rootName string, isGameMaster bool, namespaceRoot string) *V23Manager { return &V23Manager{ chatty, nil, // ctx nil, // shutdown false, // isRunning isGameMaster, // isGameMaster model.Closed, // left door model.Closed, // right door rootName, namespaceRoot, options.ServerAuthorizer{security.AllowEveryone()}, nil, // relay nil, // myself []*vPlayer{}, nil, // initialPlayerNumbers nil, // chBallCommands make(chan chan bool), // chStop make(chan chan bool), // chNoNewBallsOrPeople make(chan model.DoorCommand), new(sync.RWMutex), false, } }
func runClaim(ctx *context.T, env *cmdline.Env, args []string) error { if numargs := len(args); numargs != 2 { return fmt.Errorf("requires exactly two arguments <lock>, <name>, provided %d", numargs) } lockName, name := args[0], args[1] ctx, stop, err := withLocalNamespace(ctx, "", lockUserNhName(ctx)) if err != nil { return err } defer stop() ctx, cancel := context.WithTimeout(ctx, time.Minute) defer cancel() // TODO(ataly): We should not skip server endpoint authorization while // claiming locks but instead fetch the blessing root of the lock manufacturer // from an authoritative source and then appropriately authenticate the server. b, err := lock.UnclaimedLockClient(lockObjName(lockName)).Claim( ctx, name, options.ServerAuthorizer{security.AllowEveryone()}) if err != nil { return err } p := v23.GetPrincipal(ctx) if err := security.AddToRoots(p, b); err != nil { return fmt.Errorf("failed to add (key) blessing (%v) to roots: %v", b, err) } if _, err := p.BlessingStore().Set(b, security.BlessingPattern(name)); err != nil { return fmt.Errorf("failed to set (key) blessing (%v) for peer %v: %v", b, name, err) } fmt.Printf("Claimed lock: %v as %v and received key: %v\n", lockName, name, b) return nil }
// sendOneInvite sends invitations to all the addresses in addrs and returns the one that accepted it. // All addrs are assumed to be equivalent and thus at most one Invite RPC will succeed. // // TODO: This is aiming to replicate what the RPC stack does for all the // addresses a single name resolved to. Should all these addresses discovered // somehow be encapsulated in a single object name? func sendOneInvite(ctx *context.T, addrs []string) string { // Give at most 1 second for these connections to be made, if they // can't be made then consider the peer bad and ignore it. // TODO: Should these RPCs also use the "connection timeout" that might be implemented // as per proposal: https://docs.google.com/a/google.com/document/d/1prtxGhSR5TaL0lc_iDRC0Q6H1Drbg2T0x7MWVb_ZCSM/edit?usp=sharing ctx, cancel := context.WithTimeout(ctx, maxInvitationWaitTime) defer cancel() ch := make(chan string) for _, addr := range addrs { go func(addr string) { err := spec.ScreenClient(addr).Invite(ctx, options.ServerAuthorizer{security.AllowEveryone()}) ctx.Infof("Invitation to %v sent, error: %v", addr, err) if err == nil { ch <- addr return } ch <- "" }(addr) } for i := range addrs { if ret := <-ch; len(ret) > 0 { // Drain the rest and return go func() { i++ for i < len(addrs) { <-ch } }() return ret } } return "" }
//export Java_io_v_v23_security_VSecurity_nativeCreateAuthorizer func Java_io_v_v23_security_VSecurity_nativeCreateAuthorizer(jenv *C.JNIEnv, jVSecurityClass C.jclass, kind C.jint, jKey C.jobject) C.jobject { env := jutil.Env(uintptr(unsafe.Pointer(jenv))) var auth security.Authorizer switch kind { case 0: auth = security.AllowEveryone() case 1: auth = security.EndpointAuthorizer() case 2: auth = security.DefaultAuthorizer() case 3: key, err := GoPublicKey(env, jutil.Object(uintptr(unsafe.Pointer(jKey)))) if err != nil { jutil.JThrowV(env, err) return nil } auth = security.PublicKeyAuthorizer(key) default: return nil } ref := jutil.GoNewRef(&auth) // Un-refed when the Java PermissionsAuthorizer is finalized jAuthorizer, err := jutil.NewObject(env, jutil.Class(uintptr(unsafe.Pointer(jPermissionsAuthorizerClass))), []jutil.Sign{jutil.LongSign}, int64(ref)) if err != nil { jutil.GoDecRef(ref) jutil.JThrowV(env, err) return nil } return C.jobject(unsafe.Pointer(jAuthorizer)) }
func goNamespaceOptions(env jutil.Env, jOptions jutil.Object) ([]naming.NamespaceOpt, error) { var opts []naming.NamespaceOpt r, err := jutil.GetBooleanOption(env, jOptions, "io.v.v23.naming.REPLACE_MOUNT") if err != nil { return nil, err } opts = append(opts, naming.ReplaceMount(r)) s, err := jutil.GetBooleanOption(env, jOptions, "io.v.v23.naming.SERVES_MOUNT_TABLE") if err != nil { return nil, err } opts = append(opts, naming.ServesMountTable(s)) l, err := jutil.GetBooleanOption(env, jOptions, "io.v.v23.naming.IS_LEAF") if err != nil { return nil, err } opts = append(opts, naming.IsLeaf(l)) e, err := jutil.GetBooleanOption(env, jOptions, "io.v.v23.SKIP_SERVER_ENDPOINT_AUTHORIZATION") if err != nil { return nil, err } if e { opts = append(opts, options.NameResolutionAuthorizer{security.AllowEveryone()}) } return opts, nil }
func (v23pd *dispatcher) Lookup(ctx *context.T, suffix string) (interface{}, security.Authorizer, error) { ctx.Infof("dispatcher.Lookup for suffix: %s", suffix) return fakeService{ appctx: v23pd.appctx, suffix: suffix, ids: bindings.NewCounter(), }, security.AllowEveryone(), nil }
func serve(ctx *context.T, env *cmdline.Env, args []string) error { name := "" if len(args) > 0 { name = args[0] fmt.Printf("mounting under: %s\n", name) } _, server, err := v23.WithNewServer(ctx, name, defaultMediaServer(), security.AllowEveryone()) if err != nil { return err } fmt.Printf("Listening at: %s", server.Status().Endpoints[0].Name()) <-signals.ShutdownOnSignals(ctx) return nil }
func channel2rpc(ctx *context.T, src <-chan *spec.Triangle, dst string, errch chan<- error, myScreen chan<- *spec.Triangle) { for t := range src { // This is an "interactive" game, if an RPC doesn't succeed in say ctxTimeout, cancel := context.WithTimeout(ctx, maxTriangleGiveTime) if err := spec.ScreenClient(dst).Give(ctxTimeout, *t, options.ServerAuthorizer{security.AllowEveryone()}); err != nil { cancel() returnTriangle(t, myScreen) ctx.Infof("%q.Give failed: %v, aborting connection with remote screen", dst, err) errch <- err break } cancel() } for t := range src { returnTriangle(t, myScreen) } ctx.VI(1).Infof("Exiting goroutine with connection to %q", dst) }
func runRecvKey(ctx *context.T, env *cmdline.Env, args []string) error { ctx, stop, err := withLocalNamespace(ctx, "", lockUserNhName(ctx)) if err != nil { return err } defer stop() service := &recvKeyService{ env: env, notify: make(chan error), } ctx, cancel := context.WithCancel(ctx) _, server, err := v23.WithNewServer(ctx, recvKeySuffix, service, security.AllowEveryone()) if err != nil { return fmt.Errorf("failed to create server to receive keys: %v", err) } defer func() { cancel() <-server.Closed() }() fmt.Println("Waiting for keys") return <-service.notify }
func (s *messageReceiver) call(name, method string, value []byte, inParamsType mojom_types.MojomStruct, outParamsType *mojom_types.MojomStruct) ([]byte, error) { s.ctx.Infof("server: %s.%s: %#v", name, method, inParamsType) inVType, err := transcoder.MojomStructToVDLType(inParamsType, s.header.desc) if err != nil { return nil, err } // Decode the vom.RawBytes from the mojom bytes and mojom type. target := util.StructSplitTarget() if err := transcoder.FromMojo(target, value, inVType); err != nil { return nil, fmt.Errorf("transcoder.FromMojo failed: %v", err) } // inVdlValue is a struct, but we need to send []interface. inargs := target.Fields() inargsIfc := make([]interface{}, len(inargs)) for i := range inargs { inargsIfc[i] = inargs[i] } // We know that the v23serverproxy will give us back a bunch of // data in []interface{}. so we'll want to decode them into *vom.RawBytes. s.ctx.Infof("%s %v", method, outParamsType) var numParams int if outParamsType != nil { numParams = len(outParamsType.Fields) } outargs := make([]*vom.RawBytes, numParams) outptrs := make([]interface{}, len(outargs)) for i := range outargs { outptrs[i] = &outargs[i] } // Now, run the call without any authorization. if err := v23.GetClient(s.ctx).Call(s.ctx, name, method, inargsIfc, outptrs, options.ServerAuthorizer{security.AllowEveryone()}); err != nil { return nil, err } if outParamsType == nil { return nil, nil } outVType, err := transcoder.MojomStructToVDLType(*outParamsType, s.header.desc) if err != nil { return nil, err } toMojoTarget := transcoder.ToMojomTarget() if err := util.JoinRawBytesAsStruct(toMojoTarget, outVType, outargs); err != nil { return nil, err } return toMojoTarget.Bytes(), nil }
func btAndDiscoveryFunc(ctx *context.T, w io.Writer) error { bothf := func(ctx *context.T, w io.Writer, format string, args ...interface{}) { fmt.Fprintf(w, format, args...) ctx.Infof(format, args...) } defer bothf(ctx, w, "finishing!") dis, err := v23.NewDiscovery(ctx) if err != nil { bothf(ctx, w, "Can't create discovery %v", err) return err } ctx = v23.WithListenSpec(ctx, rpc.ListenSpec{Addrs: rpc.ListenAddrs{{Protocol: "bt", Address: "/0"}}}) _, server, err := v23.WithNewServer(ctx, "", &echoServer{}, security.AllowEveryone()) if err != nil { bothf(ctx, w, "Can't create server %v", err) return err } ctx.Infof("Server listening on %v", server.Status().Endpoints) ctx.Infof("Server listen errors: %v", server.Status().ListenErrors) interfaces := []string{ "v.io/x/jni/impl/google/services/vango/Echo", "v.io/x/jni/impl/google/services/vango/Echo2", "v.io/x/jni/impl/google/services/vango/Echo3", "v.io/x/jni/impl/google/services/vango/Echo4", } type adstate struct { ad *discovery.Advertisement stop func() } ads := []adstate{} for _, name := range interfaces { ad := &discovery.Advertisement{ InterfaceName: name, Attributes: discovery.Attributes{ "one": "A value of some kind", "two": "Yet another value", "three": "More and more", "four": "This is insane", }, } nctx, ncancel := context.WithCancel(ctx) ch, err := libdiscovery.AdvertiseServer(nctx, dis, server, "", ad, nil) if err != nil { bothf(nctx, w, "Can't advertise server %v", err) return err } stop := func() { ncancel() <-ch } ads = append(ads, adstate{ad, stop}) } type updateState struct { ch <-chan discovery.Update stop func() } var updates []updateState for _, name := range interfaces { nctx, ncancel := context.WithCancel(ctx) u, err := dis.Scan(nctx, `v.InterfaceName="`+name+`"`) if err != nil { bothf(nctx, w, "Can't scan %v", err) return err } stop := func() { ncancel() } updates = append(updates, updateState{u, stop}) } for _, u := range updates[1:] { go func(up updateState) { for _ = range up.ch { } }(u) } makeopt := func(ad discovery.Advertisement) options.Preresolved { me := &naming.MountEntry{ IsLeaf: true, } for _, a := range ad.Addresses { addr, _ := naming.SplitAddressName(a) me.Servers = append(me.Servers, naming.MountedServer{ Server: addr, }) } return options.Preresolved{Resolution: me} } alive := map[discovery.AdId]options.Preresolved{} ticker := time.NewTicker(time.Second) for { select { case <-ticker.C: if len(alive) == 0 { bothf(ctx, w, "No live connections to dial.") } for _, opt := range alive { dialtime := options.ConnectionTimeout(5 * time.Second) channeltime := options.ChannelTimeout(2 * time.Second) data := make([]byte, 1024) summary, err := runTimedCall(ctx, "A timed call.", string(data), opt, dialtime, channeltime) if err != nil { bothf(ctx, w, "failed call %s, %v, %v", summary, err, opt.Resolution.Servers) } else { bothf(ctx, w, "succeeded call: %s, %v", summary, opt.Resolution.Servers) } } case u := <-updates[0].ch: if u.IsLost() { bothf(ctx, w, "lost %v", u.Addresses()) delete(alive, u.Id()) } else { bothf(ctx, w, "found %v", u.Addresses()) alive[u.Id()] = makeopt(u.Advertisement()) } } } }
// AllFunc runs a server, advertises it, scans for other servers and makes an // Echo RPC to every advertised remote server. func AllFunc(ctx *context.T, output io.Writer) error { ls := rpc.ListenSpec{Proxy: "proxy"} addRegisteredProto(&ls, "tcp", ":0") addRegisteredProto(&ls, "bt", "/0") fmt.Fprintf(output, "Listening on: %+v (and proxy)\n", ls.Addrs) ctx, server, err := v23.WithNewServer( v23.WithListenSpec(ctx, ls), mountName(ctx, "all"), &echoServer{}, security.AllowEveryone()) if err != nil { return err } ad := &discovery.Advertisement{ InterfaceName: interfaceName, Attributes: discovery.Attributes{ "Hello": "There", }, } d, err := v23.NewDiscovery(ctx) if err != nil { return err } stoppedAd, err := libdiscovery.AdvertiseServer(ctx, d, server, "", ad, nil) if err != nil { return err } updates, err := d.Scan(ctx, "v.InterfaceName=\""+interfaceName+"\"") if err != nil { return err } var ( status = server.Status() counter = 0 peerByAdId = make(map[discovery.AdId]*peer) lastCall = make(map[discovery.AdId]time.Time) callResults = make(chan string) activeCalls = 0 quit = false myaddrs = serverAddrs(status) ticker = time.NewTicker(time.Second) call = func(p *peer) { counter++ activeCalls++ lastCall[p.adId] = time.Now() go func(msg string) { summary, err := p.call(ctx, msg) if err != nil { ctx.Infof("Failed to call [%v]: %v", p.description, err) callResults <- "" return } callResults <- summary }(fmt.Sprintf("Hello #%d", counter)) } statRequest = make(chan chan<- string) ) defer ticker.Stop() stats.NewStringFunc(vangoStat, func() string { r := make(chan string) statRequest <- r return <-r }) defer stats.Delete(vangoStat) fmt.Fprintln(output, "My AdID:", ad.Id) fmt.Fprintln(output, "My addrs:", myaddrs) ctx.Infof("SERVER STATUS: %+v", status) for !quit { select { case <-ctx.Done(): quit = true case <-status.Dirty: status = server.Status() newaddrs := serverAddrs(status) changed := len(newaddrs) != len(myaddrs) if !changed { for i := range newaddrs { if newaddrs[i] != myaddrs[i] { changed = true break } } } if changed { myaddrs = newaddrs fmt.Fprintln(output, "My addrs:", myaddrs) } ctx.Infof("SERVER STATUS: %+v", status) case u, scanning := <-updates: if !scanning { fmt.Fprintln(output, "SCANNING STOPPED") quit = true break } if u.IsLost() { if p, ok := peerByAdId[u.Id()]; ok { fmt.Fprintln(output, "LOST:", p.description) } delete(peerByAdId, u.Id()) delete(lastCall, u.Id()) break } p, err := newPeer(ctx, u) if err != nil { ctx.Info(err) break } peerByAdId[p.adId] = p fmt.Fprintln(output, "FOUND:", p.description) call(p) case r := <-callResults: activeCalls-- if len(r) > 0 { fmt.Fprintln(output, r) } case <-stoppedAd: fmt.Fprintln(output, "STOPPED ADVERTISING") stoppedAd = nil case <-ticker.C: // Call all peers that haven't been called in a while now := time.Now() for id, t := range lastCall { if now.Sub(t) > rpcTimeout { call(peerByAdId[id]) } } case s := <-statRequest: idx := 1 ret := new(bytes.Buffer) fmt.Fprintln(ret, "ACTIVE CALLS:", activeCalls) fmt.Fprintln(ret, "PEERS") for id, p := range peerByAdId { fmt.Fprintf(ret, "%2d) %s -- %v\n", idx, p.description, lastCall[id]) } s <- ret.String() } } fmt.Println(output, "EXITING: Cleaning up") for activeCalls > 0 { <-callResults activeCalls-- } // Exhaust the scanned updates queue. // (The channel will be closed as a by-product of the context being Done). for range updates { } fmt.Fprintln(output, "EXITING: Done") return nil }
func (nm *networkManager) run(ready chan<- interface{}, newLeftScreen, newRightScreen chan<- chan<- *spec.Triangle, newInvite chan<- Invitation) { defer close(nm.myScreen) defer close(newLeftScreen) defer close(newRightScreen) notifyReady := func(result interface{}) { ready <- result close(ready) ready = nil } ctx, shutdown := v23.Init() defer shutdown() ctx, server, err := v23.WithNewServer(ctx, "", spec.ScreenServer(nm), security.AllowEveryone()) if err != nil { notifyReady(err) return } disc, err := v23.NewDiscovery(ctx) if err != nil { notifyReady(err) return } // Select a color based on some unique identifier of the process, the PublicKey serves as one. notifyReady(selectColor(v23.GetPrincipal(ctx).PublicKey())) var ( left = remoteScreen{myScreen: nm.myScreen, notify: newLeftScreen} right = remoteScreen{myScreen: nm.myScreen, notify: newRightScreen} accepted = make(chan string) // Names of remote screens that accepted an invitation seek = make(chan bool) // Send false to stop seeking invitations from others, true otherwise pendingInviterName string pendingInviteUserResponse <-chan error pendingInviteRPCResponse chan<- error ) seekInvites(ctx, disc, server, seek) go sendInvites(ctx, disc, accepted) for { select { case invitation := <-nm.inviteRPCs: if left.Active() { invitation.Response <- fmt.Errorf("thanks for the invite but I'm already engaged with a previous invitation") break } // Defer the response to the user interface. ch := make(chan error) pendingInviterName = invitation.Name pendingInviteRPCResponse = invitation.Response pendingInviteUserResponse = ch invitation.Response = ch newInvite <- invitation case err := <-pendingInviteUserResponse: pendingInviteRPCResponse <- err if err == nil { ctx.Infof("Activating left screen %q", pendingInviterName) left.Activate(ctx, pendingInviterName) seek <- false } pendingInviterName = "" pendingInviteUserResponse = nil pendingInviteRPCResponse = nil case <-left.Lost(): ctx.Infof("Deactivating left screen") left.Deactivate() seek <- true case invitee := <-accepted: ctx.Infof("Activating right screen %q", invitee) right.Activate(ctx, invitee) case <-right.Lost(): ctx.Infof("Deactivating right screen") right.Deactivate() go sendInvites(ctx, disc, accepted) case <-ctx.Done(): return } } }
func startUnclaimedLockServer(ctx *context.T, configDir string) (<-chan struct{}, func(), error) { // Start a local mounttable where the unclaimed lock server would // be mounted, and make this mounttable visible in the local // neighborhood. mtName, stopMT, err := locklib.StartMounttable(ctx, configDir, locklib.LockNhPrefix+unclaimedLockNhSuffix) if err != nil { return nil, nil, err } ctx, _, err = v23.WithNewNamespace(ctx, mtName) if err != nil { stopMT() return nil, nil, err } claimed := make(chan struct{}) ctx, cancel := context.WithCancel(ctx) _, server, err := v23.WithNewServer(ctx, lockObjectName(ctx), newUnclaimedLock(claimed, configDir), security.AllowEveryone()) if err != nil { stopMT() return nil, nil, err } stopUnclaimedLock := func() { cancel() vlog.Infof("Stopping unclaimed lock server...") <-server.Closed() vlog.Infof("Stopped unclaimed lock server...") stopMT() } vlog.Infof("Started unclaimed lock server\n") vlog.Infof("ENDPOINT: %v\n", server.Status().Endpoints[0].Name()) return claimed, stopUnclaimedLock, nil }