// HandlePaperKeyCached is called whenever a paper key is cached // in response to a rekey harassment. func (n *NotifyRouter) HandlePaperKeyCached(uid keybase1.UID, encKID keybase1.KID, sigKID keybase1.KID) { if n == nil { return } n.G().Log.Debug("+ Sending paperkey cached notfication") arg := keybase1.PaperKeyCachedArg{ Uid: uid, EncKID: encKID, SigKID: sigKID, } // For all connections we currently have open... n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { // If the connection wants the `Favorites` notification type if n.getNotificationChannels(id).Paperkeys { // In the background do... go func() { (keybase1.NotifyPaperKeyClient{ Cli: rpc.NewClient(xp, ErrorUnwrapper{}), }).PaperKeyCached(context.TODO(), arg) }() } return true }) if n.listener != nil { n.listener.PaperKeyCached(uid, encKID, sigKID) } n.G().Log.Debug("- Sent paperkey cached notfication") }
// connect performs the actual connect() and rpc setup. func (c *Connection) connect(ctx context.Context) error { c.log.Debug("Connection: dialing transport") // connect transport, err := c.transport.Dial(ctx) if err != nil { c.log.Warning("Connection: error dialing transport: %v", err) return err } client := rpc.NewClient(transport, c.errorUnwrapper) server := rpc.NewServer(transport, libkb.WrapError) // call the connect handler err = c.handler.OnConnect(ctx, c, client, server) if err != nil { c.log.Warning("Connection: error calling OnConnect handler: %v", err) return err } // set the client for other callers. // we wait to do this so the handler has time to do // any setup required, e.g. authenticate. c.mutex.Lock() defer c.mutex.Unlock() c.client = client c.server = server c.transport.Finalize() c.log.Debug("Connection: connected") return nil }
// HandleTrackingChanged is called whenever we have a new tracking or // untracking chain link related to a given user. It will broadcast the // messages to all curious listeners. func (n *NotifyRouter) HandleTrackingChanged(uid keybase1.UID, username string) { if n == nil { return } arg := keybase1.TrackingChangedArg{ Uid: uid, Username: username, } // For all connections we currently have open... n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { // If the connection wants the `Tracking` notification type if n.getNotificationChannels(id).Tracking { // In the background do... go func() { // A send of a `TrackingChanged` RPC with the user's UID (keybase1.NotifyTrackingClient{ Cli: rpc.NewClient(xp, ErrorUnwrapper{}), }).TrackingChanged(context.TODO(), arg) }() } return true }) if n.listener != nil { n.listener.TrackingChanged(uid, username) } }
// HandleFavoritesChanged is called whenever the kbfs favorites change // for a user (and caches should be invalidated). It will broadcast the // messages to all curious listeners. func (n *NotifyRouter) HandleFavoritesChanged(uid keybase1.UID) { if n == nil { return } n.G().Log.Debug("+ Sending favorites changed notfication") // For all connections we currently have open... n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { // If the connection wants the `Favorites` notification type if n.getNotificationChannels(id).Favorites { // In the background do... go func() { // A send of a `FavoritesChanged` RPC with the user's UID (keybase1.NotifyFavoritesClient{ Cli: rpc.NewClient(xp, ErrorUnwrapper{}), }).FavoritesChanged(context.TODO(), uid) }() } return true }) if n.listener != nil { n.listener.FavoritesChanged(uid) } n.G().Log.Debug("- Sent favorites changed notfication") }
// ClientOutOfDate is called whenever the API server tells us our client is out // of date. (This is done by adding special headers to every API response that // an out-of-date client makes.) func (n *NotifyRouter) HandleClientOutOfDate(upgradeTo, upgradeURI, upgradeMsg string) { if n == nil { return } n.G().Log.Debug("+ Sending client-out-of-date notfication") // For all connections we currently have open... n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { // If the connection wants the `Session` notification type if n.getNotificationChannels(id).Session { // In the background do... go func() { // A send of a `ClientOutOfDate` RPC (keybase1.NotifySessionClient{ Cli: rpc.NewClient(xp, ErrorUnwrapper{}), }).ClientOutOfDate(context.TODO(), keybase1.ClientOutOfDateArg{ UpgradeTo: upgradeTo, UpgradeURI: upgradeURI, UpgradeMsg: upgradeMsg, }) }() } return true }) if n.listener != nil { n.listener.ClientOutOfDate(upgradeTo, upgradeURI, upgradeMsg) } n.G().Log.Debug("- client-out-of-date notification sent") }
func newGregorFirehoseHandler(g *libkb.GlobalContext, connID libkb.ConnectionID, xp rpc.Transporter) *gregorFirehoseHandler { return &gregorFirehoseHandler{ Contextified: libkb.NewContextified(g), connID: connID, cli: keybase1.GregorUIClient{Cli: rpc.NewClient(xp, libkb.ErrorUnwrapper{})}, } }
func NewBaseHandler(xp rpc.Transporter) *BaseHandler { h := &BaseHandler{xp: xp} h.cli = rpc.NewClient(h.xp, libkb.ErrorUnwrapper{}) h.loginCli = &keybase1.LoginUiClient{Cli: h.cli} h.secretCli = &keybase1.SecretUiClient{Cli: h.cli} h.logCli = &keybase1.LogUiClient{Cli: h.cli} return h }
func (u *UIRouter) GetSecretUI() (libkb.SecretUI, error) { x := u.getUI(libkb.SecretUIKind) if x == nil { return nil, nil } cli := rpc.NewClient(x, libkb.ErrorUnwrapper{}) scli := keybase1.SecretUiClient{Cli: cli} return &SecretUI{cli: &scli}, nil }
func (u *UIRouter) GetSecretUI() (ui libkb.SecretUI, err error) { defer u.G().Trace("UIRouter.GetSecretUI", func() error { return err }) x := u.getUI(libkb.SecretUIKind) if x == nil { u.G().Log.Debug("| getUI(libkb.SecretUIKind) returned nil") return nil, nil } cli := rpc.NewClient(x, libkb.ErrorUnwrapper{}) scli := keybase1.SecretUiClient{Cli: cli} u.G().Log.Debug("| returning delegated SecretUI") return &SecretUI{cli: &scli}, nil }
func (u *UIRouter) GetRekeyUINoSessionID() (keybase1.RekeyUIInterface, error) { var err error defer u.G().Trace("UIRouter.GetRekeyUINoSessionID", func() error { return err })() x := u.getUI(libkb.RekeyUIKind) if x == nil { return nil, nil } cli := rpc.NewClient(x, libkb.ErrorUnwrapper{}) uicli := keybase1.RekeyUIClient{Cli: cli} ret := &RekeyUI{ cli: &uicli, Contextified: libkb.NewContextified(u.G()), } return ret, nil }
// HandleLogout is called whenever the current user logged out. It will broadcast // the message to all connections who care about such a mesasge. func (n *NotifyRouter) HandleLogout() { // For all connections we currently have open... n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { // If the connection wants the `Session` notification type if n.getNotificationChannels(id).Session { // In the background do... go func() { // A send of a `LoggedOut` RPC (keybase1.NotifySessionClient{ Cli: rpc.NewClient(xp, ErrorUnwrapper{}), }).LoggedOut(context.TODO()) }() } return true }) }
// HandleUserChanged is called whenever we know that a given user has // changed (and must be cache-busted). It will broadcast the messages // to all curious listeners. func (n *NotifyRouter) HandleUserChanged(uid keybase1.UID) { // For all connections we currently have open... n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { // If the connection wants the `Users` notification type if n.getNotificationChannels(id).Users { // In the background do... go func() { // A send of a `UserChanged` RPC with the user's UID (keybase1.NotifyUsersClient{ Cli: rpc.NewClient(xp, ErrorUnwrapper{}), }).UserChanged(context.TODO(), uid) }() } return true }) }
// HandleAppExit is called whenever an app exit command is issued func (n *NotifyRouter) HandleAppExit() { if n == nil { return } n.G().Log.Debug("+ Sending app exit notification") n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { if n.getNotificationChannels(id).App { go func() { (keybase1.NotifyAppClient{ Cli: rpc.NewClient(xp, ErrorUnwrapper{}), }).Exit(context.TODO()) }() } return true }) n.G().Log.Debug("- Sent app exit notfication") }
func (u *UIRouter) GetSecretUI(sessionID int) (ui libkb.SecretUI, err error) { defer u.G().Trace("UIRouter.GetSecretUI", func() error { return err }) x := u.getUI(libkb.SecretUIKind) if x == nil { u.G().Log.Debug("| getUI(libkb.SecretUIKind) returned nil") return nil, nil } cli := rpc.NewClient(x, libkb.ErrorUnwrapper{}) scli := keybase1.SecretUiClient{Cli: cli} u.G().Log.Debug("| returning delegated SecretUI with sessionID = %d", sessionID) ret := &SecretUI{ cli: &scli, sessionID: sessionID, Contextified: libkb.NewContextified(u.G()), } return ret, nil }
// HandleFSActivity is called for any KBFS notification. It will broadcast the messages // to all curious listeners. func (n *NotifyRouter) HandleFSActivity(activity keybase1.FSNotification) { if n == nil { return } // For all connections we currently have open... n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { // If the connection wants the `Kbfs` notification type if n.getNotificationChannels(id).Kbfs { // In the background do... go func() { // A send of a `FSActivity` RPC with the notification (keybase1.NotifyFSClient{ Cli: rpc.NewClient(xp, ErrorUnwrapper{}), }).FSActivity(context.TODO(), activity) }() } return true }) }
func (p *provisionee) pickFirstConnection() (err error) { select { case <-p.start: case sec := <-p.arg.SecretChannel: p.conn.Close() err = p.startServer(sec) if err != nil { return err } cli := keybase1.Kex2ProvisionerClient{Cli: rpc.NewClient(p.xp, nil)} if err = cli.KexStart(context.TODO()); err != nil { return err } case <-p.arg.Ctx.Done(): err = ErrCanceled case <-time.After(p.arg.Timeout): err = ErrTimedOut } return }
func (u *UIRouter) GetRekeyUI() (keybase1.RekeyUIInterface, int, error) { var err error defer u.G().Trace("UIRouter.GetRekeyUI", func() error { return err })() x := u.getUI(libkb.RekeyUIKind) if x == nil { return nil, 0, nil } cli := rpc.NewClient(x, libkb.ErrorUnwrapper{}) uicli := keybase1.RekeyUIClient{Cli: cli} sessionID, err := uicli.DelegateRekeyUI(context.TODO()) if err != nil { return nil, 0, err } ret := &RekeyUI{ sessionID: sessionID, cli: &uicli, Contextified: libkb.NewContextified(u.G()), } return ret, sessionID, nil }
// HandleLogin is called whenever a user logs in. It will broadcast // the message to all connections who care about such a mesasge. func (n *NotifyRouter) HandleLogin(u string) { if n == nil { return } n.G().Log.Debug("+ Sending login notfication, as user %q", u) // For all connections we currently have open... n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { // If the connection wants the `Session` notification type if n.getNotificationChannels(id).Session { // In the background do... go func() { // A send of a `LoggedIn` RPC (keybase1.NotifySessionClient{ Cli: rpc.NewClient(xp, ErrorUnwrapper{}), }).LoggedIn(context.TODO(), u) }() } return true }) n.G().Log.Debug("- Login notification sent") }
// HandleServiceShutdown is called whenever the service shuts down. func (n *NotifyRouter) HandleServiceShutdown() { if n == nil { return } n.G().Log.Debug("+ Sending service shutdown notfication") var wg sync.WaitGroup // For all connections we currently have open... n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { // If the connection wants the `Service` notification type if n.getNotificationChannels(id).Service { // In the background do... wg.Add(1) go func() { (keybase1.NotifyServiceClient{ Cli: rpc.NewClient(xp, ErrorUnwrapper{}), }).Shutdown(context.TODO()) wg.Done() }() } return true }) done := make(chan struct{}) go func() { wg.Wait() close(done) }() // timeout after 4s (launchd will SIGKILL after 5s) select { case <-done: case <-time.After(4 * time.Second): n.G().Log.Warning("Timed out sending service shutdown notifications, proceeding to shutdown") } n.G().Log.Debug("- Sent service shutdown notfication") }
func (u *UIRouter) GetIdentifyUI() (libkb.IdentifyUI, error) { x := u.getUI(libkb.IdentifyUIKind) if x == nil { return nil, nil } cli := rpc.NewClient(x, libkb.ErrorUnwrapper{}) iuicli := keybase1.IdentifyUiClient{Cli: cli} sessionID, err := iuicli.DelegateIdentifyUI(context.TODO()) if err != nil { return nil, err } ret := &RemoteIdentifyUI{ sessionID: sessionID, uicli: iuicli, logUI: &LogUI{ sessionID, &keybase1.LogUiClient{Cli: cli}, }, Contextified: libkb.NewContextified(u.G()), } return ret, nil }
func (p *provisioner) runProtocol() (err error) { cli := keybase1.Kex2ProvisioneeClient{Cli: rpc.NewClient(p.xp, nil)} var helloArg keybase1.HelloArg helloArg, err = p.arg.Provisioner.GetHelloArg() if err != nil { return } var res keybase1.HelloRes if res, err = cli.Hello(context.TODO(), helloArg); err != nil { return } if p.canceled { return ErrCanceled } var counterSigned []byte if counterSigned, err = p.arg.Provisioner.CounterSign(res); err != nil { return err } if err = cli.DidCounterSign(context.TODO(), counterSigned); err != nil { return err } return nil }
func FixVersionClash(g *libkb.GlobalContext, cl libkb.CommandLine) (err error) { var cli keybase1.ConfigClient var ctlCli keybase1.CtlClient var serviceConfig keybase1.Config var socket net.Conn g.Log.Debug("+ FixVersionClash") defer func() { if socket != nil { socket.Close() socket = nil } g.Log.Debug("- FixVersionClash -> %v", err) }() // Make our own stack here, circumventing all of our libraries, so // as not to introduce any incompatibilities with earlier services // (like 1.0.8) socket, err = g.SocketInfo.DialSocket() if err != nil { g.Log.Debug("| Failed to DialSocket, but ignoring error: %s\n", err) return nil } xp := libkb.NewTransportFromSocket(g, socket) srv := rpc.NewServer(xp, libkb.WrapError) gcli := rpc.NewClient(xp, libkb.ErrorUnwrapper{}) cli = keybase1.ConfigClient{Cli: gcli} srv.Register(NewLogUIProtocol()) serviceConfig, err = cli.GetConfig(context.TODO(), 0) if err != nil { return err } g.Log.Debug("| Contacted service; got version: %s", serviceConfig.Version) // We'll check and restart the service if there is a new version. var semverClient, semverService semver.Version cliVersion := libkb.VersionString() if g.Env.GetRunMode() == libkb.DevelRunMode { tmp := os.Getenv("KEYBASE_SET_VERSION") if len(tmp) > 0 { cliVersion = tmp } } semverClient, err = semver.Make(cliVersion) if err != nil { return err } semverService, err = semver.Make(serviceConfig.Version) if err != nil { return err } g.Log.Debug("| version check %s v %s", semverClient, semverService) if semverClient.EQ(semverService) { g.Log.Debug("| versions check out") return nil } else if semverClient.LT(semverService) && semverClient.Major < semverService.Major { return fmt.Errorf("Unexpected version clash; client is at v%s, which is significantly *less than* server at v%s", semverClient, semverService) } g.Log.Warning("Restarting after upgrade; service is running v%s, while v%s is available", semverService, semverClient) origPid, err := getPid(g) if err != nil { g.Log.Warning("Failed to find pid for service: %v\n", err) } if serviceConfig.ForkType == keybase1.ForkType_LAUNCHD { return restartLaunchdService(g, serviceConfig.Label, g.Env.GetServiceInfoPath()) } ctlCli = keybase1.CtlClient{Cli: gcli} err = ctlCli.Stop(context.TODO(), keybase1.StopArg{}) if err != nil && origPid >= 0 { // A fallback approach. I haven't seen a need for it, but it can't really hurt. // If we fail to restart via Stop() then revert to kill techniques. g.Log.Warning("Error in Stopping %d via RPC: %v; trying fallback (kill via pidfile)", origPid, err) time.Sleep(time.Second) var newPid int newPid, err = getPid(g) if err != nil { g.Log.Warning("No pid; shutdown must have worked (%v)", err) } else if newPid != origPid { g.Log.Warning("New service found with pid=%d; assuming restart", newPid) return nil } else { if err = killPid(origPid); err != nil { g.Log.Warning("Kill via pidfile failed: %v\n", err) return err } g.Log.Warning("Successful kill() on pid=%d", origPid) } } socket.Close() socket = nil time.Sleep(10 * time.Millisecond) g.Log.Debug("Waiting for shutdown...") time.Sleep(1 * time.Second) if serviceConfig.ForkType == keybase1.ForkType_AUTO { g.Log.Info("Restarting service...") _, err = AutoForkServer(g, cl) } return err }
func introduceMyself(g *libkb.GlobalContext, xp rpc.Transporter) error { cli := rpc.NewClient(xp, libkb.ErrorUnwrapper{}) ccli := keybase1.ConfigClient{Cli: cli} return ccli.HelloIAm(context.TODO(), g.GetMyClientDetails()) }
func GetRPCClientWithContext(g *libkb.GlobalContext) (ret *rpc.Client, xp rpc.Transporter, err error) { if _, xp, err = g.GetSocket(false); err == nil { ret = rpc.NewClient(xp, libkb.ErrorUnwrapper{}) } return }