예제 #1
0
        private async Task SendAsyncInternal(CoapMessage message, ICoapEndpoint remoteEndpoint, CancellationToken token)
        {
            if (remoteEndpoint == null)
            {
                remoteEndpoint = new CoapEndpoint
                {
                    BaseUri = new UriBuilder(message.GetUri())
                    {
                        Path = "/", Fragment = "", Query = ""
                    }.Uri,
                      IsMulticast = message.IsMulticast,
                }
            }
            ;
            else if (message.IsMulticast && !remoteEndpoint.IsMulticast)
            {
                throw new CoapClientException("Can not send CoAP multicast message to a non-multicast endpoint");
            }

            Task task;

            lock (this)
            {
                task = (Endpoint == null)
                    ? Task.CompletedTask
                    : Endpoint.SendAsync(new CoapPacket
                {
                    Payload  = message.ToBytes(),
                    Endpoint = remoteEndpoint
                }, token);
            }

            await task.ConfigureAwait(false);
        }
예제 #2
0
        private async Task SendAsyncInternal(CoapMessage message, ICoapEndpoint remoteEndpoint, CancellationToken token)
        {
            if (Endpoint == null)
            {
                return;
            }

            if (remoteEndpoint == null)
            {
                remoteEndpoint = new CoapEndpoint
                {
                    BaseUri = new UriBuilder(message.GetUri())
                    {
                        Path = "/", Fragment = "", Query = ""
                    }.Uri,
                      IsMulticast = message.IsMulticast,
                }
            }
            ;
            else if (message.IsMulticast && !remoteEndpoint.IsMulticast)
            {
                throw new CoapClientException("Can not send CoAP multicast message to a non-multicast endpoint");
            }

            await Task.Run(async() => await Endpoint.SendAsync(new CoapPacket
            {
                Payload  = message.Serialise(),
                Endpoint = remoteEndpoint
            }), token).ConfigureAwait(false);
        }
예제 #3
0
        private async Task BindToNextendpoint(ICoapEndpoint endpoint, ICoapHandler handler)
        {
            _logger?.LogDebug(CoapLoggingEvents.ServerBindTo, "Binding to", endpoint);
            var transport = _transportFactory.Create(endpoint, handler);

            await transport.BindAsync();

            _transports.Add(transport);
        }
예제 #4
0
        public CoapBlockStreamWriter(CoapBlockWiseContext context, ICoapEndpoint endpoint = null)
            : base(context, endpoint)
        {
            if (!Context.Request.Code.IsRequest())
            {
                throw new InvalidOperationException($"Can not create a {nameof(CoapBlockStreamWriter)} with a {nameof(context)}.{nameof(context.Request)}.{nameof(CoapMessage.Type)} of {context.Request.Type}");
            }

            _writerTask = WriteBlocksAsync();
        }
예제 #5
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;
            }));
        }
예제 #6
0
        public virtual async Task <int> GetAsync(string uri, ICoapEndpoint endpoint, CancellationToken token = default(CancellationToken))
        {
            var message = new CoapMessage
            {
                Code = CoapMessageCode.Get,
                Type = CoapMessageType.Confirmable
            };

            message.SetUri(uri);

            return(await SendAsync(message, endpoint, token).ConfigureAwait(false));
        }
