diff --git a/bindings/fileTransfer.go b/bindings/fileTransfer.go index 5c51b36dd8a183ea06c348731b183d31f74a5375..b0182ed6e2cb9c018a54ee716946e60cbb74f328 100644 --- a/bindings/fileTransfer.go +++ b/bindings/fileTransfer.go @@ -125,7 +125,8 @@ type FileTransferReceiveProgressCallback interface { // Parameters: // - e2eID - e2e object ID in the tracker // - paramsJSON - JSON marshalled fileTransfer.Params -func InitFileTransfer(e2eID int, receiveFileCallback ReceiveFileCallback, e2eFileTransferParamsJson, fileTransferParamsJson []byte) (*FileTransfer, error) { +func InitFileTransfer(e2eID int, receiveFileCallback ReceiveFileCallback, + e2eFileTransferParamsJson, fileTransferParamsJson []byte) (*FileTransfer, error) { // Get user from singleton user, err := e2eTrackerSingleton.get(e2eID) @@ -133,10 +134,6 @@ func InitFileTransfer(e2eID int, receiveFileCallback ReceiveFileCallback, e2eFil return nil, err } - // User info - myID := user.api.GetReceptionIdentity().ID - rng := user.api.GetRng() - e2eFileTransferParams, err := parseE2eFileTransferParams(e2eFileTransferParamsJson) if err != nil { return nil, err @@ -148,8 +145,7 @@ func InitFileTransfer(e2eID int, receiveFileCallback ReceiveFileCallback, e2eFil } // Create file transfer manager - m, err := fileTransfer.NewManager(fileTransferParams, myID, - user.api.GetCmix(), user.api.GetStorage(), rng) + m, err := fileTransfer.NewManager(fileTransferParams, user.api) rcb := func(tid *ftCrypto.TransferID, fileName, fileType string, sender *id.ID, size uint32, preview []byte) { @@ -163,7 +159,7 @@ func InitFileTransfer(e2eID int, receiveFileCallback ReceiveFileCallback, e2eFil })) } - w, err := e2e.NewWrapper(rcb, e2eFileTransferParams, m, myID, user.api.GetE2E(), user.api.GetCmix()) + w, err := e2e.NewWrapper(rcb, e2eFileTransferParams, m, user.api) if err != nil { return nil, err } diff --git a/cmd/fileTransfer.go b/cmd/fileTransfer.go index 0a6cfbf97012e24027c3f850a23f6a19fc8051d4..1b0e2fe5c79da6c8f5d8494e7b9d2b618a0f83d0 100644 --- a/cmd/fileTransfer.go +++ b/cmd/fileTransfer.go @@ -153,11 +153,7 @@ func initFileTransferManager(user *xxdk.E2e, maxThroughput int) ( } // Create new manager - manager, err := ft.NewManager(p, - user.GetReceptionIdentity().ID, - user.GetCmix(), - user.GetStorage(), - user.GetRng()) + manager, err := ft.NewManager(p, user) if err != nil { jww.FATAL.Panicf( "[FT] Failed to create new file transfer manager: %+v", err) @@ -170,8 +166,7 @@ func initFileTransferManager(user *xxdk.E2e, maxThroughput int) ( } e2eParams := ftE2e.DefaultParams() - e2eFt, err := ftE2e.NewWrapper(receiveCB, e2eParams, manager, - user.GetReceptionIdentity().ID, user.GetE2E(), user.GetCmix()) + e2eFt, err := ftE2e.NewWrapper(receiveCB, e2eParams, manager, user) if err != nil { jww.FATAL.Panicf( "[FT] Failed to create new e2e file transfer wrapper: %+v", err) diff --git a/fileTransfer/connect/params.go b/fileTransfer/connect/params.go index 93a3a44a1f6a6d001724875bd85ba5fd13374a54..bd36ef4f6addca4c0f7f6de98f9e7224bb725187 100644 --- a/fileTransfer/connect/params.go +++ b/fileTransfer/connect/params.go @@ -15,14 +15,14 @@ const ( defaultNotifyUponCompletion = true ) -// Params contains parameters used for Connection file transfer. +// Params contains parameters used for connection file transfer. type Params struct { // NotifyUponCompletion indicates if a final notification message is sent // to the recipient on completion of file transfer. If true, the ping is NotifyUponCompletion bool } -// paramsDisk will be the marshal-able and umarshal-able object. +// paramsDisk will be the marshal-able and unmarshalable object. type paramsDisk struct { NotifyUponCompletion bool } @@ -34,8 +34,8 @@ func DefaultParams() Params { } } -// GetParameters returns the default Params, or override with given -// parameters, if set. +// GetParameters returns the default Params, or override with given parameters, +// if set. func GetParameters(params string) (Params, error) { p := DefaultParams() if len(params) > 0 { diff --git a/fileTransfer/connect/send.go b/fileTransfer/connect/send.go index 0d2b2a56113bd5604d866716e3f080959ab68743..2b00c8ba71cc8817a2764025ae34f8e4bdcc3438 100644 --- a/fileTransfer/connect/send.go +++ b/fileTransfer/connect/send.go @@ -37,7 +37,7 @@ const ( // sendNewFileTransferMessage sends an E2E message to the recipient informing // them of the incoming file transfer. func sendNewFileTransferMessage( - transferInfo []byte, connectionHandler Connection) error { + transferInfo []byte, connectionHandler connection) error { // Get E2E parameters params := e2e.GetDefaultParams() @@ -56,7 +56,7 @@ func sendNewFileTransferMessage( // sendEndFileTransferMessage sends an E2E message to the recipient informing // them that all file parts have arrived once the network is healthy. -func sendEndFileTransferMessage(cmix ft.Cmix, connectionHandler Connection) { +func sendEndFileTransferMessage(cmix ft.Cmix, connectionHandler connection) { callbackID := make(chan uint64, 1) callbackID <- cmix.AddHealthCallback( func(healthy bool) { diff --git a/fileTransfer/connect/utils_test.go b/fileTransfer/connect/utils_test.go index 20adcb6eb701ef338601f6ad8a03a1ba67428779..7d0fb6aeba668c2fcccf89cd881746007a84a101 100644 --- a/fileTransfer/connect/utils_test.go +++ b/fileTransfer/connect/utils_test.go @@ -11,28 +11,66 @@ import ( jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/catalog" "gitlab.com/elixxir/client/cmix" + "gitlab.com/elixxir/client/cmix/gateway" + "gitlab.com/elixxir/client/cmix/identity" "gitlab.com/elixxir/client/cmix/identity/receptionID" "gitlab.com/elixxir/client/cmix/message" "gitlab.com/elixxir/client/cmix/rounds" "gitlab.com/elixxir/client/e2e" "gitlab.com/elixxir/client/e2e/ratchet/partner" "gitlab.com/elixxir/client/e2e/receive" + "gitlab.com/elixxir/client/stoppable" + "gitlab.com/elixxir/client/storage" + "gitlab.com/elixxir/client/storage/user" "gitlab.com/elixxir/client/storage/versioned" + "gitlab.com/elixxir/client/xxdk" + "gitlab.com/elixxir/comms/network" "gitlab.com/elixxir/crypto/cyclic" e2eCrypto "gitlab.com/elixxir/crypto/e2e" "gitlab.com/elixxir/crypto/fastRNG" "gitlab.com/elixxir/ekv" "gitlab.com/elixxir/primitives/format" + "gitlab.com/elixxir/primitives/version" + "gitlab.com/xx_network/comms/connect" "gitlab.com/xx_network/crypto/csprng" "gitlab.com/xx_network/crypto/large" + "gitlab.com/xx_network/crypto/signature/rsa" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/id/ephemeral" + "gitlab.com/xx_network/primitives/ndf" "gitlab.com/xx_network/primitives/netTime" "sync" "testing" "time" ) +//////////////////////////////////////////////////////////////////////////////// +// Mock xxdk.E2e // +//////////////////////////////////////////////////////////////////////////////// + +type mockUser struct { + rid xxdk.ReceptionIdentity + c cmix.Client + s storage.Session + rng *fastRNG.StreamGenerator +} + +func newMockUser(rid *id.ID, c cmix.Client, s storage.Session, + rng *fastRNG.StreamGenerator) *mockUser { + return &mockUser{ + rid: xxdk.ReceptionIdentity{ID: rid}, + c: c, + s: s, + rng: rng, + } +} + +func (m *mockUser) GetStorage() storage.Session { return m.s } +func (m *mockUser) GetReceptionIdentity() xxdk.ReceptionIdentity { return m.rid } +func (m *mockUser) GetCmix() cmix.Client { return m.c } +func (m *mockUser) GetRng() *fastRNG.StreamGenerator { return m.rng } +func (m *mockUser) GetE2E() e2e.Handler { return nil } + //////////////////////////////////////////////////////////////////////////////// // Mock cMix // //////////////////////////////////////////////////////////////////////////////// @@ -70,11 +108,18 @@ func newMockCmix( } } +func (m *mockCmix) Follow(cmix.ClientErrorReport) (stoppable.Stoppable, error) { panic("implement me") } + func (m *mockCmix) GetMaxMessageLength() int { msg := format.NewMessage(m.numPrimeBytes) return msg.ContentsSize() } +func (m *mockCmix) Send(*id.ID, format.Fingerprint, message.Service, []byte, + []byte, cmix.CMIXParams) (id.Round, ephemeral.Id, error) { + panic("implement me") +} + func (m *mockCmix) SendMany(messages []cmix.TargetedCmixMessage, _ cmix.CMIXParams) (id.Round, []ephemeral.Id, error) { m.handler.Lock() @@ -91,6 +136,10 @@ func (m *mockCmix) SendMany(messages []cmix.TargetedCmixMessage, return 42, []ephemeral.Id{}, nil } +func (m *mockCmix) AddIdentity(*id.ID, time.Time, bool) { panic("implement me") } +func (m *mockCmix) RemoveIdentity(*id.ID) { panic("implement me") } +func (m *mockCmix) GetIdentity(*id.ID) (identity.TrackedID, error) { panic("implement me") } + func (m *mockCmix) AddFingerprint(_ *id.ID, fp format.Fingerprint, mp message.Processor) error { m.Lock() defer m.Unlock() @@ -104,13 +153,14 @@ func (m *mockCmix) DeleteFingerprint(_ *id.ID, fp format.Fingerprint) { m.handler.Unlock() } -func (m *mockCmix) CheckInProgressMessages() {} - -func (m *mockCmix) IsHealthy() bool { - return m.health -} - -func (m *mockCmix) WasHealthy() bool { return true } +func (m *mockCmix) DeleteClientFingerprints(*id.ID) { panic("implement me") } +func (m *mockCmix) AddService(*id.ID, message.Service, message.Processor) { panic("implement me") } +func (m *mockCmix) DeleteService(*id.ID, message.Service, message.Processor) { panic("implement me") } +func (m *mockCmix) DeleteClientService(*id.ID) { panic("implement me") } +func (m *mockCmix) TrackServices(message.ServicesTracker) { panic("implement me") } +func (m *mockCmix) CheckInProgressMessages() {} +func (m *mockCmix) IsHealthy() bool { return m.health } +func (m *mockCmix) WasHealthy() bool { return true } func (m *mockCmix) AddHealthCallback(f func(bool)) uint64 { m.Lock() @@ -130,12 +180,35 @@ func (m *mockCmix) RemoveHealthCallback(healthID uint64) { delete(m.healthCBs, healthID) } +func (m *mockCmix) HasNode(*id.ID) bool { panic("implement me") } +func (m *mockCmix) NumRegisteredNodes() int { panic("implement me") } +func (m *mockCmix) TriggerNodeRegistration(*id.ID) { panic("implement me") } + func (m *mockCmix) GetRoundResults(_ time.Duration, roundCallback cmix.RoundEventCallback, _ ...id.Round) error { go roundCallback(true, false, map[id.Round]cmix.RoundResult{42: {}}) return nil } +func (m *mockCmix) LookupHistoricalRound(id.Round, rounds.RoundResultCallback) error { + panic("implement me") +} +func (m *mockCmix) SendToAny(func(host *connect.Host) (interface{}, error), *stoppable.Single) (interface{}, error) { + panic("implement me") +} +func (m *mockCmix) SendToPreferred([]*id.ID, gateway.SendToPreferredFunc, *stoppable.Single, time.Duration) (interface{}, error) { + panic("implement me") +} +func (m *mockCmix) SetGatewayFilter(gateway.Filter) { panic("implement me") } +func (m *mockCmix) GetHostParams() connect.HostParams { panic("implement me") } +func (m *mockCmix) GetAddressSpace() uint8 { panic("implement me") } +func (m *mockCmix) RegisterAddressSpaceNotification(string) (chan uint8, error) { + panic("implement me") +} +func (m *mockCmix) UnregisterAddressSpaceNotification(string) { panic("implement me") } +func (m *mockCmix) GetInstance() *network.Instance { panic("implement me") } +func (m *mockCmix) GetVerboseRounds() string { panic("implement me") } + //////////////////////////////////////////////////////////////////////////////// // Mock Connection Handler // //////////////////////////////////////////////////////////////////////////////// @@ -165,8 +238,8 @@ func newMockConnectionHandler() *mockConnectionHandler { } } -// Tests that mockConnection adheres to the Connection interface. -var _ Connection = (*mockConnection)(nil) +// Tests that mockConnection adheres to the connection interface. +var _ connection = (*mockConnection)(nil) type mockConnection struct { myID *id.ID @@ -237,5 +310,34 @@ func newMockStorage() *mockStorage { } } -func (m *mockStorage) GetKV() *versioned.KV { return m.kv } -func (m *mockStorage) GetCmixGroup() *cyclic.Group { return m.cmixGroup } +func (m *mockStorage) GetClientVersion() version.Version { panic("implement me") } +func (m *mockStorage) Get(string) (*versioned.Object, error) { panic("implement me") } +func (m *mockStorage) Set(string, *versioned.Object) error { panic("implement me") } +func (m *mockStorage) Delete(string) error { panic("implement me") } +func (m *mockStorage) GetKV() *versioned.KV { return m.kv } +func (m *mockStorage) GetCmixGroup() *cyclic.Group { return m.cmixGroup } +func (m *mockStorage) GetE2EGroup() *cyclic.Group { panic("implement me") } +func (m *mockStorage) ForwardRegistrationStatus(storage.RegistrationStatus) error { + panic("implement me") +} +func (m *mockStorage) GetRegistrationStatus() storage.RegistrationStatus { panic("implement me") } +func (m *mockStorage) SetRegCode(string) { panic("implement me") } +func (m *mockStorage) GetRegCode() (string, error) { panic("implement me") } +func (m *mockStorage) SetNDF(*ndf.NetworkDefinition) { panic("implement me") } +func (m *mockStorage) GetNDF() *ndf.NetworkDefinition { panic("implement me") } +func (m *mockStorage) GetTransmissionID() *id.ID { panic("implement me") } +func (m *mockStorage) GetTransmissionSalt() []byte { panic("implement me") } +func (m *mockStorage) GetReceptionID() *id.ID { panic("implement me") } +func (m *mockStorage) GetReceptionSalt() []byte { panic("implement me") } +func (m *mockStorage) GetReceptionRSA() *rsa.PrivateKey { panic("implement me") } +func (m *mockStorage) GetTransmissionRSA() *rsa.PrivateKey { panic("implement me") } +func (m *mockStorage) IsPrecanned() bool { panic("implement me") } +func (m *mockStorage) SetUsername(string) error { panic("implement me") } +func (m *mockStorage) GetUsername() (string, error) { panic("implement me") } +func (m *mockStorage) PortableUserInfo() user.Info { panic("implement me") } +func (m *mockStorage) GetTransmissionRegistrationValidationSignature() []byte { panic("implement me") } +func (m *mockStorage) GetReceptionRegistrationValidationSignature() []byte { panic("implement me") } +func (m *mockStorage) GetRegistrationTimestamp() time.Time { panic("implement me") } +func (m *mockStorage) SetTransmissionRegistrationValidationSignature([]byte) { panic("implement me") } +func (m *mockStorage) SetReceptionRegistrationValidationSignature([]byte) { panic("implement me") } +func (m *mockStorage) SetRegistrationTimestamp(int64) { panic("implement me") } diff --git a/fileTransfer/connect/wrapper.go b/fileTransfer/connect/wrapper.go index 9f4c3a99a3902373da30e0f74615f8a673694b5a..60a3f6641da53aad60d53a29feb533180738556b 100644 --- a/fileTransfer/connect/wrapper.go +++ b/fileTransfer/connect/wrapper.go @@ -33,12 +33,12 @@ type Wrapper struct { p Params cmix ft.Cmix - conn Connection + conn connection } -// Connection interface matches a subset of the connect.Connection methods used +// connection interface matches a subset of the connect.Connection methods used // by the Wrapper for easier testing. -type Connection interface { +type connection interface { GetPartner() partner.Manager SendE2E(mt catalog.MessageType, payload []byte, params e2e.Params) ( []id.Round, e2eCrypto.MessageID, time.Time, error) @@ -46,9 +46,9 @@ type Connection interface { newListener receive.Listener) (receive.ListenerID, error) } -// NewWrapper generates a new file transfer manager using Connection E2E. +// NewWrapper generates a new file transfer manager using connection E2E. func NewWrapper(receiveCB ft.ReceiveCallback, p Params, ft ft.FileTransfer, - conn Connection, cmix ft.Cmix) (*Wrapper, error) { + conn connection, cmix ft.Cmix) (*Wrapper, error) { w := &Wrapper{ receiveCB: receiveCB, ft: ft, @@ -88,7 +88,7 @@ func (w *Wrapper) MaxPreviewSize() int { // Send initiates the sending of a file to the connection partner and returns a // transfer ID that uniquely identifies this file transfer. The initial and -// final messages are sent via Connection E2E. +// final messages are sent via connection E2E. func (w *Wrapper) Send(fileName, fileType string, fileData []byte, retry float32, preview []byte, progressCB ft.SentProgressCallback, period time.Duration) ( @@ -116,7 +116,7 @@ func (w *Wrapper) RegisterSentProgressCallback(tid *ftCrypto.TransferID, return w.ft.RegisterSentProgressCallback(tid, modifiedProgressCB, period) } -// addEndMessageToCallback adds the sending of a Connection E2E message when +// addEndMessageToCallback adds the sending of a connection E2E message when // the transfer completed to the callback. If NotifyUponCompletion is not set, // then the message is not sent. func (w *Wrapper) addEndMessageToCallback(progressCB ft.SentProgressCallback) ft.SentProgressCallback { diff --git a/fileTransfer/connect/wrapper_test.go b/fileTransfer/connect/wrapper_test.go index 0b7bd0b9f544dcead038b49ffb2c410d7d364bc5..a9b7552044d439c31c25a15e1cfb01be13f886bf 100644 --- a/fileTransfer/connect/wrapper_test.go +++ b/fileTransfer/connect/wrapper_test.go @@ -26,7 +26,7 @@ import ( ) // Tests that Connection adheres to the connect.Connection interface. -var _ Connection = (connect.Connection)(nil) +var _ connection = (connect.Connection)(nil) // Smoke test of the entire file transfer system. func Test_FileTransfer_Smoke(t *testing.T) { @@ -61,8 +61,9 @@ func Test_FileTransfer_Smoke(t *testing.T) { endE2eChan1 := make(chan receive.Message, 3) conn1 := newMockConnection(myID1, myID2, e2eHandler, t) _, _ = conn1.RegisterListener(catalog.EndFileTransfer, newMockListener(endE2eChan1)) - cmix1 := newMockCmix(myID1, cMixHandler, storage1) - ftManager1, err := ft.NewManager(ftParams, myID1, cmix1, storage1, rngGen) + cMix1 := newMockCmix(myID1, cMixHandler, storage1) + user1 := newMockUser(myID1, cMix1, storage1, rngGen) + ftManager1, err := ft.NewManager(ftParams, user1) if err != nil { t.Errorf("Failed to make new file transfer manager: %+v", err) } @@ -70,7 +71,7 @@ func Test_FileTransfer_Smoke(t *testing.T) { if err != nil { t.Errorf("Failed to start processes for manager 1: %+v", err) } - m1, err := NewWrapper(receiveCB1, params, ftManager1, conn1, cmix1) + m1, err := NewWrapper(receiveCB1, params, ftManager1, conn1, cMix1) if err != nil { t.Errorf("Failed to create new file transfer manager 1: %+v", err) } @@ -86,8 +87,9 @@ func Test_FileTransfer_Smoke(t *testing.T) { endE2eChan2 := make(chan receive.Message, 3) conn2 := newMockConnection(myID2, myID1, e2eHandler, t) _, _ = conn2.RegisterListener(catalog.EndFileTransfer, newMockListener(endE2eChan2)) - cmix2 := newMockCmix(myID1, cMixHandler, storage2) - ftManager2, err := ft.NewManager(ftParams, myID2, cmix2, storage2, rngGen) + cMix2 := newMockCmix(myID1, cMixHandler, storage2) + user2 := newMockUser(myID2, cMix2, storage2, rngGen) + ftManager2, err := ft.NewManager(ftParams, user2) if err != nil { t.Errorf("Failed to make new file transfer manager: %+v", err) } @@ -95,7 +97,7 @@ func Test_FileTransfer_Smoke(t *testing.T) { if err != nil { t.Errorf("Failed to start processes for manager 2: %+v", err) } - m2, err := NewWrapper(receiveCB2, params, ftManager2, conn2, cmix2) + m2, err := NewWrapper(receiveCB2, params, ftManager2, conn2, cMix2) if err != nil { t.Errorf("Failed to create new file transfer manager 2: %+v", err) } diff --git a/fileTransfer/e2e/send.go b/fileTransfer/e2e/send.go index 8719e0b7bc582e753918ffda876a9da31a3f8bba..a073d0afe841a04026081b9033e0e1cc5c164062 100644 --- a/fileTransfer/e2e/send.go +++ b/fileTransfer/e2e/send.go @@ -38,7 +38,7 @@ const ( // sendNewFileTransferMessage sends an E2E message to the recipient informing // them of the incoming file transfer. func sendNewFileTransferMessage( - recipient *id.ID, transferInfo []byte, e2eHandler E2e) error { + recipient *id.ID, transferInfo []byte, e2eHandler e2eHandler) error { // Get E2E parameters params := e2e.GetDefaultParams() @@ -57,7 +57,7 @@ func sendNewFileTransferMessage( // sendEndFileTransferMessage sends an E2E message to the recipient informing // them that all file parts have arrived once the network is healthy. -func sendEndFileTransferMessage(recipient *id.ID, cmix ft.Cmix, e2eHandler E2e) { +func sendEndFileTransferMessage(recipient *id.ID, cmix ft.Cmix, e2eHandler e2eHandler) { callbackID := make(chan uint64, 1) callbackID <- cmix.AddHealthCallback( func(healthy bool) { diff --git a/fileTransfer/e2e/utils_test.go b/fileTransfer/e2e/utils_test.go index b5c57bcc2ed01ba1a8e9d07aa3401569bf23a579..633483607275fb4e2714ccc67f1852a22c1d78a8 100644 --- a/fileTransfer/e2e/utils_test.go +++ b/fileTransfer/e2e/utils_test.go @@ -8,31 +8,74 @@ package e2e import ( + "github.com/cloudflare/circl/dh/sidh" jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/catalog" "gitlab.com/elixxir/client/cmix" + "gitlab.com/elixxir/client/cmix/gateway" + "gitlab.com/elixxir/client/cmix/identity" "gitlab.com/elixxir/client/cmix/identity/receptionID" "gitlab.com/elixxir/client/cmix/message" "gitlab.com/elixxir/client/cmix/rounds" "gitlab.com/elixxir/client/e2e" + "gitlab.com/elixxir/client/e2e/ratchet/partner" + "gitlab.com/elixxir/client/e2e/ratchet/partner/session" "gitlab.com/elixxir/client/e2e/receive" + "gitlab.com/elixxir/client/stoppable" + "gitlab.com/elixxir/client/storage" + userStorage "gitlab.com/elixxir/client/storage/user" "gitlab.com/elixxir/client/storage/versioned" + "gitlab.com/elixxir/client/xxdk" + "gitlab.com/elixxir/comms/network" "gitlab.com/elixxir/crypto/cyclic" - e2eCrypto "gitlab.com/elixxir/crypto/e2e" + e "gitlab.com/elixxir/crypto/e2e" "gitlab.com/elixxir/crypto/fastRNG" "gitlab.com/elixxir/ekv" "gitlab.com/elixxir/primitives/format" + "gitlab.com/elixxir/primitives/version" + "gitlab.com/xx_network/comms/connect" "gitlab.com/xx_network/crypto/csprng" "gitlab.com/xx_network/crypto/large" + "gitlab.com/xx_network/crypto/signature/rsa" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/id/ephemeral" + "gitlab.com/xx_network/primitives/ndf" "gitlab.com/xx_network/primitives/netTime" "sync" "time" ) //////////////////////////////////////////////////////////////////////////////// -// Mock cMix // +// Mock xxdk.E2e // +//////////////////////////////////////////////////////////////////////////////// + +type mockUser struct { + rid xxdk.ReceptionIdentity + c cmix.Client + e2e e2e.Handler + s storage.Session + rng *fastRNG.StreamGenerator +} + +func newMockUser(rid *id.ID, c cmix.Client, e2e e2e.Handler, s storage.Session, + rng *fastRNG.StreamGenerator) *mockUser { + return &mockUser{ + rid: xxdk.ReceptionIdentity{ID: rid}, + c: c, + e2e: e2e, + s: s, + rng: rng, + } +} + +func (m *mockUser) GetStorage() storage.Session { return m.s } +func (m *mockUser) GetReceptionIdentity() xxdk.ReceptionIdentity { return m.rid } +func (m *mockUser) GetCmix() cmix.Client { return m.c } +func (m *mockUser) GetE2E() e2e.Handler { return m.e2e } +func (m *mockUser) GetRng() *fastRNG.StreamGenerator { return m.rng } + +//////////////////////////////////////////////////////////////////////////////// +// Mock cMix // //////////////////////////////////////////////////////////////////////////////// type mockCmixHandler struct { @@ -67,11 +110,18 @@ func newMockCmix(myID *id.ID, handler *mockCmixHandler, storage *mockStorage) *m } } +func (m *mockCmix) Follow(cmix.ClientErrorReport) (stoppable.Stoppable, error) { panic("implement me") } + func (m *mockCmix) GetMaxMessageLength() int { msg := format.NewMessage(m.numPrimeBytes) return msg.ContentsSize() } +func (m *mockCmix) Send(*id.ID, format.Fingerprint, message.Service, []byte, + []byte, cmix.CMIXParams) (id.Round, ephemeral.Id, error) { + panic("implement me") +} + func (m *mockCmix) SendMany(messages []cmix.TargetedCmixMessage, _ cmix.CMIXParams) (id.Round, []ephemeral.Id, error) { m.handler.Lock() @@ -88,6 +138,10 @@ func (m *mockCmix) SendMany(messages []cmix.TargetedCmixMessage, return 42, []ephemeral.Id{}, nil } +func (m *mockCmix) AddIdentity(*id.ID, time.Time, bool) { panic("implement me") } +func (m *mockCmix) RemoveIdentity(*id.ID) { panic("implement me") } +func (m *mockCmix) GetIdentity(*id.ID) (identity.TrackedID, error) { panic("implement me") } + func (m *mockCmix) AddFingerprint(_ *id.ID, fp format.Fingerprint, mp message.Processor) error { m.Lock() defer m.Unlock() @@ -101,13 +155,14 @@ func (m *mockCmix) DeleteFingerprint(_ *id.ID, fp format.Fingerprint) { m.handler.Unlock() } -func (m *mockCmix) CheckInProgressMessages() {} - -func (m *mockCmix) IsHealthy() bool { - return m.health -} - -func (m *mockCmix) WasHealthy() bool { return true } +func (m *mockCmix) DeleteClientFingerprints(*id.ID) { panic("implement me") } +func (m *mockCmix) AddService(*id.ID, message.Service, message.Processor) { panic("implement me") } +func (m *mockCmix) DeleteService(*id.ID, message.Service, message.Processor) { panic("implement me") } +func (m *mockCmix) DeleteClientService(*id.ID) { panic("implement me") } +func (m *mockCmix) TrackServices(message.ServicesTracker) { panic("implement me") } +func (m *mockCmix) CheckInProgressMessages() {} +func (m *mockCmix) IsHealthy() bool { return m.health } +func (m *mockCmix) WasHealthy() bool { return true } func (m *mockCmix) AddHealthCallback(f func(bool)) uint64 { m.Lock() @@ -127,15 +182,39 @@ func (m *mockCmix) RemoveHealthCallback(healthID uint64) { delete(m.healthCBs, healthID) } +func (m *mockCmix) HasNode(*id.ID) bool { panic("implement me") } +func (m *mockCmix) NumRegisteredNodes() int { panic("implement me") } +func (m *mockCmix) TriggerNodeRegistration(*id.ID) { panic("implement me") } + func (m *mockCmix) GetRoundResults(_ time.Duration, roundCallback cmix.RoundEventCallback, _ ...id.Round) error { go roundCallback(true, false, map[id.Round]cmix.RoundResult{42: {}}) return nil } +func (m *mockCmix) LookupHistoricalRound(id.Round, rounds.RoundResultCallback) error { + panic("implement me") +} +func (m *mockCmix) SendToAny(func(host *connect.Host) (interface{}, error), *stoppable.Single) (interface{}, error) { + panic("implement me") +} +func (m *mockCmix) SendToPreferred([]*id.ID, gateway.SendToPreferredFunc, *stoppable.Single, time.Duration) (interface{}, error) { + panic("implement me") +} +func (m *mockCmix) SetGatewayFilter(gateway.Filter) { panic("implement me") } +func (m *mockCmix) GetHostParams() connect.HostParams { panic("implement me") } +func (m *mockCmix) GetAddressSpace() uint8 { panic("implement me") } +func (m *mockCmix) RegisterAddressSpaceNotification(string) (chan uint8, error) { + panic("implement me") +} +func (m *mockCmix) UnregisterAddressSpaceNotification(string) { panic("implement me") } +func (m *mockCmix) GetInstance() *network.Instance { panic("implement me") } +func (m *mockCmix) GetVerboseRounds() string { panic("implement me") } + //////////////////////////////////////////////////////////////////////////////// // Mock E2E Handler // //////////////////////////////////////////////////////////////////////////////// + func newMockListener(hearChan chan receive.Message) *mockListener { return &mockListener{hearChan: hearChan} } @@ -176,9 +255,11 @@ func newMockE2e(myID *id.ID, handler *mockE2eHandler) *mockE2e { } } +func (m *mockE2e) StartProcesses() (stoppable.Stoppable, error) { panic("implement me") } + // SendE2E adds the message to the e2e handler map. -func (m *mockE2e) SendE2E(mt catalog.MessageType, recipient *id.ID, payload []byte, - _ e2e.Params) ([]id.Round, e2eCrypto.MessageID, time.Time, error) { +func (m *mockE2e) SendE2E(mt catalog.MessageType, recipient *id.ID, + payload []byte, _ e2e.Params) ([]id.Round, e.MessageID, time.Time, error) { m.handler.listeners[mt].Hear(receive.Message{ MessageType: mt, @@ -187,7 +268,7 @@ func (m *mockE2e) SendE2E(mt catalog.MessageType, recipient *id.ID, payload []by RecipientID: recipient, }) - return []id.Round{42}, e2eCrypto.MessageID{}, netTime.Now(), nil + return []id.Round{42}, e.MessageID{}, netTime.Now(), nil } func (m *mockE2e) RegisterListener(_ *id.ID, mt catalog.MessageType, @@ -196,6 +277,36 @@ func (m *mockE2e) RegisterListener(_ *id.ID, mt catalog.MessageType, return receive.ListenerID{} } +func (m *mockE2e) RegisterFunc(string, *id.ID, catalog.MessageType, receive.ListenerFunc) receive.ListenerID { + panic("implement me") +} +func (m *mockE2e) RegisterChannel(string, *id.ID, catalog.MessageType, chan receive.Message) receive.ListenerID { + panic("implement me") +} +func (m *mockE2e) Unregister(receive.ListenerID) { panic("implement me") } +func (m *mockE2e) UnregisterUserListeners(*id.ID) { panic("implement me") } +func (m *mockE2e) AddPartner(*id.ID, *cyclic.Int, *cyclic.Int, *sidh.PublicKey, *sidh.PrivateKey, session.Params, session.Params) (partner.Manager, error) { + panic("implement me") +} +func (m *mockE2e) GetPartner(*id.ID) (partner.Manager, error) { panic("implement me") } +func (m *mockE2e) DeletePartner(*id.ID) error { panic("implement me") } +func (m *mockE2e) GetAllPartnerIDs() []*id.ID { panic("implement me") } +func (m *mockE2e) HasAuthenticatedChannel(*id.ID) bool { panic("implement me") } +func (m *mockE2e) AddService(string, message.Processor) error { panic("implement me") } +func (m *mockE2e) RemoveService(string) error { panic("implement me") } +func (m *mockE2e) SendUnsafe(catalog.MessageType, *id.ID, []byte, e2e.Params) ([]id.Round, time.Time, error) { + panic("implement me") +} +func (m *mockE2e) EnableUnsafeReception() { panic("implement me") } +func (m *mockE2e) GetGroup() *cyclic.Group { panic("implement me") } +func (m *mockE2e) GetHistoricalDHPubkey() *cyclic.Int { panic("implement me") } +func (m *mockE2e) GetHistoricalDHPrivkey() *cyclic.Int { panic("implement me") } +func (m *mockE2e) GetReceptionID() *id.ID { panic("implement me") } +func (m *mockE2e) FirstPartitionSize() uint { panic("implement me") } +func (m *mockE2e) SecondPartitionSize() uint { panic("implement me") } +func (m *mockE2e) PartitionSize(uint) uint { panic("implement me") } +func (m *mockE2e) PayloadSize() uint { panic("implement me") } + //////////////////////////////////////////////////////////////////////////////// // Mock Storage Session // //////////////////////////////////////////////////////////////////////////////// @@ -217,5 +328,34 @@ func newMockStorage() *mockStorage { } } -func (m *mockStorage) GetKV() *versioned.KV { return m.kv } -func (m *mockStorage) GetCmixGroup() *cyclic.Group { return m.cmixGroup } +func (m *mockStorage) GetClientVersion() version.Version { panic("implement me") } +func (m *mockStorage) Get(string) (*versioned.Object, error) { panic("implement me") } +func (m *mockStorage) Set(string, *versioned.Object) error { panic("implement me") } +func (m *mockStorage) Delete(string) error { panic("implement me") } +func (m *mockStorage) GetKV() *versioned.KV { return m.kv } +func (m *mockStorage) GetCmixGroup() *cyclic.Group { return m.cmixGroup } +func (m *mockStorage) GetE2EGroup() *cyclic.Group { panic("implement me") } +func (m *mockStorage) ForwardRegistrationStatus(storage.RegistrationStatus) error { + panic("implement me") +} +func (m *mockStorage) GetRegistrationStatus() storage.RegistrationStatus { panic("implement me") } +func (m *mockStorage) SetRegCode(string) { panic("implement me") } +func (m *mockStorage) GetRegCode() (string, error) { panic("implement me") } +func (m *mockStorage) SetNDF(*ndf.NetworkDefinition) { panic("implement me") } +func (m *mockStorage) GetNDF() *ndf.NetworkDefinition { panic("implement me") } +func (m *mockStorage) GetTransmissionID() *id.ID { panic("implement me") } +func (m *mockStorage) GetTransmissionSalt() []byte { panic("implement me") } +func (m *mockStorage) GetReceptionID() *id.ID { panic("implement me") } +func (m *mockStorage) GetReceptionSalt() []byte { panic("implement me") } +func (m *mockStorage) GetReceptionRSA() *rsa.PrivateKey { panic("implement me") } +func (m *mockStorage) GetTransmissionRSA() *rsa.PrivateKey { panic("implement me") } +func (m *mockStorage) IsPrecanned() bool { panic("implement me") } +func (m *mockStorage) SetUsername(string) error { panic("implement me") } +func (m *mockStorage) GetUsername() (string, error) { panic("implement me") } +func (m *mockStorage) PortableUserInfo() userStorage.Info { panic("implement me") } +func (m *mockStorage) GetTransmissionRegistrationValidationSignature() []byte { panic("implement me") } +func (m *mockStorage) GetReceptionRegistrationValidationSignature() []byte { panic("implement me") } +func (m *mockStorage) GetRegistrationTimestamp() time.Time { panic("implement me") } +func (m *mockStorage) SetTransmissionRegistrationValidationSignature([]byte) { panic("implement me") } +func (m *mockStorage) SetReceptionRegistrationValidationSignature([]byte) { panic("implement me") } +func (m *mockStorage) SetRegistrationTimestamp(int64) { panic("implement me") } diff --git a/fileTransfer/e2e/wrapper.go b/fileTransfer/e2e/wrapper.go index e77681000d090e8cd9100f7d65bbea1500f50eeb..e27c281c9dfc490d271b3d225b73643b9e75cfa2 100644 --- a/fileTransfer/e2e/wrapper.go +++ b/fileTransfer/e2e/wrapper.go @@ -32,12 +32,12 @@ type Wrapper struct { myID *id.ID cmix ft.Cmix - e2e E2e + e2e e2eHandler } -// E2e interface matches a subset of the e2e.Handler methods used by the Wrapper +// e2eHandler interface matches a subset of the e2e.Handler methods used by the Wrapper // for easier testing. -type E2e interface { +type e2eHandler interface { SendE2E(mt catalog.MessageType, recipient *id.ID, payload []byte, params e2e.Params) ([]id.Round, e2eCrypto.MessageID, time.Time, error) RegisterListener(senderID *id.ID, messageType catalog.MessageType, @@ -46,14 +46,14 @@ type E2e interface { // NewWrapper generates a new file transfer manager using E2E. func NewWrapper(receiveCB ft.ReceiveCallback, p Params, ft ft.FileTransfer, - myID *id.ID, e2e E2e, cmix ft.Cmix) (*Wrapper, error) { + user ft.FtE2e) (*Wrapper, error) { w := &Wrapper{ receiveCB: receiveCB, ft: ft, p: p, - myID: myID, - cmix: cmix, - e2e: e2e, + myID: user.GetReceptionIdentity().ID, + cmix: user.GetCmix(), + e2e: user.GetE2E(), } // Register listener to receive new file transfers diff --git a/fileTransfer/e2e/wrapper_test.go b/fileTransfer/e2e/wrapper_test.go index 31f26da652d47a7450a8a55f6fdaae60b853e455..9ea7b46b5b586c95a1bcb0b92bf5e7412c229b02 100644 --- a/fileTransfer/e2e/wrapper_test.go +++ b/fileTransfer/e2e/wrapper_test.go @@ -25,8 +25,8 @@ import ( "time" ) -// Tests that E2e adheres to the e2e.Handler interface. -var _ E2e = (e2e.Handler)(nil) +// Tests that e2eHandler adheres to the e2e.Handler interface. +var _ e2eHandler = (e2e.Handler)(nil) // Smoke test of the entire file transfer system. func Test_FileTransfer_Smoke(t *testing.T) { @@ -61,8 +61,9 @@ func Test_FileTransfer_Smoke(t *testing.T) { e2e1 := newMockE2e(myID1, e2eHandler) e2e1.RegisterListener( myID1, catalog.EndFileTransfer, newMockListener(endE2eChan1)) - cmix1 := newMockCmix(myID1, cMixHandler, storage1) - ftManager1, err := ft.NewManager(ftParams, myID1, cmix1, storage1, rngGen) + cMix1 := newMockCmix(myID1, cMixHandler, storage1) + user1 := newMockUser(myID1, cMix1, e2e1, storage1, rngGen) + ftManager1, err := ft.NewManager(ftParams, user1) if err != nil { t.Errorf("Failed to make new file transfer manager: %+v", err) } @@ -70,7 +71,7 @@ func Test_FileTransfer_Smoke(t *testing.T) { if err != nil { t.Errorf("Failed to start processes for manager 1: %+v", err) } - m1, err := NewWrapper(receiveCB1, params, ftManager1, myID1, e2e1, cmix1) + m1, err := NewWrapper(receiveCB1, params, ftManager1, user1) if err != nil { t.Errorf("Failed to create new file transfer manager 1: %+v", err) } @@ -88,8 +89,9 @@ func Test_FileTransfer_Smoke(t *testing.T) { e2e2 := newMockE2e(myID2, e2eHandler) e2e2.RegisterListener( myID2, catalog.EndFileTransfer, newMockListener(endE2eChan2)) - cmix2 := newMockCmix(myID1, cMixHandler, storage2) - ftManager2, err := ft.NewManager(ftParams, myID2, cmix2, storage2, rngGen) + cMix2 := newMockCmix(myID1, cMixHandler, storage2) + user2 := newMockUser(myID2, cMix2, e2e2, storage1, rngGen) + ftManager2, err := ft.NewManager(ftParams, user2) if err != nil { t.Errorf("Failed to make new file transfer manager: %+v", err) } @@ -97,7 +99,7 @@ func Test_FileTransfer_Smoke(t *testing.T) { if err != nil { t.Errorf("Failed to start processes for manager 2: %+v", err) } - m2, err := NewWrapper(receiveCB2, params, ftManager2, myID2, e2e2, cmix2) + m2, err := NewWrapper(receiveCB2, params, ftManager2, user2) if err != nil { t.Errorf("Failed to create new file transfer manager 2: %+v", err) } diff --git a/fileTransfer/groupChat/send.go b/fileTransfer/groupChat/send.go index e85190cba9f2e8352e8a040cc5f29c67787e8007..b8d5edaf5fb80811c9a9f0606e430aab812fb727 100644 --- a/fileTransfer/groupChat/send.go +++ b/fileTransfer/groupChat/send.go @@ -21,7 +21,7 @@ const ( // sendNewFileTransferMessage sends a group chat message to the group ID // informing them of the incoming file transfer. func sendNewFileTransferMessage( - groupID *id.ID, transferInfo []byte, gc GroupChat) error { + groupID *id.ID, transferInfo []byte, gc gcManager) error { // Send the message via group chat _, _, _, err := gc.Send(groupID, newFileTransferTag, transferInfo) diff --git a/fileTransfer/groupChat/utils_test.go b/fileTransfer/groupChat/utils_test.go index 087f095dd60b07648840e3c7d38424837be1a8ba..38604350816258fbb6e9c85ac882525f78ec3909 100644 --- a/fileTransfer/groupChat/utils_test.go +++ b/fileTransfer/groupChat/utils_test.go @@ -10,26 +10,65 @@ package groupChat import ( jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/cmix" + "gitlab.com/elixxir/client/cmix/gateway" + "gitlab.com/elixxir/client/cmix/identity" "gitlab.com/elixxir/client/cmix/identity/receptionID" "gitlab.com/elixxir/client/cmix/message" "gitlab.com/elixxir/client/cmix/rounds" + "gitlab.com/elixxir/client/e2e" "gitlab.com/elixxir/client/groupChat" + "gitlab.com/elixxir/client/stoppable" + "gitlab.com/elixxir/client/storage" + "gitlab.com/elixxir/client/storage/user" "gitlab.com/elixxir/client/storage/versioned" + "gitlab.com/elixxir/client/xxdk" + "gitlab.com/elixxir/comms/network" "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/fastRNG" "gitlab.com/elixxir/crypto/group" "gitlab.com/elixxir/ekv" "gitlab.com/elixxir/primitives/format" + "gitlab.com/elixxir/primitives/version" + "gitlab.com/xx_network/comms/connect" "gitlab.com/xx_network/crypto/csprng" "gitlab.com/xx_network/crypto/large" + "gitlab.com/xx_network/crypto/signature/rsa" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/id/ephemeral" + "gitlab.com/xx_network/primitives/ndf" "sync" "time" ) //////////////////////////////////////////////////////////////////////////////// -// Mock cMix // +// Mock xxdk.E2e // +//////////////////////////////////////////////////////////////////////////////// + +type mockUser struct { + rid xxdk.ReceptionIdentity + c cmix.Client + s storage.Session + rng *fastRNG.StreamGenerator +} + +func newMockUser(rid *id.ID, c cmix.Client, s storage.Session, + rng *fastRNG.StreamGenerator) *mockUser { + return &mockUser{ + rid: xxdk.ReceptionIdentity{ID: rid}, + c: c, + s: s, + rng: rng, + } +} + +func (m *mockUser) GetStorage() storage.Session { return m.s } +func (m *mockUser) GetReceptionIdentity() xxdk.ReceptionIdentity { return m.rid } +func (m *mockUser) GetCmix() cmix.Client { return m.c } +func (m *mockUser) GetRng() *fastRNG.StreamGenerator { return m.rng } +func (m *mockUser) GetE2E() e2e.Handler { return nil } + +//////////////////////////////////////////////////////////////////////////////// +// Mock cMix // //////////////////////////////////////////////////////////////////////////////// type mockCmixHandler struct { @@ -65,11 +104,18 @@ func newMockCmix( } } +func (m *mockCmix) Follow(cmix.ClientErrorReport) (stoppable.Stoppable, error) { panic("implement me") } + func (m *mockCmix) GetMaxMessageLength() int { msg := format.NewMessage(m.numPrimeBytes) return msg.ContentsSize() } +func (m *mockCmix) Send(*id.ID, format.Fingerprint, message.Service, []byte, + []byte, cmix.CMIXParams) (id.Round, ephemeral.Id, error) { + panic("implement me") +} + func (m *mockCmix) SendMany(messages []cmix.TargetedCmixMessage, _ cmix.CMIXParams) (id.Round, []ephemeral.Id, error) { m.handler.Lock() @@ -86,6 +132,10 @@ func (m *mockCmix) SendMany(messages []cmix.TargetedCmixMessage, return 42, []ephemeral.Id{}, nil } +func (m *mockCmix) AddIdentity(*id.ID, time.Time, bool) { panic("implement me") } +func (m *mockCmix) RemoveIdentity(*id.ID) { panic("implement me") } +func (m *mockCmix) GetIdentity(*id.ID) (identity.TrackedID, error) { panic("implement me") } + func (m *mockCmix) AddFingerprint(_ *id.ID, fp format.Fingerprint, mp message.Processor) error { m.Lock() defer m.Unlock() @@ -99,13 +149,14 @@ func (m *mockCmix) DeleteFingerprint(_ *id.ID, fp format.Fingerprint) { m.handler.Unlock() } -func (m *mockCmix) CheckInProgressMessages() {} - -func (m *mockCmix) IsHealthy() bool { - return m.health -} - -func (m *mockCmix) WasHealthy() bool { return true } +func (m *mockCmix) DeleteClientFingerprints(*id.ID) { panic("implement me") } +func (m *mockCmix) AddService(*id.ID, message.Service, message.Processor) { panic("implement me") } +func (m *mockCmix) DeleteService(*id.ID, message.Service, message.Processor) { panic("implement me") } +func (m *mockCmix) DeleteClientService(*id.ID) { panic("implement me") } +func (m *mockCmix) TrackServices(message.ServicesTracker) { panic("implement me") } +func (m *mockCmix) CheckInProgressMessages() {} +func (m *mockCmix) IsHealthy() bool { return m.health } +func (m *mockCmix) WasHealthy() bool { return true } func (m *mockCmix) AddHealthCallback(f func(bool)) uint64 { m.Lock() @@ -125,12 +176,35 @@ func (m *mockCmix) RemoveHealthCallback(healthID uint64) { delete(m.healthCBs, healthID) } +func (m *mockCmix) HasNode(*id.ID) bool { panic("implement me") } +func (m *mockCmix) NumRegisteredNodes() int { panic("implement me") } +func (m *mockCmix) TriggerNodeRegistration(*id.ID) { panic("implement me") } + func (m *mockCmix) GetRoundResults(_ time.Duration, roundCallback cmix.RoundEventCallback, _ ...id.Round) error { go roundCallback(true, false, map[id.Round]cmix.RoundResult{42: {}}) return nil } +func (m *mockCmix) LookupHistoricalRound(id.Round, rounds.RoundResultCallback) error { + panic("implement me") +} +func (m *mockCmix) SendToAny(func(host *connect.Host) (interface{}, error), *stoppable.Single) (interface{}, error) { + panic("implement me") +} +func (m *mockCmix) SendToPreferred([]*id.ID, gateway.SendToPreferredFunc, *stoppable.Single, time.Duration) (interface{}, error) { + panic("implement me") +} +func (m *mockCmix) SetGatewayFilter(gateway.Filter) { panic("implement me") } +func (m *mockCmix) GetHostParams() connect.HostParams { panic("implement me") } +func (m *mockCmix) GetAddressSpace() uint8 { panic("implement me") } +func (m *mockCmix) RegisterAddressSpaceNotification(string) (chan uint8, error) { + panic("implement me") +} +func (m *mockCmix) UnregisterAddressSpaceNotification(string) { panic("implement me") } +func (m *mockCmix) GetInstance() *network.Instance { panic("implement me") } +func (m *mockCmix) GetVerboseRounds() string { panic("implement me") } + //////////////////////////////////////////////////////////////////////////////// // Mock Group Chat Manager // //////////////////////////////////////////////////////////////////////////////// @@ -194,5 +268,34 @@ func newMockStorage() *mockStorage { } } -func (m *mockStorage) GetKV() *versioned.KV { return m.kv } -func (m *mockStorage) GetCmixGroup() *cyclic.Group { return m.cmixGroup } +func (m *mockStorage) GetClientVersion() version.Version { panic("implement me") } +func (m *mockStorage) Get(string) (*versioned.Object, error) { panic("implement me") } +func (m *mockStorage) Set(string, *versioned.Object) error { panic("implement me") } +func (m *mockStorage) Delete(string) error { panic("implement me") } +func (m *mockStorage) GetKV() *versioned.KV { return m.kv } +func (m *mockStorage) GetCmixGroup() *cyclic.Group { return m.cmixGroup } +func (m *mockStorage) GetE2EGroup() *cyclic.Group { panic("implement me") } +func (m *mockStorage) ForwardRegistrationStatus(storage.RegistrationStatus) error { + panic("implement me") +} +func (m *mockStorage) GetRegistrationStatus() storage.RegistrationStatus { panic("implement me") } +func (m *mockStorage) SetRegCode(string) { panic("implement me") } +func (m *mockStorage) GetRegCode() (string, error) { panic("implement me") } +func (m *mockStorage) SetNDF(*ndf.NetworkDefinition) { panic("implement me") } +func (m *mockStorage) GetNDF() *ndf.NetworkDefinition { panic("implement me") } +func (m *mockStorage) GetTransmissionID() *id.ID { panic("implement me") } +func (m *mockStorage) GetTransmissionSalt() []byte { panic("implement me") } +func (m *mockStorage) GetReceptionID() *id.ID { panic("implement me") } +func (m *mockStorage) GetReceptionSalt() []byte { panic("implement me") } +func (m *mockStorage) GetReceptionRSA() *rsa.PrivateKey { panic("implement me") } +func (m *mockStorage) GetTransmissionRSA() *rsa.PrivateKey { panic("implement me") } +func (m *mockStorage) IsPrecanned() bool { panic("implement me") } +func (m *mockStorage) SetUsername(string) error { panic("implement me") } +func (m *mockStorage) GetUsername() (string, error) { panic("implement me") } +func (m *mockStorage) PortableUserInfo() user.Info { panic("implement me") } +func (m *mockStorage) GetTransmissionRegistrationValidationSignature() []byte { panic("implement me") } +func (m *mockStorage) GetReceptionRegistrationValidationSignature() []byte { panic("implement me") } +func (m *mockStorage) GetRegistrationTimestamp() time.Time { panic("implement me") } +func (m *mockStorage) SetTransmissionRegistrationValidationSignature([]byte) { panic("implement me") } +func (m *mockStorage) SetReceptionRegistrationValidationSignature([]byte) { panic("implement me") } +func (m *mockStorage) SetRegistrationTimestamp(int64) { panic("implement me") } diff --git a/fileTransfer/groupChat/wrapper.go b/fileTransfer/groupChat/wrapper.go index 19d0ca4daadad700a9f6ecb830840807f2883cee..63741b74296bc0c6ed6b0a3271324132a06cc8e8 100644 --- a/fileTransfer/groupChat/wrapper.go +++ b/fileTransfer/groupChat/wrapper.go @@ -37,19 +37,19 @@ type Wrapper struct { ft ft.FileTransfer // Group chat Manager - gc GroupChat + gc gcManager } -// GroupChat interface matches a subset of the groupChat.GroupChat methods used +// gcManager interface matches a subset of the groupChat.GroupChat methods used // by the Wrapper for easier testing. -type GroupChat interface { +type gcManager interface { Send(groupID *id.ID, tag string, message []byte) ( id.Round, time.Time, group.MessageID, error) AddService(tag string, p groupChat.Processor) error } // NewWrapper generates a new file transfer Wrapper for group chat. -func NewWrapper(receiveCB ft.ReceiveCallback, ft ft.FileTransfer, gc GroupChat) ( +func NewWrapper(receiveCB ft.ReceiveCallback, ft ft.FileTransfer, gc gcManager) ( *Wrapper, error) { w := &Wrapper{ receiveCB: receiveCB, diff --git a/fileTransfer/groupChat/wrapper_test.go b/fileTransfer/groupChat/wrapper_test.go index 69b6ede00966d7b32ea0c8262653bd6c8e819ad1..f5cfcca4d30e44ec6f1289d3fa87b628869f824e 100644 --- a/fileTransfer/groupChat/wrapper_test.go +++ b/fileTransfer/groupChat/wrapper_test.go @@ -23,8 +23,8 @@ import ( "time" ) -// Tests that GroupChat adheres to the groupChat.GroupChat interface. -var _ GroupChat = (groupChat.GroupChat)(nil) +// Tests that gcManager adheres to the groupChat.GroupChat interface. +var _ gcManager = (groupChat.GroupChat)(nil) // Smoke test of the entire file transfer system. func Test_FileTransfer_Smoke(t *testing.T) { @@ -49,8 +49,9 @@ func Test_FileTransfer_Smoke(t *testing.T) { myID1 := id.NewIdFromString("myID1", id.User, t) storage1 := newMockStorage() gc1 := newMockGC(gcHandler) - ftManager1, err := ft.NewManager(params, myID1, - newMockCmix(myID1, cMixHandler, storage1), storage1, rngGen) + cMix1 := newMockCmix(myID1, cMixHandler, storage1) + user1 := newMockUser(myID1, cMix1, storage1, rngGen) + ftManager1, err := ft.NewManager(params, user1) if err != nil { t.Errorf("Failed to create file transfer manager 2: %+v", err) } @@ -73,8 +74,9 @@ func Test_FileTransfer_Smoke(t *testing.T) { myID2 := id.NewIdFromString("myID2", id.User, t) storage2 := newMockStorage() gc2 := newMockGC(gcHandler) - ftManager2, err := ft.NewManager(params, myID2, - newMockCmix(myID2, cMixHandler, storage2), storage2, rngGen) + cMix2 := newMockCmix(myID2, cMixHandler, storage2) + user2 := newMockUser(myID1, cMix2, storage2, rngGen) + ftManager2, err := ft.NewManager(params, user2) if err != nil { t.Errorf("Failed to create file transfer manager 2: %+v", err) } diff --git a/fileTransfer/manager.go b/fileTransfer/manager.go index afae51d806f8262a2bf030e2225168a097d7e671..a586bad235c4145b1f2042e65511546c951ff284 100644 --- a/fileTransfer/manager.go +++ b/fileTransfer/manager.go @@ -13,11 +13,14 @@ import ( jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/cmix" "gitlab.com/elixxir/client/cmix/message" + "gitlab.com/elixxir/client/e2e" "gitlab.com/elixxir/client/fileTransfer/callbackTracker" "gitlab.com/elixxir/client/fileTransfer/store" "gitlab.com/elixxir/client/fileTransfer/store/fileMessage" "gitlab.com/elixxir/client/stoppable" + "gitlab.com/elixxir/client/storage" "gitlab.com/elixxir/client/storage/versioned" + "gitlab.com/elixxir/client/xxdk" "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/fastRNG" ftCrypto "gitlab.com/elixxir/crypto/fileTransfer" @@ -128,8 +131,18 @@ type manager struct { rng *fastRNG.StreamGenerator } -// Cmix interface matches a subset of the cmix.Client methods used by the -// manager for easier testing. +// FtE2e interface matches a subset of the xxdk.E2e methods used by the file +// transfer manager for easier testing. +type FtE2e interface { + GetStorage() storage.Session + GetReceptionIdentity() xxdk.ReceptionIdentity + GetCmix() cmix.Client + GetRng() *fastRNG.StreamGenerator + GetE2E() e2e.Handler +} + +// Cmix interface matches a subset of the cmix.Client methods used by the file +// transfer manager for easier testing. type Cmix interface { GetMaxMessageLength() int SendMany(messages []cmix.TargetedCmixMessage, p cmix.CMIXParams) (id.Round, @@ -155,9 +168,9 @@ type Storage interface { // NewManager creates a new file transfer manager object. If sent or received // transfers already existed, they are loaded from storage and queued to resume // once manager.startProcesses is called. -func NewManager(params Params, myID *id.ID, cmix Cmix, storage Storage, - rng *fastRNG.StreamGenerator) (FileTransfer, error) { - kv := storage.GetKV() +func NewManager(params Params, user FtE2e) (FileTransfer, error) { + + kv := user.GetStorage().GetKV() // Create a new list of sent file transfers or load one if it exists sent, unsentParts, err := store.NewOrLoadSent(kv) @@ -179,11 +192,11 @@ func NewManager(params Params, myID *id.ID, cmix Cmix, storage Storage, batchQueue: make(chan store.Part, batchQueueBuffLen), sendQueue: make(chan []store.Part, sendQueueBuffLen), params: params, - myID: myID, - cmix: cmix, - cmixGroup: storage.GetCmixGroup(), + myID: user.GetReceptionIdentity().ID, + cmix: user.GetCmix(), + cmixGroup: user.GetStorage().GetCmixGroup(), kv: kv, - rng: rng, + rng: user.GetRng(), } // Add all unsent file parts to queue diff --git a/fileTransfer/manager_test.go b/fileTransfer/manager_test.go index f9699a6267014185b193edcbc19b115aa809d563..425e26ad03448690d98a7b31d200634960fb7fca 100644 --- a/fileTransfer/manager_test.go +++ b/fileTransfer/manager_test.go @@ -89,8 +89,9 @@ func Test_FileTransfer_Smoke(t *testing.T) { // Set up the first client myID1 := id.NewIdFromString("myID1", id.User, t) storage1 := newMockStorage() - ftm1, err := NewManager(params, myID1, - newMockCmix(myID1, cMixHandler, storage1), storage1, rngGen) + cMix1 := newMockCmix(myID1, cMixHandler, storage1) + user1 := newMockE2e(myID1, cMix1, storage1, rngGen) + ftm1, err := NewManager(params, user1) if err != nil { t.Errorf("Failed to create new file transfer manager 1: %+v", err) } @@ -104,8 +105,9 @@ func Test_FileTransfer_Smoke(t *testing.T) { // Set up the second client myID2 := id.NewIdFromString("myID2", id.User, t) storage2 := newMockStorage() - ftm2, err := NewManager(params, myID2, - newMockCmix(myID2, cMixHandler, storage2), storage2, rngGen) + cMix2 := newMockCmix(myID2, cMixHandler, storage2) + user2 := newMockE2e(myID2, cMix2, storage2, rngGen) + ftm2, err := NewManager(params, user2) if err != nil { t.Errorf("Failed to create new file transfer manager 2: %+v", err) } diff --git a/fileTransfer/utils_test.go b/fileTransfer/utils_test.go index 781734369b36270a4c2e9298b2eaa747e1c10655..df51d90ddaa113ce471244217d567fa3868a1883 100644 --- a/fileTransfer/utils_test.go +++ b/fileTransfer/utils_test.go @@ -12,18 +12,30 @@ import ( "encoding/binary" jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/cmix" + "gitlab.com/elixxir/client/cmix/gateway" + "gitlab.com/elixxir/client/cmix/identity" "gitlab.com/elixxir/client/cmix/identity/receptionID" "gitlab.com/elixxir/client/cmix/message" "gitlab.com/elixxir/client/cmix/rounds" + "gitlab.com/elixxir/client/e2e" + "gitlab.com/elixxir/client/stoppable" + "gitlab.com/elixxir/client/storage" + userStorage "gitlab.com/elixxir/client/storage/user" "gitlab.com/elixxir/client/storage/versioned" + "gitlab.com/elixxir/client/xxdk" + "gitlab.com/elixxir/comms/network" "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/fastRNG" "gitlab.com/elixxir/ekv" "gitlab.com/elixxir/primitives/format" + "gitlab.com/elixxir/primitives/version" + "gitlab.com/xx_network/comms/connect" "gitlab.com/xx_network/crypto/csprng" "gitlab.com/xx_network/crypto/large" + "gitlab.com/xx_network/crypto/signature/rsa" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/id/ephemeral" + "gitlab.com/xx_network/primitives/ndf" "io" "math/rand" "sync" @@ -81,7 +93,34 @@ func RandStringBytes(n int, prng *rand.Rand) string { } //////////////////////////////////////////////////////////////////////////////// -// Mock cMix // +// Mock xxdk.E2e // +//////////////////////////////////////////////////////////////////////////////// + +type mockE2e struct { + rid xxdk.ReceptionIdentity + c cmix.Client + s storage.Session + rng *fastRNG.StreamGenerator +} + +func newMockE2e(rid *id.ID, c cmix.Client, s storage.Session, + rng *fastRNG.StreamGenerator) *mockE2e { + return &mockE2e{ + rid: xxdk.ReceptionIdentity{ID: rid}, + c: c, + s: s, + rng: rng, + } +} + +func (m *mockE2e) GetStorage() storage.Session { return m.s } +func (m *mockE2e) GetReceptionIdentity() xxdk.ReceptionIdentity { return m.rid } +func (m *mockE2e) GetCmix() cmix.Client { return m.c } +func (m *mockE2e) GetRng() *fastRNG.StreamGenerator { return m.rng } +func (m *mockE2e) GetE2E() e2e.Handler { return nil } + +//////////////////////////////////////////////////////////////////////////////// +// Mock cMix // //////////////////////////////////////////////////////////////////////////////// type mockCmixHandler struct { @@ -119,11 +158,18 @@ func newMockCmix( } } +func (m *mockCmix) Follow(cmix.ClientErrorReport) (stoppable.Stoppable, error) { panic("implement me") } + func (m *mockCmix) GetMaxMessageLength() int { msg := format.NewMessage(m.numPrimeBytes) return msg.ContentsSize() } +func (m *mockCmix) Send(*id.ID, format.Fingerprint, message.Service, []byte, + []byte, cmix.CMIXParams) (id.Round, ephemeral.Id, error) { + panic("implement me") +} + func (m *mockCmix) SendMany(messages []cmix.TargetedCmixMessage, _ cmix.CMIXParams) (id.Round, []ephemeral.Id, error) { m.handler.Lock() @@ -142,6 +188,10 @@ func (m *mockCmix) SendMany(messages []cmix.TargetedCmixMessage, return round, []ephemeral.Id{}, nil } +func (m *mockCmix) AddIdentity(*id.ID, time.Time, bool) { panic("implement me") } +func (m *mockCmix) RemoveIdentity(*id.ID) { panic("implement me") } +func (m *mockCmix) GetIdentity(*id.ID) (identity.TrackedID, error) { panic("implement me") } + func (m *mockCmix) AddFingerprint(_ *id.ID, fp format.Fingerprint, mp message.Processor) error { m.handler.Lock() defer m.handler.Unlock() @@ -155,13 +205,14 @@ func (m *mockCmix) DeleteFingerprint(_ *id.ID, fp format.Fingerprint) { delete(m.handler.processorMap, fp) } -func (m *mockCmix) CheckInProgressMessages() {} - -func (m *mockCmix) IsHealthy() bool { - return m.health -} - -func (m *mockCmix) WasHealthy() bool { return true } +func (m *mockCmix) DeleteClientFingerprints(*id.ID) { panic("implement me") } +func (m *mockCmix) AddService(*id.ID, message.Service, message.Processor) { panic("implement me") } +func (m *mockCmix) DeleteService(*id.ID, message.Service, message.Processor) { panic("implement me") } +func (m *mockCmix) DeleteClientService(*id.ID) { panic("implement me") } +func (m *mockCmix) TrackServices(message.ServicesTracker) { panic("implement me") } +func (m *mockCmix) CheckInProgressMessages() {} +func (m *mockCmix) IsHealthy() bool { return m.health } +func (m *mockCmix) WasHealthy() bool { return true } func (m *mockCmix) AddHealthCallback(f func(bool)) uint64 { m.Lock() @@ -181,12 +232,35 @@ func (m *mockCmix) RemoveHealthCallback(healthID uint64) { delete(m.healthCBs, healthID) } +func (m *mockCmix) HasNode(*id.ID) bool { panic("implement me") } +func (m *mockCmix) NumRegisteredNodes() int { panic("implement me") } +func (m *mockCmix) TriggerNodeRegistration(*id.ID) { panic("implement me") } + func (m *mockCmix) GetRoundResults(_ time.Duration, roundCallback cmix.RoundEventCallback, rids ...id.Round) error { go roundCallback(true, false, map[id.Round]cmix.RoundResult{rids[0]: {}}) return nil } +func (m *mockCmix) LookupHistoricalRound(id.Round, rounds.RoundResultCallback) error { + panic("implement me") +} +func (m *mockCmix) SendToAny(func(host *connect.Host) (interface{}, error), *stoppable.Single) (interface{}, error) { + panic("implement me") +} +func (m *mockCmix) SendToPreferred([]*id.ID, gateway.SendToPreferredFunc, *stoppable.Single, time.Duration) (interface{}, error) { + panic("implement me") +} +func (m *mockCmix) SetGatewayFilter(gateway.Filter) { panic("implement me") } +func (m *mockCmix) GetHostParams() connect.HostParams { panic("implement me") } +func (m *mockCmix) GetAddressSpace() uint8 { panic("implement me") } +func (m *mockCmix) RegisterAddressSpaceNotification(string) (chan uint8, error) { + panic("implement me") +} +func (m *mockCmix) UnregisterAddressSpaceNotification(string) { panic("implement me") } +func (m *mockCmix) GetInstance() *network.Instance { panic("implement me") } +func (m *mockCmix) GetVerboseRounds() string { panic("implement me") } + //////////////////////////////////////////////////////////////////////////////// // Mock Storage Session // //////////////////////////////////////////////////////////////////////////////// @@ -208,5 +282,34 @@ func newMockStorage() *mockStorage { } } -func (m *mockStorage) GetKV() *versioned.KV { return m.kv } -func (m *mockStorage) GetCmixGroup() *cyclic.Group { return m.cmixGroup } +func (m *mockStorage) GetClientVersion() version.Version { panic("implement me") } +func (m *mockStorage) Get(string) (*versioned.Object, error) { panic("implement me") } +func (m *mockStorage) Set(string, *versioned.Object) error { panic("implement me") } +func (m *mockStorage) Delete(string) error { panic("implement me") } +func (m *mockStorage) GetKV() *versioned.KV { return m.kv } +func (m *mockStorage) GetCmixGroup() *cyclic.Group { return m.cmixGroup } +func (m *mockStorage) GetE2EGroup() *cyclic.Group { panic("implement me") } +func (m *mockStorage) ForwardRegistrationStatus(storage.RegistrationStatus) error { + panic("implement me") +} +func (m *mockStorage) GetRegistrationStatus() storage.RegistrationStatus { panic("implement me") } +func (m *mockStorage) SetRegCode(string) { panic("implement me") } +func (m *mockStorage) GetRegCode() (string, error) { panic("implement me") } +func (m *mockStorage) SetNDF(*ndf.NetworkDefinition) { panic("implement me") } +func (m *mockStorage) GetNDF() *ndf.NetworkDefinition { panic("implement me") } +func (m *mockStorage) GetTransmissionID() *id.ID { panic("implement me") } +func (m *mockStorage) GetTransmissionSalt() []byte { panic("implement me") } +func (m *mockStorage) GetReceptionID() *id.ID { panic("implement me") } +func (m *mockStorage) GetReceptionSalt() []byte { panic("implement me") } +func (m *mockStorage) GetReceptionRSA() *rsa.PrivateKey { panic("implement me") } +func (m *mockStorage) GetTransmissionRSA() *rsa.PrivateKey { panic("implement me") } +func (m *mockStorage) IsPrecanned() bool { panic("implement me") } +func (m *mockStorage) SetUsername(string) error { panic("implement me") } +func (m *mockStorage) GetUsername() (string, error) { panic("implement me") } +func (m *mockStorage) PortableUserInfo() userStorage.Info { panic("implement me") } +func (m *mockStorage) GetTransmissionRegistrationValidationSignature() []byte { panic("implement me") } +func (m *mockStorage) GetReceptionRegistrationValidationSignature() []byte { panic("implement me") } +func (m *mockStorage) GetRegistrationTimestamp() time.Time { panic("implement me") } +func (m *mockStorage) SetTransmissionRegistrationValidationSignature([]byte) { panic("implement me") } +func (m *mockStorage) SetReceptionRegistrationValidationSignature([]byte) { panic("implement me") } +func (m *mockStorage) SetRegistrationTimestamp(int64) { panic("implement me") }