feature(messenger): RequestContactInfoFromMailserver (#3376)

This commit is contained in:
Igor Sirotin 2023-04-05 23:25:44 +03:00 committed by GitHub
parent 5577679733
commit fb36298e37
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 134 additions and 14 deletions

View File

@ -144,6 +144,9 @@ type Messenger struct {
requestedCommunitiesLock sync.RWMutex
requestedCommunities map[string]*transport.Filter
requestedContactsLock sync.RWMutex
requestedContacts map[string]*transport.Filter
connectionState connection.State
telemetryClient *telemetry.Client
contractMaker *contracts.ContractMaker
@ -478,6 +481,8 @@ func NewMessenger(
cancel: cancel,
requestedCommunitiesLock: sync.RWMutex{},
requestedCommunities: make(map[string]*transport.Filter),
requestedContactsLock: sync.RWMutex{},
requestedContacts: make(map[string]*transport.Filter),
importingCommunities: make(map[string]bool),
browserDatabase: c.browserDatabase,
httpServer: c.httpServer,
@ -3351,9 +3356,11 @@ func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filte
senderID := contactIDFromPublicKey(publicKey)
// Check for messages from blocked users
if contact, ok := messageState.AllContacts.Load(senderID); ok && contact.Blocked {
continue
if _, ok := m.requestedContacts[senderID]; !ok {
// Check for messages from blocked users
if contact, ok := messageState.AllContacts.Load(senderID); ok && contact.Blocked {
continue
}
}
// Don't process duplicates
@ -3379,6 +3386,7 @@ func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filte
}
contact = c
messageState.AllContacts.Store(senderID, contact)
m.forgetContactInfoRequest(senderID)
}
messageState.CurrentMessageState = &CurrentMessageState{
MessageID: messageID,
@ -3846,6 +3854,8 @@ func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filte
}
case protobuf.ContactUpdate:
logger.Info("<<< ContactUpdate", zap.String("publicKey", senderID))
if common.IsPubKeyEqual(messageState.CurrentMessageState.PublicKey, &m.identity.PublicKey) {
logger.Warn("coming from us, ignoring")
continue
@ -3859,6 +3869,8 @@ func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filte
allMessagesProcessed = false
continue
}
m.forgetContactInfoRequest(senderID)
case protobuf.AcceptContactRequest:
logger.Debug("Handling AcceptContactRequest")
message := msg.ParsedMessage.Interface().(protobuf.AcceptContactRequest)

View File

@ -4,6 +4,7 @@ import (
"context"
"crypto/ecdsa"
"errors"
"time"
"github.com/golang/protobuf/proto"
"go.uber.org/zap"
@ -326,16 +327,13 @@ func (m *Messenger) addContact(pubKey, ensName, nickname, displayName, contactRe
return nil, err
}
// Fetch contact code
publicKey, err := contact.PublicKey()
if err != nil {
return nil, err
}
filter, err := m.transport.JoinPrivate(publicKey)
if err != nil {
return nil, err
}
_, err = m.scheduleSyncFilters([]*transport.Filter{filter})
// Fetch contact code
_, err = m.scheduleSyncFiltersForContact(publicKey)
if err != nil {
return nil, err
}
@ -989,18 +987,124 @@ func (m *Messenger) BuildContact(request *requests.BuildContact) (*Contact, erro
}
// Schedule sync filter to fetch information about the contact
publicKey, err := contact.PublicKey()
if err != nil {
return nil, err
}
filter, err := m.transport.JoinPrivate(publicKey)
if err != nil {
return nil, err
}
_, err = m.scheduleSyncFilters([]*transport.Filter{filter})
_, err = m.scheduleSyncFiltersForContact(publicKey)
if err != nil {
return nil, err
}
return contact, nil
}
func (m *Messenger) scheduleSyncFiltersForContact(publicKey *ecdsa.PublicKey) (*transport.Filter, error) {
filter, err := m.transport.JoinPrivate(publicKey)
if err != nil {
return nil, err
}
_, err = m.scheduleSyncFilters([]*transport.Filter{filter})
if err != nil {
return filter, err
}
return filter, nil
}
func (m *Messenger) RequestContactInfoFromMailserver(pubkey string, waitForResponse bool) (*Contact, error) {
err := m.requestContactInfoFromMailserver(pubkey)
if err != nil {
return nil, err
}
if !waitForResponse {
return nil, nil
}
ctx := context.Background()
ctx, cancel := context.WithTimeout(ctx, 15*time.Second)
defer cancel()
var contact *Contact
fetching := true
for fetching {
select {
case <-time.After(200 * time.Millisecond):
var ok bool
contact, ok = m.allContacts.Load(pubkey)
if ok && contact != nil && contact.DisplayName != "" {
fetching = false
m.logger.Info("contact info received", zap.String("pubkey", contact.ID))
}
case <-ctx.Done():
fetching = false
}
}
m.forgetContactInfoRequest(pubkey)
return contact, nil
}
func (m *Messenger) requestContactInfoFromMailserver(pubkey string) error {
m.requestedContactsLock.Lock()
defer m.requestedContactsLock.Unlock()
if _, ok := m.requestedContacts[pubkey]; ok {
return nil
}
m.logger.Debug("requesting contact info from mailserver", zap.String("publicKey", pubkey))
c, err := buildContactFromPkString(pubkey)
if err != nil {
return err
}
publicKey, err := c.PublicKey()
if err != nil {
return err
}
var filter *transport.Filter
filter, err = m.scheduleSyncFiltersForContact(publicKey)
if err != nil {
return err
}
m.requestedContacts[pubkey] = filter
return nil
}
func (m *Messenger) forgetContactInfoRequest(publicKey string) {
m.requestedContactsLock.Lock()
defer m.requestedContactsLock.Unlock()
filter, ok := m.requestedContacts[publicKey]
if !ok {
return
}
m.logger.Debug("forgetting contact info request", zap.String("publicKey", publicKey))
err := m.transport.RemoveFilters([]*transport.Filter{filter})
if err != nil {
m.logger.Warn("failed to remove filter", zap.Error(err))
}
delete(m.requestedContacts, publicKey)
}

View File

@ -334,6 +334,10 @@ func (api *PublicAPI) GetContactByID(parent context.Context, id string) *protoco
return api.service.messenger.GetContactByID(id)
}
func (api *PublicAPI) RequestContactInfoFromMailserver(pubkey string) (*protocol.Contact, error) {
return api.service.messenger.RequestContactInfoFromMailserver(pubkey, true)
}
func (api *PublicAPI) RemoveFilters(parent context.Context, chats []*transport.Filter) error {
return api.service.messenger.RemoveFilters(chats)
}