Skip to content

tns: compile the protocol core on Windows via a Winsock shim (Windows port, phase 1) - #8

Merged
lemenkov merged 1 commit into
masterfrom
windows-core-mingw
Jul 25, 2026
Merged

tns: compile the protocol core on Windows via a Winsock shim (Windows port, phase 1)#8
lemenkov merged 1 commit into
masterfrom
windows-core-mingw

Conversation

@lemenkov

Copy link
Copy Markdown
Owner

Phase 1 of the Windows port: get the protocol core (src/common + src/tns) compiling and passing offline unit tests under MinGW-w64. Builds on the Phase 0 CI scaffold (#7).

Approach — thin in-tree shim, not a dependency

The network surface is tiny and concentrated (one file, ~10 blocking socket calls, a nonblocking connect + timeout). Portability libraries (libuv, APR) are async-runtime-sized for that and would fight the project's minimal-footprint design (clean-room, no deps beyond OpenSSL, links no Driver Manager). So this adds a small shim — the same shape curl / libpq / OpenSSH use. The recv/send-instead-of-read/write trick is curl's sread/swrite.

Changes

  • src/common/netcompat.{h,c} — one home for the POSIX↔Winsock split:
    • Windows SOCKETs aren't fds → recv/send replace read/write; seer_socket_t / SEER_INVALID_SOCKET (SOCKET is unsigned, so fd < 0 checks are wrong).
    • ioctlsocket(FIONBIO)fcntl(O_NONBLOCK); SO_RCVTIMEO is a DWORD ms not a timeval; connect "in progress" is WSAEWOULDBLOCK not EINPROGRESS; WSAPollpoll.
    • seer_net_init() runs WSAStartup once via InitOnceExecuteOnce (no threads dep in common); no-op on POSIX.
  • transport.c — socket lifecycle rewritten over the shim; WSAStartup before the first getaddrinfo.
  • ttc.c — include netcompat.h for gethostname() (Winsock on Windows).
  • stmt.c — include <strings.h> for strncasecmp (was resolving only via a glibc include chain; now portable across glibc / MinGW-w64 / macOS).
  • meson — build netcompat.c everywhere; link ws2_32 on Windows, propagated via common_dep.
  • cibuild-windows now compiles + runs offline unit tests (was configure-only).

Verification

  • Linux offline suite 9 / 0 / 4 — unchanged.
  • Live 11g under ASan/UBSan (the rewritten socket path end-to-end): odbc integration, two-phase commit, object bind, advanced queuing — 4 / 0.
  • The MinGW compile itself is validated by the Build + unit (Windows/MinGW) CI job on this PR.

Next phases

  1. ODBC shim (src/odbc): SQLWCHAR-is-UTF-16, .def export, seerodbc.dll
  2. loads under the MS Driver Manager + live query
  3. Setup DLL (ConfigDSN) + installer

🤖 Generated with Claude Code

Comment thread src/common/netcompat.h
#ifdef _WIN32
return send(s, (const char *)buf, (int)len, 0);
#else
return send(s, buf, len, 0);
@lemenkov
lemenkov force-pushed the windows-core-mingw branch 3 times, most recently from 413fb7e to 86527c8 Compare July 25, 2026 09:23
Phase 1 of the Windows port: get src/common + src/tns building under
MinGW-w64. The network surface is tiny and concentrated, so rather than
take a portability dependency (libuv/APR are async-runtime-sized for what
is ~10 blocking socket calls), add a thin in-tree shim - the same shape
curl/libpq/OpenSSH use.

  * src/common/netcompat.{h,c}: one place for the POSIX-vs-Winsock split.
    Windows SOCKETs are not file descriptors, so recv/send replace
    read/write (curl's sread/swrite trick), ioctlsocket(FIONBIO) replaces
    fcntl(O_NONBLOCK), SO_RCVTIMEO takes a DWORD not a timeval, connect's
    "in progress" is WSAEWOULDBLOCK not EINPROGRESS, and poll is WSAPoll.
    seer_net_init() runs WSAStartup once via InitOnceExecuteOnce (no
    threads dep in common); a no-op on POSIX.
  * transport.c: socket lifecycle rewritten over the shim - seer_socket_t
    / SEER_INVALID_SOCKET (SOCKET is unsigned; fd<0 checks are wrong),
    recv/send, and a WSAStartup call before the first getaddrinfo.
  * ttc.c, session.c: include netcompat.h for gethostname() (a Winsock
    call on Windows, in <unistd.h> on POSIX).
  * auth.c: replace the GNU memmem() - absent from the Windows CRT - with
    a portable seer_memmem() in src/common/compat.{c,h}, used on every
    platform (one code path, no per-caller #ifdef).
  * stmt.c: include <strings.h> for strncasecmp (portable on glibc,
    MinGW-w64 and macOS; was resolving only via a glibc include chain).
  * meson: build netcompat.c + compat.c everywhere; link ws2_32 on
    Windows, propagated through common_dep. Define __USE_MINGW_ANSI_STDIO
    on Windows so printf/snprintf use MinGW's C99 stdio - msvcrt's default
    lacks the 'z' (size_t) length modifier the core's formats rely on,
    both at compile time (-Wformat) and, more importantly, at run time.
  * scope: the ODBC shim (src/odbc) is deferred on Windows to the next
    phase. MinGW ships sql.h, but the native ODBC headers need a
    Windows-specific port (<windows.h> ordering for HWND/DWORD/GUID,
    SQLWCHAR as UTF-16, .def exports, registry DSNs), so meson builds the
    protocol core + freeoracle there for now.
  * ci: the build-windows job now compiles and runs the offline unit
    tests, not just `meson setup`.

No behaviour change on POSIX: Linux offline suite 9/0/4 unchanged, and
the live 11g integration (odbc integration, TPC, object bind, AQ) passes
under ASan/UBSan.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
@lemenkov
lemenkov force-pushed the windows-core-mingw branch from 86527c8 to 466434b Compare July 25, 2026 10:09
@lemenkov
lemenkov merged commit a087ffe into master Jul 25, 2026
10 checks passed
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.

2 participants