Add script for upstream upgrade
authorJihoon Jung <jh8801.jung@samsung.com>
Thu, 11 Mar 2021 04:27:33 +0000 (13:27 +0900)
committer정지훈/Tizen Platform Lab(SR)/Staff Engineer/삼성전자 <jh8801.jung@samsung.com>
Mon, 15 Mar 2021 22:46:33 +0000 (07:46 +0900)
Signed-off-by: Jihoon Jung <jh8801.jung@samsung.com>
packaging/connectedhomeip.spec
packaging/tizen_fix/BUILD.gn [new file with mode: 0644]
packaging/tizen_fix/MdnsImpl.cpp [new file with mode: 0644]
packaging/tizen_fix/crypto.gni [new file with mode: 0644]
packaging/tizen_fix/tizen_fix.sh [new file with mode: 0755]

index 8375ea3..f97a2e7 100755 (executable)
@@ -30,9 +30,7 @@ chmod 644 %{SOURCE0}
 cp %{SOURCE1} ./%{name}.manifest
 
 %build
-
-#source scripts/activate.sh
-gn gen out/host --args='is_debug=true target_os="linux" current_cpu="arm" bypass_rendezvous=true'
+gn gen out/host --args='is_debug=true target_os="linux" current_cpu="arm"'
 ninja -C out/host
 
 %install
