func startLockServer(ctx *context.T, configDir string) (func(), error) { blessings, _ := v23.GetPrincipal(ctx).BlessingStore().Default() lockNhSuffix := fmt.Sprint(blessings) // Start a local mounttable where the lock server would be // mounted, and make this mounttable visible in the local // neighborhood. mtName, stopMT, err := locklib.StartMounttable(ctx, configDir, locklib.LockNhPrefix+lockNhSuffix) if err != nil { return nil, err } ctx, _, err = v23.WithNewNamespace(ctx, mtName) if err != nil { stopMT() return nil, err } ctx, cancel := context.WithCancel(ctx) _, server, err := v23.WithNewServer(ctx, lockObjectName(ctx), newLock(), security.DefaultAuthorizer()) if err != nil { stopMT() return nil, err } stopLock := func() { cancel() vlog.Infof("Stopping lock server...") <-server.Closed() vlog.Infof("Stopped lock server...") stopMT() } vlog.Infof("Started lock server\n") vlog.Infof("ENDPOINT: %v\n", server.Status().Endpoints[0].Name()) return stopLock, nil }
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 }
func (nm *V23Manager) getReadyToRun(ch chan bool) { defer nm.mu.Unlock() if nm.chatty { log.Printf("Calling v23.Init") } nm.ctx, nm.shutdown = v23.Init() if nm.shutdown == nil { log.Panic("shutdown nil") } if nm.chatty { log.Printf("Setting root to %v", nm.namespaceRoot) } v23.GetNamespace(nm.ctx).SetRoots(nm.namespaceRoot) nm.initialPlayerNumbers = nm.playerNumbers() if nm.chatty { log.Printf("Found %d players.", len(nm.initialPlayerNumbers)) } sort.Ints(nm.initialPlayerNumbers) myId := 1 if len(nm.initialPlayerNumbers) > 0 { myId = nm.initialPlayerNumbers[len(nm.initialPlayerNumbers)-1] + 1 } if nm.isGameMaster { myId = 999 } nm.relay = relay.MakeRelay() nm.myself = model.NewPlayer(myId) if nm.isGameMaster { if nm.chatty { log.Printf("I am game master.") } nm.isReady = true ch <- true return } if nm.chatty { log.Printf("I am player %v\n", nm.myself) } myName := nm.serverName(nm.Me().Id()) if nm.chatty { log.Printf("Calling myself %s\n", myName) } ctx, s, err := v23.WithNewServer(nm.ctx, myName, ifc.GameServiceServer(nm.relay), MakeAuthorizer()) if err != nil { log.Panic("Error creating server:", err) ch <- false return } saveEndpointToFile(s) nm.ctx = ctx nm.isReady = true ch <- true }
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 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 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 main() { ctx, shutdown := v23.Init() defer shutdown() // Run server if *to == "" { // We are not the caller, so make the RPC available for the // caller to call in on. bsrv := ifc.BridgeServer(makeImpl()) _, server, err := v23.WithNewServer(ctx, *serviceName, bsrv, security.DefaultAuthorizer()) if err != nil { ctx.Error("Error serving service: ", err) return } endpoint := server.Status().Endpoints[0] fmt.Printf("Listening at: %v\n", endpoint) // Wait forever. <-signals.ShutdownOnSignals(ctx) } else if *to != "" && *from != "" { // pipe mode ifct := ifcTopics(*topics) tmout := options.ChannelTimeout(*timeout) leftc := ifc.BridgeClient(*to) rightc := ifc.BridgeClient(*from) leftcc, err := leftc.Link(ctx, ifct, tmout) if err != nil { ctx.Error(err) return } rightcc, err := rightc.Link(ctx, ifct, tmout) if err != nil { ctx.Error(err) return } errCh := make(chan error, 2) wg := &sync.WaitGroup{} wg.Add(2) go linkToLink(leftcc.RecvStream(), rightcc.SendStream(), errCh, wg) go linkToLink(rightcc.RecvStream(), leftcc.SendStream(), errCh, wg) wg.Wait() select { case err := <-errCh: log.Print("pipe error: ", err) default: // don't block on channel read } } else { cc, mu, err := mqttConnect() if err != nil { ctx.Error("mqtt connect: ", err) return } bc := ifc.BridgeClient(*to) ifct := ifcTopics(*topics) bcc, err := bc.Link(ctx, ifct, options.ChannelTimeout(*timeout)) if err != nil { ctx.Error(err) return } done := make(chan error, 2) go func() { done <- transmitter(ifct, bcc.SendStream(), cc, mu) println("send done") }() go func() { done <- receiver(bcc.RecvStream(), cc, mu) println("recv done") }() err = <-done log.Print("Stopped with error ", err) // Stop sender by closing cc.Incoming cc.Disconnect() } }