/// <summary>
        /// Opens channel for writing. 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 OutboundChannel and OperationStatus.Completed, OperationStatus.ObjectAlreadyInUse (when channel is already in use by another writer),
        /// OperationStatus.ObjectDoesNotExist or OperationStatus.AccessDenied
        /// </returns>
        public static OperationResult <OutboundChannel> OpenOutboundGlobalNoncontainerized(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(OutboundChannel.Open(LifecycleHelper.GlobalVisibilityPrefix + "\\" + name, name));
        }
        /// <summary>
        /// Creates or reopens channel for writing. 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 OutboundChannel and OperationStatus.Completed, OperationStatus.ObjectAlreadyInUse (when channel is already in use by another writer),
        /// OperationStatus.ElevationRequired (when current process does not have "Create global objects" permission), or OperationStatus.CapacityIsGreaterThanLogicalAddressSpace
        /// </returns>
        public static OperationResult <OutboundChannel> CreateOutboundGlobal(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(OutboundChannel.Create(LifecycleHelper.GlobalVisibilityPrefix + "\\" + name, name, capacity, WhenEmptyUse(acl, WellKnownSidType.AuthenticatedUserSid)));
        }
        /// <summary>
        /// Creates or reopens channel for writing. 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 <OutboundChannel> CreateOutboundLocal(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 at least {Header.Size} bytes");
            }

            return(OutboundChannel.Create(LifecycleHelper.LocalVisibilityPrefix + "\\" + name, name, capacity, null));
        }
Example #4
0
        /// <summary>
        /// Opens channel for writing. 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 OutboundChannel and OperationStatus.Completed, OperationStatus.ObjectAlreadyInUse (when channel is already in use by another writer),
        /// OperationStatus.ObjectDoesNotExist or OperationStatus.AccessDenied
        /// </returns>
        public static OperationResult <OutboundChannel> OpenOutboundLocalContainerized(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(OutboundChannel.Open($"{LifecycleHelper.LocalVisibilityPrefix}\\AppContainerNamedObjects\\{sid}\\{name}", name));
        }
Example #5
0
        internal static OperationResult <OutboundChannel> Create(string fullName, string name, long capacity, Acl acl)
        {
            Semaphore writerSemaphore = null;

            MemoryMappedFile file = null;

            Semaphore exclusiveAccessSemaphore = null;

            EventWaitHandle hasMessagesEvent = null;

            EventWaitHandle noMessagesEvent = null;

            EventWaitHandle clientConnectedEvent = null;

            Semaphore readerSemaphore = null;

            try
            {
                var writerSemaphoreOperationResult = LifecycleHelper.CreateAndSetWriterSemaphore(fullName, acl);

                if (writerSemaphoreOperationResult.Status != OperationStatus.Completed)
                {
                    return(new OperationResult <OutboundChannel>(writerSemaphoreOperationResult.Status, null));
                }

                writerSemaphore = writerSemaphoreOperationResult.Data;

                var fileOperationResult = LifecycleHelper.CreateMemoryMappedFile(fullName, capacity, acl);

                if (fileOperationResult.Status != OperationStatus.Completed && fileOperationResult.Status != OperationStatus.ObjectAlreadyInUse)
                {
                    try { writerSemaphore.Release(); } catch { }

                    LifecycleHelper.PlatformSpecificDispose(writerSemaphore);

                    return(new OperationResult <OutboundChannel>(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);

                readerSemaphore = LifecycleHelper.CreateReaderSemaphore(fullName, acl);

                OutboundChannel result;

                if (fileOperationResult.Status == OperationStatus.ObjectAlreadyInUse)
                {
                    result = new OutboundChannel(name, writerSemaphore, file, exclusiveAccessSemaphore, hasMessagesEvent, noMessagesEvent, clientConnectedEvent, readerSemaphore);
                }
                else
                {
                    result = new OutboundChannel(name, writerSemaphore, file, capacity, exclusiveAccessSemaphore, hasMessagesEvent, noMessagesEvent, clientConnectedEvent, readerSemaphore);
                }

                return(new OperationResult <OutboundChannel>(OperationStatus.Completed, result));
            }
            catch
            {
                if (writerSemaphore != null)
                {
                    try { writerSemaphore.Release(); } catch { }

                    LifecycleHelper.PlatformSpecificDispose(writerSemaphore);
                }

                file?.Dispose();

                LifecycleHelper.PlatformSpecificDispose(exclusiveAccessSemaphore);

                LifecycleHelper.PlatformSpecificDispose(hasMessagesEvent);

                LifecycleHelper.PlatformSpecificDispose(noMessagesEvent);

                LifecycleHelper.PlatformSpecificDispose(clientConnectedEvent);

                LifecycleHelper.PlatformSpecificDispose(readerSemaphore);

                throw;
            }
        }
Example #6
0
        internal static OperationResult <OutboundChannel> Open(string fullName, string name)
        {
            Semaphore writerSemaphore = null;

            MemoryMappedFile file = null;

            Semaphore exclusiveAccessSemaphore = null;

            EventWaitHandle hasMessagesEvent = null;

            EventWaitHandle noMessagesEvent = null;

            EventWaitHandle clientConnectedEvent = null;

            try
            {
                var writerSemaphoreOperationResult = LifecycleHelper.OpenAndSetWriterSemaphore(fullName);

                if (writerSemaphoreOperationResult.Status != OperationStatus.Completed)
                {
                    return(new OperationResult <OutboundChannel>(writerSemaphoreOperationResult.Status, null));
                }

                writerSemaphore = writerSemaphoreOperationResult.Data;

                var openCommonSharedObjectsStatus = LifecycleHelper.OpenCommonSharedObjects(fullName, out file, out exclusiveAccessSemaphore, out hasMessagesEvent, out noMessagesEvent, out clientConnectedEvent);

                if (openCommonSharedObjectsStatus != OperationStatus.Completed)
                {
                    try { writerSemaphore.Release(); } catch { }

                    LifecycleHelper.PlatformSpecificDispose(writerSemaphore);

                    return(new OperationResult <OutboundChannel>(openCommonSharedObjectsStatus, null));
                }

                var result = new OutboundChannel(name, writerSemaphore, file, exclusiveAccessSemaphore, hasMessagesEvent, noMessagesEvent, clientConnectedEvent, null);

                return(new OperationResult <OutboundChannel>(OperationStatus.Completed, result));
            }
            catch
            {
                if (writerSemaphore != null)
                {
                    try { writerSemaphore.Release(); } catch { }

                    LifecycleHelper.PlatformSpecificDispose(writerSemaphore);
                }

                file?.Dispose();

                LifecycleHelper.PlatformSpecificDispose(exclusiveAccessSemaphore);

                LifecycleHelper.PlatformSpecificDispose(hasMessagesEvent);

                LifecycleHelper.PlatformSpecificDispose(noMessagesEvent);

                LifecycleHelper.PlatformSpecificDispose(clientConnectedEvent);

                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 OutboundChannel(Internal.OutboundChannel @internal)
 {
     _internal = @internal;
 }