| ... | ... | @@ -3909,8 +3909,7 @@ fn netSendOne( |
| 3909 | 3909 | .ENETRESET => return error.ConnectionResetByPeer, |
| 3910 | 3910 | .ENETUNREACH => return error.NetworkUnreachable, |
| 3911 | 3911 | .ENOTCONN => return error.SocketUnconnected, |
| 3912 | | .ESHUTDOWN => unreachable, // The socket has been shut down; it is not possible to WSASendTo on a socket after shutdown has been invoked with how set to SD_SEND or SD_BOTH. |
| 3913 | | .NOTINITIALISED => unreachable, // A successful WSAStartup call must occur before using this function. |
| 3912 | .ESHUTDOWN => |err| return wsaErrorBug(err), |
| 3914 | 3913 | else => |err| return windows.unexpectedWSAError(err), |
| 3915 | 3914 | } |
| 3916 | 3915 | } else { |
| ... | ... | @@ -4275,12 +4274,100 @@ fn netWriteWindows( |
| 4275 | 4274 | splat: usize, |
| 4276 | 4275 | ) net.Stream.Writer.Error!usize { |
| 4277 | 4276 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 4278 | | _ = t; |
| 4279 | | _ = handle; |
| 4280 | | _ = header; |
| 4281 | | _ = data; |
| 4282 | | _ = splat; |
| 4283 | | @panic("TODO implement netWriteWindows"); |
| 4277 | comptime assert(native_os == .windows); |
| 4278 | |
| 4279 | var iovecs: [max_iovecs_len]ws2_32.WSABUF = undefined; |
| 4280 | var len: u32 = 0; |
| 4281 | addWsaBuf(&iovecs, &len, header); |
| 4282 | for (data[0 .. data.len - 1]) |bytes| addWsaBuf(&iovecs, &len, bytes); |
| 4283 | const pattern = data[data.len - 1]; |
| 4284 | if (iovecs.len - len != 0) switch (splat) { |
| 4285 | 0 => {}, |
| 4286 | 1 => addWsaBuf(&iovecs, &len, pattern), |
| 4287 | else => switch (pattern.len) { |
| 4288 | 0 => {}, |
| 4289 | 1 => { |
| 4290 | var backup_buffer: [64]u8 = undefined; |
| 4291 | const splat_buffer = &backup_buffer; |
| 4292 | const memset_len = @min(splat_buffer.len, splat); |
| 4293 | const buf = splat_buffer[0..memset_len]; |
| 4294 | @memset(buf, pattern[0]); |
| 4295 | addWsaBuf(&iovecs, &len, buf); |
| 4296 | var remaining_splat = splat - buf.len; |
| 4297 | while (remaining_splat > splat_buffer.len and len < iovecs.len) { |
| 4298 | addWsaBuf(&iovecs, &len, splat_buffer); |
| 4299 | remaining_splat -= splat_buffer.len; |
| 4300 | } |
| 4301 | addWsaBuf(&iovecs, &len, splat_buffer[0..remaining_splat]); |
| 4302 | }, |
| 4303 | else => for (0..@min(splat, iovecs.len - len)) |_| { |
| 4304 | addWsaBuf(&iovecs, &len, pattern); |
| 4305 | }, |
| 4306 | }, |
| 4307 | }; |
| 4308 | |
| 4309 | while (true) { |
| 4310 | try t.checkCancel(); |
| 4311 | |
| 4312 | var n: u32 = undefined; |
| 4313 | var overlapped: windows.OVERLAPPED = std.mem.zeroes(windows.OVERLAPPED); |
| 4314 | const rc = ws2_32.WSASend(handle, &iovecs, len, &n, 0, &overlapped, null); |
| 4315 | if (rc != ws2_32.SOCKET_ERROR) return n; |
| 4316 | const wsa_error: ws2_32.WinsockError = switch (ws2_32.WSAGetLastError()) { |
| 4317 | .IO_PENDING => e: { |
| 4318 | var result_flags: u32 = undefined; |
| 4319 | const overlapped_rc = ws2_32.WSAGetOverlappedResult( |
| 4320 | handle, |
| 4321 | &overlapped, |
| 4322 | &n, |
| 4323 | windows.TRUE, |
| 4324 | &result_flags, |
| 4325 | ); |
| 4326 | if (overlapped_rc == windows.FALSE) { |
| 4327 | break :e ws2_32.WSAGetLastError(); |
| 4328 | } else { |
| 4329 | return n; |
| 4330 | } |
| 4331 | }, |
| 4332 | else => |err| err, |
| 4333 | }; |
| 4334 | switch (wsa_error) { |
| 4335 | .EINTR => continue, |
| 4336 | .ECANCELLED, .E_CANCELLED, .OPERATION_ABORTED => return error.Canceled, |
| 4337 | .NOTINITIALISED => { |
| 4338 | try initializeWsa(t); |
| 4339 | continue; |
| 4340 | }, |
| 4341 | |
| 4342 | .ECONNABORTED => return error.ConnectionResetByPeer, |
| 4343 | .ECONNRESET => return error.ConnectionResetByPeer, |
| 4344 | .EINVAL => return error.SocketUnconnected, |
| 4345 | .ENETDOWN => return error.NetworkDown, |
| 4346 | .ENETRESET => return error.ConnectionResetByPeer, |
| 4347 | .ENOBUFS => return error.SystemResources, |
| 4348 | .ENOTCONN => return error.SocketUnconnected, |
| 4349 | .ENOTSOCK => |err| return wsaErrorBug(err), |
| 4350 | .EOPNOTSUPP => |err| return wsaErrorBug(err), |
| 4351 | .ESHUTDOWN => |err| return wsaErrorBug(err), |
| 4352 | else => |err| return windows.unexpectedWSAError(err), |
| 4353 | } |
| 4354 | } |
| 4355 | } |
| 4356 | |
| 4357 | fn addWsaBuf(v: []ws2_32.WSABUF, i: *u32, bytes: []const u8) void { |
| 4358 | const cap = std.math.maxInt(u32); |
| 4359 | var remaining = bytes; |
| 4360 | while (remaining.len > cap) { |
| 4361 | if (v.len - i.* == 0) return; |
| 4362 | v[i.*] = .{ .buf = @constCast(remaining.ptr), .len = cap }; |
| 4363 | i.* += 1; |
| 4364 | remaining = remaining[cap..]; |
| 4365 | } else { |
| 4366 | @branchHint(.likely); |
| 4367 | if (v.len - i.* == 0) return; |
| 4368 | v[i.*] = .{ .buf = @constCast(remaining.ptr), .len = @intCast(remaining.len) }; |
| 4369 | i.* += 1; |
| 4370 | } |
| 4284 | 4371 | } |
| 4285 | 4372 | |
| 4286 | 4373 | fn netWriteUnavailable( |