summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--trial/direct_bt/dbt_client01.hpp7
-rw-r--r--trial/direct_bt/dbt_client_server1x.hpp42
-rw-r--r--trial/direct_bt/dbt_server01.hpp6
-rw-r--r--trial/direct_bt/test_client_server40_reset.cpp84
-rw-r--r--trial/java/trial/org/direct_bt/DBTClient01.java7
-rw-r--r--trial/java/trial/org/direct_bt/DBTClientServer1x.java42
-rw-r--r--trial/java/trial/org/direct_bt/DBTServer01.java7
-rw-r--r--trial/java/trial/org/direct_bt/TestDBTClientServer40_Reset.java84
8 files changed, 275 insertions, 4 deletions
diff --git a/trial/direct_bt/dbt_client01.hpp b/trial/direct_bt/dbt_client01.hpp
index 80f76ed9..a5083329 100644
--- a/trial/direct_bt/dbt_client01.hpp
+++ b/trial/direct_bt/dbt_client01.hpp
@@ -83,6 +83,13 @@ class DBTClient01 : public DBTClientTest {
} else {
fprintf_td(stderr, "****** Client SETTINGS_CHANGED: %s -> %s, changed %s\n", to_string(oldmask).c_str(),
to_string(newmask).c_str(), to_string(changedmask).c_str());
+
+ const bool justPoweredOn = isAdapterSettingBitSet(changedmask, AdapterSetting::POWERED) &&
+ isAdapterSettingBitSet(newmask, AdapterSetting::POWERED);
+ if( justPoweredOn && DiscoveryPolicy::AUTO_OFF != parent.discoveryPolicy && *parent.clientAdapter == a ) {
+ std::thread dc(&DBTClient01::startDiscovery, &parent, "powered_on"); // @suppress("Invalid arguments")
+ dc.detach();
+ }
}
fprintf_td(stderr, "Client Status BTAdapter:\n");
fprintf_td(stderr, "%s\n", a.toString().c_str());
diff --git a/trial/direct_bt/dbt_client_server1x.hpp b/trial/direct_bt/dbt_client_server1x.hpp
index 3274b30f..4d6b4523 100644
--- a/trial/direct_bt/dbt_client_server1x.hpp
+++ b/trial/direct_bt/dbt_client_server1x.hpp
@@ -57,8 +57,17 @@ class DBTClientServer1x {
PairingMode lastCompletedDevicePairingMode = PairingMode::NONE;
BTSecurityLevel lastCompletedDeviceSecurityLevel = BTSecurityLevel::NONE;
EInfoReport lastCompletedDeviceEIR;
+ int client_power_down_count = 0;
+ int client_power_up_count = 0;
+ bool client_reset_at_ready = false;
+ bool server_reset_at_ready = false;
+ bool client_reset_test = false;
+ bool server_reset_test = false;
public:
+ void set_client_reset_at_ready(const bool v) noexcept { client_reset_at_ready = v; client_reset_test = v; }
+ void set_server_reset_at_ready(const bool v) noexcept { server_reset_at_ready = v; server_reset_test = v; }
+
void test8x_fullCycle(const std::string& suffix, const int protocolSessionCount, const bool server_client_order,
const bool serverSC, const BTSecurityLevel secLevelServer, const ExpectedPairing serverExpPairing,
const BTSecurityLevel secLevelClient, const ExpectedPairing clientExpPairing)
@@ -127,6 +136,21 @@ class DBTClientServer1x {
public:
MyAdapterStatusListener(DBTClientServer1x& p) : parent(p) {}
+ void adapterSettingsChanged(BTAdapter &a, const AdapterSetting oldmask, const AdapterSetting newmask,
+ const AdapterSetting changedmask, const uint64_t timestamp) override {
+ const bool initialSetting = AdapterSetting::NONE == oldmask;
+ if( !initialSetting && isAdapterSettingBitSet(changedmask, AdapterSetting::POWERED) ) {
+ const std::lock_guard<std::mutex> lock(parent.mtx_sync); // RAII-style acquire and relinquish via destructor
+ if( isAdapterSettingBitSet(newmask, AdapterSetting::POWERED) ) {
+ ++parent.client_power_up_count;
+ } else {
+ ++parent.client_power_down_count;
+ }
+ }
+ (void)timestamp;
+ (void)a;
+ }
+
void deviceReady(BTDeviceRef device, const uint64_t timestamp) override {
(void)timestamp;
const std::lock_guard<std::mutex> lock(parent.mtx_sync); // RAII-style acquire and relinquish via destructor
@@ -135,6 +159,12 @@ class DBTClientServer1x {
parent.lastCompletedDeviceSecurityLevel = device->getConnSecurityLevel();
parent.lastCompletedDeviceEIR = *device->getEIR();
fprintf_td(stderr, "XXXXXX Client Ready: %s\n", device->toString(true).c_str());
+ if( parent.client_reset_at_ready ) {
+ parent.client_reset_at_ready = false;
+ fprintf_td(stderr, "XXXXXX Client Reset.0: %s\n", device->toString(true).c_str());
+ const HCIStatusCode rr = device->getAdapter().reset();
+ fprintf_td(stderr, "XXXXXX Client Reset.X: %s: %s\n", direct_bt::to_string(rr).c_str(), device->toString(true).c_str());
+ }
}
std::string toString() const noexcept override { return "DBTClientServer1x::Client"; }
@@ -184,9 +214,10 @@ class DBTClientServer1x {
fprintf_td(stderr, " Server ProtocolSessions[success %d/%d total, requested %d], disconnects %d of %d max\n",
server->getProtocolSessionsDoneSuccess(), server->getProtocolSessionsDoneTotal(), protocolSessionCount,
server->getDisconnectCount(), ( protocolSessionCount * max_connections_per_session ));
- fprintf_td(stderr, " Client ProtocolSessions[success %d/%d total, requested %d], disconnects %d of %d max\n",
+ fprintf_td(stderr, " Client ProtocolSessions[success %d/%d total, requested %d], disconnects %d of %d max, power[down %d, up %d]\n",
client->getProtocolSessionsDoneSuccess(), client->getProtocolSessionsDoneTotal(), protocolSessionCount,
- client->getDisconnectCount(), ( protocolSessionCount * max_connections_per_session ));
+ client->getDisconnectCount(), ( protocolSessionCount * max_connections_per_session ),
+ client_power_down_count, client_power_up_count);
fprintf_td(stderr, "\n\n");
if( expSuccess ) {
@@ -202,6 +233,13 @@ class DBTClientServer1x {
REQUIRE( EIRDataType::NONE != lastCompletedDeviceEIR.getEIRDataMask() );
REQUIRE( false == lastCompletedDevice->getConnected() );
REQUIRE( ( protocolSessionCount * max_connections_per_session ) > server->getDisconnectCount() );
+ if( client_reset_test ) {
+ REQUIRE( 1 == client_power_down_count );
+ REQUIRE( 1 == client_power_up_count );
+ } else {
+ REQUIRE( 0 == client_power_down_count );
+ REQUIRE( 0 == client_power_up_count );
+ }
}
}
diff --git a/trial/direct_bt/dbt_server01.hpp b/trial/direct_bt/dbt_server01.hpp
index ebe108dd..11a3d027 100644
--- a/trial/direct_bt/dbt_server01.hpp
+++ b/trial/direct_bt/dbt_server01.hpp
@@ -191,6 +191,12 @@ class DBTServer01 : public DBTServerTest {
} else {
fprintf_td(stderr, "****** Server SETTINGS_CHANGED: %s -> %s, changed %s\n", to_string(oldmask).c_str(),
to_string(newmask).c_str(), to_string(changedmask).c_str());
+
+ const bool justPoweredOn = isAdapterSettingBitSet(changedmask, AdapterSetting::POWERED) &&
+ isAdapterSettingBitSet(newmask, AdapterSetting::POWERED);
+ if( justPoweredOn && *parent.serverAdapter == a ) {
+ parent.startAdvertising("powered_on");
+ }
}
fprintf_td(stderr, "Server Status BTAdapter:\n");
fprintf_td(stderr, "%s\n", a.toString().c_str());
diff --git a/trial/direct_bt/test_client_server40_reset.cpp b/trial/direct_bt/test_client_server40_reset.cpp
new file mode 100644
index 00000000..6746ae5a
--- /dev/null
+++ b/trial/direct_bt/test_client_server40_reset.cpp
@@ -0,0 +1,84 @@
+/**
+ * Author: Sven Gothel <[email protected]>
+ * Copyright (c) 2022 Gothel Software e.K.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <jau/test/catch2_ext.hpp>
+
+#include "dbt_client_server1x.hpp"
+
+using namespace direct_bt;
+
+/**
+ * Testing a full Bluetooth server and client lifecycle of operations including adapter reset, requiring two BT adapter:
+ * - trigger client adapter reset
+ * - operating w/o encryption
+ * - start server advertising
+ * - start client discovery and connect to server when discovered
+ * - client/server processing of connection when ready
+ * - client disconnect
+ * - server stop advertising
+ * - security-level: NONE, ENC_ONLY freshly-paired and ENC_ONLY pre-paired
+ * - reuse server-adapter for client-mode discovery (just toggle on/off)
+ */
+class TestDBTClientServer40_Reset : public DBTClientServer1x {
+ private:
+ static constexpr const bool serverSC = true;
+
+ public:
+ void test40_ClientReset01() {
+ base_test_framework.setupTest( 20_s );
+ {
+ const std::string suffix = "40";
+ const int protocolSessionCount = 1;
+ const int max_connections_per_session = DBTConstants::max_connections_per_session;
+ const bool expSuccess = true;
+ const bool server_client_order = true;
+ const BTSecurityLevel secLevelServer = BTSecurityLevel::NONE;
+ const BTSecurityLevel secLevelClient = BTSecurityLevel::NONE;
+ const ExpectedPairing serverExpPairing = ExpectedPairing::DONT_CARE;
+ const ExpectedPairing clientExpPairing = ExpectedPairing::DONT_CARE;
+
+ std::shared_ptr<DBTServerTest> server = std::make_shared<DBTServer01>("S-"+suffix, EUI48::ALL_DEVICE, BTMode::DUAL, serverSC, secLevelServer);
+ std::shared_ptr<DBTClientTest> client = std::make_shared<DBTClient01>("C-"+suffix, EUI48::ALL_DEVICE, BTMode::DUAL);
+
+ server->setProtocolSessionsLeft( protocolSessionCount );
+
+ client->setProtocolSessionsLeft( protocolSessionCount );
+ client->setDisconnectDevice( true ); // default, auto-disconnect after work is done
+ client->setRemoveDevice( false ); // default, test side-effects
+ client->setDiscoveryPolicy( DiscoveryPolicy::PAUSE_CONNECTED_UNTIL_DISCONNECTED );
+
+ set_client_reset_at_ready(true);
+
+ test8x_fullCycle(suffix,
+ max_connections_per_session, expSuccess,
+ server_client_order,
+ server, secLevelServer, serverExpPairing,
+ client, secLevelClient, clientExpPairing);
+ }
+ base_test_framework.cleanupTest();
+ }
+
+};
+
+METHOD_AS_TEST_CASE( TestDBTClientServer40_Reset::test40_ClientReset01, "ClientServer 40 Reset Trial", "[trial][serverclient][reset]");
diff --git a/trial/java/trial/org/direct_bt/DBTClient01.java b/trial/java/trial/org/direct_bt/DBTClient01.java
index 473c5fa3..a37df5c7 100644
--- a/trial/java/trial/org/direct_bt/DBTClient01.java
+++ b/trial/java/trial/org/direct_bt/DBTClient01.java
@@ -178,6 +178,13 @@ public class DBTClient01 implements DBTClientTest {
PrintUtil.println(System.err, "****** Client SETTINGS_INITIAL: "+oldmask+" -> "+newmask+", changed "+changedmask);
} else {
PrintUtil.println(System.err, "****** Client SETTINGS_CHANGED: "+oldmask+" -> "+newmask+", changed "+changedmask);
+
+ final boolean justPoweredOn = changedmask.isSet(AdapterSettings.SettingType.POWERED) &&
+ newmask.isSet(AdapterSettings.SettingType.POWERED);
+ if( justPoweredOn && DiscoveryPolicy.AUTO_OFF != discoveryPolicy && clientAdapter.equals(adapter) ) {
+ executeOffThread( () -> { startDiscovery("powered_on"); },
+ "Client DBT-StartDiscovery-"+adapter.getAddressAndType(), true /* detach */);
+ }
}
PrintUtil.println(System.err, "Client Status Adapter:");
PrintUtil.println(System.err, adapter.toString());
diff --git a/trial/java/trial/org/direct_bt/DBTClientServer1x.java b/trial/java/trial/org/direct_bt/DBTClientServer1x.java
index 3dfa48b2..c7845f39 100644
--- a/trial/java/trial/org/direct_bt/DBTClientServer1x.java
+++ b/trial/java/trial/org/direct_bt/DBTClientServer1x.java
@@ -69,6 +69,15 @@ public abstract class DBTClientServer1x extends BaseDBTClientServer {
PairingMode lastCompletedDevicePairingMode = PairingMode.NONE;
BTSecurityLevel lastCompletedDeviceSecurityLevel = BTSecurityLevel.NONE;
EInfoReport lastCompletedDeviceEIR = null;
+ int client_power_down_count = 0;
+ int client_power_up_count = 0;
+ boolean client_reset_at_ready = false;
+ boolean server_reset_at_ready = false;
+ boolean client_reset_test = false;
+ boolean server_reset_test = false;
+
+ final void set_client_reset_at_ready(final boolean v) { client_reset_at_ready = v; client_reset_test = v; }
+ final void set_server_reset_at_ready(final boolean v) { server_reset_at_ready = v; server_reset_test = v; }
final void test8x_fullCycle(final long timeout_value,
final String suffix, final int protocolSessionCount, final boolean server_client_order,
@@ -137,6 +146,21 @@ public abstract class DBTClientServer1x extends BaseDBTClientServer {
}
final AdapterStatusListener clientAdapterStatusListener = new AdapterStatusListener() {
@Override
+ public void adapterSettingsChanged(final BTAdapter adapter, final AdapterSettings oldmask,
+ final AdapterSettings newmask, final AdapterSettings changedmask, final long timestamp) {
+ final boolean initialSetting = oldmask.isEmpty();
+ if( !initialSetting && changedmask.isSet(AdapterSettings.SettingType.POWERED) ) {
+ synchronized( mtx_sync ) {
+ if( newmask.isSet(AdapterSettings.SettingType.POWERED) ) {
+ ++client_power_up_count;
+ } else {
+ ++client_power_down_count;
+ }
+ }
+ }
+ }
+
+ @Override
public void deviceReady(final BTDevice device, final long timestamp) {
synchronized( mtx_sync ) {
lastCompletedDevice = device;
@@ -144,6 +168,12 @@ public abstract class DBTClientServer1x extends BaseDBTClientServer {
lastCompletedDeviceSecurityLevel = device.getConnSecurityLevel();
lastCompletedDeviceEIR = device.getEIR().clone();
PrintUtil.println(System.err, "XXXXXX Client Ready: "+device);
+ if( client_reset_at_ready ) {
+ client_reset_at_ready = false;
+ PrintUtil.fprintf_td(System.err, "XXXXXX Client Reset.0: %s\n", device.toString());
+ final HCIStatusCode rr = device.getAdapter().reset();
+ PrintUtil.fprintf_td(System.err, "XXXXXX Client Reset.X: %s: %s\n", rr.toString(), device.toString());
+ }
}
}
};
@@ -187,9 +217,10 @@ public abstract class DBTClientServer1x extends BaseDBTClientServer {
PrintUtil.fprintf_td(System.err, " Server ProtocolSessions[success %d/%d total, requested %d], disconnects %d of %d max\n",
server.getProtocolSessionsDoneSuccess(), server.getProtocolSessionsDoneTotal(), protocolSessionCount,
server.getDisconnectCount(), ( protocolSessionCount * max_connections_per_session ));
- PrintUtil.fprintf_td(System.err, " Client ProtocolSessions[success %d/%d total, requested %d], disconnects %d of %d max\n",
+ PrintUtil.fprintf_td(System.err, " Client ProtocolSessions[success %d/%d total, requested %d], disconnects %d of %d max, power[down %d, up %d]\n",
client.getProtocolSessionsDoneSuccess(), client.getProtocolSessionsDoneTotal(), protocolSessionCount,
- client.getDisconnectCount(), ( protocolSessionCount * max_connections_per_session ));
+ client.getDisconnectCount(), ( protocolSessionCount * max_connections_per_session ),
+ client_power_down_count, client_power_up_count);
PrintUtil.fprintf_td(System.err, "\n\n");
if( expSuccess ) {
@@ -205,6 +236,13 @@ public abstract class DBTClientServer1x extends BaseDBTClientServer {
Assert.assertNotNull(lastCompletedDeviceEIR);
Assert.assertFalse(lastCompletedDevice.getConnected());
Assert.assertTrue( ( 1 * max_connections_per_session ) > server.getDisconnectCount() );
+ if( client_reset_test ) {
+ Assert.assertEquals( 1, client_power_down_count );
+ Assert.assertEquals( 1, client_power_up_count );
+ } else {
+ Assert.assertEquals( 0, client_power_down_count );
+ Assert.assertEquals( 0, client_power_up_count );
+ }
}
}
diff --git a/trial/java/trial/org/direct_bt/DBTServer01.java b/trial/java/trial/org/direct_bt/DBTServer01.java
index b17c6465..e3cbf591 100644
--- a/trial/java/trial/org/direct_bt/DBTServer01.java
+++ b/trial/java/trial/org/direct_bt/DBTServer01.java
@@ -275,6 +275,13 @@ public class DBTServer01 implements DBTServerTest {
PrintUtil.println(System.err, "****** Server SETTINGS_INITIAL: "+oldmask+" -> "+newmask+", changed "+changedmask);
} else {
PrintUtil.println(System.err, "****** Server SETTINGS_CHANGED: "+oldmask+" -> "+newmask+", changed "+changedmask);
+
+ final boolean justPoweredOn = changedmask.isSet(AdapterSettings.SettingType.POWERED) &&
+ newmask.isSet(AdapterSettings.SettingType.POWERED);
+ if( justPoweredOn && serverAdapter.equals(adapter) ) {
+ executeOffThread( () -> { startAdvertising("powered_on"); },
+ "Server DBT-StartAdvertising-"+adapter.getAddressAndType(), true /* detach */);
+ }
}
PrintUtil.println(System.err, "Server Status Adapter:");
PrintUtil.println(System.err, adapter.toString());
diff --git a/trial/java/trial/org/direct_bt/TestDBTClientServer40_Reset.java b/trial/java/trial/org/direct_bt/TestDBTClientServer40_Reset.java
new file mode 100644
index 00000000..f0beefe1
--- /dev/null
+++ b/trial/java/trial/org/direct_bt/TestDBTClientServer40_Reset.java
@@ -0,0 +1,84 @@
+/**
+ * Author: Sven Gothel <[email protected]>
+ * Copyright (c) 2022 Gothel Software e.K.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package trial.org.direct_bt;
+
+import org.direct_bt.BTMode;
+import org.direct_bt.BTSecurityLevel;
+import org.direct_bt.DiscoveryPolicy;
+import org.jau.net.EUI48;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+/**
+ * Testing a full Bluetooth server and client lifecycle of operations including adapter reset, requiring two BT adapter:
+ * - trigger client adapter reset
+ * - operating w/o encryption
+ * - start server advertising
+ * - start client discovery and connect to server when discovered
+ * - client/server processing of connection when ready
+ * - client disconnect
+ * - server stop advertising
+ * - security-level: NONE, ENC_ONLY freshly-paired and ENC_ONLY pre-paired
+ * - reuse server-adapter for client-mode discovery (just toggle on/off)
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestDBTClientServer40_Reset extends DBTClientServer1x {
+ static final boolean serverSC = true;
+
+ @Test(timeout = 20000)
+ public final void test40_ClientReset01() {
+ final String suffix = "40";
+ final int protocolSessionCount = 1;
+ final int max_connections_per_session = DBTConstants.max_connections_per_session;
+ final boolean expSuccess = true;
+ final boolean server_client_order = true;
+ final BTSecurityLevel secLevelServer = BTSecurityLevel.NONE;
+ final BTSecurityLevel secLevelClient = BTSecurityLevel.NONE;
+ final ExpectedPairing serverExpPairing = ExpectedPairing.DONT_CARE;
+ final ExpectedPairing clientExpPairing = ExpectedPairing.DONT_CARE;
+
+ final DBTServerTest server = new DBTServer01("S-"+suffix, EUI48.ALL_DEVICE, BTMode.DUAL, serverSC, secLevelServer);
+ final DBTClientTest client = new DBTClient01("C-"+suffix, EUI48.ALL_DEVICE, BTMode.DUAL);
+
+ server.setProtocolSessionsLeft( protocolSessionCount );
+
+ client.setProtocolSessionsLeft( protocolSessionCount );
+ client.setDisconnectDeviceed( true ); // default, auto-disconnect after work is done
+ client.setRemoveDevice( false ); // default, test side-effects
+ client.setDiscoveryPolicy( DiscoveryPolicy.PAUSE_CONNECTED_UNTIL_DISCONNECTED );
+
+ set_client_reset_at_ready(true);
+
+ test8x_fullCycle(20000, suffix,
+ max_connections_per_session, expSuccess, server_client_order,
+ server, secLevelServer, serverExpPairing,
+ client, secLevelClient, clientExpPairing);
+ }
+
+ public static void main(final String args[]) {
+ org.junit.runner.JUnitCore.main(TestDBTClientServer40_Reset.class.getName());
+ }
+}