private Consumer(S101Client client, int timeout, ChildrenRetrievalPolicy childrenRetrievalPolicy, byte slot)
        {
            this.root = Root <TRoot> .Construct(new Context(null, 0, string.Empty, childrenRetrievalPolicy));

            this.client = client;
            this.childrenRetrievalTimeout  = timeout;
            this.emberDataMessage          = new S101Message(slot, EmberDataCommand);
            this.client.EmberDataReceived += this.receiveQueue.OnMessageReceived;
            this.client.ConnectionLost    += this.receiveQueue.OnConnectionLost;
        }
Example #2
0
        /// <summary>Asynchronously simulates S101 communication.</summary>
        /// <param name="client">The <see cref="S101Client"/> to use.</param>
        /// <param name="types">The types to pass to the internal <see cref="EmberConverter"/>, which is used to convert
        /// between XML payload and EmBER payload.</param>
        /// <param name="logReader">The <see cref="XmlReader"/> to read the messages from. The messages that are
        /// expected to be received from the remote party as well as the ones that will be sent are read with this
        /// reader. The format needs to match the one written by <see cref="S101Logger"/>.</param>
        /// <param name="sendFirstMessage"><c>true</c> to send the first <see cref="EmberData"/> message read with
        /// <paramref name="logReader"/>; <c>false</c> to wait for the first message from the remote party and match it
        /// to the first <see cref="EmberData"/> message read with <paramref name="logReader"/>.</param>
        /// <returns>A <see cref="Task"/> object representing the communication. This task completes when one of the
        /// following events occurs:
        /// <list type="bullet">
        /// <item>The last message in the log has been sent/received.</item>
        /// <item>The <see cref="S101Client.ConnectionLost"/> event occurred on the client passed to
        /// <see cref="RunAsync"/>.</item>
        /// </list></returns>
        /// <exception cref="ArgumentNullException"><paramref name="client"/>, <paramref name="types"/> and/or
        /// <paramref name="logReader"/> equal <c>null</c>.</exception>
        /// <exception cref="S101Exception"><list type="bullet">
        /// <item>There was a mismatch between an incoming message and one read from the log.</item>
        /// <item>The <see cref="S101Client.ConnectionLost"/> event occurred on the client passed to
        /// <see cref="RunAsync"/>.</item>
        /// </list></exception>
        /// <exception cref="XmlException">The XML read with <paramref name="logReader"/> is invalid, see
        /// <see cref="Exception.Message"/> for details.</exception>
        /// <remarks>
        /// <para>Reads messages with <paramref name="logReader"/> and depending on the direction either sends them to
        /// the remote party or matches them to messages received from the remote party. If a message received from the
        /// remote party does not match the one in the log then an appropriate exception is thrown.</para>
        /// <para>Subsequent messages read with <paramref name="logReader"/> that match the direction of the first
        /// message read with <paramref name="logReader"/> are sent if <paramref name="sendFirstMessage"/> equals
        /// <c>true</c>; otherwise such messages are matched to the ones received from the remote party. The opposite
        /// happens with log messages of opposite direction.</para>
        /// </remarks>
        public static async Task RunAsync(
            S101Client client, EmberTypeBag types, XmlReader logReader, bool sendFirstMessage)
        {
            var robot = new S101Robot(client, types, logReader, sendFirstMessage);

            try
            {
                await robot.WaitAsync();
            }
            finally
            {
                robot.Dispose();
            }
        }
Example #3
0
        private S101Robot(S101Client client, EmberTypeBag types, XmlReader logReader, bool sendFirstMessage)
        {
            if (client == null)
            {
                throw new ArgumentNullException(nameof(client));
            }

            this.client = client;
            this.logReader = new S101LogReader(types, logReader);
            this.sendFirstMessage = sendFirstMessage;

            this.client.OutOfFrameByteReceived += this.OnOutOfFrameByteReceived;
            this.client.EmberDataReceived += this.OnClientEmberDataReceived;
            this.client.ConnectionLost += this.OnClientConnectionLost;
            this.SendMessages();
        }