예제 #7
0
        /// <summary>
        /// Assigns an incremented message id (if none is already set) and performs a blocking Send operation.
        /// <para>If the mssage is <see cref="CoapMessageType.Confirmable"/>, the client will wait for a response with a coresponding message Id for the <see cref="RetransmitTimeout"/>* * <see cref="MaxRetransmitAttempts"/></para>
        /// </summary>
        /// <param name="message">The CoAP message to send. It's <see cref="CoapMessage.Id"/> may be set if it is unassigned.</param>
        /// <param name="endpoint">The remote endpoint to send the message to.
        /// <para>The endpoint must implement the same underlying transport to succeed.</para>
        /// </param>
        /// <param name="token">A token used to cancel the blocking Send operation or retransmission attempts.</param>
        /// <returns>The message Id</returns>
        /// <exception cref="CoapClientException">If the timeout period * maximum retransmission attempts was reached.</exception>
        public virtual async Task <int> SendAsync(CoapMessage message, ICoapEndpoint endpoint, CancellationToken token)
        {
            if (Endpoint == null)
            {
                throw new InvalidOperationException($"{nameof(CoapClient)} is in an invalid state");
            }

            if (message.Id == 0)
            {
                message.Id = GetNextMessageId();
            }

            if (message.IsMulticast && message.Type != CoapMessageType.NonConfirmable)
            {
                throw new CoapClientException("Can not send confirmable (CON) CoAP message to a multicast endpoint");
            }

            if (message.Type != CoapMessageType.Confirmable)
            {
                await SendAsyncInternal(message, endpoint, token).ConfigureAwait(false);

                return(message.Id);
            }

            _messageResponses.TryAdd(message.Id, new TaskCompletionSource <CoapMessage>(TaskCreationOptions.RunContinuationsAsynchronously));
            var responseTaskSource = _messageResponses[message.Id];

            for (var attempt = 1; attempt <= MaxRetransmitAttempts; attempt++)
            {
                StartReceiveAsyncInternal();

                await SendAsyncInternal(message, endpoint, token).ConfigureAwait(false);

                token.ThrowIfCancellationRequested();

                var timeout = TimeSpan.FromMilliseconds(RetransmitTimeout.TotalMilliseconds * attempt);

                await Task.WhenAny(responseTaskSource.Task, Task.Delay(timeout, token)).ConfigureAwait(false);

                token.ThrowIfCancellationRequested();


                if (responseTaskSource.Task.IsCompleted)
                {
                    return(message.Id);
                }
            }
            throw new CoapClientException($"Max retransmission attempts reached for Message Id: {message.Id}");
        }
예제 #8
0
        public Task BindTo(ICoapEndpoint endpoint)
        {
            if (endpoint == null)
            {
                throw new ArgumentNullException(nameof(endpoint));
            }
            if (_serverState != (int)ServerState.None || _bindToQueue == null)
            {
                throw new InvalidOperationException("Can not bind to endpoint when server has started");
            }

            _bindToQueue?.Enqueue(endpoint);

            return(Task.CompletedTask);
        }
예제 #9
0
파일: Client.cs 프로젝트: lulzzz/SmartWorld
        /// <summary>
        /// Send out get request to an URI. This method is used in one of the test case
        /// <seealso cref=""/>
        /// <see cref=""/>
        /// </summary>
        /// <param name="uri">destination URI</param>
        /// <permission cref="">This method can be called by: Every User</permission>
        /// <exception cref="StatusReadDeniedException"></exception>
        public async Task <int> GetAsync(string uri, ICoapEndpoint endpoint = null)
        {
            var message = new CoapMessage
            {
                Id   = messageId++,
                Code = CoapMessageCode.Get,
                Type = CoapMessageType.Confirmable
            };

            message.FromUri(uri);

            messageReponses.TryAdd(message.Id, new TaskCompletionSource <CoapMessage>());

            return(await SendAsync(message, endpoint));
        }
예제 #10
0
        public CoapMessageIdentifier(CoapMessage message, ICoapEndpoint endpoint = null, bool isRequest = false)
        {
            Id          = message.Id;
            MessageType = message.Type;
            Endpoint    = endpoint;
            IsRequest   = isRequest;

            // Even no tokens are treated as a zero-length token representing 0x0
            Token = new byte[message.Token?.Length ?? 0];

            if (message.Token != null)
            {
                Array.Copy(message.Token, Token, message.Token.Length);
            }
        }
예제 #11
0
파일: Client.cs 프로젝트: lulzzz/SmartWorld
        /// <summary>
        /// Asynchronously send out message
        /// <seealso cref=""/>
        /// <see cref=""/>
        /// </summary>
        /// <param name="message">message to send</param>
        /// <permission cref="">This method can be called by: Every User</permission>
        /// <exception cref="StatusReadDeniedException"></exception>
        public async Task <int> SendAsync(CoapMessage message, ICoapEndpoint endpoint = null)
        {
            if (message.Id == 0)
            {
                message.Id = messageId++;
            }

            if (message.Type == CoapMessageType.Confirmable)
            {
                messageReponses.TryAdd(message.Id, new TaskCompletionSource <CoapMessage>());
            }

            await transport.SendAsync(new CoapPayload { Payload = message.Serialise(), MessageId = message.Id, m_Endpoint = endpoint });

            return(message.Id);
        }
        public ICoapTransport Create(ICoapEndpoint endPoint, ICoapHandler handler)
        {
            var serverEndpoint = endPoint as CoapDtlsServerEndPoint;

            if (serverEndpoint == null)
            {
                throw new ArgumentException($"Endpoint has to be {nameof(CoapDtlsServerEndPoint)}");
            }
            if (_transport != null)
            {
                throw new InvalidOperationException("CoAP transport may only be created once!");
            }

            _transport = new CoapDtlsServerTransport(serverEndpoint, handler, _tlsServerFactory, _loggerFactory.CreateLogger <CoapDtlsServerTransport>());
            return(_transport);
        }
