Emscripten: Experimental -sPROXY_POSIX_SOCKETS support

...see
<https://emscripten.org/docs/porting/networking.html#full-posix-sockets-over-websocket-proxy-server>.

This requires
<4aff1f28b8>
"-sPROXY_POSIX_SOCKETS: Add websocket_proxy_poll".  When configured with
--disable-socketpair (which appears to have no negative consequences),
external/curl appears to only call poll(2) with socket-related file descriptors,
so we can use websocket_proxy_poll instead.

The URL on which the websocket_to_posix_proxy process listens must be specified
as Module.uno_websocket_to_posix_socket_url.

Change-Id: I4ad23098b5bbc0646fa50859c0aeb9870d1cc92a
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/172243
Reviewed-by: Stephan Bergmann <stephan.bergmann@allotropia.de>
Tested-by: Jenkins
This commit is contained in:
Stephan Bergmann
2024-08-22 11:49:08 +02:00
parent 0afb4cfc5e
commit 2d9f8f45be
8 changed files with 103 additions and 0 deletions

View File

@@ -175,6 +175,7 @@ export ENABLE_DEBUG=@ENABLE_DEBUG@
ENABLE_DOTNET=@ENABLE_DOTNET@
SYSTEM_DRAGONBOX=@SYSTEM_DRAGONBOX@
SYSTEM_FROZEN=@SYSTEM_FROZEN@
export ENABLE_EMSCRIPTEN_PROXY_POSIX_SOCKETS=@ENABLE_EMSCRIPTEN_PROXY_POSIX_SOCKETS@
export ENABLE_EPOXY=@ENABLE_EPOXY@
export ENABLE_EOT=@ENABLE_EOT@
export ENABLE_EVOAB2=@ENABLE_EVOAB2@

View File

@@ -0,0 +1,14 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#pragma once
#define HAVE_EMSCRIPTEN_PROXY_POSIX_SOCKETS 0
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */

View File

@@ -2166,6 +2166,15 @@ AC_ARG_WITH(main-module,
Default value is 'writer'.]),
,)
if test "$_os" = Emscripten; then
AC_ARG_ENABLE(emscripten-proxy-posix-sockets,
AS_HELP_STRING([--enable-emscripten-proxy-posix-sockets],
[Enable experimental Emscripten support for full POSIX sockets over WebSocket proxy
server (-sPROXY_POSIX_SOCKETS).]))
else
enable_emscripten_proxy_posix_sockets=
fi
AC_ARG_ENABLE(xmlhelp,
AS_HELP_STRING([--disable-xmlhelp],
[Disable XML help support]),
@@ -4238,6 +4247,14 @@ AC_SUBST(ENABLE_WASM_STRIP)
AC_SUBST(ENABLE_WASM_STRIP_WRITER)
AC_SUBST(ENABLE_WASM_STRIP_CALC)
if test "$enable_emscripten_proxy_posix_sockets" = yes; then
ENABLE_EMSCRIPTEN_PROXY_POSIX_SOCKETS=TRUE
AC_DEFINE(HAVE_EMSCRIPTEN_PROXY_POSIX_SOCKETS)
else
ENABLE_EMSCRIPTEN_PROXY_POSIX_SOCKETS=
fi
AC_SUBST(ENABLE_EMSCRIPTEN_PROXY_POSIX_SOCKETS)
# Use -isystem (gcc) if possible, to avoid warnings in 3rd party headers.
# NOTE: must _not_ be used for bundled external libraries!
ISYSTEM=
@@ -15697,6 +15714,7 @@ AC_CONFIG_HEADERS([config_host/config_cairo_canvas.h])
AC_CONFIG_HEADERS([config_host/config_cairo_rgba.h])
AC_CONFIG_HEADERS([config_host/config_cxxabi.h])
AC_CONFIG_HEADERS([config_host/config_dbus.h])
AC_CONFIG_HEADERS([config_host/config_emscripten.h])
AC_CONFIG_HEADERS([config_host/config_features.h])
AC_CONFIG_HEADERS([config_host/config_feature_desktop.h])
AC_CONFIG_HEADERS([config_host/config_feature_opencl.h])

View File

@@ -18,6 +18,7 @@
*/
#include <memory>
#include <config_emscripten.h>
#include <config_features.h>
#include <config_feature_desktop.h>
#include <config_feature_opencl.h>
@@ -150,6 +151,15 @@
#define GETPID getpid
#endif
#if HAVE_EMSCRIPTEN_PROXY_POSIX_SOCKETS
#include <stdexcept>
#include <string>
#include <emscripten/posix_socket.h>
#include <emscripten/threading.h>
#include <emscripten/val.h>
#include <emscripten/websocket.h>
#endif
#include <strings.hxx>
using namespace ::com::sun::star::awt;
@@ -547,6 +557,35 @@ void Desktop::Init()
RequestHandler::Disable();
}
pSignalHandler = osl_addSignalHandler(SalMainPipeExchangeSignal_impl, nullptr);
#if HAVE_EMSCRIPTEN_PROXY_POSIX_SOCKETS
{
auto const val = emscripten::val::module_property("uno_websocket_to_posix_socket_url");
if (val.isUndefined()) {
throw std::runtime_error("Module.uno_websocket_to_posix_socket_url is undefined");
} else {
auto const url = val.as<std::string>();
if (url.find('\0') != std::string::npos) {
throw std::runtime_error(
"Module.uno_websocket_to_posix_socket_url contains embedded NUL");
}
SAL_INFO("desktop.app", "connecting to <" << url << ">");
static auto const socket = emscripten_init_websocket_to_posix_socket_bridge(
url.c_str());
// 0 is CONNECTING, 1 is OPEN, see
// <https://websockets.spec.whatwg.org/#websocket-ready-state>:
unsigned short readyState = 0;
do {
emscripten_websocket_get_ready_state(socket, &readyState);
emscripten_thread_sleep(100);
} while (readyState == 0);
if (readyState != 1) {
throw std::runtime_error("could not connect to <" + url + ">");
}
SAL_INFO("desktop.app", "connected to <" << url << ">");
}
}
#endif
}
void Desktop::InitFinished()