Example #4
0
        public static async Task <Consumer <TRoot> > CreateAsync(
            S101Client client, int timeout, ChildrenRetrievalPolicy childrenRetrievalPolicy, byte slot)
        {
            if ((childrenRetrievalPolicy < ChildrenRetrievalPolicy.None) ||
                (childrenRetrievalPolicy > ChildrenRetrievalPolicy.All))
            {
                throw new ArgumentOutOfRangeException(nameof(childrenRetrievalPolicy));
            }

            var result = new Consumer <TRoot>(
                client ?? throw new ArgumentNullException(nameof(client)), timeout, childrenRetrievalPolicy, slot);
            await result.RetrieveChildrenAsync();

            result.SendReceiveLoop();
            return(result);
        }
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        #region Main Method
        private static void Main()
        {
            // This is necessary so that we can execute async code in a console application.
            AsyncPump.Run(
                async() =>
            {
                // Establish S101 protocol
                using (S101Client client = await ConnectAsync("localhost", 9000))

                    // Retrieve *all* elements in the provider database and store them in a local copy
                    using (Consumer <MyRoot> consumer = await Consumer <MyRoot> .CreateAsync(client))
                    {
                        // Get the root of the local database.
                        INode root = consumer.Root;

                        // For now just output the number of direct children under the root node.
                        Console.WriteLine(root.Children.Count);
                    }
            });
        }
        public void MainTest()
        {
            AsyncPump.Run(
                async () =>
                {
                    var proTask = WaitForConnectionAsync(9000);

                    using (var conTcp = new TcpClient())
                    {
                        await conTcp.ConnectAsync("localhost", 8999);

                        using (var proTcp = await proTask)
                        {
                            var proStream = proTcp.GetStream();

                            using (var proS101 = new S101Client(proTcp, proStream.ReadAsync, proStream.WriteAsync))
                            {
                                var conStream = conTcp.GetStream();

                                using (var conS101 = new S101Client(conTcp, conStream.ReadAsync, conStream.WriteAsync))
                                using (var resourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(
                                    typeof(ModelPayloads), "SapphireLog.xml"))
                                using (var reader = XmlReader.Create(resourceStream))
                                {
                                    var robotTask = S101Robot.RunAsync(proS101, GlowTypes.Instance, reader, true);

                                    using (await Consumer<EmptyDynamicRoot>.CreateAsync(conS101))
                                    {
                                        await conS101.SendOutOfFrameByteAsync(0x00);
                                        await robotTask;
                                    }
                                }
                            }
                        }
                    }
                });
        }
Example #7
0
        public void MainTest()
        {
            AsyncPump.Run(
                async() =>
            {
                var proTask = WaitForConnectionAsync(9000);

                using (var conTcp = new TcpClient())
                {
                    await conTcp.ConnectAsync("localhost", 8999);

                    using (var proTcp = await proTask)
                    {
                        var proStream = proTcp.GetStream();

                        using (var proS101 = new S101Client(proTcp, proStream.ReadAsync, proStream.WriteAsync))
                        {
                            var conStream = conTcp.GetStream();

                            using (var conS101 = new S101Client(conTcp, conStream.ReadAsync, conStream.WriteAsync))
                                using (var resourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(
                                           typeof(ModelPayloads), "SapphireLog.xml"))
                                    using (var reader = XmlReader.Create(resourceStream))
                                    {
                                        var robotTask = S101Robot.RunAsync(proS101, GlowTypes.Instance, reader, true);

                                        using (await Consumer <EmptyDynamicRoot> .CreateAsync(conS101))
                                        {
                                            await conS101.SendOutOfFrameByteAsync(0x00);
                                            await robotTask;
                                        }
                                    }
                        }
                    }
                }
            });
        }
Example #8
0
        public void KeepAliveExceptionTest()
        {
            AsyncPump.Run(
                async () =>
                {
                    var providerTask = WaitForConnectionAsync();
                    int timeout = this.Random.Next(4000, 8000);
                    Console.WriteLine("Timeout: {0}", timeout);

                    using (var consumer = new TcpClient("localhost", 8099))
                    using (var stream = consumer.GetStream())
                    using (var logger = new S101Logger(GlowTypes.Instance, Console.Out))
                    using (var consumerClient =
                        new S101Client(consumer, stream.ReadAsync, stream.WriteAsync, logger, timeout, 8192))
                    {
                        (await providerTask).Ignore();
                        consumerClient.KeepAliveRequestSlot = (byte)this.Random.Next(byte.MaxValue + 1);
                        var source = new TaskCompletionSource<bool>();
                        consumerClient.ConnectionLost += (s, e) => OnConnectionLost(source, e);
                        var task = await Task.WhenAny(source.Task, Task.Delay(timeout + (timeout / 4)));
                        await AssertThrowAsync<S101Exception>(() => task);
                    }
                });
        }
 public static Task <Consumer <TRoot> > CreateAsync(S101Client client, int timeout, byte slot) =>
 CreateAsync(client, timeout, ChildrenRetrievalPolicy.All, slot);
 public static Task <Consumer <TRoot> > CreateAsync(
     S101Client client, int timeout, ChildrenRetrievalPolicy childrenRetrievalPolicy)
 {
     return(CreateAsync(client, timeout, childrenRetrievalPolicy, 0x00));
 }
 public static Task <Consumer <TRoot> > CreateAsync(S101Client client, int timeout) =>
 CreateAsync(client, timeout, (byte)0x00);
 public static Task <Consumer <TRoot> > CreateAsync(S101Client client) => CreateAsync(client, 10000);
