authorgravatar for hemisputnik@proton.mehemisputnik <hemisputnik@proton.me> 2026-07-22 11:28:31+03:00
committergravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2026-10-01 10:55:12+02:00
logc4d9d65a7bfb0e675ff9b43c50332032bcec6b25
tree8f07c2d7cebf7412548621ed5d08fbaa6e388757
parent875cb2ff2f321ec40b02f8de40230a28e56d6844
signature Commit is signed but in an unrecognized format.

std.Io.net: send control data with .net_write

Add a new parameter to .net_write - control.

3 files changed, 15 insertions(+), 5 deletions(-)

lib/std/Io.zig+1
...@@ -453,6 +453,7 @@ pub const Operation = union(enum) {...@@ -453,6 +453,7 @@ pub const Operation = union(enum) {
453 header: []const u8 = &.{},453 header: []const u8 = &.{},
454 data: []const []const u8,454 data: []const []const u8,
455 splat: usize = 1,455 splat: usize = 1,
456 control: []const u8 = &.{},
456457
457 pub const Error = error{458 pub const Error = error{
458 /// Another TCP Fast Open is already in progress.459 /// Another TCP Fast Open is already in progress.
lib/std/Io/Threaded.zig+10-5
...@@ -2590,9 +2590,9 @@ fn operate(userdata: ?*anyopaque, operation: Io.Operation) Io.Cancelable!Io.Oper...@@ -2590,9 +2590,9 @@ fn operate(userdata: ?*anyopaque, operation: Io.Operation) Io.Cancelable!Io.Oper
2590 },2590 },
2591 .net_write => |o| return .{2591 .net_write => |o| return .{
2592 .net_write = (if (is_windows)2592 .net_write = (if (is_windows)
2593 netWriteWindows(o.socket_handle, o.header, o.data, o.splat)2593 netWriteWindows(o.socket_handle, o.header, o.data, o.splat, o.control)
2594 else2594 else
2595 netWritePosix(o.socket_handle, o.header, o.data, o.splat)) catch |err| switch (err) {2595 netWritePosix(o.socket_handle, o.header, o.data, o.splat, o.control)) catch |err| switch (err) {
2596 error.Canceled => |e| return e,2596 error.Canceled => |e| return e,
2597 else => |e| e,2597 else => |e| e,
2598 },2598 },
...@@ -3306,7 +3306,7 @@ fn batchDrainSubmittedWindows(t: *Threaded, b: *Io.Batch, concurrency: bool) (Io...@@ -3306,7 +3306,7 @@ fn batchDrainSubmittedWindows(t: *Threaded, b: *Io.Batch, concurrency: bool) (Io
3306 // TODO integrate with overlapped I/O or equivalent to avoid this error3306 // TODO integrate with overlapped I/O or equivalent to avoid this error
3307 if (concurrency) return error.ConcurrencyUnavailable;3307 if (concurrency) return error.ConcurrencyUnavailable;
3308 batchCompleteBlockingWindows(b, operation_userdata, .{3308 batchCompleteBlockingWindows(b, operation_userdata, .{
3309 .net_write = netWriteWindows(o.socket_handle, o.header, o.data, o.splat) catch |err| switch (err) {3309 .net_write = netWriteWindows(o.socket_handle, o.header, o.data, o.splat, o.control) catch |err| switch (err) {
3310 error.Canceled => |e| return e,3310 error.Canceled => |e| return e,
3311 else => |e| e,3311 else => |e| e,
3312 },3312 },
...@@ -13389,6 +13389,7 @@ fn netWritePosix(...@@ -13389,6 +13389,7 @@ fn netWritePosix(
13389 header: []const u8,13389 header: []const u8,
13390 data: []const []const u8,13390 data: []const []const u8,
13391 splat: usize,13391 splat: usize,
13392 control: []const u8,
13392) net.Stream.Writer.Error!usize {13393) net.Stream.Writer.Error!usize {
13393 if (!have_networking) return error.NetworkDown;13394 if (!have_networking) return error.NetworkDown;
1339413395
...@@ -13398,8 +13399,8 @@ fn netWritePosix(...@@ -13398,8 +13399,8 @@ fn netWritePosix(
13398 .namelen = 0,13399 .namelen = 0,
13399 .iov = &iovecs,13400 .iov = &iovecs,
13400 .iovlen = 0,13401 .iovlen = 0,
13401 .control = null,13402 .control = if (control.len == 0) null else @constCast(control.ptr),
13402 .controllen = 0,13403 .controllen = @intCast(control.len),
13403 .flags = 0,13404 .flags = 0,
13404 };13405 };
13405 addBuf(&iovecs, &msg.iovlen, header);13406 addBuf(&iovecs, &msg.iovlen, header);
...@@ -13481,9 +13482,13 @@ fn netWriteWindows(...@@ -13481,9 +13482,13 @@ fn netWriteWindows(
13481 header: []const u8,13482 header: []const u8,
13482 data: []const []const u8,13483 data: []const []const u8,
13483 splat: usize,13484 splat: usize,
13485 control: []const u8,
13484) net.Stream.Writer.Error!usize {13486) net.Stream.Writer.Error!usize {
13485 if (!have_networking) return error.NetworkDown;13487 if (!have_networking) return error.NetworkDown;
1348613488
13489 // Windows doesn't have the concept of control/ancillary data.
13490 _ = control;
13491
13487 var iovecs: [max_iovecs_len]windows.AFD.WSABUF(.@"const") = undefined;13492 var iovecs: [max_iovecs_len]windows.AFD.WSABUF(.@"const") = undefined;
13488 var len: u32 = 0;13493 var len: u32 = 0;
13489 addAfdBuf(.@"const", &iovecs, &len, header);13494 addAfdBuf(.@"const", &iovecs, &len, header);
lib/std/Io/net.zig+4
...@@ -1457,6 +1457,8 @@ pub const Stream = struct {...@@ -1457,6 +1457,8 @@ pub const Stream = struct {
1457 pub const Writer = struct {1457 pub const Writer = struct {
1458 io: Io,1458 io: Io,
1459 interface: Io.Writer,1459 interface: Io.Writer,
1460 /// Will be sent on next drain, then set back to an empty slice.
1461 control: []const u8 = &.{},
1460 stream: Stream,1462 stream: Stream,
1461 err: ?Error = null,1463 err: ?Error = null,
1462 write_file_err: ?WriteFileError = null,1464 write_file_err: ?WriteFileError = null,
...@@ -1499,6 +1501,7 @@ pub const Stream = struct {...@@ -1499,6 +1501,7 @@ pub const Stream = struct {
1499 .header = buffered,1501 .header = buffered,
1500 .data = data,1502 .data = data,
1501 .splat = splat,1503 .splat = splat,
1504 .control = w.control,
1502 } }) catch |err| {1505 } }) catch |err| {
1503 w.err = err;1506 w.err = err;
1504 return error.WriteFailed;1507 return error.WriteFailed;
...@@ -1507,6 +1510,7 @@ pub const Stream = struct {...@@ -1507,6 +1510,7 @@ pub const Stream = struct {
1507 w.err = err;1510 w.err = err;
1508 return error.WriteFailed;1511 return error.WriteFailed;
1509 };1512 };
1513 w.control = &.{};
1510 return io_w.consume(n);1514 return io_w.consume(n);
1511 }1515 }
15121516