Documentation
¶
Overview ¶
Package protocol implements the monolock binary wire format.
All multi-byte integers are big endian. TCP is a byte stream, so every fixed size field is read with io.ReadFull.
Client -> server:
ACQUIRE [0x01][version uint8][lease_ms uint32][name_len uint16][name bytes] HEARTBEAT [0x02]
Server -> client:
WAITING [0x11] ACQUIRED [0x12][token uint64] ERROR [0x13][code uint8][reason_len uint8][reason bytes]
The lease is chosen by the client: a session that stays quiet for lease_ms is dropped by the server. It must be positive and stays constant for the lifetime of the connection.
The token is a fencing token: it grows monotonically with every grant of any lock, so the resource a lock guards can reject writes carrying a token smaller than one it has already seen. Every ACQUIRED of a session carries the same token the session was granted.
Index ¶
- Constants
- Variables
- func AppendAcquire(dst []byte, name string, leaseMS uint32) ([]byte, error)
- func AppendAcquired(dst []byte, token uint64) []byte
- func AppendError(dst []byte, code uint8, reason string) []byte
- func ErrCodeName(c uint8) string
- func MsgName(t uint8) string
- func ReadAcquireBody(r io.Reader) (version uint8, leaseMS uint32, name string, err error)
- func ReadAcquiredBody(r io.Reader) (token uint64, err error)
- func ReadErrorBody(r io.Reader) (code uint8, reason string, err error)
- type Error
Constants ¶
const ( MsgAcquire uint8 = 0x01 MsgHeartbeat uint8 = 0x02 )
Client -> server message types.
const ( MsgWaiting uint8 = 0x11 MsgAcquired uint8 = 0x12 MsgError uint8 = 0x13 )
Server -> client message types.
const MaxNameLen = 255
MaxNameLen is the largest accepted lock name, in bytes. It is a protocol constant rather than a knob: client and server enforce the same value, so a name a client can build is a name the server will accept. The wire format carries a uint16 length and can express more, which the server rejects.
const Version uint8 = 1
Version is the protocol version implemented here.
Variables ¶
var ( ErrShuttingDown = newError(0x01, "server shutting down") ErrAdminClosed = newError(0x02, "closed by administrator") ErrUnsupportedVersion = newError(0x10, "unsupported protocol version") ErrExpectedAcquire = newError(0x11, "first message must be ACQUIRE") ErrDuplicateAcquire = newError(0x12, "duplicate ACQUIRE") ErrUnknownMessage = newError(0x13, "unknown message type") ErrEmptyName = newError(0x14, "empty lock name") ErrNameTooLong = newError(0x15, "lock name too long") ErrNameNotUTF8 = newError(0x16, "lock name is not valid UTF-8") ErrInvalidLease = newError(0x17, "lease must be positive") ErrNotAuthorized = newError(0x18, "not authorized for lock") )
Canonical protocol errors, one wire code each. AppendAcquire and ReadAcquireBody return the name and lease ones when validating input; the server sends the code and text of an ERROR message from the same values, so a client can match a received code back to one of them with CodeErr.
Functions ¶
func AppendAcquire ¶
AppendAcquire appends an ACQUIRE message for name with the given lease to dst.
func AppendAcquired ¶
AppendAcquired appends an ACQUIRED message carrying the fencing token.
func AppendError ¶
AppendError appends an ERROR message with the given code and reason. The reason is for humans: clients branch on the code alone. A reason longer than 255 bytes is truncated to fit the length field.
func ErrCodeName ¶
ErrCodeName returns a human readable name for an ERROR code.
func ReadAcquireBody ¶
ReadAcquireBody reads an ACQUIRE message body, i.e. everything after the type byte, which the caller has already consumed.
A name longer than MaxNameLen fails without reading the name itself; the caller is expected to answer with ERROR and close the connection, so the stream is not resynchronised.
func ReadAcquiredBody ¶
ReadAcquiredBody reads an ACQUIRED message body, i.e. everything after the type byte, which the caller has already consumed.
Types ¶
type Error ¶
type Error struct {
Code uint8
// contains filtered or unexported fields
}
Error is a protocol error: a stable wire code plus its canonical text. The code is what clients branch on, the text is for humans.
func CodeErr ¶
CodeErr returns the canonical Error for a wire code, or nil for a code this version of the protocol does not know.