Example #13
0
        public void ExceptionTest()
        {
            AsyncPump.Run(
                async () =>
                {
                    using (var client = new S101Client(Stream.Null, Stream.Null.ReadAsync, Stream.Null.WriteAsync))
                    {
                        await AssertThrowAsync<ArgumentNullException>(
                            () => S101Robot.RunAsync(null, Types, XmlReader.Create(Stream.Null), false),
                            () => S101Robot.RunAsync(client, null, XmlReader.Create(Stream.Null), false),
                            () => S101Robot.RunAsync(client, Types, null, false));
                    }

                    await AssertThrowAsync<XmlException>(() => TestWithRobot<S101Payloads>(
                        client => Task.FromResult(false), null, null, Types, true, "MissingPayloadLog.xml"));
                });
        }
Example #14
0
        public void ExceptionTest()
        {
            using (var dummy = new MemoryStream())
            {
                ReadAsyncCallback fakeRead = (b, o, c, t) => Task.FromResult(0);
                WriteAsyncCallback fakeWrite = (b, o, c, t) => Task.FromResult(false);
                AssertThrow<NotSupportedException>(() => new S101Client(dummy, fakeRead, fakeWrite).Dispose());

                AsyncPump.Run(
                    async () =>
                    {
                        using (var connection = new CompleteOnDispose())
                        using (var client = new S101Client(connection, (b, o, c, t) => connection.Task, fakeWrite))
                        {
                            await AssertThrowAsync<InvalidOperationException>(
                                () => Task.Run(() => client.SendMessageAsync(new S101Message(0x00, new KeepAliveRequest()))));
                        }

                        AssertThrow<ArgumentNullException>(
                            () => new S101Client(null, fakeRead, fakeWrite).Dispose(),
                            () => new S101Client(dummy, null, fakeWrite).Dispose(),
                            () => new S101Client(dummy, fakeRead, null).Dispose());

                        AssertThrow<ArgumentOutOfRangeException>(
                            () => new S101Client(dummy, fakeRead, fakeWrite, null, 3000, 0).Dispose(),
                            () => new S101Client(dummy, fakeRead, fakeWrite, null, -2, 1).Dispose());

                        using (var connection = new CompleteOnDispose())
                        using (var client = new S101Client(
                            connection, (b, o, c, t) => connection.Task, fakeWrite, null, 3000, 1))
                        {
                            await AssertThrowAsync<ArgumentNullException>(
                                () => client.SendMessageAsync(null));
                            await AssertThrowAsync<ArgumentException>(() => client.SendMessageAsync(EmberDataMessage));
                            await AssertThrowAsync<ArgumentException>(() => client.SendOutOfFrameByteAsync(0xFE));

                            client.Dispose();
                            await AssertThrowAsync<ObjectDisposedException>(
                                () => client.SendMessageAsync(new S101Message(0x00, new KeepAliveRequest())));
                        }
                    });
            }
        }
Example #15
0
        public void ConnectionLostTest()
        {
            AsyncPump.Run(
                async () =>
                {
                    var readResult = new TaskCompletionSource<int>();
                    using (var client = new S101Client(
                        new MemoryStream(),
                        (b, o, c, t) => readResult.Task,
                        (b, o, c, t) => Task.FromResult(false),
                        new S101Logger(GlowTypes.Instance, Console.Out)))
                    {
                        var exception = new IOException();
                        var connectionLost = new TaskCompletionSource<bool>();

                        client.ConnectionLost +=
                            (s, e) =>
                            {
                                Assert.AreEqual(exception, e.Exception);
                                connectionLost.SetResult(true);
                            };

                        readResult.SetException(exception);
                        await connectionLost.Task;
                        await AssertThrowAsync<ObjectDisposedException>(
                            () => client.SendMessageAsync(new S101Message(0x00, new KeepAliveRequest())));
                    }
                });
        }