merge: client PID
3 files · +43 -0
M internal/e2e/feasibility_test.go +29 -0
| @@ -2,6 +2,7 @@ package e2e_test | |||
| 2 | 2 | ||
| 3 | 3 | import ( | |
| 4 | 4 | "context" | |
| 5 | + | "os" | |
| 5 | 6 | "os/exec" | |
| 6 | 7 | "path/filepath" | |
| 7 | 8 | "strings" | |
| @@ -292,3 +293,31 @@ func (*surfaceHandler) SetBufferScale(*wayland.Surface, int32) | |||
| 292 | 293 | func (*surfaceHandler) DamageBuffer(*wayland.Surface, int32, int32, int32, int32) {} | |
| 293 | 294 | func (*surfaceHandler) Offset(*wayland.Surface, int32, int32) {} | |
| 294 | 295 | func (*surfaceHandler) GetRelease(*wayland.Surface, uint32) {} | |
| 296 | + | ||
| 297 | + | // The client PID comes from the socket credentials; in-process clients share ours. | |
| 298 | + | func TestClientPID(t *testing.T) { | |
| 299 | + | captured := make(chan *server.Resource, 1) | |
| 300 | + | socket, d, _ := startServer(t, captured) | |
| 301 | + | c, err := wlturbo.Connect(socket) | |
| 302 | + | if err != nil { | |
| 303 | + | t.Fatal(err) | |
| 304 | + | } | |
| 305 | + | defer c.Close() | |
| 306 | + | must(t, c.Roundtrip()) | |
| 307 | + | g, ok := c.Registry().FindGlobal("wl_compositor") | |
| 308 | + | if !ok { | |
| 309 | + | t.Fatal("wl_compositor not advertised") | |
| 310 | + | } | |
| 311 | + | comp, err := c.Registry().BindID(g.Name, g.Interface, 1) | |
| 312 | + | must(t, err) | |
| 313 | + | must(t, c.SendRequest(comp, uint16(wayland.CompositorRequestCreateSurface), c.AllocateID())) | |
| 314 | + | must(t, c.Roundtrip()) | |
| 315 | + | r := receive(t, captured) | |
| 316 | + | pid := make(chan int, 1) | |
| 317 | + | if !d.Do(func() { pid <- r.Client().PID() }) { | |
| 318 | + | t.Fatal("display stopped") | |
| 319 | + | } | |
| 320 | + | if got := <-pid; got != os.Getpid() { | |
| 321 | + | t.Fatalf("pid %d, want %d", got, os.Getpid()) | |
| 322 | + | } | |
| 323 | + | } | |
| @@ -2,6 +2,7 @@ package e2e_test | |||||
| 2 | 2 | ||||
| 3 | import ( | 3 | import ( | ||
| 4 | "context" | 4 | "context" | ||
| 5 | + | "os" | |||
| 5 | "os/exec" | 6 | "os/exec" | ||
| 6 | "path/filepath" | 7 | "path/filepath" | ||
| 7 | "strings" | 8 | "strings" | ||
| @@ -292,3 +293,31 @@ func (*surfaceHandler) SetBufferScale(*wayland.Surface, int32) | |||||
| 292 | func (*surfaceHandler) DamageBuffer(*wayland.Surface, int32, int32, int32, int32) {} | 293 | func (*surfaceHandler) DamageBuffer(*wayland.Surface, int32, int32, int32, int32) {} | ||
| 293 | func (*surfaceHandler) Offset(*wayland.Surface, int32, int32) {} | 294 | func (*surfaceHandler) Offset(*wayland.Surface, int32, int32) {} | ||
| 294 | func (*surfaceHandler) GetRelease(*wayland.Surface, uint32) {} | 295 | func (*surfaceHandler) GetRelease(*wayland.Surface, uint32) {} | ||
| 296 | + | ||||
| 297 | + | // The client PID comes from the socket credentials; in-process clients share ours. | |||
| 298 | + | func TestClientPID(t *testing.T) { | |||
| 299 | + | captured := make(chan *server.Resource, 1) | |||
| 300 | + | socket, d, _ := startServer(t, captured) | |||
| 301 | + | c, err := wlturbo.Connect(socket) | |||
| 302 | + | if err != nil { | |||
| 303 | + | t.Fatal(err) | |||
| 304 | + | } | |||
| 305 | + | defer c.Close() | |||
| 306 | + | must(t, c.Roundtrip()) | |||
| 307 | + | g, ok := c.Registry().FindGlobal("wl_compositor") | |||
| 308 | + | if !ok { | |||
| 309 | + | t.Fatal("wl_compositor not advertised") | |||
| 310 | + | } | |||
| 311 | + | comp, err := c.Registry().BindID(g.Name, g.Interface, 1) | |||
| 312 | + | must(t, err) | |||
| 313 | + | must(t, c.SendRequest(comp, uint16(wayland.CompositorRequestCreateSurface), c.AllocateID())) | |||
| 314 | + | must(t, c.Roundtrip()) | |||
| 315 | + | r := receive(t, captured) | |||
| 316 | + | pid := make(chan int, 1) | |||
| 317 | + | if !d.Do(func() { pid <- r.Client().PID() }) { | |||
| 318 | + | t.Fatal("display stopped") | |||
| 319 | + | } | |||
| 320 | + | if got := <-pid; got != os.Getpid() { | |||
| 321 | + | t.Fatalf("pid %d, want %d", got, os.Getpid()) | |||
| 322 | + | } | |||
| 323 | + | } | |||
M server/display.go +12 -0
| @@ -181,6 +181,18 @@ func (d *Display) Stopped() <-chan struct{} { return d.stopped } | |||
| 181 | 181 | // LiveResources reports resources not yet destroyed. Display goroutine only. | |
| 182 | 182 | func LiveResources() int { return len(live.resources) } | |
| 183 | 183 | ||
| 184 | + | // PID is the process ID of the client, read from the socket credentials | |
| 185 | + | // (SO_PEERCRED) when it connected. Zero for an invalid client. | |
| 186 | + | // Display goroutine only. | |
| 187 | + | func (c Client) PID() int { | |
| 188 | + | if c.c == 0 { | |
| 189 | + | return 0 | |
| 190 | + | } | |
| 191 | + | var pid, uid, gid int32 | |
| 192 | + | wlClientGetCredentials(c.c, unsafe.Pointer(&pid), unsafe.Pointer(&uid), unsafe.Pointer(&gid)) | |
| 193 | + | return int(pid) | |
| 194 | + | } | |
| 195 | + | ||
| 184 | 196 | func (c Client) CreateResource(iface *Interface, version int32, id uint32, h Handler) (*Resource, error) { | |
| 185 | 197 | rc := wlResourceCreate(c.c, iface.c, version, id) | |
| 186 | 198 | if rc == 0 { | |
| @@ -181,6 +181,18 @@ func (d *Display) Stopped() <-chan struct{} { return d.stopped } | |||||
| 181 | // LiveResources reports resources not yet destroyed. Display goroutine only. | 181 | // LiveResources reports resources not yet destroyed. Display goroutine only. | ||
| 182 | func LiveResources() int { return len(live.resources) } | 182 | func LiveResources() int { return len(live.resources) } | ||
| 183 | 183 | ||||
| 184 | + | // PID is the process ID of the client, read from the socket credentials | |||
| 185 | + | // (SO_PEERCRED) when it connected. Zero for an invalid client. | |||
| 186 | + | // Display goroutine only. | |||
| 187 | + | func (c Client) PID() int { | |||
| 188 | + | if c.c == 0 { | |||
| 189 | + | return 0 | |||
| 190 | + | } | |||
| 191 | + | var pid, uid, gid int32 | |||
| 192 | + | wlClientGetCredentials(c.c, unsafe.Pointer(&pid), unsafe.Pointer(&uid), unsafe.Pointer(&gid)) | |||
| 193 | + | return int(pid) | |||
| 194 | + | } | |||
| 195 | + | ||||
| 184 | func (c Client) CreateResource(iface *Interface, version int32, id uint32, h Handler) (*Resource, error) { | 196 | func (c Client) CreateResource(iface *Interface, version int32, id uint32, h Handler) (*Resource, error) { | ||
| 185 | rc := wlResourceCreate(c.c, iface.c, version, id) | 197 | rc := wlResourceCreate(c.c, iface.c, version, id) | ||
| 186 | if rc == 0 { | 198 | if rc == 0 { | ||
M server/lib.go +2 -0
| @@ -29,6 +29,7 @@ var ( | |||
| 29 | 29 | wlResourceGetID func(resource uintptr) uint32 | |
| 30 | 30 | wlResourceGetClient func(resource uintptr) uintptr | |
| 31 | 31 | wlResourceGetVersion func(resource uintptr) int32 | |
| 32 | + | wlClientGetCredentials func(client uintptr, pid, uid, gid unsafe.Pointer) | |
| 32 | 33 | ) | |
| 33 | 34 | ||
| 34 | 35 | var ( | |
| @@ -75,6 +76,7 @@ func load() error { | |||
| 75 | 76 | reg(&wlResourceGetID, "wl_resource_get_id") | |
| 76 | 77 | reg(&wlResourceGetClient, "wl_resource_get_client") | |
| 77 | 78 | reg(&wlResourceGetVersion, "wl_resource_get_version") | |
| 79 | + | reg(&wlClientGetCredentials, "wl_client_get_credentials") | |
| 78 | 80 | ||
| 79 | 81 | cbDispatcher = purego.NewCallback(dispatch) | |
| 80 | 82 | cbDestroy = purego.NewCallback(destroyed) | |
| @@ -29,6 +29,7 @@ var ( | |||||
| 29 | wlResourceGetID func(resource uintptr) uint32 | 29 | wlResourceGetID func(resource uintptr) uint32 | ||
| 30 | wlResourceGetClient func(resource uintptr) uintptr | 30 | wlResourceGetClient func(resource uintptr) uintptr | ||
| 31 | wlResourceGetVersion func(resource uintptr) int32 | 31 | wlResourceGetVersion func(resource uintptr) int32 | ||
| 32 | + | wlClientGetCredentials func(client uintptr, pid, uid, gid unsafe.Pointer) | |||
| 32 | ) | 33 | ) | ||
| 33 | 34 | ||||
| 34 | var ( | 35 | var ( | ||
| @@ -75,6 +76,7 @@ func load() error { | |||||
| 75 | reg(&wlResourceGetID, "wl_resource_get_id") | 76 | reg(&wlResourceGetID, "wl_resource_get_id") | ||
| 76 | reg(&wlResourceGetClient, "wl_resource_get_client") | 77 | reg(&wlResourceGetClient, "wl_resource_get_client") | ||
| 77 | reg(&wlResourceGetVersion, "wl_resource_get_version") | 78 | reg(&wlResourceGetVersion, "wl_resource_get_version") | ||
| 79 | + | reg(&wlClientGetCredentials, "wl_client_get_credentials") | |||
| 78 | 80 | ||||
| 79 | cbDispatcher = purego.NewCallback(dispatch) | 81 | cbDispatcher = purego.NewCallback(dispatch) | ||
| 80 | cbDestroy = purego.NewCallback(destroyed) | 82 | cbDestroy = purego.NewCallback(destroyed) | ||