示例#1
0
        public IObservable <Message> SendMessage(Message message, ICoapEndpoint endpoint)
        {
            if (message is null)
            {
                return(Observable.Empty <Message>());
            }

            var coapMessage    = message.ToCoapMessage();
            var messageContext = coapMessage.CreateBlockWiseContext(_coapClient);

            return(Observable.Create <Message>(observer =>
            {
                var cts = new CancellationTokenSource();
                Task.Run(async() =>
                {
                    try
                    {
                        if (coapMessage.IsBlockWise())
                        {
                            using (var writer = new CoapBlockStreamWriter(messageContext, endpoint))
                                await message.PayloadStream.CopyToAsync(writer, writer.BlockSize);
                        }
                        else
                        {
                            var id = await _coapClient.SendAsync(coapMessage, endpoint, cts.Token);
                            messageContext = new CoapBlockWiseContext(_coapClient, coapMessage, await _coapClient.GetResponseAsync(id, cts.Token));
                        }

                        var response = messageContext.Response.ToMessage();

                        if (messageContext.Response.IsBlockWise())
                        {
                            var memoryStream = new MemoryStream();

                            using (var reader = new CoapBlockStreamReader(messageContext, endpoint))
                                reader.CopyTo(memoryStream);

                            response.Payload = memoryStream.ToArray();
                        }

                        observer.OnNext(response);

                        observer.OnCompleted();
                    }
                    catch (Exception ex)
                    {
                        observer.OnError(ex);
                    }
                });

                return cts.Cancel;
            }));
        }
        /// <summary>
        /// Attempts to read the entire body of the block-wise message. Using the <paramref name="originalRequest"/> to request blocks.
        /// </summary>
        /// <param name="message">A message containing a <see cref="Block2"/> option.</param>
        /// <param name="client"></param>
        /// <param name="originalRequest">The orignal request which the block-wise response was for.</param>
        /// <returns>The completed body for the block-wise messages.</returns>
        public static byte[] GetCompletedBlockWisePayload(this CoapMessage message, CoapClient client, CoapMessage originalRequest)
        {
            var block2 = message.Options.Get <Options.Block2>()
                         ?? throw new ArgumentException($"{nameof(CoapMessage)} does not contain a {nameof(Options.Block2)} option", nameof(message));

            if (originalRequest == null)
            {
                throw new ArgumentNullException("Please provide original requesting message", nameof(originalRequest));
            }

            if (block2.BlockNumber != 0)
            {
                throw new CoapBlockException($"Can not get completed payload starting with block {block2.BlockNumber}. Please start from 0");
            }

            var memoryStream = new MemoryStream();

            using (var reader = new CoapBlockStreamReader(client, message, originalRequest))
                reader.CopyTo(memoryStream);

            return(memoryStream.ToArray());
        }
        public async Task Write_BlockWiseCoapMessage_ReadResponse()
        {
            int blockSize = 128;

            // Arrange
            var totalBytes  = 1234;
            var totalBlocks = ((totalBytes - 1) / blockSize) + 1;

            var baseRequestMessage = new CoapMessage
            {
                Code = CoapMessageCode.Post,
                Type = CoapMessageType.Confirmable,
            };

            var baseResponseMessage = new CoapMessage
            {
                Code = CoapMessageCode.Continue,
                Type = CoapMessageType.Acknowledgement,
            };

            var mockClientEndpoint = new Mock <MockBlockwiseEndpoint>(baseResponseMessage, blockSize, totalBytes)
            {
                CallBase = true
            };

            mockClientEndpoint.Object.FinalResponse = new CoapMessage
            {
                Code = CoapMessageCode.Changed,
                Type = CoapMessageType.Acknowledgement,
            };

            var result = new byte[totalBytes];
            int bytesRead;

            // Act
            using (var client = new CoapClient(mockClientEndpoint.Object))
            {
                var ct = new CancellationTokenSource(MaxTaskTimeout);

                var context = baseRequestMessage.CreateBlockWiseContext(client);

                using (var writer = new CoapBlockStreamWriter(context)
                {
                    BlockSize = blockSize
                })
                {
                    writer.Write(BlockWiseTestHelper.ByteRange(0, totalBytes), 0, totalBytes);
                    writer.Flush();
                };

                using (var reader = new CoapBlockStreamReader(context))
                {
                    bytesRead = reader.Read(result, 0, totalBytes);
                };
            }

            // Assert
            Assert.That(bytesRead, Is.EqualTo(totalBytes), "Incorrect number of bytes read");
            Assert.That(result, Is.EqualTo(BlockWiseTestHelper.ByteRange(0, totalBytes)), "Incorrect payload read");

            mockClientEndpoint.Verify();
        }
        public async Task Read_BlockWiseCoapMessage(
            [Values(16, 32, 64, 128, 256, 512, 1024)] int blockSize,
            [Range(1, 2)] int blocks,
            [Values] bool lastHalfblock)
        {
            // Arrange
            int totalBytes  = (blocks * blockSize) + (lastHalfblock ? blockSize / 2 : 0);
            int totalBlocks = ((totalBytes - 1) / blockSize) + 1;

            var baseRequestMessage = new CoapMessage
            {
                Code = CoapMessageCode.Get,
                Type = CoapMessageType.Confirmable,
            };

            baseRequestMessage.SetUri("/status", UriComponents.Path);

            var baseResponse = new CoapMessage
            {
                Code = CoapMessageCode.Content,
                Type = CoapMessageType.Acknowledgement,
            };

            var helper = new BlockWiseTestHelper
            {
                BlockSize  = blockSize,
                TotalBytes = totalBytes
            };

            var mockClientEndpoint = new Mock <MockBlockwiseEndpoint>(baseResponse, blockSize, totalBytes)
            {
                CallBase = true
            };

            helper.AssertReadResponseCorrespondance(mockClientEndpoint, 1)
            .AssertInitialRequest(mockClientEndpoint);

            var result = new byte[totalBytes];
            int bytesRead;

            // Act
            using (var client = new CoapClient(mockClientEndpoint.Object))
            {
                var ct = new CancellationTokenSource(MaxTaskTimeout);

                client.SetNextMessageId(1);

                var identifier = await client.SendAsync(baseRequestMessage, ct.Token);

                var response = await client.GetResponseAsync(identifier, ct.Token);

                using (var reader = new CoapBlockStreamReader(client, response, baseRequestMessage))
                {
                    bytesRead = reader.Read(result, 0, totalBytes);
                };
            }

            // Assert
            Assert.That(bytesRead, Is.EqualTo(totalBytes), "Incorrect number of bytes read");
            Assert.That(result, Is.EqualTo(BlockWiseTestHelper.ByteRange(0, totalBytes)), "Incorrect payload read");

            mockClientEndpoint.Verify();
        }