diff --git a/bindings/client.go b/bindings/client.go index 4cdfa338f802dd28c3d0b387cc6e8e7e21c19825..1d27eebecf9dda16a8ed8b3e69f55ba4d52b4007 100644 --- a/bindings/client.go +++ b/bindings/client.go @@ -31,7 +31,7 @@ import ( "google.golang.org/grpc/grpclog" ) -var extantClient bool +var extantClient bool = false var loginMux sync.Mutex var clientSingleton *Client diff --git a/bindings/restoreContacts.go b/bindings/restoreContacts.go index f9e796affcf097c3cd1220b68ea6e462c39ccd19..61e14d3c1073e3e80a44fcbb58df4b6f400393ea 100644 --- a/bindings/restoreContacts.go +++ b/bindings/restoreContacts.go @@ -8,7 +8,6 @@ package bindings import ( - "gitlab.com/elixxir/client/interfaces" "gitlab.com/elixxir/client/xxmutils" "gitlab.com/xx_network/primitives/id" ) @@ -66,7 +65,7 @@ func (r *RestoreContactsReport) GetErrorAt(index int) string { // the mobile phone apps and are not intended to be part of the xxDK. It // should be treated as internal functions specific to the phone apps. func RestoreContactsFromBackup(backupPartnerIDs []byte, client *Client, - udManager *UserDiscovery, updatesCb interfaces.RestoreContactsUpdater) ( + udManager *UserDiscovery, updatesCb RestoreContactsUpdater) ( *RestoreContactsReport, error) { restored, failed, errs, err := xxmutils.RestoreContactsFromBackup( diff --git a/go.mod b/go.mod index 536f5e8d4388cf58659d11e2f4b8a288a83bcac8..d21814b72e803fcee02798ea1f6c1b288361e2a8 100644 --- a/go.mod +++ b/go.mod @@ -26,13 +26,29 @@ require ( ) require ( + github.com/badoux/checkmail v1.2.1 // indirect + github.com/elliotchance/orderedmap v1.4.0 // indirect + github.com/fsnotify/fsnotify v1.4.9 // indirect github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/magiconair/properties v1.8.4 // indirect + github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/mapstructure v1.4.0 // indirect github.com/pelletier/go-toml v1.8.1 // indirect + github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // indirect github.com/smartystreets/assertions v1.0.1 // indirect github.com/spf13/afero v1.5.1 // indirect github.com/spf13/cast v1.3.1 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/subosito/gotenv v1.2.0 // indirect + github.com/ttacon/builder v0.0.0-20170518171403-c099f663e1c2 // indirect + github.com/ttacon/libphonenumber v1.2.1 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/zeebo/blake3 v0.1.1 // indirect + gitlab.com/xx_network/ring v0.0.3-0.20220222211904-da613960ad93 // indirect + golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac // indirect + golang.org/x/text v0.3.6 // indirect google.golang.org/genproto v0.0.0-20210105202744-fe13368bc0e1 // indirect gopkg.in/ini.v1 v1.62.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/network/node/register.go b/network/node/register.go index 1576fe89a027cbba1a29ef374a84c809848e0d57..274703a8d1fb68f001e0ab692a8c726243ed38dc 100644 --- a/network/node/register.go +++ b/network/node/register.go @@ -39,6 +39,10 @@ import ( "time" ) + +const maxAttempts = 5 +var delayTable = [5]time.Duration{0,5*time.Second,30*time.Second,60*time.Second,120*time.Second} + type RegisterNodeCommsInterface interface { SendRequestClientKeyMessage(host *connect.Host, message *pb.SignedClientKeyRequest) (*pb.SignedKeyResponse, error) @@ -49,12 +53,16 @@ func StartRegistration(sender *gateway.Sender, session *storage.Session, rngGen multi := stoppable.NewMulti("NodeRegistrations") + inProgess := &sync.Map{} + // we are relying on the in progress check to + // ensure there is only a single operator at a time, as a result this is a map of ID -> int + attempts := &sync.Map{} for i := uint(0); i < numParallel; i++ { stop := stoppable.NewSingle(fmt.Sprintf("NodeRegistration %d", i)) - go registerNodes(sender, session, rngGen, comms, stop, c, inProgess) + go registerNodes(sender, session, rngGen, comms, stop, c, inProgess, attempts) multi.Add(stop) } @@ -63,7 +71,7 @@ func StartRegistration(sender *gateway.Sender, session *storage.Session, rngGen func registerNodes(sender *gateway.Sender, session *storage.Session, rngGen *fastRNG.StreamGenerator, comms RegisterNodeCommsInterface, - stop *stoppable.Single, c chan network.NodeGateway, inProgress *sync.Map) { + stop *stoppable.Single, c chan network.NodeGateway, inProgress, attempts *sync.Map) { u := session.User() regSignature := u.GetTransmissionRegistrationValidationSignature() // Timestamp in which user has registered with registration @@ -85,6 +93,14 @@ func registerNodes(sender *gateway.Sender, session *storage.Session, if _, operating := inProgress.LoadOrStore(nidStr, struct{}{}); operating { continue } + + //keep track of how many times this has been attempted + numAttempts := uint(1) + if nunAttemptsInterface, hasValue := attempts.LoadOrStore(nidStr, numAttempts); hasValue{ + numAttempts = nunAttemptsInterface.(uint) + attempts.Store(nidStr, numAttempts+1) + } + // No need to register with stale nodes if isStale := gw.Node.Status == ndf.Stale; isStale { jww.DEBUG.Printf("Skipping registration with stale node %s", nidStr) @@ -95,12 +111,22 @@ func registerNodes(sender *gateway.Sender, session *storage.Session, inProgress.Delete(nidStr) if err != nil { jww.ERROR.Printf("Failed to register node: %+v", err) + //if we have not reached the attempt limit for this gateway, send it back into the channel to retry + if numAttempts <maxAttempts{ + go func(){ + //delay the send for a backoff + time.Sleep(delayTable[numAttempts-1]) + c<-gw + }() + } } case <-t.C: } } } + + //registerWithNode serves as a helper for RegisterWithNodes // It registers a user with a specific in the client's ndf. func registerWithNode(sender *gateway.Sender, comms RegisterNodeCommsInterface,