public void Messages() { var msg = new ChadderMessage(); msg.Type = MESSAGE_TYPE.TEXT; msg.Body = "Testing messages"; msg.myMessage = true; msg.fromId = Guid.NewGuid().ToString(); msg.messageId = Guid.NewGuid().ToString(); var packed = new ChadderPackedMessageText(msg); var serial = packed.Serialize(); var packed2 = ChadderEncryptedContent.Deserialize(serial) as ChadderPackedMessageText; Assert.NotNull(packed2); Assert.AreEqual(packed.Id, packed2.Id); Assert.AreEqual(packed.Group, packed2.Group); Assert.AreEqual(packed.Time, packed2.Time); Assert.AreEqual(packed.From, packed2.From); Assert.AreEqual(packed.Body, packed2.Body); packed = new ChadderPackedMessageText(msg); serial = packed.Serialize(); packed2 = ChadderEncryptedContent.Deserialize(serial) as ChadderPackedMessageText; Assert.NotNull(packed2); Assert.AreEqual(packed.Id, packed2.Id); Assert.AreEqual(packed.Group, packed2.Group); Assert.AreEqual(packed.Time, packed2.Time); Assert.AreEqual(packed.From, packed2.From); Assert.AreEqual(packed.Body, packed2.Body); }
protected async Task SendPendingMessages() { ChadderMessage msg = null; try { var backoff = new ExponentialBackoff(1000, 5000); while (PendingMessages.Count > 0) { if (PendingMessages.TryPeek(out msg) && msg.Status != ChadderMessage.MESSAGE_STATUS.SENT) { var conversation = db.GetConversation(msg.ConversationId); if (await SendMessageToServer(msg, conversation) == ChadderError.OK) { while (PendingMessages.TryDequeue(out msg)) { ; } backoff.Reset(); } else { await backoff.Failed(); } } } } catch (Exception ex) { Insight.Track("SendPendingMessages safe try-catch"); Insight.Report(ex); } SendPendingMessagesTask = null; }
public void AddPendingMessage(ChadderMessage msg, bool start = true) { PendingMessages.Enqueue(msg); if (start) { StartSendPendingMessages(); } }
public async Task TakeBack(ChadderMessage msg, ChadderConversation conversation) { ChadderApp.UIHelper.ShowLoading(); var result = await Source.TakeMessageBack(msg, conversation); ChadderApp.UIHelper.HideLoading(); ShowErrorIfNotOk(result); }
public async Task <ChadderMessage> SendMessage(string txt, ChadderConversation conversation) { var msg = ChadderMessage.Create(conversation, db.LocalUser, ChadderMessage.MESSAGE_TYPE.TEXT); msg.Body = txt; await db.AddMessage(msg, conversation); AddPendingMessage(msg); return(msg); }
public async void NewMessageProtocolTransition() { var source1 = await CreateAccount(); var source2 = await CreateAccount(); await source2.ChangeShareName(true); var result = await source1.addContact(source2.database.profile.myId); await source2.ChangeShareName(false); Ok(result.Item1); var contact1 = source1.database.getContact(source2.database.profile.myId); Assert.NotNull(contact1); source1.database.conversations.Clear(); var conversation1 = await source1.database.GetConversationByContact(contact1); Assert.Null(conversation1); var contact2 = source2.database.getContact(source1.database.profile.myId); Assert.NotNull(contact2); var conversation2 = await source2.database.GetConversationByContact(contact2); Assert.NotNull(conversation2); var body = "Testing"; var msg = new ChadderMessage() { Type = MESSAGE_TYPE.TEXT, messageId = Guid.NewGuid().ToString(), myMessage = true, Body = "Test", fromId = source1.database.profile.myId, LocalTime = DateTime.UtcNow, Status = MESSAGE_STATUS.SENDING }; var packed = new ChadderPackedMessageText(msg); var key = new ChadderECDHUserUserLegacy(source1.database, contact1); var encrypted = await ChadderAESEncryptedContent.Encrypt(source1, key, packed); await source2.SendNewMessage(conversation2, body); await Task.Delay(1000); Assert.AreEqual(2, conversation2.messages.Count); }
public async void SendPicture(byte[] data, ChadderConversation conversation) { var record = new ChadderSQLPicture() { ToBeUploaded = true, Bin = data, PictureId = Guid.NewGuid().ToString()// Temporary }; await sqlDB.InsertAsync(record); var picture = await db.LoadPicture(record, true); var msg = ChadderMessage.Create(conversation, db.LocalUser, ChadderMessage.MESSAGE_TYPE.PICTURE); msg.PictureId = record.PictureId; msg.Picture = picture; await db.AddMessage(msg, conversation); AddPendingMessage(msg); }
public async Task <ChadderError> TakeMessageBack(ChadderMessage msg, ChadderConversation conversation) { var package = new TakeMessageBackContent(msg.MessageId); var content = await EncryptForUser(package, conversation.Contact); var result = await AuthorizedRequest <BasicResponse>(Connection.ChatHub, "TakeMessageBack", msg.ReferenceId); if (result.Error == ChadderError.OK) { var request = new SendPackageParameter() { UserId = conversation.ContactUserId, Data = content.Serialize() }; result = await AuthorizedRequest <BasicResponse <string> >(Connection.ChatHub, "SendPackageToUser", request); if (result.Error == ChadderError.OK) { await db.DeleteMessage(msg, conversation); } } return(result.Error); }
protected async Task <ChadderError> SendMessageToServer(ChadderMessage msg, ChadderConversation conversation) { try { BasicMessage package = null; if (msg.Type == ChadderMessage.MESSAGE_TYPE.TEXT) { package = new TextMessage() { Body = msg.Body }; } else if (msg.Type == ChadderMessage.MESSAGE_TYPE.PICTURE) { if (msg.Picture.ToBeUploaded) { var record = await sqlDB.GetPicture(msg.Picture.RecordId); var presult = await UploadPicture(record); if (presult.Error == ChadderError.OK) { msg.PictureId = record.PictureId; await sqlDB.UpdateAsync(msg); } else { return(presult.Error); } } package = new ImageMessage() { PictureId = msg.PictureId }; } else { Insight.Track("Invalid Message Type in SendMessageToServer"); return(ChadderError.INVALID_INPUT); } package.Id = msg.MessageId; package.Group = null; package.TimeSent = msg.TimeSent.Value; package.Expiration = msg.Expiration.Value; var content = await EncryptForUser(package, conversation.Contact); var request = new SendPackageParameter() { UserId = conversation.ContactUserId, Data = content.Serialize() }; var result = await AuthorizedRequest <BasicResponse <string> >(Connection.ChatHub, "SendPackageToUser", request); if (result.Error == ChadderError.OK) { msg.Status = ChadderMessage.MESSAGE_STATUS.SENT; msg.TimeServer = result.Time; msg.ReferenceId = result.Extra; await sqlDB.UpdateAsync(msg); } return(result.Error); } catch (Exception ex) { Insight.Report(ex); return(ChadderError.GENERAL_EXCEPTION); } }
public virtual async Task <bool> ProcessPackage(Package package) { var content = Content.Deserialize(package.Data); var identifier = await content.Find <ECDH>(this); string fromId = null; string toId = null; if (identifier != null) { fromId = identifier.SourceId; toId = identifier.TargetId; } if (content == null) { return(false); } // If multiple layer of encryption were to be supported there should be a loop around this section if (content is IContentWrapper) // Decrypt section { content = await(content as IContentWrapper).GetContent(this); } // This has to be the clear content if (content is UserPublicKey) { if (package.OwnerId != null) { Insight.Track("Non-server trying to update client id"); } else { await ProcessUserPublicKey(content as UserPublicKey); } } else if (content is DevicePublicKey) { if (package.OwnerId != null) { Insight.Track("Non-server trying to update device id"); return(true); } var device = db.GetDevice((content as DevicePublicKey).DeviceId); var pbk = (content as DevicePublicKey).PublicKeyData; if (device == null) { if (pbk != null) { device = new ChadderUserDevice() { DeviceId = (content as DevicePublicKey).DeviceId, PublicKeyBookData = pbk, Name = "Temp", HasUserKey = false, CurrentDevice = false }; await db.AddDevice(device); } } else { if (pbk == null) { db.LocalUser.Devices.Remove(device); await sqlDB.DeleteAsync(device); } else { device.PublicKeyBookData = pbk; await sqlDB.UpdateAsync(device); } } } else if (content is PairDeviceContent) { if (package.OwnerId != db.LocalUser.UserId) { Insight.Track("Not this user trying to pair device"); return(true); } db.LocalUser.PrivateKeyBookData = (content as PairDeviceContent).Book.Serialize(); await sqlDB.UpdateAsync(db.LocalUser); return(true); } else if (content is TakeMessageBackContent) { await ProcessTakeBack(content as TakeMessageBackContent, fromId, toId); } else if (content is BasicMessage) // Process section { var msg = content as BasicMessage; ChadderConversation conversation = null; if (fromId == db.LocalUser.UserId) { conversation = db.GetContactConversation(toId); } else { conversation = db.GetContactConversation(package.OwnerId); } if (conversation.Messages.FirstOrDefault(i => i.MessageId == msg.Id) == null) { var record = new ChadderMessage() { MessageId = msg.Id, Type = ChadderMessage.MESSAGE_TYPE.TEXT, Status = ChadderMessage.MESSAGE_STATUS.SENT, Expiration = msg.Expiration, TimeSent = msg.TimeSent, TimeReceived = DateTime.UtcNow, TimeServer = package.Time, MyMessage = false, ConversationId = conversation.recordId, Sender = conversation.Contact, }; if (conversation.ContactUserId != fromId) { record.MyMessage = true; record.Sender = db.LocalUser; } record.UserId = record.Sender.UserId; if (content is TextMessage) { record.Body = (content as TextMessage).Body; } await db.AddMessage(record, conversation); } else { Insight.Track("Repeated Message GUID"); } } else { return(false); } return(true); }
public async Task DeleteMessage(ChadderMessage msg, ChadderConversation conversation) { //++await Source.DeleteMessage(msg, conversation); await Source.DeleteAllMessages(); }
public async Task BasicSystemTest() { var random = new Random(); var source1 = CreateSource(0); var username = Guid.NewGuid().ToString("N").Substring(0, 20); var name = string.Format("AutoTest{0}", random.Next()); Assert.AreEqual(ChadderError.OK, await source1.CreateUser(name, username, username)); // Login with user on a second device var source2 = CreateSource(1); using (var await1 = new AwaitUpdate(source1)) Assert.AreEqual(ChadderError.OK, await source2.Login(username, username)); Assert.AreEqual(source1.db.LocalUser.UserId, source2.db.LocalUser.UserId); Assert.AreEqual(2, source2.db.LocalUser.Devices.Count); Assert.AreEqual(2, source1.db.LocalUser.Devices.Count); Assert.AreEqual(ChadderError.OK, await source2.CreateNewKey()); // Test Logout (Logout Source1, check source2 devices, Login source1) using (var await2 = new AwaitUpdate(source2)) Assert.AreEqual(ChadderError.OK, await source1.Logout()); Assert.AreEqual(1, source2.db.LocalUser.Devices.Count); using (var await2 = new AwaitUpdate(source2)) Assert.AreEqual(ChadderError.OK, await source1.Login(username, username)); // Pair Previous Device var source2_device1 = source2.db.LocalUser.Devices.FirstOrDefault(i => i.DeviceId == source1.db.LocalDevice.DeviceId); using (var await1 = new AwaitUpdate(source1)) Assert.AreEqual(ChadderError.OK, await source2.PairDevice(source2_device1)); Assert.AreEqual(2, source1.db.LocalUser.Devices.Count); Assert.IsTrue(source1.db.LocalUser.PrivateKeyBookData.SequenceEqual(source2.db.LocalUser.PrivateKeyBookData)); // Create a second user var source3 = CreateSource(0); // Other user will share same device with source1 var name2 = string.Format("AutoTest{0}", random.Next()); Assert.AreEqual(ChadderError.OK, await source3.CreateUser(name2)); // Find first user var list = await source3.FindUser(name); Assert.AreEqual(ChadderError.OK, list.Error); Assert.IsNotNull(list.List.FirstOrDefault(i => i.UserId == source1.db.LocalUser.UserId)); // Add second user using (var await2 = new AwaitUpdate(source2)) using (var await3 = new AwaitUpdate(source3)) { var result = await source1.AddContact(source3.db.LocalUser.UserId); Assert.AreEqual(ChadderError.OK, result.Error); } Assert.AreEqual(1, source3.db.Contacts.Count); Assert.AreEqual(1, source2.db.Contacts.Count); Assert.AreEqual(1, source1.db.Contacts.Count); ChadderMessage msg = null; // Send message From User1 using (var await2 = new AwaitUpdate(source2)) using (var await3 = new AwaitUpdate(source3)) { msg = await source1.SendMessage("Testing", source1.db.Conversations[0]); await WaitUntilCondition(2000, "Too long to send a message", () => msg.Status == ChadderMessage.MESSAGE_STATUS.SENT); } // Check if all three devices have the same message Assert.AreEqual(1, source1.db.Conversations[0].Messages.Count); Assert.AreEqual(1, source2.db.Conversations[0].Messages.Count); Assert.AreEqual(1, source3.db.Conversations[0].Messages.Count); Assert.IsTrue(source1.db.Conversations[0].Messages[0].MyMessage); Assert.IsTrue(source2.db.Conversations[0].Messages[0].MyMessage); Assert.IsFalse(source3.db.Conversations[0].Messages[0].MyMessage); Assert.AreEqual(msg.Body, source2.db.Conversations[0].Messages[0].Body); Assert.AreEqual(msg.Body, source3.db.Conversations[0].Messages[0].Body); // Check TakeBack feature using (var await2 = new AwaitUpdate(source2)) using (var await3 = new AwaitUpdate(source3)) Assert.AreEqual(ChadderError.OK, await source1.TakeMessageBack(source1.db.Conversations[0].Messages[0], source1.db.Conversations[0])); Assert.AreEqual(0, source1.db.Conversations[0].Messages.Count); Assert.AreEqual(0, source2.db.Conversations[0].Messages.Count); Assert.AreEqual(0, source3.db.Conversations[0].Messages.Count); // Change name name = string.Format("AutoTest{0}", random.Next()); using (var await2 = new AwaitUpdate(source2)) using (var await3 = new AwaitUpdate(source3)) Assert.AreEqual(ChadderError.OK, await source1.ChangeName(name)); Assert.AreEqual(name, source1.db.LocalUser.Name); Assert.AreEqual(name, source2.db.LocalUser.Name); Assert.AreEqual(name, source3.db.Contacts[0].Name); // Change Picture, and download byte[] data = new byte[256 * 256]; random.NextBytes(data); using (var await2 = new AwaitUpdate(source2)) using (var await3 = new AwaitUpdate(source3)) Assert.AreEqual(ChadderError.OK, await source1.ChangePicture(data)); Assert.AreEqual(source1.db.LocalUser.PictureId, source2.db.LocalUser.PictureId); Assert.AreEqual(source1.db.LocalUser.PictureId, source3.db.Contacts[0].PictureId); await source2.db.LocalUser.Picture.LoadPictureAsync(false); await source3.db.Contacts[0].Picture.LoadPictureAsync(false); Assert.IsTrue(data.SequenceEqual((await source2.sqlDB.GetPicture(source2.db.LocalUser.Picture.RecordId)).Bin)); Assert.IsTrue(data.SequenceEqual((await source3.sqlDB.GetPicture(source3.db.Contacts[0].Picture.RecordId)).Bin)); { // Test Delete Contact using (var await2 = new AwaitUpdate(source2)) Assert.AreEqual(ChadderError.OK, await source1.DeleteContact(source1.db.Contacts[0])); Assert.AreEqual(0, source1.db.Contacts.Count); Assert.AreEqual(0, source2.db.Contacts.Count); Assert.AreEqual(1, source3.db.Contacts.Count); // Add the user again after deleting list = await source1.FindUser(name2); Assert.AreEqual(ChadderError.OK, list.Error); Assert.IsNotNull(list.List.FirstOrDefault(i => i.UserId == source3.db.LocalUser.UserId)); using (var await2 = new AwaitUpdate(source2)) { var result = await source1.AddContact(source3.db.LocalUser.UserId); Assert.AreEqual(ChadderError.OK, result.Error); } Assert.AreEqual(1, source1.db.Contacts.Count); Assert.AreEqual(1, source2.db.Contacts.Count); Assert.AreEqual(1, source3.db.Contacts.Count); } { // Test generate new keys Assert.AreEqual(PublicKeyStatus.NOT_VERIFIED, source3.db.Contacts[0].KeyStatus); using (var await3 = new AwaitUpdate(source3)) Assert.AreEqual(ChadderError.OK, await source1.RefreshKeys()); Assert.AreEqual(PublicKeyStatus.NOT_VERIFIED, source3.db.Contacts[0].KeyStatus); using (var await3 = new AwaitUpdate(source3)) Assert.AreEqual(ChadderError.OK, await source1.CreateNewKey()); Assert.AreEqual(PublicKeyStatus.CHANGED, source3.db.Contacts[0].KeyStatus); } }