sharedport

package
v0.1.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 2, 2026 License: Apache-2.0 Imports: 16 Imported by: 0

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

func SendForwardedConn(ctx context.Context, c *net.UnixConn, toPass uintptr) error

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

func AdoptFD(fd uintptr, opts Options) (*Listener, error)

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

func Listen(socketPath string, opts Options) (*Listener, error)

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

func (l *Listener) Accept() (net.Conn, error)

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) Addr added in v0.1.0

func (l *Listener) Addr() net.Addr

Addr returns the UDS address the listener is bound to.

func (*Listener) Close added in v0.1.0

func (l *Listener) Close() error

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

func (l *Listener) SocketPath() string

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

type LogFunc func(format string, args ...any)

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

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL