public int Pull() { int changes = 0; ThrowExceptionIfNotConnected(); lock (mutex) { Log("Sending PULL command."); BinaryEncoder.SendCommand(stream, ConnectionCommand.PULL); #if (DEBUG) Log("Sending ClientPullCapsula."); #endif ClientPullCapsula clientCapsula; using (Context context = new Context(config)) { clientCapsula = new ClientPullCapsula() { AesKeysUserIds = context.Contacts .Where(u => u.ReceiveAesKey == null) .Select(u => u.PublicId) .ToArray() }; } TextEncoder.SendJson(stream, clientCapsula); ServerPullCapsula capsula = TextEncoder.ReadJson <ServerPullCapsula>(stream); #if (DEBUG) Log("Received ServerPullCapsula."); #endif changes += capsula.AesKeysUserIds.Count; changes += capsula.Messages.Count; using (Context context = new Context(config)) { #if (DEBUG) Log("Receiving and saving AES keys."); #endif foreach (var id in capsula.AesKeysUserIds) { var user = new UContact(context.Contacts.Where(con => con.PublicId == id).SingleOrDefault()); try { user.ReceiveAesKey = RSAEncoder.DecryptAndVerify(BinaryEncoder.ReceiveBytes(stream), MyCertificate, X509Certificate2Utils.ImportFromPem(user.PublicCertificate)); } catch (Exception ex) { Log($"Loading of Receive AESKey from {user.PublicId} has failed."); logger.LogException(this, ex); } PushOperations.Update(context, user, UserId, UserId); } context.SaveChanges(); #if (DEBUG) Log("Receiving and saving messages."); #endif foreach (PullMessage metaMessage in capsula.Messages) { BlobMessages metaBlob = new BlobMessages() { PublicId = metaMessage.PublicId, SenderId = metaMessage.SenderId, Failed = 0, DoDelete = 0 }; context.BlobMessages.Add(metaBlob); context.SaveChanges(); try { PullMessageParser.ParseEncryptedMessage(context, BinaryEncoder.ReceiveBytes(stream), metaBlob.SenderId, metaBlob.Id, UserId); } catch (Exception ex) { Log($"Loading of message {metaMessage.PublicId} has failed."); metaBlob.Failed = 1; logger.LogException(this, ex); } context.SaveChanges(); } } Log("Pull have been done."); } return(changes); }
private void Push() { #if (DEBUG) Log("Pushing started."); #endif ClientPullCapsula clientPullCapsula = TextEncoder.ReadJson <ClientPullCapsula>(stream); using (Context context = new Context(config)) { ServerPullCapsula capsula = new ServerPullCapsula(); List <byte[]> messagesBlobsToSend = new List <byte[]>(); List <byte[]> aesBlobsToSend = new List <byte[]>(); var messagesIdsUploaded = context.ClientsMessagesDownloaded .Where(u => u.ClientsId == connectionInfo.ClientId) .Select(u => u.BlobMessagesId); List <PullMessage> pullMessages = new List <PullMessage>(); foreach (var message in from messages in context.BlobMessages orderby messages.Priority descending, messages.Id ascending //Message order must be respected where messages.RecepientId == connectionInfo.UserId //Messages of connected user where !messagesIdsUploaded.Contains(messages.Id) //New messages join keys in context.UsersKeys on messages.RecepientId equals keys.SenderId //Keys sended by connected user where keys.Trusted == true //Only trusted where messages.SenderId == keys.RecepientId //Trusted information just only about sending user select new { messages.SenderId, messages.Content, messages.Id } ) { pullMessages.Add(new PullMessage() { PublicId = message.Id, SenderId = message.SenderId }); messagesBlobsToSend.Add(message.Content); context.ClientsMessagesDownloaded.Add(new ClientsMessagesDownloaded() { BlobMessagesId = message.Id, ClientsId = connectionInfo.ClientId }); } capsula.Messages = pullMessages; #if (DEBUG) Log($"{messagesBlobsToSend.Count} messageBlobs will be pushed."); #endif capsula.AesKeysUserIds = new List <long>(); foreach (var user in from userKeys in context.UsersKeys where userKeys.RecepientId == connectionInfo.UserId where clientPullCapsula.AesKeysUserIds.Contains(userKeys.SenderId) select new { userKeys.SenderId, userKeys.AesKey }) { capsula.AesKeysUserIds.Add(user.SenderId); aesBlobsToSend.Add(user.AesKey); } #if (DEBUG) Log($"{capsula.AesKeysUserIds.Count} AES keys will be pushed."); Log($"Sending PullCapsula."); #endif TextEncoder.SendJson(stream, capsula); #if (DEBUG) Log($"Sending AES keys."); #endif foreach (byte[] data in aesBlobsToSend) { BinaryEncoder.SendBytes(stream, data); } #if (DEBUG) Log($"Sending Messages content."); #endif foreach (byte[] data in messagesBlobsToSend) { BinaryEncoder.SendBytes(stream, data); } stream.Flush(); context.SaveChanges(); } #if (DEBUG) Log("Pushing completed."); #endif }