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

session.go

  • user avatar
    Benjamin Wenger authored
    d48ec00c
    History
    session.go 4.67 KiB
    ////////////////////////////////////////////////////////////////////////////////
    // Copyright © 2020 Privategrity Corporation                                   /
    //                                                                             /
    // All rights reserved.                                                        /
    ////////////////////////////////////////////////////////////////////////////////
    
    // Session object definition
    
    package storage
    
    import (
    	"bytes"
    	"encoding/gob"
    	"gitlab.com/elixxir/client/globals"
    	"gitlab.com/elixxir/client/user"
    	"gitlab.com/elixxir/ekv"
    	"gitlab.com/xx_network/comms/connect"
    	"gitlab.com/xx_network/primitives/id"
    	"sync"
    	"testing"
    	"time"
    )
    
    // Session object, backed by encrypted filestore
    type Session struct {
    	kv  *VersionedKV
    	mux sync.Mutex
    }
    
    // Initialize a new Session object
    func Init(baseDir, password string) (*Session, error) {
    	fs, err := ekv.NewFilestore(baseDir, password)
    	var s *Session
    	if err == nil {
    		s = &Session{
    			kv: NewVersionedKV(fs),
    		}
    	}
    
    	return s, err
    }
    
    // a storage session with a memory backed for testing
    func InitMem(t *testing.T) *Session {
    	if t == nil {
    		panic("cannot use a memstore not for testing")
    	}
    	store := make(ekv.Memstore)
    	return &Session{kv: NewVersionedKV(store)}
    }
    
    // Get an object from the session
    func (s *Session) Get(key string) (*VersionedObject, error) {
    	return s.kv.Get(key)
    }
    
    // Set a value in the session
    func (s *Session) Set(key string, object *VersionedObject) error {
    	return s.kv.Set(key, object)
    }
    
    // Deletes a value in the session
    func (s *Session) Delete(key string) error {
    	return s.kv.Delete(key)
    }
    
    // Obtain the LastMessageID from the Session
    func (s *Session) GetLastMessageId() (string, error) {
    	v, err := s.Get("LastMessageID")
    	if v == nil || err != nil {
    		return "", nil
    	}
    	return string(v.Data), nil
    }
    
    // Set the LastMessageID in the Session
    func (s *Session) SetLastMessageId(id string) error {
    	ts, err := time.Now().MarshalText()
    	if err != nil {
    		return err
    	}
    	vo := &VersionedObject{
    		Timestamp: ts,
    		Data:      []byte(id),
    	}
    	return s.Set("LastMessageID", vo)
    }
    
    // GetNodeKeys returns all keys
    func (s *Session) GetNodeKeys() (map[string]user.NodeKeys, error) {
    	key := "NodeKeys"
    	var nodeKeys map[string]user.NodeKeys
    
    	// Attempt to locate the keys map
    	v, err := s.Get(key)
    	if err != nil {
    		// If the map doesn't exist, initialize it
    		ts, err := time.Now().MarshalText()
    		if err != nil {
    			return nil, err
    		}
    
    		// Encode the new map
    		nodeKeys = make(map[string]user.NodeKeys)
    		var nodeKeysBuffer bytes.Buffer
    		enc := gob.NewEncoder(&nodeKeysBuffer)
    		err = enc.Encode(nodeKeys)
    		if err != nil {
    			return nil, err
    		}
    
    		// Store the new map
    		vo := &VersionedObject{
    			Timestamp: ts,
    			Data:      nodeKeysBuffer.Bytes(),
    		}
    		err = s.Set(key, vo)
    		if err != nil {
    			return nil, err
    		}
    
    		// Return newly-initialized map
    		return nodeKeys, nil
    	}
    
    	// If the map exists, decode and return it
    	var nodeKeyBuffer bytes.Buffer
    	nodeKeyBuffer.Write(v.Data)
    	dec := gob.NewDecoder(&nodeKeyBuffer)
    	err = dec.Decode(&nodeKeys)
    
    	return nodeKeys, err
    }
    
    // GetNodeKeysFromCircuit obtains NodeKeys for a given circuit
    func (s *Session) GetNodeKeysFromCircuit(topology *connect.Circuit) (
    	[]user.NodeKeys, error) {
    	nodeKeys, err := s.GetNodeKeys()
    	if err != nil {
    		return nil, err
    	}
    
    	// Build a list of NodeKeys from the map
    	keys := make([]user.NodeKeys, topology.Len())
    	for i := 0; i < topology.Len(); i++ {
    		nid := topology.GetNodeAtIndex(i)
    		keys[i] = nodeKeys[nid.String()]
    		globals.Log.INFO.Printf("Read NodeKey: %s: %v", nid, keys[i])
    	}
    
    	return keys, nil
    }
    
    // Set NodeKeys in the Session
    func (s *Session) PushNodeKey(id *id.ID, key user.NodeKeys) error {
    	// Thread-safety
    	s.mux.Lock()
    	defer s.mux.Unlock()
    
    	// Obtain NodeKeys map
    	nodeKeys, err := s.GetNodeKeys()
    	if err != nil {
    		return err
    	}
    
    	// Set new value inside of map
    	nodeKeys[id.String()] = key
    
    	globals.Log.INFO.Printf("Adding NodeKey: %s: %v", id.String(), key)
    
    	// Encode the map
    	var nodeKeysBuffer bytes.Buffer
    	enc := gob.NewEncoder(&nodeKeysBuffer)
    	err = enc.Encode(nodeKeys)
    
    	// Insert the map back into the Session
    	ts, err := time.Now().MarshalText()
    	if err != nil {
    		return err
    	}
    	vo := &VersionedObject{
    		Timestamp: ts,
    		Data:      nodeKeysBuffer.Bytes(),
    	}
    	return s.Set("NodeKeys", vo)
    }
    
    // Initializes a Session object wrapped around a MemStore object.
    // FOR TESTING ONLY
    func InitTestingSession(i interface{}) *Session {
    	switch i.(type) {
    	case *testing.T:
    		break
    	case *testing.M:
    		break
    	case *testing.B:
    		break
    	default:
    		globals.Log.FATAL.Panicf("InitTestingSession is restricted to testing only. Got %T", i)
    	}
    
    	store := make(ekv.Memstore)
    	return &Session{kv: NewVersionedKV(store)}
    
    }