libtailcat, tailcat: add C bindings for embedding tailcat - #6
Draft
bradfitz wants to merge 1 commit into
Draft
Conversation
Add a libtailcat directory that builds tailcat as a C library (c-archive and c-shared), modeled on github.com/tailscale/libtailscale, so tailcat can be embedded from C and from languages that link C. Connections and listeners cross the Go/C boundary as AF_UNIX socketpair file descriptors: dials and accepts hand C a plain fd it can read, write, poll, and close, so callers keep their existing netpoll event loops instead of adopting a callback API. Listeners deliver accepted connection fds via SCM_RIGHTS, making the listener itself pollable. Unlike libtailscale's fd plumbing, teardown waits for both copy directions to finish, preserving tailcat's netcat-style TCP half-close semantics. Lifecycle events (client-connected, connected, dial-ok, dial-error) are delivered per handle through an event fd that becomes readable when JSON events are queued, again for event loop friendliness. tailcat_client_dial is asynchronous: it returns the connection fd immediately, buffers writes in the socketpair, and reports the dial outcome as an event. In support of that, tailcat grows three small hooks: an exported Server.OnClientConnect callback fired when a client's meow handshake adds it as a peer, a Client.Connected channel accessor, and Server.WaitDERPConnected. The latter also fixes a real race: a client meow arriving at the relay before the server's DERP connection is up was silently lost, costing a 10 second retry. libtailcat's server start now waits for the relay connection so a ConnBlob handed out right after start is immediately usable. The ctest package drives a full C client/server exchange through a local DERP relay under go test, and CI builds both library flavors. Updates #5 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com> Change-Id: I9c4e2f7a8b3d1e5f0a6c9b2d4e7f8a1c3b5d6e9f
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Add a libtailcat directory that builds tailcat as a C library
(c-archive and c-shared), modeled on github.com/tailscale/libtailscale,
so tailcat can be embedded from C and from languages that link C.
Connections and listeners cross the Go/C boundary as AF_UNIX socketpair
file descriptors: dials and accepts hand C a plain fd it can read,
write, poll, and close, so callers keep their existing netpoll event
loops instead of adopting a callback API. Listeners deliver accepted
connection fds via SCM_RIGHTS, making the listener itself pollable.
Unlike libtailscale's fd plumbing, teardown waits for both copy
directions to finish, preserving tailcat's netcat-style TCP half-close
semantics.
Lifecycle events (client-connected, connected, dial-ok, dial-error)
are delivered per handle through an event fd that becomes readable
when JSON events are queued, again for event loop friendliness.
tailcat_client_dial is asynchronous: it returns the connection fd
immediately, buffers writes in the socketpair, and reports the dial
outcome as an event.
In support of that, tailcat grows three small hooks: an exported
Server.OnClientConnect callback fired when a client's meow handshake
adds it as a peer, a Client.Connected channel accessor, and
Server.WaitDERPConnected. The latter also fixes a real race:
a client meow arriving at the relay before the server's DERP
connection is up was silently lost, costing a 10 second retry.
libtailcat's server start now waits for the relay connection so a
ConnBlob handed out right after start is immediately usable.
The ctest package drives a full C client/server exchange through a
local DERP relay under go test, and CI builds both library flavors.
Updates #5