Skip to documentation
SLOP

tiny.sys.x11.connection

Reference tiny.sys x11 connection

Defined in x11.

API (30)

Actions

Public operations.

Types and contracts

Public types and contracts.

Values and defaults

Public values and defaults.

No direct callersNo direct callsx11connection
Static calls · unresolved targets: unknown · external targets: unknown.

Source

Called byCallsNo direct callstest sourcelib.sys.src.x11.connectiontest: connection capacity derives exa...test sourcelib.sys.src.x11.connectiontest: connection performs the setup h...test sourcelib.sys.src.x11.connectiontest: connection storage acquires all...test sourcelib.sys.src.x11.connectiontest: reply storage recovers after ma...test sourcelib.sys.src.x11.connectiontest: reply wait rejects before consu...test sourcelib.sys.src.x11.connectiontest: retained messages preserve FIFO...x11.Capacityderive
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsx11.ConnectioninternAtomtest sourcelib.sys.src.x11.connectiontest: reply wait rejects before consu...x11.Requestresetx11.ConnectionbeginRequest
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callersnet.Streamcloseprivate sourcelib.sys.src.x11.connection.RetainedMessagesdeinitx11.Connectionclose
Static calls · unresolved targets: 0 · external targets: 1.
Called byCallstest sourcelib.sys.src.x11.connectiontest: connection performs the setup h...envgetx11.ConnectionconnectTox11.displayparsex11.Connectionconnect
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsx11.Connectionconnectx11.authloadCookieprivate sourcelib.sys.src.x11.connection.Storagedeinitprivate sourcelib.sys.src.x11.connection.Storageinitprivate sourcelib.sys.src.x11.connection.StoragereleaseInitializationScratchprivate sourcelib.sys.src.x11.connectionconnectSocket+5 morex11.ConnectionconnectTo
Static calls · unresolved targets: 1 · external targets: 2.
Called byCallsNo direct callersx11.ConnectionbeginRequestx11.ConnectionsendRequestx11.ConnectionwaitReplyx11.protocolinternAtomx11.ConnectioninternAtom
Static calls · unresolved targets: 0 · external targets: 1.
Called byCallsNo direct callersx11.RequestbyteCapacityx11.ConnectionmaxRequestBytes
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallstest sourcelib.sys.src.x11.connectiontest: reply wait rejects before consu...private sourcelib.sys.src.x11.connection.ConnectionfillHeadprivate sourcelib.sys.src.x11.connection.RetainedMessagespopx11.ConnectionnextMessage
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallstest sourcelib.sys.src.x11.connectiontest: reply wait rejects before consu...private sourcelib.sys.src.x11.connection.RetainedMessagesappendx11.ConnectionretainMessage
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsx11.ConnectioninternAtomnet.StreamwriteAllx11.Requestbytesx11.ConnectionsendRequest
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallstest sourcelib.sys.src.x11.connectiontest: reply storage recovers after ma...test sourcelib.sys.src.x11.connectiontest: reply wait rejects before consu...private sourcelib.sys.src.x11.connection.RetainedMessagesstatusx11.RequestcapacityRejectionCountx11.ConnectionstorageStatus
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callersnetpollReadablex11.ConnectionwaitReadable
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsx11.ConnectioninternAtomtest sourcelib.sys.src.x11.connectiontest: reply storage recovers after ma...test sourcelib.sys.src.x11.connectiontest: reply wait rejects before consu...private sourcelib.sys.src.x11.connection.ConnectionfillHeadprivate sourcelib.sys.src.x11.connection.RetainedMessagesappendprivate sourcelib.sys.src.x11.connectiondiscardExactprivate sourcelib.sys.src.x11.connectionreadExactx11.ConnectionwaitReply
Static calls · unresolved targets: 0 · external targets: 0.

Source: lib/sys/src/x11/connection.zig

