GStreamer支持https,笔者使用了openssl库libsoup,glib-networking。openssl库的wrap文件下载位置位:
libsoup可以看作是支持http/https协议的库,用glib的方式开发而成,连接管理都在里面完成。
Gstreamer TLS建立流程如下:
g_tls_connection_base_init 行 236 subprojects\glib-networking\tls\base\gtlsconnection-base.c(236)
g_initable_new 行 168 subprojects\glib\gio\ginitable.c(168)
soup_socket_setup_ssl 行 1392 subprojects\libsoup\libsoup\soup-socket.c(1392)
soup_socket_handshake_async 行 1540 subprojects\libsoup\libsoup\soup-socket.c(1540)
socket_connect_complete 行 380 subprojects\libsoup\libsoup\soup-connection.c(380)
async_connected 行 941 subprojects\libsoup\libsoup\soup-socket.c(941)
g_socket_client_async_connect_complete 行 1560 subprojects\glib\gio\gsocketclient.c(1560)
try_next_successful_connection 行 1733 subprojects\glib\gio\gsocketclient.c(1733)
try_next_connection_or_finish 行 1801 subprojects\glib\gio\gsocketclient.c(1801)
g_socket_client_connected_callback 行 1871 subprojects\glib\gio\gsocketclient.c(1871)
g_socket_connection_connect_callback 行 241 subprojects\glib\gio\gsocketconnection.c(241)
socket_source_dispatch 行 4025 subprojects\glib\gio\gsocket.c(4025)
g_main_loop_run 行 4373 subprojects\glib\glib\gmain.c(4373)
thread_func 行 1067 subprojects\gst-plugins-good\ext\soup\gstsouphttpsrc.c(1067)
Gstreamer使用openssl连接的流程如下:
tls/dtls connection-> connection base->connection openssl->ssl_lib->...->x509...
测试URL:
https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_cropped_multilingual.webm
遇到的问题如下:
-
TLS/SSL support not available
[souphttpsrc][source] Running request for method: GET
[souphttpsrc][source] got headers
[souphttpsrc][source] error: Secure connection setup failed.
[souphttpsrc][source] error: 1; install glib-networking (6), URL: https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_cropped_multilingual.webm, Redirect to: (NULL)
[souphttpsrc][source] Sending message failed: TLS support is not available
解决方法:
添加libgioopenssl.so库并
export GIO_MODULE_DIR=${GST_LIB_INSTALL_DIR}/lib/gio/modules
-
Secure connection setup failed,Unacceptable TLS certificate
[souphttpsrc][source] Running request for method: GET
[souphttpsrc][source] got headers
[souphttpsrc][source] error: Secure connection setup failed.
[souphttpsrc][source] error: Unacceptable TLS certificate (6), URL: https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_cropped_multilingual.webm, Redirect to: (NULL)
[GST_ERROR_SYSTEM][source] posting message: Secure connection setup failed.
解决方法如下:
![](https://i-blog.csdnimg.cn/blog_migrate/afe9ab26b8ffe8a4fbdd910948e4862e.png)
增加属性"ssl-strict"配置为FALSE;这个变量的主要影响,是在accept_or_reject_peer_certificate认证错误的时候,发送消息,让cb函数来处理这个结果,目前默认返回TRUE,也就是接受,关于这点,也是值得讨论的。发送消息的代码见gtlsconnection.c文档
gboolean
g_tls_connection_emit_accept_certificate (GTlsConnection *conn,
GTlsCertificate *peer_cert,
GTlsCertificateFlags errors)
{
gboolean accept = FALSE;
g_signal_emit (conn, signals[ACCEPT_CERTIFICATE], 0,
peer_cert, errors, &accept);
return accept;
}
gstsouphttpsrc将"ssl-strict"配置给soup-session流程如下:
soup_session_set_property 行 695 subprojects\libsoup\libsoup\soup-session.c(695)
object_set_property 行 1571 subprojects\glib\gobject\gobject.c(1571)
g_object_set_valist 行 2465 subprojects\glib\gobject\gobject.c(2465)
g_object_set 行 2634 subprojects\glib\gobject\gobject.c(2634)
thread_func 行 1019 subprojects\gst-plugins-good\ext\soup\gstsouphttpsrc.c(1019)
soup-session将"ssl-strict"配置给soup-socket流程如下:
soup_socket_set_property 行 333 subprojects\libsoup\libsoup\soup-socket.c(333)
object_set_property 行 1571 subprojects\glib\gobject\gobject.c(1571)
g_object_new_internal 行 1993 subprojects\glib\gobject\gobject.c(1993)
g_object_new_valist 行 2282 subprojects\glib\gobject\gobject.c(2282)
soup_socket_new 行 848 subprojects\libsoup\libsoup\soup-socket.c(848)
soup_connection_connect_async 行 414 subprojects\libsoup\libsoup\soup-connection.c(414)
get_connection 行 1957 subprojects\libsoup\libsoup\soup-session.c(1957)
soup_session_process_queue_item 行 1982 subprojects\libsoup\libsoup\soup-session.c(1982)
async_run_queue 行 2075 subprojects\libsoup\libsoup\soup-session.c(2075)
idle_run_queue 行 2115 subprojects\libsoup\libsoup\soup-session.c(2115)
消息的挂接和处理函数见soup-socket.c如下代码:
static gboolean
soup_socket_setup_ssl (SoupSocket *sock,
const char *ssl_host,
GCancellable *cancellable,
GError **error)
{
……
priv->ssl = TRUE;
if (!priv->is_server) {
GTlsClientConnection *conn;
GSocketConnectable *identity;
identity = g_network_address_new (ssl_host, 0);
conn = g_initable_new (g_tls_backend_get_client_connection_type (backend),
cancellable, error,
"base-io-stream", priv->conn,
"server-identity", identity,
"database", priv->ssl_creds,
"require-close-notify", FALSE,
"use-ssl3", priv->ssl_fallback,
NULL);
……
priv->conn = G_IO_STREAM (conn);
if (!priv->ssl_strict) {
g_signal_connect (conn, "accept-certificate",
G_CALLBACK (soup_socket_accept_certificate),
sock);
}
} else {
……
priv->conn = G_IO_STREAM (conn);
}
……
return TRUE;
}
static gboolean
soup_socket_accept_certificate (GTlsConnection *conn, GTlsCertificate *cert,
GTlsCertificateFlags errors, gpointer sock)
{
return TRUE;
}
dash/hls 的https播放过程中,由于dash/hls 片段的切换,gstsouphttpsrc可能会多次被创建,因此,每一次创建都需要对这个source设置属性。不建议将属性修改成默认参数FALSE,选择权交给用户吧,安全无小事。注意复杂环境下可能出现的多个同名库的问题,需要用readelf -d或者objdump -x来查看库的依赖问题,同时用如下方法来调试Makefile,查看Makefile中的所有变量,以便链接到正确的库上。
test:
$(foreach var,$(.VARIABLES),$(info $(var) = $($(var))))
老版本的stadaptivedemux,需要在gst_adaptive_demux_stream_update_source里面创建uri_handler的时候,配置ssl-strict,由source去配置soup-session,同时,由于在GstUriDownloader里面也创建了新的source,GstUriDownloader及其priv创建于demux初始化的时候,所以,可以在GstUriDownloader的priv里面增加一个ssl_strict字段,当配置demux的时候,顺便就配置了这个ssl_strict字段,创建source的时候,参考这个ssl_strict字段即可,如下:
if (!demux->ssl_strict &&
g_strstr_len(uri, -1, "https://")) {
g_object_set(uri_handler, "ssl-strict", FALSE, NULL);
}
uri_handler = gst_element_make_from_uri (GST_URI_SRC, uri, NULL, NULL);
if (uri_handler == NULL) {
GST_ELEMENT_ERROR (demux, CORE, MISSING_PLUGIN,
("Missing plugin to handle URI: '%s'", uri), (NULL));
gst_object_unref (queue);
return FALSE;
}
if (!demux->ssl_strict &&
g_strstr_len(uri, -1, "https://")) {
g_object_set(uri_handler, "ssl-strict", FALSE, NULL);
}
case PROP_STRICT_SSL:
demux->ssl_strict = g_value_get_boolean (value);
gst_uri_downloader_set_ssl_strict(demux->downloader, demux->ssl_strict);
void
gst_uri_downloader_set_ssl_strict (
GstUriDownloader * downloader, gboolean ssl_strict)
{
g_return_if_fail (downloader != NULL);
g_return_if_fail (downloader->priv != NULL);
downloader->priv->ssl_strict = ssl_strict;
}
if (!downloader->priv->urisrc) {
GST_DEBUG_OBJECT (downloader, "Creating source element for the URI:%s",
uri);
downloader->priv->urisrc =
gst_element_make_from_uri (GST_URI_SRC, uri, NULL, NULL);
if (downloader->priv->urisrc) {
/* gst_element_make_from_uri returns a floating reference
* and we are not going to transfer the ownership, so we
* should take it.
*/
gst_object_ref_sink (downloader->priv->urisrc);
g_object_set(downloader->priv->urisrc,
"ssl-strict", downloader->priv->ssl_strict, NULL);
}
}
而新版本的adaptivedemux2不行,需要配置GstAdaptiveDemux的DownloadHelper的session,这个session,就是soup-session,在这里面手动配置。
void downloadhelper_set_ssl_strict (DownloadHelper * dh, gboolean ssl_strict)
{
if (dh && dh->session) {
g_object_set(dh->session, "ssl-strict", FALSE, NULL);
}
}
-
高安组件使用到libcurl库下载https的数据,关于libcurl使用arm交叉编译的问题。
-
错误A:不能找到ssl,crypto库,报错如下:
/usr/local/linaro/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/ld: warning: libpsl.so.5, needed by ../lib/.libs/libcurl.so, not found (try using -rpath or -rpath-link)
/usr/local/linaro/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/ld: warning: libssl.so, needed by ../lib/.libs/libcurl.so, not found (try using -rpath or -rpath-link)
/usr/local/linaro/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/ld: warning: libcrypto.so, needed by ../lib/.libs/libcurl.so, not found (try using -rpath or -rpath-link)
/usr/local/linaro/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/ld: ../lib/.libs/libcurl.so: undefined reference to `EVP_PKEY_copy_parameters'
/usr/local/linaro/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/ld: ../lib/.libs/libcurl.so: undefined reference to `X509_LOOKUP_file'
/usr/local/linaro/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/ld: ../lib/.libs/libcurl.so: undefined reference to `ASN1_TIME_print'
/usr/local/linaro/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/ld: ../lib/.libs/libcurl.so: undefined reference to `TLS_client_method
打印出错时的链接参数如下:
libtool: link: /usr/local/linaro/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc -march=armv7-a -mtune=cortex-a7 -mabi=aapcs-linux -mfloat-abi=hard -mfpu=neon-vfpv4 -mthumb-interwork -marm -rdynamic -funwind-tables -fno-omit-frame-pointer -fno-optimize-sibling-calls -mapcs-frame -fstack-protector-strong -Wl,--build-id -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -g -O2 -Werror=incompatible-pointer-types -Werror=uninitialized -Werror-implicit-function-declaration -isystem /xxx//output//arm//include -isystem /xxx/output//arm//include -fPIC -rdynamic -funwind-tables -fomit-frame-pointer -fno-common -Werror-implicit-function-declaration -Wno-system-headers -o .libs/curl slist_wc.o tool_binmode.o tool_bname.o tool_cb_dbg.o tool_cb_hdr.o tool_cb_prg.o tool_cb_rea.o tool_cb_see.o tool_cb_wrt.o tool_cfgable.o tool_dirhie.o tool_doswin.o tool_easysrc.o tool_filetime.o tool_findfile.o tool_formparse.o tool_getparam.o tool_getpass.o tool_help.o tool_helpers.o tool_hugehelp.o tool_libinfo.o tool_listhelp.o tool_main.o tool_msgs.o tool_operate.o tool_operhlp.o tool_paramhlp.o tool_parsecfg.o tool_progress.o tool_strdup.o tool_setopt.o tool_sleep.o tool_urlglob.o tool_util.o tool_vms.o tool_writeout.o tool_writeout_json.o tool_xattr.o ../lib/strtoofft.o ../lib/timediff.o ../lib/nonblock.o ../lib/warnless.o ../lib/curl_multibyte.o ../lib/version_win32.o ../lib/dynbuf.o -L/xxx//output//arm//lib -L/xxx//output/arm/lib ../lib/.libs/libcurl.so -lz -pthread -Wl,-rpath -Wl,/xxx/output//arm/lib
-Wl已经指定了rpath,故不存在不能找到库A依赖B,B依赖C的情况,并且libpsl.so,libssl.so,libcrypto.so都已经存在于lib下面。仔细阅读这个link参数,发现未加入-l参数,于是在编译配置的Makefile中加入LIBS参数LIBS=-lssl -lcrypto -lpsl解决问题。
如下:
LIBS=-lssl -lcrypto -lpsl
CPPFLAGS = -I$(SOURCE_INC_DIR)
LDFLAGS = -L$(SOURCE_PREFIX_DIR)/lib
CFLAGS += $(CPPFLAGS) $(LIBS) -fPIC -rdynamic -funwind-tables -fomit-frame-pointer -fno-common
PKG_CONFIG_PATH = $(SOURCE_PREFIX_DIR)/lib/pkgconfig
PKG_CONFIG_LIBDIR = $(PKG_CONFIG_PATH)
CXXFLAGS = $(CFLAGS)
export CPPFLAGS CFLAGS LDFLAGS CXXFLAGS LIBS PKG_CONFIG_PATH PKG_CONFIG_LIBDIR
CONFIGURE_ARGS = CC="$(CC)" \
--with-openssl=$(SOURCE_PREFIX_DIR) \
--disable-stripping \
--without-gnutls \
--host="$(HOST)" \
--build="$(MAKE_HOST)"\
--enable-shared \
--enable-static \
--prefix=$(SOURCE_PREFIX_DIR)
all:
@echo "generate makefile for $(SOURCE_BUILD_DIR)/$(CODE_PATH)";
mkdir -p $(SOURCE_BUILD_DIR)/$(CODE_PATH);
cd $(SOURCE_BUILD_DIR)/$(CODE_PATH); $(SOURCE_DIR)/$(CODE_PATH)/configure $(CONFIGURE_ARGS);
touch $(SOURCE_BUILD_DIR)/$(CODE_PATH)/makefile-done;
cd $(SOURCE_BUILD_DIR)/$(CODE_PATH); make -j$(j) V=1; make install
$(AT)$(MAKE) -f $(CURRENT_MAKEFILES) -r install
install:
uninstall:
clean:
-rm -rf ${SOURCE_PREFIX_DIR}/build/libcurl
distclean:
以上配置用于描述解决问题的方案,不代表整个方案直接粘贴复制可用,部分变量需要配置,另外,libcurl编译过程中,一定要注意是否有生成build目录,调试脚本时,最好将这个目录每次都删除,以免部分参数没有配置进去导致一些奇怪的问题。
-
错误B: configure: error: C compiler cannot create executables具体如下:
configure: WARNING: Continuing even with errors mentioned immediately above this line.
checking for a BSD-compatible install... /usr/bin/install -c
checking for arm-linux-gnueabihf-gcc... /usr/local/linaro/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc -march=armv7-a -mtune=cortex-a7 -mabi=aapcs-linux -mfloat-abi=hard -mfpu=neon-vfpv4 -mthumb-interwork -marm -rdynamic -funwind-tables -fno-omit-frame-pointer -fno-optimize-sibling-calls -mapcs-frame -fstack-protector-strong -Wl,--build-id -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
checking whether the C compiler works... no
configure: error: in `/XXX/output/arm/build/libcurl/curl-7.88.1':
configure: error: C compiler cannot create executables
See `config.log' for more details
查看build\libcurl\curl-7.88.1\config.log文件,找到如下错误:
configure:4906: checking whether the C compiler works
configure:4928: /usr/local/linaro/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc -march=armv7-a -mtune=cortex-a7 -mabi=aapcs-linux -mfloat-abi=hard -mfpu=neon-vfpv4 -mthumb-interwork -marm -rdynamic -funwind-tables -fno-omit-frame-pointer -fno-optimize-sibling-calls -mapcs-frame -fstack-protector-strong -Wl,--build-id -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -g -O2 -Werror=incompatible-pointer-types -Werror=uninitialized -Werror-implicit-function-declaration -I/xxx/output//arm//include -I/xxx/output//arm//include -lssl -lcrypto -lpsl -fPIC -rdynamic -funwind-tables -fomit-frame-pointer -fno-common -I/xxx/output//arm//include -L/xxx/output//arm//lib conftest.c -lssl -lcrypto -lpsl >&5
/usr/local/linaro/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/ld: cannot find -lssl
/usr/local/linaro/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/ld: cannot find -lcrypto
/usr/local/linaro/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/ld: cannot find -lpsl
/usr/local/linaro/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/ld: cannot find -lssl
/usr/local/linaro/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/ld: cannot find -lcrypto
/usr/local/linaro/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/ld: cannot find -lpsl
collect2: error: ld returned 1 exit status
configure:4932: $? = 1
configure:4972: result: no
就是要先编译openssl这些东西,编译后解决。
-
错误C:error: OpenSSL libs and/or directories were not found where specified!,具体情况如下:
checking whether to enable Windows native SSL/TLS... no
checking whether to enable Secure Transport... no
checking whether to enable Amiga native SSL/TLS (AmiSSL v5)... no
checking for HMAC_Update in -lcrypto... yes
checking for SSL_connect in -lssl... yes
checking for openssl/x509.h... no
checking for openssl/rsa.h... no
checking for openssl/crypto.h... no
checking for openssl/pem.h... no
checking for openssl/ssl.h... no
checking for openssl/err.h... no
checking for x509.h... no
checking for rsa.h... no
checking for crypto.h... no
checking for pem.h... no
checking for ssl.h... no
checking for err.h... yes
configure: error: OpenSSL libs and/or directories were not found where specified!
就是找不到openssl的那一系列头文件,gstreamer编译的openssl需要在openssl的meson.build文件中加入安装头文件的命令:
openssl_installdir = join_paths(get_option('prefix'), 'include')
openssl_public_headers += files([
'include/openssl/aes.h',
......
])
install_headers(openssl_public_headers,
install_dir: join_paths(openssl_installdir, 'openssl'))
另外openssl也最好生成pkg文件,加入如下两句:
pkg = import('pkgconfig')
pkg.generate(libcrypto_lib,
libraries : libcrypto_dep,
name : 'libcrypto',
description : 'A Crypto library')
pkg.generate(libssl_lib,
libraries : libssl_dep,
name : 'libssl',
description : 'A SSL library')
这儿有篇文章,介绍了curl的参数设置:PHP: curl_setopt - Manual
-
错误D:SSL routines:ssl3_read_n:unexpected eof while
[ERROR:core/test/http_socket.cpp(446):Read] SSL_read returned 0, LibSSL Error = 1
[ERROR:core/test/http_socket.cpp(72):LogBoringSslError] BoringSSL Error: 0077FFB6:error:0A000126:SSL routines:ssl3_read_n:unexpected eof while reading:../../../../gstreamer/gstreamer/subprojects/openssl-3.0.2/ssl/record/rec_layer_s3.c:309:
这是由于期望获取的数据长度大于实际数据长度造成的,需要做如下配置:
ctx = SSL_CTX_new(c->listen ? SSLv23_server_method() : SSLv23_client_method());
SSL_CTX_set_options(ctx, SSL_OP_IGNORE_UNEXPECTED_EOF);
注意:
在Linux上,确定需要soup-2.4-1并且准备好soup-2.4-1之后,将其打包到文件系统中,gstsouploader.c中的gst_soup_load_library可能并不能成功加载soup-2.4-1,原因并不是soup-2.4-1的依赖没有打包,是soup-2.4-1依赖的依赖没有打包到文件系统中去,至于是哪个依赖,gstreamer加载的时候并不会报错,因此很难定位到需要的库,这儿介绍一下快捷定位的方法。
- APP测试文件中调用soup-2.4-1中的某个API
- 在APP测试Makefile中动态库依赖加上soup-4-1,如-l soup-4-1,这个时候,系统加载soup-4-1不成功时会提示缺失的动态库名称。
- 打印缺失的动态库到文件系统中即可。