Ejemplo n.º 1
0
        /// <summary>
        /// Create a new CoAP messages with <see cref="CoapMessageCode"/> set based on the type of <see cref="Exception"/> provided.
        /// </summary>
        /// <remarks>
        /// <see cref="CoapMessage"/>.<see cref="Code"/> will be set to <see cref="CoapMessageCode.InternalServerError"/> by default unless:
        /// <list type="bullet">
        ///   <item>
        ///     <description>When <paramref name="exception"/> is of type <see cref="CoapException"/>. Then <see cref="CoapMessage"/>.<see cref="Code"/> will be set to <see cref="CoapException"/>.<see cref="CoapException.ResponseCode"/></description>
        ///   </item>
        ///   <item>
        ///     <description>When <paramref name="exception"/> is of type <see cref="NotImplementedException"/>. Then <see cref="CoapMessage"/>.<see cref="Code"/> will be set to <see cref="CoapMessageCode.NotImplemented"/></description>
        ///   </item>
        /// </list>
        /// </remarks>
        /// <param name="exception"></param>
        /// <returns></returns>
        public static CoapMessage FromException(Exception exception)
        {
            var result = new CoapMessage
            {
                Type    = CoapMessageType.Reset,
                Code    = CoapMessageCode.InternalServerError,
                Options = { new ContentFormat(ContentFormatType.TextPlain) },
                Payload = Encoding.UTF8.GetBytes(exception.Message)
            };

            switch (exception)
            {
            case CoapException coapEx:
                result.Code = coapEx.ResponseCode;
                break;

            case NotImplementedException _:
                result.Code = CoapMessageCode.NotImplemented;
                break;
            }
            return(result);
        }
        /// <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());
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Creates an <see cref="CoapException"/> with details populated from <paramref name="message"/> with an optional inner-exception.
        /// </summary>
        /// <param name="message"></param>
        /// <param name="innerExcpetion"></param>
        /// <returns></returns>
        public static CoapException FromCoapMessage(CoapMessage message, Exception innerExcpetion = null)
        {
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            var errorMessage  = $"({message.Code.Class}.{message.Code.Detail:D2})";
            var contentFormat = message.Options.Get <Options.ContentFormat>();

            if (contentFormat != null && message.Payload != null)
            {
                if (contentFormat.MediaType == Options.ContentFormatType.TextPlain)
                {
                    errorMessage += System.Text.Encoding.UTF8.GetString(message.Payload);
                }
                else
                {
                    errorMessage += string.Join(", ", message.Payload.Select(b => $"0x{b:X2}"));
                }
            }

            return(new CoapException(errorMessage, innerExcpetion, message.Code));
        }
Ejemplo n.º 4
0
 /// <summary>
 /// <see cref="SendAsync(CoapMessage, ICoapEndpoint, CancellationToken)"/>
 /// </summary>
 /// <param name="message"></param>
 /// <param name="endpoint"></param>
 /// <returns></returns>
 public virtual async Task <int> SendAsync(CoapMessage message, ICoapEndpoint endpoint)
 => await SendAsync(message, endpoint, CancellationToken.None);
Ejemplo n.º 5
0
 /// <summary>
 /// <see cref="SendAsync(CoapMessage, ICoapEndpoint, CancellationToken)"/>
 /// </summary>
 /// <param name="message"></param>
 /// <param name="token"></param>
 /// <returns></returns>
 public virtual async Task <int> SendAsync(CoapMessage message, CancellationToken token)
 => await SendAsync(message, null, token);
