authorgravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2026-10-01 10:07:01+02:00
committergravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2026-10-01 11:21:28+02:00
log2217d43cc91145c4f569108594f6d246d4733752
tree652fcdabd7a9a1e5f476e8061c1990806ebd5c32
parentc53cb65568e80a1d9c20a07373db86377ee9421b
signature Commit is signed but in an unrecognized format.

Revert "std.Io.net: improve reception of control data"

It is not clear to me that this is the right path to take, using a shared buffer for control data makes managing the alignment trickier, and would require the Io interface itself to deal with alignment. For an example of what I consider clean design, see net_read/net_write. There is no need for the Io interface/operations to be aware of control buffer alignment and it is sufficient for the net.Stream.Reader abstraction to use an aligned buffer. Also this has no test coverage and is (to my knowledege) not currently blocking any real world Zig project. This reverts commit 7c0347fce0b6f510b43ca503ad9c1cd2f8ac9a6b.

5 files changed, 23 insertions(+), 106 deletions(-)

lib/std/Io.zig-1
...@@ -346,7 +346,6 @@ pub const Operation = union(enum) {...@@ -346,7 +346,6 @@ pub const Operation = union(enum) {
346 socket_handle: net.Socket.Handle,346 socket_handle: net.Socket.Handle,
347 message_buffer: []net.IncomingMessage,347 message_buffer: []net.IncomingMessage,
348 data_buffer: []u8,348 data_buffer: []u8,
349 control_buffer: []u8 = &.{},
350 flags: net.ReceiveFlags,349 flags: net.ReceiveFlags,
351350
352 pub const Error = error{351 pub const Error = error{
lib/std/Io/Kqueue.zig-2
...@@ -1183,7 +1183,6 @@ fn netReceive(...@@ -1183,7 +1183,6 @@ fn netReceive(
1183 handle: net.Socket.Handle,1183 handle: net.Socket.Handle,
1184 message_buffer: []net.IncomingMessage,1184 message_buffer: []net.IncomingMessage,
1185 data_buffer: []u8,1185 data_buffer: []u8,
1186 control_buffer: []u8,
1187 flags: net.ReceiveFlags,1186 flags: net.ReceiveFlags,
1188 timeout: Io.Timeout,1187 timeout: Io.Timeout,
1189) struct { ?net.Socket.ReceiveTimeoutError, usize } {1188) struct { ?net.Socket.ReceiveTimeoutError, usize } {
...@@ -1192,7 +1191,6 @@ fn netReceive(...@@ -1192,7 +1191,6 @@ fn netReceive(
1192 _ = handle;1191 _ = handle;
1193 _ = message_buffer;1192 _ = message_buffer;
1194 _ = data_buffer;1193 _ = data_buffer;
1195 _ = control_buffer;
1196 _ = flags;1194 _ = flags;
1197 _ = timeout;1195 _ = timeout;
1198 @panic("TODO");1196 @panic("TODO");
lib/std/Io/Threaded.zig+8-18
...@@ -2555,8 +2555,8 @@ fn operate(userdata: ?*anyopaque, operation: Io.Operation) Io.Cancelable!Io.Oper...@@ -2555,8 +2555,8 @@ fn operate(userdata: ?*anyopaque, operation: Io.Operation) Io.Cancelable!Io.Oper
2555 .device_io_control => |*o| return .{ .device_io_control = try deviceIoControl(o) },2555 .device_io_control => |*o| return .{ .device_io_control = try deviceIoControl(o) },
2556 .net_receive => |*o| return .{ .net_receive = o: {2556 .net_receive => |*o| return .{ .net_receive = o: {
2557 if (!have_networking) break :o .{ error.NetworkDown, 0 };2557 if (!have_networking) break :o .{ error.NetworkDown, 0 };
2558 if (is_windows) break :o netReceiveWindows(t, o.socket_handle, o.message_buffer, o.data_buffer, o.control_buffer, o.flags);2558 if (is_windows) break :o netReceiveWindows(t, o.socket_handle, o.message_buffer, o.data_buffer, o.flags);
2559 netReceiveOnePosix(o.socket_handle, &o.message_buffer[0], o.data_buffer, o.control_buffer, o.flags, false) catch |err| switch (err) {2559 netReceivePosix(o.socket_handle, &o.message_buffer[0], o.data_buffer, o.flags, false) catch |err| switch (err) {
2560 error.Canceled => |e| return e,2560 error.Canceled => |e| return e,
2561 error.WouldBlock => unreachable,2561 error.WouldBlock => unreachable,
2562 else => |e| break :o .{ e, 0 },2562 else => |e| break :o .{ e, 0 },
...@@ -2825,11 +2825,9 @@ fn batchAwaitConcurrent(userdata: ?*anyopaque, b: *Io.Batch, timeout: Io.Timeout...@@ -2825,11 +2825,9 @@ fn batchAwaitConcurrent(userdata: ?*anyopaque, b: *Io.Batch, timeout: Io.Timeout
2825 .device_io_control => |o| try poll_storage.add(o.file.handle, posix.POLL.IN | posix.POLL.OUT | posix.POLL.ERR),2825 .device_io_control => |o| try poll_storage.add(o.file.handle, posix.POLL.IN | posix.POLL.OUT | posix.POLL.ERR),
2826 .net_receive => |*o| nb: {2826 .net_receive => |*o| nb: {
2827 var data_i: usize = 0;2827 var data_i: usize = 0;
2828 var control_i: usize = 0;
2829 const result: Io.Operation.Result = .{ .net_receive = for (o.message_buffer, 0..) |*msg, msg_i| {2828 const result: Io.Operation.Result = .{ .net_receive = for (o.message_buffer, 0..) |*msg, msg_i| {
2830 const remaining_data_buffer = o.data_buffer[data_i..];2829 const remaining_data_buffer = o.data_buffer[data_i..];
2831 const remaining_control_buffer = o.control_buffer[control_i..];2830 netReceivePosix(o.socket_handle, msg, remaining_data_buffer, o.flags, true) catch |err| switch (err) {
2832 netReceiveOnePosix(o.socket_handle, msg, remaining_data_buffer, remaining_control_buffer, o.flags, true) catch |err| switch (err) {
2833 error.Canceled => |e| return e,2831 error.Canceled => |e| return e,
2834 error.WouldBlock => {2832 error.WouldBlock => {
2835 if (msg_i != 0) break .{ null, msg_i };2833 if (msg_i != 0) break .{ null, msg_i };
...@@ -2839,7 +2837,6 @@ fn batchAwaitConcurrent(userdata: ?*anyopaque, b: *Io.Batch, timeout: Io.Timeout...@@ -2839,7 +2837,6 @@ fn batchAwaitConcurrent(userdata: ?*anyopaque, b: *Io.Batch, timeout: Io.Timeout
2839 else => |e| break .{ e, 0 },2837 else => |e| break .{ e, 0 },
2840 };2838 };
2841 data_i += msg.data.len;2839 data_i += msg.data.len;
2842 control_i += msg.control.len;
2843 } else .{ null, o.message_buffer.len } };2840 } else .{ null, o.message_buffer.len } };
2844 switch (b.completed.tail) {2841 switch (b.completed.tail) {
2845 .none => b.completed.head = index,2842 .none => b.completed.head = index,
...@@ -3282,7 +3279,7 @@ fn batchDrainSubmittedWindows(t: *Threaded, b: *Io.Batch, concurrency: bool) (Io...@@ -3282,7 +3279,7 @@ fn batchDrainSubmittedWindows(t: *Threaded, b: *Io.Batch, concurrency: bool) (Io
3282 // TODO integrate with overlapped I/O or equivalent to avoid this error3279 // TODO integrate with overlapped I/O or equivalent to avoid this error
3283 if (concurrency) return error.ConcurrencyUnavailable;3280 if (concurrency) return error.ConcurrencyUnavailable;
3284 batchCompleteBlockingWindows(b, operation_userdata, .{3281 batchCompleteBlockingWindows(b, operation_userdata, .{
3285 .net_receive = netReceiveWindows(t, o.socket_handle, o.message_buffer, o.data_buffer, o.control_buffer, o.flags),3282 .net_receive = netReceiveWindows(t, o.socket_handle, o.message_buffer, o.data_buffer, o.flags),
3286 });3283 });
3287 },3284 },
3288 .net_send => |*o| {3285 .net_send => |*o| {
...@@ -13233,11 +13230,10 @@ fn netSendManyPosix(...@@ -13233,11 +13230,10 @@ fn netSendManyPosix(
13233 }13230 }
13234}13231}
1323513232
13236fn netReceiveOnePosix(13233fn netReceivePosix(
13237 socket_handle: net.Socket.Handle,13234 socket_handle: net.Socket.Handle,
13238 message: *net.IncomingMessage,13235 message: *net.IncomingMessage,
13239 data_buffer: []u8,13236 data_buffer: []u8,
13240 control_buffer: []u8,
13241 flags: net.ReceiveFlags,13237 flags: net.ReceiveFlags,
13242 nonblocking: bool,13238 nonblocking: bool,
13243) (net.Socket.ReceiveError || error{WouldBlock})!void {13239) (net.Socket.ReceiveError || error{WouldBlock})!void {
...@@ -13260,24 +13256,22 @@ fn netReceiveOnePosix(...@@ -13260,24 +13256,22 @@ fn netReceiveOnePosix(
13260 .namelen = @sizeOf(PosixAddress),13256 .namelen = @sizeOf(PosixAddress),
13261 .iov = (&iov)[0..1],13257 .iov = (&iov)[0..1],
13262 .iovlen = 1,13258 .iovlen = 1,
13263 .control = control_buffer.ptr,13259 .control = message.control.ptr,
13264 .controllen = @intCast(control_buffer.len),13260 .controllen = @intCast(message.control.len),
13265 .flags = 0,13261 .flags = 0,
13266 };13262 };
1326713263
13268 const syscall = try Syscall.start();13264 const syscall = try Syscall.start();
13269 while (true) {13265 while (true) {
13270 const rc = posix.system.recvmsg(socket_handle, &msg, posix_flags);13266 const rc = posix.system.recvmsg(socket_handle, &msg, posix_flags);
13271 const rc_control = msg.controllen;
13272 switch (posix.errno(rc)) {13267 switch (posix.errno(rc)) {
13273 .SUCCESS => {13268 .SUCCESS => {
13274 syscall.finish();13269 syscall.finish();
13275 const data = data_buffer[0..@intCast(rc)];13270 const data = data_buffer[0..@intCast(rc)];
13276 const control = control_buffer[0..@intCast(rc_control)];
13277 message.* = .{13271 message.* = .{
13278 .from = addressFromPosix(&storage),13272 .from = addressFromPosix(&storage),
13279 .data = data,13273 .data = data,
13280 .control = control,13274 .control = if (msg.control) |ptr| @as([*]u8, @ptrCast(ptr))[0..msg.controllen] else message.control,
13281 .flags = .{13275 .flags = .{
13282 .eor = (msg.flags & posix.MSG.EOR) != 0,13276 .eor = (msg.flags & posix.MSG.EOR) != 0,
13283 .trunc = (msg.flags & posix.MSG.TRUNC) != 0,13277 .trunc = (msg.flags & posix.MSG.TRUNC) != 0,
...@@ -13318,12 +13312,8 @@ fn netReceiveWindows(...@@ -13318,12 +13312,8 @@ fn netReceiveWindows(
13318 socket_handle: net.Socket.Handle,13312 socket_handle: net.Socket.Handle,
13319 message_buffer: []net.IncomingMessage,13313 message_buffer: []net.IncomingMessage,
13320 data_buffer: []u8,13314 data_buffer: []u8,
13321 control_buffer: []u8,
13322 flags: net.ReceiveFlags,13315 flags: net.ReceiveFlags,
13323) struct { ?net.Socket.ReceiveError, usize } {13316) struct { ?net.Socket.ReceiveError, usize } {
13324 // Windows doesn't have the concept of control/ancillary data.
13325 _ = control_buffer;
13326
13327 t.netReceiveOneWindows(socket_handle, &message_buffer[0], data_buffer, flags) catch |err|13317 t.netReceiveOneWindows(socket_handle, &message_buffer[0], data_buffer, flags) catch |err|
13328 return .{ err, 0 };13318 return .{ err, 0 };
13329 return .{ null, 1 };13319 return .{ null, 1 };
lib/std/Io/Uring.zig+4-9
...@@ -2095,7 +2095,7 @@ fn operate(userdata: ?*anyopaque, operation: Io.Operation) Io.Cancelable!Io.Oper...@@ -2095,7 +2095,7 @@ fn operate(userdata: ?*anyopaque, operation: Io.Operation) Io.Cancelable!Io.Oper
2095 },2095 },
2096 .net_receive => |o| .{2096 .net_receive => |o| .{
2097 .net_receive = r: {2097 .net_receive = r: {
2098 const opt_err, const n = ev.netReceive(&maybe_sync.cancel_region, o.socket_handle, o.message_buffer, o.data_buffer, o.control_buffer, o.flags);2098 const opt_err, const n = ev.netReceive(&maybe_sync.cancel_region, o.socket_handle, o.message_buffer, o.data_buffer, o.flags);
2099 break :r .{2099 break :r .{
2100 if (opt_err) |err| switch (err) {2100 if (opt_err) |err| switch (err) {
2101 error.Canceled => |e| return e,2101 error.Canceled => |e| return e,
...@@ -5075,18 +5075,15 @@ fn netReceive(...@@ -5075,18 +5075,15 @@ fn netReceive(
5075 handle: net.Socket.Handle,5075 handle: net.Socket.Handle,
5076 message_buffer: []net.IncomingMessage,5076 message_buffer: []net.IncomingMessage,
5077 data_buffer: []u8,5077 data_buffer: []u8,
5078 control_buffer: []u8,
5079 flags: net.ReceiveFlags,5078 flags: net.ReceiveFlags,
5080) struct { ?net.Socket.ReceiveError, usize } {5079) struct { ?net.Socket.ReceiveError, usize } {
5081 var message_i: usize = 0;5080 var message_i: usize = 0;
5082 var data_i: usize = 0;5081 var data_i: usize = 0;
5083 var control_i: usize = 0;
50845082
5085 while (true) {5083 while (true) {
5086 if (message_buffer.len - message_i == 0) return .{ null, message_i };5084 if (message_buffer.len - message_i == 0) return .{ null, message_i };
5087 const message = &message_buffer[message_i];5085 const message = &message_buffer[message_i];
5088 const remaining_data_buffer = data_buffer[data_i..];5086 const remaining_data_buffer = data_buffer[data_i..];
5089 const remaining_control_buffer = control_buffer[control_i..];
5090 var storage: PosixAddress = undefined;5087 var storage: PosixAddress = undefined;
5091 var iov: iovec = .{ .base = remaining_data_buffer.ptr, .len = remaining_data_buffer.len };5088 var iov: iovec = .{ .base = remaining_data_buffer.ptr, .len = remaining_data_buffer.len };
5092 var msg: linux.msghdr = .{5089 var msg: linux.msghdr = .{
...@@ -5094,8 +5091,8 @@ fn netReceive(...@@ -5094,8 +5091,8 @@ fn netReceive(
5094 .namelen = @sizeOf(PosixAddress),5091 .namelen = @sizeOf(PosixAddress),
5095 .iov = (&iov)[0..1],5092 .iov = (&iov)[0..1],
5096 .iovlen = 1,5093 .iovlen = 1,
5097 .control = remaining_control_buffer.ptr,5094 .control = message.control.ptr,
5098 .controllen = @intCast(remaining_control_buffer.len),5095 .controllen = @intCast(message.control.len),
5099 .flags = undefined,5096 .flags = undefined,
5100 };5097 };
51015098
...@@ -5124,13 +5121,11 @@ fn netReceive(...@@ -5124,13 +5121,11 @@ fn netReceive(
5124 switch (completion.errno()) {5121 switch (completion.errno()) {
5125 .SUCCESS => {5122 .SUCCESS => {
5126 const data = remaining_data_buffer[0..@intCast(completion.result)];5123 const data = remaining_data_buffer[0..@intCast(completion.result)];
5127 const control = remaining_control_buffer[0..@intCast(msg.controllen)];
5128 data_i += data.len;5124 data_i += data.len;
5129 control_i += @intCast(msg.controllen);
5130 message.* = .{5125 message.* = .{
5131 .from = addressFromPosix(&storage),5126 .from = addressFromPosix(&storage),
5132 .data = data,5127 .data = data,
5133 .control = control,5128 .control = if (msg.control) |ptr| @as([*]u8, @ptrCast(ptr))[0..msg.controllen] else message.control,
5134 .flags = .{5129 .flags = .{
5135 .eor = msg.flags & linux.MSG.EOR != 0,5130 .eor = msg.flags & linux.MSG.EOR != 0,
5136 .trunc = msg.flags & linux.MSG.TRUNC != 0,5131 .trunc = msg.flags & linux.MSG.TRUNC != 0,
lib/std/Io/net.zig+11-76
...@@ -924,20 +924,22 @@ pub const ReceiveFlags = packed struct(u8) {...@@ -924,20 +924,22 @@ pub const ReceiveFlags = packed struct(u8) {
924 _: u5 = 0,924 _: u5 = 0,
925};925};
926926
927/// Fields are populated by receive functions.
928pub const IncomingMessage = struct {927pub const IncomingMessage = struct {
928 /// Populated by receive functions.
929 from: IpAddress,929 from: IpAddress,
930 /// Points into caller-supplied buffer.930 /// Populated by receive functions, points into the caller-supplied buffer.
931 data: []u8,931 data: []u8,
932 /// Points into caller-supplied buffer.932 /// Supplied by caller before calling receive functions; mutated by receive
933 /// functions.
933 control: []u8,934 control: []u8,
935 /// Populated by receive functions.
934 flags: Flags,936 flags: Flags,
935937
936 /// Deprecated. Initialize with `undefined`.938 /// Useful for initializing before calling `receiveManyTimeout`.
937 pub const init: IncomingMessage = .{939 pub const init: IncomingMessage = .{
938 .from = undefined,940 .from = undefined,
939 .data = undefined,941 .data = undefined,
940 .control = undefined,942 .control = &.{},
941 .flags = undefined,943 .flags = undefined,
942 };944 };
943945
...@@ -1160,30 +1162,13 @@ pub const Socket = struct {...@@ -1160,30 +1162,13 @@ pub const Socket = struct {
1160 /// Waits for data. Connectionless.1162 /// Waits for data. Connectionless.
1161 ///1163 ///
1162 /// See also:1164 /// See also:
1163 /// * `receiveWithControl`
1164 /// * `receiveTimeout`1165 /// * `receiveTimeout`
1165 /// * `receiveWithControlTimeout`
1166 /// * `receiveManyTimeout`
1167 /// * `receiveManyWithControlTimeout`
1168 pub fn receive(s: *const Socket, io: Io, buffer: []u8) ReceiveError!IncomingMessage {1166 pub fn receive(s: *const Socket, io: Io, buffer: []u8) ReceiveError!IncomingMessage {
1169 return s.receiveWithControl(io, buffer, &.{});1167 var message: IncomingMessage = .init;
1170 }
1171
1172 /// Waits for data, allowing the reception of control data. Connectionless.
1173 ///
1174 /// See also:
1175 /// * `receive`
1176 /// * `receiveTimeout`
1177 /// * `receiveWithControlTimeout`
1178 /// * `receiveManyTimeout`
1179 /// * `receiveManyWithControlTimeout`
1180 pub fn receiveWithControl(s: *const Socket, io: Io, buffer: []u8, control: []u8) ReceiveError!IncomingMessage {
1181 var message: IncomingMessage = undefined;
1182 const maybe_err, const count = (try io.operate(.{ .net_receive = .{1168 const maybe_err, const count = (try io.operate(.{ .net_receive = .{
1183 .socket_handle = s.handle,1169 .socket_handle = s.handle,
1184 .message_buffer = (&message)[0..1],1170 .message_buffer = (&message)[0..1],
1185 .data_buffer = buffer,1171 .data_buffer = buffer,
1186 .control_buffer = control,
1187 .flags = .{},1172 .flags = .{},
1188 } })).net_receive;1173 } })).net_receive;
1189 if (maybe_err) |err| return err;1174 if (maybe_err) |err| return err;
...@@ -1199,42 +1184,18 @@ pub const Socket = struct {...@@ -1199,42 +1184,18 @@ pub const Socket = struct {
1199 ///1184 ///
1200 /// See also:1185 /// See also:
1201 /// * `receive`1186 /// * `receive`
1202 /// * `receiveWithControl`
1203 /// * `receiveWithControlTimeout`
1204 /// * `receiveManyTimeout`1187 /// * `receiveManyTimeout`
1205 /// * `receiveManyWithControlTimeout`
1206 pub fn receiveTimeout(1188 pub fn receiveTimeout(
1207 s: *const Socket,1189 s: *const Socket,
1208 io: Io,1190 io: Io,
1209 buffer: []u8,1191 buffer: []u8,
1210 timeout: Io.Timeout,1192 timeout: Io.Timeout,
1211 ) ReceiveTimeoutError!IncomingMessage {1193 ) ReceiveTimeoutError!IncomingMessage {
1212 return s.receiveWithControlTimeout(io, buffer, &.{}, timeout);1194 var message: IncomingMessage = .init;
1213 }
1214
1215 /// Waits for data, allowing the reception of control data. Connectionless.
1216 ///
1217 /// Returns `error.Timeout` if no message arrives early enough.
1218 ///
1219 /// See also:
1220 /// * `receive`
1221 /// * `receiveWithControl`
1222 /// * `receiveTimeout`
1223 /// * `receiveManyTimeout`
1224 /// * `receiveManyWithControlTimeout`
1225 pub fn receiveWithControlTimeout(
1226 s: *const Socket,
1227 io: Io,
1228 buffer: []u8,
1229 control: []u8,
1230 timeout: Io.Timeout,
1231 ) ReceiveTimeoutError!IncomingMessage {
1232 var message: IncomingMessage = undefined;
1233 const maybe_err, const count = (try io.operateTimeout(.{ .net_receive = .{1195 const maybe_err, const count = (try io.operateTimeout(.{ .net_receive = .{
1234 .socket_handle = s.handle,1196 .socket_handle = s.handle,
1235 .message_buffer = (&message)[0..1],1197 .message_buffer = (&message)[0..1],
1236 .data_buffer = buffer,1198 .data_buffer = buffer,
1237 .control_buffer = control,
1238 .flags = .{},1199 .flags = .{},
1239 } }, timeout)).net_receive;1200 } }, timeout)).net_receive;
1240 if (maybe_err) |err| return err;1201 if (maybe_err) |err| return err;
...@@ -1250,47 +1211,21 @@ pub const Socket = struct {...@@ -1250,47 +1211,21 @@ pub const Socket = struct {
1250 ///1211 ///
1251 /// See also:1212 /// See also:
1252 /// * `receive`1213 /// * `receive`
1253 /// * `receiveWithControl`
1254 /// * `receiveTimeout`1214 /// * `receiveTimeout`
1255 /// * `receiveWithControlTimeout`
1256 /// * `receiveManyWithControlTimeout`
1257 pub fn receiveManyTimeout(1215 pub fn receiveManyTimeout(
1258 s: *const Socket,1216 s: *const Socket,
1259 io: Io,1217 io: Io,
1218 /// Function assumes each element has initialized `control` field.
1219 /// Initializing with `IncomingMessage.init` may be helpful.
1260 message_buffer: []IncomingMessage,1220 message_buffer: []IncomingMessage,
1261 data_buffer: []u8,1221 data_buffer: []u8,
1262 flags: ReceiveFlags,1222 flags: ReceiveFlags,
1263 timeout: Io.Timeout,1223 timeout: Io.Timeout,
1264 ) struct { ?ReceiveTimeoutError, usize } {
1265 return s.receiveManyWithControlTimeout(io, message_buffer, data_buffer, &.{}, flags, timeout);
1266 }
1267
1268 /// Waits until at least one message is delivered, possibly returning more
1269 /// than one message. Allows reception of control data. Connectionless.
1270 ///
1271 /// Returns number of messages received, or `error.Timeout` if no message
1272 /// arrives early enough.
1273 ///
1274 /// See also:
1275 /// * `receive`
1276 /// * `receiveWithControl`
1277 /// * `receiveTimeout`
1278 /// * `receiveWithControlTimeout`
1279 /// * `receiveManyTimeout`
1280 pub fn receiveManyWithControlTimeout(
1281 s: *const Socket,
1282 io: Io,
1283 message_buffer: []IncomingMessage,
1284 data_buffer: []u8,
1285 control_buffer: []u8,
1286 flags: ReceiveFlags,
1287 timeout: Io.Timeout,
1288 ) struct { ?ReceiveTimeoutError, usize } {1224 ) struct { ?ReceiveTimeoutError, usize } {
1289 const result = io.operateTimeout(.{ .net_receive = .{1225 const result = io.operateTimeout(.{ .net_receive = .{
1290 .socket_handle = s.handle,1226 .socket_handle = s.handle,
1291 .message_buffer = message_buffer,1227 .message_buffer = message_buffer,
1292 .data_buffer = data_buffer,1228 .data_buffer = data_buffer,
1293 .control_buffer = control_buffer,
1294 .flags = flags,1229 .flags = flags,
1295 } }, timeout) catch |err| return .{ err, 0 };1230 } }, timeout) catch |err| return .{ err, 0 };
1296 return result.net_receive;1231 return result.net_receive;