Skip to content

Commit

Permalink
Support for session reconnect from distributed clients (#2244)
Browse files Browse the repository at this point in the history
- Support Client.Session API to save and restore session configuration information as xml or in a serializable data structure.
- Support to reactivate a session using a new secure channel. 
- API tests
  • Loading branch information
mregen committed Aug 3, 2023
1 parent e61664f commit 81340c3
Show file tree
Hide file tree
Showing 17 changed files with 1,539 additions and 624 deletions.
16 changes: 15 additions & 1 deletion Applications/ConsoleReferenceServer/ConsoleUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -310,8 +310,11 @@ public static class ConsoleUtils
bool logConsole,
LogLevel consoleLogLevel)
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
TaskScheduler.UnobservedTaskException += Unobserved_TaskException;

var loggerConfiguration = new LoggerConfiguration()
.Enrich.FromLogContext();
.Enrich.FromLogContext();

if (logConsole)
{
Expand Down Expand Up @@ -413,6 +416,17 @@ public static ManualResetEvent CtrlCHandler(CancellationTokenSource cts = defaul
}
return quitEvent;
}

private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs args)
{
Utils.LogCritical("Unhandled Exception: {0} IsTerminating: {1}", args.ExceptionObject, args.IsTerminating);
}

private static void Unobserved_TaskException(object sender, UnobservedTaskExceptionEventArgs args)
{
Utils.LogCritical("Unobserved Exception: {0} Observed: {1}", args.Exception, args.Observed);
}

}
}

75 changes: 71 additions & 4 deletions Libraries/Opc.Ua.Client/ISession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,11 @@ public interface ISession : ISessionClient, IDisposable
/// be transferred after reconnect. Service must be supported by server.
/// </remarks>
bool TransferSubscriptionsOnReconnect { get; set; }

/// <summary>
/// Whether the endpoint Url domain is checked in the certificate.
/// </summary>
bool CheckDomain { get; }
#endregion

#region Delegates and Events
Expand Down Expand Up @@ -332,6 +337,17 @@ public interface ISession : ISessionClient, IDisposable
/// <returns>The list of loaded subscriptions</returns>
IEnumerable<Subscription> Load(string filePath, bool transferSubscriptions = false);

/// <summary>
/// Returns the active session configuration and writes it to a stream.
/// </summary>
SessionConfiguration SaveSessionConfiguration(Stream stream = null);

/// <summary>
/// Applies a session configuration.
/// Using a secure channel, with the session configuration a session can be reconnected.
/// </summary>
bool ApplySessionConfiguration(SessionConfiguration sessionConfiguration);

/// <summary>
/// Updates the local copy of the server's namespace uri and server uri tables.
/// </summary>
Expand Down Expand Up @@ -641,8 +657,17 @@ public interface ISession : ISessionClient, IDisposable
bool RemoveSubscriptions(IEnumerable<Subscription> subscriptions);

/// <summary>
/// Transfers a list of Subscriptions from another session.
/// Reactivates a list of subscriptions loaded from storage.
/// </summary>
/// <param name="subscriptions">The list of subscriptions to reactivate.</param>
/// <param name="sendInitialValues">Send the last value of each monitored item in the subscriptions.</param>
bool ReactivateSubscriptions(SubscriptionCollection subscriptions, bool sendInitialValues);

/// <summary>
/// Transfers a list of subscriptions from another session.
/// </summary>
/// <param name="subscriptions">The list of subscriptions to transfer.</param>
/// <param name="sendInitialValues">Send the last value of each monitored item in the subscriptions.</param>
bool TransferSubscriptions(SubscriptionCollection subscriptions, bool sendInitialValues);

/// <summary>
Expand All @@ -658,13 +683,31 @@ public interface ISession : ISessionClient, IDisposable
/// Removes a subscription from the session.
/// </summary>
/// <param name="subscription">The subscription to remove.</param>
Task<bool> RemoveSubscriptionAsync(Subscription subscription);
/// <param name="ct">The cancellation token for the request.</param>
Task<bool> RemoveSubscriptionAsync(Subscription subscription, CancellationToken ct = default);

/// <summary>
/// Removes a list of subscriptions from the sessiont.
/// Removes a list of subscriptions from the session.
/// </summary>
/// <param name="subscriptions">The list of subscriptions to remove.</param>
Task<bool> RemoveSubscriptionsAsync(IEnumerable<Subscription> subscriptions);
/// <param name="ct">The cancellation token for the request.</param>
Task<bool> RemoveSubscriptionsAsync(IEnumerable<Subscription> subscriptions, CancellationToken ct = default);

/// <summary>
/// Reactivates a list of subscriptions loaded from storage.
/// </summary>
/// <param name="subscriptions">The list of subscriptions to reactivate.</param>
/// <param name="sendInitialValues">Send the last value of each monitored item in the subscriptions.</param>
/// <param name="ct">The cancellation token for the request.</param>
Task<bool> ReactivateSubscriptionsAsync(SubscriptionCollection subscriptions, bool sendInitialValues, CancellationToken ct = default);

/// <summary>
/// Transfers a list of subscriptions from another session.
/// </summary>
/// <param name="subscriptions">The list of subscriptions to transfer.</param>
/// <param name="sendInitialValues">Send the last value of each monitored item in the subscriptions.</param>
/// <param name="ct">The cancellation token for the request.</param>
Task<bool> TransferSubscriptionsAsync(SubscriptionCollection subscriptions, bool sendInitialValues, CancellationToken ct = default);
#endif
#endregion

Expand Down Expand Up @@ -770,6 +813,18 @@ public interface ISession : ISessionClient, IDisposable
/// <param name="args">The input arguments.</param>
/// <returns>The list of output argument values.</returns>
IList<object> Call(NodeId objectId, NodeId methodId, params object[] args);

#if CLIENT_ASYNC
/// <summary>
/// Calls the specified method and returns the output arguments.
/// </summary>
/// <param name="objectId">The NodeId of the object that provides the method.</param>
/// <param name="methodId">The NodeId of the method to call.</param>
/// <param name="ct">The cancellation token for the request.</param>
/// <param name="args">The input arguments.</param>
/// <returns>The list of output argument values.</returns>
Task<IList<object>> CallAsync(NodeId objectId, NodeId methodId, CancellationToken ct = default, params object[] args);
#endif
#endregion

#region Publish Methods
Expand All @@ -782,6 +837,18 @@ public interface ISession : ISessionClient, IDisposable
/// Sends a republish request.
/// </summary>
bool Republish(uint subscriptionId, uint sequenceNumber);

/// <summary>
/// Call the ResendData method on the server for all subscriptions.
/// </summary>
bool ResendData(IEnumerable<Subscription> subscriptions, out IList<ServiceResult> errors);

#if CLIENT_ASYNC
/// <summary>
/// Call the ResendData method on the server for all subscriptions.
/// </summary>
Task<(bool, IList<ServiceResult>)> ResendDataAsync(IEnumerable<Subscription> subscriptions, CancellationToken ct = default);
#endif
#endregion
}
}
Loading

0 comments on commit 81340c3

Please sign in to comment.