diff --git a/api/results.go b/api/results.go index 04e91e15e7c6e3407ecfab759dd9eb1f598d9885..eb0403dee92b93be7ad90cc3ab2b4cafff28e8f8 100644 --- a/api/results.go +++ b/api/results.go @@ -4,6 +4,7 @@ // Use of this source code is governed by a license that can be found in the // // LICENSE file // /////////////////////////////////////////////////////////////////////////////// + package api import ( @@ -18,7 +19,7 @@ import ( "gitlab.com/xx_network/primitives/id" ) -// Enum of possible round results to pass back +// RoundResult is the enum of possible round results to pass back type RoundResult uint const ( @@ -40,7 +41,7 @@ func (rr RoundResult) String() string { } } -// Callback interface which reports the requested rounds. +// RoundEventCallback interface which reports the requested rounds. // Designed such that the caller may decide how much detail they need. // allRoundsSucceeded: // Returns false if any rounds in the round map were unsuccessful. @@ -60,7 +61,7 @@ type historicalRoundsComm interface { GetHost(hostId *id.ID) (*connect.Host, bool) } -// Adjudicates on the rounds requested. Checks if they are +// GetRoundResults adjudicates on the rounds requested. Checks if they are // older rounds or in progress rounds. func (c *Client) GetRoundResults(roundList []id.Round, timeout time.Duration, roundCallback RoundEventCallback) error { @@ -168,7 +169,7 @@ func (c *Client) getRoundResults(roundList []id.Round, timeout time.Duration, roundsResults[roundId] = Failed allRoundsSucceeded = false } - return + continue } allRoundsSucceeded = false anyRoundTimedOut = true diff --git a/backup/backup_test.go b/backup/backup_test.go index 4b6d964b1ea1a681b8ed0d75149a11817355a638..1dc785aa311e0916f06f71618975dc9afadb1c25 100644 --- a/backup/backup_test.go +++ b/backup/backup_test.go @@ -24,7 +24,7 @@ import ( // Tests that Backup.initializeBackup returns a new Backup with a copy of the // key and the callback. func Test_initializeBackup(t *testing.T) { - cbChan := make(chan []byte) + cbChan := make(chan []byte, 2) cb := func(encryptedBackup []byte) { cbChan <- encryptedBackup } expectedPassword := "MySuperSecurePassword" b, err := initializeBackup(expectedPassword, cb, nil, @@ -34,6 +34,12 @@ func Test_initializeBackup(t *testing.T) { t.Errorf("initializeBackup returned an error: %+v", err) } + select { + case <-cbChan: + case <-time.After(10 * time.Millisecond): + t.Error("Timed out waiting for callback.") + } + // Check that the correct password is in storage loadedPassword, err := loadPassword(b.store.GetKV()) if err != nil { @@ -89,6 +95,12 @@ func Test_resumeBackup(t *testing.T) { t.Errorf("Failed to initialize new Backup: %+v", err) } + select { + case <-cbChan1: + case <-time.After(10 * time.Millisecond): + t.Error("Timed out waiting for callback.") + } + // Get key and salt to compare to later key1, salt1, _, err := loadBackup(b.store.GetKV()) if err != nil { @@ -135,7 +147,7 @@ func Test_resumeBackup(t *testing.T) { select { case r := <-cbChan1: - t.Errorf("Callback of first Backup called: %q", r) // TODO: i think there is a race condition here + t.Errorf("Callback of first Backup called: %q", r) case r := <-cbChan2: if !bytes.Equal(encryptedBackup, r) { t.Errorf("Callback has unexepected data."+ diff --git a/go.mod b/go.mod index 24691d51833d6d1cbfb7dfa5755e66b44a0b0985..0d5e6d485cfc66aa506a1fefa30f30cbf1c3999c 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( gitlab.com/elixxir/crypto v0.0.7-0.20220309234716-1ba339865787 gitlab.com/elixxir/ekv v0.1.6 gitlab.com/elixxir/primitives v0.0.3-0.20220222212109-d412a6e46623 - gitlab.com/xx_network/comms v0.0.4-0.20220223205228-7c4974139569 + gitlab.com/xx_network/comms v0.0.4-0.20220311192415-d95fe8906580 gitlab.com/xx_network/crypto v0.0.5-0.20220222212031-750f7e8a01f4 gitlab.com/xx_network/primitives v0.0.4-0.20220222211843-901fa4a2d72b golang.org/x/crypto v0.0.0-20220128200615-198e4374d7ed diff --git a/go.sum b/go.sum index a6c4c7e78ad2a2f0cd8bfdb8b3bcc83a5038c58e..d5504c7a5d85bda9142d40c5dd364953fd617a98 100644 --- a/go.sum +++ b/go.sum @@ -288,8 +288,9 @@ gitlab.com/elixxir/primitives v0.0.1/go.mod h1:kNp47yPqja2lHSiS4DddTvFpB/4D9dB2Y gitlab.com/elixxir/primitives v0.0.3-0.20220222212109-d412a6e46623 h1:NzJ06KdJd3fVJee0QvGhNr3CO+Ki8Ea1PeakZsm+rZM= gitlab.com/elixxir/primitives v0.0.3-0.20220222212109-d412a6e46623/go.mod h1:MtFIyJUQn9P7djzVlBpEYkPNnnWFTjZvw89swoXY+QM= gitlab.com/xx_network/comms v0.0.0-20200805174823-841427dd5023/go.mod h1:owEcxTRl7gsoM8c3RQ5KAm5GstxrJp5tn+6JfQ4z5Hw= -gitlab.com/xx_network/comms v0.0.4-0.20220223205228-7c4974139569 h1:TjO165sJ6S++ZcHn+u5GnkfCjq3sxfaqhHmB1WgH31s= gitlab.com/xx_network/comms v0.0.4-0.20220223205228-7c4974139569/go.mod h1:isHnwem0v4rTcwwHP455FhVlFyPcHkHiVz+N3s/uCSI= +gitlab.com/xx_network/comms v0.0.4-0.20220311192415-d95fe8906580 h1:IV0gDwdTxtCpc9Vkx7IeSStSqvG+0ZpF57X+OhTQDIM= +gitlab.com/xx_network/comms v0.0.4-0.20220311192415-d95fe8906580/go.mod h1:isHnwem0v4rTcwwHP455FhVlFyPcHkHiVz+N3s/uCSI= gitlab.com/xx_network/crypto v0.0.3/go.mod h1:DF2HYvvCw9wkBybXcXAgQMzX+MiGbFPjwt3t17VRqRE= gitlab.com/xx_network/crypto v0.0.4/go.mod h1:+lcQEy+Th4eswFgQDwT0EXKp4AXrlubxalwQFH5O0Mk= gitlab.com/xx_network/crypto v0.0.5-0.20220222212031-750f7e8a01f4 h1:95dZDMn/hpLNwsgZO9eyQgGKaSDyh6F6+WygqZIciww= diff --git a/network/gateway/hostPool.go b/network/gateway/hostPool.go index eed695bb9a56ebc4ef8ef4e43289e19376593b3f..dd4616cc4583d54621cf2fb42dc2611ab96cee95 100644 --- a/network/gateway/hostPool.go +++ b/network/gateway/hostPool.go @@ -74,21 +74,23 @@ type HostPool struct { // PoolParams Allows configuration of HostPool parameters type PoolParams struct { - MaxPoolSize uint32 // Maximum number of Hosts in the HostPool - PoolSize uint32 // Allows override of HostPool size. Set to zero for dynamic size calculation - ProxyAttempts uint32 // How many proxies will be used in event of send failure - MaxPings uint32 // How many gateways to concurrently test when initializing HostPool. Disabled if zero. - HostParams connect.HostParams // Parameters for the creation of new Host objects + MaxPoolSize uint32 // Maximum number of Hosts in the HostPool + PoolSize uint32 // Allows override of HostPool size. Set to zero for dynamic size calculation + ProxyAttempts uint32 // How many proxies will be used in event of send failure + MaxPings uint32 // How many gateways to concurrently test when initializing HostPool. Disabled if zero. + ForceConnection bool // Flag determining whether Host connections are initialized when added to HostPool + HostParams connect.HostParams // Parameters for the creation of new Host objects } // DefaultPoolParams Returns a default set of PoolParams func DefaultPoolParams() PoolParams { p := PoolParams{ - MaxPoolSize: 30, - ProxyAttempts: 5, - PoolSize: 0, - MaxPings: 0, - HostParams: connect.GetDefaultHostParams(), + MaxPoolSize: 30, + ProxyAttempts: 5, + PoolSize: 0, + MaxPings: 0, + ForceConnection: false, + HostParams: connect.GetDefaultHostParams(), } p.HostParams.MaxRetries = 1 p.HostParams.MaxSendRetries = 1 @@ -539,7 +541,7 @@ func (h *HostPool) replaceHostNoStore(newId *id.ID, oldPoolIndex uint32) error { // Use the GwId to keep track of the new random Host's index in the hostList h.hostMap[*newId] = oldPoolIndex - // Clean up and move onto next Host + // Clean up and disconnect old Host oldHostIDStr := "unknown" if oldHost != nil { oldHostIDStr = oldHost.GetId().String() @@ -547,9 +549,18 @@ func (h *HostPool) replaceHostNoStore(newId *id.ID, oldPoolIndex uint32) error { go oldHost.Disconnect() } + // Manually connect the new Host + if h.poolParams.ForceConnection { + go func() { + err := newHost.Connect() + if err != nil { + jww.WARN.Printf("Unable to initialize Host connection: %+v", err) + } + }() + } + jww.DEBUG.Printf("Replaced Host at %d [%s] with new Host %s", oldPoolIndex, oldHostIDStr, newId.String()) - return nil } @@ -653,7 +664,6 @@ func (h *HostPool) addGateway(gwId *id.ID, ndfIndex int) { // Check if the host exists host, ok := h.manager.GetHost(gwId) if !ok { - // Check if gateway ID collides with an existing hard coded ID if id.CollidesWithHardCodedID(gwId) { jww.ERROR.Printf("Gateway ID invalid, collides with a "+ @@ -714,8 +724,8 @@ func readUint32(rng io.Reader) uint32 { func readRangeUint32(start, end uint32, rng io.Reader) uint32 { size := end - start // note we could just do the part inside the () here, but then extra - // can == size which means a little bit of range is wastes, either - // choice seems negligible so we went with the "more correct" + // can == size which means a little range is wasted, either + // choice seems negligible, so we went with the "more correct" extra := (math.MaxUint32%size + 1) % size limit := math.MaxUint32 - extra // Loop until we read something inside the limit diff --git a/network/gateway/hostpool_test.go b/network/gateway/hostpool_test.go index 5e93ba8df80ded94f70034bdc6ba3540ac6d1644..30f3b6a6151626a68e5d2b2fe4d3c282de0aefeb 100644 --- a/network/gateway/hostpool_test.go +++ b/network/gateway/hostpool_test.go @@ -485,11 +485,12 @@ func TestHostPool_UpdateNdf(t *testing.T) { // Construct a manager (bypass business logic in constructor) hostPool := &HostPool{ - manager: manager, - hostList: make([]*connect.Host, newIndex+1), - hostMap: make(map[id.ID]uint32), - ndf: testNdf, - storage: storage.InitTestingSession(t), + manager: manager, + hostList: make([]*connect.Host, newIndex+1), + hostMap: make(map[id.ID]uint32), + ndf: testNdf, + storage: storage.InitTestingSession(t), + poolParams: DefaultPoolParams(), filter: func(m map[id.ID]int, _ *ndf.NetworkDefinition) map[id.ID]int { return m }, @@ -855,6 +856,7 @@ func TestHostPool_AddGateway(t *testing.T) { hostList: make([]*connect.Host, newIndex+1), hostMap: make(map[id.ID]uint32), ndf: testNdf, + poolParams: params, addGatewayChan: make(chan network.NodeGateway), storage: storage.InitTestingSession(t), } @@ -888,6 +890,7 @@ func TestHostPool_RemoveGateway(t *testing.T) { hostList: make([]*connect.Host, newIndex+1), hostMap: make(map[id.ID]uint32), ndf: testNdf, + poolParams: params, addGatewayChan: make(chan network.NodeGateway), storage: storage.InitTestingSession(t), rng: fastRNG.NewStreamGenerator(1, 1, csprng.NewSystemRNG), diff --git a/network/manager.go b/network/manager.go index bba264c6b63263a196d4bfc135f1db42649948ec..1cec837978ffc0aaa120ea061b4d993df8110e07 100644 --- a/network/manager.go +++ b/network/manager.go @@ -133,6 +133,7 @@ func NewManager(session *storage.Session, switchboard *switchboard.Switchboard, poolParams.HostParams.KaClientOpts.Time = time.Duration(math.MaxInt64) // Enable optimized HostPool initialization poolParams.MaxPings = 50 + poolParams.ForceConnection = true m.sender, err = gateway.NewSender(poolParams, rng, ndf, comms, session, m.NodeRegistration) if err != nil { diff --git a/network/message/utils_test.go b/network/message/utils_test.go index 80b31c9a911a49babe5862078fc864498f3fdb32..e0bf2222d6f36a6934fd3469cfa1222fe257bae1 100644 --- a/network/message/utils_test.go +++ b/network/message/utils_test.go @@ -17,10 +17,10 @@ func (mc *MockSendCMIXComms) GetHost(*id.ID) (*connect.Host, bool) { nid1 := id.NewIdFromString("zezima", id.Node, mc.t) gwID := nid1.DeepCopy() gwID.SetType(id.Gateway) - h, _ := connect.NewHost(gwID, "0.0.0.0", []byte(""), connect.HostParams{ - MaxRetries: 0, - AuthEnabled: false, - }) + p := connect.GetDefaultHostParams() + p.MaxRetries = 0 + p.AuthEnabled = false + h, _ := connect.NewHost(gwID, "0.0.0.0", []byte(""), p) return h, true } diff --git a/network/rounds/remoteFilters_test.go b/network/rounds/remoteFilters_test.go index 43be06bf6d9f9719d45d630ab2f44b73fdfb7a5a..e490432857d5e94bf599d3b7eb3c4b1a66ee8017 100644 --- a/network/rounds/remoteFilters_test.go +++ b/network/rounds/remoteFilters_test.go @@ -20,7 +20,7 @@ import ( ) func TestMain(m *testing.M) { - jww.SetStdoutThreshold(jww.LevelTrace) + jww.SetStdoutThreshold(jww.LevelDebug) connect.TestingOnlyDisableTLS = true os.Exit(m.Run()) } diff --git a/network/rounds/utils_test.go b/network/rounds/utils_test.go index 8779a68acdf4f0c929186ddb59b6a0ad26bc3f05..ea24534930b93b345ef2bff86de0f29f6663507b 100644 --- a/network/rounds/utils_test.go +++ b/network/rounds/utils_test.go @@ -62,10 +62,10 @@ func (mmrc *mockMessageRetrievalComms) RemoveHost(hid *id.ID) { } func (mmrc *mockMessageRetrievalComms) GetHost(hostId *id.ID) (*connect.Host, bool) { - h, _ := connect.NewHost(hostId, "0.0.0.0", []byte(""), connect.HostParams{ - MaxRetries: 0, - AuthEnabled: false, - }) + p := connect.GetDefaultHostParams() + p.MaxRetries = 0 + p.AuthEnabled = false + h, _ := connect.NewHost(hostId, "0.0.0.0", []byte(""), p) return h, true }