Skip to content
Snippets Groups Projects
Select Git revision
  • 6cec75481e99a5cbcc1c39ffc7981e19aeaa6e49
  • release default protected
  • 11-22-implement-kv-interface-defined-in-collectiveversionedkvgo
  • hotfix/TestHostPool_UpdateNdf_AddFilter
  • XX-4719/announcementChannels
  • xx-4717/logLevel
  • jonah/noob-channel
  • master protected
  • XX-4707/tagDiskJson
  • xx-4698/notification-retry
  • hotfix/notifylockup
  • syncNodes
  • hotfix/localCB
  • XX-4677/NewChanManagerMobile
  • XX-4689/DmSync
  • duplicatePrefix
  • XX-4601/HavenInvites
  • finalizedUICallbacks
  • XX-4673/AdminKeySync
  • debugNotifID
  • anne/test
  • v4.7.5
  • v4.7.4
  • v4.7.3
  • v4.7.2
  • v4.7.1
  • v4.6.3
  • v4.6.1
  • v4.5.0
  • v4.4.4
  • v4.3.11
  • v4.3.8
  • v4.3.7
  • v4.3.6
  • v4.3.5
  • v4.2.0
  • v4.3.0
  • v4.3.4
  • v4.3.3
  • v4.3.2
  • v4.3.1
41 results

