/// <summary> /// The ensure length. /// </summary> /// <param name="buffer"> /// The buffer. /// </param> /// <param name="length"> /// The length. /// </param> /// <param name="withRepeat"> /// The with repeat. /// </param> /// <returns> /// The <see cref="IBuffer"/>. /// </returns> private static IBuffer EnsureLength(IBuffer buffer, int length, bool withRepeat) { if (buffer.Length == length) { return(buffer); } if (buffer.Length > length) { var array = new byte[length]; buffer.CopyTo(0, array, 0, length); return(array.AsBuffer()); } var longerArray = new byte[length]; if (!withRepeat) { buffer.CopyTo(0, longerArray, 0, (int)buffer.Length); return(longerArray.AsBuffer()); } var pos = 0; while (pos < length) { var toGo = length - pos; var pad = toGo <= buffer.Length ? toGo : (int)buffer.Length; buffer.CopyTo(0, longerArray, pos, pad); pos += pad; } return(longerArray.AsBuffer()); }
private Task <uint> createSaveBufferTask(IBuffer buffer) { if (OnDataWriting != null) { var arg = new BufferWriteEventArgs(BufferActions.Write, _position, buffer.Length); OnDataWriting(this, ref arg); if (!arg.IsAllowed) { return(new Task <uint>(() => { return buffer.Length; })); } } return(new Task <uint>(() => { uint len = buffer.Length; var data = new byte[len]; buffer.CopyTo(data); try { doSend(data); if (_position + len > _streamSize) { _streamSize = _position + len; } return len; } catch { DataSendingFailed?.Invoke(this, new EventArgs()); return 0; } })); }
/// <summary> /// Encrypt value using password. /// </summary> /// <param name="value">Value to encrypt.</param> /// <param name="key">Key that is used for encryption.</param> /// <returns>A buffer with the encrypted data is returned.</returns> public IBuffer Encrypt(string value, string key) { // Create a Sha256 from key. var passwordBuffer = CryptographicBuffer.ConvertStringToBinary(key, BinaryStringEncoding.Utf8); var hashProvider = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256); IBuffer keyMaterial = hashProvider.HashData(passwordBuffer); // Create an Aes256 with CBC and Pkcs7 var aesProvider = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesCbcPkcs7); CryptographicKey aesKey = aesProvider.CreateSymmetricKey(keyMaterial); // Create a random IV so the password can be used more than once. IBuffer iv = CryptographicBuffer.GenerateRandom(aesProvider.BlockLength); // Encrypt value. var data = CryptographicBuffer.ConvertStringToBinary(value, BinaryStringEncoding.Utf8); IBuffer encrypted = CryptographicEngine.Encrypt(aesKey, data, iv); // Insert random generated IV before encrypted message because it will be needed at decryption. IBuffer result = CryptographicBuffer.CreateFromByteArray(new byte[iv.Length + encrypted.Length]); iv.CopyTo(0, result, 0, iv.Length); encrypted.CopyTo(0, result, iv.Length, encrypted.Length); return(result); }
public static byte[] ToArray(this IBuffer source, uint sourceIndex, int count) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (count < 0) { throw new ArgumentOutOfRangeException(nameof(count)); } if (source.Capacity <= sourceIndex) { throw new ArgumentException(SR.Argument_BufferIndexExceedsCapacity); } if (source.Capacity - sourceIndex < count) { throw new ArgumentException(SR.Argument_InsufficientSpaceInSourceBuffer); } if (count == 0) { return(Array.Empty <byte>()); } byte[] destination = new byte[count]; source.CopyTo(sourceIndex, destination, 0, count); return(destination); }
/// <summary> /// Derives the base key used by <see cref="HmacBlockHandler"/> given /// a database's master seed and the user's composite key. /// /// The derived key is a SHA-512 hash of the result of concatenating /// these values together, with the byte 0x1 appended at the end. /// </summary> /// <param name="compositeKey">The user's composite key.</param> /// <param name="masterSeed">The database's master seed.</param> /// <returns>A buffer to use for an HMAC block key.</returns> public static IBuffer DeriveHmacKey(IBuffer compositeKey, IBuffer masterSeed) { if (compositeKey == null) { throw new ArgumentNullException(nameof(compositeKey)); } if (masterSeed == null) { throw new ArgumentNullException(nameof(masterSeed)); } if (compositeKey.Length != 32) { throw new ArgumentException("Composite key should be 32 bytes", nameof(compositeKey)); } if (masterSeed.Length != 32) { throw new ArgumentException("Master seed should be 32 bytes", nameof(masterSeed)); } byte[] buffer = new byte[compositeKey.Length + masterSeed.Length + 1]; masterSeed.CopyTo(buffer); compositeKey.CopyTo(0, buffer, (int)masterSeed.Length, (int)compositeKey.Length); buffer[buffer.Length - 1] = 1; HashAlgorithmProvider sha512 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha512); CryptographicHash hash = sha512.CreateHash(); hash.Append(buffer.AsBuffer()); return(hash.GetValueAndReset()); }
public void TestWrite() { LosgapSystem.InvokeOnMaster(() => { // Define variables and constants IBuffer res = BufferFactory.NewBuffer <int>() .WithUsage(ResourceUsage.Write) .WithLength(100) .Create(); IBuffer copyDest = (res as Buffer <int>).Clone() .WithUsage(ResourceUsage.StagingRead) .WithPermittedBindings(GPUBindings.None) .Create(); // Set up context // Execute Assert.IsTrue(res.CanWrite); res.Write(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, 10U); res.CopyTo(copyDest); // Assert outcome byte[] readData = copyDest.Read(); for (int i = 10; i < 20; ++i) { Assert.AreEqual(i - 9, readData[i]); } res.Dispose(); copyDest.Dispose(); }); }
public static byte[] ToArray(this IBuffer source, uint sourceIndex, int count) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (count < 0) { throw new ArgumentOutOfRangeException(nameof(count)); } if (source.Length < sourceIndex) { throw new ArgumentException("The specified buffer index is not within the buffer length."); } if (source.Length - sourceIndex < count) { throw new ArgumentException(global::Windows.Storage.Streams.SR.Argument_InsufficientSpaceInSourceBuffer); } if (count == 0) { return(Array.Empty <byte>()); } byte[] destination = new byte[count]; source.CopyTo(sourceIndex, destination, 0, count); return(destination); }
public static Byte[] ToArray(this IBuffer source, UInt32 sourceIndex, Int32 count) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (count < 0) { throw new ArgumentOutOfRangeException(nameof(count)); } if (sourceIndex < 0) { throw new ArgumentOutOfRangeException(nameof(sourceIndex)); } if (source.Capacity <= sourceIndex) { throw new ArgumentException(SR.Argument_BufferIndexExceedsCapacity); } if (source.Capacity - sourceIndex < count) { throw new ArgumentException(SR.Argument_InsufficientSpaceInSourceBuffer); } Contract.EndContractBlock(); if (count == 0) { return(Array.Empty <Byte>()); } Byte[] destination = new Byte[count]; source.CopyTo(sourceIndex, destination, 0, count); return(destination); }
/// <summary> /// Asynchronously transforms the user's 32-byte key using ECB AES. /// /// Since Rijndael works on 16-byte blocks, the k is split in half and /// each half is encrypted separately the same number of times. /// </summary> /// <param name="rawKey">The key to transform.</param> /// <param name="token">Token used to cancel the transform task.</param> /// <returns>The transformed key.</returns> public async Task <IBuffer> TransformKeyAsync(IBuffer rawKey, CancellationToken token) { if (rawKey == null) { throw new ArgumentNullException(nameof(rawKey)); } if (rawKey.Length != 32) { throw new ArgumentException("Key must be 32 bytes", nameof(rawKey)); } // Split the k buffer in half byte[] rawKeyBytes = rawKey.ToArray(); IBuffer lowerBuffer = WindowsRuntimeBuffer.Create(rawKeyBytes, 0, 16, 16); IBuffer upperBuffer = WindowsRuntimeBuffer.Create(rawKeyBytes, 16, 16, 16); // Set up the encryption parameters var aes = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesEcb); CryptographicKey key = aes.CreateSymmetricKey(this.algoParams.Seed); IBuffer iv = null; // Run the encryption rounds in two threads (upper and lower) ConditionChecker checkForCancel = () => token.IsCancellationRequested; Task <bool> lowerTask = Task.Run(() => { lowerBuffer = KeePassHelper.TransformKey(this.algoParams.Rounds, this.algoParams.Seed, iv, lowerBuffer, checkForCancel); return(!checkForCancel()); } ); Task <bool> upperTask = Task.Run(() => { upperBuffer = KeePassHelper.TransformKey(this.algoParams.Rounds, this.algoParams.Seed, iv, upperBuffer, checkForCancel); return(!checkForCancel()); } ); // Verify the work was completed successfully await Task.WhenAll(lowerTask, upperTask); if (!(lowerTask.Result && upperTask.Result)) { return(null); } // Copy the units of work back into one buffer, hash it, and return. IBuffer transformedKey = (new byte[32]).AsBuffer(); lowerBuffer.CopyTo(0, transformedKey, 0, 16); upperBuffer.CopyTo(0, transformedKey, 16, 16); var sha256 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256); CryptographicHash hash = sha256.CreateHash(); hash.Append(transformedKey); return(hash.GetValueAndReset()); }
/// <summary> /// Ends an asynchronous Receive /// </summary> /// <param name="ar">AsyncResult obtained from BeginReive</param> /// <param name="Error">Indicates an error occured while receiving data</param> /// <returns>Received Data</returns> public byte[] EndReceive(IAsyncResult ar, out bool Error) { Error = false; int bytesRead = 0; try { lock (syncSocket) { bytesRead = socket.EndReceive(ar); } } catch (ObjectDisposedException ex) { if (!isClosing) { Diags.LogSocketException(ex); } Error = true; } catch (Exception ex) { Diags.LogSocketException(ex); Error = true; } byte[] readData; if (Error || bytesRead < 0) { readData = new byte[0]; } else { readData = new byte[bytesRead]; } if (recvBuffer != null && !recvBuffer.IsDisposed) { if (!Error && bytesRead > 0) { recvBuffer.CopyTo(readData, 0, bytesRead); } //Dispose buffer if it's greater than a specified threshold if (recvBuffer.Size > BufferRenewalSizeThreshold) { recvBuffer.Dispose(); } } return(readData); }
/// <summary> /// Loads the byte data from a StorageFile /// </summary> /// <param name="file">The file to read</param> public async Task <byte[]> ReadFile(StorageFile file) { using (IRandomAccessStreamWithContentType stream = await file.OpenReadAsync()) { stream.Seek((ulong)0); byte[] fileBytes = new byte[stream.Size]; var buffer = CryptographicBuffer.CreateFromByteArray(fileBytes); IBuffer rd = await stream.ReadAsync(buffer, (uint)fileBytes.Length, InputStreamOptions.None); rd.CopyTo(fileBytes); return(fileBytes); } }
protected override void SendToRemote(byte[] e) { if (remoteConnected) { try { r.Send(e); } catch (Exception) { Debug.WriteLine("Cannot send to remote"); Dispose(); return; } LogData("Sent to remote ", e); // Send header first, followed by local buffer if (localbuf != null) { IBuffer newLocalbuf; lock (localbuf) { if (localbuf != null && localbuf.Length > 0) { newLocalbuf = WindowsRuntimeBuffer.Create((int)localbuf.Length); localbuf.CopyTo(newLocalbuf); newLocalbuf.Length = localbuf.Length; //LogData("Sending local buffer ", newLocalbuf.ToArray()); localbuf = null; } else { localbuf = null; return; } } r.Send(newLocalbuf.ToArray()); Debug.WriteLine("Buffer sent"); //await r.OutputStream.WriteAsync(outData.Take((int)len).ToArray().AsBuffer()); } return; } else { lock (localbuf) { e.CopyTo(0, localbuf, localbuf.Length, e.Length); localbuf.Length += (uint)e.Length; } return; } }
internal static void EnsureResultsInUserBuffer(IBuffer userBuffer, IBuffer resultBuffer) { // Results buffer may be different from user specified buffer. If so - copy data to the user. Debug.Assert(userBuffer != null); Debug.Assert(resultBuffer != null); if (resultBuffer.IsSameData(userBuffer)) { return; } resultBuffer.CopyTo(userBuffer); userBuffer.Length = resultBuffer.Length; }
/// <summary> /// Decrypt buffer using password. /// </summary> /// <param name="data">Data buffer to decrypt.</param> /// <param name="key">Key that is used for decryption.</param> /// <returns>Returns the decrypted value as string.</returns> public string Decrypt(IBuffer data, string key) { // Create a Sha256 from key. var passwordBuffer = CryptographicBuffer.ConvertStringToBinary(key, BinaryStringEncoding.Utf8); var hashProvider = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256); IBuffer keyMaterial = hashProvider.HashData(passwordBuffer); // Create am Aes256 with CBC and Pkcs7. var aesProvider = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesCbcPkcs7); CryptographicKey aesKey = aesProvider.CreateSymmetricKey(keyMaterial); // Split data into IV and encrypted data. IBuffer iv = CryptographicBuffer.CreateFromByteArray(new byte[aesProvider.BlockLength]); IBuffer encrypted = CryptographicBuffer.CreateFromByteArray(new byte[data.Length - iv.Length]); data.CopyTo(0, iv, 0, iv.Length); data.CopyTo(iv.Length, encrypted, 0, encrypted.Length); // Decrypt data. IBuffer decrypted = CryptographicEngine.Decrypt(aesKey, encrypted, iv); string value = CryptographicBuffer.ConvertBinaryToString(BinaryStringEncoding.Utf8, decrypted); return(value); }
unsafe int DecryptBuffer(IBuffer buf, Span <byte> outBuf) { var len = (int)buf.Length; if (len == 0) { return(0); } if (buf != recvDataBuffer) { buf.CopyTo(0, recvDataBuffer, 0, (uint)len); } return((int)Decrypt(recvData.AsSpan(0, len), outBuf.Slice(0, len))); }
/// <summary> /// Given a stream past the header, asynchronously fetches encrypted ciphertext /// from the file as a single buffer. /// </summary> /// <remarks> /// For KDBX3.1, this is just the rest of the stream. For KDBX4, it involves /// pulling out HMAC blocks from the stream. /// </remarks> /// <param name="dataStream">The stream representing the remainder of the database file.</param> /// <returns>A buffer representing the encrypted database.</returns> private async Task <IBuffer> GetCipherText(IRandomAccessStream dataStream, HmacBlockHandler macHandler) { uint streamRemaining = (uint)(dataStream.Size - dataStream.Position); DebugHelper.Trace("Stream has {0} bytes remaining.", streamRemaining); IBuffer fileRemainder; using (DataReader reader = GetReaderForStream(dataStream)) { if (this.parameters.UseHmacBlocks) { // KDBX 4: HMAC block content int bytesLeft = (int)streamRemaining; DebugHelper.Assert(bytesLeft > 0); fileRemainder = WindowsRuntimeBuffer.Create(bytesLeft); for (ulong index = 0; bytesLeft > 0; index++) { IBuffer block = await macHandler.ReadCipherBlockAsync(reader, index); if (block == null || block.Length == 0) { break; } DebugHelper.Assert((int)block.Length > 0); bytesLeft -= (int)block.Length + 4 + 32; block.CopyTo(0, fileRemainder, fileRemainder.Length, block.Length); fileRemainder.Length += block.Length; } } else { // KDBX 3.1: Rest of file as-is DebugHelper.Assert(reader.UnconsumedBufferLength == 0); await reader.LoadAsync(streamRemaining).AsTask().ConfigureAwait(false); fileRemainder = reader.ReadBuffer(streamRemaining); } reader.DetachStream(); return(fileRemainder); } }
private async void OnPreviewFrameAvailable(IImageSize imageSize) { if (!_isRendering) { _isRendering = true; await _writeableBitmapRenderer.RenderAsync(); await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync( CoreDispatcherPriority.High, () => { int bufferSize = _writeableBitmap.PixelWidth *_writeableBitmap.PixelHeight * 4; if (_buffer == null || _buffer.Length != bufferSize) { _buffer = new byte[bufferSize]; } IBuffer pixelBuffer = _writeableBitmap.PixelBuffer; pixelBuffer.CopyTo(_buffer); GCHandle handle = GCHandle.Alloc(_buffer, GCHandleType.Pinned); using ( Mat m = new Mat(_writeableBitmap.PixelHeight, _writeableBitmap.PixelWidth, DepthType.Cv8U, 4, handle.AddrOfPinnedObject(), _writeableBitmap.PixelWidth * 4)) using (Mat gray = new Mat()) using (Mat canny = new Mat()) { CvInvoke.CvtColor(m, gray, ColorConversion.Bgr2Gray); CvInvoke.Canny(gray, canny, 40, 60); CvInvoke.CvtColor(canny, m, ColorConversion.Gray2Bgra); } handle.Free(); using (Stream s = pixelBuffer.AsStream()) { s.Write(_buffer, 0, _buffer.Length); } _writeableBitmap.Invalidate(); }); _isRendering = false; } }
// Implements sending of video/audio data to the service. // The message is encoded the following way: // 4 bytes - position in MP4 file where data shall be put. // n bytes - video/audio data. public IAsyncOperationWithProgress <uint, uint> WriteAsync(IBuffer buffer) { Task <uint> aTask = new Task <uint>(() => { uint aVideoDataLength = buffer.Length; byte[] aMessage = new byte[aVideoDataLength + 4]; // Put position within MP4 file to the message. byte[] aPosition = BitConverter.GetBytes((int)this.Position); Array.Copy(aPosition, aMessage, aPosition.Length); // Put video/audio data to the message. buffer.CopyTo(0, aMessage, 4, (int)aVideoDataLength); uint aTransferedSize = 0; try { // Send the message to the service. // myOutputChannel.SendMessage(aMessage); this.pushStream.Write(aMessage); memoryBuffer.WriteAsync(buffer); aTransferedSize = (uint)aVideoDataLength; } catch { // If sending fails then the connection is broken. if (ConnectionBroken != null) { ConnectionBroken(this, new EventArgs()); } } return(aTransferedSize); }); aTask.RunSynchronously(); Func <CancellationToken, IProgress <uint>, Task <uint> > aTaskProvider = (token, progress) => aTask; return(AsyncInfo.Run <uint, uint>(aTaskProvider)); }
/// <summary> /// Generates the HMAC-SHA-256 value for a given block. /// The actual hashed value is i || n (block size) || C. /// </summary> /// <param name="i">The block index.</param> /// <param name="cipherText">Encrypted block value.</param> /// <param name="offset">Offset into <paramref name="cipherText"/>.</param> /// <param name="length">Number of bytes of <paramref name="cipherText"/> to use.</param> /// <returns>The HMAC value of the block.</returns> public IBuffer GetMacForBlock(ulong i, IBuffer cipherText, uint offset, uint length) { if (cipherText == null) { throw new ArgumentNullException(nameof(cipherText)); } if (offset > cipherText.Length) { throw new ArgumentOutOfRangeException(nameof(offset)); } length = (offset + length > cipherText.Length ? cipherText.Length - offset : length); DebugHelper.Assert(length <= int.MaxValue); // Construct the HMAC buffer: i || n || C byte[] buffer = new byte[8 + 4 + length]; ByteHelper.GetLittleEndianBytes(i, buffer); ByteHelper.GetLittleEndianBytes(length, buffer, 8); if (length > 0) { // Necessary because buffers don't play nice if they're empty... cipherText.CopyTo(offset, buffer, 12, (int)length); } CryptographicHash hash = this.hmacAlgo.CreateHash(GetKeyForBlock(i)); hash.Append(buffer.AsBuffer()); IBuffer macValue = hash.GetValueAndReset(); DebugHelper.Trace($"Generating MAC value for block #{i}, data length {length}"); if (length > 0) { DebugHelper.Trace($"data[0]: { buffer[12]}, data[n]: { buffer[buffer.Length - 1]}"); } DebugHelper.Trace($"MAC[0]: {macValue.GetByte(0)}, MAC[31]: {macValue.GetByte(31)}"); return(macValue); }
private async void Sck_MessageReceived(MessageWebSocket sender, MessageWebSocketMessageReceivedEventArgs args) { //[email protected]("Message received " + args); if (args.MessageType == SocketMessageType.Utf8) { Windows.Storage.Streams.DataReader messageReader = args.GetDataReader(); messageReader.UnicodeEncoding = UnicodeEncoding.Utf8; string messageString = messageReader.ReadString(messageReader.UnconsumedBufferLength); com.codename1.io.websocket.WebSocket.messageReceived(id, messageString); } else { Windows.Storage.Streams.IInputStream readStream = args.GetDataStream(); byte[] readBuffer = new byte[4096]; try { while (true) { if (sender != sck) { return; } IBuffer res = await readStream.ReadAsync(readBuffer.AsBuffer(), (uint)readBuffer.Length, 0); if (res.Length == 0) { return; } byte[] resArr = new byte[res.Length]; res.CopyTo(resArr); com.codename1.io.websocket.WebSocket.messageReceived(1, resArr); } } catch (Exception ex) { com.codename1.io.websocket.WebSocket.errorReceived(id, ex.Message, ex.HResult); } } }
private async Task RestoreBitmapAsync(int width, int height) { _bitmap = new WriteableBitmap(width, height); var folder = ApplicationData.Current.LocalFolder; var file = await folder.GetFileAsync(c_filename); using (var stream = await file.OpenAsync(FileAccessMode.Read)) { using (var input = stream.GetInputStreamAt(0)) { using (var reader = new DataReader(input)) { var size = await reader.LoadAsync((uint)stream.Size); IBuffer pixels = reader.ReadBuffer(size); pixels.CopyTo(_bitmap.PixelBuffer); Photo.Source = _bitmap; _bitmap.Invalidate(); } } } }
private void OnMessageReceived(MessageWebSocket sender, MessageWebSocketMessageReceivedEventArgs args) { // GetDataReader() throws an exception when either: // (1) The underlying TCP connection is closed prematurely (e.g., FIN/RST received without sending/receiving a WebSocket Close frame). // (2) The server sends invalid data (e.g., corrupt HTTP headers or a message exceeding the MaxMessageSize). // // In both cases, the appropriate thing to do is to close the socket, as we have reached an unexpected state in // the WebSocket protocol. try { using (DataReader reader = args.GetDataReader()) { uint dataAvailable; while ((dataAvailable = reader.UnconsumedBufferLength) > 0) { ArraySegment <byte> buffer; try { buffer = _receiveAsyncBufferTcs.Task.GetAwaiter().GetResult(); } catch (OperationCanceledException) // Caused by Abort call on WebSocket { return; } _receiveAsyncBufferTcs = new TaskCompletionSource <ArraySegment <byte> >(); WebSocketMessageType messageType; if (args.MessageType == SocketMessageType.Binary) { messageType = WebSocketMessageType.Binary; } else { messageType = WebSocketMessageType.Text; } bool endOfMessage = false; uint readCount = Math.Min(dataAvailable, (uint)buffer.Count); if (readCount > 0) { IBuffer dataBuffer = reader.ReadBuffer(readCount); // Safe to cast readCount to int as the maximum value that readCount can be is buffer.Count. dataBuffer.CopyTo(0, buffer.Array, buffer.Offset, (int)readCount); } if (dataAvailable == readCount) { endOfMessage = !IsPartialMessageEvent(args); } WebSocketReceiveResult recvResult = new WebSocketReceiveResult((int)readCount, messageType, endOfMessage); _webSocketReceiveResultTcs.TrySetResult(recvResult); } } } catch (Exception exc) { // WinRT WebSockets always throw exceptions of type System.Exception. However, we can determine whether // or not we're dealing with a known error by using WinRT's WebSocketError.GetStatus method. WebErrorStatus status = RTWebSocketError.GetStatus(exc.HResult); WebSocketError actualError = WebSocketError.Faulted; switch (status) { case WebErrorStatus.ConnectionAborted: case WebErrorStatus.ConnectionReset: case WebErrorStatus.Disconnected: actualError = WebSocketError.ConnectionClosedPrematurely; break; } // Propagate a custom exception to any pending ReceiveAsync/CloseAsync operations and close the socket. WebSocketException customException = new WebSocketException(actualError, exc); AbortInternal(customException); } }
private static void DoTestRead(Func <IInputStream> createStreamFunc, InputStreamOptions inputStreamOptions, bool mustInvokeProgressHandler, bool completesSynchronously) { IInputStream stream = createStreamFunc(); IBuffer buffer = WindowsRuntimeBuffer.Create(TestStreamProvider.ModelStreamLength); IAsyncOperationWithProgress <IBuffer, uint> readOp = stream.ReadAsync(buffer, (uint)TestStreamProvider.ModelStreamLength, inputStreamOptions); if (completesSynchronously) { // New readOp for a stream where we know that reading is sycnhronous must have Status = Completed Assert.Equal(AsyncStatus.Completed, readOp.Status); } else { // Note the race. By the tie we get here, the status of the op may be started or already completed. AsyncStatus readOpStatus = readOp.Status; Assert.True(readOpStatus == AsyncStatus.Completed || readOpStatus == AsyncStatus.Started, "New readOp must have Status = Started or Completed (race)"); } bool progressCallbackInvoked = false; bool completedCallbackInvoked = false; uint readOpId = readOp.Id; EventWaitHandle waitHandle = new ManualResetEvent(false); readOp.Progress = (asyncReadOp, bytesCompleted) => { progressCallbackInvoked = true; // asyncReadOp.Id in a progress callback must match the ID of the asyncReadOp to which the callback was assigned Assert.Equal(readOpId, asyncReadOp.Id); // asyncReadOp.Status must be 'Started' for an asyncReadOp in progress Assert.Equal(AsyncStatus.Started, asyncReadOp.Status); // bytesCompleted must be in range [0, maxBytesToRead] asyncReadOp in progress Assert.InRange(bytesCompleted, 0u, (uint)TestStreamProvider.ModelStreamLength); }; readOp.Completed = (asyncReadOp, passedStatus) => { try { completedCallbackInvoked = true; // asyncReadOp.Id in a completion callback must match the ID of the asyncReadOp to which the callback was assigned Assert.Equal(readOpId, asyncReadOp.Id); // asyncReadOp.Status must match passedStatus for a completed asyncReadOp Assert.Equal(passedStatus, asyncReadOp.Status); // asyncReadOp.Status must be 'Completed' for a completed asyncReadOp Assert.Equal(AsyncStatus.Completed, asyncReadOp.Status); IBuffer resultBuffer = asyncReadOp.GetResults(); // asyncReadOp.GetResults() must not return null for a completed asyncReadOp Assert.NotNull(resultBuffer); AssertExtensions.GreaterThan(resultBuffer.Capacity, 0u, "resultBuffer.Capacity should be more than zero in completed callback"); AssertExtensions.GreaterThan(resultBuffer.Length, 0u, "resultBuffer.Length should be more than zero in completed callback"); AssertExtensions.LessThanOrEqualTo(resultBuffer.Length, resultBuffer.Capacity, "resultBuffer.Length should be <= Capacity in completed callback"); if (inputStreamOptions == InputStreamOptions.None) { // resultBuffer.Length must be equal to requested number of bytes when an asyncReadOp with // InputStreamOptions.None completes successfully Assert.Equal(resultBuffer.Length, (uint)TestStreamProvider.ModelStreamLength); } if (inputStreamOptions == InputStreamOptions.Partial) { AssertExtensions.LessThanOrEqualTo(resultBuffer.Length, (uint)TestStreamProvider.ModelStreamLength, "resultBuffer.Length must be <= requested number of bytes with InputStreamOptions.Partial in completed callback"); } buffer = resultBuffer; } finally { waitHandle.Set(); } }; // Now, let's block until the read op is complete. // We speculate that it will complete within 3500 msec, although under high load it may not be. // If the test fails we should use a better way to determine if callback is really not invoked, or if it's just too slow. waitHandle.WaitOne(500); waitHandle.WaitOne(1000); waitHandle.WaitOne(2000); if (mustInvokeProgressHandler) { Assert.True(progressCallbackInvoked, "Progress callback specified to ReadAsync callback must be invoked when reading from this kind of stream"); } Assert.True(completedCallbackInvoked, "Completion callback specified to ReadAsync callback must be invoked"); // readOp.Status must be 'Completed' for a completed async readOp Assert.Equal(AsyncStatus.Completed, readOp.Status); AssertExtensions.GreaterThan(buffer.Capacity, 0u, "buffer.Capacity should be greater than zero bytes"); AssertExtensions.GreaterThan(buffer.Length, 0u, "buffer.Length should be greater than zero bytes"); AssertExtensions.LessThanOrEqualTo(buffer.Length, buffer.Capacity, "buffer.Length <= buffer.Capacity is required for a completed async readOp"); if (inputStreamOptions == InputStreamOptions.None) { // buffer.Length must be equal to requested number of bytes when an async readOp with // InputStreamOptions.None completes successfully Assert.Equal((uint)TestStreamProvider.ModelStreamLength, buffer.Length); } if (inputStreamOptions == InputStreamOptions.Partial) { AssertExtensions.LessThanOrEqualTo(buffer.Length, (uint)TestStreamProvider.ModelStreamLength, "resultBuffer.Length must be <= requested number of bytes with InputStreamOptions.Partial"); } byte[] results = new byte[buffer.Length]; buffer.CopyTo(0, results, 0, (int)buffer.Length); Assert.True(TestStreamProvider.CheckContent(results, 0, (int)buffer.Length), "Result data returned from AsyncRead must be the same as expected from the test data source"); }