Documentation
¶
Overview ¶
Package sharedport provides client functionality for HTCondor's shared port protocol.
The shared port protocol allows multiple HTCondor daemons to share a single network port by having a shared port server daemon forward connections to the appropriate daemon based on a shared port ID.
This implementation is based on the HTCondor C++ reference implementation in shared_port_client.cpp and related files.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func SendForwardedConn ¶ added in v0.1.0
SendForwardedConn is the producer side of the fd-pass handshake. Tests use it to drive the receiver in-process; production callers should never need it (real condor_shared_port talks the C++ side of this protocol).
SendForwardedConn writes the CEDAR-framed PASS_SOCK header on c then uses sendmsg(2) (via WriteMsgUnix) to attach toPass.Fd as ancillary data. The caller still owns toPass after the call returns; closing it on this side does not affect the duplicated fd that arrives on the receiver.
Types ¶
type Listener ¶ added in v0.1.0
type Listener struct {
// contains filtered or unexported fields
}
Listener is the endpoint side of HTCondor's shared-port forwarding mechanism: the side that *receives* connections forwarded by a condor_shared_port daemon.
A condor_shared_port daemon lets many daemons share one network port. When it decides a connection belongs to a particular endpoint, it hands the connected client fd off over a Unix-domain socket using a SHARED_PORT_PASS_SOCK handshake followed by SCM_RIGHTS fd passing. This is the general shared-port endpoint mechanism — it is not specific to any particular application protocol (HTTP, CEDAR, or otherwise); whatever bytes arrive on the forwarded fd are presented untouched.
Listener accepts those forwarded fds and exposes each one as a net.Conn. It implements net.Listener so callers can plug it directly into anything expecting a net.Listener (for example http.Server.Serve / ServeTLS), treating forwarded connections like any other accepted connection.
func AdoptFD ¶ added in v0.1.0
AdoptFD wraps a Unix-domain listening fd that was passed to us via process inheritance (typically from condor_master through CONDOR_INHERIT's SharedPort: token) and returns a Listener that runs the same shared-port handshake on incoming connections as Listen does.
The fd must already be in listening state and inheritable. After AdoptFD returns successfully, the Listener owns the fd's lifecycle — its Close will close the listener but will NOT remove the underlying socket file: condor_master created that path under $(DAEMON_SOCKET_DIR), and unlinking it would break the parent's shared_port routing for sibling daemons.
On error the fd is closed before returning so the caller doesn't have to track ownership during failure paths.
func Listen ¶ added in v0.1.0
Listen creates a UDS at socketPath, starts accepting fd-pass handshakes from shared_port, and returns a Listener whose Accept hands back the forwarded connections.
Any pre-existing socket file at socketPath is unlinked first; this matches the behavior of HTCondor's own SharedPortEndpoint, which must tolerate dead sockets left by a crash.
func (*Listener) Accept ¶ added in v0.1.0
Accept waits for the next connection forwarded by shared_port.
Implements net.Listener so callers can pass us directly to http.Server.Serve (or ServeTLS).
func (*Listener) Close ¶ added in v0.1.0
Close stops accepting new fd-pass handshakes, unlinks the UDS file, unblocks any pending Accept calls, and waits for in-flight handler goroutines to finish before returning. Safe to call multiple times.
The wait-for-handlers part exists because each handler may call l.logf as it returns (on a malformed handshake from a peer, typically). Tests that wire `Logf: t.Logf` would otherwise see a goroutine still emitting log lines after the test exited — Go's testing.T panics on that with "Log in goroutine after Test... has completed".
In production this is also the right thing: a graceful shutdown shouldn't leak goroutines that might still touch a logger the caller's about to tear down.
func (*Listener) SocketPath ¶ added in v0.1.0
SocketPath returns the absolute UDS path the listener is bound to — useful for tests and for emitting log lines that point at the address shared_port has been told to forward to. Returns "" for listeners adopted via AdoptFD (the parent owns the path, not us).
type LogFunc ¶ added in v0.1.0
LogFunc lets callers redirect this package's diagnostics to whatever logger they're already using. Defaults to a no-op.
type Options ¶ added in v0.1.0
type Options struct {
// HandshakeTimeout caps how long a single fd-pass handshake on the
// UDS may take. Zero defaults to 10s — shared_port handshakes are
// effectively local and should complete in milliseconds, so a tight
// bound mostly serves to catch misconfigured peers.
HandshakeTimeout time.Duration
// Logf is invoked for protocol errors (bad header, recvmsg
// failures, etc.). Set to nil to silence.
Logf LogFunc
}
Options controls listener construction. Zero values are sensible.
type SharedPortClient ¶
type SharedPortClient struct {
// contains filtered or unexported fields
}
SharedPortClient handles connections to daemons behind HTCondor's shared port
func NewSharedPortClient ¶
func NewSharedPortClient(clientName string) *SharedPortClient
NewSharedPortClient creates a new shared port client
func (*SharedPortClient) ConnectToHTCondorAddress ¶
func (spc *SharedPortClient) ConnectToHTCondorAddress(ctx context.Context, address string, deadline time.Duration) (*stream.Stream, error)
ConnectToHTCondorAddress is a convenience function that can connect to any HTCondor address, handling both regular TCP connections and shared port connections automatically.
It takes: - ctx: context for cancellation and timeouts - address: HTCondor address (e.g., "host:port" or "host:port?sock=daemon") - deadline: connection timeout
Returns a stream connected to the target daemon
func (*SharedPortClient) ConnectViaSharedPort ¶
func (spc *SharedPortClient) ConnectViaSharedPort(ctx context.Context, sharedPortAddr, sharedPortID string, deadline time.Duration) (*stream.Stream, error)
ConnectViaSharedPort connects to a daemon through HTCondor's shared port mechanism
It takes: - ctx: context for cancellation and timeouts - sharedPortAddr: the address of the shared port server (host:port) - sharedPortID: the ID of the target daemon (e.g., "startd", "schedd") - deadline: connection timeout
Returns a stream connected directly to the target daemon