예제 #13
0
        public CoapBlockStreamReader(CoapBlockWiseContext context, ICoapEndpoint endpoint = null)
            : base(context, endpoint)
        {
            if (context.Response == null)
            {
                throw new ArgumentNullException($"{nameof(context)}.{nameof(context.Response)}");
            }

            var payload = Context.Response.Payload;

            Context.Request.Payload  = null;
            Context.Response.Payload = null;

            if (payload != null)
            {
                _reader.Enqueue(payload, 0, payload.Length);
            }

            var block2 = Context.Response.Options.Get <Block2>();

            if (block2 != null)
            {
                _readBlockNumber = block2.BlockNumber;

                BlockSizeInternal = block2.BlockSize;
                EndOfStream       = !block2.IsMoreFollowing;

                if (payload != null)
                {
                    _readBlockNumber += payload.Length / BlockSizeInternal;
                }

                _readerTask = ReadBlocksAsync();
            }
            else
            {
                EndOfStream = true;
                _readerTask = Task.CompletedTask;
            }
        }
예제 #14
0
        private bool IsRepeated(ICoapEndpoint endpoint, int messageId)
        {
            var clearBefore = DateTime.Now.Subtract(MessageCacheTimeSpan);

            lock (_recentMessages)
            {
                // Clear out expired messageIds
                while (_recentMessages.Count > 0)
                {
                    if (_recentMessages.Peek().Item1 >= clearBefore)
                    {
                        break;
                    }
                    _recentMessages.Dequeue();
                }

                if (_recentMessages.Any(r => r.Item3.Id == messageId && r.Item2 == endpoint))
                {
                    return(true);
                }
            }

            return(false);
        }
예제 #15
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);
예제 #16
0
        /// <summary>
        /// Assigns an incremented message id (if none is already set) and performs a blocking Send operation.
        /// <para>If the mssage is <see cref="CoapMessageType.Confirmable"/>, the client will wait for a response with a coresponding message Id for the <see cref="RetransmitTimeout"/>* * <see cref="MaxRetransmitAttempts"/></para>
        /// </summary>
        /// <param name="message">The CoAP message to send. It's <see cref="CoapMessage.Id"/> may be set if it is unassigned.</param>
        /// <param name="endpoint">The remote endpoint to send the message to.
        /// <para>The endpoint must implement the same underlying transport to succeed.</para>
        /// </param>
        /// <param name="token">A token used to cancel the blocking Send operation or retransmission attempts.</param>
        /// <returns>The message Id</returns>
        /// <exception cref="CoapClientException">If the timeout period * maximum retransmission attempts was reached.</exception>
        public virtual async Task <CoapMessageIdentifier> SendAsync(CoapMessage message, ICoapEndpoint endpoint, CancellationToken token)
        {
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            if (Endpoint == null)
            {
                throw new CoapEndpointException($"{nameof(CoapClient)} has an invalid {nameof(Endpoint)}");
            }

            if (message.Id == 0)
            {
                message.Id = GetNextMessageId();
            }

            if (message.IsMulticast && message.Type != CoapMessageType.NonConfirmable)
            {
                throw new CoapClientException("Can not send confirmable (CON) CoAP message to a multicast endpoint");
            }

            var messageId = message.GetIdentifier(endpoint, message.Type == CoapMessageType.Confirmable || message.Type == CoapMessageType.NonConfirmable);

            _messageResponses.TryAdd(messageId, new TaskCompletionSource <CoapMessage>(TaskCreationOptions.RunContinuationsAsynchronously));

            if (message.Type != CoapMessageType.Confirmable)
            {
                await SendAsyncInternal(message, endpoint, token).ConfigureAwait(false);

                return(messageId);
            }

            if (!_messageResponses.TryGetValue(messageId, out var responseTaskSource))
            {
                throw new CoapClientException("Race condition? This shouldn't happen. Congratuations!");
            }

            for (var attempt = 1; attempt <= MaxRetransmitAttempts; attempt++)
            {
                StartReceiveAsyncInternal();

                await SendAsyncInternal(message, endpoint, token).ConfigureAwait(false);

                token.ThrowIfCancellationRequested();

                var timeout = TimeSpan.FromMilliseconds(RetransmitTimeout.TotalMilliseconds * attempt);

                await Task.WhenAny(responseTaskSource.Task, Task.Delay(timeout, token)).ConfigureAwait(false);

                token.ThrowIfCancellationRequested();


                if (responseTaskSource.Task.IsCompleted)
                {
                    return(messageId);
                }
            }
            throw new CoapClientException($"Max retransmission attempts reached for Message Id: {message.Id}");
        }
