Skip to content

feat(socket): UDPSocket + UNIXSocket/UNIXServer + server-side TLS - #192

Merged
tannevaled merged 1 commit into
mainfrom
feat/socket-udp-unix-tls
Jul 6, 2026
Merged

tannevaled merged 1 commit into
mainfrom
feat/socket-udp-unix-tls

Conversation

@tannevaled

Copy link
Copy Markdown
Contributor

Extends rbgo's socket transport (require "socket" / "openssl", PR #173) with the socket families and TLS features it deferred, all backed by Go net + crypto/tls.

What's bound

Feature Go backing File
UDPSocket — new([af])/bind/connect/send(msg,flags[,host,port])/recvfrom→[msg,sender]/recv/addr/close *net.UDPConn socket_udp.go
UNIXSocket / UNIXServer — connect/accept/path/addr + shared stream IO (read/gets/write/recv/send/…) net unix socket_unix.go
Server-side TLS — SSLSocket#accept + OpenSSL::SSL::SSLServer (wraps TCPServer + SSLContext, #accept returns handshaked server sockets) tls.Server socket_bind.go
Cert / verify — SSLContext#cert/#key/#ca_file → real server cert / client RootCAs / mutual-TLS client cert; VERIFY_PEER chain+hostname; #peer_cert; real X509::Certificate (new(pem)/to_pem/subject) crypto/tls + crypto/x509 socket_bind.go

recv/send were also added to the shared connected-stream surface (TCP/UNIX/SSL). Both TLS handshakes release the GVL so an in-VM client and a server Thread handshake concurrently.

Hermetic proofs (through the engine, no external network)

  • UDP: in-test Go UDP echo server; Ruby UDPSocket connect+send+recv and send-with-dest+recvfrom assert the echo.
  • UNIX: temp socket path, in-VM server/client via Thread; skipped on Windows.
  • Server-TLS: in-VM SSLServer with a self-signed cert generated in-test; a client SSLSocket connects and round-trips; plus mutual-TLS and client ca_file verification (success + hostname-mismatch failure via httptest).

Windows / AF_UNIX

AF_UNIX is unsupported on Windows, so the UNIX transport is build-tagged !windows; the Windows build (socket_unix_windows.go) installs UNIXSocket/UNIXServer stubs whose constructors raise a clean, rescuable NotImplementedError (a Windows-only test covers them). classOf's platform-gated tail is split (classof_platform*.go) so neither lane has a dead branch. Cross-compiled GOOS=windows build/vet/test-compile all clean.

Coverage

100% on the new code (loopback + injected error seams, e.g. a udpListen seam for the ephemeral-bind error arm); full internal/... suite green at 100% total, -race clean.

Deferred

Raw Socket.new, full Addrinfo, SNI callbacks / session-resumption tuning.

🤖 Generated with Claude Code

Extend rbgo's socket transport (require "socket" / "openssl") with the
families and TLS features the initial PR (#173) deferred, all backed by
Go's net + crypto/tls:

- UDPSocket (socket_udp.go): datagram socket over *net.UDPConn —
  new([af]) / bind / connect / send(msg,flags[,host,port]) / recvfrom ->
  [msg, sender] / recv / addr / close, with MRI datagram semantics for the
  common cases (ephemeral bind on new, connect records a default peer).

- UNIXSocket / UNIXServer (socket_unix.go): AF_UNIX stream sockets sharing
  the connected-stream IO surface (read/gets/write/recv/send/...) with
  TCPSocket. AF_UNIX is unsupported on Windows, so the whole transport is
  build-tagged !windows; the Windows build (socket_unix_windows.go) installs
  stub classes whose constructors raise a clean, rescuable
  NotImplementedError. The UNIX loopback tests skip on Windows.

- Server-side TLS (socket_bind.go): OpenSSL::SSL::SSLSocket#accept (server
  handshake via tls.Server) and OpenSSL::SSL::SSLServer wrapping a TCPServer
  + SSLContext so #accept returns handshaked server SSLSockets. Both
  handshakes release the GVL so an in-VM client and server Thread run
  concurrently.

- Cert / verify surface: SSLContext#cert / #key / #ca_file now feed real
  crypto/tls material — server certificate, client RootCAs, mutual-TLS
  client certificate. VERIFY_PEER performs Go's chain + hostname
  verification; #peer_cert returns the handshaked peer's certificate.
  OpenSSL::X509::Certificate is upgraded from a shell to a real PEM-carrying
  cert (parse on new, #to_pem / #subject).

Proven end-to-end through the engine against in-test loopback servers:
UDP echo, UNIX loopback (skipped on Windows), in-VM server-TLS round trip
with a self-signed cert generated in-test, mutual-TLS, and ca_file
verification (success + hostname-mismatch failure). 100% coverage on the
new code (loopback + injected error seams).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@tannevaled
tannevaled merged commit f538c0b into main Jul 6, 2026
9 checks passed
@tannevaled
tannevaled deleted the feat/socket-udp-unix-tls branch July 6, 2026 20:44
tannevaled added a commit that referenced this pull request Jul 6, 2026
)

Extend rbgo's socket transport (require "socket") with the name-resolution
and address utilities the connected/datagram socket work (#173/#192)
deferred, all backed by Go's net package (no cgo):

- Socket.getaddrinfo(host, port[, family, socktype, protocol, flags]) ->
  MRI's [afamily, port, host, addr, pfamily, socktype, protocol] tuples,
  resolved through net.Resolver with no reverse lookup (hermetic).
- Addrinfo value class: .tcp / .udp / .ip / .getaddrinfo / .new (packed
  sockaddr String or [afamily, port, host, addr] array), plus
  ip_address / ip_port / afamily / pfamily / socktype / protocol /
  ipv4? / ipv6? / to_sockaddr / inspect.
- sockaddr pack/unpack: Socket.pack_sockaddr_in / sockaddr_in /
  unpack_sockaddr_in (IPv4 + IPv6) and pack_sockaddr_un / sockaddr_un /
  unpack_sockaddr_un (AF_UNIX, non-Windows; NotImplementedError stubs on
  Windows, mirroring the UNIXSocket transport).

The sockaddr layout is the Linux one (no BSD sa_len byte): the family
field is host native byte order (a C sa_family_t) while port and address
are network byte order, so the [port, host] round-trip is byte-exact on
every arch. Verified on big-endian s390x under emulation.

Tests exercise the whole surface through the rbgo engine against
loopback-resolvable inputs (127.0.0.1 / ::1 / localhost); the resolver and
service-name port lookup are driven through injectable seams (resolveIPs /
lookupPort) so the suite never touches live DNS. 100% coverage of the new
code, including every error and platform arm.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
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.

1 participant