| ... | @@ -1308,11 +1308,64 @@ fn netSend( | ... | @@ -1308,11 +1308,64 @@ fn netSend( |
| 1308 | @as(u32, if (@hasDecl(posix.MSG, "FASTOPEN") and flags.fastopen) posix.MSG.FASTOPEN else 0) | | 1308 | @as(u32, if (@hasDecl(posix.MSG, "FASTOPEN") and flags.fastopen) posix.MSG.FASTOPEN else 0) | |
| 1309 | posix.MSG.NOSIGNAL; | 1309 | posix.MSG.NOSIGNAL; |
| 1310 | | 1310 | |
| 1311 | _ = k; | 1311 | for (outgoing_messages, 0..) |*msg, i| { |
| 1312 | _ = posix_flags; | 1312 | netSendOne(k, handle, msg, posix_flags) catch |err| return .{ err, i }; |
| 1313 | _ = handle; | 1313 | } |
| 1314 | _ = outgoing_messages; | 1314 | |
| 1315 | @panic("TODO"); | 1315 | return .{ null, outgoing_messages.len }; |
| | 1316 | } |
| | 1317 | |
| | 1318 | fn netSendOne( |
| | 1319 | k: *Kqueue, |
| | 1320 | handle: net.Socket.Handle, |
| | 1321 | message: *net.OutgoingMessage, |
| | 1322 | flags: u32, |
| | 1323 | ) net.Socket.SendError!void { |
| | 1324 | var addr: Io.Threaded.PosixAddress = undefined; |
| | 1325 | var iovec: posix.iovec_const = .{ .base = @constCast(message.data_ptr), .len = message.data_len }; |
| | 1326 | const msg: posix.msghdr_const = .{ |
| | 1327 | .name = &addr.any, |
| | 1328 | .namelen = Io.Threaded.addressToPosix(message.address, &addr), |
| | 1329 | .iov = (&iovec)[0..1], |
| | 1330 | .iovlen = 1, |
| | 1331 | // OS returns EINVAL if this pointer is invalid even if controllen is zero. |
| | 1332 | .control = if (message.control.len == 0) null else @constCast(message.control.ptr), |
| | 1333 | .controllen = @intCast(message.control.len), |
| | 1334 | .flags = 0, |
| | 1335 | }; |
| | 1336 | while (true) { |
| | 1337 | try k.checkCancel(); |
| | 1338 | const rc = posix.system.sendmsg(handle, &msg, flags); |
| | 1339 | switch (posix.errno(rc)) { |
| | 1340 | .SUCCESS => { |
| | 1341 | message.data_len = @intCast(rc); |
| | 1342 | return; |
| | 1343 | }, |
| | 1344 | .INTR => continue, |
| | 1345 | .CANCELED => return error.Canceled, |
| | 1346 | |
| | 1347 | .ACCES => return error.AccessDenied, |
| | 1348 | .ALREADY => return error.FastOpenAlreadyInProgress, |
| | 1349 | .BADF => |err| return errnoBug(err), // File descriptor used after closed. |
| | 1350 | .CONNRESET => return error.ConnectionResetByPeer, |
| | 1351 | .DESTADDRREQ => |err| return errnoBug(err), |
| | 1352 | .FAULT => |err| return errnoBug(err), |
| | 1353 | .INVAL => |err| return errnoBug(err), |
| | 1354 | .ISCONN => |err| return errnoBug(err), |
| | 1355 | .MSGSIZE => return error.MessageOversize, |
| | 1356 | .NOBUFS => return error.SystemResources, |
| | 1357 | .NOMEM => return error.SystemResources, |
| | 1358 | .NOTSOCK => |err| return errnoBug(err), |
| | 1359 | .OPNOTSUPP => |err| return errnoBug(err), |
| | 1360 | .PIPE => return error.SocketUnconnected, |
| | 1361 | .AFNOSUPPORT => return error.AddressFamilyUnsupported, |
| | 1362 | .HOSTUNREACH => return error.HostUnreachable, |
| | 1363 | .NETUNREACH => return error.NetworkUnreachable, |
| | 1364 | .NOTCONN => return error.SocketUnconnected, |
| | 1365 | .NETDOWN => return error.NetworkDown, |
| | 1366 | else => |err| return posix.unexpectedErrno(err), |
| | 1367 | } |
| | 1368 | } |
| 1316 | } | 1369 | } |
| 1317 | | 1370 | |
| 1318 | fn netReceive( | 1371 | fn netReceive( |