/// <summary> /// Initializes a new instance of the <see cref="PayloadReceipt"/> class. /// </summary> /// <param name="payload">The payload itself.</param> /// <param name="dateNotificationPosted">The date the cloud inbox received notification of the payload.</param> public PayloadReceipt(Payload payload, DateTimeOffset dateNotificationPosted) { Requires.NotNull(payload, "payload"); this.Payload = payload; this.DateNotificationPosted = dateNotificationPosted; }
/// <summary> /// Executes the send/receive loop until the user exits the chat session with the "#quit" command. /// </summary> /// <param name="friend">The remote endpoint to send messages to.</param> /// <returns>A task representing the asynchronous operation.</returns> private async Task ChatLoopAsync(Endpoint friend) { while (true) { Console.Write("> "); var line = Console.ReadLine(); if (line == "#quit") { return; } if (line.Length > 0) { var payload = new Payload(Encoding.UTF8.GetBytes(line), "text/plain"); await this.Channel.PostAsync(payload, new[] { friend }, DateTime.UtcNow + TimeSpan.FromMinutes(5)); } Console.WriteLine("Awaiting friend's reply..."); var incoming = await this.Channel.ReceiveAsync(longPoll: true); foreach (var payloadReceipt in incoming) { var message = Encoding.UTF8.GetString(payloadReceipt.Payload.Content); Console.WriteLine("< {0}", message); } await Task.WhenAll(incoming.Select(receipt => this.Channel.DeleteInboxItemAsync(receipt.Payload))); } }
/// <summary> /// Deletes the online inbox item that points to a previously downloaded payload. /// </summary> /// <param name="payload">The payload whose originating inbox item should be deleted.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>The task representing the asynchronous operation.</returns> /// <remarks> /// This method should be called after the client application has saved the /// downloaded payload to persistent storage. /// </remarks> public Task DeleteInboxItemAsync(Payload payload, CancellationToken cancellationToken = default(CancellationToken)) { Requires.NotNull(payload, "payload"); Requires.Argument(payload.PayloadReferenceUri != null, "payload", "Original payload reference URI no longer available."); return this.DeletePayloadReferenceAsync(payload.PayloadReferenceUri, cancellationToken); }
/// <summary> /// Encrypts a message and uploads it to the cloud. /// </summary> /// <param name="message">The message being transmitted.</param> /// <param name="expiresUtc">The date after which the message may be destroyed.</param> /// <param name="bytesCopiedProgress">Receives progress in terms of number of bytes uploaded.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>The task whose result is a reference to the uploaded payload including decryption key.</returns> public virtual async Task<PayloadReference> PostPayloadAsync(Payload message, DateTime expiresUtc, IProgress<int> bytesCopiedProgress = null, CancellationToken cancellationToken = default(CancellationToken)) { Requires.NotNull(message, "message"); Requires.That(expiresUtc.Kind == DateTimeKind.Utc, "expiresUtc", Strings.UTCTimeRequired); Requires.ValidState(this.CloudBlobStorage != null, "BlobStorageProvider must not be null"); cancellationToken.ThrowIfCancellationRequested(); var plainTextStream = new MemoryStream(); var writer = new BinaryWriter(plainTextStream); writer.SerializeDataContract(message); writer.Flush(); var plainTextBuffer = plainTextStream.ToArray(); this.Log("Message plaintext", plainTextBuffer); plainTextStream.Position = 0; var cipherTextStream = new MemoryStream(); var encryptionVariables = await this.CryptoServices.EncryptAsync(plainTextStream, cipherTextStream, cancellationToken: cancellationToken).ConfigureAwait(false); this.Log("Message symmetrically encrypted", cipherTextStream.ToArray()); this.Log("Message symmetric key", encryptionVariables.Key); this.Log("Message symmetric IV", encryptionVariables.IV); cipherTextStream.Position = 0; var hasher = WinRTCrypto.HashAlgorithmProvider.OpenAlgorithm(this.CryptoServices.SymmetricHashAlgorithm); var messageHash = hasher.HashData(cipherTextStream.ToArray()); this.Log("Encrypted message hash", messageHash); cipherTextStream.Position = 0; Uri blobUri = await this.CloudBlobStorage.UploadMessageAsync(cipherTextStream, expiresUtc, contentType: message.ContentType, bytesCopiedProgress: bytesCopiedProgress, cancellationToken: cancellationToken).ConfigureAwait(false); return new PayloadReference(blobUri, messageHash, this.CryptoServices.SymmetricHashAlgorithm.GetHashAlgorithmName(), encryptionVariables.Key, encryptionVariables.IV, expiresUtc); }
/// <summary> /// Encrypts a message and uploads it to the cloud. /// </summary> /// <param name="message">The message being transmitted.</param> /// <param name="expiresUtc">The date after which the message may be destroyed.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>The task whose result is a reference to the uploaded payload including decryption key.</returns> protected virtual async Task<PayloadReference> PostPayloadAsync(Payload message, DateTime expiresUtc, CancellationToken cancellationToken) { Requires.NotNull(message, "message"); Requires.That(expiresUtc.Kind == DateTimeKind.Utc, "expiresUtc", Strings.UTCTimeRequired); Requires.ValidState(this.CloudBlobStorage != null, "BlobStorageProvider must not be null"); cancellationToken.ThrowIfCancellationRequested(); var plainTextStream = new MemoryStream(); var writer = new BinaryWriter(plainTextStream); writer.SerializeDataContract(message); writer.Flush(); var plainTextBuffer = plainTextStream.ToArray(); this.Log("Message plaintext", plainTextBuffer); var encryptionResult = this.CryptoServices.Encrypt(plainTextBuffer); this.Log("Message symmetrically encrypted", encryptionResult.Ciphertext); this.Log("Message symmetric key", encryptionResult.Key); this.Log("Message symmetric IV", encryptionResult.IV); var messageHash = this.CryptoServices.Hash(encryptionResult.Ciphertext); this.Log("Encrypted message hash", messageHash); using (MemoryStream cipherTextStream = new MemoryStream(encryptionResult.Ciphertext)) { Uri blobUri = await this.CloudBlobStorage.UploadMessageAsync(cipherTextStream, expiresUtc, cancellationToken: cancellationToken); return new PayloadReference(blobUri, messageHash, encryptionResult.Key, encryptionResult.IV, expiresUtc); } }
/// <summary> /// Sends some payload to a set of recipients. /// </summary> /// <param name="message">The payload to transmit.</param> /// <param name="recipients">The recipients to receive the message.</param> /// <param name="expiresUtc">The date after which the message may be destroyed.</param> /// <param name="bytesCopiedProgress">Progress in terms of bytes copied.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>The task representing the asynchronous operation.</returns> public async Task<IReadOnlyCollection<NotificationPostedReceipt>> PostAsync(Payload message, IReadOnlyCollection<Endpoint> recipients, DateTime expiresUtc, IProgress<int> bytesCopiedProgress = null, CancellationToken cancellationToken = default(CancellationToken)) { Requires.NotNull(message, "message"); Requires.That(expiresUtc.Kind == DateTimeKind.Utc, "expiresUtc", Strings.UTCTimeRequired); Requires.NotNullOrEmpty(recipients, "recipients"); var payloadReference = await this.PostPayloadAsync(message, expiresUtc, bytesCopiedProgress, cancellationToken).ConfigureAwait(false); return await this.PostPayloadReferenceAsync(payloadReference, recipients, cancellationToken).ConfigureAwait(false); }
/// <summary> /// Sends some payload to a set of recipients. /// </summary> /// <param name="message">The payload to transmit.</param> /// <param name="recipients">The recipients to receive the message.</param> /// <param name="expiresUtc">The date after which the message may be destroyed.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>The task representing the asynchronous operation.</returns> public async Task PostAsync(Payload message, ReadOnlyCollectionOfEndpoint recipients, DateTime expiresUtc, CancellationToken cancellationToken = default(CancellationToken)) { Requires.NotNull(message, "message"); Requires.That(expiresUtc.Kind == DateTimeKind.Utc, "expiresUtc", Strings.UTCTimeRequired); Requires.NotNullOrEmpty(recipients, "recipients"); var payloadReference = await this.PostPayloadAsync(message, expiresUtc, cancellationToken); await this.PostPayloadReferenceAsync(payloadReference, recipients, cancellationToken); }
/// <summary> /// Sends some payload to a set of recipients. /// </summary> /// <param name="message">The payload to transmit.</param> /// <param name="recipients">The recipients to receive the message.</param> /// <param name="expiresUtc">The date after which the message may be destroyed.</param> /// <param name="bytesCopiedProgress">Progress in terms of bytes copied.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>The task representing the asynchronous operation.</returns> public async Task <IReadOnlyCollection <NotificationPostedReceipt> > PostAsync(Payload message, IReadOnlyCollection <Endpoint> recipients, DateTime expiresUtc, IProgress <int> bytesCopiedProgress = null, CancellationToken cancellationToken = default(CancellationToken)) { Requires.NotNull(message, "message"); Requires.That(expiresUtc.Kind == DateTimeKind.Utc, "expiresUtc", Strings.UTCTimeRequired); Requires.NotNullOrEmpty(recipients, "recipients"); var payloadReference = await this.PostPayloadAsync(message, expiresUtc, bytesCopiedProgress, cancellationToken); return(await this.PostPayloadReferenceAsync(payloadReference, recipients, cancellationToken)); }
private async Task ProcessReceivedMessagedAsync(Payload payload) { var message = Encoding.UTF8.GetString(payload.Content); this.History.Items.Add(message); await this.Channel.DeleteInboxItemAsync(payload); }
private async void SendMessageButton_Click(object sender, RoutedEventArgs e) { this.AuthoredMessage.IsReadOnly = true; this.SendMessageButton.IsEnabled = false; try { if (this.AuthoredMessage.Text.Length > 0) { var payload = new Payload(Encoding.UTF8.GetBytes(this.AuthoredMessage.Text), "text/plain"); await this.Channel.PostAsync(payload, this.members.Values.ToList(), DateTime.UtcNow + TimeSpan.FromDays(14)); } this.BottomInfoBar.Visibility = Visibility.Collapsed; this.AuthoredMessage.Text = string.Empty; } catch (Exception ex) { this.BottomInfoBar.Text = "Unable to transmit message: " + ex.Message; this.BottomInfoBar.Visibility = Visibility.Visible; } finally { this.AuthoredMessage.IsReadOnly = false; this.SendMessageButton.IsEnabled = true; } }