Skip to content

Commit

Permalink
Allow selectively setting Uri componetns in CoapMessage.SetUri
Browse files Browse the repository at this point in the history
  • Loading branch information
NZSmartie committed Sep 22, 2017
1 parent b8ef59a commit 2f453f5
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 24 deletions.
11 changes: 10 additions & 1 deletion src/CoAPNet/CoapClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,15 @@ public CoapClient(ICoapEndpoint endpoint)

private readonly AsyncAutoResetEvent _receiveEvent = new AsyncAutoResetEvent(false);

public async Task<CoapReceiveResult> ReceiveAsync()
=> await ReceiveAsync(RetransmitTimeout.Milliseconds * MaxRetransmitAttempts);

public async Task<CoapReceiveResult> ReceiveAsync(int milliseconds)
=> await ReceiveAsync(new CancellationTokenSource(milliseconds).Token);

public async Task<CoapReceiveResult> ReceiveAsync(TimeSpan timeout)
=> await ReceiveAsync(new CancellationTokenSource(timeout).Token);

/// <summary>
/// Checks if a <see cref="CoapReceiveResult"/> has been received and returns it. Otherwise waits until a new result is received unless cancelled by the <paramref name="token"/>
/// </summary>
Expand Down Expand Up @@ -380,7 +389,7 @@ internal void SetNextMessageId(int value)
Code = CoapMessageCode.Get,
Type = CoapMessageType.Confirmable
};
message.FromUri(uri);
message.SetUri(uri);

return await SendAsync(message, endpoint, token).ConfigureAwait(false);
}
Expand Down
69 changes: 46 additions & 23 deletions src/CoAPNet/CoapMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ public void Deserialise(byte[] data)
/// <param name="input"></param>
[Obsolete]
public void FromUri(string input)
=> SetUri(new Uri(input));
=> SetUri(new Uri(input, UriKind.RelativeOrAbsolute));

/// <summary>
/// Obsolete: See <see cref="SetUri(Uri)"/>
Expand All @@ -453,49 +453,72 @@ public void FromUri(Uri uri)
/// </summary>
/// <remarks>Any potentially conflicting <see cref="CoapOption"/>s are stripped after URI validation and before processing.</remarks>
/// <param name="input"></param>
public void SetUri(string input)
=> SetUri(new Uri(input));
/// <param name="parts"></param>
public void SetUri(string input, UriComponents parts = UriComponents.HttpRequestUrl)
=> SetUri(new Uri(input, UriKind.RelativeOrAbsolute), parts);

/// <summary>
/// Popualtes <see cref="Options"/> to match the Uri.
/// </summary>
/// <remarks>Any potentially conflicting <see cref="CoapOption"/>s are stripped after URI validation and before processing.</remarks>
/// <param name="uri"></param>
public void SetUri(Uri uri) {
/// <param name="parts"></param>
public void SetUri(Uri uri, UriComponents parts = UriComponents.HttpRequestUrl) {

if (!uri.IsAbsoluteUri)
throw new UriFormatException("URI is not absolute and unsupported by the CoAP scheme");
//if (!uri.IsAbsoluteUri)
// throw new UriFormatException("URI is not absolute and unsupported by the CoAP scheme");

if (uri.Scheme != "coap" && uri.Scheme != "coaps")
if (parts.HasFlag(UriComponents.Scheme) && uri.Scheme != "coap" && uri.Scheme != "coaps")
throw new UriFormatException("Input URI scheme is not coap:// or coaps://");

if (uri.Fragment.Length > 0)
if (parts.HasFlag(UriComponents.Fragment) && uri.Fragment.Length > 0)
throw new UriFormatException("Fragments are unsupported in the CoAP scheme");

// Strip out any existing URI Options
var optionsToDiscard = new int[] { CoapRegisteredOptionNumber.UriHost, CoapRegisteredOptionNumber.UriPort, CoapRegisteredOptionNumber.UriPath, CoapRegisteredOptionNumber.UriQuery };
var optionsToDiscard = new List<int>();
if (parts.HasFlag(UriComponents.Host))
optionsToDiscard.Add(CoapRegisteredOptionNumber.UriHost);
if (parts.HasFlag(UriComponents.Port))
optionsToDiscard.Add(CoapRegisteredOptionNumber.UriPort);
if (parts.HasFlag(UriComponents.Path))
optionsToDiscard.Add(CoapRegisteredOptionNumber.UriPath);
if (parts.HasFlag(UriComponents.Query))
optionsToDiscard.Add(CoapRegisteredOptionNumber.UriQuery);

_options = _options.Where(kv => !optionsToDiscard.Contains(kv.OptionNumber)).ToList();

switch (uri.HostNameType)
if (parts.HasFlag(UriComponents.Host))
{
case UriHostNameType.Dns:
_options.Add(new Options.UriHost(uri.IdnHost));
break;
case UriHostNameType.IPv4:
case UriHostNameType.IPv6:
_options.Add(new Options.UriHost(uri.Host));
break;
default:
throw new UriFormatException("Unknown Hostname");
switch (uri.HostNameType)
{
case UriHostNameType.Dns:
_options.Add(new Options.UriHost(uri.IdnHost));
break;
case UriHostNameType.IPv4:
case UriHostNameType.IPv6:
_options.Add(new Options.UriHost(uri.Host));
break;
default:
throw new UriFormatException("Unknown Hostname");
}
}

if ((uri.Scheme == "coap" && !uri.IsDefaultPort && uri.Port != 5683) ||
if (parts.HasFlag(UriComponents.Port))
{

if ((uri.Scheme == "coap" && !uri.IsDefaultPort && uri.Port != 5683) ||
(uri.Scheme == "coaps" && !uri.IsDefaultPort && uri.Port != 5684))
_options.Add(new Options.UriPort((ushort)uri.Port));
_options.Add(new Options.UriPort((ushort)uri.Port));
}

// Can't access path parameters if uri is not absolute....
if (!uri.IsAbsoluteUri)
uri = new Uri(new Uri("coap://localhost/"), uri);

_options.AddRange(uri.AbsolutePath.Substring(1).Split(new[] { '/' }).Select(p => new Options.UriPath(Uri.UnescapeDataString(p))));
if (parts.HasFlag(UriComponents.Path))
_options.AddRange(uri.AbsolutePath.Substring(1).Split(new[] { '/' }).Select(p => new Options.UriPath(Uri.UnescapeDataString(p))));

if (uri.Query.Length > 0)
if (parts.HasFlag(UriComponents.Query) && uri.Query.Length > 0)
_options.AddRange(uri.Query.Substring(1).Split(new[] { '&' }).Select(p => new Options.UriQuery(Uri.UnescapeDataString(p))));
}

Expand Down

0 comments on commit 2f453f5

Please sign in to comment.