Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions packages/posix/src/driver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ import { ModuleCache } from './module-cache.js';
import { readdir, stat } from 'node:fs/promises';
import { existsSync, statSync } from 'node:fs';
import { basename, isAbsolute, join } from 'node:path';
import { type Socket } from 'node:net';
import { type Socket, isIP } from 'node:net';
import { connect as tlsConnect, type TLSSocket } from 'node:tls';
import { lookup } from 'node:dns/promises';

Expand Down Expand Up @@ -1325,8 +1325,11 @@ class WasmVmRuntimeDriver implements RuntimeDriver {
const hostname = msg.args.hostname as string;
const tlsOpts: Record<string, unknown> = {
socket: realSock,
servername: hostname, // SNI
};
// SNI is not allowed for IP addresses in Node.js
if (!isIP(hostname)) {
tlsOpts.servername = hostname;
}
if (msg.args.verifyPeer === false) {
tlsOpts.rejectUnauthorized = false;
}
Expand Down
8 changes: 8 additions & 0 deletions packages/posix/src/wasi-constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,12 +100,16 @@ export const ERRNO_EBADF = 8;
export const ERRNO_ECHILD = 10;
export const ERRNO_ECONNREFUSED = 14;
export const ERRNO_EEXIST = 20;
export const ERRNO_EINPROGRESS = 26;
export const ERRNO_EINVAL = 28;
export const ERRNO_EIO = 76;
export const ERRNO_EISDIR = 31;
export const ERRNO_EMFILE = 33;
export const ERRNO_EMSGSIZE = 40;
export const ERRNO_ENOENT = 44;
export const ERRNO_ENOSPC = 51;
export const ERRNO_ENOSYS = 52;
export const ERRNO_ENOTCONN = 53;
export const ERRNO_ENOTDIR = 54;
export const ERRNO_ENOTEMPTY = 55;
export const ERRNO_EPERM = 63;
Expand All @@ -123,12 +127,16 @@ export const ERRNO_MAP: Record<string, number> = {
ECHILD: ERRNO_ECHILD,
ECONNREFUSED: ERRNO_ECONNREFUSED,
EEXIST: ERRNO_EEXIST,
EINPROGRESS: ERRNO_EINPROGRESS,
EINVAL: ERRNO_EINVAL,
EIO: ERRNO_EIO,
EISDIR: ERRNO_EISDIR,
EMFILE: ERRNO_EMFILE,
EMSGSIZE: ERRNO_EMSGSIZE,
ENOENT: ERRNO_ENOENT,
ENOSPC: ERRNO_ENOSPC,
ENOSYS: ERRNO_ENOSYS,
ENOTCONN: ERRNO_ENOTCONN,
ENOTDIR: ERRNO_ENOTDIR,
ENOTEMPTY: ERRNO_ENOTEMPTY,
EPERM: ERRNO_EPERM,
Expand Down
36 changes: 36 additions & 0 deletions registry/native/c/curl-upstream-overlay/lib/wasi_getsockopt.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/* getsockopt shim — routes through host_net.net_getsockopt WASM import.
*
* The WASI socket patch provides setsockopt but not getsockopt. curl calls
* getsockopt(SOL_SOCKET, SO_ERROR) in verifyconnect() to check the result
* of a non-blocking connect. Without this shim, getsockopt returns -1 and
* curl treats every connection as failed (exit code 7).
*/

#include <sys/socket.h>
#include <errno.h>
#include <stdint.h>

#define WASM_IMPORT(mod, fn) \
__attribute__((__import_module__(mod), __import_name__(fn)))

WASM_IMPORT("host_net", "net_getsockopt")
uint32_t __host_net_getsockopt(uint32_t fd, uint32_t level, uint32_t optname,
uint8_t *optval_ptr, uint32_t *optval_len_ptr);

int getsockopt(int sockfd, int level, int optname, void *restrict optval,
socklen_t *restrict optlen) {
if (optval == NULL || optlen == NULL) {
errno = EINVAL;
return -1;
}
uint32_t len = (uint32_t)*optlen;
uint32_t err = __host_net_getsockopt(
(uint32_t)sockfd, (uint32_t)level, (uint32_t)optname,
(uint8_t *)optval, &len);
if (err != 0) {
errno = (int)err;
return -1;
}
*optlen = (socklen_t)len;
return 0;
}
12 changes: 8 additions & 4 deletions registry/native/c/scripts/build-curl-upstream.sh
Original file line number Diff line number Diff line change
Expand Up @@ -207,16 +207,20 @@ if "#define CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG 1" not in text:
config.write_text(text)
PY

echo "Patching generated lib/Makefile to compile wasi_tls.c..."
echo "Patching generated lib/Makefile to compile wasi_tls.c and wasi_getsockopt.c..."
cat >> lib/Makefile <<'EOF'

am_libcurl_la_OBJECTS += vtls/libcurl_la-wasi_tls.lo
libcurl_la_LIBADD += vtls/libcurl_la-wasi_tls.lo
libcurl.la: vtls/libcurl_la-wasi_tls.lo
am_libcurl_la_OBJECTS += vtls/libcurl_la-wasi_tls.lo libcurl_la-wasi_getsockopt.lo
libcurl_la_LIBADD += vtls/libcurl_la-wasi_tls.lo libcurl_la-wasi_getsockopt.lo
libcurl.la: vtls/libcurl_la-wasi_tls.lo libcurl_la-wasi_getsockopt.lo

vtls/libcurl_la-wasi_tls.lo: vtls/$(am__dirstamp) vtls/$(DEPDIR)/$(am__dirstamp) vtls/wasi_tls.c
$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT vtls/libcurl_la-wasi_tls.lo -MD -MP -MF vtls/$(DEPDIR)/libcurl_la-wasi_tls.Tpo -c -o vtls/libcurl_la-wasi_tls.lo `test -f 'vtls/wasi_tls.c' || echo '$(srcdir)/'`vtls/wasi_tls.c
$(AM_V_at)$(am__mv) vtls/$(DEPDIR)/libcurl_la-wasi_tls.Tpo vtls/$(DEPDIR)/libcurl_la-wasi_tls.Plo

libcurl_la-wasi_getsockopt.lo: wasi_getsockopt.c
$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-wasi_getsockopt.lo -MD -MP -MF $(DEPDIR)/libcurl_la-wasi_getsockopt.Tpo -c -o libcurl_la-wasi_getsockopt.lo `test -f 'wasi_getsockopt.c' || echo '$(srcdir)/'`wasi_getsockopt.c
$(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-wasi_getsockopt.Tpo $(DEPDIR)/libcurl_la-wasi_getsockopt.Plo
EOF

echo "Building upstream libcurl..."
Expand Down