internal static OperationResult <InboundChannel> Open(string fullName, string name) { Semaphore readerSemaphore = null; MemoryMappedFile file = null; Semaphore exclusiveAccessSemaphore = null; EventWaitHandle hasMessagesEvent = null; EventWaitHandle noMessagesEvent = null; EventWaitHandle clientConnectedEvent = null; try { var readerSemaphoreOperationResult = LifecycleHelper.OpenAndSetReaderSemaphore(fullName); if (readerSemaphoreOperationResult.Status != OperationStatus.Completed) { return(new OperationResult <InboundChannel>(readerSemaphoreOperationResult.Status, null)); } readerSemaphore = readerSemaphoreOperationResult.Data; var openCommonSharedObjectsStatus = LifecycleHelper.OpenCommonSharedObjects(fullName, out file, out exclusiveAccessSemaphore, out hasMessagesEvent, out noMessagesEvent, out clientConnectedEvent); if (openCommonSharedObjectsStatus != OperationStatus.Completed) { try { readerSemaphore.Release(); } catch { } LifecycleHelper.PlatformSpecificDispose(readerSemaphore); } var result = new InboundChannel(name, readerSemaphore, exclusiveAccessSemaphore, file, hasMessagesEvent, noMessagesEvent, clientConnectedEvent, null); return(new OperationResult <InboundChannel>(OperationStatus.Completed, result)); } catch { if (readerSemaphore != null) { try { readerSemaphore.Release(); } catch { } LifecycleHelper.PlatformSpecificDispose(readerSemaphore); } LifecycleHelper.PlatformSpecificDispose(exclusiveAccessSemaphore); file?.Dispose(); LifecycleHelper.PlatformSpecificDispose(hasMessagesEvent); LifecycleHelper.PlatformSpecificDispose(noMessagesEvent); LifecycleHelper.PlatformSpecificDispose(clientConnectedEvent); throw; } }
/// <summary> /// Opens channel for reading. Channel must be created by process running without app container and it must be visible from all user sessions. /// </summary> /// <param name="name">Channel name.</param> /// <returns> /// OperationResult with InboundChannel and OperationStatus.Completed, OperationStatus.ObjectAlreadyInUse (when channel is already in use by another reader), /// OperationStatus.ObjectDoesNotExist or OperationStatus.AccessDenied /// </returns> public static OperationResult <InboundChannel> OpenInboundGlobalNoncontainerized(string name) { if (name == null) { throw new ArgumentNullException(nameof(name)); } if (name.Length == 0) { throw new ArgumentException("Channel name required to find shared memory channel"); } return(InboundChannel.Open(LifecycleHelper.GlobalVisibilityPrefix + "\\" + name, name)); }
/// <summary> /// Creates or reopens channel for reading. Channel will be visible from processes in all user sessions. /// </summary> /// <param name="name">Channel name.</param> /// <param name="capacity">Capacity of the cannel's queue in bytes.</param> /// <param name="acl"> /// The list of security indentifiers for entities allowed to access this channel. /// Use new System.Security.Principal.SecurityIdentifier(yourUwpAppContainerSidString) to grant access to UWP app. /// Empty list is equivalent of WellKnownSidType.AuthenticatedUserSid. /// </param> /// <returns> /// OperationResult with InboundChannel and OperationStatus.Completed, OperationStatus.ObjectAlreadyInUse (when channel is already in use by another reader), /// OperationStatus.ElevationRequired (when current process does not have "Create global objects" permission) or OperationStatus.CapacityIsGreaterThanLogicalAddressSpace /// </returns> public static OperationResult <InboundChannel> CreateInboundGlobal(string name, long capacity, IEnumerable <IdentityReference> acl) { if (name == null) { throw new ArgumentNullException(nameof(name)); } if (name.Length == 0) { throw new ArgumentException("Channel name required to create shared memory channel"); } if (capacity < Header.Size) { throw new ArgumentException($"Channel capacity must be at least {Header.Size} bytes"); } return(InboundChannel.Create(LifecycleHelper.GlobalVisibilityPrefix + "\\" + name, name, capacity, WhenEmptyUse(acl, WellKnownSidType.AuthenticatedUserSid))); }
/// <summary> /// Creates or reopens channel for reading. Channel will be visible from processes in the local user session. /// </summary> /// <param name="name">Channel name.</param> /// <param name="capacity">Capacity of the cannel's queue in bytes.</param> /// <returns> /// OperationResult with OutboundChannel and OperationStatus.Completed, OperationStatus.ObjectAlreadyInUse (when channel is already in use by another writer) /// or OperationStatus.CapacityIsGreaterThanLogicalAddressSpace /// </returns> public static OperationResult <InboundChannel> CreateInboundLocal(string name, long capacity) { if (name == null) { throw new ArgumentNullException(nameof(name)); } if (name.Length == 0) { throw new ArgumentException("Channel name required to create shared memory channel"); } if (capacity < Header.Size) { throw new ArgumentException($"Channel capacity must be greater than {Header.Size} bytes"); } return(InboundChannel.Create(LifecycleHelper.LocalVisibilityPrefix + "\\" + name, name, capacity, null)); }
/// <summary> /// Opens channel for reading. Channel must be created by process running in app container and it must be visible only from current user session. /// </summary> /// <param name="name">Channel name.</param> /// <param name="sid">SID of the app container of the process that created this channel.</param> /// <returns> /// OperationResult with InboundChannel and OperationStatus.Completed, OperationStatus.ObjectAlreadyInUse (when channel is already in use by another writer), /// OperationStatus.ObjectDoesNotExist or OperationStatus.AccessDenied /// </returns> public static OperationResult <InboundChannel> OpenInboundLocalContainerized(string name, string sid) { if (name == null) { throw new ArgumentNullException(nameof(name)); } if (name.Length == 0) { throw new ArgumentException("Channel name required to find shared memory channel"); } if (sid == null) { throw new ArgumentNullException(nameof(sid)); } if (sid.Length == 0) { throw new ArgumentException("Container's security identifier cannot be empty string"); } return(InboundChannel.Open($"{LifecycleHelper.LocalVisibilityPrefix}\\AppContainerNamedObjects\\{sid}\\{name}", name)); }
internal static OperationResult <InboundChannel> Create(string fullName, string name, long capacity, Acl acl) { Semaphore readerSemaphore = null; MemoryMappedFile file = null; Semaphore exclusiveAccessSemaphore = null; EventWaitHandle hasMessagesEvent = null; EventWaitHandle noMessagesEvent = null; EventWaitHandle clientConnectedEvent = null; Semaphore writerSemaphore = null; try { var readerSemaphoreOperationResult = LifecycleHelper.CreateAndSetReaderSemaphore(fullName, acl); if (readerSemaphoreOperationResult.Status != OperationStatus.Completed) { return(new OperationResult <InboundChannel>(readerSemaphoreOperationResult.Status, null)); } readerSemaphore = readerSemaphoreOperationResult.Data; var fileOperationResult = LifecycleHelper.CreateMemoryMappedFile(fullName, capacity, acl); if (fileOperationResult.Status != OperationStatus.Completed && fileOperationResult.Status != OperationStatus.ObjectAlreadyInUse) { LifecycleHelper.PlatformSpecificDispose(readerSemaphore); return(new OperationResult <InboundChannel>(fileOperationResult.Status, null)); } file = fileOperationResult.Data; exclusiveAccessSemaphore = LifecycleHelper.CreateExclusiveAccessSemaphore(fullName, acl); hasMessagesEvent = LifecycleHelper.CreateHasMessagesEvent(fullName, acl); noMessagesEvent = LifecycleHelper.CreateNoMessagesEvent(fullName, acl); clientConnectedEvent = LifecycleHelper.CreateClientConnectedEvent(fullName, acl); writerSemaphore = LifecycleHelper.CreateWriterSemaphore(fullName, acl); InboundChannel result; if (fileOperationResult.Status == OperationStatus.ObjectAlreadyInUse) { result = new InboundChannel(name, readerSemaphore, exclusiveAccessSemaphore, file, hasMessagesEvent, noMessagesEvent, clientConnectedEvent, writerSemaphore); } else { result = new InboundChannel(name, readerSemaphore, exclusiveAccessSemaphore, file, capacity, hasMessagesEvent, noMessagesEvent, clientConnectedEvent, writerSemaphore); } return(new OperationResult <InboundChannel>(OperationStatus.Completed, result)); } catch { if (readerSemaphore != null) { try { readerSemaphore.Release(); } catch { } LifecycleHelper.PlatformSpecificDispose(readerSemaphore); } file?.Dispose(); LifecycleHelper.PlatformSpecificDispose(exclusiveAccessSemaphore); LifecycleHelper.PlatformSpecificDispose(hasMessagesEvent); LifecycleHelper.PlatformSpecificDispose(noMessagesEvent); LifecycleHelper.PlatformSpecificDispose(clientConnectedEvent); LifecycleHelper.PlatformSpecificDispose(writerSemaphore); throw; } }
/// <summary> /// Disposes shared objects associated with this channel. /// Most of the resources associated with the channel and messages in the queue will stay alive until both client and server /// will be disposed. It's ok to reconnect or recreate channel with the same parameters. /// </summary> public void Dispose() { _internal?.Dispose(); _internal = null; }
internal InboundChannel(Internal.InboundChannel @internal) { _internal = @internal; }