Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CLI and networking support #119

Merged
merged 67 commits into from
Jan 30, 2023
Merged

CLI and networking support #119

merged 67 commits into from
Jan 30, 2023

Conversation

adamziel
Copy link
Collaborator

@adamziel adamziel commented Jan 25, 2023

Description

Adds support for CLI SAPI and networking in node.js:

> npm run build

> node ./build-cli/php-cli.js -r 'echo "Hello from PHP !";'
Hello from PHP !

> node ./build-cli/php-cli.js -r 'echo substr(file_get_contents("https://wordpress.org"), 0, 16);'
<!DOCTYPE html>

> node ./build-cli/php-cli.js -r 'echo phpversion();'
8.2.0-dev

> PHP=5.6 node ./build-cli/php-cli.js -r 'echo phpversion();'
5.6.40

Highlights:

In broad strokes:

  • CLI SAPI is compiled with libedit (readline replacement) and ncurses.
  • Network calls are asynchronous. Emscripten's Asyncify enables calling asynchronous code from synchronous code. TCP sockets are shimmed with a WebSocket connection to a built-in proxy server running on localhost. It supports data transfer, arbitrary connection targets, and setting a few TCP socket options.
  • PHP's OpenSSL uses the same CA certs as Node.js
  • PHP 5.6 is patched to work with OpenSSL 1.1.0 and many other small patches are introduced. For more details, see patches overview, Dockerfile, and phpwasm-emscripten-library.js

Future work:

  • PHP Interactive server isn't supported yet. Adding support is a matter of making the incoming connection polling non-blocking using Asyncify.
  • Use a more recent OpenSSL version
  • Better support for CLI interactive mode

@adamziel adamziel changed the title Networking support in CLI CLI and networking support Jan 27, 2023
@adamziel adamziel marked this pull request as ready for review January 27, 2023 16:13
@dmsnell
Copy link
Member

dmsnell commented Jan 27, 2023

Is there a discussion of where these patches come from or why they are what they are? Is there a reason they have to be here vs. in a fork of the upstream projects? I saw patches to SSL, which you know, catches the eye.

@eliot-akira
Copy link
Collaborator

Here's some discussion started about the patches: Propose PRs for the projects that are now patched ad-hoc.

@adamziel
Copy link
Collaborator Author

adamziel commented Jan 30, 2023

Is there a discussion of where these patches come from or why they are what they are? Is there a reason they have to be here vs. in a fork of the upstream projects? I saw patches to SSL, which you know, catches the eye.

As @eliot-akira mentioned, I'd love to merge these patches to the upstream projects. I will open Pull Requests for actively maintained projects like Emscripten. Unfortunately, PHP 5.6 and some friends are not getting new releases anymore. The OpenSSL patch you've mentioned is actually a PHP 5.6 patch to add OpenSSL 1.1.0 support. It's been proposed for upstream PHP 5.6 and rejected. AFAIK most webhosts who still support PHP 5.6 are maintaining their own fork to keep applying security patches.