state.go

  • state.go 6.03 KiB
    ///////////////////////////////////////////////////////////////////////////////
    // Copyright © 2020 xx network SEZC                                          //
    //                                                                           //
    // Use of this source code is governed by a license that can be found in the //
    // LICENSE file                                                              //
    ///////////////////////////////////////////////////////////////////////////////
    
    package auth
    
    import (
    	"encoding/base64"
    
    	"github.com/pkg/errors"
    	"gitlab.com/elixxir/client/auth/store"
    	"gitlab.com/elixxir/client/cmix"
    	"gitlab.com/elixxir/client/cmix/identity/receptionID"
    	"gitlab.com/elixxir/client/cmix/message"
    	"gitlab.com/elixxir/client/e2e"
    	"gitlab.com/elixxir/client/e2e/ratchet/partner/session"
    	"gitlab.com/elixxir/client/event"
    	"gitlab.com/elixxir/client/storage/versioned"
    	"gitlab.com/elixxir/crypto/fastRNG"
    	"gitlab.com/xx_network/primitives/id"
    )
    
    // state is an implementation of the State interface.
    type state struct {
    	// Main Callbacks for all auth operations
    	callbacks Callbacks
    	// partner-specific Callbacks
    	partnerCallbacks partnerCallbacks
    
    	net cmixClient
    	e2e e2eHandler
    	rng *fastRNG.StreamGenerator
    
    	store *store.Store
    	event event.Reporter
    
    	params Params
    
    	// These are the parameters used when creating/adding session
    	// partners
    	sessionParams session.Params
    
    	backupTrigger func(reason string)
    }
    
    // NewState loads the auth state or creates new auth state if one cannot be
    // found.
    // Bases its reception identity and keys off of what is found in e2e.
    // Uses this ID to modify the kv prefix for a unique storage path
    // Parameters:
    //   The params object passed in determines the services that will be used
    //   to pick up requests and signal notifications. These are unique to an
    //   identity, so multiple auth states with the same service tags with
    //   different identities can run simultaneously.
    //   Default parameters can be retrieved via GetDefaultParameters()
    // Temporary:
    //   In some cases, for example client <-> server communications, connections
    //   are treated as ephemeral. To do so in auth, pass in an ephemeral e2e (made
    //   with a memory only versioned.KV) as well as a memory only versioned.KV for
    //   NewState and use GetDefaultTemporaryParams() for the parameters
    func NewState(kv *versioned.KV, net cmix.Client, e2e e2e.Handler,
    	rng *fastRNG.StreamGenerator, event event.Reporter, authParams Params,
    	sessParams session.Params, callbacks Callbacks,
    	backupTrigger func(reason string)) (State, error) {
    	kv = kv.Prefix(makeStorePrefix(e2e.GetReceptionID()))
    	return NewStateLegacy(kv, net, e2e, rng, event, authParams, sessParams,
    		callbacks, backupTrigger)
    }
    
    // NewStateLegacy loads the auth state or creates new auth state if one cannot
    // be found. Bases its reception identity and keys off of what is found in e2e.
    // Does not modify the kv prefix for backwards compatibility.
    // Otherwise, acts the same as NewState
    func NewStateLegacy(kv *versioned.KV, net cmix.Client, e2e e2e.Handler,
    	rng *fastRNG.StreamGenerator, event event.Reporter, authParams Params,
    	sessParams session.Params, callbacks Callbacks,
    	backupTrigger func(reason string)) (State, error) {
    
    	s := &state{
    		callbacks:        callbacks,
    		partnerCallbacks: partnerCallbacks{callbacks: make(map[id.ID]Callbacks)},
    		net:              net,
    		e2e:              e2e,
    		rng:              rng,
    		event:            event,
    		params:           authParams,
    		sessionParams:    sessParams,
    		backupTrigger:    backupTrigger,
    	}
    
    	// create the store
    	var err error
    	s.store, err = store.NewOrLoadStore(kv, e2e.GetGroup(),
    		&sentRequestHandler{s: s})
    
    	// register services
    	net.AddService(e2e.GetReceptionID(), message.Service{
    		Identifier: e2e.GetReceptionID()[:],
    		Tag:        authParams.RequestTag,
    		Metadata:   nil,
    	}, &receivedRequestService{s: s, reset: false})
    
    	net.AddService(e2e.GetReceptionID(), message.Service{
    		Identifier: e2e.GetReceptionID()[:],
    		Tag:        authParams.ResetRequestTag,
    		Metadata:   nil,
    	}, &receivedRequestService{s: s, reset: true})
    
    	if err != nil {
    		return nil, errors.WithMessage(err,
    			"Failed to make Auth State manager")
    	}
    
    	return s, nil
    }
    
    // CallAllReceivedRequests will iterate through all pending contact requests
    // and replay them on the callbacks.
    func (s *state) CallAllReceivedRequests() {
    	rrList := s.store.GetAllReceivedRequests()
    	for i := range rrList {
    		rr := rrList[i]
    		eph := receptionID.BuildIdentityFromRound(rr.GetContact().ID,
    			rr.GetRound())
    		if cb := s.partnerCallbacks.getPartnerCallback(rr.GetContact().ID); cb != nil {
    			cb.Request(rr.GetContact(), eph, rr.GetRound())
    		} else {
    			s.callbacks.Request(rr.GetContact(), eph, rr.GetRound())
    		}
    	}
    }
    
    func makeStorePrefix(partner *id.ID) string {
    	return "authStore:" + base64.StdEncoding.EncodeToString(partner.Marshal())
    }
    
    func (s *state) Close() error {
    	s.net.DeleteService(s.e2e.GetReceptionID(), message.Service{
    		Identifier: s.e2e.GetReceptionID()[:],
    		Tag:        s.params.RequestTag,
    		Metadata:   nil,
    	}, nil)
    
    	s.net.DeleteService(s.e2e.GetReceptionID(), message.Service{
    		Identifier: s.e2e.GetReceptionID()[:],
    		Tag:        s.params.ResetRequestTag,
    		Metadata:   nil,
    	}, nil)
    	return nil
    }
    
    // DeletePartner deletes the request and/or confirmation for the given partner.
    func (s *state) DeletePartner(partner *id.ID) error {
    	err := s.store.DeleteRequest(partner)
    	err2 := s.store.DeleteConfirmation(partner)
    
    	// Only return an error if both failed to delete
    	if err != nil && err2 != nil {
    		return errors.Errorf("Failed to delete partner: no requests or "+
    			"confirmations found: %s, %s", err, err2)
    	}
    
    	s.DeletePartnerCallback(partner)
    
    	return nil
    }
    
    // AddPartnerCallback that overrides the generic auth callback for the given partnerId
    func (s *state) AddPartnerCallback(partnerId *id.ID, cb Callbacks) {
    	s.partnerCallbacks.AddPartnerCallback(partnerId, cb)
    }
    
    // DeletePartnerCallback that overrides the generic auth callback for the given partnerId
    func (s *state) DeletePartnerCallback(partnerId *id.ID) {
    	s.partnerCallbacks.DeletePartnerCallback(partnerId)
    }