Documentation
¶
Index ¶
- Constants
- func GenerateInsecureSelfSignedCert() (tls.Certificate, error)
- func IsClusterALPN(alpn string) bool
- func IsClusterNotReady(err error) bool
- func RegistryALPNs() []string
- type QUICConn
- func (c *QUICConn) Close() error
- func (c *QUICConn) LocalAddr() net.Addr
- func (c *QUICConn) Read(b []byte) (n int, err error)
- func (c *QUICConn) RemoteAddr() net.Addr
- func (c *QUICConn) SetDeadline(t time.Time) error
- func (c *QUICConn) SetReadDeadline(t time.Time) error
- func (c *QUICConn) SetWriteDeadline(t time.Time) error
- func (c *QUICConn) Write(b []byte) (n int, err error)
- type QUICSerfTransport
- func (t *QUICSerfTransport) DialTimeout(addr string, timeout time.Duration) (net.Conn, error)
- func (t *QUICSerfTransport) FinalAdvertiseAddr(ip string, port int) (net.IP, int, error)
- func (t *QUICSerfTransport) PacketCh() <-chan *memberlist.Packet
- func (t *QUICSerfTransport) Shutdown() error
- func (t *QUICSerfTransport) StreamCh() <-chan net.Conn
- func (t *QUICSerfTransport) WriteTo(b []byte, addr string) (time.Time, error)
- type QUICStreamLayer
- type SharedListener
Constants ¶
const ( // ALPNGoblinRPC is the goblinctl/scheduler RPC channel. ALPNGoblinRPC = "goblin-rpc" // ALPNSerfQUIC carries Serf gossip over QUIC datagrams/streams. ALPNSerfQUIC = "serf-quic" // ALPNRaftQUIC carries the Raft transport stream. ALPNRaftQUIC = "raft-quic" // ALPNGoblinCkpt carries CRIU checkpoint images between nodes // during migration (GOBLIN-DIV-018). Deliberately its own ALPN, and // therefore its own QUIC connection: a multi-gigabyte image sharing // a connection-level flow-control window with Raft heartbeats would // degrade the control plane exactly when a migration is in flight. ALPNGoblinCkpt = "goblin-ckpt" // ALPNGapiQUIC is the kernel's protocol, imported - never redefined // - so the two repos cannot drift (consumes GAPI-DIV-011). ALPNGapiQUIC = gapitransport.ALPNGapiQUIC )
ALPN protocol identifiers for the orchestrator's QUIC listeners and dialers. They mirror the ecosystem ALPN registry as their governing contract (append-only, tombstoned): a collision is a review failure, not a runtime discovery. Every handler and the ALPN router switch import these; inline literals are forbidden (GOBLIN-DIV-010).
const ( // CodeALPNNotServing: the negotiated ALPN is in the registry and // NOTHING IS EVER GOING TO SERVE IT here - a tombstoned row, or a // plane this build does not carry. Not retryable. CodeALPNNotServing = quic.ApplicationErrorCode(0x100) // CodeAdapterBacklogged: the adapter's accept channel is full; the // connection is refused rather than stalling every other plane. CodeAdapterBacklogged = quic.ApplicationErrorCode(0x101) // CodeClusterNotReady: a CLUSTER ALPN arrived before the cluster // stack registered it - Phase 4 has not completed on this node. // RETRYABLE, and that is the entire reason it is a separate code // (GOBLIN-DIV-051). // // It used to share 0x100 with the case above, and the conflation was // not cosmetic. A joining peer that cannot tell "not yet" from // "never" must treat a transient phase skew as a hard join failure, // which is exactly what it did: node-2 dialling node-1 during the // window before node-1 registered serf-quic got a refusal it read as // fatal, gave up, and the cluster never formed a leader. That race // was intermittent and its signature was a placement timeout, which // is how it survived as an unexplained flake across three suites. CodeClusterNotReady = quic.ApplicationErrorCode(0x102) )
QUIC application error codes the shared listener closes with. Named, never reused: a refused connection tells the peer exactly why.
Variables ¶
This section is empty.
Functions ¶
func GenerateInsecureSelfSignedCert ¶
func GenerateInsecureSelfSignedCert() (tls.Certificate, error)
GenerateInsecureSelfSignedCert generates a self-signed cert for testing/insecure modes.
func IsClusterALPN ¶
IsClusterALPN reports whether alpn is served only once the cluster stack exists.
func IsClusterNotReady ¶
IsClusterNotReady reports whether err is a peer's cluster-not-ready refusal - the retryable one.
It matches only the REMOTE close. A local application error with the same code would mean this node refused something, which is not a reason to redial anyone.
func RegistryALPNs ¶
func RegistryALPNs() []string
RegistryALPNs returns the full ALPN registry the shared listener advertises; per-ALPN TLS policies (GetConfigForClient) must carry the same list or negotiation would silently narrow.
Types ¶
type QUICSerfTransport ¶
type QUICSerfTransport struct {
// contains filtered or unexported fields
}
QUICSerfTransport implements memberlist.Transport using QUIC. It uses QUIC Datagrams for packet-based gossip and QUIC Streams for reliable sync. It does not own a listener: inbound connections arrive from the shared control-plane listener's ALPN router (GOBLIN-DIV-023); only the dial side opens connections, offering exactly the serf-quic ALPN.
func NewRoutedQUICSerfTransport ¶
func NewRoutedQUICSerfTransport(routed <-chan *quic.Conn, advertise net.Addr, tlsConf *tls.Config) (*QUICSerfTransport, error)
NewRoutedQUICSerfTransport builds the serf transport over routed connections. advertise is the node's single advertised control-plane address - it becomes the serf member address, so it must be dialable by peers.
func (*QUICSerfTransport) DialTimeout ¶
DialTimeout creates a reliable stream connection to the given address.
func (*QUICSerfTransport) FinalAdvertiseAddr ¶
FinalAdvertiseAddr returns the address to advertise: the node's single control-plane address unless memberlist overrides it.
func (*QUICSerfTransport) PacketCh ¶
func (t *QUICSerfTransport) PacketCh() <-chan *memberlist.Packet
PacketCh returns a channel for reading incoming packets.
func (*QUICSerfTransport) Shutdown ¶
func (t *QUICSerfTransport) Shutdown() error
Shutdown closes the transport's dialed connections. The shared listener stays open - it belongs to the supervisor, not this adapter.
func (*QUICSerfTransport) StreamCh ¶
func (t *QUICSerfTransport) StreamCh() <-chan net.Conn
StreamCh returns a channel for accepting incoming stream connections.
type QUICStreamLayer ¶
type QUICStreamLayer struct {
// contains filtered or unexported fields
}
QUICStreamLayer implements raft.StreamLayer over QUIC. It does not own a listener: inbound connections arrive from the shared control-plane listener's ALPN router (GOBLIN-DIV-023); only the dial side opens connections, offering exactly the raft-quic ALPN.
func NewRoutedQUICStreamLayer ¶
func NewRoutedQUICStreamLayer(conns <-chan *quic.Conn, addr net.Addr, tlsConf *tls.Config) *QUICStreamLayer
NewRoutedQUICStreamLayer builds the raft stream layer over routed connections. addr is the node's single advertised control-plane address - it becomes this server's raft address, so it must be dialable by peers.
func (*QUICStreamLayer) Accept ¶
func (l *QUICStreamLayer) Accept() (net.Conn, error)
Accept waits for the next routed raft-quic connection and surfaces its first stream as the raft net.Conn.
func (*QUICStreamLayer) Addr ¶
func (l *QUICStreamLayer) Addr() net.Addr
Addr returns the advertised control-plane address.
func (*QUICStreamLayer) Close ¶
func (l *QUICStreamLayer) Close() error
Close stops accepting routed connections. The shared listener stays open - it belongs to the supervisor, not this adapter.
func (*QUICStreamLayer) Dial ¶
func (l *QUICStreamLayer) Dial(addr raft.ServerAddress, timeout time.Duration) (net.Conn, error)
Dial creates a new connection to the given address.
type SharedListener ¶
type SharedListener struct {
// contains filtered or unexported fields
}
SharedListener is goblind's single control-plane QUIC listener (GOBLIN-DIV-023): every protocol shares one bind address and is routed to its adapter by negotiated ALPN. Adapters attach with Register; a connection negotiating an ALPN with no attached adapter is refused at accept with CodeALPNNotServing - fail closed, which is also the phase-aware admission rule (cluster ALPNs are not served until the cluster stack registers them).
func NewSharedListener ¶
func NewSharedListener(bindAddr string, tlsCfg *tls.Config, clusterReady func() bool) (*SharedListener, error)
NewSharedListener binds the control-plane address and starts the accept loop. The TLS config is cloned; its NextProtos are replaced with the full ALPN registry (datagrams are enabled - serf gossip requires RFC 9221 support end to end). clusterReady is required, not optional. It reports whether the cluster stack has registered its planes; the listener uses it to tell a peer "not yet" instead of "never" (GOBLIN-DIV-051). A nil predicate is a programming error rather than a default, because the default that would suit a test - always ready - is the answer that reintroduces the defect in production.
func (*SharedListener) Addr ¶
func (l *SharedListener) Addr() net.Addr
Addr is the single advertised control-plane address.
func (*SharedListener) Close ¶
func (l *SharedListener) Close() error
Close stops the accept loop and closes the listener.