Skip to content
This repository has been archived by the owner on Sep 1, 2022. It is now read-only.

Commit

Permalink
Merge pull request #366 from dnp3/feature/reconnect-delay-3.0
Browse files Browse the repository at this point in the history
Reconnection delay [develop]
  • Loading branch information
emgre committed Apr 20, 2020
2 parents 71d7f0b + ec57e1f commit bf34bd7
Show file tree
Hide file tree
Showing 14 changed files with 85 additions and 34 deletions.
3 changes: 3 additions & 0 deletions cpp/lib/include/opendnp3/channel/ChannelRetry.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class ChannelRetry
*/
ChannelRetry(TimeDuration minOpenRetry,
TimeDuration maxOpenRetry,
TimeDuration reconnectDelay = TimeDuration::Zero(),
IOpenDelayStrategy& strategy = ExponentialBackoffStrategy::Instance());

/// Return the default configuration of exponential backoff from 1 sec to 1 minute
Expand All @@ -48,6 +49,8 @@ class ChannelRetry
TimeDuration minOpenRetry;
/// maximum connection retry interval on failure
TimeDuration maxOpenRetry;
/// reconnect delay (defaults to zero)
TimeDuration reconnectDelay;

TimeDuration NextDelay(const TimeDuration& current) const
{
Expand Down
7 changes: 5 additions & 2 deletions cpp/lib/src/channel/ChannelRetry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,11 @@
namespace opendnp3
{

ChannelRetry::ChannelRetry(TimeDuration minOpenRetry_, TimeDuration maxOpenRetry_, IOpenDelayStrategy& strategy_)
: minOpenRetry(minOpenRetry_), maxOpenRetry(maxOpenRetry_), strategy(strategy_)
ChannelRetry::ChannelRetry(TimeDuration minOpenRetry_,
TimeDuration maxOpenRetry_,
TimeDuration reconnectDelay_,
IOpenDelayStrategy& strategy_)
: minOpenRetry(minOpenRetry_), maxOpenRetry(maxOpenRetry_), reconnectDelay(reconnectDelay_), strategy(strategy_)
{
}

Expand Down
6 changes: 4 additions & 2 deletions cpp/lib/src/channel/SerialIOHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@ void SerialIOHandler::SuspendChannelAccept()

void SerialIOHandler::OnChannelShutdown()
{
this->BeginChannelAccept();
this->retrytimer = this->executor->start(this->retry.reconnectDelay.value, [this, self = shared_from_this()]() {
this->BeginChannelAccept();
});
}

void SerialIOHandler::TryOpen(const TimeDuration& timeout)
Expand All @@ -71,7 +73,7 @@ void SerialIOHandler::TryOpen(const TimeDuration& timeout)

++this->statistics.numOpenFail;

auto callback = [this, timeout]() { this->TryOpen(this->retry.NextDelay(timeout)); };
auto callback = [this, timeout, self = shared_from_this()]() { this->TryOpen(this->retry.NextDelay(timeout)); };

this->retrytimer = this->executor->start(timeout.value, callback);
}
Expand Down
7 changes: 6 additions & 1 deletion cpp/lib/src/channel/TCPClientIOHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,12 @@ void TCPClientIOHandler::SuspendChannelAccept()

void TCPClientIOHandler::OnChannelShutdown()
{
this->BeginChannelAccept();
if (!client) return;

this->retrytimer = this->executor->start(this->retry.reconnectDelay.value, [this, self = shared_from_this()]() {
if (!client) return;
this->BeginChannelAccept();
});
}

bool TCPClientIOHandler::StartConnect(const TimeDuration& delay)
Expand Down
20 changes: 13 additions & 7 deletions cpp/lib/src/channel/tls/TLSClientIOHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ void TLSClientIOHandler::BeginChannelAccept()
}
else
{
this->StartConnect(this->client, this->retry.minOpenRetry);
this->StartConnect(this->retry.minOpenRetry);
}
}

Expand All @@ -73,13 +73,19 @@ void TLSClientIOHandler::SuspendChannelAccept()

void TLSClientIOHandler::OnChannelShutdown()
{
this->BeginChannelAccept();
if (!client) return;

this->retrytimer = this->executor->start(this->retry.reconnectDelay.value, [this, self = shared_from_this()]() {
if (!client) return;
this->BeginChannelAccept();
});
}