Ejemplo n.º 6
0
        private async Task ReceiveAsyncInternal()
        {
            try
            {
                while (true)
                {
                    if (Endpoint == null)
                    {
                        return;
                    }

                    var payload = await Endpoint.ReceiveAsync();

                    var message = new CoapMessage(Endpoint.IsMulticast);
                    try
                    {
                        message.Deserialise(payload.Payload);
                    }
                    catch (CoapMessageFormatException)
                    {
                        if (message.Type == CoapMessageType.Confirmable &&
                            !Endpoint.IsMulticast)
                        {
                            await SendAsync(new CoapMessage
                            {
                                Id   = message.Id,
                                Type = CoapMessageType.Reset
                            }, payload.Endpoint);
                        }
                        throw;
                    }

                    if (_messageResponses.ContainsKey(message.Id))
                    {
                        _messageResponses[message.Id].TrySetResult(message);
                    }

                    lock (_receiveQueue)
                    {
                        _receiveQueue.Enqueue(Task.FromResult(new CoapReceiveResult(payload.Endpoint, message)));
                    }
                    _receiveEvent.Set();
                }
            }
            catch (Exception ex)
            {
                if (ex is CoapEndpointException)
                {
                    Endpoint?.Dispose();
                    Endpoint = null;

                    foreach (var response in _messageResponses.Values)
                    {
                        response.TrySetCanceled();
                    }
                }

                lock (_receiveQueue)
                {
                    // Gona cheat and enque that exception so it gets thrown as if this detached-infinite-loop never existed...
                    _receiveQueue.Enqueue(Task.FromException <CoapReceiveResult>(ex));
                }
                _receiveEvent.Set();
            }
        }
Ejemplo n.º 7
0
        public static CoapBlockWiseContext CreateBlockWiseContext(this CoapMessage message, CoapClient client, CoapMessage response = null)
        {
            if (!message.Code.IsRequest())
            {
                throw new ArgumentException($"A block-Wise context requires a base request message. Message code {message.Code} is invalid.", nameof(message));
            }

            if (response != null && response.Code.IsRequest())
            {
                throw new ArgumentException($"A block-Wise context response can not be set from a message code {message.Code}.", nameof(response));
            }

            return(new CoapBlockWiseContext(client, message, response));
        }
Ejemplo n.º 8
0
 public static CoapMessageIdentifier GetIdentifier(this CoapMessage message, ICoapEndpoint endpoint = null, bool isRequest = false)
 => new CoapMessageIdentifier(message, endpoint, isRequest);
Ejemplo n.º 9
0
 public virtual Task <CoapMessage> DeleteAsync(CoapMessage request, ICoapConnectionInformation connectionInformation)
 => DeleteAsync(request);
Ejemplo n.º 10
0
 public virtual Task <CoapMessage> PostAsync(CoapMessage request)
 => Task.FromResult(Post(request));
Ejemplo n.º 11
0
 /// <summary>
 /// <see cref="SendAsync(CoapMessage, ICoapEndpoint, CancellationToken)"/>
 /// </summary>
 /// <param name="message"></param>
 /// <returns></returns>
 public virtual async Task <CoapMessageIdentifier> SendAsync(CoapMessage message)
 => await SendAsync(message, null, CancellationToken.None);
Ejemplo n.º 12
0
 /// <summary>
 /// Checks if a <see cref="CoapReceiveResult"/> has been received for the coresponding <paramref name="request"/> and returns it.
 /// Otherwise waits until a new result is received unless cancelled by the <paramref name="token"/> or the <see cref="MaxRetransmitAttempts"/> is reached.
 /// </summary>
 /// <param name="request">Waits for a result with a coresponding request message.</param>
 /// <param name="token">Token to cancel the blocking Receive operation</param>
 /// <returns>Valid result if a result is received, <c>null</c> if canceled.</returns>
 /// <exception cref="CoapClientException">If the timeout period * maximum retransmission attempts was reached.</exception>
 public Task <CoapMessage> GetResponseAsync(CoapMessage request, ICoapEndpoint endpoint = null, bool isRequest = false, CancellationToken token = default(CancellationToken), bool dequeue = true)
 => GetResponseAsync(request.GetIdentifier(endpoint, isRequest), token, dequeue);
