Skip to content

Commit

Permalink
Observe (#9)
Browse files Browse the repository at this point in the history
* Clean up from different code review software

* Check point cleanups

* Turn reconnect behaior off by default

* Address issues #6 and #7

These are both turned off by default now
Setup to release to nuget
  • Loading branch information
jimsch authored May 26, 2017
1 parent a6e49a3 commit 1ca1c08
Show file tree
Hide file tree
Showing 9 changed files with 171 additions and 181 deletions.
2 changes: 1 addition & 1 deletion CoAP.NET/Log/LogManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace Com.AugustCellars.CoAP.Log
/// </summary>
public static class LogManager
{
static LogLevel _level = LogLevel.All;
static LogLevel _level = LogLevel.None;
static ILogManager _manager;

static LogManager()
Expand Down
45 changes: 20 additions & 25 deletions CoAP.NET/Observe/ObserveNotificationOrderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@

using System;
using System.Threading;
using Com.AugustCellars.CoAP.Util;

namespace Com.AugustCellars.CoAP.Observe
{
Expand All @@ -21,9 +20,8 @@ namespace Com.AugustCellars.CoAP.Observe
/// </summary>
public class ObserveNotificationOrderer
{
readonly ICoapConfig _config;
private readonly ICoapConfig _config;
private Int32 _number;
private DateTime _timestamp;

public ObserveNotificationOrderer()
: this(null)
Expand All @@ -41,8 +39,7 @@ public ObserveNotificationOrderer(ICoapConfig config)
public Int32 GetNextObserveNumber()
{
Int32 next = Interlocked.Increment(ref _number);
while (next >= 1 << 24)
{
while (next >= 1 << 24) {
Interlocked.CompareExchange(ref _number, 0, next);
next = Interlocked.Increment(ref _number);
}
Expand All @@ -54,20 +51,20 @@ public Int32 GetNextObserveNumber()
/// </summary>
public Int32 Current
{
get { return _number; }
get => _number;
}

public DateTime Timestamp
{
get { return _timestamp; }
set { _timestamp = value; }
}
public DateTime Timestamp { get; set; }

/// <summary>
/// Is this the most recent response that we have seen for this observe relation?
/// </summary>
/// <param name="response"></param>
/// <returns></returns>
public Boolean IsNew(Response response)
{
Int32? obs = response.Observe;
if (!obs.HasValue)
{
if (!obs.HasValue) {
// this is a final response, e.g., error or proactive cancellation
return true;
}
Expand All @@ -76,21 +73,19 @@ public Boolean IsNew(Response response)
// arrive and be processed by different threads. We have to
// ensure that only the most fresh one is being delivered.
// We use the notation from the observe draft-08.
DateTime T1 = Timestamp;
DateTime T2 = DateTime.Now;
Int32 V1 = Current;
Int32 V2 = obs.Value;
DateTime t1 = Timestamp;
DateTime t2 = DateTime.Now;
Int32 v1 = Current;
Int32 v2 = obs.Value;
Int64 notifMaxAge = (_config ?? CoapConfig.Default).NotificationMaxAge;
if (V1 < V2 && V2 - V1 < 1 << 23
|| V1 > V2 && V1 - V2 > 1 << 23
|| T2 > T1.AddMilliseconds(notifMaxAge))
{
Timestamp = T2;
_number = V2;
if ((v1 < v2) && (v2 - v1 < 1 << 23)
|| (v1 > v2) && (v1 - v2 > 1 << 23)
|| (t2 > t1.AddMilliseconds(notifMaxAge))) {
Timestamp = t2;
_number = v2;
return true;
}
else
{
else {
return false;
}
}
Expand Down
92 changes: 41 additions & 51 deletions CoAP.NET/Observe/ObserveRelation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,19 @@ namespace Com.AugustCellars.CoAP.Observe
/// </summary>
public class ObserveRelation
{
static readonly ILogger log = LogManager.GetLogger(typeof(ObserveRelation));
readonly ICoapConfig _config;
readonly ObservingEndpoint _endpoint;
readonly IResource _resource;
readonly Exchange _exchange;
private Response _recentControlNotification;
private Response _nextControlNotification;
private String _key;
private Boolean _established;
private static readonly ILogger _Log = LogManager.GetLogger(typeof(ObserveRelation));
private readonly ICoapConfig _config;
private readonly ObservingEndpoint _endpoint;
private readonly IResource _resource;
private readonly Exchange _exchange;
private readonly String _key;
private DateTime _interestCheckTime = DateTime.Now;
private Int32 _interestCheckCounter = 1;

/// <summary>
/// The notifications that have been sent, so they can be removed from the Matcher
/// </summary>
private ConcurrentQueue<Response> _notifications = new ConcurrentQueue<Response>();
private readonly ConcurrentQueue<Response> _notifications = new ConcurrentQueue<Response>();

/// <summary>
/// Constructs a new observe relation.
Expand All @@ -50,82 +47,64 @@ public class ObserveRelation
/// <param name="exchange">the exchange that tries to establish the observe relation</param>
public ObserveRelation(ICoapConfig config, ObservingEndpoint endpoint, IResource resource, Exchange exchange)
{
if (config == null)
throw ThrowHelper.ArgumentNull("config");
if (endpoint == null)
throw ThrowHelper.ArgumentNull("endpoint");
if (resource == null)
throw ThrowHelper.ArgumentNull("resource");
if (exchange == null)
throw ThrowHelper.ArgumentNull("exchange");
_config = config;
_endpoint = endpoint;
_resource = resource;
_exchange = exchange;
_key = String.Format("{0}#{1}", Source, exchange.Request.TokenString);
_config = config?? throw ThrowHelper.ArgumentNull("config");
_endpoint = endpoint?? throw ThrowHelper.ArgumentNull("endpoint");
_resource = resource?? throw ThrowHelper.ArgumentNull("resource");
_exchange = exchange?? throw ThrowHelper.ArgumentNull("exchange");
_key = $"{Source}#{exchange.Request.TokenString}";
}

/// <summary>
/// Gets the resource.
/// </summary>
public IResource Resource
{
get { return _resource; }
get =>_resource;
}

/// <summary>
/// Gets the exchange.
/// </summary>
public Exchange Exchange
{
get { return _exchange; }
get => _exchange;
}

public String Key
{
get { return _key; }
get => _key;
}

/// <summary>
/// Gets the source endpoint of the observing endpoint.
/// </summary>
public System.Net.EndPoint Source
{
get { return _endpoint.EndPoint; }
get => _endpoint.EndPoint;
}

public Response CurrentControlNotification
{
get { return _recentControlNotification; }
set { _recentControlNotification = value; }
}
public Response CurrentControlNotification { get; set; }

public Response NextControlNotification
{
get { return _nextControlNotification; }
set { _nextControlNotification = value; }
}
public Response NextControlNotification { get; set; }

/// <summary>
/// Gets or sets a value indicating if this relation has been established.
/// </summary>
public Boolean Established
{
get { return _established; }
set { _established = value; }
}
public Boolean Established { get; set; }

/// <summary>
/// Cancel this observe relation.
/// </summary>
public void Cancel()
{
if (log.IsDebugEnabled)
log.Debug("Cancel observe relation from " + _key + " with " + _resource.Path);
if (_Log.IsDebugEnabled) {
_Log.Debug("Cancel observe relation from " + _key + " with " + _resource.Path);
}
// stop ongoing retransmissions
if (_exchange.Response != null)
if (_exchange.Response != null) {
_exchange.Response.Cancel();
_established = false;
}
Established = false;
_resource.RemoveObserveRelation(this);
_endpoint.RemoveObserveRelation(this);
_exchange.Complete = true;
Expand All @@ -149,30 +128,41 @@ public void NotifyObservers()
_resource.HandleRequest(_exchange);
}

/// <summary>
/// Do we think that we should be doing a CON check on the resource?
/// The check is done on both a time intervolt and a number of notifications.
/// </summary>
/// <returns>true if should do a CON check</returns>
public Boolean Check()
{
Boolean check = false;
bool check = false;
DateTime now = DateTime.Now;
check |= _interestCheckTime.AddMilliseconds(_config.NotificationCheckIntervalTime) < now;
check |= (++_interestCheckCounter >= _config.NotificationCheckIntervalCount);
if (check)
{
if (check) {
_interestCheckTime = now;
_interestCheckCounter = 0;
}
return check;
}

/// <summary>
/// Add the response to the notification list for this observation
/// </summary>
/// <param name="notification">Response to send</param>
public void AddNotification(Response notification)
{
_notifications.Enqueue(notification);
}

/// <summary>
/// Enumerate through all of the queued notifications
/// </summary>
/// <returns></returns>
public IEnumerable<Response> ClearNotifications()
{
Response resp;
while (_notifications.TryDequeue(out resp))
{
while (_notifications.TryDequeue(out resp)) {
yield return resp;
}
}
Expand Down
15 changes: 7 additions & 8 deletions CoAP.NET/Observe/ObservingEndpoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ namespace Com.AugustCellars.CoAP.Observe
/// </summary>
public class ObservingEndpoint
{
readonly System.Net.EndPoint _endpoint;
readonly ICollection<ObserveRelation> _relations = new SynchronizedCollection<ObserveRelation>();
private readonly System.Net.EndPoint _endpoint;
private readonly ICollection<ObserveRelation> _relations = new SynchronizedCollection<ObserveRelation>();

/// <summary>
/// Constructs a new observing endpoint.
Expand All @@ -39,7 +39,7 @@ public ObservingEndpoint(System.Net.EndPoint ep)
/// </summary>
public System.Net.EndPoint EndPoint
{
get { return _endpoint; }
get => _endpoint;
}

/// <summary>
Expand All @@ -63,10 +63,10 @@ public void RemoveObserveRelation(ObserveRelation relation)
/// </summary>
public ObserveRelation GetObserveRelation(Byte[] token)
{
foreach (ObserveRelation relation in _relations)
{
if (ByteArrayUtils.Equals(token, relation.Exchange.Request.Token))
foreach (ObserveRelation relation in _relations) {
if (ByteArrayUtils.Equals(token, relation.Exchange.Request.Token)) {
return relation;
}
}
return null;
}
Expand All @@ -77,8 +77,7 @@ public ObserveRelation GetObserveRelation(Byte[] token)
/// </summary>
public void CancelAll()
{
foreach (ObserveRelation relation in _relations)
{
foreach (ObserveRelation relation in _relations) {
relation.Cancel();
}
}
Expand Down
4 changes: 2 additions & 2 deletions CoAP.NET/Observe/ReregisterEventArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ public ReregisterEventArgs(Request refresh)
/// <summary>
/// Gets the request sent to refresh an observation.
/// </summary>
public Request RefreshRequest
public Request RefreshRequest
{
get { return _refreshRequest; }
get =>_refreshRequest;
}
}
}
6 changes: 6 additions & 0 deletions CoAP.NET/Request.cs
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,12 @@ public Request SetUri(String uri)
return this;
}

/// <summary>
/// Should we attempt to reconnect to keep an observe relationship fresh
/// in the event the MAX-AGE expires on the current value?
/// </summary>
public Boolean ObserveReconnect { get; set; }

/// <summary>
/// Sets CoAP's observe option. If the target resource of this request
/// responds with a success code and also sets the observe option, it will
Expand Down
Loading

0 comments on commit 1ca1c08

Please sign in to comment.