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));
        }
Esempio n. 5
0
        /// <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;
            }
        }
Esempio n. 7
0
        /// <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;
        }
Esempio n. 8
0
 internal InboundChannel(Internal.InboundChannel @internal)
 {
     _internal = @internal;
 }