void TLSClientIOHandler::StartConnect(const std::shared_ptr<TLSClient>& client, const TimeDuration& delay)
void TLSClientIOHandler::StartConnect(const TimeDuration& delay)
{
auto cb = [=, self = shared_from_this()](const std::shared_ptr<exe4cpp::StrandExecutor>& executor,
const std::shared_ptr<asio::ssl::stream<asio::ip::tcp::socket>>& stream,
if (!this->client) false;

auto cb = [=, self = shared_from_this()](const std::shared_ptr<exe4cpp::StrandExecutor>& executor, const std::shared_ptr<asio::ssl::stream<asio::ip::tcp::socket>>& stream,
const std::error_code& ec) -> void {
if (ec)
{
Expand All @@ -89,9 +95,9 @@ void TLSClientIOHandler::StartConnect(const std::shared_ptr<TLSClient>& client,

const auto newDelay = this->retry.NextDelay(delay);

auto cb = [self, newDelay, client, this]() {
auto cb = [self, newDelay, this]() {
this->remotes.Next();
this->StartConnect(client, newDelay);
this->StartConnect(newDelay);
};

this->retrytimer = this->executor->start(delay.value, cb);
Expand Down
2 changes: 1 addition & 1 deletion cpp/lib/src/channel/tls/TLSClientIOHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class TLSClientIOHandler final : public IOHandler
virtual void OnChannelShutdown() override;

private:
void StartConnect(const std::shared_ptr<TLSClient>& client, const TimeDuration& delay);
void StartConnect(const TimeDuration& delay);

void ResetState();

Expand Down
3 changes: 2 additions & 1 deletion dotnet/CLRAdapter/src/DNP3ManagerAdapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,8 @@ namespace Automatak
opendnp3::ChannelRetry DNP3ManagerAdapter::Convert(Interface::ChannelRetry ^ retry)
{
return opendnp3::ChannelRetry(Conversions::ConvertTimespan(retry->minRetryDelay),
Conversions::ConvertTimespan(retry->maxRetryDelay));
Conversions::ConvertTimespan(retry->maxRetryDelay),
Conversions::ConvertTimespan(retry->reconnectDelay));
}
}
}
Expand Down
7 changes: 5 additions & 2 deletions dotnet/CLRInterface/src/ChannelRetry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,12 @@ public class ChannelRetry
/// </summary>
/// <param name="minRetryDelay">the minimum (first) retry delay</param>
/// <param name="maxRetryDelay">the maximum delay</param>
public ChannelRetry(TimeSpan minRetryDelay, TimeSpan maxRetryDelay)
/// <param name="reconnectDelay">delay between reconnections when a read/write fails</param>
public ChannelRetry(TimeSpan minRetryDelay, TimeSpan maxRetryDelay, TimeSpan reconnectDelay)
{
this.minRetryDelay = minRetryDelay;
this.maxRetryDelay = maxRetryDelay;
this.reconnectDelay = reconnectDelay;
}

/// <summary>
Expand All @@ -46,11 +48,12 @@ public static ChannelRetry Default
{
get
{
return new ChannelRetry(TimeSpan.FromSeconds(1), TimeSpan.FromMinutes(1));
return new ChannelRetry(TimeSpan.FromSeconds(1), TimeSpan.FromMinutes(1), TimeSpan.Zero);
}
}

public readonly TimeSpan minRetryDelay;
public readonly TimeSpan maxRetryDelay;
public readonly TimeSpan reconnectDelay;
}
}
2 changes: 1 addition & 1 deletion dotnet/examples/master/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ static int Main(string[] args)
var channel = mgr.AddTCPClient(
"client",
LogLevels.NORMAL | LogLevels.APP_COMMS,
ChannelRetry.Default,
new ChannelRetry(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(5)),
new List<IPEndpoint> { new IPEndpoint("127.0.0.1", 20000) },
ChannelListener.Print()
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,24 @@ public class ChannelRetry
* Construct a channel retry class
* @param minRetryDelay minimum retry delay
* @param maxRetryDelay maximum retry delay
* @param reconnectDelay delay between reconnections when a read/write fails
*/
public ChannelRetry(Duration minRetryDelay, Duration maxRetryDelay)
public ChannelRetry(Duration minRetryDelay, Duration maxRetryDelay, Duration reconnectDelay)
{
this.minRetryDelay = minRetryDelay;
this.maxRetryDelay = maxRetryDelay;
this.reconnectDelay = reconnectDelay;
}

/// <summary>
/// Default configuration from 1 second to 1 minute
/// </summary>
public static ChannelRetry getDefault()
{
return new ChannelRetry(Duration.ofSeconds(1), Duration.ofMinutes(1));
return new ChannelRetry(Duration.ofSeconds(1), Duration.ofMinutes(1), Duration.ofSeconds(0));
}

public final Duration minRetryDelay;
public final Duration maxRetryDelay;
public final Duration reconnectDelay;
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,17 @@ public synchronized Channel addTCPClient(String id, int levels, ChannelRetry ret
throw new DNP3Exception("Manager has been shutdown");
}

long ptr = get_native_channel_tcp_client(this.pointer, id, levels, retry.minRetryDelay.toMillis(), retry.maxRetryDelay.toMillis(), remotes, adapter, listener);
long ptr = get_native_channel_tcp_client(
this.pointer,
id,
levels,
retry.minRetryDelay.toMillis(),
retry.maxRetryDelay.toMillis(),
retry.reconnectDelay.toMillis(),
remotes,
adapter,
listener
);

if(ptr == 0) {
throw new DNP3Exception("Unable to create channel");
Expand Down Expand Up @@ -99,7 +109,18 @@ public synchronized Channel addTLSClient(String id, int levels, ChannelRetry ret
throw new DNP3Exception("Manager has been shutdown");
}

long ptr = get_native_channel_tls_client(this.pointer, id, levels, retry.minRetryDelay.toMillis(), retry.maxRetryDelay.toMillis(), remotes, adapter, config, listener);
long ptr = get_native_channel_tls_client(
this.pointer,
id,
levels,
retry.minRetryDelay.toMillis(),
retry.maxRetryDelay.toMillis(),
retry.reconnectDelay.toMillis(),
remotes,
adapter,
config,
listener
);

if(ptr == 0) {
throw new DNP3Exception("Unable to create TLS client. Did you compile opendnp3 w/ TLS support?");
Expand Down Expand Up @@ -139,6 +160,7 @@ public synchronized Channel addSerial(String id, int levels, ChannelRetry retry,
levels,
retry.minRetryDelay.toMillis(),
retry.maxRetryDelay.toMillis(),
retry.reconnectDelay.toMillis(),
settings.port,
settings.baudRate,
settings.dataBits,
Expand Down Expand Up @@ -168,12 +190,12 @@ public synchronized void shutdown()
private native long create_native_manager(int concurrency, LogHandler handler);
private native void shutdown_native_manager(long nativePointer);

private native long get_native_channel_tcp_client(long nativePointer, String id, int level, long minRetryMs, long maxRetryMs, List<IPEndpoint> remotes, String adapter, ChannelListener listener);
private native long get_native_channel_tcp_client(long nativePointer, String id, int level, long minRetryMs, long maxRetryMs, long reconnectDelayMs, List<IPEndpoint> remotes, String adapter, ChannelListener listener);
private native long get_native_channel_tcp_server(long nativePointer, String id, int level, int acceptMode, IPEndpoint endpoint, ChannelListener listener);
private native long get_native_channel_udp(long nativePointer, String id, int level, long minRetryMs, long maxRetryMs, IPEndpoint localEndpoint, IPEndpoint remoteEndpoint, ChannelListener listener);
private native long get_native_channel_tls_client(long nativePointer, String id, int level, long minRetryMs, long maxRetryMs, List<IPEndpoint> remotes, String adapter, TLSConfig config, ChannelListener listener);
private native long get_native_channel_tls_client(long nativePointer, String id, int level, long minRetryMs, long maxRetryMs, long reconnectDelayMs, List<IPEndpoint> remotes, String adapter, TLSConfig config, ChannelListener listener);
private native long get_native_channel_tls_server(long nativePointer, String id, int level, int acceptMode, IPEndpoint endpoint, TLSConfig config, ChannelListener listener);
private native long get_native_channel_serial(long nativePointer, String id, int level, long minRetryMs, long maxRetryMs, String port, int baudRate, int dataBits, int parity, int stopBits, int flowControl, ChannelListener listener);
private native long get_native_channel_serial(long nativePointer, String id, int level, long minRetryMs, long maxRetryMs, long reconnectDelayMs, String port, int baudRate, int dataBits, int parity, int stopBits, int flowControl, ChannelListener listener);


}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public class DNP3ManagerIntegrationTest extends TestCase {
static final int NUM_POINTS_PER_EVENT_TYPE = 50;
static final int NUM_ITERATIONS = 10;
static final int EVENTS_PER_ITERATION = 50;
static final int START_PORT = 20000;
static final int START_PORT = 20010;

static final int NUM_THREADS_IN_POOL = 4;
static final Duration TIMEOUT = Duration.ofSeconds(10);
Expand Down
9 changes: 6 additions & 3 deletions java/cpp/com_automatak_dnp3_impl_ManagerImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ JNIEXPORT jlong JNICALL Java_com_automatak_dnp3_impl_ManagerImpl_get_1native_1ch
jint jlevels,
jlong jminRetry,
jlong jmaxRetry,
jlong jreconnectDelay,
jobject jremotes,
jstring jadapter,
jobject jlistener)
Expand All @@ -88,7 +89,7 @@ JNIEXPORT jlong JNICALL Java_com_automatak_dnp3_impl_ManagerImpl_get_1native_1ch

CString id(env, jid);
CString adapter(env, jadapter);
ChannelRetry retry(TimeDuration::Milliseconds(jminRetry), TimeDuration::Milliseconds(jmaxRetry));
ChannelRetry retry(TimeDuration::Milliseconds(jminRetry), TimeDuration::Milliseconds(jmaxRetry), TimeDuration::Milliseconds(jreconnectDelay));
auto listener = jlistener ? std::make_shared<ChannelListenerAdapter>(jlistener) : nullptr;

// Convert endpoints
Expand Down Expand Up @@ -147,6 +148,7 @@ JNIEXPORT jlong JNICALL Java_com_automatak_dnp3_impl_ManagerImpl_get_1native_1ch
jint jlevels,
jlong jminRetry,
jlong jmaxRetry,
jlong jreconnectDelay,
jobject jremotes,
jstring jadapter,
jobject jtlsconfig,
Expand All @@ -156,7 +158,7 @@ JNIEXPORT jlong JNICALL Java_com_automatak_dnp3_impl_ManagerImpl_get_1native_1ch

CString id(env, jid);
CString adapter(env, jadapter);
ChannelRetry retry(TimeDuration::Milliseconds(jminRetry), TimeDuration::Milliseconds(jmaxRetry));
ChannelRetry retry(TimeDuration::Milliseconds(jminRetry), TimeDuration::Milliseconds(jmaxRetry), TimeDuration::Milliseconds(jreconnectDelay));
auto tlsconf = ConvertTLSConfig(env, jtlsconfig);
auto listener = jlistener ? std::make_shared<ChannelListenerAdapter>(jlistener) : nullptr;

Expand Down Expand Up @@ -207,6 +209,7 @@ JNIEXPORT jlong JNICALL Java_com_automatak_dnp3_impl_ManagerImpl_get_1native_1ch
jint jlevels,
jlong jminRetry,
jlong jmaxRetry,
jlong jreconnectDelay,
jstring jsdevice,
jint jbaudRate,
jint jdatabits,
Expand All @@ -218,7 +221,7 @@ JNIEXPORT jlong JNICALL Java_com_automatak_dnp3_impl_ManagerImpl_get_1native_1ch
const auto manager = (DNP3Manager*)native;

CString id(env, jid);
ChannelRetry retry(TimeDuration::Milliseconds(jminRetry), TimeDuration::Milliseconds(jmaxRetry));
ChannelRetry retry(TimeDuration::Milliseconds(jminRetry), TimeDuration::Milliseconds(jmaxRetry), TimeDuration::Milliseconds(jreconnectDelay));
CString sdevice(env, jsdevice);

opendnp3::SerialSettings settings;
Expand Down
12 changes: 6 additions & 6 deletions java/cpp/com_automatak_dnp3_impl_ManagerImpl.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit bf34bd7

Please sign in to comment.