diff --git a/e2e/ratchet/interface.go b/e2e/ratchet/interface.go index 889dba56feede2f1953dfb7c03ba1224533f5ee4..4e1bb580bf4266eb7791426043d75ec48356ae3f 100644 --- a/e2e/ratchet/interface.go +++ b/e2e/ratchet/interface.go @@ -2,17 +2,22 @@ package ratchet import ( "github.com/cloudflare/circl/dh/sidh" + "gitlab.com/elixxir/client/e2e/ratchet/partner" "gitlab.com/elixxir/client/e2e/ratchet/partner/session" "gitlab.com/elixxir/client/network/message" "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/xx_network/primitives/id" ) -type Ratchet interface { +type Ratchet2 interface { + // AddPartner adds a partner. Automatically creates both send and receive + // sessions using the passed cryptographic data and per the parameters sent + // AddPartner(partnerID *id.ID, partnerPubKey, myPrivKey *cyclic.Int, partnerSIDHPubKey *sidh.PublicKey, mySIDHPrivKey *sidh.PrivateKey, sendParams, receiveParams session.Params) - GetPartner(partnerID *id.ID) (*Manager, error) + + GetPartner(partnerID *id.ID) (*partner.Manager, error) DeletePartner(partnerId *id.ID) GetAllPartnerIDs() []*id.ID GetDHPrivateKey() *cyclic.Int diff --git a/e2e/ratchet/partner/manager.go b/e2e/ratchet/partner/manager.go index d9643ca39dc4b4051d6681f10414735e3168f010..f32c5224fdc9d9b72b7f0aba01b72024b31d7477 100644 --- a/e2e/ratchet/partner/manager.go +++ b/e2e/ratchet/partner/manager.go @@ -90,7 +90,7 @@ func NewManager(kv *versioned.KV, myID, partnerID *id.ID, myPrivKey, return m } -//loads a relationship and all buffers and sessions from disk +//LoadManager loads a relationship and all buffers and sessions from disk func LoadManager(kv *versioned.KV, myID, partnerID *id.ID, cyHandler session.CypherHandler, grp *cyclic.Group, rng *fastRNG.StreamGenerator) (*Manager, error) { diff --git a/e2e/ratchet/partner/relationship.go b/e2e/ratchet/partner/relationship.go index 571f255d1d5d47dae69430f97d7e0f1f67b21a26..9f080d7c9fb998b2153713901b177e778ccb9c0c 100644 --- a/e2e/ratchet/partner/relationship.go +++ b/e2e/ratchet/partner/relationship.go @@ -58,6 +58,7 @@ type ServiceHandler interface { // fixme - this is weird becasue it creates the relationsip and the session. // Should be refactored to create an empty relationship, with a second call // adding the session +// todo - doscstring func NewRelationship(kv *versioned.KV, t session.RelationshipType, myID, partnerID *id.ID, myOriginPrivateKey, partnerOriginPublicKey *cyclic.Int, originMySIDHPrivKey *sidh.PrivateKey, @@ -110,6 +111,7 @@ func NewRelationship(kv *versioned.KV, t session.RelationshipType, return r } +// todo - doscstring func LoadRelationship(kv *versioned.KV, t session.RelationshipType, myID, partnerID *id.ID, cyHandler session.CypherHandler, grp *cyclic.Group, rng *fastRNG.StreamGenerator) (*relationship, error) { @@ -223,6 +225,7 @@ func (r *relationship) unmarshal(b []byte) error { return nil } +// todo - doscstring func (r *relationship) Delete() { r.mux.Lock() defer r.mux.Unlock() @@ -232,6 +235,7 @@ func (r *relationship) Delete() { } } +// todo - doscstring func (r *relationship) AddSession(myPrivKey, partnerPubKey, baseKey *cyclic.Int, mySIDHPrivKey *sidh.PrivateKey, partnerSIDHPubKey *sidh.PublicKey, trigger session.SessionID, negotiationStatus session.Negotiation, @@ -252,12 +256,14 @@ func (r *relationship) AddSession(myPrivKey, partnerPubKey, baseKey *cyclic.Int, return s } +// todo - doscstring func (r *relationship) addSession(s *session.Session) { r.sessions = append([]*session.Session{s}, r.sessions...) r.sessionByID[s.GetID()] = s return } +// todo - doscstring func (r *relationship) GetNewest() *session.Session { r.mux.RLock() defer r.mux.RUnlock() @@ -328,6 +334,7 @@ func (r *relationship) getSessionForSending() *session.Session { return nil } +// todo - doscstring // returns a list of session that need rekeys. Nil instances mean a new rekey // from scratch func (r *relationship) TriggerNegotiation() []*session.Session { @@ -386,12 +393,14 @@ func (r *relationship) getNewestRekeyableSession() *session.Session { return unconfirmed } +// todo - doscstring func (r *relationship) GetByID(id session.SessionID) *session.Session { r.mux.RLock() defer r.mux.RUnlock() return r.sessionByID[id] } +// todo - doscstring // sets the passed session ID as confirmed. Call "GetSessionRotation" after // to get any sessions that are to be deleted and then "DeleteSession" to // remove them @@ -420,6 +429,7 @@ func (r *relationship) getInternalBufferShallowCopy() []*session.Session { return r.sessions } +// todo - doscstring func (r *relationship) clean() { numConfirmed := uint(0) diff --git a/e2e/ratchet/partner/session/session.go b/e2e/ratchet/partner/session/session.go index 9b0543ac70ceb803a946683db443ab3f46230545..33970009fc6d92ed6bbe0db02385ba57e52fc155 100644 --- a/e2e/ratchet/partner/session/session.go +++ b/e2e/ratchet/partner/session/session.go @@ -182,7 +182,7 @@ func NewSession(kv *versioned.KV, t RelationshipType, partner *id.ID, myPrivKey, return session } -// Load session and state vector from kv and populate runtime fields +// LoadSession and state vector from kv and populate runtime fields func LoadSession(kv *versioned.KV, sessionID SessionID, relationshipFingerprint []byte, cyHandler CypherHandler, grp *cyclic.Group, rng *fastRNG.StreamGenerator) (*Session, error) { @@ -220,6 +220,7 @@ func LoadSession(kv *versioned.KV, sessionID SessionID, return &session, nil } +// todo - doscstring func (s *Session) Save() error { now := netTime.Now() @@ -404,7 +405,8 @@ func (s *Session) unmarshal(b []byte) error { } //key usage -// Pops the first unused key, skipping any which are denoted as used. + +// Popkey Pops the first unused key, skipping any which are denoted as used. // will return if the remaining keys are designated as rekeys func (s *Session) PopKey() (*Cypher, error) { if s.keyState.GetNumAvailable() <= uint32(s.e2eParams.NumRekeys) { @@ -428,6 +430,7 @@ func (s *Session) PopReKey() (*Cypher, error) { return newKey(s, keyNum), nil } +// todo - doscstring func (s *Session) GetRelationshipFingerprint() []byte { return s.relationshipFingerprint } @@ -476,12 +479,14 @@ var legalStateChanges = [][]bool{ {false, false, true, false, false, false}, // NewCreat } +// todo - doscstring func (s *Session) SetNegotiationStatus(status Negotiation) { if err := s.TrySetNegotiationStatus(status); err != nil { jww.FATAL.Panicf("Failed to set Negotiation status: %s", err) } } +// todo - doscstring func (s *Session) TrySetNegotiationStatus(status Negotiation) error { s.mux.Lock() defer s.mux.Unlock() @@ -512,7 +517,7 @@ func (s *Session) TrySetNegotiationStatus(status Negotiation) error { return nil } -// This function, in a mostly thread safe manner, checks if the session needs a +// TriggerNegotiation in a mostly thread safe manner, checks if the session needs a // negotiation, returns if it does while updating the session to denote the // negotiation was triggered // WARNING: This function relies on proper action by the caller for data safety. @@ -578,20 +583,21 @@ func (s *Session) TriggerNegotiation() bool { return false } -// checks if the session has been confirmed +// NegotiationStatus checks if the session has been confirmed func (s *Session) NegotiationStatus() Negotiation { s.mux.RLock() defer s.mux.RUnlock() return s.negotiationStatus } -// checks if the session has been confirmed +// IsConfirmed checks if the session has been confirmed func (s *Session) IsConfirmed() bool { c := s.NegotiationStatus() //fmt.Println(c) return c >= Confirmed } +// todo - doscstring func (s *Session) String() string { partner := s.GetPartner() if partner != nil { @@ -607,6 +613,7 @@ func (s *Session) useKey(keynum uint32) { s.keyState.Use(keynum) } +// todo - doscstring // finalizeKeyNegotiation generates keys from the base data stored in the session object. // myPrivKey will be generated if not present func (s *Session) finalizeKeyNegotiation() { @@ -635,6 +642,7 @@ func (s *Session) finalizeKeyNegotiation() { s.sID = GetSessionIDFromBaseKey(s.baseKey) } +// todo - doscstring func (s *Session) buildChildKeys() { p := s.e2eParams h, _ := hash.NewCMixHash() @@ -687,6 +695,7 @@ func MakeSessionPrefix(sid SessionID) string { return fmt.Sprintf(sessionPrefix, sid) } +// todo - doscstring func decideIfResendRekey(genRng *fastRNG.StreamGenerator, ratio float64) bool { stream := genRng.GetStream() b := make([]byte, 8) diff --git a/e2e/ratchet/serviceList.go b/e2e/ratchet/serviceList.go index 3f4d2747c4f481f42e3d417df6dee1d707a7f525..1f6fb32e824e9ada47a5ea2ebf9ff33abd10a6bf 100644 --- a/e2e/ratchet/serviceList.go +++ b/e2e/ratchet/serviceList.go @@ -15,53 +15,53 @@ type Services interface { processor message.Processor) } -func (s *Store) add(m *partner.Manager) { - s.servicesmux.RLock() - defer s.servicesmux.RUnlock() - for tag, process := range s.services { - s.sInteface.AddService(s.myID, m.MakeService(tag), process) +func (r *Ratchet) add(m *partner.Manager) { + r.servicesmux.RLock() + defer r.servicesmux.RUnlock() + for tag, process := range r.services { + r.sInteface.AddService(r.myID, m.MakeService(tag), process) } } -func (s *Store) delete(m *partner.Manager) { - s.servicesmux.RLock() - defer s.servicesmux.RUnlock() - for tag, process := range s.services { - s.sInteface.DeleteService(s.myID, m.MakeService(tag), process) +func (r *Ratchet) delete(m *partner.Manager) { + r.servicesmux.RLock() + defer r.servicesmux.RUnlock() + for tag, process := range r.services { + r.sInteface.DeleteService(r.myID, m.MakeService(tag), process) } } -func (s *Store) AddService(tag string, processor message.Processor) error { - s.servicesmux.Lock() - defer s.servicesmux.Unlock() +func (r *Ratchet) AddService(tag string, processor message.Processor) error { + r.servicesmux.Lock() + defer r.servicesmux.Unlock() //add the services to the list - if _, exists := s.services[tag]; exists { - return errors.Errorf("Cannot add more than one service '%s'", tag) + if _, exists := r.services[tag]; exists { + return errors.Errorf("Cannot add more than one service '%r'", tag) } - s.services[tag] = processor + r.services[tag] = processor //add a service for every manager - for _, m := range s.managers { - s.sInteface.AddService(s.myID, m.MakeService(tag), processor) + for _, m := range r.managers { + r.sInteface.AddService(r.myID, m.MakeService(tag), processor) } return nil } -func (s *Store) RemoveService(tag string) error { - s.servicesmux.Lock() - defer s.servicesmux.Unlock() +func (r *Ratchet) RemoveService(tag string) error { + r.servicesmux.Lock() + defer r.servicesmux.Unlock() - oldServiceProcess, exists := s.services[tag] + oldServiceProcess, exists := r.services[tag] if !exists { return errors.Errorf("Cannot remove a service that doesnt "+ - "exist: '%s'", tag) + "exist: '%r'", tag) } - delete(s.services, tag) + delete(r.services, tag) - for _, m := range s.managers { - s.sInteface.DeleteService(s.myID, m.MakeService(tag), oldServiceProcess) + for _, m := range r.managers { + r.sInteface.DeleteService(r.myID, m.MakeService(tag), oldServiceProcess) } return nil diff --git a/e2e/ratchet/standardServices.go b/e2e/ratchet/standardServices.go new file mode 100644 index 0000000000000000000000000000000000000000..0d28c336b789e6ba182fcbb7c85a04fceed06f2e --- /dev/null +++ b/e2e/ratchet/standardServices.go @@ -0,0 +1,4 @@ +package ratchet + +const Silent = "silent" +const E2e = "e2e" diff --git a/e2e/ratchet/store.go b/e2e/ratchet/store.go index 193b05dc8038042e7da42b4c6b839017ec1fd62f..0cf1ca902210122ab812113ddc3a7c28c57f6570 100644 --- a/e2e/ratchet/store.go +++ b/e2e/ratchet/store.go @@ -28,16 +28,14 @@ import ( const ( currentStoreVersion = 0 packagePrefix = "e2eSession" - storeKey = "Store" + storeKey = "Ratchet" pubKeyKey = "DhPubKey" privKeyKey = "DhPrivKey" - sidhPubKeyKey = "SidhPubKey" - sidhPrivKeyKey = "SidhPrivKey" ) var NoPartnerErrorStr = "No relationship with partner found" -type Store struct { +type Ratchet struct { managers map[id.ID]*partner.Manager mux sync.RWMutex @@ -57,17 +55,23 @@ type Store struct { kv *versioned.KV } -func NewStore(kv *versioned.KV, privKey *cyclic.Int, +// NewRatchet creates a new store for the passed user id and private key. +// The store can then be accessed by calling LoadStore. +// Does not create at a unique prefix, if multiple Ratchets are needed, make +// sure to add a uint prefix to the KV before instantiation. +func NewRatchet(kv *versioned.KV, privKey *cyclic.Int, myID *id.ID, grp *cyclic.Group, cyHandler session.CypherHandler, - rng *fastRNG.StreamGenerator) (*Store, error) { + services Services, rng *fastRNG.StreamGenerator) error { + // Generate public key pubKey := diffieHellman.GeneratePublicKey(privKey, grp) // Modify the prefix of the KV kv = kv.Prefix(packagePrefix) - s := &Store{ + r := &Ratchet{ managers: make(map[id.ID]*partner.Manager), + services: make(map[string]message.Processor), myID: myID, dhPrivateKey: privKey, @@ -78,30 +82,33 @@ func NewStore(kv *versioned.KV, privKey *cyclic.Int, cyHandler: cyHandler, grp: grp, rng: rng, + sInteface: services, } err := util.StoreCyclicKey(kv, pubKey, pubKeyKey) if err != nil { - return nil, errors.WithMessage(err, + return errors.WithMessage(err, "Failed to store e2e DH public key") } err = util.StoreCyclicKey(kv, privKey, privKeyKey) if err != nil { - return nil, errors.WithMessage(err, + return errors.WithMessage(err, "Failed to store e2e DH private key") } - return s, s.save() + return r.save() } -func LoadStore(kv *versioned.KV, myID *id.ID, grp *cyclic.Group, - cyHandler session.CypherHandler, rng *fastRNG.StreamGenerator) ( - *Store, error) { +// LoadRatchet loads an extant ratchet from disk +func LoadRatchet(kv *versioned.KV, myID *id.ID, grp *cyclic.Group, + cyHandler session.CypherHandler, services Services, rng *fastRNG.StreamGenerator) ( + *Ratchet, error) { kv = kv.Prefix(packagePrefix) - s := &Store{ + r := &Ratchet{ managers: make(map[id.ID]*partner.Manager), + services: make(map[string]message.Processor), myID: myID, @@ -110,6 +117,7 @@ func LoadStore(kv *versioned.KV, myID *id.ID, grp *cyclic.Group, cyHandler: cyHandler, grp: grp, rng: rng, + sInteface: services, } obj, err := kv.Get(storeKey, currentStoreVersion) @@ -117,18 +125,28 @@ func LoadStore(kv *versioned.KV, myID *id.ID, grp *cyclic.Group, return nil, err } - err = s.unmarshal(obj.Data) + err = r.unmarshal(obj.Data) if err != nil { return nil, err } - return s, nil + // add standard services + if err = r.AddService(Silent, nil); err != nil { + jww.FATAL.Panicf("Could not add standard %r "+ + "service: %+v", Silent, err) + } + if err = r.AddService(E2e, nil); err != nil { + jww.FATAL.Panicf("Could not add standard %r "+ + "service: %+v", E2e, err) + } + + return r, nil } -func (s *Store) save() error { +func (r *Ratchet) save() error { now := netTime.Now() - data, err := s.marshal() + data, err := r.marshal() if err != nil { return err } @@ -139,59 +157,69 @@ func (s *Store) save() error { Data: data, } - return s.kv.Set(storeKey, currentStoreVersion, &obj) + return r.kv.Set(storeKey, currentStoreVersion, &obj) } -func (s *Store) AddPartner(partnerID *id.ID, partnerPubKey, +// AddPartner adds a partner. Automatically creates both send and receive +// sessions using the passed cryptographic data and per the parameters sent +func (r *Ratchet) AddPartner(partnerID *id.ID, partnerPubKey, myPrivKey *cyclic.Int, partnerSIDHPubKey *sidh.PublicKey, mySIDHPrivKey *sidh.PrivateKey, sendParams, - receiveParams session.Params) error { - s.mux.Lock() - defer s.mux.Unlock() + receiveParams session.Params) (*partner.Manager, error) { + r.mux.Lock() + defer r.mux.Unlock() - jww.INFO.Printf("Adding Partner %s:\n\tMy Private Key: %s"+ - "\n\tPartner Public Key: %s", + jww.INFO.Printf("Adding Partner %r:\n\tMy Private Key: %r"+ + "\n\tPartner Public Key: %r", partnerID, myPrivKey.TextVerbose(16, 0), partnerPubKey.TextVerbose(16, 0)) - if _, ok := s.managers[*partnerID]; ok { - return errors.New("Cannot overwrite existing partner") + if _, ok := r.managers[*partnerID]; ok { + return nil, errors.New("Cannot overwrite existing partner") } - m := partner.NewManager(s.kv, s.myID, partnerID, myPrivKey, partnerPubKey, + m := partner.NewManager(r.kv, r.myID, partnerID, myPrivKey, partnerPubKey, mySIDHPrivKey, partnerSIDHPubKey, - sendParams, receiveParams, s.cyHandler, s.grp, s.rng) + sendParams, receiveParams, r.cyHandler, r.grp, r.rng) - s.managers[*partnerID] = m - if err := s.save(); err != nil { - jww.FATAL.Printf("Failed to add Partner %s: Save of store failed: %s", + r.managers[*partnerID] = m + if err := r.save(); err != nil { + jww.FATAL.Printf("Failed to add Partner %r: Save of store failed: %r", partnerID, err) } - return nil + //add services for the manager + r.add(m) + + return m, nil } // DeletePartner removes the associated contact from the E2E store -func (s *Store) DeletePartner(partnerId *id.ID) error { - m, ok := s.managers[*partnerId] +func (r *Ratchet) DeletePartner(partnerId *id.ID) error { + m, ok := r.managers[*partnerId] if !ok { return errors.New(NoPartnerErrorStr) } - if err := partner.ClearManager(m, s.kv); err != nil { - return errors.WithMessagef(err, "Could not remove partner %s from store", partnerId) + if err := partner.ClearManager(m, r.kv); err != nil { + return errors.WithMessagef(err, "Could not remove partner %r from store", partnerId) } - delete(s.managers, *partnerId) - return s.save() + //delete services + r.delete(m) + + delete(r.managers, *partnerId) + return r.save() + } -func (s *Store) GetPartner(partnerID *id.ID) (*partner.Manager, error) { - s.mux.RLock() - defer s.mux.RUnlock() +// GetPartner returns the partner per its ID, if it exists +func (r *Ratchet) GetPartner(partnerID *id.ID) (*partner.Manager, error) { + r.mux.RLock() + defer r.mux.RUnlock() - m, ok := s.managers[*partnerID] + m, ok := r.managers[*partnerID] if !ok { return nil, errors.New(NoPartnerErrorStr) @@ -202,13 +230,13 @@ func (s *Store) GetPartner(partnerID *id.ID) (*partner.Manager, error) { // GetAllPartnerIDs returns a list of all partner IDs that the user has // an E2E relationship with. -func (s *Store) GetAllPartnerIDs() []*id.ID { - s.mux.RLock() - defer s.mux.RUnlock() +func (r *Ratchet) GetAllPartnerIDs() []*id.ID { + r.mux.RLock() + defer r.mux.RUnlock() - partnerIds := make([]*id.ID, 0, len(s.managers)) + partnerIds := make([]*id.ID, 0, len(r.managers)) - for partnerId := range s.managers { + for partnerId := range r.managers { partnerIds = append(partnerIds, &partnerId) } @@ -216,21 +244,21 @@ func (s *Store) GetAllPartnerIDs() []*id.ID { } // GetDHPrivateKey returns the diffie hellman private key. -func (s *Store) GetDHPrivateKey() *cyclic.Int { - return s.dhPrivateKey +func (r *Ratchet) GetDHPrivateKey() *cyclic.Int { + return r.dhPrivateKey } // GetDHPublicKey returns the diffie hellman public key. -func (s *Store) GetDHPublicKey() *cyclic.Int { - return s.dhPublicKey +func (r *Ratchet) GetDHPublicKey() *cyclic.Int { + return r.dhPublicKey } // ekv functions -func (s *Store) marshal() ([]byte, error) { - contacts := make([]id.ID, len(s.managers)) +func (r *Ratchet) marshal() ([]byte, error) { + contacts := make([]id.ID, len(r.managers)) index := 0 - for partnerID := range s.managers { + for partnerID := range r.managers { contacts[index] = partnerID index++ } @@ -238,7 +266,7 @@ func (s *Store) marshal() ([]byte, error) { return json.Marshal(&contacts) } -func (s *Store) unmarshal(b []byte) error { +func (r *Ratchet) unmarshal(b []byte) error { var contacts []id.ID @@ -253,29 +281,32 @@ func (s *Store) unmarshal(b []byte) error { partnerID := (&contacts[i]).DeepCopy() // Load the relationship. The relationship handles adding the fingerprints via the // context object - manager, err := partner.LoadManager(s.kv, s.myID, partnerID, - s.cyHandler, s.grp, s.rng) + manager, err := partner.LoadManager(r.kv, r.myID, partnerID, + r.cyHandler, r.grp, r.rng) if err != nil { - jww.FATAL.Panicf("Failed to load relationship for partner %s: %s", + jww.FATAL.Panicf("Failed to load relationship for partner %r: %r", partnerID, err.Error()) } if !manager.GetPartnerID().Cmp(partnerID) { jww.FATAL.Panicf("Loaded a manager with the wrong partner "+ - "ID: \n\t loaded: %s \n\t present: %s", + "ID: \n\t loaded: %r \n\t present: %r", partnerID, manager.GetPartnerID()) } - s.managers[*partnerID] = manager + //add services for the manager + r.add(manager) + + r.managers[*partnerID] = manager } - s.dhPrivateKey, err = util.LoadCyclicKey(s.kv, privKeyKey) + r.dhPrivateKey, err = util.LoadCyclicKey(r.kv, privKeyKey) if err != nil { return errors.WithMessage(err, "Failed to load e2e DH private key") } - s.dhPublicKey, err = util.LoadCyclicKey(s.kv, pubKeyKey) + r.dhPublicKey, err = util.LoadCyclicKey(r.kv, pubKeyKey) if err != nil { return errors.WithMessage(err, "Failed to load e2e DH public key") diff --git a/e2e/ratchet/store_test.go b/e2e/ratchet/store_test.go index feacc60c94494df0d02af10d81153a2d147b7903..53cd33181ff12e240d09d0c84ba6e2cc7354b6ee 100644 --- a/e2e/ratchet/store_test.go +++ b/e2e/ratchet/store_test.go @@ -39,7 +39,7 @@ func TestNewStore(t *testing.T) { fingerprints := newFingerprints() rng := fastRNG.NewStreamGenerator(12, 3, csprng.NewSystemRNG) e2eP := params.GetDefaultE2ESessionParams() - expectedStore := &Store{ + expectedStore := &Ratchet{ managers: make(map[id.ID]*partner.Manager), dhPrivateKey: privKey, dhPublicKey: diffieHellman.GeneratePublicKey(privKey, grp), @@ -65,18 +65,18 @@ func TestNewStore(t *testing.T) { } if !reflect.DeepEqual(expectedStore, store) { - t.Errorf("NewStore() returned incorrect Store."+ + t.Errorf("NewStore() returned incorrect Ratchet."+ "\n\texpected: %+v\n\treceived: %+v", expectedStore, store) } key, err := expectedStore.kv.Get(storeKey, 0) if err != nil { - t.Errorf("get() error when getting Store from KV: %v", err) + t.Errorf("get() error when getting Ratchet from KV: %v", err) } if !bytes.Equal(expectedData, key.Data) { - t.Errorf("NewStore() returned incorrect Store."+ + t.Errorf("NewStore() returned incorrect Ratchet."+ "\n\texpected: %+v\n\treceived: %+v", expectedData, key.Data) } @@ -92,13 +92,13 @@ func TestLoadStore(t *testing.T) { } if !reflect.DeepEqual(expectedStore, store) { - t.Errorf("LoadStore() returned incorrect Store."+ + t.Errorf("LoadStore() returned incorrect Ratchet."+ "\n\texpected: %#v\n\treceived: %#v", expectedStore, store) } } -// Tests happy path of Store.AddPartner. +// Tests happy path of Ratchet.AddPartner. func TestStore_AddPartner(t *testing.T) { rng := csprng.NewSystemRNG() s, _, _ := makeTestStore() @@ -164,7 +164,7 @@ func TestStore_DeletePartner(t *testing.T) { } -// Tests happy path of Store.GetPartner. +// Tests happy path of Ratchet.GetPartner. func TestStore_GetPartner(t *testing.T) { rng := csprng.NewSystemRNG() s, _, _ := makeTestStore() @@ -189,7 +189,7 @@ func TestStore_GetPartner(t *testing.T) { } } -// Tests that Store.GetPartner returns an error for non existent partnerID. +// Tests that Ratchet.GetPartner returns an error for non existent partnerID. func TestStore_GetPartner_Error(t *testing.T) { s, _, _ := makeTestStore() partnerID := id.NewIdFromUInt(rand.Uint64(), id.User, t) @@ -205,7 +205,7 @@ func TestStore_GetPartner_Error(t *testing.T) { } } -// Tests happy path of Store.GetPartnerContact. +// Tests happy path of Ratchet.GetPartnerContact. func TestStore_GetPartnerContact(t *testing.T) { s, _, _ := makeTestStore() partnerID := id.NewIdFromUInt(rand.Uint64(), id.User, t) @@ -233,7 +233,7 @@ func TestStore_GetPartnerContact(t *testing.T) { } } -// Tests that Store.GetPartnerContact returns an error for non existent partnerID. +// Tests that Ratchet.GetPartnerContact returns an error for non existent partnerID. func TestStore_GetPartnerContact_Error(t *testing.T) { s, _, _ := makeTestStore() partnerID := id.NewIdFromUInt(rand.Uint64(), id.User, t) @@ -245,7 +245,7 @@ func TestStore_GetPartnerContact_Error(t *testing.T) { } } -// Tests happy path of Store.PopKey. +// Tests happy path of Ratchet.PopKey. func TestStore_PopKey(t *testing.T) { s, _, _ := makeTestStore() se, _ := session.makeTestSession() @@ -279,7 +279,7 @@ func TestStore_PopKey(t *testing.T) { } } -// Tests happy path of Store.CheckKey. +// Tests happy path of Ratchet.CheckKey. func TestStore_CheckKey(t *testing.T) { s, _, _ := makeTestStore() se, _ := session.makeTestSession() @@ -303,7 +303,7 @@ func TestStore_CheckKey(t *testing.T) { } } -// Tests happy path of Store.GetDHPrivateKey. +// Tests happy path of Ratchet.GetDHPrivateKey. func TestStore_GetDHPrivateKey(t *testing.T) { s, _, _ := makeTestStore() @@ -314,7 +314,7 @@ func TestStore_GetDHPrivateKey(t *testing.T) { } } -// Tests happy path of Store.GetDHPublicKey. +// Tests happy path of Ratchet.GetDHPublicKey. func TestStore_GetDHPublicKey(t *testing.T) { s, _, _ := makeTestStore() @@ -325,7 +325,7 @@ func TestStore_GetDHPublicKey(t *testing.T) { } } -// Tests happy path of Store.GetGroup. +// Tests happy path of Ratchet.GetGroup. func TestStore_GetGroup(t *testing.T) { s, _, _ := makeTestStore() @@ -382,7 +382,7 @@ func TestFingerprints_remove(t *testing.T) { } } -func makeTestStore() (*Store, *versioned.KV, *fastRNG.StreamGenerator) { +func makeTestStore() (*Ratchet, *versioned.KV, *fastRNG.StreamGenerator) { grp := cyclic.NewGroup(large.NewInt(107), large.NewInt(2)) privKey := grp.NewInt(57) kv := versioned.NewKV(make(ekv.Memstore)) diff --git a/network/interface.go b/network/interface.go index 3d45710cde447dc85adf39ecbdb798ef8ff8b403..62f2425c4c6d740fe64f09a0f6a8706a3fcdb771 100644 --- a/network/interface.go +++ b/network/interface.go @@ -145,6 +145,11 @@ type Manager interface { // notifications. // source - A byte buffer of related data. Generally used in notifications. // Example: Sender ID + // There can be multiple "default" services, the must use the "default" tag + // and the identifier must be the client reception ID. + // A service may have a nil response unless it is default. In general a + // nil service is used to detect notifications when pickup is done by + // fingerprints AddService(AddService *id.ID, newService message.Service, response message.Processor) @@ -152,6 +157,7 @@ type Manager interface { // associated with the preimage, the entire preimage is removed. If there is // more than one response, only the given response is removed. If nil is // passed in for response, all triggers for the preimage will be removed. + // The processor is only used in deletion when deleting a default service DeleteService(clientID *id.ID, toDelete message.Service, processor message.Processor) diff --git a/network/message/handler.go b/network/message/handler.go index 687f68544c3413f452e9deda1b77d18515995f72..26ca4d8b1e640ec5c1cba84f1ba16bd411a680a9 100644 --- a/network/message/handler.go +++ b/network/message/handler.go @@ -81,7 +81,8 @@ func (p *handler) handleMessage(ecrMsg format.Message, bundle Bundle) bool { go t.Process(ecrMsg, identity, round) } if len(services) == 0 { - jww.ERROR.Printf("empty service list for %s", ecrMsg.GetSIH()) + jww.WARN.Printf("empty service list for %s: %s", + ecrMsg.Digest(), ecrMsg.GetSIH()) } return true } else { diff --git a/network/message/services.go b/network/message/services.go index 3a9ca471dbb07fffddca01bd5ed2b86412a6c27c..4fd062d92f9a7d77af97fef30e89e59fa1c4c716 100644 --- a/network/message/services.go +++ b/network/message/services.go @@ -80,8 +80,13 @@ func (sm *ServicesManager) get(clientID *id.ID, receivedSIH, // Check if the SIH matches this service if s.ForMe(ecrMsgContents, receivedSIH) { if s.defaultList == nil && s.Tag != sih.Default { + //skip if the processor is nil + if s.Processor != nil { + return []Processor{}, true + } // Return this service directly if not the default service return []Processor{s}, true + } else if s.defaultList != nil { // If it is default and the default list is not empty, then // return the default list @@ -104,6 +109,9 @@ func (sm *ServicesManager) get(clientID *id.ID, receivedSIH, // type - a descriptive string of the service. Generally used in notifications // source - a byte buffer of related data. Generally used in notifications. // Example: Sender ID +// There can be multiple "default" services, the must use the "default" tag +// and the identifier must be the client reception ID. +// A service may have a nil response unless it is default. func (sm *ServicesManager) AddService(clientID *id.ID, newService Service, response Processor) { sm.Lock()