diff --git a/packaging/tizen_fix/BUILD.gn b/packaging/tizen_fix/BUILD.gn
new file mode 100644 (file)
index 0000000..5b9bed3
--- /dev/null
@@ -0,0 +1,307 @@
+# Copyright (c) 2020 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/chip.gni")
+import("//build_overrides/mbedtls.gni")
+import("//build_overrides/nlassert.gni")
+import("//build_overrides/nlio.gni")
+import("//build_overrides/nlunit_test.gni")
+import("//build_overrides/pigweed.gni")
+
+# This build file should not be used in superproject builds.
+assert(chip_root == "//")
+
+import("${chip_root}/build/chip/tests.gni")
+import("${chip_root}/build/chip/tools.gni")
+
+if (current_toolchain != "${dir_pw_toolchain}/dummy:dummy") {
+  declare_args() {
+    chip_enable_python_modules =
+        (current_os == "mac" || current_os == "linux") && host_cpu == "x64"
+  }
+
+  # This is a real toolchain. Build CHIP.
+  group("default") {
+    deps = [ ":all" ]
+  }
+
+  group("all") {
+    deps = [
+      "${chip_root}/src/app",
+      "${chip_root}/src/ble",
+      "${chip_root}/src/controller",
+      "${chip_root}/src/crypto",
+      "${chip_root}/src/inet",
+      "${chip_root}/src/lib",
+      "${chip_root}/src/lib/asn1",
+      "${chip_root}/src/lib/core",
+      "${chip_root}/src/lib/shell",
+      "${chip_root}/src/lib/support",
+      "${chip_root}/src/lwip:all",
+      "${chip_root}/src/messaging",
+      "${chip_root}/src/protocols",
+      "${chip_root}/src/setup_payload",
+      "${chip_root}/src/system",
+      "${chip_root}/src/transport",
+      "${mbedtls_root}:mbedtls",
+      "${nlassert_root}:nlassert",
+      "${nlio_root}:nlio",
+      "${nlunit_test_root}:nlunit-test",
+    ]
+
+    if (chip_build_tests) {
+      deps += [ "//src:tests" ]
+    }
+
+    if (chip_build_tools) {
+      deps += [
+        "${chip_root}/examples/shell/standalone:chip-shell",
+        "${chip_root}/src/qrcodetool",
+        "${chip_root}/src/setup_payload",
+      ]
+      if (chip_enable_python_modules) {
+        deps += [ "${chip_root}/src/controller/python" ]
+      }
+    }
+
+    if (current_os == "android") {
+      deps += [
+        "${chip_root}/src/controller/java",
+        "${chip_root}/src/setup_payload/java",
+      ]
+    }
+
+    deps += [
+      "${chip_root}/examples/all-clusters-app/linux",
+      "${chip_root}/examples/lighting-app/linux",
+      "${chip_root}/examples/chip-tool",
+      "${chip_root}/examples/minimal-mdns:minimal-mdns-client",
+      "${chip_root}/examples/minimal-mdns:minimal-mdns-server",
+    ]
+  }
+
+  group("check") {
+    if (chip_link_tests) {
+      deps = [ "//src:tests_run" ]
+    }
+  }
+
+  # We don't always want to run happy tests, make them a seperate group.
+  if (chip_enable_happy_tests) {
+    group("happy_tests") {
+      if (chip_link_tests) {
+        deps = [ "//src:happy_tests" ]
+      }
+    }
+  }
+} else {
+  # This is the unified build. Configure various real toolchains.
+  import("${chip_root}/build/chip/chip_build.gni")
+  declare_args() {
+    # Set this to false to disable all builds by default.
+    enable_default_builds = true
+
+    # Enable building for Android.
+    enable_android_builds = false
+
+    # Set this to true to enable efr32 builds by default.
+    enable_efr32_builds = false
+
+    # Set this to true to enable qpg6100 builds by default.
+    enable_qpg6100_builds = false
+
+    # Set this to true to enable k32w builds by default.
+    enable_k32w_builds = false
+  }
+
+  declare_args() {
+    # Enable building chip with clang.
+    enable_host_clang_build = enable_default_builds
+
+    # Enable building chip with gcc.
+    enable_host_gcc_build = enable_default_builds
+
+    # Enable building chip with gcc & mbedtls.
+    enable_host_gcc_mbedtls_build = enable_default_builds
+
+    # Build the chip-tool example.
+    enable_standalone_chip_tool_build = enable_default_builds
+
+    # Build the shell example.
+    enable_standalone_shell_build = enable_default_builds
+
+    # Build the Linux all clusters app example.
+    enable_linux_all_clusters_app_build =
+        enable_default_builds && host_os == "linux"
+
+    # Build the Linux lighting app example.
+    enable_linux_lighting_app_build =
+        enable_default_builds && host_os == "linux"
+
+    # Build the efr32 lock app example.
+    enable_efr32_lock_app_build = enable_efr32_builds
+
+    # Build the qpg6100 lock app example.
+    enable_qpg6100_lock_app_build = enable_qpg6100_builds
+
+    # Build the efr32 lighting app example.
+    enable_efr32_lighting_app_build = enable_efr32_builds
+
+    # Build the k32w lock app example.
+    enable_k32w_lock_app_build = enable_k32w_builds
+  }
+
+  if (enable_host_clang_build) {
+    chip_build("host_clang") {
+      toolchain = "//build/toolchain/host:${host_os}_${host_cpu}_clang"
+    }
+  }
+
+  if (enable_host_gcc_build) {
+    chip_build("host_gcc") {
+      toolchain = "//build/toolchain/host:${host_os}_${host_cpu}_gcc"
+    }
+  }
+
+  if (enable_host_gcc_mbedtls_build) {
+    chip_build("host_gcc_mbedtls") {
+      toolchain = "${chip_root}/config/mbedtls/toolchain:${host_os}_${host_cpu}_gcc_mbedtls"
+    }
+  }
+
+  if (enable_android_builds) {
+    chip_build("android_arm") {
+      toolchain = "//build/toolchain/android:android_arm"
+    }
+
+    chip_build("android_arm64") {
+      toolchain = "//build/toolchain/android:android_arm64"
+    }
+
+    chip_build("android_x64") {
+      toolchain = "//build/toolchain/android:android_x64"
+    }
+
+    chip_build("android_x86") {
+      toolchain = "//build/toolchain/android:android_x86"
+    }
+  }
+
+  standalone_toolchain = "${chip_root}/config/standalone/toolchain:standalone"
+
+  if (enable_standalone_chip_tool_build) {
+    group("standalone_chip_tool") {
+      deps = [ "${chip_root}/examples/chip-tool(${standalone_toolchain})" ]
+    }
+  }
+
+  if (enable_standalone_shell_build) {
+    group("standalone_shell") {
+      deps =
+          [ "${chip_root}/examples/shell/standalone(${standalone_toolchain})" ]
+    }
+  }
+
+  if (enable_linux_all_clusters_app_build) {
+    group("linux_all_clusters_app") {
+      deps = [
+        "${chip_root}/examples/all-clusters-app/linux(${standalone_toolchain})",
+      ]
+    }
+  }
+
+  if (enable_linux_lighting_app_build) {
+    group("linux_lighting_app") {
+      deps = [
+        "${chip_root}/examples/lighting-app/linux(${standalone_toolchain})",
+      ]
+    }
+  }
+
+  if (enable_efr32_lock_app_build) {
+    group("efr32_lock_app") {
+      deps = [ "${chip_root}/examples/lock-app/efr32(${chip_root}/config/efr32/toolchain:efr32_lock_app)" ]
+    }
+  }
+
+  if (enable_qpg6100_lock_app_build) {
+    group("qpg6100_lock_app") {
+      deps = [ "${chip_root}/examples/lock-app/qpg6100(${chip_root}/config/qpg6100/toolchain:qpg6100_lock_app)" ]
+    }
+  }
+
+  if (enable_efr32_lighting_app_build) {
+    group("efr32_lighting_app") {
+      deps = [ "${chip_root}/examples/lighting-app/efr32(${chip_root}/config/efr32/toolchain:efr32_lighting_app)" ]
+    }
+  }
+
+  if (enable_k32w_lock_app_build) {
+    group("k32w_lock_app") {
+      deps = [ "${chip_root}/examples/lock-app/k32w(${chip_root}/config/k32w/toolchain:k32w_lock_app)" ]
+    }
+  }
+
+  group("default") {
+    deps = []
+    if (enable_host_clang_build) {
+      deps += [ ":all_host_clang" ]
+    }
+    if (enable_host_gcc_build) {
+      deps += [ ":all_host_gcc" ]
+    }
+    if (enable_host_gcc_mbedtls_build) {
+      deps += [ ":all_host_gcc_mbedtls" ]
+    }
+    if (enable_android_builds) {
+      deps += [
+        ":all_android_arm",
+        ":all_android_arm64",
+        ":all_android_x64",
+        ":all_android_x86",
+      ]
+    }
+    if (enable_standalone_chip_tool_build) {
+      deps += [ ":standalone_chip_tool" ]
+    }
+    if (enable_standalone_shell_build) {
+      deps += [ ":standalone_shell" ]
+    }
+    if (enable_linux_all_clusters_app_build) {
+      deps += [ ":linux_all_clusters_app" ]
+    }
+    if (enable_linux_lighting_app_build) {
+      deps += [ ":linux_lighting_app" ]
+    }
+    if (enable_efr32_lock_app_build) {
+      deps += [ ":efr32_lock_app" ]
+    }
+    if (enable_k32w_lock_app_build) {
+      deps += [ ":k32w_lock_app" ]
+    }
+  }
+
+  group("check") {
+    deps = []
+    if (enable_host_clang_build) {
+      deps += [ ":check_host_clang" ]
+    }
+    if (enable_host_gcc_build) {
+      deps += [ ":check_host_gcc" ]
+    }
+    if (enable_host_gcc_mbedtls_build) {
+      deps += [ ":check_host_gcc_mbedtls" ]
+    }
+  }
+}
diff --git a/packaging/tizen_fix/MdnsImpl.cpp b/packaging/tizen_fix/MdnsImpl.cpp
new file mode 100644 (file)
index 0000000..c63b3be
--- /dev/null
@@ -0,0 +1,785 @@
+/*
+ *
+ *    Copyright (c) 2020 Project CHIP Authors
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#include "MdnsImpl.h"
+
+#include <algorithm>
+#include <sstream>
+#include <string.h>
+#include <time.h>
+#include <vector>
+
+#include <netinet/in.h>
+
+#include "support/CHIPMem.h"
+#include "support/CodeUtils.h"
+
+using chip::Mdns::kMdnsTypeMaxSize;
+using chip::Mdns::MdnsServiceProtocol;
+using chip::Mdns::TextEntry;
+using std::chrono::duration_cast;
+using std::chrono::microseconds;
+using std::chrono::seconds;
+using std::chrono::steady_clock;
+
+namespace {
+
+AvahiProtocol ToAvahiProtocol(chip::Inet::IPAddressType addressType)
+{
+    AvahiProtocol protocol;
+
+    switch (addressType)
+    {
+    case chip::Inet::IPAddressType::kIPAddressType_IPv4:
+        protocol = AVAHI_PROTO_INET;
+        break;
+    case chip::Inet::IPAddressType::kIPAddressType_IPv6:
+        protocol = AVAHI_PROTO_INET6;
+        break;
+    default:
+        protocol = AVAHI_PROTO_UNSPEC;
+        break;
+    }
+
+    return protocol;
+}
+
+chip::Inet::IPAddressType ToAddressType(AvahiProtocol protocol)
+{
+    chip::Inet::IPAddressType type;
+
+    switch (protocol)
+    {
+    case AVAHI_PROTO_INET:
+        type = chip::Inet::IPAddressType::kIPAddressType_IPv4;
+        break;
+    case AVAHI_PROTO_INET6:
+        type = chip::Inet::IPAddressType::kIPAddressType_IPv6;
+        break;
+    default:
+        type = chip::Inet::IPAddressType::kIPAddressType_Unknown;
+        break;
+    }
+
+    return type;
+}
+
+CHIP_ERROR MakeAvahiStringListFromTextEntries(TextEntry * entries, size_t size, AvahiStringList ** strListOut)
+{
+    *strListOut = avahi_string_list_new(nullptr, nullptr);
+
+    for (size_t i = 0; i < size; i++)
+    {
+        uint8_t buf[kMdnsTypeMaxSize];
+        size_t offset = static_cast<size_t>(snprintf(reinterpret_cast<char *>(buf), sizeof(buf), "%s=", entries[i].mKey));
+
+        if (offset + entries[i].mDataSize > sizeof(buf))
+        {
+            avahi_string_list_free(*strListOut);
+            *strListOut = nullptr;
+            return CHIP_ERROR_INVALID_ARGUMENT;
+        }
+
+        memcpy(&buf[offset], entries[i].mData, entries[i].mDataSize);
+        *strListOut = avahi_string_list_add_arbitrary(*strListOut, buf, offset + entries[i].mDataSize);
+    }
+    return CHIP_NO_ERROR;
+}
+
+const char * GetProtocolString(MdnsServiceProtocol protocol)
+{
+    return protocol == MdnsServiceProtocol::kMdnsProtocolUdp ? "_udp" : "_tcp";
+}
+
+std::string GetFullType(const char * type, MdnsServiceProtocol protocol)
+{
+    std::ostringstream typeBuilder;
+    typeBuilder << type << "." << GetProtocolString(protocol);
+    return typeBuilder.str();
+}
+
+} // namespace
+
+namespace chip {
+namespace Mdns {
+
+MdnsAvahi MdnsAvahi::sInstance;
+
+constexpr uint64_t kUsPerSec = 1000 * 1000;
+
+Poller::Poller()
+{
+    mAvahiPoller.userdata         = this;
+    mAvahiPoller.watch_new        = WatchNew;
+    mAvahiPoller.watch_update     = WatchUpdate;
+    mAvahiPoller.watch_get_events = WatchGetEvents;
+    mAvahiPoller.watch_free       = WatchFree;
+
+    mAvahiPoller.timeout_new    = TimeoutNew;
+    mAvahiPoller.timeout_update = TimeoutUpdate;
+    mAvahiPoller.timeout_free   = TimeoutFree;
+}
+
+AvahiWatch * Poller::WatchNew(const struct AvahiPoll * poller, int fd, AvahiWatchEvent event, AvahiWatchCallback callback,
+                              void * context)
+{
+    return reinterpret_cast<Poller *>(poller->userdata)->WatchNew(fd, event, callback, context);
+}
+
+AvahiWatch * Poller::WatchNew(int fd, AvahiWatchEvent event, AvahiWatchCallback callback, void * context)
+{
+    VerifyOrDie(callback != nullptr && fd >= 0);
+
+    mWatches.emplace_back(new AvahiWatch{ fd, event, 0, callback, context, this });
+
+    return mWatches.back().get();
+}
+
+void Poller::WatchUpdate(AvahiWatch * watch, AvahiWatchEvent event)
+{
+    watch->mWatchEvents = event;
+}
+
+AvahiWatchEvent Poller::WatchGetEvents(AvahiWatch * watch)
+{
+    return static_cast<AvahiWatchEvent>(watch->mHappenedEvents);
+}
+
+void Poller::WatchFree(AvahiWatch * watch)
+{
+    reinterpret_cast<Poller *>(watch->mPoller)->WatchFree(*watch);
+}
+
+void Poller::WatchFree(AvahiWatch & watch)
+{
+    mWatches.erase(std::remove_if(mWatches.begin(), mWatches.end(),
+                                  [&watch](const std::unique_ptr<AvahiWatch> & aValue) { return aValue.get() == &watch; }),
+                   mWatches.end());
+}
+
+AvahiTimeout * Poller::TimeoutNew(const AvahiPoll * poller, const struct timeval * timeout, AvahiTimeoutCallback callback,
+                                  void * context)
+{
+    VerifyOrDie(poller != nullptr && callback != nullptr);
+
+    return static_cast<Poller *>(poller->userdata)->TimeoutNew(timeout, callback, context);
+}
+
+steady_clock::time_point GetAbsTimeout(const struct timeval * timeout)
+{
+    steady_clock::time_point now        = steady_clock::now();
+    steady_clock::time_point absTimeout = now;
+
+    if (timeout != nullptr)
+    {
+        absTimeout += seconds(timeout->tv_sec);
+        absTimeout += microseconds(timeout->tv_usec);
+    }
+
+    return absTimeout;
+}
+
+AvahiTimeout * Poller::TimeoutNew(const struct timeval * timeout, AvahiTimeoutCallback callback, void * context)
+{
+
+    mTimers.emplace_back(new AvahiTimeout{ GetAbsTimeout(timeout), callback, timeout != nullptr, context, this });
+    return mTimers.back().get();
+}
+
+void Poller::TimeoutUpdate(AvahiTimeout * timer, const struct timeval * timeout)
+{
+    if (timeout)
+    {
+        timer->mAbsTimeout = GetAbsTimeout(timeout);
+        timer->mEnabled    = true;
+    }
+    else
+    {
+        timer->mEnabled = false;
+    }
+}
+
+void Poller::TimeoutFree(AvahiTimeout * timer)
+{
+    static_cast<Poller *>(timer->mPoller)->TimeoutFree(*timer);
+}
+
+void Poller::TimeoutFree(AvahiTimeout & timer)
+{
+    mTimers.erase(std::remove_if(mTimers.begin(), mTimers.end(),
+                                 [&timer](const std::unique_ptr<AvahiTimeout> & aValue) { return aValue.get() == &timer; }),
+                  mTimers.end());
+}
+
+void Poller::UpdateFdSet(fd_set & readFdSet, fd_set & writeFdSet, fd_set & errorFdSet, int & aMaxFd, timeval & timeout)
+{
+    microseconds timeoutVal = seconds(timeout.tv_sec) + microseconds(timeout.tv_usec);
+
+    for (auto && watch : mWatches)
+    {
+        int fd                 = watch->mFd;
+        AvahiWatchEvent events = watch->mWatchEvents;
+
+        if (AVAHI_WATCH_IN & events)
+        {
+            FD_SET(fd, &readFdSet);
+        }
+
+        if (AVAHI_WATCH_OUT & events)
+        {
+            FD_SET(fd, &writeFdSet);
+        }
+
+        if (AVAHI_WATCH_ERR & events)
+        {
+            FD_SET(fd, &errorFdSet);
+        }
+
+        if (aMaxFd < fd)
+        {
+            aMaxFd = fd;
+        }
+
+        watch->mHappenedEvents = 0;
+    }
+
+    for (auto && timer : mTimers)
+    {
+        steady_clock::time_point absTimeout = timer->mAbsTimeout;
+        steady_clock::time_point now        = steady_clock::now();
+
+        if (!timer->mEnabled)
+        {
+            continue;
+        }
+        if (absTimeout < now)
+        {
+            timeoutVal = microseconds(0);
+            break;
+        }
+        else
+        {
+            timeoutVal = std::min(timeoutVal, duration_cast<microseconds>(absTimeout - now));
+        }
+    }
+
+    timeout.tv_sec  = (__time_t)(static_cast<uint64_t>(timeoutVal.count()) / kUsPerSec);
+    timeout.tv_usec = (__suseconds_t)(static_cast<uint64_t>(timeoutVal.count()) % kUsPerSec);
+}
+
+void Poller::Process(const fd_set & readFdSet, const fd_set & writeFdSet, const fd_set & errorFdSet)
+{
+    steady_clock::time_point now = steady_clock::now();
+
+    for (auto && watch : mWatches)
+    {
+        int fd                 = watch->mFd;
+        AvahiWatchEvent events = watch->mWatchEvents;
+
+        watch->mHappenedEvents = 0;
+
+        if ((AVAHI_WATCH_IN & events) && FD_ISSET(fd, &readFdSet))
+        {
+            watch->mHappenedEvents |= AVAHI_WATCH_IN;
+        }
+
+        if ((AVAHI_WATCH_OUT & events) && FD_ISSET(fd, &writeFdSet))
+        {
+            watch->mHappenedEvents |= AVAHI_WATCH_OUT;
+        }
+
+        if ((AVAHI_WATCH_ERR & events) && FD_ISSET(fd, &errorFdSet))
+        {
+            watch->mHappenedEvents |= AVAHI_WATCH_ERR;
+        }
+
+        if (watch->mHappenedEvents)
+        {
+            watch->mCallback(watch.get(), watch->mFd, static_cast<AvahiWatchEvent>(watch->mHappenedEvents), watch->mContext);
+        }
+    }
+
+    for (auto && timer : mTimers)
+    {
+        if (!timer->mEnabled)
+        {
+            continue;
+        }
+        if (timer->mAbsTimeout <= now)
+        {
+            timer->mCallback(timer.get(), timer->mContext);
+        }
+    }
+}
+
+CHIP_ERROR MdnsAvahi::Init(MdnsAsyncReturnCallback initCallback, MdnsAsyncReturnCallback errorCallback, void * context)
+{
+    CHIP_ERROR error = CHIP_NO_ERROR;
+    int avahiError   = 0;
+
+    VerifyOrExit(initCallback != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
+    VerifyOrExit(errorCallback != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
+    VerifyOrExit(mClient == nullptr && mGroup == nullptr, error = CHIP_ERROR_INCORRECT_STATE);
+    mInitCallback       = initCallback;
+    mErrorCallback      = errorCallback;
+    mAsyncReturnContext = context;
+    mClient             = avahi_client_new(mPoller.GetAvahiPoll(), AVAHI_CLIENT_NO_FAIL, HandleClientState, this, &avahiError);
+    VerifyOrExit(mClient != nullptr, error = CHIP_ERROR_OPEN_FAILED);
+    VerifyOrExit(avahiError == 0, error = CHIP_ERROR_OPEN_FAILED);
+
+exit:
+    return error;
+}
+
+CHIP_ERROR MdnsAvahi::SetHostname(const char * hostname)
+{
+    CHIP_ERROR error = CHIP_NO_ERROR;
+    int avahiRet;
+
+    VerifyOrExit(mClient != nullptr, error = CHIP_ERROR_INCORRECT_STATE);
+    avahiRet = avahi_client_set_host_name(mClient, hostname);
+    if (avahiRet == AVAHI_ERR_ACCESS_DENIED)
+    {
+        ChipLogError(DeviceLayer, "Cannot set hostname on this system, continue anyway...");
+    }
+    else if (avahiRet != AVAHI_OK && avahiRet != AVAHI_ERR_NO_CHANGE)
+    {
+        error = CHIP_ERROR_INTERNAL;
+    }
+
+exit:
+    return error;
+}
+
+void MdnsAvahi::HandleClientState(AvahiClient * client, AvahiClientState state, void * context)
+{
+    static_cast<MdnsAvahi *>(context)->HandleClientState(client, state);
+}
+
+void MdnsAvahi::HandleClientState(AvahiClient * client, AvahiClientState state)
+{
+    switch (state)
+    {
+    case AVAHI_CLIENT_S_RUNNING:
+        ChipLogProgress(DeviceLayer, "Avahi client registered");
+        mClient = client;
+        mGroup  = avahi_entry_group_new(client, HandleGroupState, this);
+        if (mGroup == nullptr)
+        {
+            ChipLogError(DeviceLayer, "Failed to create avahi group: %s", avahi_strerror(avahi_client_errno(client)));
+            mInitCallback(mAsyncReturnContext, CHIP_ERROR_OPEN_FAILED);
+        }
+        else
+        {
+            mInitCallback(mAsyncReturnContext, CHIP_NO_ERROR);
+        }
+        break;
+    case AVAHI_CLIENT_FAILURE:
+        ChipLogError(DeviceLayer, "Avahi client failure");
+        mErrorCallback(mAsyncReturnContext, CHIP_ERROR_INTERNAL);
+        break;
+    case AVAHI_CLIENT_S_COLLISION:
+    case AVAHI_CLIENT_S_REGISTERING:
+        ChipLogProgress(DeviceLayer, "Avahi re-register required");
+        if (mGroup != nullptr)
+        {
+            avahi_entry_group_reset(mGroup);
+            avahi_entry_group_free(mGroup);
+        }
+        mGroup = avahi_entry_group_new(client, HandleGroupState, this);
+        mPublishedServices.clear();
+        if (mGroup == nullptr)
+        {
+            ChipLogError(DeviceLayer, "Failed to create avahi group: %s", avahi_strerror(avahi_client_errno(client)));
+            mErrorCallback(mAsyncReturnContext, CHIP_ERROR_OPEN_FAILED);
+        }
+        else
+        {
+            mErrorCallback(mAsyncReturnContext, CHIP_ERROR_FORCED_RESET);
+        }
+        break;
+    case AVAHI_CLIENT_CONNECTING:
+        ChipLogProgress(DeviceLayer, "Avahi connecting");
+        break;
+    }
+}
+
+void MdnsAvahi::HandleGroupState(AvahiEntryGroup * group, AvahiEntryGroupState state, void * context)
+{
+    static_cast<MdnsAvahi *>(context)->HandleGroupState(group, state);
+}
+
+void MdnsAvahi::HandleGroupState(AvahiEntryGroup * group, AvahiEntryGroupState state)
+{
+    switch (state)
+    {
+    case AVAHI_ENTRY_GROUP_ESTABLISHED:
+        ChipLogProgress(DeviceLayer, "Avahi group established");
+        break;
+    case AVAHI_ENTRY_GROUP_COLLISION:
+        ChipLogError(DeviceLayer, "Avahi group collission");
+        mErrorCallback(mAsyncReturnContext, CHIP_ERROR_MDNS_COLLISSION);
+        break;
+    case AVAHI_ENTRY_GROUP_FAILURE:
+        ChipLogError(DeviceLayer, "Avahi group internal failure %s",
+                     avahi_strerror(avahi_client_errno(avahi_entry_group_get_client(mGroup))));
+        mErrorCallback(mAsyncReturnContext, CHIP_ERROR_INTERNAL);
+        break;
+    case AVAHI_ENTRY_GROUP_UNCOMMITED:
+    case AVAHI_ENTRY_GROUP_REGISTERING:
+        break;
+    }
+}
+
+CHIP_ERROR MdnsAvahi::PublishService(const MdnsService & service)
+{
+    std::ostringstream keyBuilder;
+    std::string key;
+    std::string type       = GetFullType(service.mType, service.mProtocol);
+    CHIP_ERROR error       = CHIP_NO_ERROR;
+    AvahiStringList * text = nullptr;
+    AvahiIfIndex interface =
+        service.mInterface == INET_NULL_INTERFACEID ? AVAHI_IF_UNSPEC : static_cast<AvahiIfIndex>(service.mInterface);
+
+    keyBuilder << service.mName << "." << type << service.mPort << "." << interface;
+    key = keyBuilder.str();
+    ChipLogProgress(DeviceLayer, "PublishService %s", key.c_str());
+
+    if (mPublishedServices.find(key) == mPublishedServices.end())
+    {
+        SuccessOrExit(error = MakeAvahiStringListFromTextEntries(service.mTextEntries, service.mTextEntrySize, &text));
+
+        mPublishedServices.emplace(key);
+        VerifyOrExit(avahi_entry_group_add_service_strlst(mGroup, interface, ToAvahiProtocol(service.mAddressType),
+                                                          static_cast<AvahiPublishFlags>(0), service.mName, type.c_str(), nullptr,
+                                                          nullptr, service.mPort, text) == 0,
+                     error = CHIP_ERROR_INTERNAL);
+        for (size_t i = 0; i < service.mSubTypeSize; i++)
+        {
+            std::ostringstream sstream;
+
+            sstream << service.mSubTypes[i] << "._sub." << type;
+
+            VerifyOrExit(avahi_entry_group_add_service_subtype(mGroup, interface, ToAvahiProtocol(service.mAddressType),
+                                                               static_cast<AvahiPublishFlags>(0), service.mName, type.c_str(),
+                                                               nullptr, sstream.str().c_str()) == 0,
+                         error = CHIP_ERROR_INTERNAL);
+        }
+    }
+    else
+    {
+        SuccessOrExit(error = MakeAvahiStringListFromTextEntries(service.mTextEntries, service.mTextEntrySize, &text));
+
+        VerifyOrExit(avahi_entry_group_update_service_txt_strlst(mGroup, interface, ToAvahiProtocol(service.mAddressType),
+                                                                 static_cast<AvahiPublishFlags>(0), service.mName, type.c_str(),
+                                                                 nullptr, text) == 0,
+                     error = CHIP_ERROR_INTERNAL);
+    }
+
+    VerifyOrExit(avahi_entry_group_commit(mGroup) == 0, error = CHIP_ERROR_INTERNAL);
+
+exit:
+    if (text != nullptr)
+    {
+        avahi_string_list_free(text);
+    }
+    if (error != CHIP_NO_ERROR)
+    {
+        ChipLogError(DeviceLayer, "Avahi publish service failed: %d", static_cast<int>(error));
+    }
+
+    return error;
+}
+
+CHIP_ERROR MdnsAvahi::StopPublish()
+{
+    CHIP_ERROR error = CHIP_NO_ERROR;
+
+    VerifyOrExit(avahi_entry_group_reset(mGroup) == 0, error = CHIP_ERROR_INTERNAL);
+exit:
+    return error;
+}
+
+CHIP_ERROR MdnsAvahi::Browse(const char * type, MdnsServiceProtocol protocol, chip::Inet::IPAddressType addressType,
+                             chip::Inet::InterfaceId interface, MdnsBrowseCallback callback, void * context)
+{
+    AvahiServiceBrowser * browser;
+    BrowseContext * browseContext = static_cast<BrowseContext *>(chip::Platform::MemoryAlloc(sizeof(BrowseContext)));
+    AvahiIfIndex avahiInterface   = static_cast<AvahiIfIndex>(interface);
+
+    browseContext->mInstance = this;
+    browseContext->mContext  = context;
+    browseContext->mCallback = callback;
+    if (interface == INET_NULL_INTERFACEID)
+    {
+        avahiInterface = AVAHI_IF_UNSPEC;
+    }
+
+    browser = avahi_service_browser_new(mClient, avahiInterface, ToAvahiProtocol(addressType), GetFullType(type, protocol).c_str(),
+                                        nullptr, static_cast<AvahiLookupFlags>(0), HandleBrowse, browseContext);
+    // Otherwise the browser will be freed in the callback
+    if (browser == nullptr)
+    {
+        chip::Platform::MemoryFree(browseContext);
+    }
+
+    return browser == nullptr ? CHIP_ERROR_INTERNAL : CHIP_NO_ERROR;
+}
+
+MdnsServiceProtocol TruncateProtocolInType(char * type)
+{
+    char * deliminator           = strrchr(type, '.');
+    MdnsServiceProtocol protocol = MdnsServiceProtocol::kMdnsProtocolUnknown;
+
+    if (deliminator != NULL)
+    {
+        if (strcmp("._tcp", deliminator) == 0)
+        {
+            protocol     = MdnsServiceProtocol::kMdnsProtocolTcp;
+            *deliminator = 0;
+        }
+        else if (strcmp("._udp", deliminator) == 0)
+        {
+            protocol     = MdnsServiceProtocol::kMdnsProtocolUdp;
+            *deliminator = 0;
+        }
+    }
+    return protocol;
+}
+
+void MdnsAvahi::HandleBrowse(AvahiServiceBrowser * browser, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event,
+                             const char * name, const char * type, const char * domain, AvahiLookupResultFlags /*flags*/,
+                             void * userdata)
+{
+    BrowseContext * context = static_cast<BrowseContext *>(userdata);
+
+    switch (event)
+    {
+    case AVAHI_BROWSER_FAILURE:
+        context->mCallback(context->mContext, nullptr, 0, CHIP_ERROR_INTERNAL);
+        avahi_service_browser_free(browser);
+        chip::Platform::MemoryFree(context);
+        break;
+    case AVAHI_BROWSER_NEW:
+        ChipLogProgress(DeviceLayer, "Avahi browse: cache new");
+        if (strcmp("local", domain) == 0)
+        {
+            MdnsService service;
+
+            strncpy(service.mName, name, sizeof(service.mName));
+            strncpy(service.mType, type, sizeof(service.mType));
+            service.mName[kMdnsNameMaxSize] = 0;
+            service.mType[kMdnsTypeMaxSize] = 0;
+            service.mProtocol               = TruncateProtocolInType(service.mType);
+            service.mAddressType            = ToAddressType(protocol);
+            context->mServices.push_back(service);
+        }
+        break;
+    case AVAHI_BROWSER_ALL_FOR_NOW:
+        ChipLogProgress(DeviceLayer, "Avahi browse: all for now");
+        context->mCallback(context->mContext, context->mServices.data(), context->mServices.size(), CHIP_NO_ERROR);
+        avahi_service_browser_free(browser);
+        chip::Platform::MemoryFree(context);
+        break;
+    case AVAHI_BROWSER_REMOVE:
+        ChipLogProgress(DeviceLayer, "Avahi browse: remove");
+        if (strcmp("local", domain) == 0)
+        {
+            std::remove_if(context->mServices.begin(), context->mServices.end(), [name, type](const MdnsService service) {
+                return strcmp(name, service.mName) == 0 && type == GetFullType(service.mType, service.mProtocol);
+            });
+        }
+        break;
+    case AVAHI_BROWSER_CACHE_EXHAUSTED:
+        ChipLogProgress(DeviceLayer, "Avahi browse: cache exhausted");
+        break;
+    }
+}
+
+CHIP_ERROR MdnsAvahi::Resolve(const char * name, const char * type, MdnsServiceProtocol protocol,
+                              chip::Inet::IPAddressType addressType, chip::Inet::InterfaceId interface,
+                              MdnsResolveCallback callback, void * context)
+{
+    AvahiServiceResolver * resolver;
+    AvahiIfIndex avahiInterface     = static_cast<AvahiIfIndex>(interface);
+    ResolveContext * resolveContext = static_cast<ResolveContext *>(chip::Platform::MemoryAlloc(sizeof(ResolveContext)));
+    CHIP_ERROR error                = CHIP_NO_ERROR;
+
+    resolveContext->mInstance = this;
+    resolveContext->mCallback = callback;
+    resolveContext->mContext  = context;
+    if (interface == INET_NULL_INTERFACEID)
+    {
+        avahiInterface = AVAHI_IF_UNSPEC;
+    }
+    resolver = avahi_service_resolver_new(mClient, avahiInterface, ToAvahiProtocol(addressType), name,
+                                          GetFullType(type, protocol).c_str(), nullptr, ToAvahiProtocol(addressType),
+                                          static_cast<AvahiLookupFlags>(0), HandleResolve, resolveContext);
+    // Otherwise the resolver will be freed in the callback
+    if (resolver == nullptr)
+    {
+        error = CHIP_ERROR_INTERNAL;
+        chip::Platform::MemoryFree(resolver);
+    }
+
+    return error;
+}
+
+void MdnsAvahi::HandleResolve(AvahiServiceResolver * resolver, AvahiIfIndex interface, AvahiProtocol protocol,
+                              AvahiResolverEvent event, const char * name, const char * type, const char * /*domain*/,
+                              const char * /*host_name*/, const AvahiAddress * address, uint16_t port, AvahiStringList * txt,
+                              AvahiLookupResultFlags flags, void * userdata)
+{
+    ResolveContext * context = reinterpret_cast<ResolveContext *>(userdata);
+    std::vector<TextEntry> textEntries;
+
+    switch (event)
+    {
+    case AVAHI_RESOLVER_FAILURE:
+        ChipLogError(DeviceLayer, "Avahi resolve failed");
+        context->mCallback(context->mContext, nullptr, CHIP_ERROR_INTERNAL);
+        break;
+    case AVAHI_RESOLVER_FOUND:
+        MdnsService result;
+
+        result.mAddress.SetValue(chip::Inet::IPAddress());
+        ChipLogError(DeviceLayer, "Avahi resolve found");
+        strncpy(result.mName, name, sizeof(result.mName));
+        strncpy(result.mType, type, sizeof(result.mType));
+        result.mName[kMdnsNameMaxSize] = 0;
+        result.mType[kMdnsTypeMaxSize] = 0;
+        result.mProtocol               = TruncateProtocolInType(result.mType);
+        result.mPort                   = port;
+        result.mAddressType            = ToAddressType(protocol);
+
+        if (address)
+        {
+            switch (address->proto)
+            {
+            case AVAHI_PROTO_INET:
+                struct in_addr addr4;
+
+                memcpy(&addr4, &(address->data.ipv4), sizeof(addr4));
+                result.mAddress.SetValue(chip::Inet::IPAddress::FromIPv4(addr4));
+                break;
+            case AVAHI_PROTO_INET6:
+                struct in6_addr addr6;
+
+                memcpy(&addr6, &(address->data.ipv6), sizeof(addr6));
+                result.mAddress.SetValue(chip::Inet::IPAddress::FromIPv6(addr6));
+                break;
+            default:
+                break;
+            }
+        }
+
+        while (txt != nullptr)
+        {
+            for (size_t i = 0; i < txt->size; i++)
+            {
+                if (txt->text[i] == '=')
+                {
+                    txt->text[i] = '\0';
+                    textEntries.push_back(TextEntry{ reinterpret_cast<char *>(txt->text), &txt->text[i + 1], txt->size - i - 1 });
+                    break;
+                }
+            }
+            txt = txt->next;
+        }
+
+        if (!textEntries.empty())
+        {
+            result.mTextEntries = textEntries.data();
+        }
+        result.mTextEntrySize = textEntries.size();
+
+        context->mCallback(context->mContext, &result, CHIP_NO_ERROR);
+        break;
+    }
+
+    avahi_service_resolver_free(resolver);
+    chip::Platform::MemoryFree(context);
+}
+
+MdnsAvahi::~MdnsAvahi()
+{
+    if (mGroup)
+    {
+        avahi_entry_group_free(mGroup);
+    }
+    if (mClient)
+    {
+        avahi_client_free(mClient);
+    }
+}
+
+void UpdateMdnsDataset(fd_set & readFdSet, fd_set & writeFdSet, fd_set & errorFdSet, int & maxFd, timeval & timeout)
+{
+    MdnsAvahi::GetInstance().GetPoller().UpdateFdSet(readFdSet, writeFdSet, errorFdSet, maxFd, timeout);
+}
+
+void ProcessMdns(fd_set & readFdSet, fd_set & writeFdSet, fd_set & errorFdSet)
+{
+    MdnsAvahi::GetInstance().GetPoller().Process(readFdSet, writeFdSet, errorFdSet);
+}
+
+CHIP_ERROR ChipMdnsInit(MdnsAsyncReturnCallback initCallback, MdnsAsyncReturnCallback errorCallback, void * context)
+{
+    return MdnsAvahi::GetInstance().Init(initCallback, errorCallback, context);
+}
+
+CHIP_ERROR ChipMdnsSetHostname(const char * hostname)
+{
+    return MdnsAvahi::GetInstance().SetHostname(hostname);
+}
+
+CHIP_ERROR ChipMdnsPublishService(const MdnsService * service)
+{
+    return MdnsAvahi::GetInstance().PublishService(*service);
+}
+
+CHIP_ERROR ChipMdnsStopPublish()
+{
+    return MdnsAvahi::GetInstance().StopPublish();
+}
+
+CHIP_ERROR ChipMdnsBrowse(const char * type, MdnsServiceProtocol protocol, chip::Inet::IPAddressType addressType,
+                          chip::Inet::InterfaceId interface, MdnsBrowseCallback callback, void * context)
+{
+    return MdnsAvahi::GetInstance().Browse(type, protocol, addressType, interface, callback, context);
+}
+
+CHIP_ERROR ChipMdnsResolve(MdnsService * browseResult, chip::Inet::InterfaceId interface, MdnsResolveCallback callback,
+                           void * context)
+
+{
+    CHIP_ERROR error;
+
+    if (browseResult != nullptr)
+    {
+        error = MdnsAvahi::GetInstance().Resolve(browseResult->mName, browseResult->mType, browseResult->mProtocol,
+                                                 browseResult->mAddressType, interface, callback, context);
+    }
+    else
+    {
+        error = CHIP_ERROR_INVALID_ARGUMENT;
+    }
+    return error;
+}
+
+} // namespace Mdns
+} // namespace chip
diff --git a/packaging/tizen_fix/crypto.gni b/packaging/tizen_fix/crypto.gni
new file mode 100644 (file)
index 0000000..9e5152d
--- /dev/null
@@ -0,0 +1,30 @@
+# Copyright (c) 2020 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+declare_args() {
+  # Crypto implementation: mbedtls, openssl.
+  chip_crypto = ""
+}
+
+if (chip_crypto == "") {
+  if (current_os == "android" || current_os == "freertos" ||
+      current_os == "zephyr" || current_os == "linux") {
+    chip_crypto = "mbedtls"
+  } else {
+    chip_crypto = "openssl"
+  }
+}
+
+assert(chip_crypto == "mbedtls" || chip_crypto == "openssl",
+       "Please select a valid crypto implementation: mbedtls, openssl")
diff --git a/packaging/tizen_fix/tizen_fix.sh b/packaging/tizen_fix/tizen_fix.sh
new file mode 100755 (executable)
index 0000000..b2dfc40
--- /dev/null
@@ -0,0 +1,18 @@
+#!/bin/bash
+SCRIPT_DIR=`dirname "$0"`
+DST_PATH=$SCRIPT_DIR/../../
+FILE1="BUILD.gn"
+FILE2="src/crypto/crypto.gni"
+FILE3="src/platform/Linux/MdnsImpl.cpp"
+
+git clone https://github.com/project-chip/connectedhomeip
+cd connectedhomeip
+git submodule update --init
+rm -rf .git/
+cd ..
+cp -rf ./connectedhomeip/* $DST_PATH
+rm -rf ./connectedhomeip/
+
+cp ${SCRIPT_DIR}/BUILD.gn ${DST_PATH}${FILE1}
+cp ${SCRIPT_DIR}/crypto.gni ${DST_PATH}${FILE2}
+cp ${SCRIPT_DIR}/MdnsImpl.cpp ${DST_PATH}${FILE3}