Check for mobile data connection if setting is on (#5511)

* feat_: Check for mobile data connection if setting is on

* fix_: check code control flag inside  asyncRequestAllHistoricMessages

---------

Co-authored-by: Igor Sirotin <sirotin@status.im>
This commit is contained in:
Andrea Maria Piana 2024-07-26 23:34:57 +02:00 committed by GitHub
parent 4ddf9f2727
commit 3cc4767638
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 322 additions and 11 deletions

View File

@ -767,6 +767,14 @@ func (db *Database) SetPeerSyncingEnabled(value bool) error {
return db.SaveSettingField(PeerSyncingEnabled, value)
}
func (db *Database) SetSyncingOnMobileNetwork(value bool) error {
err := db.SaveSettingField(SyncingOnMobileNetwork, value)
if err != nil {
return err
}
return db.SaveSettingField(RememberSyncingChoice, true)
}
func (db *Database) GetPeerSyncingEnabled() (result bool, err error) {
err = db.makeSelectRow(PeerSyncingEnabled).Scan(&result)
if err == sql.ErrNoRows {

View File

@ -50,6 +50,7 @@ type DatabaseSettingsManager interface {
SetUseMailservers(value bool) error
SetTokenGroupByCommunity(value bool) error
SetPeerSyncingEnabled(value bool) error
SetSyncingOnMobileNetwork(value bool) error
CreateSettings(s Settings, n params.NodeConfig) error
SaveSetting(setting string, value interface{}) error

View File

@ -206,6 +206,14 @@ func (m *MockDatabaseSettingsManager) SetPeerSyncingEnabled(value bool) error {
return ret0
}
// SetSyncingOnMobileNetwork mocks base method.
func (m *MockDatabaseSettingsManager) SetSyncingOnMobileNetwork(value bool) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SetSyncingOnMobile", value)
ret0, _ := ret[0].(error)
return ret0
}
// SetPeerSyncingEnabled indicates an expected call of SetPeerSyncingEnabled.
func (mr *MockDatabaseSettingsManagerMockRecorder) SetPeerSyncingEnabled(value interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()

View File

@ -27,6 +27,7 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/p2p"
"github.com/status-im/status-go/account"
"github.com/status-im/status-go/appmetrics"
utils "github.com/status-im/status-go/common"
@ -739,6 +740,8 @@ func (m *Messenger) ToForeground() {
if m.httpServer != nil {
m.httpServer.ToForeground()
}
m.asyncRequestAllHistoricMessages()
}
func (m *Messenger) ToBackground() {
@ -1004,7 +1007,7 @@ func (m *Messenger) handleConnectionChange(online bool) {
}
// Start fetching messages from store nodes
if online && m.config.codeControlFlags.AutoRequestHistoricMessages {
if online {
m.asyncRequestAllHistoricMessages()
}

View File

@ -1205,6 +1205,9 @@ func (m *Messenger) SpectateCommunity(communityID types.HexBytes) (*MessengerRes
return nil, err
}
// sync community
m.asyncRequestAllHistoricMessages()
return response, nil
}

View File

@ -261,12 +261,19 @@ func (m *Messenger) syncBackup() error {
if filter == nil {
return errors.New("personal topic filter not loaded")
}
canSync, err := m.canSyncWithStoreNodes()
if err != nil {
return err
}
if !canSync {
return nil
}
from, to := m.calculateMailserverTimeBounds(oneMonthDuration)
batch := MailserverBatch{From: from, To: to, Topics: []types.TopicType{filter.ContentTopic}}
ms := m.getActiveMailserver(filter.ChatID)
err := m.processMailserverBatch(*ms, batch)
err = m.processMailserverBatch(*ms, batch)
if err != nil {
return err
}
@ -365,16 +372,20 @@ func (m *Messenger) RequestAllHistoricMessages(forceFetchingBackup, withRetries
if err != nil {
return nil, err
}
allResponses.AddChats(response.Chats())
allResponses.AddMessages(response.Messages())
if response != nil {
allResponses.AddChats(response.Chats())
allResponses.AddMessages(response.Messages())
}
continue
}
response, err := m.syncFilters(*ms, filtersForMs)
if err != nil {
return nil, err
}
allResponses.AddChats(response.Chats())
allResponses.AddMessages(response.Messages())
if response != nil {
allResponses.AddChats(response.Chats())
allResponses.AddMessages(response.Messages())
}
}
return allResponses, nil
}
@ -415,6 +426,14 @@ func getPrioritizedBatches() []int {
}
func (m *Messenger) syncFiltersFrom(ms mailservers.Mailserver, filters []*transport.Filter, lastRequest uint32) (*MessengerResponse, error) {
canSync, err := m.canSyncWithStoreNodes()
if err != nil {
return nil, err
}
if !canSync {
return nil, nil
}
response := &MessengerResponse{}
topicInfo, err := m.mailserversDatabase.Topics()
if err != nil {
@ -866,12 +885,27 @@ loop:
return result
}
func (m *Messenger) canSyncWithStoreNodes() (bool, error) {
if m.featureFlags.StoreNodesDisabled {
return false, nil
}
if m.connectionState.IsExpensive() {
return m.settings.CanSyncOnMobileNetwork()
}
return true, nil
}
func (m *Messenger) DisableStoreNodes() {
m.featureFlags.StoreNodesDisabled = true
}
func (m *Messenger) processMailserverBatch(ms mailservers.Mailserver, batch MailserverBatch) error {
if m.featureFlags.StoreNodesDisabled {
canSync, err := m.canSyncWithStoreNodes()
if err != nil {
return err
}
if !canSync {
return nil
}
@ -884,7 +918,11 @@ func (m *Messenger) processMailserverBatch(ms mailservers.Mailserver, batch Mail
}
func (m *Messenger) processMailserverBatchWithOptions(ms mailservers.Mailserver, batch MailserverBatch, pageLimit uint32, shouldProcessNextPage func(int) (bool, uint32), processEnvelopes bool) error {
if m.featureFlags.StoreNodesDisabled {
canSync, err := m.canSyncWithStoreNodes()
if err != nil {
return err
}
if !canSync {
return nil
}
@ -914,6 +952,14 @@ func (m *Messenger) SyncChatFromSyncedFrom(chatID string) (uint32, error) {
ms := m.getActiveMailserver(chat.CommunityID)
var from uint32
_, err := m.performMailserverRequest(ms, func(ms mailservers.Mailserver) (*MessengerResponse, error) {
canSync, err := m.canSyncWithStoreNodes()
if err != nil {
return nil, err
}
if !canSync {
return nil, nil
}
pubsubTopic, topics, err := m.topicsForChat(chatID)
if err != nil {
return nil, nil
@ -1094,6 +1140,14 @@ func (m *Messenger) fetchMessages(chatID string, duration time.Duration) (uint32
ms := m.getActiveMailserver(chat.CommunityID)
_, err := m.performMailserverRequest(ms, func(ms mailservers.Mailserver) (*MessengerResponse, error) {
canSync, err := m.canSyncWithStoreNodes()
if err != nil {
return nil, err
}
if !canSync {
return nil, nil
}
m.logger.Debug("fetching messages", zap.String("chatID", chatID), zap.String("mailserver", ms.Name))
pubsubTopic, topics, err := m.topicsForChat(chatID)
if err != nil {

View File

@ -18,6 +18,7 @@ import (
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/status-im/status-go/params"
"github.com/status-im/status-go/protocol/storenodes"
"github.com/status-im/status-go/services/mailservers"
@ -446,9 +447,7 @@ func (m *Messenger) connectToMailserver(ms mailservers.Mailserver) error {
m.transport.SetStorePeerID(peerID)
// Query mailserver
if m.config.codeControlFlags.AutoRequestHistoricMessages {
m.asyncRequestAllHistoricMessages()
}
m.asyncRequestAllHistoricMessages()
}
}
return nil
@ -636,7 +635,12 @@ func (m *Messenger) handleMailserverCycleEvent(connectedPeers []ConnectedPeer) e
}
func (m *Messenger) asyncRequestAllHistoricMessages() {
if !m.config.codeControlFlags.AutoRequestHistoricMessages {
return
}
m.logger.Debug("asyncRequestAllHistoricMessages")
go func() {
_, err := m.RequestAllHistoricMessages(false, true)
if err != nil {

View File

@ -16,6 +16,20 @@ func (m *Messenger) SetStoreConfirmationForMessagesSent(request *requests.SetSto
return nodecfg.SetStoreConfirmationForMessagesSent(m.database, request.Enabled)
}
func (m *Messenger) SetSyncingOnMobileNetwork(request *requests.SetSyncingOnMobileNetwork) error {
if err := request.Validate(); err != nil {
return err
}
err := m.settings.SetSyncingOnMobileNetwork(request.Enabled)
if err != nil {
return err
}
if request.Enabled {
m.asyncRequestAllHistoricMessages()
}
return nil
}
func (m *Messenger) SetLogLevel(request *requests.SetLogLevel) error {
if err := request.Validate(); err != nil {
return err

View File

@ -1144,3 +1144,162 @@ func (s *MessengerPushNotificationSuite) TestReceivePushNotificationPairedDevice
})
s.Require().NoError(err)
}
func (s *MessengerPushNotificationSuite) TestReceivePushNotificationReply() {
bob := s.m
serverKey, err := crypto.GenerateKey()
s.Require().NoError(err)
server := s.newPushNotificationServer(s.shh, serverKey)
defer TearDownMessenger(&s.Suite, server)
alice := s.newMessenger(s.shh)
s.Require().NoError(err)
defer TearDownMessenger(&s.Suite, alice)
s.Require().NoError(alice.EnableSendingPushNotifications())
bobInstallationIDs := []string{bob.installationID}
// Create public chat and join for both alice and bob
chat := CreatePublicChat("status", s.m.transport)
err = bob.SaveChat(chat)
s.Require().NoError(err)
_, err = bob.Join(chat)
s.Require().NoError(err)
err = alice.SaveChat(chat)
s.Require().NoError(err)
_, err = alice.Join(chat)
s.Require().NoError(err)
// Register bob
err = bob.AddPushNotificationsServer(context.Background(), &server.identity.PublicKey, pushnotificationclient.ServerTypeCustom)
s.Require().NoError(err)
err = bob.RegisterForPushNotifications(context.Background(), bob1DeviceToken, testAPNTopic, protobuf.PushNotificationRegistration_APN_TOKEN)
// Pull servers and check we registered
err = tt.RetryWithBackOff(func() error {
_, err = server.RetrieveAll()
if err != nil {
return err
}
_, err = bob.RetrieveAll()
if err != nil {
return err
}
registered, err := bob.RegisteredForPushNotifications()
if err != nil {
return err
}
if !registered {
return errors.New("not registered")
}
bobServers, err := bob.GetPushNotificationsServers()
if err != nil {
return err
}
if len(bobServers) == 0 {
return errors.New("not registered")
}
return nil
})
// Make sure we receive it
s.Require().NoError(err)
bobServers, err := bob.GetPushNotificationsServers()
s.Require().NoError(err)
firstMessage := buildTestMessage(*chat)
firstMessage.Text = "Hello!"
response, err := bob.SendChatMessage(context.Background(), firstMessage)
s.Require().NoError(err)
messageIDString := response.Messages()[0].ID
_, err = WaitOnMessengerResponse(
alice,
func(r *MessengerResponse) bool {
for _, message := range r.Messages() {
if message.ID == messageIDString {
return true
}
}
return false
},
"no messages",
)
replyMessage := buildTestMessage(*chat)
replyMessage.Text = "Hello reply"
replyMessage.ResponseTo = messageIDString
response, err = alice.SendChatMessage(context.Background(), replyMessage)
s.Require().NoError(err)
messageIDString = response.Messages()[0].ID
messageID, err := hex.DecodeString(messageIDString[2:])
s.Require().NoError(err)
var bobInfo []*pushnotificationclient.PushNotificationInfo
err = tt.RetryWithBackOff(func() error {
_, err = server.RetrieveAll()
if err != nil {
return err
}
_, err = alice.RetrieveAll()
if err != nil {
return err
}
bobInfo, err = alice.pushNotificationClient.GetPushNotificationInfo(&bob.identity.PublicKey, bobInstallationIDs)
if err != nil {
return err
}
// Check we have replies for bob
if len(bobInfo) != 1 {
return errors.New("info not fetched")
}
return nil
})
s.Require().NoError(err)
s.Require().NotEmpty(bobInfo)
s.Require().Equal(bob.installationID, bobInfo[0].InstallationID)
s.Require().Equal(bobServers[0].AccessToken, bobInfo[0].AccessToken)
s.Require().Equal(&bob.identity.PublicKey, bobInfo[0].PublicKey)
retrievedNotificationInfo, err := alice.pushNotificationClient.GetPushNotificationInfo(&bob.identity.PublicKey, bobInstallationIDs)
s.Require().NoError(err)
s.Require().NotNil(retrievedNotificationInfo)
s.Require().Len(retrievedNotificationInfo, 1)
var sentNotification *pushnotificationclient.SentNotification
err = tt.RetryWithBackOff(func() error {
_, err = server.RetrieveAll()
if err != nil {
return err
}
_, err = alice.RetrieveAll()
if err != nil {
return err
}
sentNotification, err = alice.pushNotificationClient.GetSentNotification(common.HashPublicKey(&bob.identity.PublicKey), bob.installationID, messageID)
if err != nil {
return err
}
if sentNotification == nil {
return errors.New("sent notification not found")
}
if !sentNotification.Success {
return errors.New("sent notification not successul")
}
return nil
})
s.Require().NoError(err)
}

View File

@ -907,6 +907,50 @@ func (c *Client) handlePublicMessageSent(sentMessage *common.SentMessage) error
}
c.config.Logger.Debug("message found", zap.Binary("messageID", messageID))
if message.ResponseTo != "" {
reply, err := c.getMessage(message.ResponseTo)
if err != nil {
c.config.Logger.Error("could not retrieve message", zap.Error(err))
}
if reply != nil {
pkString := reply.From
c.config.Logger.Debug("handling mention", zap.String("publickey", pkString))
pubkeyBytes, err := types.DecodeHex(pkString)
if err != nil {
return err
}
publicKey, err := crypto.UnmarshalPubkey(pubkeyBytes)
if err != nil {
return err
}
// we use a synthetic installationID for mentions, as all devices need to be notified
shouldNotify, err := c.shouldNotifyOn(publicKey, mentionInstallationID, messageID)
if err != nil {
return err
}
c.config.Logger.Debug("should no mention", zap.Any("publickey", shouldNotify))
// we send the notifications and return the info of the devices notified
infos, err := c.SendNotification(publicKey, nil, messageID, message.LocalChatID, protobuf.PushNotification_MENTION)
if err != nil {
return err
}
// mark message as sent so we don't notify again
for _, i := range infos {
c.config.Logger.Debug("marking as sent ", zap.Binary("mid", messageID), zap.String("id", i.InstallationID))
if err := c.notifiedOn(publicKey, i.InstallationID, messageID, message.LocalChatID, protobuf.PushNotification_MESSAGE); err != nil {
return err
}
}
}
}
for _, pkString := range message.Mentions {
c.config.Logger.Debug("handling mention", zap.String("publickey", pkString))
pubkeyBytes, err := types.DecodeHex(pkString)

View File

@ -0,0 +1,9 @@
package requests
type SetSyncingOnMobileNetwork struct {
Enabled bool `json:"enabled"`
}
func (r *SetSyncingOnMobileNetwork) Validate() error {
return nil
}

View File

@ -1526,6 +1526,10 @@ func (api *PublicAPI) TogglePeerSyncing(request *requests.TogglePeerSyncingReque
return api.service.messenger.TogglePeerSyncing(request)
}
func (api *PublicAPI) SetSyncingOnMobileNetwork(request *requests.SetSyncingOnMobileNetwork) error {
return api.service.messenger.SetSyncingOnMobileNetwork(request)
}
func (api *PublicAPI) SetPinnedMailservers(pinnedMailservers map[string]string) error {
return api.service.messenger.SetPinnedMailservers(pinnedMailservers)
}