Here's the overview of all the patches:

  • This PR removes all sqlite3 patches originally inherited from https://github.com/seanmorris/php-wasm. These patches moved SQLite3 sources directly to php-src, updated the #include paths to bake SQLite3 into the PHP build, and prevented a sqlite3 > 3.7.4 version check during the PHP ./configure command. This PR instead builds the correct sqlite3 version as a static WASM library using Emscripten's SIDE_MODULE and lets the linker connect the dots.
  • ncurses.patch – PHP CLI is compiled with readline support and linked with ncurses, however building ncurses using Emscripten fails since it involved creating some database files using the make_hash and make_keys binaries that can't be compiled as WASM. The patch ensures these databases are built using the system-native versions of make_hash and make_keys. Source 1 Source 2 (also provided inline).
  • bison2.7.patch – Compatibility with Emscripten's version of glibc which is newer than the one supported by Bison 2.7. Source: OpenWRT, more details (also provided inline).
  • php5.6-openssl1.1 patch – Adds OpenSSL 1.1.0 support for PHP 5.6. Source (also provided inline).
  • php5.6.patch – Adds a missing header declaration, otherwise emscripten won't compile the mbstring extension. Source: me.
  • php7.0.patch up to php8.0.patch:
    • Replaces zend_ulong with size_t, zend_off_t with long long, and ensures a pointer is used when calling php_stream_seek. It solves Esmcripten compilation errors, but I don't have a good grasp why is this even needed. Ideally this part of the patch could be removed. Source: me.
    • Avoids copying empty files as that crashes Emscripten's runtime. That's an Emscripten bug, not a PHP bug, but I found it much easier to patch in PHP. An ideal solution would patch upstream Emscripten. Source: me.
  • Dockerfile performs string-replace patching of:
    • ncurses Makefile – this could be merged into the provided .patch file and perhaps proposed for the upstream ncurses project. Source: same as above.
    • PHP – Adjusts build nuances like enforcing posix readdir_r support on older PHP versions or manually disabling unitstd.h. A few of these changes could be brought into upstream PHP 8, but most target the EOL-ed PHP versions. Source: me.
    • Built Emscripten's php5.6.js, php-8.0.js, etc. – these bugfixes and features are documented inline and I'd love to have every single one of them merged into upstream Emscripten repo as they're useful and will be hard to maintain separately. Source: me.
  • zlib – Playground uses a 10 years old Emscripten-compatible port of zlib because my initial attempt to compile the upstream version as WASM failed. I'm sure this old port can be removed, especially since Emscripten comes with -s USE_ZLIB=1 switch these days, but I didn't get there yet. PRs welcome!

@adamziel
Copy link
Collaborator Author

Let's merge this one and keep iterating in subsequent PRs

@adamziel adamziel merged commit 9c7d797 into trunk Jan 30, 2023
@adamziel adamziel deleted the explore/networking branch January 30, 2023 12:15
@adamziel adamziel mentioned this pull request Jan 30, 2023
@adamziel adamziel mentioned this pull request Apr 27, 2023
56 tasks
Pookie717 added a commit to Pookie717/wordpress-playground that referenced this pull request Oct 1, 2023
### Description

Adds support for CLI SAPI and networking in node.js:

```
> npm run build

> node ./build-cli/php-cli.js -r 'echo "Hello from PHP !";'
Hello from PHP !

> node ./build-cli/php-cli.js -r 'echo substr(file_get_contents("https://wordpress.org"), 0, 16);'
<!DOCTYPE html>

> node ./build-cli/php-cli.js -r 'echo phpversion();'
8.2.0-dev

> PHP=5.6 node ./build-cli/php-cli.js -r 'echo phpversion();'
5.6.40
```

### Highlights:

* Networking is supported (including MySQL and HTTPS)
* Switching PHP versions is supported.
* [Most WordPress PHPUnit tests pass](WordPress/wordpress-playground#111). The failures are caused by missing extensions and a few misconfigured settings
* PHP Interactive mode is supported but [the arrow keys don't work](WordPress/wordpress-playground#118)
* `wp-cli` works

### In broad strokes:

* CLI SAPI is compiled with libedit (readline replacement) and ncurses. 
* Network calls are asynchronous. Emscripten's Asyncify enables calling asynchronous code from synchronous code. TCP sockets are shimmed with a WebSocket connection to a built-in proxy server running on localhost. It supports data transfer, arbitrary connection targets, and setting a few TCP socket options.
* PHP's OpenSSL uses the same CA certs as Node.js
* PHP 5.6 is patched to work with OpenSSL 1.1.0 and many other small patches are introduced. For more details, see [patches overview](WordPress/wordpress-playground#119 (comment)), Dockerfile, and `phpwasm-emscripten-library.js`

### Future work:

* PHP Interactive server isn't supported yet. Adding support is a matter of making the incoming connection polling non-blocking using Asyncify.
* Use a more recent OpenSSL version
* [Better support for CLI interactive mode](WordPress/wordpress-playground#118)
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