Ophestra af741f20a0
All checks were successful
Test / Create distribution (push) Successful in 36s
Test / Sandbox (push) Successful in 2m35s
Test / Sandbox (race detector) (push) Successful in 4m45s
Test / Hakurei (push) Successful in 5m0s
Test / Hpkg (push) Successful in 5m7s
Test / Hakurei (race detector) (push) Successful in 6m37s
Test / Flake checks (push) Successful in 1m34s
internal/pipewire: implement client context
This consumes the entire sample, is validated to send identical messages and correctly handle received messages.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-12-02 06:03:21 +09:00

74 lines
2.4 KiB
Go

package pipewire
import (
"encoding/binary"
"errors"
)
const (
// SizeHeader is the fixed size of [Header].
SizeHeader = 16
// SizeMax is the largest value of [Header.Size] that can be represented in its 3-byte segment.
SizeMax = 0x00ffffff
)
var (
// ErrSizeRange indicates that the value of [Header.Size] cannot be represented in its 3-byte segment.
ErrSizeRange = errors.New("size out of range")
// ErrBadHeader indicates that the header slice does not have length [HeaderSize].
ErrBadHeader = errors.New("incorrect header size")
)
// A Header is the fixed-size message header described in protocol native.
type Header struct {
// The message id this is the destination resource/proxy id.
ID Int `json:"Id"`
// The opcode on the resource/proxy interface.
Opcode byte `json:"opcode"`
// The size of the payload and optional footer of the message.
// Note: this value is only 24 bits long in the format.
Size uint32 `json:"size"`
// An increasing sequence number for each message.
Sequence Int `json:"seq"`
// Number of file descriptors in this message.
FileCount Int `json:"n_fds"`
}
// append appends the protocol native message header to data.
//
// Callers must perform bounds check on [Header.Size].
func (h *Header) append(data []byte) []byte {
data = binary.NativeEndian.AppendUint32(data, Word(h.ID))
data = binary.NativeEndian.AppendUint32(data, Word(h.Opcode)<<24|h.Size)
data = binary.NativeEndian.AppendUint32(data, Word(h.Sequence))
data = binary.NativeEndian.AppendUint32(data, Word(h.FileCount))
return data
}
// MarshalBinary encodes the protocol native message header.
func (h *Header) MarshalBinary() (data []byte, err error) {
if h.Size&^SizeMax != 0 {
return nil, ErrSizeRange
}
return h.append(make([]byte, 0, SizeHeader)), nil
}
// unmarshalBinary decodes the protocol native message header.
func (h *Header) unmarshalBinary(data [SizeHeader]byte) {
h.ID = Int(binary.NativeEndian.Uint32(data[0:4]))
h.Size = binary.NativeEndian.Uint32(data[4:8])
h.Opcode = byte(h.Size >> 24)
h.Size &= SizeMax
h.Sequence = Int(binary.NativeEndian.Uint32(data[8:]))
h.FileCount = Int(binary.NativeEndian.Uint32(data[12:]))
}
// UnmarshalBinary decodes the protocol native message header.
func (h *Header) UnmarshalBinary(data []byte) error {
if len(data) != SizeHeader {
return ErrBadHeader
}
h.unmarshalBinary(([SizeHeader]byte)(data))
return nil
}