Skip to content

Commit

Permalink
add java pairing test (#23714)
Browse files Browse the repository at this point in the history
  • Loading branch information
yunhanw-google authored and pull[bot] committed Jun 22, 2023
1 parent ba9c553 commit 1096536
Show file tree
Hide file tree
Showing 10 changed files with 255 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -113,5 +113,6 @@ public static void main(String[] args) {
} catch (Exception e) {
System.out.println("Run command failed with exception: " + e.getMessage());
}
controller.shutdownCommissioning();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,21 @@ public void setValue(String value) {
String str = (String) mValue;
isValidArgument = value.equals(str);
break;
case NUMBER_INT16:
AtomicInteger numShort = (AtomicInteger) mValue;
numShort.set(Integer.parseInt(value));
isValidArgument = (numShort.intValue() >= mMin && numShort.intValue() <= mMax);
break;
case NUMBER_INT32:
AtomicInteger num = (AtomicInteger) mValue;
num.set(Integer.parseInt(value));
isValidArgument = (num.intValue() >= mMin && num.intValue() <= mMax);
break;
case NUMBER_INT64:
AtomicLong numLong = (AtomicLong) mValue;
numLong.set(Long.parseLong(value));
isValidArgument = (numLong.intValue() >= mMin && numLong.intValue() <= mMax);
break;
case ADDRESS:
try {
IPAddress ipAddress = (IPAddress) mValue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,11 @@ public final void run(String[] args) {
}
}

String[] temp = Arrays.copyOfRange(args, 1, args.length);
// need skip over binary and command name and only get arguments
String[] temp = Arrays.copyOfRange(args, 2, args.length);

try {
command.initArguments(args.length - 1, temp);
command.initArguments(temp.length, temp);
command.run();
} catch (IllegalArgumentException e) {
System.out.println("Arguments init failed with exception: " + e.getMessage());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,8 @@ public void setAddress(InetAddress address) {
public String toString() {
return address.toString();
}

public String getHostAddress() {
return address.getHostAddress();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public abstract class MatterCommand extends Command {
private final AtomicLong mCommissionerNodeId = new AtomicLong();
private final AtomicBoolean mUseMaxSizedCerts = new AtomicBoolean();;
private final AtomicBoolean mOnlyAllowTrustedCdKeys = new AtomicBoolean();;
private Optional<String> mTestResult = Optional.empty();

public MatterCommand(
ChipDeviceController controller, String commandName, CredentialsIssuer credIssuerCmds) {
Expand All @@ -56,6 +57,8 @@ public MatterCommand(
this.mCredIssuerCmds = Optional.ofNullable(credIssuerCmds);
this.mChipDeviceController = controller;

// TODO: Add support to enable the below optional arguments
/*
addArgument(
"paa-trust-store-path",
mPaaTrustStorePath,
Expand Down Expand Up @@ -87,6 +90,7 @@ public MatterCommand(
mOnlyAllowTrustedCdKeys,
"Only allow trusted CD verifying keys (disallow test keys). If not provided or 0 (\"false\"), untrusted CD "
+ "verifying keys are allowed. If 1 (\"true\"), test keys are disallowed.");
*/
}

// This method returns the commissioner instance to be used for running the command.
Expand All @@ -97,9 +101,10 @@ public ChipDeviceController currentCommissioner() {
/////////// Command Interface /////////
@Override
public void run() throws Exception {
maybeSetUpStack();
// TODO: setup chip storage from Java, currently it is using example one from chip-tool
// maybeSetUpStack();
runCommand();
maybeTearDownStack();
// maybeTearDownStack();
}

protected abstract void runCommand();
Expand All @@ -113,4 +118,40 @@ private void maybeSetUpStack() throws Exception {
private void maybeTearDownStack() {
// ToDo:We need to call DeviceController::Shutdown()
}

public void setTestResult(String result) {
mTestResult = Optional.of(result);
}

public void expectSuccess(long timeout) {
expectResult("Success", timeout);
}

private void expectResult(String expectedResult, long timeout) {
long start = System.currentTimeMillis();
while (!mTestResult.isPresent())
try {
if (System.currentTimeMillis() > (start + timeout)) {
throw new RuntimeException("timeout!");
}
Thread.sleep(100);
} catch (InterruptedException ex) {
}

if (!mTestResult.isPresent()) {
throw new RuntimeException("received empty test result");
}

if (!mTestResult.get().equals(expectedResult)) {
if (!expectedResult.equals("Success")) {
System.out.format(
"%s command failed:%n Expected: %s%n Got: %s%n",
getName(), expectedResult, mTestResult);
throw new RuntimeException(getName());
} else {
System.out.format("%s command failed: %s%n", getName(), mTestResult.get());
}
}
mTestResult = Optional.empty();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import com.matter.controller.commands.common.CredentialsIssuer;

public final class PairOnNetworkLongCommand extends PairingCommand {
private static final int MATTER_PORT = 5540;

public PairOnNetworkLongCommand(ChipDeviceController controller, CredentialsIssuer credsIssue) {
super(
controller,
Expand All @@ -15,5 +17,16 @@ public PairOnNetworkLongCommand(ChipDeviceController controller, CredentialsIssu
}

@Override
protected void runCommand() {}
protected void runCommand() {
currentCommissioner()
.pairDeviceWithAddress(
getNodeId(),
getRemoteAddr().getHostAddress(),
MATTER_PORT,
getDiscriminator(),
getSetupPINCode(),
null);
currentCommissioner().setCompletionListener(this);
expectSuccess(getTimeoutMillis());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,15 @@
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

public abstract class PairingCommand extends MatterCommand {
public abstract class PairingCommand extends MatterCommand
implements ChipDeviceController.CompletionListener {
private PairingModeType mPairingMode = PairingModeType.NONE;
private PairingNetworkType mNetworkType = PairingNetworkType.NONE;
private DiscoveryFilterType mFilterType = DiscoveryFilterType.NONE;
private final IPAddress mRemoteAddr;
private final AtomicLong mNodeId = new AtomicLong();
private final AtomicLong mDiscoveryFilterCode = new AtomicLong();
private final AtomicInteger mTimeout = new AtomicInteger();
private final AtomicLong mTimeoutMillis = new AtomicLong();
private final AtomicBoolean mDiscoverOnce = new AtomicBoolean();
private final AtomicBoolean mUseOnlyOnNetworkDiscovery = new AtomicBoolean();
private final AtomicInteger mRemotePort = new AtomicInteger();
Expand All @@ -47,6 +48,94 @@ public abstract class PairingCommand extends MatterCommand {
private final StringBuffer mOnboardingPayload = new StringBuffer();
private final StringBuffer mDiscoveryFilterInstanceName = new StringBuffer();

public long getNodeId() {
return mNodeId.get();
}

public int getSetupPINCode() {
return mSetupPINCode.get();
}

public int getDiscriminator() {
return mDiscriminator.get();
}

public long getTimeoutMillis() {
return mTimeoutMillis.get();
}

@Override
public void onConnectDeviceComplete() {
System.out.println("onConnectDeviceComplete");
}

@Override
public void onStatusUpdate(int status) {
System.out.println("onStatusUpdate with status: " + status);
}

@Override
public void onPairingComplete(int errorCode) {
System.out.println("onPairingComplete with error code: " + errorCode);
if (errorCode != 0) {
setTestResult("Failure");
}
}

@Override
public void onPairingDeleted(int errorCode) {
System.out.println("onPairingDeleted with error code: " + errorCode);
}

@Override
public void onCommissioningComplete(long nodeId, int errorCode) {
System.out.println("onCommissioningComplete with error code: " + errorCode);
if (errorCode == 0) {
setTestResult("Success");
} else {
setTestResult("Failure");
}
}

@Override
public void onReadCommissioningInfo(
int vendorId, int productId, int wifiEndpointId, int threadEndpointId) {
System.out.println("onReadCommissioningInfo");
}

@Override
public void onCommissioningStatusUpdate(long nodeId, String stage, int errorCode) {
System.out.println("onCommissioningStatusUpdate");
}

@Override
public void onNotifyChipConnectionClosed() {
System.out.println("onNotifyChipConnectionClosed");
}

@Override
public void onCloseBleComplete() {
System.out.println("onCloseBleComplete");
}

@Override
public void onError(Throwable error) {
setTestResult(error.toString());
System.out.println("onError with error: " + error.toString());
}

@Override
public void onOpCSRGenerationComplete(byte[] csr) {
System.out.println("onOpCSRGenerationComplete");
for (int i = 0; i < csr.length; i++) {
System.out.print(csr[i] + " ");
}
}

public IPAddress getRemoteAddr() {
return mRemoteAddr;
}

public PairingCommand(
ChipDeviceController controller,
String commandName,
Expand All @@ -69,7 +158,7 @@ public PairingCommand(
this.mFilterType = filterType;

try {
this.mRemoteAddr = new IPAddress(InetAddress.getByName("0.0.0.0"));
this.mRemoteAddr = new IPAddress(InetAddress.getByName("::1"));
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
Expand Down Expand Up @@ -147,6 +236,6 @@ public PairingCommand(
break;
}

addArgument("timeout", (short) 0, Short.MAX_VALUE, mTimeout, null);
addArgument("timeout", (long) 0, Long.MAX_VALUE, mTimeoutMillis, null);
}
}
31 changes: 27 additions & 4 deletions src/controller/java/AndroidDeviceControllerWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@
#include <lib/support/TestGroupData.h>
#include <lib/support/ThreadOperationalDataset.h>
#include <platform/KeyValueStoreManager.h>
#ifndef JAVA_MATTER_CONTROLLER_TEST
#include <platform/android/CHIPP256KeypairBridge.h>

#endif // JAVA_MATTER_CONTROLLER_TEST
using namespace chip;
using namespace chip::Controller;
using namespace chip::Credentials;
Expand All @@ -53,11 +54,13 @@ AndroidDeviceControllerWrapper::~AndroidDeviceControllerWrapper()
}
mController->Shutdown();

#ifndef JAVA_MATTER_CONTROLLER_TEST
if (mKeypairBridge != nullptr)
{
chip::Platform::Delete(mKeypairBridge);
mKeypairBridge = nullptr;
}
#endif // JAVA_MATTER_CONTROLLER_TEST
}

void AndroidDeviceControllerWrapper::SetJavaObjectRef(JavaVM * vm, jobject obj)
Expand All @@ -75,7 +78,12 @@ void AndroidDeviceControllerWrapper::CallJavaMethod(const char * methodName, jin
AndroidDeviceControllerWrapper * AndroidDeviceControllerWrapper::AllocateNew(
JavaVM * vm, jobject deviceControllerObj, chip::NodeId nodeId, chip::FabricId fabricId, const chip::CATValues & cats,
chip::System::Layer * systemLayer, chip::Inet::EndPointManager<Inet::TCPEndPoint> * tcpEndPointManager,
chip::Inet::EndPointManager<Inet::UDPEndPoint> * udpEndPointManager, AndroidOperationalCredentialsIssuerPtr opCredsIssuerPtr,
chip::Inet::EndPointManager<Inet::UDPEndPoint> * udpEndPointManager,
#ifdef JAVA_MATTER_CONTROLLER_TEST
ExampleOperationalCredentialsIssuerPtr opCredsIssuerPtr,
#else
AndroidOperationalCredentialsIssuerPtr opCredsIssuerPtr,
#endif
jobject keypairDelegate, jbyteArray rootCertificate, jbyteArray intermediateCertificate, jbyteArray nodeOperationalCertificate,
jbyteArray ipkEpochKey, uint16_t listenPort, uint16_t controllerVendorId, uint16_t failsafeTimerSeconds,
bool attemptNetworkScanWiFi, bool attemptNetworkScanThread, bool skipCommissioningComplete, CHIP_ERROR * errInfoOnFailure)
Expand Down Expand Up @@ -124,11 +132,22 @@ AndroidDeviceControllerWrapper * AndroidDeviceControllerWrapper::AllocateNew(
std::unique_ptr<AndroidDeviceControllerWrapper> wrapper(
new AndroidDeviceControllerWrapper(std::move(controller), std::move(opCredsIssuerPtr)));

#ifdef JAVA_MATTER_CONTROLLER_TEST
if (wrapper->mExampleStorage.Init() != CHIP_NO_ERROR)
{
ChipLogError(Controller, "Init Storage failure");
return nullptr;
}
chip::PersistentStorageDelegate * wrapperStorage = &wrapper->mExampleStorage;
wrapper->SetJavaObjectRef(vm, deviceControllerObj);
chip::Controller::ExampleOperationalCredentialsIssuer * opCredsIssuer = wrapper->mOpCredsIssuer.get();
#else
chip::PersistentStorageDelegate * wrapperStorage = wrapper.get();

wrapper->SetJavaObjectRef(vm, deviceControllerObj);

chip::Controller::AndroidOperationalCredentialsIssuer * opCredsIssuer = wrapper->mOpCredsIssuer.get();
#endif

// Initialize device attestation verifier
// TODO: Replace testingRootStore with a AttestationTrustStore that has the necessary official PAA roots available
Expand Down Expand Up @@ -177,9 +196,12 @@ AndroidDeviceControllerWrapper * AndroidDeviceControllerWrapper::AllocateNew(
return nullptr;
}
initParams.opCertStore = &wrapper->mOpCertStore;

#ifdef JAVA_MATTER_CONTROLLER_TEST
opCredsIssuer->Initialize(wrapper->mExampleStorage);
#else
// TODO: Init IPK Epoch Key in opcreds issuer, so that commissionees get the right IPK
opCredsIssuer->Initialize(*wrapper.get(), &wrapper->mAutoCommissioner, wrapper.get()->mJavaObjectRef);
#endif

Platform::ScopedMemoryBuffer<uint8_t> noc;
if (!noc.Alloc(kMaxCHIPDERCertLength))
Expand Down Expand Up @@ -208,7 +230,7 @@ AndroidDeviceControllerWrapper * AndroidDeviceControllerWrapper::AllocateNew(

// The lifetime of the ephemeralKey variable must be kept until SetupParams is saved.
Crypto::P256Keypair ephemeralKey;

#ifndef JAVA_MATTER_CONTROLLER_TEST
if (rootCertificate != nullptr && nodeOperationalCertificate != nullptr && keypairDelegate != nullptr)
{
CHIPP256KeypairBridge * nativeKeypairBridge = wrapper->GetP256KeypairBridge();
Expand Down Expand Up @@ -245,6 +267,7 @@ AndroidDeviceControllerWrapper * AndroidDeviceControllerWrapper::AllocateNew(
setupParams.controllerNOC = chip::ByteSpan(wrapper->mNocCertificate.data(), wrapper->mNocCertificate.size());
}
else
#endif // JAVA_MATTER_CONTROLLER_TEST
{
ChipLogProgress(Controller,
"No existing credentials provided: generating ephemeral local NOC chain with OperationalCredentialsIssuer");
Expand Down
Loading

0 comments on commit 1096536

Please sign in to comment.