Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add text entries to mDNS service discovery response #19027

Merged
merged 14 commits into from
Jun 3, 2022
Original file line number Diff line number Diff line change
Expand Up @@ -112,14 +112,7 @@ public void promptCommissioningSucceeded(int vendorId, int productId, String com
}

public void promptCommissioningFailed(String commissioneeName, String error) {
Log.d(
TAG,
"Received prompt for failure vendor id:"
+ vendorId
+ " productId:"
+ productId
+ ". Commissionee: "
+ commissioneeName);
Log.d(TAG, "Received prompt for failure Commissionee: " + commissioneeName);
NotificationCompat.Builder builder =
new NotificationCompat.Builder(activity, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_baseline_clear_24)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

public class UserPrompterResolver {

private static final String TAG = "UserPrompterResolver";
protected static final String TAG = "UserPrompterResolver";

public native void OnPinCodeEntered(int pinCode);

Expand Down
6 changes: 3 additions & 3 deletions src/platform/android/AndroidChipPlatform-JNI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,11 +238,11 @@ JNI_METHOD(void, nativeSetServiceResolver)(JNIEnv * env, jclass self, jobject re
}

JNI_MDNSCALLBACK_METHOD(void, handleServiceResolve)
(JNIEnv * env, jclass self, jstring instanceName, jstring serviceType, jstring address, jint port, jlong callbackHandle,
jlong contextHandle)
(JNIEnv * env, jclass self, jstring instanceName, jstring serviceType, jstring address, jint port, jobject attributes,
jlong callbackHandle, jlong contextHandle)
{
using ::chip::Dnssd::HandleResolve;
HandleResolve(instanceName, serviceType, address, port, callbackHandle, contextHandle);
HandleResolve(instanceName, serviceType, address, port, attributes, callbackHandle, contextHandle);
}

#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
Expand Down
105 changes: 99 additions & 6 deletions src/platform/android/DnssdImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

#include <cstddef>
#include <jni.h>
#include <memory>
#include <string>

namespace chip {
Expand All @@ -37,11 +38,14 @@ namespace Dnssd {
using namespace chip::Platform;

namespace {
jobject sResolverObject = nullptr;
jobject sMdnsCallbackObject = nullptr;
jmethodID sResolveMethod = nullptr;
jmethodID sPublishMethod = nullptr;
jmethodID sRemoveServicesMethod = nullptr;
jobject sResolverObject = nullptr;
jobject sMdnsCallbackObject = nullptr;
jmethodID sResolveMethod = nullptr;
jmethodID sGetTextEntryKeysMethod = nullptr;
jmethodID sGetTextEntryDataMethod = nullptr;
jclass sMdnsCallbackClass = nullptr;
jmethodID sPublishMethod = nullptr;
jmethodID sRemoveServicesMethod = nullptr;
} // namespace

// Implementation of functions declared in lib/dnssd/platform/Dnssd.h
Expand Down Expand Up @@ -185,9 +189,14 @@ void InitializeWithObjects(jobject resolverObject, jobject mdnsCallbackObject)
sResolverObject = env->NewGlobalRef(resolverObject);
sMdnsCallbackObject = env->NewGlobalRef(mdnsCallbackObject);
jclass resolverClass = env->GetObjectClass(sResolverObject);
sMdnsCallbackClass = env->GetObjectClass(sMdnsCallbackObject);

VerifyOrReturn(resolverClass != nullptr, ChipLogError(Discovery, "Failed to get Resolver Java class"));

sGetTextEntryKeysMethod = env->GetMethodID(sMdnsCallbackClass, "getTextEntryKeys", "(Ljava/util/Map;)[Ljava/lang/String;");

sGetTextEntryDataMethod = env->GetMethodID(sMdnsCallbackClass, "getTextEntryData", "(Ljava/util/Map;Ljava/lang/String;)[B");

sResolveMethod =
env->GetMethodID(resolverClass, "resolve", "(Ljava/lang/String;Ljava/lang/String;JJLchip/platform/ChipMdnsCallback;)V");
if (sResolveMethod == nullptr)
Expand All @@ -196,6 +205,18 @@ void InitializeWithObjects(jobject resolverObject, jobject mdnsCallbackObject)
env->ExceptionClear();
}

if (sGetTextEntryKeysMethod == nullptr)
{
ChipLogError(Discovery, "Failed to access MdnsCallback 'getTextEntryKeys' method");
env->ExceptionClear();
}

if (sGetTextEntryDataMethod == nullptr)
{
ChipLogError(Discovery, "Failed to access MdnsCallback 'getTextEntryData' method");
env->ExceptionClear();
}

sPublishMethod =
env->GetMethodID(resolverClass, "publish",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I[Ljava/lang/String;[[B[Ljava/lang/String;)V");
Expand All @@ -213,7 +234,8 @@ void InitializeWithObjects(jobject resolverObject, jobject mdnsCallbackObject)
}
}

void HandleResolve(jstring instanceName, jstring serviceType, jstring address, jint port, jlong callbackHandle, jlong contextHandle)
void HandleResolve(jstring instanceName, jstring serviceType, jstring address, jint port, jobject textEntries, jlong callbackHandle,
jlong contextHandle)
{
VerifyOrReturn(callbackHandle != 0, ChipLogError(Discovery, "HandleResolve called with callback equal to nullptr"));

Expand Down Expand Up @@ -242,8 +264,79 @@ void HandleResolve(jstring instanceName, jstring serviceType, jstring address, j
CopyString(service.mName, jniInstanceName.c_str());
CopyString(service.mType, jniServiceType.c_str());
service.mPort = static_cast<uint16_t>(port);
service.mTextEntrySize = 0;
service.mTextEntries = nullptr;

// Note on alloc/free memory use
// We are only allocating the entries list and the data field of each entry
// so we free these in the exit section
if (textEntries != nullptr)
{
jobjectArray keys = (jobjectArray) env->CallObjectMethod(sMdnsCallbackObject, sGetTextEntryKeysMethod, textEntries);
size_t size = env->GetArrayLength(keys);
TextEntry * entries = new (std::nothrow) TextEntry[size];
if (entries == nullptr)
{
ChipLogError(Discovery, "entries alloc failure");
goto exit;
chrisdecenzo marked this conversation as resolved.
Show resolved Hide resolved
}
service.mTextEntries = entries;
for (size_t i = 0; i < size; i++)
chrisdecenzo marked this conversation as resolved.
Show resolved Hide resolved
{
jstring jniKeyObject = (jstring) env->GetObjectArrayElement(keys, i);
JniUtfString key(env, jniKeyObject);
entries[i].mKey = strdup(key.c_str());

jbyteArray datas =
(jbyteArray) env->CallObjectMethod(sMdnsCallbackObject, sGetTextEntryDataMethod, textEntries, jniKeyObject);
if (datas != nullptr)
{
size_t dataSize = env->GetArrayLength(datas);
uint8_t * data = new (std::nothrow) uint8_t[dataSize];
if (data == nullptr)
{
ChipLogError(Discovery, "data alloc failure");
goto exit;
}

jbyte * jnidata = env->GetByteArrayElements(datas, nullptr);
for (size_t j = 0; j < dataSize; j++)
{
data[j] = static_cast<uint8_t>(jnidata[j]);
}
entries[i].mDataSize = dataSize;
entries[i].mData = data;

ChipLogProgress(Discovery, " ----- entry [%u] : %s %s\n", static_cast<unsigned int>(i), entries[i].mKey,
std::string(reinterpret_cast<char *>(data), dataSize).c_str());
}
else
{
ChipLogProgress(Discovery, " ----- entry [%u] : %s NULL\n", static_cast<unsigned int>(i), entries[i].mKey);

entries[i].mDataSize = 0;
entries[i].mData = nullptr;
}
service.mTextEntrySize = size;
}
}

exit:
dispatch(CHIP_NO_ERROR, &service, &ipAddress);

if (service.mTextEntries != nullptr)
{
size_t size = service.mTextEntrySize;
for (size_t i = 0; i < size; i++)
{
delete[] service.mTextEntries[i].mKey;
chrisdecenzo marked this conversation as resolved.
Show resolved Hide resolved
if (service.mTextEntries[i].mData != nullptr)
{
delete[] service.mTextEntries[i].mData;
}
}
delete[] service.mTextEntries;
}
}

} // namespace Dnssd
Expand Down
2 changes: 1 addition & 1 deletion src/platform/android/DnssdImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ void InitializeWithObjects(jobject resolverObject, jobject chipMdnsCallbackObjec
/**
* Pass results of the service resolution to the CHIP stack.
*/
void HandleResolve(jstring instanceName, jstring serviceType, jstring address, jint port, jlong callbackHandle,
void HandleResolve(jstring instanceName, jstring serviceType, jstring address, jint port, jobject textEntries, jlong callbackHandle,
jlong contextHandle);

} // namespace Dnssd
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@
*/
package chip.platform;

import java.util.Map;

/** Interface for communicating with the CHIP mDNS stack. */
public interface ChipMdnsCallback {
void handleServiceResolve(
String instanceName,
String serviceType,
String address,
int port,
Map<String, byte[]> textEntries,
long callbackHandle,
long contextHandle);
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,23 @@
*/
package chip.platform;

import java.util.Map;

public class ChipMdnsCallbackImpl implements ChipMdnsCallback {
public native void handleServiceResolve(
String instanceName,
String serviceType,
String address,
int port,
Map<String, byte[]> textEntries,
long callbackHandle,
long contextHandle);

public String[] getTextEntryKeys(Map<String, byte[]> textEntries) {
return textEntries.keySet().toArray(new String[textEntries.size()]);
}

public byte[] getTextEntryData(Map<String, byte[]> textEntries, String key) {
return textEntries.get(key);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,13 @@ public void resolve(
NsdServiceInfo serviceInfo = new NsdServiceInfo();
serviceInfo.setServiceName(instanceName);
serviceInfo.setServiceType(serviceType);
Log.d(TAG, "Starting service resolution for '" + instanceName + "'");
Log.d(
TAG,
"resolve: Starting service resolution for '"
+ instanceName
+ "' type '"
+ serviceType
+ "'");

Runnable timeoutRunnable =
new Runnable() {
Expand All @@ -67,6 +73,7 @@ public void run() {
// Ensure we always release the multicast lock. It's possible that we release the
// multicast lock here before ResolveListener returns, but since NsdManager has no API
// to cancel service resolution, there's not much we can do here.
Log.d(TAG, "resolve: Timing out");
if (multicastLock.isHeld()) {
multicastLock.release();
}
Expand All @@ -82,7 +89,7 @@ public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {
TAG,
"Failed to resolve service '" + serviceInfo.getServiceName() + "': " + errorCode);
chipMdnsCallback.handleServiceResolve(
instanceName, serviceType, null, 0, callbackHandle, contextHandle);
instanceName, serviceType, null, 0, null, callbackHandle, contextHandle);

if (multicastLock.isHeld()) {
multicastLock.release();
Expand All @@ -104,6 +111,7 @@ public void onServiceResolved(NsdServiceInfo serviceInfo) {
serviceType,
serviceInfo.getHost().getHostAddress(),
serviceInfo.getPort(),
serviceInfo.getAttributes(),
callbackHandle,
contextHandle);

Expand Down