Documentation
¶
Index ¶
- Constants
- func NewLogger(logLevel string) *logrus.Logger
- func NewLoggerWithFormat(logLevel, format string) *logrus.Logger
- func ReceiveBinaryByte(conn net.Conn) (byte, error)
- func ReceiveBinaryString(conn interface{}) (string, error)
- func ReceiveBinaryTransportString(conn interface{}) (string, byte, error)
- func SendBinaryByte(conn interface{}, message byte) error
- func SendBinaryByteWithin(conn net.Conn, message byte, timeout time.Duration) error
- func SendBinaryString(conn interface{}, message string) error
- func SendBinaryTransportString(conn interface{}, message string, transport byte) error
- func WebSocketSignal(messageType int, payload []byte) (signal byte, ok bool)
- type CustomFormatter
Constants ¶
const ( SG_HB byte = iota // for heartbeat SG_Chan // for channel, req a new conn SG_Ping // for ping SG_Closed // for closed channel SG_TCP // TCP Transport ID SG_UDP // TCP Transport ID SG_RTT // For RTT measurment // SG_ChanV2 opens a control channel that authorises pool connections by a // per-run nonce instead of by source address. It is a separate signal // rather than a flag inside the old one so that a server which predates it // simply does not recognise it, and the client can fall back — see the // handshake in the client transports. SG_ChanV2 // SG_Pool announces a pool connection, carrying the nonce the server handed // out when the control channel was established. SG_Pool // SG_Refused answers a control handshake the server will not accept, // carrying a short reason. // // It exists because the alternative was silence. The server used to close // the connection on a token it did not recognise and on a claim for a // control channel it had already given away, and both reach the client as // "failed to read message length from net.Conn: EOF" — the same thing an // old server produces by not understanding the signal at all. Three // different faults, one symptom, and the client guessed the least likely of // them: it reported the server as out of date and told the operator to // upgrade a server whose only problem was a mistyped token. // // A client too old to know this signal is no worse off than before. It // compares the answer against its own token, fails to match, and reports an // invalid token — which is wrong in wording but points at the right half of // the configuration, where EOF pointed at nothing. SG_Refused )
const ( // RefusedBadToken is a token that does not match the server's. RefusedBadToken = "token" // RefusedInUse is a control channel this server has already given to // somebody else — two clients dialling one server with the same token, or // an old service left running beside its replacement. RefusedInUse = "in-use" )
Why a control handshake was refused. Short, because it crosses the wire on every rejected attempt, and free of anything an unauthenticated peer should not be told — a refusal says which side is wrong, never what the right answer would have been.
Variables ¶
This section is empty.
Functions ¶
func NewLoggerWithFormat ¶
NewLoggerWithFormat builds a logger in either the human-readable format or JSON.
JSON exists for anyone shipping logs somewhere that parses them — journald's structured fields, a log collector, a script. The default stays the coloured text format, because the usual way these logs are read is a person running journalctl on their own server, and JSON is worse for that.
func ReceiveBinaryString ¶
func SendBinaryByte ¶
func SendBinaryByteWithin ¶
SendBinaryByteWithin is SendBinaryByte with a bound on how long it may take.
A one-byte write looks instant and is not. It lands in the kernel's send buffer, and when the peer has stopped absorbing anything — a path that has black-holed, a machine that went away without closing — the buffer fills and the write blocks. Nothing returns an error until the kernel gives up retransmitting, which on Linux defaults is on the order of fifteen minutes.
For a heartbeat on the control channel that is not a delay, it is the whole failure: the server goes on believing it has a control channel, refuses the client's attempts to establish a new one because one is "already established", cannot ask for pool connections because the request never reaches anybody, and drops every user connection with the queue full — for as long as the kernel takes. The tunnel is down and the only thing that clears it is a restart by hand.
A control channel that cannot take one byte within a few seconds is not a control channel. This says so while it is still worth saying.
func SendBinaryString ¶
func WebSocketSignal ¶
WebSocketSignal reads one control-channel signal out of a WebSocket frame.
Every signal above goes on the wire the same way: a binary frame holding exactly one byte. The read loops took that on trust and went straight to msg[0], which is fine for every frame either end of this tunnel has ever sent and fatal for one it has not — an empty binary frame indexes past the end of the slice and takes the whole process down with it. A control channel is reachable by whoever holds the token, and a tunnel that can be stopped by one zero-length frame is not one that should be.
ok is false for anything that is not a single-byte binary frame. The callers log it and read on: dropping a frame that carries no signal leaves them exactly where ignoring it always left them, and is the one response that cannot be provoked into disrupting a tunnel that is working.
Types ¶
type CustomFormatter ¶
type CustomFormatter struct{}
Directories
¶
| Path | Synopsis |
|---|---|
|
Package acceptloop keeps a failing accept loop from burning a core.
|
Package acceptloop keeps a failing accept loop from burning a core. |