feat: transparently send fds
parent
ea4a75cc76
commit
7a9e12abf8
|
@ -196,41 +196,16 @@ pub fn main() !void {
|
||||||
|
|
||||||
const wl_shm_pool_id = id_pool.create();
|
const wl_shm_pool_id = id_pool.create();
|
||||||
{
|
{
|
||||||
var buffer: [10]u32 = undefined;
|
std.debug.print("framebuffer_fd: {}\n", .{framebuffer_fd});
|
||||||
const message = try wayland.serialize(
|
try conn.send(
|
||||||
wayland.core.Shm.Request,
|
wayland.core.Shm.Request,
|
||||||
&buffer,
|
|
||||||
shm_id,
|
shm_id,
|
||||||
.{ .create_pool = .{
|
.{ .create_pool = .{
|
||||||
.new_id = wl_shm_pool_id,
|
.new_id = wl_shm_pool_id,
|
||||||
|
.fd = @enumFromInt(framebuffer_fd),
|
||||||
.size = framebuffer_file_len,
|
.size = framebuffer_file_len,
|
||||||
} },
|
} },
|
||||||
);
|
);
|
||||||
// Send the file descriptor through a control message
|
|
||||||
const message_bytes = std.mem.sliceAsBytes(message);
|
|
||||||
const msg_iov = [_]std.os.iovec_const{
|
|
||||||
.{
|
|
||||||
.iov_base = message_bytes.ptr,
|
|
||||||
.iov_len = message_bytes.len,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const control_message = cmsg(std.os.fd_t){
|
|
||||||
.level = std.os.SOL.SOCKET,
|
|
||||||
.type = 0x01, // value of SCM_RIGHTS
|
|
||||||
.data = framebuffer_fd,
|
|
||||||
};
|
|
||||||
const socket_message = std.os.msghdr_const{
|
|
||||||
.name = null,
|
|
||||||
.namelen = 0,
|
|
||||||
.iov = &msg_iov,
|
|
||||||
.iovlen = msg_iov.len,
|
|
||||||
// .control = null,
|
|
||||||
// .controllen = 0,
|
|
||||||
.control = &control_message,
|
|
||||||
.controllen = @sizeOf(cmsg(std.os.fd_t)),
|
|
||||||
.flags = 0,
|
|
||||||
};
|
|
||||||
_ = try std.os.sendmsg(conn.socket.handle, &socket_message, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const wl_buffer_id = id_pool.create();
|
const wl_buffer_id = id_pool.create();
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
const types = @import("types.zig");
|
||||||
|
|
||||||
pub const Display = struct {
|
pub const Display = struct {
|
||||||
pub const Request = union(enum) {
|
pub const Request = union(enum) {
|
||||||
sync: struct {
|
sync: struct {
|
||||||
|
@ -90,7 +92,7 @@ pub const Shm = struct {
|
||||||
create_pool: struct {
|
create_pool: struct {
|
||||||
new_id: u32,
|
new_id: u32,
|
||||||
// file descriptors are sent through a control message
|
// file descriptors are sent through a control message
|
||||||
// fd: u32,
|
fd: types.Fd,
|
||||||
size: u32,
|
size: u32,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -306,7 +308,7 @@ pub const Keyboard = struct {
|
||||||
pub const Event = union(enum) {
|
pub const Event = union(enum) {
|
||||||
keymap: struct {
|
keymap: struct {
|
||||||
format: KeymapFormat,
|
format: KeymapFormat,
|
||||||
// fd: u32,
|
fd: types.Fd,
|
||||||
size: u32,
|
size: u32,
|
||||||
},
|
},
|
||||||
enter: struct {
|
enter: struct {
|
||||||
|
|
69
src/main.zig
69
src/main.zig
|
@ -3,6 +3,7 @@ const testing = std.testing;
|
||||||
pub const core = @import("./core.zig");
|
pub const core = @import("./core.zig");
|
||||||
pub const xdg = @import("./xdg.zig");
|
pub const xdg = @import("./xdg.zig");
|
||||||
pub const zxdg = @import("./zxdg.zig");
|
pub const zxdg = @import("./zxdg.zig");
|
||||||
|
pub const types = @import("./types.zig");
|
||||||
|
|
||||||
pub fn getDisplayPath(gpa: std.mem.Allocator) ![]u8 {
|
pub fn getDisplayPath(gpa: std.mem.Allocator) ![]u8 {
|
||||||
const xdg_runtime_dir_path = try std.process.getEnvVarOwned(gpa, "XDG_RUNTIME_DIR");
|
const xdg_runtime_dir_path = try std.process.getEnvVarOwned(gpa, "XDG_RUNTIME_DIR");
|
||||||
|
@ -112,6 +113,7 @@ pub fn deserializeArguments(comptime Signature: type, buffer: []const u32) !Sign
|
||||||
var result: Signature = undefined;
|
var result: Signature = undefined;
|
||||||
var pos: usize = 0;
|
var pos: usize = 0;
|
||||||
inline for (std.meta.fields(Signature)) |field| {
|
inline for (std.meta.fields(Signature)) |field| {
|
||||||
|
if (field.type == types.Fd) continue; // Must be handled
|
||||||
switch (@typeInfo(field.type)) {
|
switch (@typeInfo(field.type)) {
|
||||||
.Int => |int_info| switch (int_info.signedness) {
|
.Int => |int_info| switch (int_info.signedness) {
|
||||||
.signed => @field(result, field.name) = try readInt(buffer, &pos),
|
.signed => @field(result, field.name) = try readInt(buffer, &pos),
|
||||||
|
@ -169,11 +171,36 @@ pub fn calculateSerializedWordLen(comptime Signature: type, message: Signature)
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn countFds(comptime Signature: type) usize {
|
||||||
|
if (Signature == void) return 0;
|
||||||
|
var count: usize = 0;
|
||||||
|
inline for (std.meta.fields(Signature)) |field| {
|
||||||
|
if (field.type == types.Fd) {
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn extractFds(comptime Signature: type, message: *const Signature) [countFds(Signature)]*const types.Fd {
|
||||||
|
if (Signature == void) return [_]*const types.Fd{};
|
||||||
|
var fds: [countFds(Signature)]*const types.Fd = undefined;
|
||||||
|
var i: usize = 0;
|
||||||
|
inline for (std.meta.fields(Signature)) |field| {
|
||||||
|
if (field.type == types.Fd) {
|
||||||
|
fds[i] = &@field(message, field.name);
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fds;
|
||||||
|
}
|
||||||
|
|
||||||
/// Message must live until the iovec array is written.
|
/// Message must live until the iovec array is written.
|
||||||
pub fn serializeArguments(comptime Signature: type, buffer: []u32, message: Signature) ![]u32 {
|
pub fn serializeArguments(comptime Signature: type, buffer: []u32, message: Signature) ![]u32 {
|
||||||
if (Signature == void) return buffer[0..0];
|
if (Signature == void) return buffer[0..0];
|
||||||
var pos: usize = 0;
|
var pos: usize = 0;
|
||||||
inline for (std.meta.fields(Signature)) |field| {
|
inline for (std.meta.fields(Signature)) |field| {
|
||||||
|
if (field.type == types.Fd) continue;
|
||||||
switch (@typeInfo(field.type)) {
|
switch (@typeInfo(field.type)) {
|
||||||
.Int => {
|
.Int => {
|
||||||
if (pos >= buffer.len) return error.OutOfMemory;
|
if (pos >= buffer.len) return error.OutOfMemory;
|
||||||
|
@ -416,6 +443,17 @@ pub fn registerGlobals(alloc: std.mem.Allocator, id_pool: *IdPool, socket: std.n
|
||||||
return ids;
|
return ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn cmsg(comptime T: type) type {
|
||||||
|
const padding_size = (@sizeOf(T) + @sizeOf(c_long) - 1) & ~(@as(usize, @sizeOf(c_long)) - 1);
|
||||||
|
return extern struct {
|
||||||
|
len: c_ulong = @sizeOf(@This()) - padding_size,
|
||||||
|
level: c_int,
|
||||||
|
type: c_int,
|
||||||
|
data: T,
|
||||||
|
_padding: [padding_size]u8 align(1) = [_]u8{0} ** padding_size,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub const Conn = struct {
|
pub const Conn = struct {
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
send_buffer: []u32,
|
send_buffer: []u32,
|
||||||
|
@ -455,11 +493,40 @@ pub const Conn = struct {
|
||||||
|
|
||||||
break msg;
|
break msg;
|
||||||
};
|
};
|
||||||
try conn.socket.writeAll(std.mem.sliceAsBytes(msg));
|
const msg_bytes = std.mem.sliceAsBytes(msg);
|
||||||
|
const msg_iov = [_]std.os.iovec_const{
|
||||||
|
.{
|
||||||
|
.iov_base = msg_bytes.ptr,
|
||||||
|
.iov_len = msg_bytes.len,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const fds = switch (message) {
|
||||||
|
inline else => |*payload| extractFds(@TypeOf(payload.*), payload),
|
||||||
|
};
|
||||||
|
var ctrl_msgs: [fds.len]cmsg(std.os.fd_t) = undefined;
|
||||||
|
for (fds, 0..) |fdp, i| {
|
||||||
|
std.debug.print("fd {}: {}\n", .{ i, fdp.* });
|
||||||
|
ctrl_msgs[i] = .{
|
||||||
|
.level = std.os.SOL.SOCKET,
|
||||||
|
.type = 0x01,
|
||||||
|
.data = @intFromEnum(fdp.*),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const socket_msg = std.os.msghdr_const{
|
||||||
|
.name = null,
|
||||||
|
.namelen = 0,
|
||||||
|
.iov = &msg_iov,
|
||||||
|
.iovlen = msg_iov.len,
|
||||||
|
.control = &ctrl_msgs,
|
||||||
|
.controllen = @intCast(@sizeOf(cmsg(std.os.fd_t)) * ctrl_msgs.len),
|
||||||
|
.flags = 0,
|
||||||
|
};
|
||||||
|
_ = try std.os.sendmsg(conn.socket.handle, &socket_msg, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const Message = struct { Header, []const u32 };
|
pub const Message = struct { Header, []const u32 };
|
||||||
pub fn recv(conn: *Conn) !Message {
|
pub fn recv(conn: *Conn) !Message {
|
||||||
|
// TODO: recvmesg and read fds
|
||||||
var header: Header = undefined;
|
var header: Header = undefined;
|
||||||
const header_bytes_read = try conn.socket.readAll(std.mem.asBytes(&header));
|
const header_bytes_read = try conn.socket.readAll(std.mem.asBytes(&header));
|
||||||
if (header_bytes_read < @sizeOf(Header)) {
|
if (header_bytes_read < @sizeOf(Header)) {
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
const std = @import("std");
|
||||||
|
pub const Fd = enum(std.os.fd_t) { _ };
|
Loading…
Reference in New Issue