Ejemplo n.º 13
0
        private async Task ReceiveAsyncInternal()
        {
            var isMulticast = Endpoint?.IsMulticast ?? false;

            try
            {
                while (true)
                {
                    Task <CoapPacket> payloadTask;
                    lock (this)
                    {
                        if (Endpoint == null)
                        {
                            return;
                        }

                        payloadTask = Endpoint.ReceiveAsync(_receiveTaskCTS.Token);
                    }

                    var payload    = await payloadTask;
                    var receivedAt = DateTime.Now;

                    var message = new CoapMessage {
                        IsMulticast = isMulticast
                    };
                    try
                    {
                        message.FromBytes(payload.Payload);

                        // Ignore non-empty reset messages
                        if (message.Type == CoapMessageType.Reset && message.Code != CoapMessageCode.None)
                        {
                            continue;
                        }

                        // Reject confirmable empty messages
                        if (message.Type == CoapMessageType.Confirmable && message.Code == CoapMessageCode.None)
                        {
                            await SendAsync(new CoapMessage { Id = message.Id, Type = CoapMessageType.Reset }, payload.Endpoint);

                            continue;
                        }

                        // Ignore repeated messages
                        if (IsRepeated(payload.Endpoint, message.Id))
                        {
                            continue;
                        }
                    }
                    catch (CoapMessageFormatException)
                    {
                        if (message.Type == CoapMessageType.Confirmable &&
                            !isMulticast)
                        {
                            await SendAsync(new CoapMessage
                            {
                                Id   = message.Id,
                                Type = CoapMessageType.Reset
                            }, payload.Endpoint);
                        }
                        if (message.Type == CoapMessageType.Acknowledgement &&
                            Coap.ReservedMessageCodeClasses.Contains(message.Code.Class))
                        {
                            continue;
                        }

                        throw;
                    }

                    lock (_recentMessages)
                    {
                        var messageId = message.GetIdentifier(payload.Endpoint);

                        if (_messageResponses.ContainsKey(messageId))
                        {
                            _messageResponses[messageId].TrySetResult(message);
                        }

                        _recentMessages.Enqueue(Tuple.Create(receivedAt, payload.Endpoint, message));
                    }

                    _receiveQueue.Enqueue(Task.FromResult(new CoapReceiveResult(payload.Endpoint, message)));
                    _receiveEvent.Set();
                }
            }
            catch (Exception ex)
            {
                if (ex is CoapEndpointException)
                {
                    var endpoint = Endpoint;

                    lock (this)
                        Endpoint = null;

                    endpoint?.Dispose();

                    foreach (var response in _messageResponses.Values)
                    {
                        response.TrySetCanceled();
                    }
                }

                // Gona cheat and enque that exception so it gets thrown as if this detached-infinite-loop never existed...
                _receiveQueue.Enqueue(Task.FromException <CoapReceiveResult>(ex));

                _receiveEvent.Set();
            }
        }
Ejemplo n.º 14
0
 public virtual Task <int> PostAsync(string uri, CoapMessage message, ICoapEndpoint endpoint = null)
 {
     throw new NotImplementedException();
 }
Ejemplo n.º 15
0
 public virtual Task <CoapMessage> DeleteAsync(CoapMessage request)
 => Task.FromResult(Delete(request));
Ejemplo n.º 16
0
        public CoapReceiveResult(ICoapEndpoint endpoint, CoapMessage message)
        {
            Endpoint = endpoint;

            Message = message;
        }
 /// <summary>
 /// Checks if a <see cref="CoapMessage"/> is part ofa block-wise transfer by checking for the presence of either <see cref="CoAPNet.Options.Block1"/> or <see cref="CoAPNet.Options.Block2"/>.
 /// </summary>
 /// <param name="message"></param>
 /// <returns><c>true</c> when <paramref name="message"/> is part of a Block-Wise transfer</returns>
 public static bool IsBlockWise(this CoapMessage message)
 {
     return(message.Options.Any(o => o.OptionNumber == CoapRegisteredOptionNumber.Block1 || o.OptionNumber == CoapRegisteredOptionNumber.Block2));
 }