diff --git a/config_host.mk.in b/config_host.mk.in index 15b1c2b74e9a..810abab5f4ca 100644 --- a/config_host.mk.in +++ b/config_host.mk.in @@ -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@ diff --git a/config_host/config_emscripten.h.in b/config_host/config_emscripten.h.in new file mode 100644 index 000000000000..24d1a9ca5dd8 --- /dev/null +++ b/config_host/config_emscripten.h.in @@ -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: */ diff --git a/configure.ac b/configure.ac index 2c11703cb3ff..f0fb5765abc9 100644 --- a/configure.ac +++ b/configure.ac @@ -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]) diff --git a/desktop/source/app/app.cxx b/desktop/source/app/app.cxx index 2a52f9843f75..a4ce4c965d3a 100644 --- a/desktop/source/app/app.cxx +++ b/desktop/source/app/app.cxx @@ -18,6 +18,7 @@ */ #include +#include #include #include #include @@ -150,6 +151,15 @@ #define GETPID getpid #endif +#if HAVE_EMSCRIPTEN_PROXY_POSIX_SOCKETS +#include +#include +#include +#include +#include +#include +#endif + #include 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(); + 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 + // : + 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() diff --git a/external/curl/ExternalProject_curl.mk b/external/curl/ExternalProject_curl.mk index 9d39e62e6fd3..45aa6d561389 100644 --- a/external/curl/ExternalProject_curl.mk +++ b/external/curl/ExternalProject_curl.mk @@ -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)" \ diff --git a/external/curl/UnpackedTarball_curl.mk b/external/curl/UnpackedTarball_curl.mk index 4412857d36a0..4f21212eff8d 100644 --- a/external/curl/UnpackedTarball_curl.mk +++ b/external/curl/UnpackedTarball_curl.mk @@ -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: diff --git a/external/curl/emscripten-proxy-poll.patch.0 b/external/curl/emscripten-proxy-poll.patch.0 new file mode 100644 index 000000000000..ac1f4a84d25c --- /dev/null +++ b/external/curl/emscripten-proxy-poll.patch.0 @@ -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 */ diff --git a/solenv/gbuild/platform/EMSCRIPTEN_INTEL_GCC.mk b/solenv/gbuild/platform/EMSCRIPTEN_INTEL_GCC.mk index 268d2dbf932e..416cdbc4c1a4 100644 --- a/solenv/gbuild/platform/EMSCRIPTEN_INTEL_GCC.mk +++ b/solenv/gbuild/platform/EMSCRIPTEN_INTEL_GCC.mk @@ -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