Skip to content

RDKEMW-6898: gdialserver not compatible with Libsoup3 library#203

Open
balav08 wants to merge 7 commits into
developfrom
feature/RDKEMW-6898-may18-new
Open

RDKEMW-6898: gdialserver not compatible with Libsoup3 library#203
balav08 wants to merge 7 commits into
developfrom
feature/RDKEMW-6898-may18-new

Conversation

@balav08
Copy link
Copy Markdown

@balav08 balav08 commented May 18, 2026

Reason for change: gdialserver not compatible with Libsoup3 library Updating gssdp to 1.6.3 provides libsoup3 compatibility .
Test Procedure: Compiled and Verified
Risks: Low
Priority: P1
version: minor

Reason for change: gdialserver not compatible with Libsoup3 library
Updating gssdp to 1.6.3 provides libsoup3 compatibility .
Test Procedure: Compiled and Verified
Risks: Low
Priority: P1
version: minor

Signed-off-by: balaji velmurugan <balaji_velmurugan@comcast.com>
@balav08 balav08 requested a review from a team as a code owner May 18, 2026 06:31
Copilot AI review requested due to automatic review settings May 18, 2026 06:31
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds libsoup 3 / GSSDP 1.6 compatibility while preserving a libsoup 2.4 build path for the GDial server.

Changes:

  • Splits REST, SSDP, and shield implementations into server/libsoup/2.4 and server/libsoup/3.0.
  • Updates CMake to select libsoup/GSSDP versions and corresponding source files.
  • Adds libsoup3-specific handling in gdialservice.cpp.

Reviewed changes

Copilot reviewed 5 out of 8 changed files in this pull request and generated 15 comments.

Show a summary per file
File Description
server/CMakeLists.txt Selects libsoup 3 or 2.4 source sets and GSSDP dependencies.
server/gdialservice.cpp Adds libsoup3-compatible callback and URI logging code paths.
server/libsoup/3.0/gdial-rest.c Adds REST server implementation using libsoup3 APIs.
server/libsoup/3.0/gdial-ssdp.c Adds SSDP implementation using libsoup3/GSSDP 1.6 APIs.
server/libsoup/3.0/gdial-shield.c Adds request-throttling shield implementation for libsoup3.
server/libsoup/2.4/gdial-rest.c Adds libsoup2.4 REST implementation in versioned path.
server/libsoup/2.4/gdial-ssdp.c Adds libsoup2.4 SSDP implementation in versioned path.
server/libsoup/2.4/gdial-shield.c Adds libsoup2.4 shield implementation in versioned path.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread server/libsoup/3.0/gdial-ssdp.c
Comment thread server/libsoup/3.0/gdial-ssdp.c
Comment thread server/libsoup/3.0/gdial-ssdp.c
Comment thread server/libsoup/3.0/gdial-rest.c
Comment thread server/libsoup/3.0/gdial-rest.c
Comment thread server/libsoup/3.0/gdial-ssdp.c
Comment thread server/libsoup/3.0/gdial-ssdp.c
Comment thread server/libsoup/3.0/gdial-rest.c
Comment thread server/libsoup/3.0/gdial-rest.c
Comment thread server/libsoup/3.0/gdial-rest.c
Copilot AI review requested due to automatic review settings May 18, 2026 06:59
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 10 changed files in this pull request and generated 8 comments.

Comments suppressed due to low confidence (4)

server/libsoup/3.0/gdial-rest.c:494

  • g_uri_escape_string() returns memory allocated by GLib and must be released with g_free(), not free(). Mixing allocators can corrupt memory on platforms where GLib is not using the system allocator.
        char *tmp = g_uri_escape_string(payload, "=&", FALSE);
        // note that we later g_free(payload_safe) which doesn't necessarily work with malloc'ed memory (seems to depend on glib version)
        payload_safe = g_strdup(tmp);
        free(tmp);

server/libsoup/3.0/gdial-rest.c:501

  • additional_data_url_safe is allocated by g_uri_escape_string(), so it must be released with g_free() rather than free(). Using the wrong deallocator risks heap corruption with non-system GLib allocators.
    start_error = gdial_app_start(app, payload_safe, query_str_safe, additional_data_url_safe, gdial_rest_server);
    if (query_str_safe) g_free(query_str_safe);
    if (payload_safe) g_free(payload_safe);
    free(additional_data_url_safe);
    g_free(additional_data_url);

