From: Sangchul Lee Date: Fri, 23 Dec 2022 06:31:10 +0000 (+0900) Subject: webrtc_dns: Add support for registering DNS service X-Git-Tag: accepted/tizen/unified/20230109.151011~3 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=cbb39ec1054d882ea9619b4d91b59493f5e68ccd;p=platform%2Fcore%2Fapi%2Fwebrtc.git webrtc_dns: Add support for registering DNS service This patch uses dns_sd.h of mdnsresponder to register DNS service and to publish hostname for private IP address. [Version] 0.3.276 [Issue type] New feature Change-Id: I9a9d64c367b2a49f2fe6e2ca7d1cd3ceca91770d Signed-off-by: Sangchul Lee --- diff --git a/CMakeLists.txt b/CMakeLists.txt index dc637db6..44bd99ee 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,7 @@ INCLUDE_DIRECTORIES(${INC_DIR}) SET(dependents "dlog glib-2.0 gstreamer-1.0 gstreamer-webrtc-1.0 gstreamer-video-1.0 gstreamer-audio-1.0 \ gstreamer-allocators-1.0 libpulse json-glib-1.0 iniparser mm-common mm-display-interface capi-media-tool \ libtbm libwebsockets cynara-client libsmack capi-system-info libsoup-2.4 bundle capi-media-sound-manager \ - mm-fileinfo mmutil-common mmutil-imgp mmutil-jpeg mmutil-magick") + mm-fileinfo mmutil-common mmutil-imgp mmutil-jpeg mmutil-magick dns_sd") IF(NOT TIZEN_PROFILE_TV) SET(dependents "${dependents} mm-resource-manager") IF(TIZEN_FEATURE_UI) diff --git a/include/webrtc_private.h b/include/webrtc_private.h index 9f3c468d..cc863585 100644 --- a/include/webrtc_private.h +++ b/include/webrtc_private.h @@ -32,6 +32,7 @@ #include #include #include +#include #include "webrtc_internal.h" @@ -513,6 +514,11 @@ typedef struct _webrtc_s { GAsyncQueue *queue; } snapshot; + struct { + DNSServiceRef client; + DNSServiceRef client_pa; /* proxy address record */ + } dns; + guint idle_cb_event_source_ids[IDLE_CB_TYPE_NUM]; webrtc_callbacks_s error_cb; @@ -840,6 +846,10 @@ void _destroy_tbm_bo_list(webrtc_tbm_s *tbm); void *_get_unused_tbm_bo(webrtc_tbm_s *tbm, unsigned int timeout_sec); void _release_tbm_bo(webrtc_tbm_s *tbm, void *bo); +/* DNS */ +int _register_dns_service(webrtc_s *webrtc); +void _unregister_dns_service(webrtc_s *webrtc); + /* websocket*/ typedef int (*_websocket_cb)(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len); webrtc_websocket_s *_alloc_websocket(const int port, const char *ssl_cert_path, const char *ssl_private_key_path, const char *ssl_ca_path, _websocket_cb callback, void *user_data); diff --git a/packaging/capi-media-webrtc.spec b/packaging/capi-media-webrtc.spec index ed2e87cd..bd0c0934 100644 --- a/packaging/capi-media-webrtc.spec +++ b/packaging/capi-media-webrtc.spec @@ -1,6 +1,6 @@ Name: capi-media-webrtc Summary: A WebRTC library in Tizen Native API -Version: 0.3.275 +Version: 0.3.276 Release: 0 Group: Multimedia/API License: Apache-2.0 @@ -39,6 +39,7 @@ BuildRequires: pkgconfig(mmutil-common) BuildRequires: pkgconfig(mmutil-imgp) BuildRequires: pkgconfig(mmutil-jpeg) BuildRequires: pkgconfig(mmutil-magick) +BuildRequires: pkgconfig(dns_sd) %if "%{tizen_profile_name}" != "tv" BuildRequires: pkgconfig(mm-resource-manager) BuildRequires: pkgconfig(capi-system-sensor) diff --git a/src/webrtc_dns.c b/src/webrtc_dns.c new file mode 100644 index 00000000..fc6aa09a --- /dev/null +++ b/src/webrtc_dns.c @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 "webrtc_private.h" +#include +#include +#include +#include +#include + +#define DNSS_REGISTER_NAME "nativeWebRTC" +#define DNSS_REGISTER_HOST "nativewebrtc.local" + +//LCOV_EXCL_START +static void __dns_service_register_record_cb(DNSServiceRef service, DNSRecordRef record, const DNSServiceFlags flags, DNSServiceErrorType error_type, + void *context) +{ + char *hostname = (char *)context; + LOG_DEBUG("service[%p] record[%p] flags[0x%x] error_type[0x%x] hostname[%s]", service, record, flags, error_type, hostname); + + switch (error_type) { + case kDNSServiceErr_NoError: + LOG_INFO("name now registered and active"); + break; + case kDNSServiceErr_NameConflict: + LOG_ERROR("name in use, please choose another"); + break; + default: + LOG_ERROR("error %d", error_type); + break; + } +} + +static void __dns_service_register_reply_cb(DNSServiceRef service, DNSServiceFlags flags, DNSServiceErrorType error_type, const char *name, + const char *regtype, const char *domain, void *context) +{ + LOG_DEBUG("service[%p] flags[0x%x] error_type[0x%x] name[%s] regtype[%s] domain[%s] context[%p]", + service, flags, error_type, name, regtype, domain, context); + + switch (error_type) { + case kDNSServiceErr_NoError: + LOG_INFO("name now registered and active"); + break; + case kDNSServiceErr_NameConflict: + LOG_ERROR("name in use, please choose another"); + break; + default: + LOG_ERROR("error %d", error_type); + break; + } +} + +static gchar *__get_my_private_ip(void) +{ + struct ifaddrs *ifaddr = NULL; + struct ifaddrs *ifaddr_ptr = NULL; + void *sin_addr = NULL; + char addressBuffer[INET_ADDRSTRLEN]; + gchar *ip = NULL; + + getifaddrs(&ifaddr); + + for (ifaddr_ptr = ifaddr; ifaddr_ptr != NULL; ifaddr_ptr = ifaddr_ptr->ifa_next) { + if (!ifaddr_ptr->ifa_addr) + continue; + + if (ifaddr_ptr->ifa_addr->sa_family != AF_INET) /* TODO: IPv6 */ + continue; + + sin_addr = &((struct sockaddr_in *)ifaddr_ptr->ifa_addr)->sin_addr; + inet_ntop(AF_INET, sin_addr, addressBuffer, INET_ADDRSTRLEN); + if (!g_str_has_prefix(addressBuffer, "192.168.")) + continue; + + LOG_DEBUG("%s IPv4 Address %s", (const char *)ifaddr_ptr->ifa_name, addressBuffer); + ip = g_strdup(addressBuffer); + break; + } + + if (ifaddr) + freeifaddrs(ifaddr); + + return ip; +} + +int _register_dns_service(webrtc_s *webrtc) +{ + int ret; + struct sockaddr_storage hostaddr; + struct addrinfo *addrs = NULL; + static DNSRecordRef record = NULL; + gchar *ip; + const char *host = DNSS_REGISTER_HOST; + + RET_VAL_IF(webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL"); + RET_VAL_IF(webrtc->dns.client_pa != NULL, WEBRTC_ERROR_INVALID_OPERATION, "client_pa has been already registered"); + RET_VAL_IF(webrtc->dns.client != NULL, WEBRTC_ERROR_INVALID_OPERATION, "client_pa has been already registered"); + + ip = __get_my_private_ip(); + RET_VAL_IF(ip == NULL, WEBRTC_ERROR_INVALID_OPERATION, "ip is NULL"); + + ret = DNSServiceCreateConnection(&webrtc->dns.client_pa); + if (ret != kDNSServiceErr_NoError) { + LOG_ERROR("failed to DNSServiceCreateConnection(), ret[0x%x]", ret); + goto error; + } + + memset(&hostaddr, 0, sizeof(hostaddr)); + ret = getaddrinfo((const char *)ip, NULL, NULL, &addrs); + if (ret) { + LOG_ERROR("failed to getaddrinfo(), error %d for %s", ret, ip); + goto error; + } + memcpy(&hostaddr, addrs->ai_addr, sizeof(struct sockaddr_in)); + freeaddrinfo(addrs); + + if (hostaddr.ss_family != AF_INET) { /* ToDO: support IPv6 */ + LOG_ERROR("hostaddr.ss_family is not AF_INET"); + goto error; + } + + ret = DNSServiceRegisterRecord(webrtc->dns.client_pa, &record, kDNSServiceFlagsUnique, kDNSServiceInterfaceIndexAny, host, + kDNSServiceType_A, kDNSServiceClass_IN, 4, &((struct sockaddr_in *)&hostaddr)->sin_addr, 240, __dns_service_register_record_cb, (void*)host); + if (ret != kDNSServiceErr_NoError) { + LOG_ERROR("failed to DNSServiceRegisterRecord(), ret[0x%x]", ret); + goto error; + } + + ret = DNSServiceRegister(&webrtc->dns.client, + kDNSServiceFlagsUnique, /* flags */ + 0, /* interfaceIndex */ + DNSS_REGISTER_NAME, /* name */ + "_http._tcp", /* regtype */ + "", /* domain */ + host, /* host */ + htons(80), /* port */ + 0, /* txtLen */ + NULL, /* txtRecord */ + __dns_service_register_reply_cb, /* callback */ + NULL /* context */ + ); + if (ret != kDNSServiceErr_NoError) { + LOG_ERROR("failed to DNSServiceRegister(), ret[0x%x]", ret); + goto error; + } + + LOG_INFO("client_pa[%p] client[%p] name[%s] host[%s] ip[%s]", webrtc->dns.client_pa, webrtc->dns.client, DNSS_REGISTER_NAME, host, ip); + + g_free(ip); + + return WEBRTC_ERROR_NONE; + +error: + g_free(ip); + if (webrtc->dns.client_pa) { + DNSServiceRefDeallocate(webrtc->dns.client_pa); + webrtc->dns.client_pa = NULL; + } + if (webrtc->dns.client) { + DNSServiceRefDeallocate(webrtc->dns.client); + webrtc->dns.client = NULL; + } + return WEBRTC_ERROR_INVALID_OPERATION; +} + +void _unregister_dns_service(webrtc_s *webrtc) +{ + RET_IF(webrtc == NULL, "webrtc is NULL"); + RET_IF(webrtc->dns.client_pa == NULL, "client_pa is NULL"); + RET_IF(webrtc->dns.client == NULL, "client is NULL"); + + LOG_INFO("client_pa[%p] client[%p]", webrtc->dns.client_pa, webrtc->dns.client); + + DNSServiceRefDeallocate(webrtc->dns.client_pa); + DNSServiceRefDeallocate(webrtc->dns.client); + webrtc->dns.client_pa = NULL; + webrtc->dns.client = NULL; +} +//LCOV_EXCL_STOP