Skip to content
Snippets Groups Projects
Select Git revision
  • b35c5f632b801efce7486aea534cb600059eb478
  • 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

manager.go

Blame
  • manager.go 6.30 KiB
    package ud
    
    import (
    	"github.com/pkg/errors"
    	jww "github.com/spf13/jwalterweatherman"
    	"gitlab.com/elixxir/client/api"
    	"gitlab.com/elixxir/client/interfaces"
    	"gitlab.com/elixxir/client/single"
    	"gitlab.com/elixxir/client/stoppable"
    	"gitlab.com/elixxir/client/storage"
    	"gitlab.com/elixxir/comms/client"
    	"gitlab.com/elixxir/crypto/contact"
    	"gitlab.com/elixxir/crypto/cyclic"
    	"gitlab.com/elixxir/crypto/fastRNG"
    	"gitlab.com/xx_network/comms/connect"
    	"gitlab.com/xx_network/crypto/signature/rsa"
    	"gitlab.com/xx_network/primitives/id"
    	"math"
    	"time"
    )
    
    type SingleInterface interface {
    	TransmitSingleUse(contact.Contact, []byte, string, uint8, single.ReplyComm,
    		time.Duration) error
    	StartProcesses() (stoppable.Stoppable, error)
    }
    
    type Manager struct {
    	// External
    	client  *api.Client
    	comms   *client.Comms
    	rng     *fastRNG.StreamGenerator
    	sw      interfaces.Switchboard
    	storage *storage.Session
    	net     interfaces.NetworkManager
    
    	// Loaded from external access
    	privKey *rsa.PrivateKey
    	grp     *cyclic.Group
    
    	// internal structures
    	single SingleInterface
    	myID   *id.ID
    
    	// alternate User discovery service to circumvent production
    	alternativeUd *alternateUd
    
    	registered *uint32
    }
    
    // alternateUd is an alternative user discovery service.
    // This is used for testing, so client can avoid using
    // the production server.
    type alternateUd struct {
    	host     *connect.Host
    	dhPubKey []byte
    }
    
    // NewManager builds a new user discovery manager. It requires that an updated
    // NDF is available and will error if one is not.
    func NewManager(client *api.Client, single *single.Manager) (*Manager, error) {
    	jww.INFO.Println("ud.NewManager()")
    	if client.NetworkFollowerStatus() != api.Running {
    		return nil, errors.New(
    			"cannot start UD Manager when network follower is not running.")
    	}
    
    	m := &Manager{
    		client:  client,
    		comms:   client.GetComms(),
    		rng:     client.GetRng(),
    		sw:      client.GetSwitchboard(),
    		storage: client.GetStorage(),
    		net:     client.GetNetworkInterface(),
    		single:  single,
    	}
    
    	// check that user discovery is available in the NDF
    	def := m.net.GetInstance().GetPartialNdf().Get()
    
    	if def.UDB.Cert == "" {
    		return nil, errors.New("NDF does not have User Discovery information, " +
    			"is there network access?: Cert not present.")
    	}
    
    	// Create the user discovery host object
    	hp := connect.GetDefaultHostParams()
    	// Client will not send KeepAlive packets
    	hp.KaClientOpts.Time = time.Duration(math.MaxInt64)
    	hp.MaxRetries = 3
    	hp.SendTimeout = 3 * time.Second
    	hp.AuthEnabled = false
    
    	m.myID = m.storage.User().GetCryptographicIdentity().GetReceptionID()
    
    	// Get the commonly used data from storage
    	m.privKey = m.storage.GetUser().ReceptionRSA
    
    	// Load if the client is registered
    	m.loadRegistered()
    
    	// Store the pointer to the group locally for easy access
    	m.grp = m.storage.E2e().GetGroup()
    
    	return m, nil
    }
    
    // SetAlternativeUserDiscovery sets the alternativeUd object within manager.
    // Once set, any user discovery operation will go through the alternative
    // user discovery service.
    // To undo this operation, use UnsetAlternativeUserDiscovery.
    func (m *Manager) SetAlternativeUserDiscovery(altCert, altAddress, contactFile []byte) error {
    	params := connect.GetDefaultHostParams()
    	params.AuthEnabled = false
    
    	udIdBytes, dhPubKey, err := contact.ReadContactFromFile(contactFile)
    	if err != nil {
    		return err
    	}
    
    	udID, err := id.Unmarshal(udIdBytes)
    	if err != nil {
    		return err
    	}
    
    	// Add a new host and return it if it does not already exist
    	host, err := m.comms.AddHost(udID, string(altAddress),
    		altCert, params)
    	if err != nil {
    		return errors.WithMessage(err, "User Discovery host object could "+
    			"not be constructed.")
    	}
    
    	m.alternativeUd = &alternateUd{
    		host:     host,
    		dhPubKey: dhPubKey,
    	}
    
    	return nil
    }
    
    // UnsetAlternativeUserDiscovery clears out the information from
    // the Manager object.
    func (m *Manager) UnsetAlternativeUserDiscovery() error {
    	if m.alternativeUd == nil {
    		return errors.New("Alternative User Discovery is already unset.")
    	}
    
    	m.alternativeUd = nil
    	return nil
    }
    
    // getHost returns the current UD host for the UD ID found in the NDF. If the
    // host does not exist, then it is added and returned
    func (m *Manager) getHost() (*connect.Host, error) {
    	// Return alternative User discovery service if it has been set
    	if m.alternativeUd != nil {
    		return m.alternativeUd.host, nil
    	}
    
    	netDef := m.net.GetInstance().GetPartialNdf().Get()
    	// Unmarshal UD ID from the NDF
    	udID, err := id.Unmarshal(netDef.UDB.ID)
    	if err != nil {
    		return nil, errors.Errorf("failed to unmarshal UD ID from NDF: %+v", err)
    	}
    
    	// Return the host, if it exists
    	host, exists := m.comms.GetHost(udID)
    	if exists {
    		return host, nil
    	}
    
    	params := connect.GetDefaultHostParams()
    	params.AuthEnabled = false
    	params.SendTimeout = 20 * time.Second
    
    	// Add a new host and return it if it does not already exist
    	host, err = m.comms.AddHost(udID, netDef.UDB.Address,
    		[]byte(netDef.UDB.Cert), params)
    	if err != nil {
    		return nil, errors.WithMessage(err, "User Discovery host object could "+
    			"not be constructed.")
    	}
    
    	return host, nil
    }
    
    // getContact returns the contact for UD as retrieved from the NDF.
    func (m *Manager) getContact() (contact.Contact, error) {
    	// Return alternative User discovery contact if set
    	if m.alternativeUd != nil {
    		// Unmarshal UD DH public key
    		alternativeDhPubKey := m.storage.E2e().GetGroup().NewInt(1)
    		if err := alternativeDhPubKey.UnmarshalJSON(m.alternativeUd.dhPubKey); err != nil {
    			return contact.Contact{},
    				errors.WithMessage(err, "Failed to unmarshal UD DH public key.")
    		}
    
    		return contact.Contact{
    			ID:             m.alternativeUd.host.GetId(),
    			DhPubKey:       alternativeDhPubKey,
    			OwnershipProof: nil,
    			Facts:          nil,
    		}, nil
    	}
    
    	netDef := m.net.GetInstance().GetPartialNdf().Get()
    
    	// Unmarshal UD ID from the NDF
    	udID, err := id.Unmarshal(netDef.UDB.ID)
    	if err != nil {
    		return contact.Contact{},
    			errors.Errorf("failed to unmarshal UD ID from NDF: %+v", err)
    	}
    
    	// Unmarshal UD DH public key
    	dhPubKey := m.storage.E2e().GetGroup().NewInt(1)
    	if err = dhPubKey.UnmarshalJSON(netDef.UDB.DhPubKey); err != nil {
    		return contact.Contact{},
    			errors.WithMessage(err, "Failed to unmarshal UD DH public key.")
    	}
    
    	return contact.Contact{
    		ID:             udID,
    		DhPubKey:       dhPubKey,
    		OwnershipProof: nil,
    		Facts:          nil,
    	}, nil
    }