server/libsoup/3.0/gdial-rest.c:1015

  • priv->local_soup_instance is unreffed before the registered app handlers are removed, but gdial_rest_server_registered_apps_clear() uses that same server to call soup_server_remove_handler(). If this unref drops the last reference, dispose will use a freed SoupServer; the handlers should be removed before releasing the server references.
  g_object_unref(priv->soup_instance);
  g_object_unref(priv->local_soup_instance);
  while (priv->registered_apps) {
    priv->registered_apps = gdial_rest_server_registered_apps_clear(object, priv->registered_apps, priv->registered_apps);

server/libsoup/3.0/gdial-rest.c:940

  • For a valid POST to the dial_data endpoint this branch only verifies the method and then falls through without calling gdial_rest_server_handle_POST_dial_data() or setting the response status/body. As a result, /.../<app>/dial_data POST requests from loopback are accepted but the dial data is never cached.
      else {
        gdial_rest_server_http_return_if_fail(soup_server_message_get_method(msg) == SOUP_METHOD_POST, msg, SOUP_STATUS_NOT_IMPLEMENTED);

Comment thread configure.ac
[libsoup_version="2.4"],
[PKG_CHECK_MODULES([SOUP], [libsoup-3.0],
[],
[libsoup_version="3.0"],
Comment thread tests/L1Tests/Makefile.am
Comment on lines +94 to +98
if LIBSOUP_3_0
run_L1Tests_SOURCES += \
$(top_srcdir)/server/libsoup/3.0/gdial-rest.c \
$(top_srcdir)/server/libsoup/3.0/gdial-shield.c \
$(top_srcdir)/server/libsoup/3.0/gdial-ssdp.c
Comment thread server/CMakeLists.txt
pthread_mutex_lock(&ssdpServerEventSync);
if (ssdp_http_server_)
{
soup_server_remove_handler(ssdp_http_server_, "/dd.xml");
gint instance_id = (gint)g_ascii_strtoll(instance, &endptr, 10);
if (strlen(endptr) == 0) {
app_by_instance = gdial_app_find_instance_by_instance_id(instance_id);
g_return_val_if_fail(app == app_by_instance, app);
Comment on lines +136 to +143
GDIAL_LOGTRACE("Entering ...");
g_return_if_fail(active_conns_ != NULL);
GDIAL_LOGINFO("gdial_shield_term: hash_table_size start= %d", g_hash_table_size(active_conns_));
g_hash_table_iter_init(&iter, (GHashTable *)active_conns_);
while (g_hash_table_iter_next(&iter, &key, &value)) {
SoupMessage *msg = (SoupMessage *)key;
server_request_remove_callback(msg);
}
/*
* Any request only respond to app name that is among registered apps
*/
g_signal_emit(gdial_rest_server, gdial_rest_server_signals[SIGNAL_INVALID_URI], 0, "URI containes unregistered app name");
ssdp_http_server_ = ssdp_http_server;
app_random_uuid = g_strdup(random_uuid);
gchar *dail_ssdp_handler = g_strdup_printf("/%s/%s", random_uuid,"dd.xml");
soup_server_add_handler(ssdp_http_server_, dail_ssdp_handler, ssdp_http_server_callback, NULL, NULL);
Copilot AI review requested due to automatic review settings May 18, 2026 08:48
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 10 changed files in this pull request and generated 10 comments.

Comment thread configure.ac Outdated
Comment on lines +47 to +49
[PKG_CHECK_MODULES([SOUP], [libsoup-3.0],
[libsoup_version="3.0"],
PKG_CHECK_MODULES([SOUP], [libsoup-2.4],
Comment thread tests/L1Tests/Makefile.am
Comment on lines 94 to +98
$(top_srcdir)/server/plat/gdial-plat-util.c \
$(top_srcdir)/server/plat/gdialappcache.cpp \
$(top_srcdir)/server/plat/gdial_app_registry.c

if LIBSOUP_2_4
Comment thread tests/L1Tests/Makefile.am
Comment on lines 94 to +98
$(top_srcdir)/server/plat/gdial-plat-util.c \
$(top_srcdir)/server/plat/gdialappcache.cpp \
$(top_srcdir)/server/plat/gdial_app_registry.c

if LIBSOUP_2_4
gint instance_id = (gint)g_ascii_strtoll(instance, &endptr, 10);
if (strlen(endptr) == 0) {
app_by_instance = gdial_app_find_instance_by_instance_id(instance_id);
g_return_val_if_fail(app == app_by_instance, app);
Comment on lines +134 to +143
GHashTableIter iter;
gpointer key, value;
GDIAL_LOGTRACE("Entering ...");
g_return_if_fail(active_conns_ != NULL);
GDIAL_LOGINFO("gdial_shield_term: hash_table_size start= %d", g_hash_table_size(active_conns_));
g_hash_table_iter_init(&iter, (GHashTable *)active_conns_);
while (g_hash_table_iter_next(&iter, &key, &value)) {
SoupMessage *msg = (SoupMessage *)key;
server_request_remove_callback(msg);
}
pthread_mutex_lock(&ssdpServerEventSync);
if (ssdp_http_server_)
{
soup_server_remove_handler(ssdp_http_server_, "/dd.xml");
g_string_append_printf(rbuf, " <link rel=\"run\" href=\"%s\"/>\r\n", rbuilder->link_href);
}
if (rbuilder->additionalData) {
g_string_append_printf(rbuf, " <additionalData>%s</additionalData>\r\n", "");
Comment on lines +491 to +494
char *tmp = g_uri_escape_string(payload, "=&", FALSE);
// note that we later g_free(payload_safe) which doesn't necessarily work with malloc'ed memory (seems to depend on glib version)
payload_safe = g_strdup(tmp);
free(tmp);
Comment on lines +1012 to +1016
g_object_unref(priv->soup_instance);
g_object_unref(priv->local_soup_instance);
while (priv->registered_apps) {
priv->registered_apps = gdial_rest_server_registered_apps_clear(object, priv->registered_apps, priv->registered_apps);
}
Comment on lines +296 to +299
if (app_random_uuid != NULL) {
g_free(app_random_uuid);
app_random_uuid = NULL;
}
Copilot AI review requested due to automatic review settings May 18, 2026 09:01
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 10 changed files in this pull request and generated 5 comments.

Comments suppressed due to low confidence (9)

tests/L1Tests/Makefile.am:109

  • When libsoup-3.0 is selected, this still builds the existing L1 test sources, but those tests use libsoup-2.4-only APIs such as SoupURI, SoupClientContext, direct SoupMessage fields, and soup_session_queue_message. Selecting the 3.0 implementation here will therefore make the L1 test target fail to compile unless the tests are ported or the libsoup3 path is excluded from this autotools test build.
if LIBSOUP_3_0
run_L1Tests_SOURCES += \
	$(top_srcdir)/server/libsoup/3.0/gdial-rest.c \
	$(top_srcdir)/server/libsoup/3.0/gdial-shield.c \
	$(top_srcdir)/server/libsoup/3.0/gdial-ssdp.c

server/libsoup/3.0/gdial-rest.c:361

  • On an instance-id mismatch this returns app instead of NULL, and the callers treat any non-null return as authorization to delete or hide the app. A request for a different numeric instance can therefore pass validation and operate on the app found by name; return a failure value when app != app_by_instance.
    if (strlen(endptr) == 0) {
      app_by_instance = gdial_app_find_instance_by_instance_id(instance_id);
      g_return_val_if_fail(app == app_by_instance, app);

server/libsoup/3.0/gdial-rest.c:860

  • Skipping an empty path component advances j without checking whether it reached the NULL terminator. For paths with a trailing slash (for example /<route>/<app>/), the next loop iteration dereferences elements[j] when it is NULL, which can crash the server instead of returning an HTTP error.
    if (strlen(elements[j]) == 0) {
      j++;
      continue;
    }

server/libsoup/3.0/gdial-rest.c:465

  • additional_data_url remains NULL when a registry disables additional data, but it is still passed to g_uri_escape_string(). That GLib API requires a non-null string, so registering an app with use_additional_data == FALSE will emit a critical and pass a NULL/invalid value into app launch instead of simply omitting the additional data URL.
    gchar *additional_data_url = NULL;
    if (app_registry->use_additional_data) {
      additional_data_url = gdial_rest_server_new_additional_data_url(listening_port, app_registry->name, FALSE, app_registry->app_uri );
    }
    gchar *additional_data_url_safe = g_uri_escape_string(additional_data_url, NULL, FALSE);

server/libsoup/3.0/gdial-rest.c:1160

  • gdial_app_registry_new() duplicates app_name internally, so passing g_strdup(app_name) leaks the intermediate copy on every registration. Pass the original string here and let the registry own its internal duplicate.
  GDialAppRegistry *app_registry = gdial_app_registry_new (g_strdup(app_name),

server/libsoup/3.0/gdial-ssdp.c:299

  • Destroy clears app_random_uuid but leaves app_friendly_name, app_manufacturer_name, and app_model_name allocated and still assigned. After a restart, the next SSDP instance can reuse stale override values from the previous run and leak the old strings.
  if (app_random_uuid != NULL) {
    g_free(app_random_uuid);
    app_random_uuid = NULL;
  }

server/libsoup/3.0/gdial-rest.c:968

  • This fallback differs from the libsoup-2.4 implementation, which returns SOUP_STATUS_NOT_IMPLEMENTED for unsupported methods on an instance URL. The libsoup3 path should preserve the same REST behavior; otherwise clients will get a 404 instead of the expected method-not-supported response only when built with libsoup3.
      else {
        gdial_rest_server_http_return_if_fail(FALSE, msg, SOUP_STATUS_NOT_FOUND);
      }

server/libsoup/3.0/gdial-rest.c:1280

  • rbuilder is zeroed twice in a row, which is redundant and makes this constructor look copy-pasted. Remove the duplicate memset to keep the initialization path clear.
  GDialServerResponseBuilderGetApp *rbuilder = (GDialServerResponseBuilderGetApp *) malloc(sizeof(*rbuilder));
  memset(rbuilder, 0, sizeof(*rbuilder));
  memset(rbuilder, 0, sizeof(*rbuilder));
  rbuilder->app_name = g_strdup(app_name);

server/libsoup/3.0/gdial-rest.c:941

  • For a loopback POST to the documented /.../<app>/dial_data route, this only verifies the method and then falls through without calling gdial_rest_server_handle_POST_dial_data() or setting a response. The request can appear successful while the dial_data payload is never cached.
      else {
        gdial_rest_server_http_return_if_fail(soup_server_message_get_method(msg) == SOUP_METHOD_POST, msg, SOUP_STATUS_NOT_IMPLEMENTED);
      }

Comment thread tests/L1Tests/Makefile.am
endif

if GSSDP_1_6
AM_CPPFLAGS += -DHAVE_GSSDP_VERSION_1_6_OR_NEWER
pthread_mutex_lock(&ssdpServerEventSync);
if (ssdp_http_server_)
{
soup_server_remove_handler(ssdp_http_server_, "/dd.xml");
Comment on lines +136 to +143
GDIAL_LOGTRACE("Entering ...");
g_return_if_fail(active_conns_ != NULL);
GDIAL_LOGINFO("gdial_shield_term: hash_table_size start= %d", g_hash_table_size(active_conns_));
g_hash_table_iter_init(&iter, (GHashTable *)active_conns_);
while (g_hash_table_iter_next(&iter, &key, &value)) {
SoupMessage *msg = (SoupMessage *)key;
server_request_remove_callback(msg);
}
/*
* Any request only respond to app name that is among registered apps
*/
g_signal_emit(gdial_rest_server, gdial_rest_server_signals[SIGNAL_INVALID_URI], 0, "URI containes unregistered app name");
* ORIGIN header is not present.
* 7.10.1 The ORIGIN header MUST match https://${ANY}.youtube.com or package
*/
GUri *origin_uri = g_uri_parse(header_origin, G_URI_FLAGS_NONE, NULL);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants