internal/pipewire: implement SecurityContext::Create
All checks were successful
Test / Create distribution (push) Successful in 36s
Test / Sandbox (push) Successful in 2m26s
Test / Hakurei (push) Successful in 3m18s
Test / Hpkg (push) Successful in 4m16s
Test / Sandbox (race detector) (push) Successful in 4m22s
Test / Hakurei (race detector) (push) Successful in 5m12s
Test / Flake checks (push) Successful in 1m27s
All checks were successful
Test / Create distribution (push) Successful in 36s
Test / Sandbox (push) Successful in 2m26s
Test / Hakurei (push) Successful in 3m18s
Test / Hpkg (push) Successful in 4m16s
Test / Sandbox (race detector) (push) Successful in 4m22s
Test / Hakurei (race detector) (push) Successful in 5m12s
Test / Flake checks (push) Successful in 1m27s
This is finally the thing we are after. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
parent
5a5c4705dd
commit
de3fc7ba38
@ -10,6 +10,7 @@ func TestFooterCoreGeneration(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
encodingTestCases[pipewire.Footer[pipewire.FooterCoreGeneration], *pipewire.Footer[pipewire.FooterCoreGeneration]]{
|
||||
|
||||
/* recvmsg 0 */
|
||||
|
||||
{"sample0", samplePWContainer[1][0][2], pipewire.Footer[pipewire.FooterCoreGeneration]{
|
||||
@ -29,6 +30,7 @@ func TestFooterCoreGeneration(t *testing.T) {
|
||||
}.run(t)
|
||||
|
||||
encodingTestCases[pipewire.Footer[pipewire.FooterClientGeneration], *pipewire.Footer[pipewire.FooterClientGeneration]]{
|
||||
|
||||
/* sendmsg 1 */
|
||||
|
||||
{"sample0", samplePWContainer[3][0][2], pipewire.Footer[pipewire.FooterClientGeneration]{
|
||||
@ -36,6 +38,13 @@ func TestFooterCoreGeneration(t *testing.T) {
|
||||
// why does this not match FooterCoreGeneration sample2?
|
||||
Payload: pipewire.FooterClientGeneration{ClientGeneration: 0x23},
|
||||
}, nil},
|
||||
|
||||
/* sendmsg 2 */
|
||||
|
||||
{"sample1", samplePWContainer[6][0][2], pipewire.Footer[pipewire.FooterClientGeneration]{
|
||||
Opcode: pipewire.FOOTER_CORE_OPCODE_GENERATION,
|
||||
Payload: pipewire.FooterClientGeneration{ClientGeneration: 0x24},
|
||||
}, nil},
|
||||
}.run(t)
|
||||
}
|
||||
|
||||
@ -101,6 +110,12 @@ func TestCoreDone(t *testing.T) {
|
||||
ID: 0,
|
||||
Sequence: pipewire.CoreSyncSequenceOffset + 3,
|
||||
}, nil},
|
||||
|
||||
// matches the second Core::Sync sample
|
||||
{"sample2", samplePWContainer[7][0][1], pipewire.CoreDone{
|
||||
ID: 0,
|
||||
Sequence: pipewire.CoreSyncSequenceOffset + 6,
|
||||
}, nil},
|
||||
}.run(t)
|
||||
}
|
||||
|
||||
@ -150,10 +165,15 @@ func TestCoreSync(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
encodingTestCases[pipewire.CoreSync, *pipewire.CoreSync]{
|
||||
{"sample", samplePWContainer[0][3][1], pipewire.CoreSync{
|
||||
{"sample0", samplePWContainer[0][3][1], pipewire.CoreSync{
|
||||
ID: 0,
|
||||
Sequence: pipewire.CoreSyncSequenceOffset + 3,
|
||||
}, nil},
|
||||
|
||||
{"sample1", samplePWContainer[6][1][1], pipewire.CoreSync{
|
||||
ID: 0,
|
||||
Sequence: pipewire.CoreSyncSequenceOffset + 6,
|
||||
}, nil},
|
||||
}.run(t)
|
||||
}
|
||||
|
||||
|
||||
@ -32,7 +32,7 @@ func TestHeader(t *testing.T) {
|
||||
Size: 0x28, Sequence: 2, FileCount: 0,
|
||||
}, nil},
|
||||
|
||||
{"PW_CORE_METHOD_SYNC", samplePWContainer[0][3][0], pipewire.Header{
|
||||
{"PW_CORE_METHOD_SYNC 0", samplePWContainer[0][3][0], pipewire.Header{
|
||||
ID: pipewire.PW_ID_CORE,
|
||||
Opcode: pipewire.PW_CORE_METHOD_SYNC,
|
||||
Size: 0x28, Sequence: 3, FileCount: 0,
|
||||
@ -314,33 +314,27 @@ func TestHeader(t *testing.T) {
|
||||
Size: 0x68, Sequence: 43, FileCount: 0,
|
||||
}, nil},
|
||||
|
||||
{"PW_SECURITY_CONTEXT_METHOD_CREATE", []byte{
|
||||
// Id
|
||||
3, 0, 0, 0,
|
||||
// size
|
||||
0xd8, 0, 0,
|
||||
// opcode
|
||||
1,
|
||||
// seq
|
||||
5, 0, 0, 0,
|
||||
// n_fds
|
||||
2, 0, 0, 0,
|
||||
}, pipewire.Header{ID: 3, Opcode: pipewire.PW_SECURITY_CONTEXT_METHOD_CREATE,
|
||||
Size: 0xd8, Sequence: 5, FileCount: 2}, nil},
|
||||
/* sendmsg 2 */
|
||||
|
||||
{"PW_SECURITY_CONTEXT_METHOD_NUM", []byte{
|
||||
// Id
|
||||
0, 0, 0, 0,
|
||||
// size
|
||||
0x28, 0, 0,
|
||||
// opcode
|
||||
2,
|
||||
// seq
|
||||
6, 0, 0, 0,
|
||||
// n_fds
|
||||
0, 0, 0, 0,
|
||||
}, pipewire.Header{ID: 0, Opcode: pipewire.PW_SECURITY_CONTEXT_METHOD_NUM,
|
||||
Size: 0x28, Sequence: 6, FileCount: 0}, nil},
|
||||
{"PW_SECURITY_CONTEXT_METHOD_CREATE", samplePWContainer[6][0][0], pipewire.Header{
|
||||
ID: 3,
|
||||
Opcode: pipewire.PW_SECURITY_CONTEXT_METHOD_CREATE,
|
||||
Size: 0xd8, Sequence: 5, FileCount: 2,
|
||||
}, nil},
|
||||
|
||||
{"PW_CORE_METHOD_SYNC 1", samplePWContainer[6][1][0], pipewire.Header{
|
||||
ID: pipewire.PW_ID_CORE,
|
||||
Opcode: pipewire.PW_CORE_METHOD_SYNC,
|
||||
Size: 0x28, Sequence: 6, FileCount: 0,
|
||||
}, nil},
|
||||
|
||||
/* recvmsg 2 */
|
||||
|
||||
{"PW_CORE_EVENT_DONE 2", samplePWContainer[7][0][0], pipewire.Header{
|
||||
ID: pipewire.PW_ID_CORE,
|
||||
Opcode: pipewire.PW_CORE_EVENT_DONE,
|
||||
Size: 0x28, Sequence: 44, FileCount: 0,
|
||||
}, nil},
|
||||
}.run(t)
|
||||
|
||||
t.Run("size range", func(t *testing.T) {
|
||||
|
||||
@ -356,30 +356,6 @@ const (
|
||||
PW_KEY_PROFILER_NAME = "profiler.name"
|
||||
)
|
||||
|
||||
/* pipewire/extensions/security-context.h */
|
||||
|
||||
const (
|
||||
PW_TYPE_INTERFACE_SecurityContext = PW_TYPE_INFO_INTERFACE_BASE + "SecurityContext"
|
||||
PW_SECURITY_CONTEXT_PERM_MASK = PW_PERM_RWX
|
||||
PW_VERSION_SECURITY_CONTEXT = 3
|
||||
|
||||
PW_EXTENSION_MODULE_SECURITY_CONTEXT = PIPEWIRE_MODULE_PREFIX + "module-security-context"
|
||||
)
|
||||
|
||||
const (
|
||||
PW_SECURITY_CONTEXT_EVENT_NUM = iota
|
||||
|
||||
PW_VERSION_SECURITY_CONTEXT_EVENTS = 0
|
||||
)
|
||||
|
||||
const (
|
||||
PW_SECURITY_CONTEXT_METHOD_ADD_LISTENER = iota
|
||||
PW_SECURITY_CONTEXT_METHOD_CREATE
|
||||
PW_SECURITY_CONTEXT_METHOD_NUM
|
||||
|
||||
PW_VERSION_SECURITY_CONTEXT_METHODS = 0
|
||||
)
|
||||
|
||||
/* pipewire/type.h */
|
||||
|
||||
const (
|
||||
|
||||
@ -30,6 +30,9 @@ type (
|
||||
String = string
|
||||
// Bytes is a byte slice representing SPA_TYPE_Bytes.
|
||||
Bytes = []byte
|
||||
|
||||
// A Fd is a signed integer value representing SPA_TYPE_Fd.
|
||||
Fd Long
|
||||
)
|
||||
|
||||
const (
|
||||
@ -49,6 +52,9 @@ const (
|
||||
SizeInt Word = 4
|
||||
// SizeLong is the fixed, unpadded size of a [SPA_TYPE_Long] value.
|
||||
SizeLong Word = 8
|
||||
|
||||
// SizeFd is the fixed, unpadded size of a [SPA_TYPE_Fd] value.
|
||||
SizeFd = SizeLong
|
||||
)
|
||||
|
||||
/* Basic types */
|
||||
@ -176,6 +182,15 @@ func marshalValueAppend(data []byte, v reflect.Value) ([]byte, error) {
|
||||
|
||||
// marshalValueAppendRaw implements [MarshalAppend] on [reflect.Value] without the size prefix.
|
||||
func marshalValueAppendRaw(data []byte, v reflect.Value) ([]byte, error) {
|
||||
if v.CanInterface() {
|
||||
switch c := v.Interface().(type) {
|
||||
case Fd:
|
||||
data = binary.NativeEndian.AppendUint32(data, SPA_TYPE_Fd)
|
||||
data = binary.NativeEndian.AppendUint64(data, uint64(c))
|
||||
return data, nil
|
||||
}
|
||||
}
|
||||
|
||||
switch v.Kind() {
|
||||
case reflect.Uint32:
|
||||
data = binary.NativeEndian.AppendUint32(data, SPA_TYPE_Id)
|
||||
@ -312,6 +327,16 @@ func unmarshalValue(data []byte, v reflect.Value, wireSizeP *Word) error {
|
||||
*wireSizeP, err = u.UnmarshalPOD(data)
|
||||
return err
|
||||
}
|
||||
|
||||
switch v.Interface().(type) {
|
||||
case Fd:
|
||||
*wireSizeP = SizeFd
|
||||
if err := unmarshalCheckTypeBounds(&data, SPA_TYPE_Fd, wireSizeP); err != nil {
|
||||
return err
|
||||
}
|
||||
v.SetInt(int64(binary.NativeEndian.Uint64(data)))
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
switch v.Kind() {
|
||||
|
||||
69
internal/pipewire/securitycontext.go
Normal file
69
internal/pipewire/securitycontext.go
Normal file
@ -0,0 +1,69 @@
|
||||
package pipewire
|
||||
|
||||
/* pipewire/extensions/security-context.h */
|
||||
|
||||
const (
|
||||
PW_TYPE_INTERFACE_SecurityContext = PW_TYPE_INFO_INTERFACE_BASE + "SecurityContext"
|
||||
PW_SECURITY_CONTEXT_PERM_MASK = PW_PERM_RWX
|
||||
PW_VERSION_SECURITY_CONTEXT = 3
|
||||
|
||||
PW_EXTENSION_MODULE_SECURITY_CONTEXT = PIPEWIRE_MODULE_PREFIX + "module-security-context"
|
||||
)
|
||||
|
||||
const (
|
||||
PW_SECURITY_CONTEXT_EVENT_NUM = iota
|
||||
|
||||
PW_VERSION_SECURITY_CONTEXT_EVENTS = 0
|
||||
)
|
||||
|
||||
const (
|
||||
PW_SECURITY_CONTEXT_METHOD_ADD_LISTENER = iota
|
||||
PW_SECURITY_CONTEXT_METHOD_CREATE
|
||||
PW_SECURITY_CONTEXT_METHOD_NUM
|
||||
|
||||
PW_VERSION_SECURITY_CONTEXT_METHODS = 0
|
||||
)
|
||||
|
||||
// SecurityContextCreate is sent to create a new security context.
|
||||
//
|
||||
// Creates a new security context with a socket listening FD.
|
||||
// PipeWire will accept new client connections on listen_fd.
|
||||
//
|
||||
// listen_fd must be ready to accept new connections when this
|
||||
// request is sent by the client. In other words, the client must
|
||||
// call bind(2) and listen(2) before sending the FD.
|
||||
//
|
||||
// close_fd is a FD closed by the client when PipeWire should stop
|
||||
// accepting new connections on listen_fd.
|
||||
//
|
||||
// PipeWire must continue to accept connections on listen_fd when
|
||||
// the client which created the security context disconnects.
|
||||
//
|
||||
// After sending this request, closing listen_fd and close_fd
|
||||
// remains the only valid operation on them.
|
||||
type SecurityContextCreate struct {
|
||||
// The offset in the SCM_RIGHTS msg_control message to
|
||||
// the fd to listen on for new connections.
|
||||
ListenFd Fd
|
||||
// The offset in the SCM_RIGHTS msg_control message to
|
||||
// the fd used to stop listening.
|
||||
CloseFd Fd
|
||||
|
||||
// Extra properties. These will be copied on the client
|
||||
// that connects through this context.
|
||||
Properties *SPADict `json:"props"`
|
||||
}
|
||||
|
||||
// Size satisfies [KnownSize] with a value computed at runtime.
|
||||
func (c *SecurityContextCreate) Size() Word {
|
||||
return SizePrefix +
|
||||
Size(SizeFd) +
|
||||
Size(SizeFd) +
|
||||
c.Properties.Size()
|
||||
}
|
||||
|
||||
// MarshalBinary satisfies [encoding.BinaryMarshaler] via [Marshal].
|
||||
func (c *SecurityContextCreate) MarshalBinary() ([]byte, error) { return Marshal(c) }
|
||||
|
||||
// UnmarshalBinary satisfies [encoding.BinaryUnmarshaler] via [Unmarshal].
|
||||
func (c *SecurityContextCreate) UnmarshalBinary(data []byte) error { return Unmarshal(data, c) }
|
||||
21
internal/pipewire/securitycontext_test.go
Normal file
21
internal/pipewire/securitycontext_test.go
Normal file
@ -0,0 +1,21 @@
|
||||
package pipewire_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"hakurei.app/internal/pipewire"
|
||||
)
|
||||
|
||||
func TestSecurityContextCreate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
encodingTestCases[pipewire.SecurityContextCreate, *pipewire.SecurityContextCreate]{
|
||||
{"sample", samplePWContainer[6][0][1], pipewire.SecurityContextCreate{
|
||||
ListenFd: 1 /* 21: duplicated from listen_fd */, CloseFd: 0, /* 20: duplicated from close_fd */
|
||||
Properties: &pipewire.SPADict{
|
||||
{Key: "pipewire.sec.engine", Value: "org.flatpak"},
|
||||
{Key: "pipewire.access", Value: "restricted"},
|
||||
},
|
||||
}, nil},
|
||||
}.run(t)
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user