From: Sangchul Lee Date: Mon, 11 Jan 2021 12:10:28 +0000 (+0900) Subject: webrtc_signaling_server: Add internal API set for signaling server X-Git-Tag: submit/tizen/20210729.023123~151 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=84d1ffc2e74a235b826096d949082453ad8ae85d;p=platform%2Fcore%2Fapi%2Fwebrtc.git webrtc_signaling_server: Add internal API set for signaling server This signaling server is only for private network. Handling messages between server and client will be added with following patches. Functions are adde as below. - webrtc_signaling_server_create() - webrtc_signaling_server_start() - webrtc_signaling_server_stop() - webrtc_signaling_server_destroy() [Version] 0.1.90 [Issue Type] API Change-Id: I7719cacb9bcb1a0639b0e425067beba5fcb4a881 Signed-off-by: Sangchul Lee --- diff --git a/include/webrtc_internal.h b/include/webrtc_internal.h index 55224cec..1e2c53b9 100644 --- a/include/webrtc_internal.h +++ b/include/webrtc_internal.h @@ -31,6 +31,13 @@ extern "C" { * @{ */ +/** + * @internal + * @brief WebRTC signaling server handle type. + * @since_tizen 6.5 + */ +typedef void *webrtc_signaling_server_h; + /** * @internal * @brief Set an ecore wayland display to the media track. @@ -50,6 +57,70 @@ extern "C" { */ int webrtc_set_ecore_wl_display(webrtc_h webrtc, unsigned int track_id, void *ecore_wl_window); +/** + * @internal + * @brief Create a signaling server for private network. + * @since_tizen 6.5 + * @param[in] port The port number + * @param[out] server Signaling server handle + * @return @c 0 on success, + * otherwise a negative error value + * @retval #WEBRTC_ERROR_NONE Successful + * @retval #WEBRTC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #WEBRTC_ERROR_INVALID_OPERATION Invalid operation + * @see webrtc_signaling_server_start() + * @see webrtc_signaling_server_stop() + * @see webrtc_signaling_server_destroy() + */ +int webrtc_signaling_server_create(int port, webrtc_signaling_server_h *server); + +/** + * @internal + * @brief Start the signaling server. + * @since_tizen 6.5 + * @param[in] server Signaling server handle + * @return @c 0 on success, + * otherwise a negative error value + * @retval #WEBRTC_ERROR_NONE Successful + * @retval #WEBRTC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #WEBRTC_ERROR_INVALID_OPERATION Invalid operation + * @pre Call webrtc_signaling_server_create() before calling this function. + * @see webrtc_signaling_server_stop() + * @see webrtc_signaling_server_destroy() + */ +int webrtc_signaling_server_start(webrtc_signaling_server_h server); + +/** + * @internal + * @brief Stop the signaling server. + * @since_tizen 6.5 + * @param[in] server Signaling server handle + * @return @c 0 on success, + * otherwise a negative error value + * @retval #WEBRTC_ERROR_NONE Successful + * @retval #WEBRTC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #WEBRTC_ERROR_INVALID_OPERATION Invalid operation + * @pre Call webrtc_signaling_server_start() before calling this function. + * @see webrtc_signaling_server_start() + * @see webrtc_signaling_server_destroy() + */ +int webrtc_signaling_server_stop(webrtc_signaling_server_h server); + +/** + * @internal + * @brief Destroy the signaling server. + * @since_tizen 6.5 + * @param[in] server Signaling server handle + * @return @c 0 on success, + * otherwise a negative error value + * @retval #WEBRTC_ERROR_NONE Successful + * @retval #WEBRTC_ERROR_INVALID_PARAMETER Invalid parameter + * @pre Call webrtc_signaling_server_create() before calling this function. + * @see webrtc_signaling_server_start() + * @see webrtc_signaling_server_stop() + */ +int webrtc_signaling_server_destroy(webrtc_signaling_server_h server); + /** * @} */ diff --git a/include/webrtc_private.h b/include/webrtc_private.h index 6eea4f9b..1dd9159f 100644 --- a/include/webrtc_private.h +++ b/include/webrtc_private.h @@ -358,6 +358,13 @@ typedef struct _webrtc_websocket_s { struct lws_context *context; } webrtc_websocket_s; +typedef struct _webrtc_signaling_server_s { + GMutex mutex; + webrtc_websocket_s *ws; + GThread *thread; + bool exit_thread; +} webrtc_signaling_server_s; + int _load_ini(webrtc_s *webrtc); void _unload_ini(webrtc_s *webrtc); ini_item_media_source_s* _ini_get_source_by_type(webrtc_ini_s *ini, webrtc_media_source_type_e type); diff --git a/packaging/capi-media-webrtc.spec b/packaging/capi-media-webrtc.spec index c8a08d32..05068d6f 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.1.89 +Version: 0.1.90 Release: 0 Group: Multimedia/API License: Apache-2.0 diff --git a/src/webrtc_signaling_server.c b/src/webrtc_signaling_server.c new file mode 100644 index 00000000..88208a5e --- /dev/null +++ b/src/webrtc_signaling_server.c @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2021 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.h" +#include "webrtc_private.h" +#include "webrtc_internal.h" + +static void __send_message(struct lws *wsi, const char *message) +{ + guchar *buffer; + int size; + int len; + + RET_IF(wsi == NULL, "wsi is NULL"); + RET_IF(message == NULL, "message is NULL"); + + len = strlen(message) + 1; + + buffer = g_malloc0(LWS_SEND_BUFFER_PRE_PADDING + len + LWS_SEND_BUFFER_POST_PADDING); + + memcpy(buffer + LWS_SEND_BUFFER_PRE_PADDING, message, len); + + size = lws_write(wsi, (buffer + LWS_SEND_BUFFER_PRE_PADDING), len, LWS_WRITE_TEXT); + if (size == -1) + LOG_ERROR("failed to lws_write()"); + else + LOG_DEBUG("message is sent[size:%d, %s]", size, buffer + LWS_SEND_BUFFER_PRE_PADDING); + + g_free(buffer); + + return; +} + +static int __ws_cb(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) +{ + LOG_DEBUG("wsi[%p] reason[%d] user[%p] in[%p] size[%zu]", wsi, reason, user, in, len); + + switch (reason) { + case LWS_CALLBACK_ESTABLISHED: + LOG_INFO("ESTABLISHED"); + /* FIXME: send message with unique id */ + __send_message(wsi, "ESTABLISHED"); + break; + case LWS_CALLBACK_RECEIVE: { + gchar *message = g_strndup((const gchar*)in, (gsize)len); + LOG_INFO("RECEIVE:\n%s", message); + /* FIXME: handle received message from client */ + g_free(message); + break; + } + case LWS_CALLBACK_CLOSED: + LOG_INFO("CLOSED"); + break; + case LWS_CALLBACK_PROTOCOL_INIT: + LOG_DEBUG("PROTOCOL INIT"); + break; + case LWS_CALLBACK_PROTOCOL_DESTROY: + LOG_DEBUG("PROTOCOL DESTROY"); + break; + case LWS_CALLBACK_WSI_CREATE: + LOG_DEBUG("WSI CREATE"); + break; + case LWS_CALLBACK_WSI_DESTROY: + LOG_DEBUG("WSI DESTROY"); + break; + case LWS_CALLBACK_EVENT_WAIT_CANCELLED: + LOG_DEBUG("EVENT WAIT CANCELLED"); + break; + default: + LOG_DEBUG("reason(%d)", reason); + break; + } + + return 0; +} + +static gpointer __thread_func(gpointer data) +{ + webrtc_signaling_server_s *server = (webrtc_signaling_server_s *)data; + RET_VAL_IF(server == NULL, NULL, "server is NULL"); + RET_VAL_IF(server->ws == NULL, NULL, "ws is NULL"); + + LOG_DEBUG(">>>>> start thread func, server[%p]", server); + + while (!server->exit_thread) { + if (_start_websocket(server->ws, 1000) != WEBRTC_ERROR_NONE) + LOG_ERROR("failed to _start_websocket()"); + } + + LOG_DEBUG("<<<<< exit thread func, server[%p]", server); + + return NULL; +} + +int webrtc_signaling_server_create(int port, webrtc_signaling_server_h *server) +{ + webrtc_signaling_server_s *_server; + + RET_VAL_IF(server == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "server is NULL"); + + _server = g_new0(webrtc_signaling_server_s, 1); + + /* FIXME: check the parameters from ini */ + _server->ws = _alloc_websocket(port, NULL, NULL, NULL, __ws_cb, _server); + if (!_server->ws) { + LOG_ERROR("failed to _alloc_websocket(), port[%d]", port); + g_free(_server); + return WEBRTC_ERROR_INVALID_OPERATION; + } + + g_mutex_init(&_server->mutex); + + *server = _server; + + LOG_INFO("server[%p, port:%d]", *server, port); + + return WEBRTC_ERROR_NONE; +} + +int webrtc_signaling_server_start(webrtc_signaling_server_h server) +{ + int ret = WEBRTC_ERROR_NONE; + webrtc_signaling_server_s *_server = (webrtc_signaling_server_s *)server; + GError *error; + + RET_VAL_IF(server == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "server is NULL"); + + g_mutex_lock(&_server->mutex); + + if (_server->thread) { + LOG_DEBUG("thread[%p] has been already started", _server->thread); + g_mutex_unlock(&_server->mutex); + return WEBRTC_ERROR_NONE; + } + + _server->exit_thread = false; + + _server->thread = g_thread_try_new("signaling-thread", __thread_func, _server, &error); + RET_VAL_WITH_UNLOCK_IF(_server->thread == NULL, WEBRTC_ERROR_INVALID_OPERATION, &_server->mutex, + "failed to g_thread_try_new(), error[%s]", error->message); + + LOG_INFO("server[%p, thread:%p]", _server, _server->thread); + + g_mutex_unlock(&_server->mutex); + + return ret; +} + +static void __stop_server(webrtc_signaling_server_s *server) +{ + RET_IF(server == NULL, "server is NULL"); + + server->exit_thread = true; + + if (_stop_websocket(server->ws) != WEBRTC_ERROR_NONE) + LOG_WARNING("failed to _stop_websocket()"); + + LOG_DEBUG("thread[%p]", server->thread); + + g_thread_join(server->thread); + + LOG_DEBUG("thread[%p] is joined", server->thread); + + server->thread = NULL; +} + +int webrtc_signaling_server_stop(webrtc_signaling_server_h server) +{ + webrtc_signaling_server_s *_server = (webrtc_signaling_server_s *)server; + + RET_VAL_IF(server == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "server is NULL"); + + g_mutex_lock(&_server->mutex); + + RET_VAL_WITH_UNLOCK_IF(_server->thread == NULL, WEBRTC_ERROR_INVALID_OPERATION, &_server->mutex, "thread is NULL"); + + __stop_server(_server); + + g_mutex_unlock(&_server->mutex); + + return WEBRTC_ERROR_NONE; +} + +int webrtc_signaling_server_destroy(webrtc_signaling_server_h server) +{ + webrtc_signaling_server_s *_server = (webrtc_signaling_server_s *)server; + + RET_VAL_IF(server == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "server is NULL"); + + g_mutex_lock(&_server->mutex); + + if (!_server->exit_thread) + __stop_server(_server); + + _release_websocket(_server->ws); + + LOG_INFO("server[%p]", _server); + + g_mutex_unlock(&_server->mutex); + g_mutex_clear(&_server->mutex); + + g_free(_server); + + return WEBRTC_ERROR_NONE; +}