예제 #17
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);
 public MockConnectionInformation(ICoapEndpoint endPoint)
 {
     LocalEndpoint = endPoint;
 }
예제 #19
0
 internal OicCoapEndpoint(ICoapEndpoint coapEndpoint, OicCoapTransport transport)
 {
     _coapEndpoint = coapEndpoint;
     Transport     = transport;
 }
예제 #20
0
 public CoapService(Uri listenAddress)
 {
     _endpoint   = CoapEndpointFactory.GetEndpoint(listenAddress);
     _coapClient = new CoapClient(_endpoint);
 }
예제 #21
0
 public virtual Task <int> ObserveAsync(string uri, ICoapEndpoint endpoint = null)
 {
     throw new NotImplementedException();
 }
예제 #22
0
        /// <summary>
        /// Initiates a mew client and assigns a random message Id to be used in new CoAP requests.
        /// </summary>
        /// <param name="endpoint">The local CoAP endpoint to bind to and perform Send/Receive operations on.</param>
        /// <exception cref="ArgumentNullException">When <paramref name="endpoint"/> is <c>null</c></exception>
        public CoapClient(ICoapEndpoint endpoint)
        {
            Endpoint = endpoint ?? throw new ArgumentNullException(nameof(endpoint));

            _messageId = new Random().Next() & 0xFFFF;
        }
예제 #23
0
 public ICoapTransport Create(ICoapEndpoint endPoint, ICoapHandler handler)
 {
     return(new CoapUdpTransport(endPoint as CoapUdpEndPoint ?? throw new InvalidOperationException(), handler, _loggerFactory?.CreateLogger <CoapUdpTransport>()));
 }
예제 #24
0
 public static CoapMessageIdentifier GetIdentifier(this CoapMessage message, ICoapEndpoint endpoint = null, bool isRequest = false)
 => new CoapMessageIdentifier(message, endpoint, isRequest);
예제 #25
0
 public virtual Task <int> PostAsync(string uri, CoapMessage message, ICoapEndpoint endpoint = null)
 {
     throw new NotImplementedException();
 }
예제 #26
0
 public OicCoapEndpoint(ICoapEndpoint coapEndpoint)
 {
     _coapEndpoint = coapEndpoint;
 }
예제 #27
0
        public CoapReceiveResult(ICoapEndpoint endpoint, CoapMessage message)
        {
            Endpoint = endpoint;

            Message = message;
        }
예제 #28
0
 public OicCoapTransport(ICoapEndpoint endpoint)
 {
     _client = new CoapClient(endpoint);
 }
예제 #29
0
 public void Listen(ICoapEndpoint coapEndpoint)
 {
     Listeners.Add(coapEndpoint ?? throw new ArgumentNullException(nameof(coapEndpoint)));
 }
예제 #30
0
파일: Client.cs 프로젝트: lulzzz/SmartWorld
 /// <summary>
 /// Create CoAP Endpoint
 /// </summary>
 /// <param name="transportEndpoint">input string as ICoAPEndpoint type</param>
 /// <exception cref=""></exception>
 /// <remarks>N/a</remarks>
 /// <seealso cref=""/>
 /// <see cref=""/>
 /// <permission cref="">This method can be called by: every user</permission>
 public Coapclient(ICoapEndpoint transportEndpoint)
 {
     transport = transportEndpoint;
     messageId = (ushort)(new Random().Next() & 0xFFFFu);
 }