public async Task OutboundChannelCanWriteAsynchronously() { OutboundChannel channel = null; try { var channelResult = Channel.CreateOutboundLocal(GetUniqueName()); channel = channelResult.Data; InconclusiveWhenNotCompleted(channelResult); var data = new byte[11]; var writingResult = await channel.WriteAsync(async (stream) => { await stream.WriteAsync(data, 0, data.Length); return(OperationStatus.Completed); }, data.Length); Assert.AreEqual(OperationStatus.Completed, writingResult.Status); Assert.AreEqual(1, writingResult.Data.MessagesCount, "Message counter should increase after writing"); } finally { channel?.Dispose(); } }
public void OutboundChannelNameCanBeReused() { var name = GetUniqueName(); OutboundChannel channel = null; try { var result = Channel.CreateOutboundLocal(name); channel = result.Data; InconclusiveWhenNotCompleted(result); channel.Dispose(); result = Channel.CreateOutboundLocal(name); channel = result.Data; Assert.AreEqual(OperationStatus.Completed, result.Status); } finally { channel?.Dispose(); } }
public async Task ServerCanAwaitForClient() { var name = GetUniqueName(); OutboundChannel outboundChannel = null; InboundChannel inboundChannel = null; try { var outboundChannelResult = Channel.CreateOutboundLocal(name); outboundChannel = outboundChannelResult.Data; InconclusiveWhenNotCompleted(outboundChannelResult); var task = outboundChannel.WhenClientConnectedAsync(TimeSpan.FromSeconds(1)); var inboundChannelResult = Channel.OpenInboundLocalNoncontainerized(name); inboundChannel = inboundChannelResult.Data; InconclusiveWhenNotCompleted(inboundChannelResult); var status = await task; Assert.AreEqual(OperationStatus.Completed, status); } finally { inboundChannel?.Dispose(); outboundChannel?.Dispose(); } }
public void InboundChannelCanBeOpened() { var name = GetUniqueName(); OutboundChannel outboundChannel = null; InboundChannel inboundChannel = null; try { var outboundChannelResult = Channel.CreateOutboundLocal(name); outboundChannel = outboundChannelResult.Data; InconclusiveWhenNotCompleted(outboundChannelResult); var inboundChannelResult = Channel.OpenInboundLocalNoncontainerized(name); inboundChannel = inboundChannelResult.Data; Assert.AreEqual(OperationStatus.Completed, inboundChannelResult.Status); } finally { inboundChannel?.Dispose(); outboundChannel?.Dispose(); } }
public void MemoryManagerReusesFreeSpaceOnExactMatch() { var name = GetUniqueName(); OutboundChannel outboundChannel = null; InboundChannel inboundChannel = null; try { var outboundChannelResult = Channel.CreateOutboundLocal(name); outboundChannel = outboundChannelResult.Data; InconclusiveWhenNotCompleted(outboundChannelResult); var data = new byte[5]; // Write two nodes var writingResult = outboundChannel.Write((stream) => { stream.Write(data, 0, data.Length); }, data.Length); InconclusiveWhenNotCompleted(outboundChannelResult); writingResult = outboundChannel.Write((stream) => { stream.Write(data, 0, data.Length); }, data.Length); InconclusiveWhenNotCompleted(writingResult); var previousAllocatedSpace = writingResult.Data.AllocatedSpace; var inboundChannelResult = Channel.OpenInboundLocalNoncontainerized(name); inboundChannel = inboundChannelResult.Data; InconclusiveWhenNotCompleted(inboundChannelResult); // Remove node #1 var readingResult = inboundChannel.Read((stream) => { }); InconclusiveWhenNotCompleted(readingResult); // Write node #3 in place of #1 writingResult = outboundChannel.Write((stream) => { stream.Write(data, 0, data.Length); }, data.Length); InconclusiveWhenNotCompleted(writingResult); var allocatedSpace = writingResult.Data.AllocatedSpace; Assert.AreEqual(previousAllocatedSpace, allocatedSpace); } finally { inboundChannel?.Dispose(); outboundChannel?.Dispose(); } }
public async Task InboundChannelCanReadAsynchronously() { var name = GetUniqueName(); OutboundChannel outboundChannel = null; InboundChannel inboundChannel = null; try { var outboundChannelResult = Channel.CreateOutboundLocal(name); outboundChannel = outboundChannelResult.Data; InconclusiveWhenNotCompleted(outboundChannelResult); var data = new byte[5] { 1, 2, 3, 4, 5 }; var writingResult = outboundChannel.Write((stream) => { stream.Write(data, 0, data.Length); return(OperationStatus.Completed); }, data.Length); InconclusiveWhenNotCompleted(writingResult); var inboundChannelResult = Channel.OpenInboundLocalNoncontainerized(name); inboundChannel = inboundChannelResult.Data; InconclusiveWhenNotCompleted(inboundChannelResult); var buffer = new byte[data.Length]; var readingResult = await inboundChannel.ReadAsync(async (stream) => { await stream.ReadAsync(buffer, 0, data.Length); return(OperationStatus.Completed); }); CollectionAssert.AreEqual(data, buffer); Assert.AreEqual(0, readingResult.Data.MessagesCount, "Message counter should decrease after reading"); } finally { inboundChannel?.Dispose(); outboundChannel?.Dispose(); } }
public void OutboundChannelCanBeCreatedAndDisposed() { OutboundChannel channel = null; try { var result = Channel.CreateOutboundLocal(GetUniqueName()); channel = result.Data; Assert.AreEqual(OperationStatus.Completed, result.Status); } finally { channel?.Dispose(); } }
public async Task OutboundChannelCanAwaitWhenQueueIsEmpty() { var name = GetUniqueName(); OutboundChannel outboundChannel = null; InboundChannel inboundChannel = null; try { var data = new byte[5]; var outboundChannelResult = Channel.CreateOutboundLocal(name); outboundChannel = outboundChannelResult.Data; InconclusiveWhenNotCompleted(outboundChannelResult); var inboundChannelResult = Channel.OpenInboundLocalNoncontainerized(name); inboundChannel = inboundChannelResult.Data; InconclusiveWhenNotCompleted(inboundChannelResult); var writingResult = await outboundChannel.WriteAsync(async (stream) => { await stream.WriteAsync(data, 0, data.Length); }, data.Length); InconclusiveWhenNotCompleted(writingResult); var task = outboundChannel.WhenQueueIsEmptyAsync(TimeSpan.FromSeconds(1)); var readingResult = await inboundChannel.ReadAsync(async (stream) => { await stream.ReadAsync(data, 0, data.Length); }); InconclusiveWhenNotCompleted(readingResult); var status = await task; Assert.AreEqual(OperationStatus.Completed, status); } finally { inboundChannel?.Dispose(); outboundChannel?.Dispose(); } }
private async Task ListenAndSendFiles() { const long megabyte = 1024 * 1024; var cancellationToken = _cts.Token; OutboundChannel fileChannel = null; InboundChannel pathChannel = null; try { var acl = new[] { new SecurityIdentifier(WellKnownSidType.AuthenticatedUserSid, null), new SecurityIdentifier(AppContainerSid) }; var pathChannelOperationResult = Channel.CreateInboundGlobal("sample_path", megabyte, acl); var fileChannelOperationResult = Channel.CreateOutboundGlobal("sample_file", megabyte, acl); pathChannel = pathChannelOperationResult.Data; fileChannel = fileChannelOperationResult.Data; if (pathChannelOperationResult.Status == OperationStatus.ObjectAlreadyInUse || fileChannelOperationResult.Status == OperationStatus.ObjectAlreadyInUse) { _eventLog.WriteEntry("Channel wasn't disposed during previous run of the service."); return; } if (pathChannelOperationResult.Status == OperationStatus.ElevationRequired || fileChannelOperationResult.Status == OperationStatus.ElevationRequired) { _eventLog.WriteEntry("Process doesn't have permission to create global shared objects. See https://docs.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/create-global-objects for details."); return; } while (!cancellationToken.IsCancellationRequested) { var waitingForPathStatus = await pathChannel.WhenQueueHasMessagesAsync(cancellationToken, Timeout.InfiniteTimeSpan); if (waitingForPathStatus == OperationStatus.Cancelled) { return; } string path = null; var pathOperationResult = await pathChannel.ReadAsync(async (stream) => { using (var reader = new StreamReader(stream)) path = await reader.ReadLineAsync(); return(OperationStatus.Completed); }, cancellationToken, Timeout.InfiniteTimeSpan); if (pathOperationResult.Status == OperationStatus.Cancelled) { return; } // Actually app is already connected, line below is just example of waiting for connection var waitingForClientStatus = await fileChannel.WhenClientConnectedAsync(cancellationToken, Timeout.InfiniteTimeSpan); if (waitingForClientStatus == OperationStatus.Cancelled) { return; } FileStream fileStream = null; try { var fileOpened = false; try { fileStream = File.OpenRead(path); fileOpened = true; } catch (Exception e) { _eventLog.WriteEntry(e.ToString()); await TryWriteString(fileChannel, "Cannot open this file. Please check Event Log for details."); } if (fileOpened) { var writingOperationResult = await fileChannel.WriteAsync(async (targetStream, parameter, token) => { try { var sourceStream = (Stream)parameter; await sourceStream.CopyToAsync(targetStream, 4096, token); return(OperationStatus.Completed); } catch (Exception e) { if (!(e is OperationCanceledException)) { _eventLog.WriteEntry(e.ToString()); // WriteAsync does not throw, it returns OperationStatus.DelegateFailed } throw; } }, fileStream, fileStream.Length, cancellationToken, Timeout.InfiniteTimeSpan); if (writingOperationResult.Status == OperationStatus.Cancelled) { return; } if (writingOperationResult.Status == OperationStatus.DelegateFailed) { await TryWriteString(fileChannel, "Cannot send file. Please check Event Log for details."); } if (writingOperationResult.Status == OperationStatus.RequestedLengthIsGreaterThanLogicalAddressSpace || writingOperationResult.Status == OperationStatus.RequestedLengthIsGreaterThanVirtualAddressSpace || writingOperationResult.Status == OperationStatus.OutOfSpace) { await TryWriteString(fileChannel, "File is too large."); _eventLog.WriteEntry($"Failed to send file {path} because it is too large."); } } } finally { fileStream?.Close(); } } } catch (Exception e) { _eventLog.WriteEntry(e.ToString()); Stop(); } finally { pathChannel?.Dispose(); fileChannel?.Dispose(); } }
public void MemoryManagerReusesFreeSpaceWhenAllocationRequired() { var name = GetUniqueName(); OutboundChannel outboundChannel = null; InboundChannel inboundChannel = null; const int messageSize = 5; try { var outboundChannelResult = Channel.CreateOutboundLocal(name); outboundChannel = outboundChannelResult.Data; InconclusiveWhenNotCompleted(outboundChannelResult); var data = new byte[messageSize]; // Write two nodes var writingResult = outboundChannel.Write((stream) => { stream.Write(data, 0, data.Length); }, data.Length); InconclusiveWhenNotCompleted(outboundChannelResult); writingResult = outboundChannel.Write((stream) => { stream.Write(data, 0, data.Length); }, data.Length); InconclusiveWhenNotCompleted(writingResult); var inboundChannelResult = Channel.OpenInboundLocalNoncontainerized(name); inboundChannel = inboundChannelResult.Data; InconclusiveWhenNotCompleted(inboundChannelResult); // Remove one node ... var readingResult = inboundChannel.Read((stream) => { }); InconclusiveWhenNotCompleted(readingResult); // ... to write node #3 in place of first node writingResult = outboundChannel.Write((stream) => { stream.Write(data, 0, data.Length); }, data.Length); InconclusiveWhenNotCompleted(writingResult); // Remove node #2 readingResult = inboundChannel.Read((stream) => { }); InconclusiveWhenNotCompleted(readingResult); // To force MM write next large node #4 in place of #2 var previousAllocatedSpace = readingResult.Data.AllocatedSpace; var largeData = new byte[messageSize + 1]; writingResult = outboundChannel.Write((stream) => { stream.Write(largeData, 0, largeData.Length); }, largeData.Length); InconclusiveWhenNotCompleted(writingResult); var allocatedSpace = writingResult.Data.AllocatedSpace; // It is one byte larger than #2, so MM should allocate one additional byte after free node Assert.AreEqual(previousAllocatedSpace + 1, allocatedSpace); } finally { inboundChannel?.Dispose(); outboundChannel?.Dispose(); } }
public void MemoryManagerReusesFreeSpaceWhenItCanSplitFreeNode() { var name = GetUniqueName(); OutboundChannel outboundChannel = null; InboundChannel inboundChannel = null; var sizeOfNode = Marshal.SizeOf <Node>(); try { var outboundChannelResult = Channel.CreateOutboundLocal(name); outboundChannel = outboundChannelResult.Data; InconclusiveWhenNotCompleted(outboundChannelResult); var data = new byte[sizeOfNode]; // Write two nodes having data with length >= size of node's header var writingResult = outboundChannel.Write((stream) => { stream.Write(data, 0, data.Length); }, data.Length); InconclusiveWhenNotCompleted(outboundChannelResult); writingResult = outboundChannel.Write((stream) => { stream.Write(data, 0, data.Length); }, data.Length); var previousAllocatedSpace = writingResult.Data.AllocatedSpace; InconclusiveWhenNotCompleted(writingResult); var inboundChannelResult = Channel.OpenInboundLocalNoncontainerized(name); inboundChannel = inboundChannelResult.Data; InconclusiveWhenNotCompleted(inboundChannelResult); // Remove one var readingResult = inboundChannel.Read((stream) => { }); InconclusiveWhenNotCompleted(readingResult); // Write third empty node writingResult = outboundChannel.Write((stream) => { stream.Write(new byte[0], 0, 0); }, data.Length); InconclusiveWhenNotCompleted(writingResult); // MM should split free node into active node and new free list node var allocatedSpace = writingResult.Data.AllocatedSpace; Assert.AreEqual(previousAllocatedSpace, allocatedSpace); } finally { inboundChannel?.Dispose(); outboundChannel?.Dispose(); } }
public void Dispose() { _pathChannel?.Dispose(); _fileChannel?.Dispose(); }