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; }
/// <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(); } }
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(); }
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; } } } } } }); }
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; } } } } } }); }
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);
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")); }); }
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()))); } }); } }
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()))); } }); }