View File

@@ -65,6 +65,7 @@ $(call gb_ExternalProject_get_state_target,curl,build):
$(if $(filter MACOSX,$(OS)),--prefix=/@.__________________________________________________OOO) \
$(if $(filter MACOSX,$(OS)),CFLAGS='$(CFLAGS) \
-mmacosx-version-min=$(MACOSX_DEPLOYMENT_TARGET)') \
$(if $(ENABLE_EMSCRIPTEN_PROXY_POSIX_SOCKETS),--disable-socketpair) \
$(if $(filter -fsanitize=undefined,$(CC)),CC='$(CC) -fno-sanitize=function') \
CPPFLAGS='$(curl_CPPFLAGS)' \
CFLAGS="$(gb_CFLAGS) $(call gb_ExternalProject_get_build_flags,curl)" \

View File

@@ -33,4 +33,10 @@ $(eval $(call gb_UnpackedTarball_add_patches,curl, \
))
endif
ifeq ($(ENABLE_EMSCRIPTEN_PROXY_POSIX_SOCKETS),TRUE)
$(eval $(call gb_UnpackedTarball_add_patches,curl, \
external/curl/emscripten-proxy-poll.patch.0 \
))
endif
# vim: set noet sw=4 ts=4:

View File

@@ -0,0 +1,20 @@
--- lib/select.c
+++ lib/select.c
@@ -51,6 +51,8 @@
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
+
+int websocket_proxy_poll(struct pollfd *fds, nfds_t nfds, int timeout);
/*
* Internal function used for waiting a specific amount of ms
@@ -318,7 +320,7 @@
pending_ms = -1;
else
pending_ms = 0;
- r = poll(ufds, nfds, pending_ms);
+ r = websocket_proxy_poll(ufds, nfds, pending_ms);
if(r <= 0) {
if((r == -1) && (SOCKERRNO == EINTR))
/* make EINTR from select or poll not a "lethal" error */

View File

@@ -26,6 +26,10 @@ gb_EMSCRIPTEN_LDFLAGS += -sSTACK_SIZE=131072 -sDEFAULT_PTHREAD_STACK_SIZE=65536
gb_EMSCRIPTEN_LDFLAGS += --bind -s FORCE_FILESYSTEM=1 -s WASM_BIGINT=1 -s ERROR_ON_UNDEFINED_SYMBOLS=1 -s FETCH=1 -s ASSERTIONS=1 -s EXIT_RUNTIME=0 -s EXPORTED_RUNTIME_METHODS=["UTF16ToString","stringToUTF16","UTF8ToString","ccall","cwrap","addOnPreMain","addOnPostRun","registerType","throwBindingError"$(if $(ENABLE_QT6),$(COMMA)"callMain"$(COMMA)"specialHTMLTargets")]
gb_EMSCRIPTEN_QTDEFS := -DQT_NO_LINKED_LIST -DQT_NO_JAVA_STYLE_ITERATORS -DQT_NO_EXCEPTIONS -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB
ifeq ($(ENABLE_EMSCRIPTEN_PROXY_POSIX_SOCKETS),TRUE)
gb_EMSCRIPTEN_LDFLAGS += -sPROXY_POSIX_SOCKETS -lwebsocket.js
endif
gb_Executable_EXT := .html
gb_EMSCRIPTEN_EXCEPT = -fwasm-exceptions -s SUPPORT_LONGJMP=wasm