aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ancillary-data.zig65
-rw-r--r--src/types.zig4
-rw-r--r--src/wl/display.zig9
3 files changed, 77 insertions, 1 deletions
diff --git a/src/ancillary-data.zig b/src/ancillary-data.zig
new file mode 100644
index 0000000..0754720
--- /dev/null
+++ b/src/ancillary-data.zig
@@ -0,0 +1,65 @@
+const std = @import("std");
+
+const ControlMessage = extern struct {
+ const Level = enum(u32) {
+ socket = std.posix.SOL.SOCKET,
+ };
+
+ // WARNING: this kind enum might be wrong for non-linux posix systems.
+ const Kind = enum(u32) {
+ rights = 1,
+ credentials = 2,
+ };
+
+ const Header = extern struct {
+ length: usize,
+ level: Level,
+ kind: Kind,
+ };
+
+ header: Header,
+ payload: union {
+ fd: [255]std.posix.fd_t,
+ },
+
+ pub fn alignment(length: usize) usize {
+ return (length + @sizeOf(usize) - 1) & ~(@sizeOf(usize) - 1);
+ }
+
+ pub fn space(self: @This()) usize {
+ return self.alignment(self.length) + self.alignment(@sizeOf(Header));
+ }
+
+ pub fn from_fds(fds: []std.posix.fd_t) @This() {
+ var self: @This() = .{
+ };
+
+ self.level = .socket;
+ self.kind = .rights;
+ self.length = self.alignment(@sizeOf(Header)) + (fds.len * @sizeOf(std.posix.fd_t));
+
+ @memcpy(self.payload, fds);
+ }
+};
+
+pub fn send_fds(socket: std.posix.socket_t, fds: []std.posix.fd_t) !void {
+ var iobuf: [1]u8 = std.mem.zeroes([1]u8);
+
+ const io = std.posix.iovec {
+ .base = &iobuf,
+ .len = iobuf.len,
+ };
+
+ var cmsg: ControlMessage = .from_fds(fds);
+
+ const msghdr = std.posix.msghdr_const {
+ .name = null,
+ .namelen = 0,
+ .iov = &io,
+ .iolen = 1,
+ .control = &cmsg,
+ .controllen = cmsg.control_length(),
+ };
+
+ _ = try std.posix.sendmsg(socket, &msghdr, 0);
+}
diff --git a/src/types.zig b/src/types.zig
index 2849af1..023f319 100644
--- a/src/types.zig
+++ b/src/types.zig
@@ -1,6 +1,8 @@
const std = @import("std");
-pub const Fd = struct { fd: std.posix.fd_t };
+pub const Fd = struct {
+ fd: std.posix.fd_t
+};
pub const Fixed = struct {
n: u24,
diff --git a/src/wl/display.zig b/src/wl/display.zig
index db5ed3c..ed4a94f 100644
--- a/src/wl/display.zig
+++ b/src/wl/display.zig
@@ -1,6 +1,7 @@
const std = @import("std");
const wayland = @import("../root.zig");
const wl = wayland.wl;
+const ancillary_data = @import("../ancillary-data.zig");
const log = std.log.scoped(.display);
@@ -85,6 +86,7 @@ pub fn request(self: *Self, object: anytype, args: @TypeOf(object.*).Request) !v
const id: u32 = @truncate(object.handle);
var size: u32 = 8;
+ comptime var fds: []std.posix.fd_t = &.{};
inline for (data) |value| {
switch (@TypeOf(value)) {
@@ -94,6 +96,7 @@ pub fn request(self: *Self, object: anytype, args: @TypeOf(object.*).Request) !v
const padding_size: usize = padding_len(u8, value.len + 1);
size += @as(u32, @intCast(@sizeOf(u32) + (value.len + 1) + padding_size));
},
+ wayland.types.Fd => |fd| fds = fds ++ .{ fd },
else => |t| switch (@typeInfo(t)) {
.pointer => |ptr| if (ptr.size == .slice) {
const padding_size: usize = padding_len(ptr.child, value.len);
@@ -119,6 +122,7 @@ pub fn request(self: *Self, object: anytype, args: @TypeOf(object.*).Request) !v
_ = try self.stream.writeAll(std.mem.asBytes(&@as(u8, 0)));
}
},
+ wayland.types.Fd => {},
else => |t| switch (@typeInfo(t)) {
.pointer => |ptr| if (ptr.size == .slice) {
const padding_size: usize = @mod(@as(usize, @bitCast(-@as(isize, @intCast(value.len * @sizeOf(ptr.child))))), 4);
@@ -132,6 +136,11 @@ pub fn request(self: *Self, object: anytype, args: @TypeOf(object.*).Request) !v
},
}
}
+
+ if (fds.len > 0) {
+ try ancillary_data.send_fds(self.stream.handle, fds);
+ }
+
return;
}
}