zig
const std = @import("std");const sys = @import("../root.zig");const auth = @import("auth.zig");const display = @import("display.zig");const protocol = @import("protocol.zig");const env = sys.env;const net = sys.net;pub const Message = [protocol.message_length]u8;const message_bytes = @sizeOf(Message);pub const minimum_reply_byte_count = 0;pub const default_reply_byte_count = 1 << 20;pub const Limits = struct {    retained_message_count: usize = 256,    request_byte_count: usize = protocol.maximum_request_byte_count,    reply_byte_count: usize = default_reply_byte_count,};pub const CapacityError = error{    RetainedMessagesEmpty,    RequestStorageTooSmall,    RequestStorageTooLarge,    RequestStorageUnaligned,    ReplyStorageTooSmall,    ReplyStorageTooLarge,    ReplyStorageUnaligned,    CapacityOverflow,};pub const Capacity = struct {    retained_message_count: usize,    retained_message_bytes: usize,    request_byte_count: usize,    reply_byte_count: usize,    initialization_scratch_byte_count: usize,    steady_requested_bytes: usize,    initialization_high_water_bytes: usize,    pub fn derive(limits: Limits) CapacityError!Capacity {        if (limits.retained_message_count == 0) return error.RetainedMessagesEmpty;        if (limits.request_byte_count < protocol.minimum_request_byte_count) {            return error.RequestStorageTooSmall;        }        if (limits.request_byte_count > protocol.maximum_request_byte_count) {            return error.RequestStorageTooLarge;        }        if (limits.request_byte_count % 4 != 0) return error.RequestStorageUnaligned;        if (@as(u64, @intCast(limits.reply_byte_count)) >            protocol.maximum_reply_extra_byte_count)        {            return error.ReplyStorageTooLarge;        }        if (limits.reply_byte_count % 4 != 0) return error.ReplyStorageUnaligned;        const retained_message_bytes = std.math.mul(            usize,            limits.retained_message_count,            message_bytes,        ) catch return error.CapacityOverflow;        const initialization_scratch_byte_count = @max(            auth.maximum_authority_file_byte_count,            protocol.maximum_setup_response_byte_count,        );        const retained_and_request_bytes = std.math.add(            usize,            retained_message_bytes,            limits.request_byte_count,        ) catch return error.CapacityOverflow;        const steady_requested_bytes = std.math.add(            usize,            retained_and_request_bytes,            limits.reply_byte_count,        ) catch return error.CapacityOverflow;        const initialization_high_water_bytes = std.math.add(            usize,            steady_requested_bytes,            initialization_scratch_byte_count,        ) catch return error.CapacityOverflow;        std.debug.assert(            retained_message_bytes / message_bytes == limits.retained_message_count,        );        return .{            .retained_message_count = limits.retained_message_count,            .retained_message_bytes = retained_message_bytes,            .request_byte_count = limits.request_byte_count,            .reply_byte_count = limits.reply_byte_count,            .initialization_scratch_byte_count = initialization_scratch_byte_count,            .steady_requested_bytes = steady_requested_bytes,            .initialization_high_water_bytes = initialization_high_water_bytes,        };    }};pub const Status = struct {    retained_message_capacity_rejection_count: u64 = 0,    request_capacity_rejection_count: u64 = 0,    reply_capacity_rejection_count: u64 = 0,};pub const RetainError = error{    RetainedMessageCapacityExceeded,};const RetainedMessages = struct {    allocator: std.mem.Allocator,    items: []Message,    head: usize = 0,    count: usize = 0,    rejection_count: u64 = 0,    fn init(        allocator: std.mem.Allocator,        capacity: Capacity,    ) std.mem.Allocator.Error!RetainedMessages {        std.debug.assert(capacity.retained_message_count > 0);        std.debug.assert(capacity.retained_message_bytes % message_bytes == 0);        std.debug.assert(            capacity.retained_message_bytes / message_bytes ==                capacity.retained_message_count,        );        return .{            .allocator = allocator,            .items = try allocator.alloc(Message, capacity.retained_message_count),        };    }    fn deinit(self: *RetainedMessages) void {        std.debug.assert(self.count <= self.items.len);        self.allocator.free(self.items);        self.* = undefined;    }    fn append(self: *RetainedMessages, message: Message) RetainError!void {        std.debug.assert(self.count <= self.items.len);        if (self.count == self.items.len) {            self.rejection_count +|= 1;            return error.RetainedMessageCapacityExceeded;        }        const index = (self.head + self.count) % self.items.len;        self.items[index] = message;        self.count += 1;    }    fn pop(self: *RetainedMessages) ?Message {        std.debug.assert(self.count <= self.items.len);        if (self.count == 0) return null;        const message = self.items[self.head];        self.head = (self.head + 1) % self.items.len;        self.count -= 1;        return message;    }    fn status(self: *const RetainedMessages) Status {        std.debug.assert(self.count <= self.items.len);        return .{            .retained_message_capacity_rejection_count = self.rejection_count,        };    }};const Storage = struct {    allocator: std.mem.Allocator,    retained_messages: RetainedMessages,    request: []u8,    reply: []u8,    initialization_scratch: []u8,    fn init(        allocator: std.mem.Allocator,        capacity: Capacity,    ) std.mem.Allocator.Error!Storage {        var retained_messages = try RetainedMessages.init(allocator, capacity);        errdefer retained_messages.deinit();        const request = try allocator.alloc(u8, capacity.request_byte_count);        errdefer allocator.free(request);        const reply = try allocator.alloc(u8, capacity.reply_byte_count);        errdefer allocator.free(reply);        return .{            .allocator = allocator,            .retained_messages = retained_messages,            .request = request,            .reply = reply,            .initialization_scratch = try allocator.alloc(                u8,                capacity.initialization_scratch_byte_count,            ),        };    }    fn deinit(self: *Storage) void {        self.retained_messages.deinit();        self.allocator.free(self.request);        self.allocator.free(self.reply);        if (self.initialization_scratch.len != 0) {            self.allocator.free(self.initialization_scratch);        }        self.* = undefined;    }    fn releaseInitializationScratch(self: *Storage) void {        std.debug.assert(self.initialization_scratch.len > 0);        self.allocator.free(self.initialization_scratch);        self.initialization_scratch = &.{};    }};pub const ConnectError = error{    MissingDisplay,    RemoteDisplayUnsupported,    InvalidDisplay,    ConnectionFailed,    AuthenticationFailed,    SetupFailed,    SetupTruncated,    NoUsableScreen,    NoUsableVisual,    OutOfMemory,};pub const IoError = error{    ConnectionLost,};pub const ReplyError = error{    ConnectionLost,    RequestFailed,    ReplyCapacityExceeded,    RetainedMessageCapacityExceeded,} || protocol.RequestError;pub const ReplyView = struct {    head: [protocol.message_length]u8,    extra: []const u8,    pub fn dataByte(self: *const ReplyView) u8 {        return self.head[1];    }    pub fn u32At(self: *const ReplyView, offset: usize) u32 {        return std.mem.readInt(u32, self.head[offset..][0..4], .little);    }    pub fn u16At(self: *const ReplyView, offset: usize) u16 {        return std.mem.readInt(u16, self.head[offset..][0..2], .little);    }};fn connectSocket(path: []const u8) !net.Stream {    if (net.Address.initUnixAbstract(path)) |abstract| {        if (net.connectStream(abstract)) |stream| return stream else |_| {}    } else |_| {}    const filesystem = try net.Address.initUnix(path);    return net.connectStream(filesystem);}pub const Connection = struct {    allocator: std.mem.Allocator,    target: display.Target,    stream: net.Stream,    setup: protocol.Setup,    screen: u32,    next_resource: u32 = 0,    retained_messages: RetainedMessages,    request_storage: []u8,    request_scratch: protocol.Request,    reply_storage: []u8,    receive_head: Message = undefined,    receive_head_count: usize = 0,    reply_capacity_rejection_count: u64 = 0,    pub fn connect(        allocator: std.mem.Allocator,        capacity: Capacity,    ) ConnectError!Connection {        const target = display.parse(env.get("DISPLAY")) catch |err| switch (err) {            error.MissingDisplay => return error.MissingDisplay,            error.RemoteDisplayUnsupported => return error.RemoteDisplayUnsupported,            error.InvalidDisplay => return error.InvalidDisplay,        };        return connectTo(allocator, target, capacity);    }    pub fn connectTo(        allocator: std.mem.Allocator,        target: display.Target,        capacity: Capacity,    ) ConnectError!Connection {        var storage = Storage.init(allocator, capacity) catch return error.OutOfMemory;        errdefer storage.deinit();        var path_buffer: [64]u8 = undefined;        const path = target.socketPath(&path_buffer) catch return error.InvalidDisplay;        var stream = connectSocket(path) catch return error.ConnectionFailed;        errdefer stream.close();        var setup_request_storage: [protocol.setup_request_byte_count]u8 = undefined;        var setup_request = protocol.Request.init(            &setup_request_storage,            setup_request_storage.len,        );        const cookie = auth.loadCookie(storage.initialization_scratch, target.display);        if (cookie) |found| {            protocol.setupRequest(&setup_request, auth.cookie_name, &found.data) catch unreachable;        } else {            protocol.setupRequest(&setup_request, "", "") catch unreachable;        }        stream.writeAll(setup_request.bytes()) catch return error.ConnectionFailed;        var prefix: [8]u8 = undefined;        readExact(stream, &prefix) catch return error.ConnectionFailed;        const status = prefix[0];        const body_units = std.mem.readInt(u16, prefix[6..8], .little);        const body_byte_count = @as(usize, body_units) * 4;        std.debug.assert(body_byte_count <= storage.initialization_scratch.len);        const body = storage.initialization_scratch[0..body_byte_count];        readExact(stream, body) catch return error.ConnectionFailed;        if (status == 0) return error.AuthenticationFailed;        if (status != 1) return error.SetupFailed;        const setup = protocol.parseSetup(body, target.screen) catch |err| switch (err) {            error.SetupFailed => return error.SetupFailed,            error.SetupTruncated => return error.SetupTruncated,            error.NoUsableScreen => return error.NoUsableScreen,            error.NoUsableVisual => return error.NoUsableVisual,        };        const server_request_bytes = @as(usize, setup.max_request_units) * 4;        if (server_request_bytes < protocol.minimum_request_byte_count) {            return error.SetupFailed;        }        const request_byte_count = @min(storage.request.len, server_request_bytes);        storage.releaseInitializationScratch();        return .{            .allocator = allocator,            .target = target,            .stream = stream,            .setup = setup,            .screen = target.screen,            .retained_messages = storage.retained_messages,            .request_storage = storage.request,            .request_scratch = protocol.Request.init(storage.request, request_byte_count),            .reply_storage = storage.reply,        };    }    pub fn close(self: *Connection) void {        self.retained_messages.deinit();        self.allocator.free(self.request_storage);        self.allocator.free(self.reply_storage);        self.stream.close();    }    pub fn generateId(self: *Connection) u32 {        const id = self.setup.resource_id_base | (self.next_resource & self.setup.resource_id_mask);        self.next_resource += 1;        return id;    }    pub fn maxRequestBytes(self: *const Connection) usize {        return self.request_scratch.byteCapacity();    }    pub fn beginRequest(self: *Connection) *protocol.Request {        self.request_scratch.reset();        return &self.request_scratch;    }    pub fn sendRequest(self: *Connection) IoError!void {        const bytes = self.request_scratch.bytes();        std.debug.assert(bytes.len >= 4);        std.debug.assert(bytes.len % 4 == 0);        self.stream.writeAll(bytes) catch return error.ConnectionLost;    }    pub fn nextMessage(self: *Connection) IoError!?Message {        if (self.retained_messages.pop()) |message| return message;        try self.fillHead(false);        if (self.receive_head_count < protocol.message_length) return null;        const head = self.receive_head;        self.receive_head_count = 0;        return head;    }    pub fn retainMessage(self: *Connection, message: Message) RetainError!void {        try self.retained_messages.append(message);    }    pub fn storageStatus(self: *const Connection) Status {        var status = self.retained_messages.status();        status.request_capacity_rejection_count =            self.request_scratch.capacityRejectionCount();        status.reply_capacity_rejection_count = self.reply_capacity_rejection_count;        return status;    }    pub fn waitReadable(self: *Connection, timeout_ms: i32) IoError!bool {        return net.pollReadable(self.stream.handle, timeout_ms) catch error.ConnectionLost;    }    pub fn waitReply(self: *Connection) ReplyError!ReplyView {        while (true) {            try self.fillHead(true);            const head = self.receive_head;            const code = head[0] & 0x7F;            if (code == 1) {                const extra_units = std.mem.readInt(u32, head[4..8], .little);                const extra_byte_count = @as(u64, extra_units) * 4;                self.receive_head_count = 0;                if (extra_byte_count > self.reply_storage.len) {                    self.reply_capacity_rejection_count +|= 1;                    discardExact(self.stream, extra_byte_count) catch                        return error.ConnectionLost;                    return error.ReplyCapacityExceeded;                }                const extra_len: usize = @intCast(extra_byte_count);                const extra = self.reply_storage[0..extra_len];                readExact(self.stream, extra) catch return error.ConnectionLost;                return .{ .head = head, .extra = extra };            }            if (code == 0) {                self.receive_head_count = 0;                return error.RequestFailed;            }            try self.retained_messages.append(head);            self.receive_head_count = 0;        }    }    fn fillHead(self: *Connection, blocking: bool) IoError!void {        std.debug.assert(self.receive_head_count <= self.receive_head.len);        while (self.receive_head_count < self.receive_head.len) {            if (!blocking) {                const readable = net.pollReadable(self.stream.handle, 0) catch                    return error.ConnectionLost;                if (!readable) return;            }            const count = self.stream.read(self.receive_head[self.receive_head_count..]) catch                return error.ConnectionLost;            if (count == 0) return error.ConnectionLost;            self.receive_head_count += count;        }    }    pub fn internAtom(self: *Connection, name: []const u8) ReplyError!u32 {        const request = self.beginRequest();        try protocol.internAtom(request, name);        try self.sendRequest();        const reply = try self.waitReply();        return reply.u32At(8);    }};fn readExact(stream: net.Stream, buffer: []u8) !void {    var filled: usize = 0;    while (filled < buffer.len) {        const count = try stream.read(buffer[filled..]);        if (count == 0) return error.ConnectionLost;        filled += count;    }}fn discardExact(stream: net.Stream, byte_count: u64) !void {    std.debug.assert(byte_count <= protocol.maximum_reply_extra_byte_count);    var scratch: [protocol.reply_discard_scratch_byte_count]u8 = undefined;    var remaining = byte_count;    while (remaining > 0) {        const count: usize = @intCast(@min(remaining, scratch.len));        try readExact(stream, scratch[0..count]);        remaining -= count;    }}test "connection capacity derives exact steady and initialization storage" {    const capacity = try Capacity.derive(.{});    try std.testing.expectEqual(@as(usize, 256), capacity.retained_message_count);    try std.testing.expectEqual(256 * message_bytes, capacity.retained_message_bytes);    try std.testing.expectEqual(        protocol.maximum_request_byte_count,        capacity.request_byte_count,    );    try std.testing.expectEqual(default_reply_byte_count, capacity.reply_byte_count);    try std.testing.expectEqual(        capacity.retained_message_bytes + capacity.request_byte_count + capacity.reply_byte_count,        capacity.steady_requested_bytes,    );    try std.testing.expectEqual(        @max(            auth.maximum_authority_file_byte_count,            protocol.maximum_setup_response_byte_count,        ),        capacity.initialization_scratch_byte_count,    );    try std.testing.expectEqual(        capacity.steady_requested_bytes + capacity.initialization_scratch_byte_count,        capacity.initialization_high_water_bytes,    );    try std.testing.expectError(error.RetainedMessagesEmpty, Capacity.derive(.{        .retained_message_count = 0,    }));    try std.testing.expectError(error.RequestStorageTooSmall, Capacity.derive(.{        .request_byte_count = protocol.minimum_request_byte_count - 4,    }));    try std.testing.expectError(error.RequestStorageTooLarge, Capacity.derive(.{        .request_byte_count = protocol.maximum_request_byte_count + 4,    }));    try std.testing.expectError(error.RequestStorageUnaligned, Capacity.derive(.{        .request_byte_count = protocol.minimum_request_byte_count + 1,    }));    try std.testing.expectEqual(        minimum_reply_byte_count,        (try Capacity.derive(.{ .reply_byte_count = minimum_reply_byte_count })).reply_byte_count,    );    try std.testing.expectError(error.ReplyStorageUnaligned, Capacity.derive(.{        .reply_byte_count = 5,    }));    if (@sizeOf(usize) > @sizeOf(u32)) {        try std.testing.expectError(error.ReplyStorageTooLarge, Capacity.derive(.{            .reply_byte_count = @as(usize, @intCast(protocol.maximum_reply_extra_byte_count)) + 4,        }));    }    try std.testing.expectError(error.CapacityOverflow, Capacity.derive(.{        .retained_message_count = std.math.maxInt(usize) / message_bytes + 1,    }));}test "connection storage acquires all regions before readiness" {    const capacity = try Capacity.derive(.{        .retained_message_count = 2,        .request_byte_count = protocol.minimum_request_byte_count,        .reply_byte_count = 4,    });    var failing = std.testing.FailingAllocator.init(std.testing.allocator, .{        .fail_index = 0,    });    try std.testing.expectError(error.OutOfMemory, Storage.init(failing.allocator(), capacity));    failing = std.testing.FailingAllocator.init(std.testing.allocator, .{        .fail_index = 1,    });    try std.testing.expectError(error.OutOfMemory, Storage.init(failing.allocator(), capacity));    failing = std.testing.FailingAllocator.init(std.testing.allocator, .{        .fail_index = 2,    });    try std.testing.expectError(error.OutOfMemory, Storage.init(failing.allocator(), capacity));    failing = std.testing.FailingAllocator.init(std.testing.allocator, .{        .fail_index = 3,    });    try std.testing.expectError(error.OutOfMemory, Storage.init(failing.allocator(), capacity));    failing = std.testing.FailingAllocator.init(std.testing.allocator, .{        .fail_index = 4,    });    var storage = try Storage.init(failing.allocator(), capacity);    defer storage.deinit();    try std.testing.expectEqual(@as(usize, 2), storage.retained_messages.items.len);    try std.testing.expectEqual(        protocol.minimum_request_byte_count,        storage.request.len,    );    try std.testing.expectEqual(@as(usize, 4), storage.reply.len);    try std.testing.expectEqual(        capacity.initialization_scratch_byte_count,        storage.initialization_scratch.len,    );    try std.testing.expectEqual(@as(usize, 4), failing.allocations);    storage.releaseInitializationScratch();    try std.testing.expectEqual(@as(usize, 0), storage.initialization_scratch.len);    try std.testing.expectEqual(@as(usize, 1), failing.deallocations);}test "retained messages preserve FIFO order without steady allocation" {    const capacity = try Capacity.derive(.{ .retained_message_count = 2 });    var failing = std.testing.FailingAllocator.init(std.testing.allocator, .{        .fail_index = 0,    });    try std.testing.expectError(        error.OutOfMemory,        RetainedMessages.init(failing.allocator(), capacity),    );    failing = std.testing.FailingAllocator.init(std.testing.allocator, .{        .fail_index = 1,    });    var retained = try RetainedMessages.init(failing.allocator(), capacity);    defer retained.deinit();    const first: Message = @splat(1);    const second: Message = @splat(2);    const third: Message = @splat(3);    try retained.append(first);    try retained.append(second);    try std.testing.expectError(        error.RetainedMessageCapacityExceeded,        retained.append(third),    );    try std.testing.expectEqual(first, retained.pop().?);    try retained.append(third);    try std.testing.expectEqual(second, retained.pop().?);    try std.testing.expectEqual(third, retained.pop().?);    try std.testing.expect(retained.pop() == null);    try std.testing.expectEqual(Status{        .retained_message_capacity_rejection_count = 1,    }, retained.status());    retained.rejection_count = std.math.maxInt(u64);    try retained.append(first);    try retained.append(second);    try std.testing.expectError(        error.RetainedMessageCapacityExceeded,        retained.append(third),    );    try std.testing.expectEqual(Status{        .retained_message_capacity_rejection_count = std.math.maxInt(u64),    }, retained.status());    try std.testing.expectEqual(@as(usize, 1), failing.allocations);}test "reply wait rejects before consuming a message that cannot be retained" {    const capacity = try Capacity.derive(.{        .retained_message_count = 1,        .reply_byte_count = 4,    });    var request_storage: [protocol.minimum_request_byte_count]u8 = undefined;    var reply_storage: [4]u8 = undefined;    var connection: Connection = .{        .allocator = std.testing.allocator,        .target = undefined,        .stream = undefined,        .setup = undefined,        .screen = 0,        .retained_messages = try RetainedMessages.init(std.testing.allocator, capacity),        .request_storage = &request_storage,        .request_scratch = protocol.Request.init(&request_storage, request_storage.len),        .reply_storage = &reply_storage,    };    defer connection.retained_messages.deinit();    const retained: Message = @splat(7);    try connection.retainMessage(retained);    var blocked: Message = @splat(0);    blocked[0] = @backingInt(protocol.EventCode.key_press);    var reply: Message = @splat(0);    reply[0] = @backingInt(protocol.EventCode.reply);    connection.receive_head = blocked;    connection.receive_head_count = protocol.message_length;    try std.testing.expectError(        error.RetainedMessageCapacityExceeded,        connection.waitReply(),    );    try std.testing.expectEqual(protocol.message_length, connection.receive_head_count);    try std.testing.expectEqual(retained, (try connection.nextMessage()).?);    try std.testing.expectEqual(blocked, (try connection.nextMessage()).?);    connection.receive_head = reply;    connection.receive_head_count = protocol.message_length;    const received_reply = try connection.waitReply();    try std.testing.expectEqual(reply, received_reply.head);    const request = connection.beginRequest();    try protocol.sendEvent(request, 1, 0, &blocked);    try protocol.windowRequest(request, .map_window, 1);    try std.testing.expectError(        error.RequestCapacityExceeded,        protocol.windowRequest(request, .unmap_window, 1),    );    try std.testing.expectEqual(Status{        .retained_message_capacity_rejection_count = 1,        .request_capacity_rejection_count = 1,    }, connection.storageStatus());}test "reply storage recovers after max plus one without steady allocation" {    const sockets = net.socketPairUnixStream() catch |err| switch (err) {        error.UnsupportedPlatform => return error.SkipZigTest,        else => return err,    };    defer net.close(sockets[0]);    defer net.close(sockets[1]);    const capacity = try Capacity.derive(.{        .retained_message_count = 1,        .request_byte_count = protocol.minimum_request_byte_count,        .reply_byte_count = 4,    });    var failing = std.testing.FailingAllocator.init(std.testing.allocator, .{        .fail_index = 1,    });    var request_storage: [protocol.minimum_request_byte_count]u8 = undefined;    var reply_storage: [4]u8 = undefined;    var connection: Connection = .{        .allocator = failing.allocator(),        .target = undefined,        .stream = net.Stream.initFd(sockets[1]),        .setup = undefined,        .screen = 0,        .retained_messages = try RetainedMessages.init(failing.allocator(), capacity),        .request_storage = &request_storage,        .request_scratch = protocol.Request.init(&request_storage, request_storage.len),        .reply_storage = &reply_storage,    };    defer connection.retained_messages.deinit();    var oversized_head: Message = @splat(0);    oversized_head[0] = @backingInt(protocol.EventCode.reply);    std.mem.writeInt(u32, oversized_head[4..8], 2, .little);    var exact_head: Message = @splat(0);    exact_head[0] = @backingInt(protocol.EventCode.reply);    std.mem.writeInt(u32, exact_head[4..8], 1, .little);    const peer = net.Stream.initFd(sockets[0]);    try peer.writeAll(&oversized_head);    try peer.writeAll("eight888");    try peer.writeAll(&exact_head);    try peer.writeAll("four");    try std.testing.expectError(error.ReplyCapacityExceeded, connection.waitReply());    const exact = try connection.waitReply();    try std.testing.expectEqual(exact_head, exact.head);    try std.testing.expectEqualStrings("four", exact.extra);    try std.testing.expectEqual(@as(usize, 1), failing.allocations);    try std.testing.expectEqual(@as(u64, 1), connection.storageStatus().reply_capacity_rejection_count);    connection.reply_capacity_rejection_count = std.math.maxInt(u64);    try peer.writeAll(&oversized_head);    try peer.writeAll("eight888");    try std.testing.expectError(error.ReplyCapacityExceeded, connection.waitReply());    try std.testing.expectEqual(        std.math.maxInt(u64),        connection.storageStatus().reply_capacity_rejection_count,    );    try std.testing.expectEqual(@as(usize, 1), failing.allocations);}test "connection performs the setup handshake against a live display" {    if (env.get("DISPLAY") == null) return error.SkipZigTest;    const capacity = try Capacity.derive(.{});    var connection = Connection.connect(std.testing.allocator, capacity) catch |err| switch (err) {        error.ConnectionFailed, error.AuthenticationFailed => return error.SkipZigTest,        else => return err,    };    defer connection.close();    try std.testing.expect(connection.setup.root != 0);    try std.testing.expect(connection.setup.visual != 0);    try std.testing.expect(connection.setup.max_request_units >= 4096);    try std.testing.expect(connection.setup.visual_depth == 24 or connection.setup.visual_depth == 32);    const first = connection.generateId();    const second = connection.generateId();    try std.testing.expect(first != second);    const protocols = try connection.internAtom("WM_PROTOCOLS");    try std.testing.expect(protocols != 0);    const again = try connection.internAtom("WM_PROTOCOLS");    try std.testing.expectEqual(protocols, again);}

Source: lib/sys/src/x11/root.zig:2

zig
pub const connection = @import("connection.zig");

Complete call list for x11.Connection.connectTo

10 direct calls.

Audit

Definitions31
Public names61
Members48
Version26.7.0
Revisiondaab053ee433