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); }
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); }
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); }
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(); }
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; })); }
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)); }
/// <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}"); }
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); }
/// <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)); }
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); } }
/// <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); }
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; } }
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); }
/// <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);
/// <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}"); }
/// <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; }
internal OicCoapEndpoint(ICoapEndpoint coapEndpoint, OicCoapTransport transport) { _coapEndpoint = coapEndpoint; Transport = transport; }
public CoapService(Uri listenAddress) { _endpoint = CoapEndpointFactory.GetEndpoint(listenAddress); _coapClient = new CoapClient(_endpoint); }
public virtual Task <int> ObserveAsync(string uri, ICoapEndpoint endpoint = null) { throw new NotImplementedException(); }
/// <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; }
public ICoapTransport Create(ICoapEndpoint endPoint, ICoapHandler handler) { return(new CoapUdpTransport(endPoint as CoapUdpEndPoint ?? throw new InvalidOperationException(), handler, _loggerFactory?.CreateLogger <CoapUdpTransport>())); }
public static CoapMessageIdentifier GetIdentifier(this CoapMessage message, ICoapEndpoint endpoint = null, bool isRequest = false) => new CoapMessageIdentifier(message, endpoint, isRequest);
public virtual Task <int> PostAsync(string uri, CoapMessage message, ICoapEndpoint endpoint = null) { throw new NotImplementedException(); }
public OicCoapEndpoint(ICoapEndpoint coapEndpoint) { _coapEndpoint = coapEndpoint; }
public CoapReceiveResult(ICoapEndpoint endpoint, CoapMessage message) { Endpoint = endpoint; Message = message; }
public OicCoapTransport(ICoapEndpoint endpoint) { _client = new CoapClient(endpoint); }
public void Listen(ICoapEndpoint coapEndpoint) { Listeners.Add(coapEndpoint ?? throw new ArgumentNullException(nameof(coapEndpoint))); }
/// <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); }