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

Commit

Permalink
Fix Java LinkStatusListener not getting called. (#441)
Browse files Browse the repository at this point in the history
Fix #423.
  • Loading branch information
emgre committed Apr 21, 2022
1 parent c019f43 commit c4d8210
Show file tree
Hide file tree
Showing 21 changed files with 504 additions and 26 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
See [#439](https://github.com/dnp3/opendnp3/pull/439).
* :beetle: In Java, `CommandHeader` builder methods now all return `CommandHeaders`.
See [#440](https://github.com/dnp3/opendnp3/pull/440).
* :beetle: In Java, fix `LinkStatusListener` not getting called. Also added the missing
`onUnknownDestinationAddress` and `onUnknownSourceAddress` callbacks. All the callbacks
now have an empty default implementation. See [#441](https://github.com/dnp3/opendnp3/pull/441).

### 3.1.1 ###
* :beetle: Fix static octet string serilazation bug.
Expand Down
4 changes: 4 additions & 0 deletions java/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,10 @@ set(all_sources
./cpp/jni/JNILinkLayerStatistics.h
./cpp/jni/JNILinkStatistics.cpp
./cpp/jni/JNILinkStatistics.h
./cpp/jni/JNILinkStatus.cpp
./cpp/jni/JNILinkStatus.h
./cpp/jni/JNILinkStatusListener.cpp
./cpp/jni/JNILinkStatusListener.h
./cpp/jni/JNIList.cpp
./cpp/jni/JNIList.h
./cpp/jni/JNILogEntry.cpp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,30 @@ public interface LinkStatusListener
* Called when a the reset/unreset status of the link layer changes
* @param value the current state of the link layer
*/
void onStateChange(LinkStatus value);
default void onStateChange(LinkStatus value) {}

/**
* Called when a link-layer frame is received from an unknown destination address
*/
default void onUnknownDestinationAddress(int destination) {}

/**
* Called when a link-layer frame is received from an unknown source address
*/
default void onUnknownSourceAddress(int source) {}

/**
* Called when a keep alive message is transmitted
*/
void onKeepAliveInitiated();
default void onKeepAliveInitiated() {}

/**
* Called when a keep alive message (request link status) receives no response
*/
void onKeepAliveFailure();
default void onKeepAliveFailure() {}

/**
* Called when a keep alive message receives a valid response
*/
void onKeepAliveSuccess();
default void onKeepAliveSuccess() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,21 @@ public Iterable<ClassAssignment> getClassAssignments()
}

@Override
public void onStateChange(LinkStatus value){}
public void onStateChange(LinkStatus value) {}

@Override
public void onKeepAliveInitiated(){}
public void onUnknownDestinationAddress(int destination) {}

@Override
public void onKeepAliveFailure(){}
public void onUnknownSourceAddress(int source) {}

@Override
public void onKeepAliveSuccess(){}
public void onKeepAliveInitiated() {}

@Override
public void onKeepAliveFailure() {}

@Override
public void onKeepAliveSuccess() {}

}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,16 @@ public void onStateChange(LinkStatus value) {
// do nothing in the default implementation
}

@Override
public void onUnknownDestinationAddress(int destination) {
// do nothing in the default implementation
}

@Override
public void onUnknownSourceAddress(int source) {
// do nothing in the default implementation
}

@Override
public void onKeepAliveInitiated() {
// do nothing in the default implementation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ object Classes {
classOf[AssignClassType],
classOf[RestartMode],
classOf[IndexQualifierMode],
classOf[LinkStatus],

classOf[StaticBinaryVariation],
classOf[StaticDoubleBinaryVariation],
Expand All @@ -77,6 +78,7 @@ object Classes {
private def interfaces : List[ClassConfig] = List(
classOf[LogHandler],
classOf[SOEHandler],
classOf[LinkStatusListener],
classOf[MasterApplication],
classOf[OutstationApplication],
classOf[CommandProcessor],
Expand Down
36 changes: 36 additions & 0 deletions java/cpp/adapters/MasterApplicationAdapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,42 @@

using namespace opendnp3;

void MasterApplicationAdapter::OnStateChange(LinkStatus value)
{
const auto env = JNI::GetEnv();
jni::JCache::LinkStatusListener.onStateChange(env, jni::JLinkStatusListener(proxy.get()), jni::JCache::LinkStatus.fromType(env, static_cast<jint>(value)));
}

void MasterApplicationAdapter::OnUnknownDestinationAddress(uint16_t destination)
{
const auto env = JNI::GetEnv();
jni::JCache::LinkStatusListener.onUnknownDestinationAddress(env, jni::JLinkStatusListener(proxy.get()), destination);
}

void MasterApplicationAdapter::OnUnknownSourceAddress(uint16_t source)
{
const auto env = JNI::GetEnv();
jni::JCache::LinkStatusListener.onUnknownSourceAddress(env, jni::JLinkStatusListener(proxy.get()), source);
}

void MasterApplicationAdapter::OnKeepAliveInitiated()
{
const auto env = JNI::GetEnv();
jni::JCache::LinkStatusListener.onKeepAliveInitiated(env, jni::JLinkStatusListener(proxy.get()));
}

void MasterApplicationAdapter::OnKeepAliveFailure()
{
const auto env = JNI::GetEnv();
jni::JCache::LinkStatusListener.onKeepAliveFailure(env, jni::JLinkStatusListener(proxy.get()));
}

void MasterApplicationAdapter::OnKeepAliveSuccess()
{
const auto env = JNI::GetEnv();
jni::JCache::LinkStatusListener.onKeepAliveSuccess(env, jni::JLinkStatusListener(proxy.get()));
}

opendnp3::UTCTimestamp MasterApplicationAdapter::Now()
{
const auto env = JNI::GetEnv();
Expand Down
14 changes: 13 additions & 1 deletion java/cpp/adapters/MasterApplicationAdapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,19 @@ class MasterApplicationAdapter final : public opendnp3::IMasterApplication
public:
MasterApplicationAdapter(jni::JMasterApplication proxy) : proxy(proxy) {}

virtual opendnp3::UTCTimestamp Now() override;
// opendnp3::ILinkListener

void OnStateChange(opendnp3::LinkStatus value) override;
void OnUnknownDestinationAddress(uint16_t destination) override;
void OnUnknownSourceAddress(uint16_t source) override;
void OnKeepAliveInitiated() override;
void OnKeepAliveFailure() override;
void OnKeepAliveSuccess() override;

// opendnp3::IUTCTimeSource
opendnp3::UTCTimestamp Now() override;

// opendnp3::IMasterApplication

void OnReceiveIIN(const opendnp3::IINField& iin) override;
void OnTaskStart(opendnp3::MasterTaskType type, opendnp3::TaskId id) override;
Expand Down
36 changes: 36 additions & 0 deletions java/cpp/adapters/OutstationApplicationAdapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,42 @@
using namespace jni;
using namespace opendnp3;

void OutstationApplicationAdapter::OnStateChange(LinkStatus value)
{
const auto env = JNI::GetEnv();
JCache::LinkStatusListener.onStateChange(env, jni::JLinkStatusListener(proxy.get()), JCache::LinkStatus.fromType(env, static_cast<jint>(value)));
}

void OutstationApplicationAdapter::OnUnknownDestinationAddress(uint16_t destination)
{
const auto env = JNI::GetEnv();
JCache::LinkStatusListener.onUnknownDestinationAddress(env, jni::JLinkStatusListener(proxy.get()), destination);
}

void OutstationApplicationAdapter::OnUnknownSourceAddress(uint16_t source)
{
const auto env = JNI::GetEnv();
JCache::LinkStatusListener.onUnknownSourceAddress(env, jni::JLinkStatusListener(proxy.get()), source);
}

void OutstationApplicationAdapter::OnKeepAliveInitiated()
{
const auto env = JNI::GetEnv();
JCache::LinkStatusListener.onKeepAliveInitiated(env, jni::JLinkStatusListener(proxy.get()));
}

void OutstationApplicationAdapter::OnKeepAliveFailure()
{
const auto env = JNI::GetEnv();
JCache::LinkStatusListener.onKeepAliveFailure(env, jni::JLinkStatusListener(proxy.get()));
}

void OutstationApplicationAdapter::OnKeepAliveSuccess()
{
const auto env = JNI::GetEnv();
JCache::LinkStatusListener.onKeepAliveSuccess(env, jni::JLinkStatusListener(proxy.get()));
}

bool OutstationApplicationAdapter::SupportsWriteAbsoluteTime()
{
const auto env = JNI::GetEnv();
Expand Down
20 changes: 19 additions & 1 deletion java/cpp/adapters/OutstationApplicationAdapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,27 @@
#include "GlobalRef.h"
#include "../jni/JNIWrappers.h"

class OutstationApplicationAdapter : public opendnp3::IOutstationApplication
class OutstationApplicationAdapter final : public opendnp3::IOutstationApplication
{
public:
OutstationApplicationAdapter(jni::JOutstationApplication proxy) : proxy(proxy) {}

// opendnp3::ILinkListener

void OnStateChange(opendnp3::LinkStatus value) override;

void OnUnknownDestinationAddress(uint16_t destination) override;

void OnUnknownSourceAddress(uint16_t source) override;

void OnKeepAliveInitiated() override;

void OnKeepAliveFailure() override;

void OnKeepAliveSuccess() override;

// opendnp3::IOutstationApplication

bool SupportsWriteAbsoluteTime() override;

bool WriteAbsoluteTime(const opendnp3::UTCTimestamp& timestamp) override;
Expand All @@ -54,6 +70,8 @@ class OutstationApplicationAdapter : public opendnp3::IOutstationApplication

void OnConfirmProcessed(bool is_unsolicited, uint32_t num_class1, uint32_t num_class2, uint32_t num_class3) override;

// opendnp3::IDnpTimeSource

opendnp3::DNPTime Now() override;

private:
Expand Down
6 changes: 6 additions & 0 deletions java/cpp/jni/JCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ namespace jni
cache::LinkLayerConfig JCache::LinkLayerConfig;
cache::LinkLayerStatistics JCache::LinkLayerStatistics;
cache::LinkStatistics JCache::LinkStatistics;
cache::LinkStatus JCache::LinkStatus;
cache::LinkStatusListener JCache::LinkStatusListener;
cache::List JCache::List;
cache::LogEntry JCache::LogEntry;
cache::LogHandler JCache::LogHandler;
Expand Down Expand Up @@ -211,6 +213,8 @@ namespace jni
&& LinkLayerConfig.init(env)
&& LinkLayerStatistics.init(env)
&& LinkStatistics.init(env)
&& LinkStatus.init(env)
&& LinkStatusListener.init(env)
&& List.init(env)
&& LogEntry.init(env)
&& LogHandler.init(env)
Expand Down Expand Up @@ -324,6 +328,8 @@ namespace jni
LinkLayerConfig.cleanup(env);
LinkLayerStatistics.cleanup(env);
LinkStatistics.cleanup(env);
LinkStatus.cleanup(env);
LinkStatusListener.cleanup(env);
List.cleanup(env);
LogEntry.cleanup(env);
LogHandler.cleanup(env);
Expand Down
4 changes: 4 additions & 0 deletions java/cpp/jni/JCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@
#include "JNILinkLayerConfig.h"
#include "JNILinkLayerStatistics.h"
#include "JNILinkStatistics.h"
#include "JNILinkStatus.h"
#include "JNILinkStatusListener.h"
#include "JNIList.h"
#include "JNILogEntry.h"
#include "JNILogHandler.h"
Expand Down Expand Up @@ -217,6 +219,8 @@ namespace jni
static cache::LinkLayerConfig LinkLayerConfig;
static cache::LinkLayerStatistics LinkLayerStatistics;
static cache::LinkStatistics LinkStatistics;
static cache::LinkStatus LinkStatus;
static cache::LinkStatusListener LinkStatusListener;
static cache::List List;
static cache::LogEntry LogEntry;
static cache::LogHandler LogHandler;
Expand Down
20 changes: 10 additions & 10 deletions java/cpp/jni/JNICommandHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,19 +48,19 @@ namespace jni
this->method1 = env->GetMethodID(this->clazz, "end", "()V");
if(!this->method1) return false;

this->method2 = env->GetMethodID(this->clazz, "operate", "(Lcom/automatak/dnp3/AnalogOutputInt16;ILcom/automatak/dnp3/Database;Lcom/automatak/dnp3/enums/OperateType;)Lcom/automatak/dnp3/enums/CommandStatus;");
this->method2 = env->GetMethodID(this->clazz, "operate", "(Lcom/automatak/dnp3/AnalogOutputDouble64;ILcom/automatak/dnp3/Database;Lcom/automatak/dnp3/enums/OperateType;)Lcom/automatak/dnp3/enums/CommandStatus;");
if(!this->method2) return false;

this->method3 = env->GetMethodID(this->clazz, "operate", "(Lcom/automatak/dnp3/AnalogOutputInt32;ILcom/automatak/dnp3/Database;Lcom/automatak/dnp3/enums/OperateType;)Lcom/automatak/dnp3/enums/CommandStatus;");
this->method3 = env->GetMethodID(this->clazz, "operate", "(Lcom/automatak/dnp3/AnalogOutputFloat32;ILcom/automatak/dnp3/Database;Lcom/automatak/dnp3/enums/OperateType;)Lcom/automatak/dnp3/enums/CommandStatus;");
if(!this->method3) return false;

this->method4 = env->GetMethodID(this->clazz, "operate", "(Lcom/automatak/dnp3/AnalogOutputFloat32;ILcom/automatak/dnp3/Database;Lcom/automatak/dnp3/enums/OperateType;)Lcom/automatak/dnp3/enums/CommandStatus;");
this->method4 = env->GetMethodID(this->clazz, "operate", "(Lcom/automatak/dnp3/AnalogOutputInt16;ILcom/automatak/dnp3/Database;Lcom/automatak/dnp3/enums/OperateType;)Lcom/automatak/dnp3/enums/CommandStatus;");
if(!this->method4) return false;

this->method5 = env->GetMethodID(this->clazz, "operate", "(Lcom/automatak/dnp3/ControlRelayOutputBlock;ILcom/automatak/dnp3/Database;Lcom/automatak/dnp3/enums/OperateType;)Lcom/automatak/dnp3/enums/CommandStatus;");
this->method5 = env->GetMethodID(this->clazz, "operate", "(Lcom/automatak/dnp3/AnalogOutputInt32;ILcom/automatak/dnp3/Database;Lcom/automatak/dnp3/enums/OperateType;)Lcom/automatak/dnp3/enums/CommandStatus;");
if(!this->method5) return false;

this->method6 = env->GetMethodID(this->clazz, "operate", "(Lcom/automatak/dnp3/AnalogOutputDouble64;ILcom/automatak/dnp3/Database;Lcom/automatak/dnp3/enums/OperateType;)Lcom/automatak/dnp3/enums/CommandStatus;");
this->method6 = env->GetMethodID(this->clazz, "operate", "(Lcom/automatak/dnp3/ControlRelayOutputBlock;ILcom/automatak/dnp3/Database;Lcom/automatak/dnp3/enums/OperateType;)Lcom/automatak/dnp3/enums/CommandStatus;");
if(!this->method6) return false;

this->method7 = env->GetMethodID(this->clazz, "select", "(Lcom/automatak/dnp3/AnalogOutputInt32;I)Lcom/automatak/dnp3/enums/CommandStatus;");
Expand Down Expand Up @@ -96,27 +96,27 @@ namespace jni
env->CallVoidMethod(instance, this->method1);
}

LocalRef<JCommandStatus> CommandHandler::operate(JNIEnv* env, JCommandHandler instance, JAnalogOutputInt16 arg0, jint arg1, JDatabase arg2, JOperateType arg3)
LocalRef<JCommandStatus> CommandHandler::operate(JNIEnv* env, JCommandHandler instance, JAnalogOutputDouble64 arg0, jint arg1, JDatabase arg2, JOperateType arg3)
{
return LocalRef<JCommandStatus>(env, env->CallObjectMethod(instance, this->method2, arg0, arg1, arg2, arg3));
}

LocalRef<JCommandStatus> CommandHandler::operate(JNIEnv* env, JCommandHandler instance, JAnalogOutputInt32 arg0, jint arg1, JDatabase arg2, JOperateType arg3)
LocalRef<JCommandStatus> CommandHandler::operate(JNIEnv* env, JCommandHandler instance, JAnalogOutputFloat32 arg0, jint arg1, JDatabase arg2, JOperateType arg3)
{
return LocalRef<JCommandStatus>(env, env->CallObjectMethod(instance, this->method3, arg0, arg1, arg2, arg3));
}

LocalRef<JCommandStatus> CommandHandler::operate(JNIEnv* env, JCommandHandler instance, JAnalogOutputFloat32 arg0, jint arg1, JDatabase arg2, JOperateType arg3)
LocalRef<JCommandStatus> CommandHandler::operate(JNIEnv* env, JCommandHandler instance, JAnalogOutputInt16 arg0, jint arg1, JDatabase arg2, JOperateType arg3)
{
return LocalRef<JCommandStatus>(env, env->CallObjectMethod(instance, this->method4, arg0, arg1, arg2, arg3));
}

LocalRef<JCommandStatus> CommandHandler::operate(JNIEnv* env, JCommandHandler instance, JControlRelayOutputBlock arg0, jint arg1, JDatabase arg2, JOperateType arg3)
LocalRef<JCommandStatus> CommandHandler::operate(JNIEnv* env, JCommandHandler instance, JAnalogOutputInt32 arg0, jint arg1, JDatabase arg2, JOperateType arg3)
{
return LocalRef<JCommandStatus>(env, env->CallObjectMethod(instance, this->method5, arg0, arg1, arg2, arg3));
}

LocalRef<JCommandStatus> CommandHandler::operate(JNIEnv* env, JCommandHandler instance, JAnalogOutputDouble64 arg0, jint arg1, JDatabase arg2, JOperateType arg3)
LocalRef<JCommandStatus> CommandHandler::operate(JNIEnv* env, JCommandHandler instance, JControlRelayOutputBlock arg0, jint arg1, JDatabase arg2, JOperateType arg3)
{
return LocalRef<JCommandStatus>(env, env->CallObjectMethod(instance, this->method6, arg0, arg1, arg2, arg3));
}
Expand Down
4 changes: 2 additions & 2 deletions java/cpp/jni/JNICommandHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ namespace jni
// methods
void begin(JNIEnv* env, JCommandHandler instance);
void end(JNIEnv* env, JCommandHandler instance);
LocalRef<JCommandStatus> operate(JNIEnv* env, JCommandHandler instance, JAnalogOutputDouble64 arg0, jint arg1, JDatabase arg2, JOperateType arg3);
LocalRef<JCommandStatus> operate(JNIEnv* env, JCommandHandler instance, JAnalogOutputFloat32 arg0, jint arg1, JDatabase arg2, JOperateType arg3);
LocalRef<JCommandStatus> operate(JNIEnv* env, JCommandHandler instance, JAnalogOutputInt16 arg0, jint arg1, JDatabase arg2, JOperateType arg3);
LocalRef<JCommandStatus> operate(JNIEnv* env, JCommandHandler instance, JAnalogOutputInt32 arg0, jint arg1, JDatabase arg2, JOperateType arg3);
LocalRef<JCommandStatus> operate(JNIEnv* env, JCommandHandler instance, JAnalogOutputFloat32 arg0, jint arg1, JDatabase arg2, JOperateType arg3);
LocalRef<JCommandStatus> operate(JNIEnv* env, JCommandHandler instance, JControlRelayOutputBlock arg0, jint arg1, JDatabase arg2, JOperateType arg3);
LocalRef<JCommandStatus> operate(JNIEnv* env, JCommandHandler instance, JAnalogOutputDouble64 arg0, jint arg1, JDatabase arg2, JOperateType arg3);
LocalRef<JCommandStatus> select(JNIEnv* env, JCommandHandler instance, JAnalogOutputInt32 arg0, jint arg1);
LocalRef<JCommandStatus> select(JNIEnv* env, JCommandHandler instance, JAnalogOutputInt16 arg0, jint arg1);
LocalRef<JCommandStatus> select(JNIEnv* env, JCommandHandler instance, JAnalogOutputFloat32 arg0, jint arg1);
Expand Down

0 comments on commit c4d8210

Please sign in to comment.