diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index df13a359..90a82ec3 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,90 +1,101 @@ -name: gstd CI + name: gstd CI -on: - push: - branches: - - master - - develop - pull_request: - branches: - - develop + on: + push: + branches: + - master + - develop + pull_request: + branches: + - develop -jobs: - autotools: - strategy: - fail-fast: false - matrix: - os: - - ubuntu-20.04 - include: - - os: ubuntu-22.04 - remove-unwind: fix-unwind + jobs: + autotools: + strategy: + fail-fast: false + matrix: + ubuntu_version: [ "20.04", "22.04", "24.04" ] + include: + - ubuntu_version: "20.04" + libsoup2: "libsoup2.4-dev" - runs-on: ${{ matrix.os }} + runs-on: ubuntu-24.04 + container: + image: ubuntu:${{ matrix.ubuntu_version }} - steps: - - uses: actions/checkout@v2 - - if: ${{ matrix.remove-unwind }} - run: sudo apt remove libunwind-14-dev - - name: Dependecies - run: | - sudo apt update - sudo apt install automake libtool pkg-config libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev - sudo apt install libglib2.0-dev libjson-glib-dev gtk-doc-tools libedit-dev libncursesw5-dev - sudo apt install libdaemon-dev libjansson-dev python3-pip python3-setuptools libsoup2.4-dev - - name: Generate - run: ./autogen.sh - - name: Configure - run: ./configure CFLAGS=-Werror - - name: Compile - run: make - - name: Checks - run: make check - - name: Install - run: sudo make install - - name: Check pygstc installation - run: python3 -c "import pygstc" - - name: List Pipelines Verification - run: | - gstd -e - gstd-client list_pipelines + steps: + - uses: actions/checkout@v2 + - name: Dependecies + run: | + export DEBIAN_FRONTEND=noninteractive + apt update + apt install -y automake libtool pkg-config libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev + apt install -y libglib2.0-dev libjson-glib-dev gtk-doc-tools libedit-dev libncursesw5-dev + apt install -y libdaemon-dev libjansson-dev python3-pip python3-setuptools + if [ "${{ matrix.libsoup2 }}" ]; then + apt install -y libsoup2.4-dev + else + apt install -y libsoup-3.0-dev + fi + - name: Generate + run: ./autogen.sh + - name: Configure + run: ./configure CFLAGS=-Werror + - name: Compile + run: make + - name: Checks + run: make check + - name: Install + run: make install + - name: Check pygstc installation + run: python3 -c "import pygstc" + - name: List Pipelines Verification + run: | + gstd -e + gstd-client list_pipelines - meson: - strategy: - fail-fast: false - matrix: - os: - - ubuntu-20.04 - include: - - os: ubuntu-22.04 - remove-unwind: fix-unwind + meson: + strategy: + fail-fast: false + matrix: + ubuntu_version: [ "20.04", "22.04", "24.04" ] + include: + - ubuntu_version: "24.04" + meson_opts: "-Dpython.install_env=auto" + - ubuntu_version: "20.04" + libsoup2: "libsoup2.4-dev" - runs-on: ${{ matrix.os }} + runs-on: ubuntu-24.04 + container: + image: ubuntu:${{ matrix.ubuntu_version }} - steps: - - uses: actions/checkout@v2 - - if: ${{ matrix.remove-unwind }} - run: sudo apt remove libunwind-14-dev - - name: Dependecies - run: | - sudo apt update - sudo apt install automake libtool pkg-config libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev - sudo apt install libglib2.0-dev libjson-glib-dev gtk-doc-tools libedit-dev libncursesw5-dev - sudo apt install libdaemon-dev libjansson-dev python3-pip python3-setuptools libsoup2.4-dev - sudo apt install ninja-build python3-wheel - sudo pip3 install meson + steps: + - uses: actions/checkout@v2 + - name: Dependecies + run: | + export DEBIAN_FRONTEND=noninteractive + apt update + apt install -y automake libtool pkg-config libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev + apt install -y libglib2.0-dev libjson-glib-dev gtk-doc-tools libedit-dev libncursesw5-dev + apt install -y libdaemon-dev libjansson-dev python3-pip python3-setuptools + if [ "${{ matrix.libsoup2 }}" ]; then + apt install -y libsoup2.4-dev + else + apt install -y libsoup-3.0-dev + fi + apt install -y ninja-build meson - - name: Generate for Ubuntu 20.04 and above - run: meson --werror build -Dpython.install_env=auto - - name: Compile - run: ninja -C build - - name: Checks - run: ninja -C build test - - name: Install - run: sudo ninja -C build install - - name: Check pygstc installation - run: python3 -c "import pygstc" - - name: List Pipelines Verification - run: | - gstd -e - gstd-client list_pipelines + - name: Generate for Ubuntu 20.04 and above + run: meson --werror build ${{ matrix.meson_opts }} + - name: Compile + run: ninja -C build + - name: Checks + run: ninja -C build test + - name: Install + run: ninja -C build install + - name: Check pygstc installation + run: python3 -c "import pygstc" + - name: List Pipelines Verification + run: | + gstd -e + gstd-client list_pipelines diff --git a/configure.ac b/configure.ac index 7152a175..a2aa9f64 100644 --- a/configure.ac +++ b/configure.ac @@ -7,6 +7,10 @@ AC_INIT([gstd],[0.15.2]) dnl required version of gstreamer and gst-plugins-base GST_REQUIRED=1.0.0 +dnl required version of libsoup +LIBSOUP3_REQUIRED=3.0 +LIBSOUP2_REQUIRED=2.4 + dnl required version of gio GIO_REQUIRED=2.44.1 @@ -85,7 +89,27 @@ PKG_CHECK_MODULES(GST, [ ]) ]) -PKG_CHECK_MODULES(LIBSOUP, [libsoup-2.4 >= 2.32]) +PKG_CHECK_MODULES([LIBSOUP], [libsoup-3.0 >= 3.0], [ + AC_DEFINE([HAVE_LIBSOUP3], [1], [Define if libsoup3 exists.]) + ], [ + PKG_CHECK_MODULES([LIBSOUP], [libsoup-2.4 >= 2.4], [ + AC_MSG_WARN(libsoup-2.4 detected: this library will be deprecated in upcoming releases. + Consider migrating to libsoup-3.0.) + ], [ + AC_DEFINE([HAVE_LIBSOUP2], [1], [Define if libsoup2 exists.]) + ], [ + AC_MSG_ERROR([ + Can't find any of the following LIBSOUP development packages: + + libsoup-3.0 >= $LIBSOUP3_REQUIRED + libsoup-2.4 >= $LIBSOUP2_REQUIRED (to be deprecated in incoming releases) + + Please make sure you have the necessary LIBSOUP3 or LIBSOUP2 + development headers installed. + ]) + ]) +]) + AC_SUBST(LIBSOUP_CFLAGS) AC_SUBST(LIBSOUP_LIBS) diff --git a/libgstd/gstd_http.c b/libgstd/gstd_http.c index ef4a20f5..0d3d0658 100644 --- a/libgstd/gstd_http.c +++ b/libgstd/gstd_http.c @@ -36,10 +36,16 @@ GST_DEBUG_CATEGORY_STATIC (gstd_http_debug); #define GSTD_DEBUG_DEFAULT_LEVEL GST_LEVEL_INFO +#if SOUP_CHECK_VERSION(3,0,0) +typedef SoupServerMessage SoupMsg; +#else +typedef SoupMessage SoupMsg; +#endif + typedef struct _GstdHttpRequest { SoupServer *server; - SoupMessage *msg; + SoupMsg *msg; GstdSession *session; const char *path; GHashTable *query; @@ -73,19 +79,27 @@ static GstdReturnCode gstd_http_stop (GstdIpc * base); static gboolean gstd_http_init_get_option_group (GstdIpc * base, GOptionGroup ** group); static SoupStatus get_status_code (GstdReturnCode ret); -static GstdReturnCode do_get (SoupServer * server, SoupMessage * msg, +static GstdReturnCode do_get (SoupServer * server, SoupMsg * msg, char **output, const char *path, GstdSession * session); -static GstdReturnCode do_post (SoupServer * server, SoupMessage * msg, +static GstdReturnCode do_post (SoupServer * server, SoupMsg * msg, char *name, char *description, char **output, const char *path, GstdSession * session); -static GstdReturnCode do_put (SoupServer * server, SoupMessage * msg, +static GstdReturnCode do_put (SoupServer * server, SoupMsg * msg, char *name, char **output, const char *path, GstdSession * session); -static GstdReturnCode do_delete (SoupServer * server, SoupMessage * msg, +static GstdReturnCode do_delete (SoupServer * server, SoupMsg * msg, char *name, char **output, const char *path, GstdSession * session); static void do_request (gpointer data_request, gpointer eval); -static void server_callback (SoupServer * server, SoupMessage * msg, + +#if SOUP_CHECK_VERSION(3,0,0) +/* libsoup3: no context argument for server_callback */ +static void server_callback (SoupServer * server, SoupMsg * msg, + const char *path, GHashTable * query, gpointer data); +#else +/* libsoup2.4: include context argument for server_callback */ +static void server_callback (SoupServer * server, SoupMsg * msg, const char *path, GHashTable * query, SoupClientContext * context, gpointer data); +#endif static void gstd_http_class_init (GstdHttpClass * klass) @@ -168,7 +182,7 @@ get_status_code (GstdReturnCode ret) } static GstdReturnCode -do_get (SoupServer * server, SoupMessage * msg, char **output, const char *path, +do_get (SoupServer * server, SoupMsg * msg, char **output, const char *path, GstdSession * session) { gchar *message = NULL; @@ -189,7 +203,7 @@ do_get (SoupServer * server, SoupMessage * msg, char **output, const char *path, } static GstdReturnCode -do_post (SoupServer * server, SoupMessage * msg, char *name, +do_post (SoupServer * server, SoupMsg * msg, char *name, char *description, char **output, const char *path, GstdSession * session) { gchar *message = NULL; @@ -224,7 +238,7 @@ do_post (SoupServer * server, SoupMessage * msg, char *name, } static GstdReturnCode -do_put (SoupServer * server, SoupMessage * msg, char *name, char **output, +do_put (SoupServer * server, SoupMsg * msg, char *name, char **output, const char *path, GstdSession * session) { gchar *message = NULL; @@ -254,7 +268,7 @@ do_put (SoupServer * server, SoupMessage * msg, char *name, char **output, } static GstdReturnCode -do_delete (SoupServer * server, SoupMessage * msg, char *name, +do_delete (SoupServer * server, SoupMsg * msg, char *name, char **output, const char *path, GstdSession * session) { gchar *message = NULL; @@ -294,11 +308,12 @@ do_request (gpointer data_request, gpointer eval) const gchar *description = NULL; SoupStatus status = SOUP_STATUS_OK; SoupServer *server = NULL; - SoupMessage *msg = NULL; + SoupMsg *msg = NULL; GstdSession *session = NULL; const char *path = NULL; GHashTable *query = NULL; GstdHttpRequest *data_request_local = NULL; + const char *method; g_return_if_fail (data_request); @@ -315,16 +330,20 @@ do_request (gpointer data_request, gpointer eval) name = g_hash_table_lookup (query, "name"); description_pipe = g_hash_table_lookup (query, "description"); } - - if (msg->method == SOUP_METHOD_GET) { +#if SOUP_CHECK_VERSION(3,0,0) + method = soup_server_message_get_method (msg); +#else + method = msg->method; +#endif + if (method == SOUP_METHOD_GET) { ret = do_get (server, msg, &output, path, session); - } else if (msg->method == SOUP_METHOD_POST) { + } else if (method == SOUP_METHOD_POST) { ret = do_post (server, msg, name, description_pipe, &output, path, session); - } else if (msg->method == SOUP_METHOD_PUT) { + } else if (method == SOUP_METHOD_PUT) { ret = do_put (server, msg, name, &output, path, session); - } else if (msg->method == SOUP_METHOD_DELETE) { + } else if (method == SOUP_METHOD_DELETE) { ret = do_delete (server, msg, name, &output, path, session); - } else if (msg->method == SOUP_METHOD_OPTIONS) { + } else if (method == SOUP_METHOD_OPTIONS) { ret = GSTD_EOK; } @@ -336,15 +355,31 @@ do_request (gpointer data_request, gpointer eval) g_free (output); output = NULL; +#if SOUP_CHECK_VERSION(3,0,0) + soup_server_message_set_response (msg, "application/json", SOUP_MEMORY_COPY, + response, strlen (response)); +#else soup_message_set_response (msg, "application/json", SOUP_MEMORY_COPY, response, strlen (response)); +#endif g_free (response); response = NULL; status = get_status_code (ret); + +#if SOUP_CHECK_VERSION(3,0,0) + soup_server_message_set_status (msg, status, NULL); +#else soup_message_set_status (msg, status); +#endif + g_mutex_lock (data_request_local->mutex); + +#if SOUP_CHECK_VERSION(3,2,0) + soup_server_message_unpause (msg); +#else soup_server_unpause_message (server, msg); +#endif g_mutex_unlock (data_request_local->mutex); if (query != NULL) { @@ -356,14 +391,23 @@ do_request (gpointer data_request, gpointer eval) return; } +#if SOUP_CHECK_VERSION(3,0,0) +/* libsoup3: no context argument for server_callback */ static void -server_callback (SoupServer * server, SoupMessage * msg, - const char *path, GHashTable * query, - SoupClientContext * context, gpointer data) +server_callback (SoupServer * server, SoupMsg * msg, + const char *path, GHashTable * query, gpointer data) +#else +/* libsoup2.4: include context argument for server_callback */ +static void +server_callback (SoupServer * server, SoupMsg * msg, + const char *path, GHashTable * query, SoupClientContext * context, + gpointer data) +#endif { GstdSession *session = NULL; GstdHttp *self = NULL; GstdHttpRequest *data_request = NULL; + SoupMessageHeaders *response_headers = NULL; g_return_if_fail (server); g_return_if_fail (msg); @@ -385,14 +429,26 @@ server_callback (SoupServer * server, SoupMessage * msg, } data_request->mutex = &self->mutex; - soup_message_headers_append (msg->response_headers, + +#if SOUP_CHECK_VERSION(3,0,0) +/* libsoup3: no context argument for server_callback */ + response_headers = soup_server_message_get_request_headers (msg); +#else +/* libsoup2.4: include context argument for server_callback */ + response_headers = msg->response_headers; +#endif + soup_message_headers_append (response_headers, "Access-Control-Allow-Origin", "*"); - soup_message_headers_append (msg->response_headers, + soup_message_headers_append (response_headers, "Access-Control-Allow-Headers", "origin,range,content-type"); - soup_message_headers_append (msg->response_headers, + soup_message_headers_append (response_headers, "Access-Control-Allow-Methods", "PUT, GET, POST, DELETE"); g_mutex_lock (&self->mutex); +#if SOUP_CHECK_VERSION(3,2,0) + soup_server_message_pause (msg); +#else soup_server_pause_message (server, msg); +#endif g_mutex_unlock (&self->mutex); if (!g_thread_pool_push (self->pool, (gpointer) data_request, NULL)) { GST_ERROR_OBJECT (self->pool, "Thread pool push failed"); @@ -420,7 +476,7 @@ gstd_http_start (GstdIpc * base, GstdSession * session) gstd_http_stop (base); GST_DEBUG_OBJECT (self, "Initializing HTTP server"); - self->server = soup_server_new (SOUP_SERVER_SERVER_HEADER, "Gstd-1.0", NULL); + self->server = soup_server_new ("server-header", "Gstd-1.0", NULL); if (!self->server) { goto noconnection; } diff --git a/meson.build b/meson.build index 7d7eacd9..21190706 100644 --- a/meson.build +++ b/meson.build @@ -27,9 +27,14 @@ json_glib_dep = dependency('json-glib-1.0', version : '>=0.16.2') libd_dep = dependency('libdaemon', version : '>=0.14') jansson_dep = dependency('jansson', version : '>=2.7') thread_dep = dependency('threads') -libsoup_dep = dependency('libsoup-2.4', version : '>=2.4') libedit_dep = dependency('libedit', version : '>=3.0') +libsoup_dep = dependency('libsoup-3.0', version : '>=3.0', required: false) +if not libsoup_dep.found() + libsoup_dep = dependency('libsoup-2.4', version : '>=2.4') + warning('libsoup-2.4 detected; this will be deprecated in upcoming releases. Please migrate to libsoup-3.0.') +endif + gst_check_required = get_option('enable-tests').enabled() gst_check_dep = dependency('gstreamer-check-1.0', required : gst_check_required, version : '>=1.0.5') @@ -46,55 +51,55 @@ gstd_deps = [ # Define gst client library dependencies libgstc_deps = [ - gst_base_dep, - json_glib_dep, - jansson_dep, + gst_base_dep, + json_glib_dep, + jansson_dep, thread_dep ] # Define gst core library dependencies libgstd_deps = [ - gst_base_dep, - gio_unix_dep, - json_glib_dep, - jansson_dep, - thread_dep, + gst_base_dep, + gio_unix_dep, + json_glib_dep, + jansson_dep, + thread_dep, libsoup_dep ] # Define gst client application dependencies gst_client_deps = [ libedit_dep, - json_glib_dep, + json_glib_dep, gio_unix_dep ] # Define test dependencies test_libgstc_deps=[ - gst_base_dep, - json_glib_dep, - jansson_dep, - thread_dep, + gst_base_dep, + json_glib_dep, + jansson_dep, + thread_dep, gst_check_dep ] test_gstd_deps=[ - gst_base_dep, - gio_unix_dep, - json_glib_dep, - libd_dep, - jansson_dep, + gst_base_dep, + gio_unix_dep, + json_glib_dep, + libd_dep, + jansson_dep, gst_check_dep ] test_libgstd_deps=[ - gst_base_dep, - gio_unix_dep, - json_glib_dep, - libd_dep, - jansson_dep, - thread_dep, - libsoup_dep, + gst_base_dep, + gio_unix_dep, + json_glib_dep, + libd_dep, + jansson_dep, + thread_dep, + libsoup_dep, gst_check_dep ]