Esempio n. 1
0
        /// <summary>
        /// Asynchronously sends a message to the remote muxer.
        /// </summary>
        /// <param name="message">
        /// The message to send.
        /// </param>
        /// <param name="cancellationToken">
        /// A <see cref="CancellationToken"/> which can be used to cancel the asynchronous operation.
        /// </param>
        /// <returns>
        /// A <see cref="Task"/> which represents the asynchronous operation.
        /// </returns>
        public virtual async Task WriteMessageAsync(MuxerMessage message, CancellationToken cancellationToken)
        {
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            // Serialize the underlying message so we can calculate the packet size
            var dictionary    = message.ToPropertyList();
            var xml           = dictionary.ToXmlPropertyList();
            int messageLength = Encoding.UTF8.GetByteCount(xml);

            var packetLength = MuxerHeader.BinarySize + messageLength;

            using (var packet = this.memoryPool.Rent(packetLength))
            {
                // Construct the entire packet:
                // [muxer header] (16 bytes)
                // [UTF-8 XML-encoded property list message] (N bytes)
                var header = new MuxerHeader()
                {
                    Length  = (uint)(MuxerHeader.BinarySize + messageLength),
                    Version = ProtocolVersion,
                    Message = MuxerMessageType.Plist,
                    Tag     = this.tag++,
                };

                header.Write(packet.Memory.Slice(0, MuxerHeader.BinarySize).Span);

                Encoding.UTF8.GetBytes(xml, packet.Memory.Slice(MuxerHeader.BinarySize, messageLength).Span);

                // Send the packet
                await this.stream.WriteAsync(packet.Memory.Slice(0, packetLength), cancellationToken).ConfigureAwait(false);

                await this.stream.FlushAsync(cancellationToken).ConfigureAwait(false);
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Asynchronously receives a message from the remote muxer.
        /// </summary>
        /// <param name="cancellationToken">
        /// A <see cref="CancellationToken"/> which can be used to cancel the asynchronous operation.
        /// </param>
        /// <returns>
        /// A <see cref="DeviceListMessage"/> object which represents the property list value received
        /// from the remote muxer.
        /// </returns>
        public virtual async Task <MuxerMessage> ReadMessageAsync(CancellationToken cancellationToken)
        {
            int         read;
            MuxerHeader header;

            using (var headerBuffer = this.memoryPool.Rent(MuxerHeader.BinarySize))
            {
                if ((read = await this.stream.ReadBlockAsync(headerBuffer.Memory.Slice(0, MuxerHeader.BinarySize), cancellationToken).ConfigureAwait(false)) != MuxerHeader.BinarySize)
                {
                    this.logger.LogInformation("Could only read {read}/{total} bytes of the muxer header; exiting.", read, MuxerHeader.BinarySize);
                    return(null);
                }

                header = MuxerHeader.Read(headerBuffer.Memory.Slice(0, MuxerHeader.BinarySize).Span);
            }

            if (header.Message != MuxerMessageType.Plist)
            {
                throw new NotSupportedException($"Only Plist message types are supported; but a {header.Message} message was received");
            }

            int messageLength = (int)header.Length - MuxerHeader.BinarySize;

            using (var messageBuffer = this.memoryPool.Rent(messageLength))
            {
                if ((read = await this.stream.ReadBlockAsync(messageBuffer.Memory.Slice(0, messageLength), cancellationToken).ConfigureAwait(false)) != messageLength)
                {
                    this.logger.LogInformation("Could only read {read}/{total} bytes of the muxer header; exiting.", read, messageLength);
                    return(null);
                }

                var propertyListData = messageBuffer.Memory.Slice(0, messageLength).ToArray();
                var propertyList     = (NSDictionary)XmlPropertyListParser.Parse(propertyListData);

                return(MuxerMessage.ReadAny(propertyList));
            }
        }