diff --git a/.fvm/fvm_config.json b/.fvm/fvm_config.json index 30c9706..d8abe1b 100644 --- a/.fvm/fvm_config.json +++ b/.fvm/fvm_config.json @@ -1,4 +1,4 @@ { - "flutterSdkVersion": "2.10.0", + "flutterSdkVersion": "3.13.9", "flavors": {} } \ No newline at end of file diff --git a/.gitignore b/.gitignore index f0974e6..24476c5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,44 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp .DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id .dart_tool/ -.fvm -!.fvm/fvm_config.json +.flutter-plugins +.flutter-plugins-dependencies .packages +.pub-cache/ .pub/ -pubspec.lock -build/ +/build/ + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/CHANGELOG.md b/CHANGELOG.md index 87a0ed1..b71e435 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,23 @@ +## 1.4.0 +Added support for Kotlin 1.5.20 + +## 1.3.3 + +Fixed #33: Windows: TXT records are returned as string instead of UInt8List, causing failure (Thanks @jnstahl) +Fixed #36: Windows: txt records are sent as [key: key] instead of [key: value] (Thanks @jnstahl) + +## 1.3.2 + +This release is identical in functionality to the previous one. It only fixes pub.dev analysis +errors. + +* Fixed: pub.dev analsis error + ## 1.3.1 +This release is identical in functionality to the previous one. It only fixes pub.dev analysis +errors. + * Fixed #27: Address pub.dev static analysis * Fixed various lint errors diff --git a/README.md b/README.md index 67e04e0..2ce9e20 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,3 @@ -[![flutter_nsd](https://github.com/Nimrodda/flutter_nsd/actions/workflows/build.yaml/badge.svg)](https://github.com/Nimrodda/flutter_nsd/actions/workflows/build.yaml) - # Flutter Network Service Discovery plugin A Flutter plugin for Network Service Discovery (mDNS) on Android, iOS, MacOS and Windows. The plugin uses the platform's own API when possible. @@ -12,7 +10,7 @@ Add the dependency to pubspec.yaml: ``` dependencies: - flutter_nsd: ^1.3.1 + flutter_nsd: ^1.4.0 ``` ## Getting Started @@ -115,7 +113,7 @@ Then scan for this service using the example app on any of the supported platfor ## License -Copyright 2022 Nimrod Dayan nimroddayan.com +Copyright 2023 Nimrod Dayan nimroddayan.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/android/.gitignore b/android/.gitignore index c6cbe56..6f56801 100644 --- a/android/.gitignore +++ b/android/.gitignore @@ -1,8 +1,13 @@ -*.iml -.gradle +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat /local.properties -/.idea/workspace.xml -/.idea/libraries -.DS_Store -/build -/captures +GeneratedPluginRegistrant.java + +# Remember to never publicly share your keystore. +# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +key.properties +**/*.keystore +**/*.jks diff --git a/android/build.gradle b/android/build.gradle index 06d38cf..fe7874b 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -47,6 +47,7 @@ android { namespace 'com.nimroddayan.flutternsd' } + compileSdkVersion 34 sourceSets { diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index 8de19ea..b96ab2e 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -19,4 +19,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml index 6eff9e3..49a85b2 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -18,5 +18,5 @@ - + diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index 2189513..062f915 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -43,7 +43,7 @@ apply plugin: 'kotlin-android' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { - compileSdkVersion 29 + compileSdkVersion 33 sourceSets { main.java.srcDirs += 'src/main/kotlin' diff --git a/example/android/build.gradle b/example/android/build.gradle index dceb22a..6350fd4 100644 --- a/example/android/build.gradle +++ b/example/android/build.gradle @@ -16,14 +16,14 @@ */ buildscript { - ext.kotlin_version = '1.4.0' + ext.kotlin_version = '1.7.10' repositories { google() - jcenter() + mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:4.0.1' + classpath 'com.android.tools.build:gradle:7.3.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } @@ -31,7 +31,7 @@ buildscript { allprojects { repositories { google() - jcenter() + mavenCentral() } } @@ -43,6 +43,6 @@ subprojects { project.evaluationDependsOn(':app') } -task clean(type: Delete) { +tasks.register("clean", Delete) { delete rootProject.buildDir } diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties index 575459e..d194ec5 100644 --- a/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/example/android/gradle/wrapper/gradle-wrapper.properties @@ -20,4 +20,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip diff --git a/example/pubspec.lock b/example/pubspec.lock new file mode 100644 index 0000000..daa1f34 --- /dev/null +++ b/example/pubspec.lock @@ -0,0 +1,196 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + async: + dependency: transitive + description: + name: async + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" + source: hosted + version: "2.11.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + characters: + dependency: transitive + description: + name: characters + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + clock: + dependency: transitive + description: + name: clock + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" + source: hosted + version: "1.1.1" + collection: + dependency: transitive + description: + name: collection + sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 + url: "https://pub.dev" + source: hosted + version: "1.17.2" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d + url: "https://pub.dev" + source: hosted + version: "1.0.6" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: b543301ad291598523947dc534aaddc5aaad597b709d2426d3a0e0d44c5cb493 + url: "https://pub.dev" + source: hosted + version: "1.0.4" + flutter_nsd: + dependency: "direct main" + description: + path: ".." + relative: true + source: path + version: "1.4.0" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + lints: + dependency: transitive + description: + name: lints + sha256: a2c3d198cb5ea2e179926622d433331d8b58374ab8f29cdda6e863bd62fd369c + url: "https://pub.dev" + source: hosted + version: "1.0.1" + matcher: + dependency: transitive + description: + name: matcher + sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + url: "https://pub.dev" + source: hosted + version: "0.12.16" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" + url: "https://pub.dev" + source: hosted + version: "0.5.0" + meta: + dependency: transitive + description: + name: meta + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + url: "https://pub.dev" + source: hosted + version: "1.9.1" + path: + dependency: transitive + description: + name: path + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + url: "https://pub.dev" + source: hosted + version: "1.8.3" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_span: + dependency: transitive + description: + name: source_span + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + url: "https://pub.dev" + source: hosted + version: "1.10.0" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + url: "https://pub.dev" + source: hosted + version: "1.11.0" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + test_api: + dependency: transitive + description: + name: test_api + sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" + url: "https://pub.dev" + source: hosted + version: "0.6.0" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + web: + dependency: transitive + description: + name: web + sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + url: "https://pub.dev" + source: hosted + version: "0.1.4-beta" +sdks: + dart: ">=3.1.0-185.0.dev <4.0.0" + flutter: ">=1.20.0" diff --git a/example/pubspec.yaml b/example/pubspec.yaml index c63958d..9327d2d 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -13,7 +13,7 @@ dependencies: flutter_nsd: path: ../ - cupertino_icons: ^0.1.3 + cupertino_icons: ^1.0.6 dev_dependencies: flutter_lints: ^1.0.4 diff --git a/example/windows/flutter/generated_plugins.cmake b/example/windows/flutter/generated_plugins.cmake index 650012f..0173e5a 100644 --- a/example/windows/flutter/generated_plugins.cmake +++ b/example/windows/flutter/generated_plugins.cmake @@ -6,6 +6,9 @@ list(APPEND FLUTTER_PLUGIN_LIST flutter_nsd ) +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + set(PLUGIN_BUNDLED_LIBRARIES) foreach(plugin ${FLUTTER_PLUGIN_LIST}) @@ -14,3 +17,8 @@ foreach(plugin ${FLUTTER_PLUGIN_LIST}) list(APPEND PLUGIN_BUNDLED_LIBRARIES $) list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/lib/flutter_nsd.dart b/lib/flutter_nsd.dart index f7f51ac..42e2ac9 100644 --- a/lib/flutter_nsd.dart +++ b/lib/flutter_nsd.dart @@ -16,7 +16,6 @@ */ import 'dart:async'; -import 'dart:typed_data'; import 'package:flutter/services.dart'; @@ -27,7 +26,8 @@ import 'package:flutter/services.dart'; /// Stop discovery by calling [stopDiscovery] when you're done. /// class FlutterNsd { - static const MethodChannel _channel = MethodChannel('com.nimroddayan/flutter_nsd'); + static const MethodChannel _channel = + MethodChannel('com.nimroddayan/flutter_nsd'); static final FlutterNsd _instance = FlutterNsd._internal(); final _streamController = StreamController(); @@ -78,7 +78,7 @@ class FlutterNsd { _streamController.add(nsdServiceInfo); break; case 'onServiceLost': - // TODO issue #28 + // TODO issue #28 break; default: throw MissingPluginException(); diff --git a/pubspec.yaml b/pubspec.yaml index 29ac602..4063885 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_nsd description: A Flutter plugin for Network Service Discovery (mDNS) that uses platform API on Android, iOS, MacOS and Windows. -version: 1.3.1 +version: 1.4.0 homepage: https://github.com/Nimrodda/flutter_nsd environment: diff --git a/test/flutter_nsd_test.dart b/test/flutter_nsd_test.dart index dea8561..ba98fae 100644 --- a/test/flutter_nsd_test.dart +++ b/test/flutter_nsd_test.dart @@ -24,13 +24,13 @@ void main() { TestWidgetsFlutterBinding.ensureInitialized(); setUp(() { - channel.setMockMethodCallHandler((MethodCall methodCall) async { + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler(channel, (MethodCall methodCall) async { return '42'; }); }); tearDown(() { - channel.setMockMethodCallHandler(null); + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler(channel, null); }); test('getPlatformVersion', () async { diff --git a/windows/flutter_nsd_plugin.cpp b/windows/flutter_nsd_plugin.cpp index 8fd15cf..a6b36a4 100644 --- a/windows/flutter_nsd_plugin.cpp +++ b/windows/flutter_nsd_plugin.cpp @@ -42,6 +42,14 @@ namespace { std::map txt; }; + class MdnsSentResult { + public: + std::chrono::steady_clock::time_point lastSeen; + std::string name; + std::string hostname; + int port; + }; + class MdnsRequest { public: @@ -65,7 +73,7 @@ namespace { volatile boolean keepRunning; std::shared_ptr> channel; std::map packets; - std::set sent_results; + std::map sent_results; }; @@ -79,17 +87,22 @@ namespace { void MdnsRequest::send(MdnsResult& packet) { auto digest = packet.name + packet.dnsname + packet.hostname + packet.ipv4address + packet.ipv6address + std::to_string(packet.port); + auto time = std::chrono::steady_clock::now(); + + if (sent_results.find(digest) != sent_results.end()) { + sent_results[digest].lastSeen = time; return; } - sent_results.insert(digest); + + if (packet.hostname.empty()) { packet.hostname = packet.ipv4address; } else { struct hostent* ent = gethostbyname(packet.hostname.c_str()); if (ent == NULL) { - printf("cannot resolve hostname %s, returning IP address %s", packet.hostname.c_str(), packet.ipv4address.c_str()); + //printf("cannot resolve hostname %s, returning IP address %s", packet.hostname.c_str(), packet.ipv4address.c_str()); packet.hostname = packet.ipv4address; } } @@ -103,7 +116,15 @@ namespace { name = name.substr(0, pos); } - } + } + MdnsSentResult result; + result.name = name; + result.hostname = packet.hostname; + result.port = packet.port; + result.lastSeen = time; + sent_results[digest] = result; + + channel->InvokeMethod("onServiceResolved", std::make_unique(flutter::EncodableValue(flutter::EncodableMap{ @@ -142,7 +163,7 @@ namespace { void MdnsRequest::callbackSRV(const void* base, boolean last, STRING_ARG_DECL(name), STRING_ARG_DECL(hostname), int port) { MAKE_STRING(name); MAKE_STRING(hostname); - printf("resolved: %s, %s\n\r", _name.c_str(), _hostname.c_str()); + //printf("resolved: %s, %s\n\r", _name.c_str(), _hostname.c_str()); MdnsResult& packet = packets[base]; packet.name = _name; @@ -176,8 +197,9 @@ namespace { void MdnsRequest::callbackTXT(const void* base, boolean last, STRING_ARG_DECL(key), STRING_ARG_DECL(value)) { MAKE_STRING(key); MAKE_STRING(value); + std::vector _vector(_value.begin(), _value.end()); // flutter_nsd expects txt values as UInt8List not as string MdnsResult& packet = packets[base]; - packet.txt[flutter::EncodableValue(_key)] = flutter::EncodableValue(_value); + packet.txt[flutter::EncodableValue(_key)] = flutter::EncodableValue(_vector); process(base, last); } @@ -192,6 +214,27 @@ namespace { send(it->second); } if (result == -1) return; + auto time = std::chrono::steady_clock::now(); + std::list toDelete; + for (auto i = sent_results.begin(); i != sent_results.end(); i++) { + if (time > (i->second.lastSeen + std::chrono::seconds(30))) { + std::map empty_map; + channel->InvokeMethod("onServiceLost", + + std::make_unique(flutter::EncodableValue(flutter::EncodableMap{ + {flutter::EncodableValue("hostname"), flutter::EncodableValue(i->second.hostname)}, + {flutter::EncodableValue("port"), flutter::EncodableValue(i->second.port)}, + {flutter::EncodableValue("name"), flutter::EncodableValue(i->second.name)}, + {flutter::EncodableValue("txt"), flutter::EncodableValue(empty_map)} + } + )) + ); + toDelete.push_back(i->first); + } + } + for (auto i = toDelete.begin(); i != toDelete.end(); i++) { + sent_results.erase(*i); + } } delete this; } @@ -346,7 +389,7 @@ void call_HandlePTRRecord(const void* p, const void* base, boolean last, STRING_ } void call_HandleTXTRecord(const void* p, const void* base, boolean last, STRING_ARG_DECL(key), STRING_ARG_DECL(value)) { - ((MdnsRequest*)p)->callbackTXT(base, last, STRING_ARG_CALL(key), STRING_ARG_CALL(key)); + ((MdnsRequest*)p)->callbackTXT(base, last, STRING_ARG_CALL(key), STRING_ARG_CALL(value)); }