diff --git a/README.md b/README.md index c3f572fd1a8e885c9dec994f626fbcca7318c450..dc58f697ff36740f76504073c92ae3d96676b16d 100644 --- a/README.md +++ b/README.md @@ -415,4 +415,97 @@ You can verify that all symbols got bound by unzipping `bindings-sources.jar` an Every time you make a change to the client or bindings, you must rebuild the client bindings into a `.aar` or `iOS.zip` to propagate those changes to the app. There's a script that runs gomobile for you in the `bindings-integration` -repository. \ No newline at end of file +repository. + + +## Regenerate Protobuf File + +First install the protobuf compiler or update by following the instructions in +[Installing Protocol Buffer Compiler](#installing-protocol-buffer-compiler) +below. + +Use the following command to compile a protocol buffer. + +```shell +protoc -I. -I../vendor --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative *.proto +``` + +* This command must be run from the directory containing the `.proto` file + being compiled. +* The `-I` flag specifies where to find imports used by the `.proto` file and + may need to be modified or removed to suit the .proto file being compiled.\ + * 💡 **Note:** Note: If you are importing a file from the vendor directory, + ensure that you have the correct version by running `go mod vendor`. +* If there is more than one proto file in the directory, replace `*.proto` with + the file’s name. +* If the `.proto` file does not use gRPC, then the `--go-grpc_out` and + `--go-grpc_opt` can be excluded. + + + +## Installing Protocol Buffer Compiler + +This guide describes how to install the required dependencies to compile +`.proto` files to Go. + +Before following the instructions below, be sure to remove all old versions of +`protoc`. If your previous protoc-gen-go file is not installed in your Go bin +directory, it will also need to be removed. + +If you have followed this guide previously when installing `protoc` and need to +update, you can simply follow the instructions below. No uninstallation or +removal is necessary. + +To compile a protocol buffer, you need the protocol buffer compiler `protoc` +along with two plugins `protoc-gen-go` and `protoc-gen-go-grpc`. Make sure you +use the correct versions as listed below. + +| | Version | Download | Documentation | +|----------------------|--------:|---------------------------------------------------------------------|-------------------------------------------------------------------------| +| `protoc` | 3.15.6 | https://github.com/protocolbuffers/protobuf/releases/tag/v3.15.6 | https://developers.google.com/protocol-buffers/docs/gotutorial | +| `protoc-gen-go` | 1.27.1 | https://github.com/protocolbuffers/protobuf-go/releases/tag/v1.27.1 | https://pkg.go.dev/google.golang.org/protobuf@v1.27.1/cmd/protoc-gen-go | +| `protoc-gen-go-grpc` | 1.2.0 | https://github.com/grpc/grpc-go/releases/tag/v1.2.0 | https://pkg.go.dev/google.golang.org/grpc/cmd/protoc-gen-go-grpc | + +1. Download the correct release of `protoc` from the + [release page](https://github.com/protocolbuffers/protobuf/releases) or use + the link from the table above to get the download for your OS. + + wget https://github.com/protocolbuffers/protobuf/releases/download/v3.15.6/protoc-3.15.6-linux-x86_64.zip + +2. Extract the files to a folder, such as `$HOME/.local`. + + unzip protoc-3.15.6-linux-x86_64.zip -d $HOME/.local + +3. Add the selected directory to your environment’s `PATH` variable, make sure + to include it in your `.profile` or `.bashrc` file. Also, include your go bin + directory (`$GOPATH/bin` or `$GOBIN`) if it is not already included. + + export PATH="$PATH:$HOME/.local/bin:$GOPATH/bin" + + 💡 **Note:** Make sure you update your configuration file once done with + source `.profile`. + +4. Now check that `protoc` is installed with the correct version by running the + following command. + + protoc --version + + Which prints the current version + + libprotoc 3.15.6 + +5. Next, download `protoc-gen-go` and `protoc-gen-go-grpc` using the version + found in the table above. + + go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.27 + go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2 + +6. Check that `protoc-gen-go` is installed with the correct version. + + protoc-gen-go --version + protoc-gen-go v1.27.1 + +7. Check that `protoc-gen-go-grpc` is installed with the correct version. + + protoc-gen-go-grpc --version + protoc-gen-go-grpc 1.2.0 \ No newline at end of file diff --git a/backup/backup.go b/backup/backup.go index d4cc92a408a48cd809b30a93f25bb9ea93b02e59..b7fc57f5e3d46cb4e17277cc2d236b146cffd74f 100644 --- a/backup/backup.go +++ b/backup/backup.go @@ -93,6 +93,7 @@ type UpdateBackupFn func(encryptedBackup []byte) func InitializeBackup(backupPassphrase string, updateBackupCb UpdateBackupFn, container *xxdk.Container, e2e E2e, session Session, ud UserDiscovery, kv *versioned.KV, rng *fastRNG.StreamGenerator) (*Backup, error) { + b := &Backup{ updateBackupCb: updateBackupCb, container: container, diff --git a/backup/backupRestore.go b/backup/backupRestore.go index 6be4fd04620c011b8d3c318471e4aef04d86b700..2d408c173b49cd1a82d824b480bb3c2c47fcddce 100644 --- a/backup/backupRestore.go +++ b/backup/backupRestore.go @@ -92,6 +92,7 @@ func NewCmixFromBackup(ndfJSON, storageDir, backupPassphrase string, phone = f } } + err = ud.InitStoreFromBackup(storageSess.GetKV(), username, email, phone) return backUp.Contacts.Identities, backUp.JSONParams, err } diff --git a/bindings/fileTransfer.go b/bindings/fileTransfer.go index 2a25aa4a7829c0fdd576c9c660709261dd23997c..4b8b5adde300191ba85b524fdd1499c3319b1998 100644 --- a/bindings/fileTransfer.go +++ b/bindings/fileTransfer.go @@ -9,6 +9,7 @@ package bindings import ( "encoding/json" + jww "github.com/spf13/jwalterweatherman" "time" "gitlab.com/elixxir/client/fileTransfer" @@ -127,7 +128,7 @@ type FileTransferReceiveProgressCallback interface { // - paramsJSON - JSON marshalled fileTransfer.Params func InitFileTransfer(e2eID int, receiveFileCallback ReceiveFileCallback, e2eFileTransferParamsJson, fileTransferParamsJson []byte) (*FileTransfer, error) { - + jww.INFO.Printf("Calling InitFileTransfer()") // Get user from singleton user, err := e2eTrackerSingleton.get(e2eID) if err != nil { diff --git a/bindings/group.go b/bindings/group.go index ddb6f12b985ebfaf7e6d7c1df0c2c3b86cae3c45..b7faa628b8b1439b27b0f27413b7049e0f926a97 100644 --- a/bindings/group.go +++ b/bindings/group.go @@ -348,7 +348,7 @@ type GroupRequest interface { // The decryptedMessage field will be a JSON marshalled GroupChatMessage. type GroupChatProcessor interface { Process(decryptedMessage, msg, receptionId []byte, ephemeralId, - roundId int64, err error) + roundId int64, roundUrl string, err error) fmt.Stringer } @@ -402,13 +402,14 @@ func convertMessageReceive(decryptedMsg gc.MessageReceive) GroupChatMessage { // binding-layer primitives equivalents within the GroupChatProcessor.Process. func convertGroupChatProcessor(decryptedMsg gc.MessageReceive, msg format.Message, receptionID receptionID.EphemeralIdentity, round rounds.Round) ( - decryptedMessage, message, receptionId []byte, ephemeralId, roundId int64, err error) { + decryptedMessage, message, receptionId []byte, ephemeralId, roundId int64, roundUrl string, err error) { decryptedMessage, err = json.Marshal(convertMessageReceive(decryptedMsg)) message = msg.Marshal() receptionId = receptionID.Source.Marshal() ephemeralId = receptionID.EphId.Int64() roundId = int64(round.ID) + roundUrl = getRoundURL(round.ID) return } diff --git a/bindings/ud.go b/bindings/ud.go index 976321c5b33b5fd964b37dfd4c3aa5e97be66cac..9332ea975b90db019389bfe569a73ccbaa40880d 100644 --- a/bindings/ud.go +++ b/bindings/ud.go @@ -203,29 +203,23 @@ func NewOrLoadUd(e2eID int, follower UdNetworkStatus, username string, } // NewUdManagerFromBackup builds a new user discover manager from a backup. It -// will construct a manager that is already registered and restore already -// registered facts into store. +// will construct a manager that is already registered. Confirmed facts have +// already been restored via the call NewCmixFromBackup. // // Parameters: // - e2eID - e2e object ID in the tracker // - follower - network follower func wrapped in UdNetworkStatus -// - username - The username this user registered with initially. This should -// not be nullable, and be JSON marshalled as retrieved from -// UserDiscovery.GetFacts(). -// - emailFactJson - nullable JSON marshalled email [fact.Fact] -// - phoneFactJson - nullable JSON marshalled phone [fact.Fact] // - cert - the TLS certificate for the UD server this call will connect with. // You may use the UD server run by the xx network team by using -// E2e.GetUdCertFromNdf. -// - contactFile - the data within a marshalled contact.Contact. This +// [E2e.GetUdCertFromNdf]. +// - contactFile - the data within a marshalled [contact.Contact]. This // represents the contact file of the server this call will connect with. You // may use the UD server run by the xx network team by using -// E2e.GetUdContactFromNdf. +// [E2e.GetUdContactFromNdf]. // - address - the IP address of the UD server this call will connect with. You // may use the UD server run by the xx network team by using -// E2e.GetUdAddressFromNdf. +// [E2e.GetUdAddressFromNdf]. func NewUdManagerFromBackup(e2eID int, follower UdNetworkStatus, - usernameJson, emailFactJson, phoneFactJson, cert, contactFile []byte, address string) (*UserDiscovery, error) { // Get user from singleton @@ -234,38 +228,12 @@ func NewUdManagerFromBackup(e2eID int, follower UdNetworkStatus, return nil, err } - var email, phone, username fact.Fact - - // Parse email if non-nil - if emailFactJson != nil { - err = json.Unmarshal(emailFactJson, &email) - if err != nil { - return nil, err - } - } - - // Parse phone if non-nil - if phoneFactJson != nil { - err = json.Unmarshal(phoneFactJson, &phone) - if err != nil { - return nil, err - } - } - - // Parse username - err = json.Unmarshal(usernameJson, &username) - if err != nil { - return nil, err - } - UdNetworkStatusFn := func() xxdk.Status { return xxdk.Status(follower.UdNetworkStatus()) } - u, err := ud.NewManagerFromBackup( - user.api, user.api.GetComms(), UdNetworkStatusFn, - username, email, phone, - cert, contactFile, address) + u, err := ud.NewManagerFromBackup(user.api, user.api.GetComms(), + UdNetworkStatusFn, cert, contactFile, address) if err != nil { return nil, err } @@ -445,9 +413,9 @@ type UdMultiLookupCallback interface { } type lookupResp struct { - id *id.ID - contact contact.Contact - err error + Id *id.ID + Contact contact.Contact + Err error } // MultiLookupUD returns the public key of all passed in IDs as known by the @@ -490,26 +458,27 @@ func MultiLookupUD(e2eID int, udContact []byte, cb UdMultiLookupCallback, return err } + jww.INFO.Printf("ud.MultiLookupUD(%s, %s)", idList, p.Timeout) + respCh := make(chan lookupResp, len(idList)) for _, uid := range idList { - localID := uid.DeepCopy() callback := func(c contact.Contact, err error) { respCh <- lookupResp{ - id: localID, - contact: c, - err: err, + Id: uid, + Contact: c, + Err: err, } } - go func() { + go func(localID *id.ID) { _, _, err := ud.Lookup(user.api, c, callback, localID, p) if err != nil { respCh <- lookupResp{ - id: localID, - contact: contact.Contact{}, - err: err, + Id: localID, + Contact: contact.Contact{}, + Err: err, } } - }() + }(uid.DeepCopy()) } @@ -519,14 +488,14 @@ func MultiLookupUD(e2eID int, udContact []byte, cb UdMultiLookupCallback, var errorString string for numReturned := 0; numReturned < len(idList); numReturned++ { response := <-respCh - if response.err != nil { - failedIDs = append(failedIDs, response.id) - marshaledContactList = append( - marshaledContactList, response.contact.Marshal()) - } else { + if response.Err != nil { + failedIDs = append(failedIDs, response.Id) errorString = errorString + fmt.Sprintf("Failed to lookup id %s: %+v", - response.id, response.err) + response.Id, response.Err) + } else { + marshaledContactList = append( + marshaledContactList, response.Contact.Marshal()) } } diff --git a/fileTransfer/manager.go b/fileTransfer/manager.go index 923218fcd2315dae4541de13dc75827f498b98d7..f4ef20744369953459f0f49c1fc24c5b57e18726 100644 --- a/fileTransfer/manager.go +++ b/fileTransfer/manager.go @@ -216,21 +216,21 @@ func NewManager(params Params, user FtE2e) (FileTransfer, error) { // StartProcesses starts the sending threads. Adheres to the xxdk.Service type. func (m *manager) StartProcesses() (stoppable.Stoppable, error) { // Construct stoppables + multiStoppable := stoppable.NewMulti(fileTransferStoppable) senderPoolStop := stoppable.NewMulti(workerPoolStoppable) batchBuilderStop := stoppable.NewSingle(batchBuilderThreadStoppable) // Start sending threads + go m.batchBuilderThread(batchBuilderStop) + // Note that the startSendingWorkerPool already creates thread for every // worker. As a result, there is no need to run it asynchronously. In fact, // running this asynchronously could result in a race condition where // some worker threads are not added to senderPoolStop before that stoppable // is added to the multiStoppable. m.startSendingWorkerPool(senderPoolStop) - go m.batchBuilderThread(batchBuilderStop) // Create a multi stoppable - multiStoppable := stoppable.NewMulti(fileTransferStoppable) - multiStoppable.Add(senderPoolStop) multiStoppable.Add(batchBuilderStop) return multiStoppable, nil diff --git a/fileTransfer/send.go b/fileTransfer/send.go index ea9bac2027cc65f2db3ede5ee8ef684cb1eb7f05..e4a107f7b3e588318056706dc2b8f6dba9bf3d02 100644 --- a/fileTransfer/send.go +++ b/fileTransfer/send.go @@ -74,16 +74,44 @@ func (m *manager) sendingThread(stop *stoppable.Single) { healthChanID := m.cmix.AddHealthCallback(func(b bool) { healthChan <- b }) for { select { + // A quit signal has been sent by the user. Typically, this is a result + // of a user-level shutdown of the client. case <-stop.Quit(): jww.DEBUG.Printf("[FT] Stopping file part sending thread (%s): "+ "stoppable triggered.", stop.Name()) m.cmix.RemoveHealthCallback(healthChanID) stop.ToStopped() return + + // If the network becomes unhealthy, we will cease sending files until + // it is resolved. case healthy := <-healthChan: + // There exists an edge case where an unhealthy signal is received + // due to a user-level shutdown, meaning the health tracker has + // ceased operation. If the health tracker is shutdown, a healthy + // signal will never be received, and this for loop will run + // infinitely. If we are caught in this loop, the stop's Quit() + // signal will never be received in case statement above, and this + // sender thread will run indefinitely. To avoid lingering threads + // in the case of a shutdown, we must actively listen for either the + // Quit() signal or a network health update here. for !healthy { - healthy = <-healthChan + select { + case <-stop.Quit(): + // Listen for a quit signal if the network becomes unhealthy + // before a user-level shutdown. + jww.DEBUG.Printf("[FT] Stopping file part sending "+ + "thread (%s): stoppable triggered.", stop.Name()) + m.cmix.RemoveHealthCallback(healthChanID) + stop.ToStopped() + return + + // Wait for a healthy signal before continuing to send files. + case healthy = <-healthChan: + } } + // A file part has been sent through the queue and must be sent by + // this thread. case packet := <-m.sendQueue: m.sendCmix(packet) } diff --git a/groupChat/send.go b/groupChat/send.go index 2f1b17c167b13f5c06dbbc3fd3223dc6c1ef4e0f..5c4d8dee34eca9362cce47115f223725c2ec7bfb 100644 --- a/groupChat/send.go +++ b/groupChat/send.go @@ -14,9 +14,7 @@ import ( "gitlab.com/elixxir/client/cmix/message" "gitlab.com/elixxir/client/cmix/rounds" gs "gitlab.com/elixxir/client/groupChat/groupStore" - "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/group" - "gitlab.com/elixxir/primitives/format" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/netTime" "io" @@ -64,7 +62,7 @@ func (m *manager) Send(groupID *id.ID, tag string, message []byte) ( timeNow := netTime.Now().Round(0) // Create a cMix message for each group member - groupMessages, err := m.newMessages(g, tag, message, timeNow) + groupMessages, msgId, err := m.newMessages(g, tag, message, timeNow) if err != nil { return rounds.Round{}, time.Time{}, group.MessageID{}, errors.Errorf(newCmixMsgErr, g.Name, g.ID, err) @@ -93,14 +91,39 @@ func (m *manager) Send(groupID *id.ID, tag string, message []byte) ( // newMessages builds a list of messages, one for each group chat member. func (m *manager) newMessages(g gs.Group, tag string, msg []byte, - timestamp time.Time) ([]cmix.TargetedCmixMessage, error) { + timestamp time.Time) ([]cmix.TargetedCmixMessage, group.MessageID, error) { // Create list of cMix messages messages := make([]cmix.TargetedCmixMessage, 0, len(g.Members)) rng := m.getRng().GetStream() defer rng.Close() - // Create cMix messages in parallel + // Generate initial internal message + maxCmixMessageLength := m.getCMix().GetMaxMessageLength() + + // Generate public message to determine what length internal message can be + pubMsg, err := newPublicMsg(maxCmixMessageLength) + if err != nil { + return nil, group.MessageID{}, errors.Errorf(newPublicMsgErr, err) + } + + // Generate internal message + intlMsg, err := newInternalMsg(pubMsg.GetPayloadSize()) + if err != nil { + return nil, group.MessageID{}, errors.Errorf(newInternalMsgErr, err) + } + + // Return an error if the message is too large to fit in the payload + if intlMsg.GetPayloadMaxSize() < len(msg) { + return nil, group.MessageID{}, errors.Errorf( + messageLenErr, len(msg), intlMsg.GetPayloadMaxSize()) + } + + // Generate internal message + internalMessagePayload := setInternalPayload(intlMsg, timestamp, + m.getReceptionIdentity().ID, msg) + + // Create cMix messages for _, member := range g.Members { // Do not send to the sender if m.getReceptionIdentity().ID.Cmp(member.ID) { @@ -108,21 +131,22 @@ func (m *manager) newMessages(g gs.Group, tag string, msg []byte, } // Add cMix message to list - cMixMsg, err := newCmixMsg(g, tag, msg, timestamp, member, rng, - m.getReceptionIdentity().ID, m.getCMix().GetMaxMessageLength()) + cMixMsg, err := newCmixMsg(g, tag, timestamp, member, rng, maxCmixMessageLength, + internalMessagePayload) if err != nil { - return nil, err + return nil, group.MessageID{}, err } messages = append(messages, cMixMsg) } - return messages, nil + return messages, group.NewMessageID(g.ID, internalMessagePayload), nil } // newCmixMsg generates a new cmix.TargetedCmixMessage for the given group // member -func newCmixMsg(g gs.Group, tag string, msg []byte, timestamp time.Time, - mem group.Member, rng io.Reader, senderId *id.ID, maxCmixMessageSize int) ( +func newCmixMsg(g gs.Group, tag string, timestamp time.Time, + mem group.Member, rng io.Reader, maxCmixMessageSize int, + internalMessagePayload []byte) ( cmix.TargetedCmixMessage, error) { // Initialize targeted message @@ -135,18 +159,12 @@ func newCmixMsg(g gs.Group, tag string, msg []byte, timestamp time.Time, }, } - // Create three message layers - pubMsg, intlMsg, err := newMessageParts(maxCmixMessageSize) + // Generate public message + pubMsg, err := newPublicMsg(maxCmixMessageSize) if err != nil { return cmixMsg, err } - // Return an error if the message is too large to fit in the payload - if intlMsg.GetPayloadMaxSize() < len(msg) { - return cmixMsg, errors.Errorf( - messageLenErr, len(msg), intlMsg.GetPayloadMaxSize()) - } - // Generate 256-bit salt salt, err := newSalt(rng) if err != nil { @@ -162,11 +180,9 @@ func newCmixMsg(g gs.Group, tag string, msg []byte, timestamp time.Time, return cmixMsg, errors.WithMessage(err, newKeyErr) } - // Generate internal message - payload := setInternalPayload(intlMsg, timestamp, senderId, msg) - // Encrypt internal message - encryptedPayload := group.Encrypt(key, cmixMsg.Fingerprint, payload) + encryptedPayload := group.Encrypt(key, cmixMsg.Fingerprint, + internalMessagePayload) // Generate public message cmixMsg.Payload = setPublicPayload(pubMsg, salt, encryptedPayload) @@ -177,35 +193,6 @@ func newCmixMsg(g gs.Group, tag string, msg []byte, timestamp time.Time, return cmixMsg, nil } -// getGroupMessageId builds the group message ID. -func getGroupMessageId(grp *cyclic.Group, groupId, senderId *id.ID, - timestamp time.Time, msg []byte) (group.MessageID, error) { - cmixMsg := format.NewMessage(grp.GetP().ByteLen()) - _, intlMsg, err := newMessageParts(cmixMsg.ContentsSize()) - if err != nil { - return group.MessageID{}, errors.WithMessage(err, - "Failed to make message parts for message ID") - } - return group.NewMessageID(groupId, - setInternalPayload(intlMsg, timestamp, senderId, msg)), nil -} - -// newMessageParts generates a public payload message and the internal payload -// message. An error is returned if the messages cannot fit in the payloadSize. -func newMessageParts(payloadSize int) (publicMsg, internalMsg, error) { - pubMsg, err := newPublicMsg(payloadSize) - if err != nil { - return pubMsg, internalMsg{}, errors.Errorf(newPublicMsgErr, err) - } - - intlMsg, err := newInternalMsg(pubMsg.GetPayloadSize()) - if err != nil { - return pubMsg, intlMsg, errors.Errorf(newInternalMsgErr, err) - } - - return pubMsg, intlMsg, nil -} - // newSalt generates a new salt of the specified size. func newSalt(rng io.Reader) ([group.SaltLen]byte, error) { var salt [group.SaltLen]byte diff --git a/groupChat/send_test.go b/groupChat/send_test.go index 5ecaa63efdca7f1d461fb59c67908988370accc5..c0d4f599f63e7e1ab853af0257c80cf5cb662a6e 100644 --- a/groupChat/send_test.go +++ b/groupChat/send_test.go @@ -78,9 +78,9 @@ func TestGroup_newCmixMsg_SaltReaderError(t *testing.T) { m, _ := newTestManager(t) _, err := newCmixMsg( - gs.Group{ID: id.NewIdFromString("test", id.User, t)}, "", - []byte{}, time.Time{}, group.Member{}, strings.NewReader(""), - m.getReceptionIdentity().ID, m.getCMix().GetMaxMessageLength()) + gs.Group{ID: id.NewIdFromString("test", id.User, t)}, + "", time.Time{}, group.Member{}, strings.NewReader(""), + m.getCMix().GetMaxMessageLength(), []byte("internal Message")) if err == nil || !strings.Contains(err.Error(), expectedErr) { t.Errorf("newCmixMsg failed to return the expected error"+ "\nexpected: %s\nreceived: %+v", expectedErr, err) @@ -97,40 +97,16 @@ func TestGroup_newCmixMsg_InternalMsgSizeError(t *testing.T) { // Create test parameters testMsg := make([]byte, 1500) - mem := group.Member{ID: id.NewIdFromString("memberID", id.User, t)} // Create cMix message prng = rand.New(rand.NewSource(42)) - _, err := newCmixMsg(g, "", testMsg, netTime.Now(), mem, prng, - m.getReceptionIdentity().ID, m.getCMix().GetMaxMessageLength()) + _, _, err := m.newMessages(g, "", testMsg, netTime.Now()) if err == nil || !strings.Contains(err.Error(), expectedErr) { t.Errorf("newCmixMsg failed to return the expected error"+ "\nexpected: %s\nreceived: %+v", expectedErr, err) } } -// Error path: payload size too small to fit publicMsg. -func Test_newMessageParts_PublicMsgSizeErr(t *testing.T) { - expectedErr := strings.SplitN(newPublicMsgErr, "%", 2)[0] - - _, _, err := newMessageParts(publicMinLen - 1) - if err == nil || !strings.Contains(err.Error(), expectedErr) { - t.Errorf("newMessageParts did not return the expected error."+ - "\nexpected: %s\nreceived: %+v", expectedErr, err) - } -} - -// Error path: payload size too small to fit internalMsg. -func Test_newMessageParts_InternalMsgSizeErr(t *testing.T) { - expectedErr := strings.SplitN(newInternalMsgErr, "%", 2)[0] - - _, _, err := newMessageParts(publicMinLen) - if err == nil || !strings.Contains(err.Error(), expectedErr) { - t.Errorf("newMessageParts did not return the expected error."+ - "\nexpected: %s\nreceived: %+v", expectedErr, err) - } -} - // Tests the consistency of newSalt. func Test_newSalt_Consistency(t *testing.T) { prng := rand.New(rand.NewSource(42)) diff --git a/stoppable/multi.go b/stoppable/multi.go index 3ac77c7507fb058af1deac2b098121b16d3569b0..456e376a7b71851f254f786ae8a13d2e086ee60f 100644 --- a/stoppable/multi.go +++ b/stoppable/multi.go @@ -121,15 +121,15 @@ func (m *Multi) Close() error { m.once.Do(func() { var wg sync.WaitGroup - jww.TRACE.Printf("Sending on quit channel to multi stoppable %q.", - m.Name()) + jww.TRACE.Printf("Sending on quit channel to multi stoppable %q with subprocesseses %v.", + m.Name(), m.GetRunningProcesses()) m.mux.Lock() // Attempt to stop each stoppable in its own goroutine for _, stoppable := range m.stoppables { wg.Add(1) - go func(stoppable Stoppable) { - if stoppable.Close() != nil { + go func(s Stoppable) { + if s.Close() != nil { atomic.AddUint32(&numErrors, 1) } wg.Done() diff --git a/stoppable/single.go b/stoppable/single.go index ea11ab42b586c3c1543509b5f575cda75f0cfca5..5af656b67f92e8e1e6dfb8404a37b73a698e5d3b 100644 --- a/stoppable/single.go +++ b/stoppable/single.go @@ -110,6 +110,10 @@ func (s *Single) Close() error { // Send on quit channel s.quit <- struct{}{} + + jww.TRACE.Printf("Sent to quit channel for single stoppable %q.", + s.Name()) + }) if err != nil { diff --git a/ud/lookup.go b/ud/lookup.go index 569dc5b99578e9487c350028eb5e4649cbf8efc1..867c2900cbf598be9e041f1de1244a9379e0c919 100644 --- a/ud/lookup.go +++ b/ud/lookup.go @@ -44,30 +44,6 @@ func Lookup(user udE2e, return lookup(net, rng, uid, grp, udContact, callback, p) } -// BatchLookup performs a Lookup operation on a list of user IDs. -// The lookup performs a callback on each lookup on the returned contact object -// constructed from the response. -func BatchLookup(udContact contact.Contact, - net udCmix, callback lookupCallback, - rng csprng.Source, - uids []*id.ID, grp *cyclic.Group, - p single.RequestParams) { - jww.INFO.Printf("ud.BatchLookup(%s, %s)", uids, p.Timeout) - - for _, uid := range uids { - go func(localUid *id.ID) { - _, _, err := lookup(net, rng, localUid, grp, - udContact, callback, p) - if err != nil { - jww.WARN.Printf("Failed batch lookup on user %s: %v", - localUid, err) - } - }(uid) - } - - return -} - // lookup is a helper function which sends a lookup request to the user discovery // service. It will construct a contact object off of the returned public key. // The callback will be called on that contact object. diff --git a/ud/manager.go b/ud/manager.go index fd57a886b7046c09cfb33bf6a58adc0d752730e5..9ea87cf84bef02982f8830ba8afa68b8149938dc 100644 --- a/ud/manager.go +++ b/ud/manager.go @@ -129,12 +129,8 @@ func NewOrLoad(user udE2e, comms Comms, follower udNetworkStatus, // - user is an interface that adheres to the xxdk.E2e object. // - comms is an interface that adheres to client.Comms object. // - follower is a method off of xxdk.Cmix which returns the network follower's status. -// - username is the name of the user as it is registered with UD. This will be what the end user -// provides if through the bindings. // - networkValidationSig is a signature provided by the network (i.e. the client registrar). This may // be nil, however UD may return an error in some cases (e.g. in a production level environment). -// - email is a fact.Fact (type Email) which has been registered with UD already. -// - phone is a fact.Fact (type Phone) which has been registered with UD already. // - cert is the TLS certificate for the UD server this call will connect with. // - contactFile is the data within a marshalled contact.Contact. This represents the // contact file of the server this call will connect with. @@ -142,9 +138,9 @@ func NewOrLoad(user udE2e, comms Comms, follower udNetworkStatus, // // Returns // - A Manager object which is registered to the specified UD service. -func NewManagerFromBackup(user udE2e, comms Comms, follower udNetworkStatus, - username, email, phone fact.Fact, - cert, contactFile []byte, address string) (*Manager, error) { +func NewManagerFromBackup(user udE2e, comms Comms, + follower udNetworkStatus, cert, contactFile []byte, + address string) (*Manager, error) { jww.INFO.Println("ud.NewManagerFromBackup()") if follower() != xxdk.Running { return nil, errors.New( @@ -165,13 +161,6 @@ func NewManagerFromBackup(user udE2e, comms Comms, follower udNetworkStatus, return nil, err } - // Put any passed in missing facts into store - err = m.store.BackUpMissingFacts(username, email, phone) - if err != nil { - return nil, errors.WithMessage(err, "Failed to restore UD store "+ - "from backup") - } - // Set as registered. Since it's from a backup, // the user is already registered if err = setRegistered(m.getKv()); err != nil {