| author | |
| committer | |
| log | 2217d43cc91145c4f569108594f6d246d4733752 |
| tree | 652fcdabd7a9a1e5f476e8061c1990806ebd5c32 |
| parent | c53cb65568e80a1d9c20a07373db86377ee9421b |
| signature | Commit is signed but in an unrecognized format. |
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, |
| 351 | 350 | ||
| 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 error | 3279 | // 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 | } |
| 13235 | 13232 | ||
| 13236 | fn netReceiveOnePosix( | 13233 | fn 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 | }; |
| 13267 | 13263 | ||
| 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; | ||
| 5084 | 5082 | ||
| 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 | }; |
| 5101 | 5098 | ||
| ... | @@ -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 | }; |
| 926 | 926 | ||
| 927 | /// Fields are populated by receive functions. | ||
| 928 | pub const IncomingMessage = struct { | 927 | pub 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, |
| 935 | 937 | ||
| 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 | }; |
| 943 | 945 | ||
| ... | @@ -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; |