| ... | @@ -168,80 +168,28 @@ pub fn io(t: *Threaded) Io { | ... | @@ -168,80 +168,28 @@ pub fn io(t: *Threaded) Io { |
| 168 | .conditionWaitUncancelable = conditionWaitUncancelable, | 168 | .conditionWaitUncancelable = conditionWaitUncancelable, |
| 169 | .conditionWake = conditionWake, | 169 | .conditionWake = conditionWake, |
| 170 | | 170 | |
| 171 | .dirMake = switch (native_os) { | 171 | .dirMake = dirMake, |
| 172 | .windows => dirMakeWindows, | 172 | .dirMakePath = dirMakePath, |
| 173 | .wasi => dirMakeWasi, | 173 | .dirMakeOpenPath = dirMakeOpenPath, |
| 174 | else => dirMakePosix, | | |
| 175 | }, | | |
| 176 | .dirMakePath = switch (native_os) { | | |
| 177 | .windows => dirMakePathWindows, | | |
| 178 | else => dirMakePathPosix, | | |
| 179 | }, | | |
| 180 | .dirMakeOpenPath = switch (native_os) { | | |
| 181 | .windows => dirMakeOpenPathWindows, | | |
| 182 | .wasi => dirMakeOpenPathWasi, | | |
| 183 | else => dirMakeOpenPathPosix, | | |
| 184 | }, | | |
| 185 | .dirStat = dirStat, | 174 | .dirStat = dirStat, |
| 186 | .dirStatPath = switch (native_os) { | 175 | .dirStatPath = dirStatPath, |
| 187 | .linux => dirStatPathLinux, | 176 | .fileStat = fileStat, |
| 188 | .windows => dirStatPathWindows, | 177 | .dirAccess = dirAccess, |
| 189 | .wasi => dirStatPathWasi, | 178 | .dirCreateFile = dirCreateFile, |
| 190 | else => dirStatPathPosix, | 179 | .dirOpenFile = dirOpenFile, |
| 191 | }, | 180 | .dirOpenDir = dirOpenDir, |
| 192 | .fileStat = switch (native_os) { | | |
| 193 | .linux => fileStatLinux, | | |
| 194 | .windows => fileStatWindows, | | |
| 195 | .wasi => fileStatWasi, | | |
| 196 | else => fileStatPosix, | | |
| 197 | }, | | |
| 198 | .dirAccess = switch (native_os) { | | |
| 199 | .windows => dirAccessWindows, | | |
| 200 | .wasi => dirAccessWasi, | | |
| 201 | else => dirAccessPosix, | | |
| 202 | }, | | |
| 203 | .dirCreateFile = switch (native_os) { | | |
| 204 | .windows => dirCreateFileWindows, | | |
| 205 | .wasi => dirCreateFileWasi, | | |
| 206 | else => dirCreateFilePosix, | | |
| 207 | }, | | |
| 208 | .dirOpenFile = switch (native_os) { | | |
| 209 | .windows => dirOpenFileWindows, | | |
| 210 | .wasi => dirOpenFileWasi, | | |
| 211 | else => dirOpenFilePosix, | | |
| 212 | }, | | |
| 213 | .dirOpenDir = switch (native_os) { | | |
| 214 | .wasi => dirOpenDirWasi, | | |
| 215 | .haiku => dirOpenDirHaiku, | | |
| 216 | else => dirOpenDirPosix, | | |
| 217 | }, | | |
| 218 | .dirClose = dirClose, | 181 | .dirClose = dirClose, |
| 219 | .fileClose = fileClose, | 182 | .fileClose = fileClose, |
| 220 | .fileWriteStreaming = fileWriteStreaming, | 183 | .fileWriteStreaming = fileWriteStreaming, |
| 221 | .fileWritePositional = fileWritePositional, | 184 | .fileWritePositional = fileWritePositional, |
| 222 | .fileReadStreaming = switch (native_os) { | 185 | .fileReadStreaming = fileReadStreaming, |
| 223 | .windows => fileReadStreamingWindows, | 186 | .fileReadPositional = fileReadPositional, |
| 224 | else => fileReadStreamingPosix, | | |
| 225 | }, | | |
| 226 | .fileReadPositional = switch (native_os) { | | |
| 227 | .windows => fileReadPositionalWindows, | | |
| 228 | else => fileReadPositionalPosix, | | |
| 229 | }, | | |
| 230 | .fileSeekBy = fileSeekBy, | 187 | .fileSeekBy = fileSeekBy, |
| 231 | .fileSeekTo = fileSeekTo, | 188 | .fileSeekTo = fileSeekTo, |
| 232 | .openSelfExe = openSelfExe, | 189 | .openSelfExe = openSelfExe, |
| 233 | | 190 | |
| 234 | .now = switch (native_os) { | 191 | .now = now, |
| 235 | .windows => nowWindows, | 192 | .sleep = sleep, |
| 236 | .wasi => nowWasi, | | |
| 237 | else => nowPosix, | | |
| 238 | }, | | |
| 239 | .sleep = switch (native_os) { | | |
| 240 | .windows => sleepWindows, | | |
| 241 | .wasi => sleepWasi, | | |
| 242 | .linux => sleepLinux, | | |
| 243 | else => sleepPosix, | | |
| 244 | }, | | |
| 245 | | 193 | |
| 246 | .netListenIp = switch (native_os) { | 194 | .netListenIp = switch (native_os) { |
| 247 | .windows => netListenIpWindows, | 195 | .windows => netListenIpWindows, |
| ... | @@ -291,6 +239,73 @@ pub fn io(t: *Threaded) Io { | ... | @@ -291,6 +239,73 @@ pub fn io(t: *Threaded) Io { |
| 291 | }; | 239 | }; |
| 292 | } | 240 | } |
| 293 | | 241 | |
| | 242 | /// Same as `io` but disables all networking functionality, which has |
| | 243 | /// an additional dependency on Windows (ws2_32). |
| | 244 | pub fn ioBasic(t: *Threaded) Io { |
| | 245 | return .{ |
| | 246 | .userdata = t, |
| | 247 | .vtable = &.{ |
| | 248 | .async = async, |
| | 249 | .concurrent = concurrent, |
| | 250 | .await = await, |
| | 251 | .cancel = cancel, |
| | 252 | .cancelRequested = cancelRequested, |
| | 253 | .select = select, |
| | 254 | |
| | 255 | .groupAsync = groupAsync, |
| | 256 | .groupWait = groupWait, |
| | 257 | .groupWaitUncancelable = groupWaitUncancelable, |
| | 258 | .groupCancel = groupCancel, |
| | 259 | |
| | 260 | .mutexLock = mutexLock, |
| | 261 | .mutexLockUncancelable = mutexLockUncancelable, |
| | 262 | .mutexUnlock = mutexUnlock, |
| | 263 | |
| | 264 | .conditionWait = conditionWait, |
| | 265 | .conditionWaitUncancelable = conditionWaitUncancelable, |
| | 266 | .conditionWake = conditionWake, |
| | 267 | |
| | 268 | .dirMake = dirMake, |
| | 269 | .dirMakePath = dirMakePath, |
| | 270 | .dirMakeOpenPath = dirMakeOpenPath, |
| | 271 | .dirStat = dirStat, |
| | 272 | .dirStatPath = dirStatPath, |
| | 273 | .fileStat = fileStat, |
| | 274 | .dirAccess = dirAccess, |
| | 275 | .dirCreateFile = dirCreateFile, |
| | 276 | .dirOpenFile = dirOpenFile, |
| | 277 | .dirOpenDir = dirOpenDir, |
| | 278 | .dirClose = dirClose, |
| | 279 | .fileClose = fileClose, |
| | 280 | .fileWriteStreaming = fileWriteStreaming, |
| | 281 | .fileWritePositional = fileWritePositional, |
| | 282 | .fileReadStreaming = fileReadStreaming, |
| | 283 | .fileReadPositional = fileReadPositional, |
| | 284 | .fileSeekBy = fileSeekBy, |
| | 285 | .fileSeekTo = fileSeekTo, |
| | 286 | .openSelfExe = openSelfExe, |
| | 287 | |
| | 288 | .now = now, |
| | 289 | .sleep = sleep, |
| | 290 | |
| | 291 | .netListenIp = netListenIpUnavailable, |
| | 292 | .netListenUnix = netListenUnixUnavailable, |
| | 293 | .netAccept = netAcceptUnavailable, |
| | 294 | .netBindIp = netBindIpUnavailable, |
| | 295 | .netConnectIp = netConnectIpUnavailable, |
| | 296 | .netConnectUnix = netConnectUnixUnavailable, |
| | 297 | .netClose = netCloseUnavailable, |
| | 298 | .netRead = netReadUnavailable, |
| | 299 | .netWrite = netWriteUnavailable, |
| | 300 | .netSend = netSendUnavailable, |
| | 301 | .netReceive = netReceiveUnavailable, |
| | 302 | .netInterfaceNameResolve = netInterfaceNameResolveUnavailable, |
| | 303 | .netInterfaceName = netInterfaceNameUnavailable, |
| | 304 | .netLookup = netLookupUnavailable, |
| | 305 | }, |
| | 306 | }; |
| | 307 | } |
| | 308 | |
| 294 | pub const socket_flags_unsupported = native_os.isDarwin() or native_os == .haiku; // 💩💩 | 309 | pub const socket_flags_unsupported = native_os.isDarwin() or native_os == .haiku; // 💩💩 |
| 295 | const have_accept4 = !socket_flags_unsupported; | 310 | const have_accept4 = !socket_flags_unsupported; |
| 296 | const have_flock_open_flags = @hasField(posix.O, "EXLOCK"); | 311 | const have_flock_open_flags = @hasField(posix.O, "EXLOCK"); |
| ... | @@ -804,7 +819,7 @@ fn mutexUnlock(userdata: ?*anyopaque, prev_state: Io.Mutex.State, mutex: *Io.Mut | ... | @@ -804,7 +819,7 @@ fn mutexUnlock(userdata: ?*anyopaque, prev_state: Io.Mutex.State, mutex: *Io.Mut |
| 804 | fn conditionWaitUncancelable(userdata: ?*anyopaque, cond: *Io.Condition, mutex: *Io.Mutex) void { | 819 | fn conditionWaitUncancelable(userdata: ?*anyopaque, cond: *Io.Condition, mutex: *Io.Mutex) void { |
| 805 | if (builtin.single_threaded) unreachable; // Deadlock. | 820 | if (builtin.single_threaded) unreachable; // Deadlock. |
| 806 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 821 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 807 | const t_io = t.io(); | 822 | const t_io = ioBasic(t); |
| 808 | comptime assert(@TypeOf(cond.state) == u64); | 823 | comptime assert(@TypeOf(cond.state) == u64); |
| 809 | const ints: *[2]std.atomic.Value(u32) = @ptrCast(&cond.state); | 824 | const ints: *[2]std.atomic.Value(u32) = @ptrCast(&cond.state); |
| 810 | const cond_state = &ints[0]; | 825 | const cond_state = &ints[0]; |
| ... | @@ -835,6 +850,7 @@ fn conditionWaitUncancelable(userdata: ?*anyopaque, cond: *Io.Condition, mutex: | ... | @@ -835,6 +850,7 @@ fn conditionWaitUncancelable(userdata: ?*anyopaque, cond: *Io.Condition, mutex: |
| 835 | fn conditionWait(userdata: ?*anyopaque, cond: *Io.Condition, mutex: *Io.Mutex) Io.Cancelable!void { | 850 | fn conditionWait(userdata: ?*anyopaque, cond: *Io.Condition, mutex: *Io.Mutex) Io.Cancelable!void { |
| 836 | if (builtin.single_threaded) unreachable; // Deadlock. | 851 | if (builtin.single_threaded) unreachable; // Deadlock. |
| 837 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 852 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| | 853 | const t_io = ioBasic(t); |
| 838 | comptime assert(@TypeOf(cond.state) == u64); | 854 | comptime assert(@TypeOf(cond.state) == u64); |
| 839 | const ints: *[2]std.atomic.Value(u32) = @ptrCast(&cond.state); | 855 | const ints: *[2]std.atomic.Value(u32) = @ptrCast(&cond.state); |
| 840 | const cond_state = &ints[0]; | 856 | const cond_state = &ints[0]; |
| ... | @@ -858,8 +874,8 @@ fn conditionWait(userdata: ?*anyopaque, cond: *Io.Condition, mutex: *Io.Mutex) I | ... | @@ -858,8 +874,8 @@ fn conditionWait(userdata: ?*anyopaque, cond: *Io.Condition, mutex: *Io.Mutex) I |
| 858 | assert(state & waiter_mask != waiter_mask); | 874 | assert(state & waiter_mask != waiter_mask); |
| 859 | state += one_waiter; | 875 | state += one_waiter; |
| 860 | | 876 | |
| 861 | mutex.unlock(t.io()); | 877 | mutex.unlock(t_io); |
| 862 | defer mutex.lockUncancelable(t.io()); | 878 | defer mutex.lockUncancelable(t_io); |
| 863 | | 879 | |
| 864 | while (true) { | 880 | while (true) { |
| 865 | try futexWait(t, cond_epoch, epoch); | 881 | try futexWait(t, cond_epoch, epoch); |
| ... | @@ -939,6 +955,12 @@ fn conditionWake(userdata: ?*anyopaque, cond: *Io.Condition, wake: Io.Condition. | ... | @@ -939,6 +955,12 @@ fn conditionWake(userdata: ?*anyopaque, cond: *Io.Condition, wake: Io.Condition. |
| 939 | } | 955 | } |
| 940 | } | 956 | } |
| 941 | | 957 | |
| | 958 | const dirMake = switch (native_os) { |
| | 959 | .windows => dirMakeWindows, |
| | 960 | .wasi => dirMakeWasi, |
| | 961 | else => dirMakePosix, |
| | 962 | }; |
| | 963 | |
| 942 | fn dirMakePosix(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, mode: Io.Dir.Mode) Io.Dir.MakeError!void { | 964 | fn dirMakePosix(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, mode: Io.Dir.Mode) Io.Dir.MakeError!void { |
| 943 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 965 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 944 | | 966 | |
| ... | @@ -1027,6 +1049,11 @@ fn dirMakeWindows(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, mode | ... | @@ -1027,6 +1049,11 @@ fn dirMakeWindows(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, mode |
| 1027 | windows.CloseHandle(sub_dir_handle); | 1049 | windows.CloseHandle(sub_dir_handle); |
| 1028 | } | 1050 | } |
| 1029 | | 1051 | |
| | 1052 | const dirMakePath = switch (native_os) { |
| | 1053 | .windows => dirMakePathWindows, |
| | 1054 | else => dirMakePathPosix, |
| | 1055 | }; |
| | 1056 | |
| 1030 | fn dirMakePathPosix(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, mode: Io.Dir.Mode) Io.Dir.MakeError!void { | 1057 | fn dirMakePathPosix(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, mode: Io.Dir.Mode) Io.Dir.MakeError!void { |
| 1031 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 1058 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 1032 | _ = t; | 1059 | _ = t; |
| ... | @@ -1045,6 +1072,12 @@ fn dirMakePathWindows(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, | ... | @@ -1045,6 +1072,12 @@ fn dirMakePathWindows(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, |
| 1045 | @panic("TODO implement dirMakePathWindows"); | 1072 | @panic("TODO implement dirMakePathWindows"); |
| 1046 | } | 1073 | } |
| 1047 | | 1074 | |
| | 1075 | const dirMakeOpenPath = switch (native_os) { |
| | 1076 | .windows => dirMakeOpenPathWindows, |
| | 1077 | .wasi => dirMakeOpenPathWasi, |
| | 1078 | else => dirMakeOpenPathPosix, |
| | 1079 | }; |
| | 1080 | |
| 1048 | fn dirMakeOpenPathPosix( | 1081 | fn dirMakeOpenPathPosix( |
| 1049 | userdata: ?*anyopaque, | 1082 | userdata: ?*anyopaque, |
| 1050 | dir: Io.Dir, | 1083 | dir: Io.Dir, |
| ... | @@ -1052,11 +1085,11 @@ fn dirMakeOpenPathPosix( | ... | @@ -1052,11 +1085,11 @@ fn dirMakeOpenPathPosix( |
| 1052 | options: Io.Dir.OpenOptions, | 1085 | options: Io.Dir.OpenOptions, |
| 1053 | ) Io.Dir.MakeOpenPathError!Io.Dir { | 1086 | ) Io.Dir.MakeOpenPathError!Io.Dir { |
| 1054 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 1087 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 1055 | const t_io = t.io(); | 1088 | const t_io = ioBasic(t); |
| 1056 | return dir.openDir(t_io, sub_path, options) catch |err| switch (err) { | 1089 | return dirOpenDirPosix(t, dir, sub_path, options) catch |err| switch (err) { |
| 1057 | error.FileNotFound => { | 1090 | error.FileNotFound => { |
| 1058 | try dir.makePath(t_io, sub_path); | 1091 | try dir.makePath(t_io, sub_path); |
| 1059 | return dir.openDir(t_io, sub_path, options); | 1092 | return dirOpenDirPosix(t, dir, sub_path, options); |
| 1060 | }, | 1093 | }, |
| 1061 | else => |e| return e, | 1094 | else => |e| return e, |
| 1062 | }; | 1095 | }; |
| ... | @@ -1135,7 +1168,7 @@ fn dirMakeOpenPathWindows( | ... | @@ -1135,7 +1168,7 @@ fn dirMakeOpenPathWindows( |
| 1135 | // could cause an infinite loop | 1168 | // could cause an infinite loop |
| 1136 | check_dir: { | 1169 | check_dir: { |
| 1137 | // workaround for windows, see https://github.com/ziglang/zig/issues/16738 | 1170 | // workaround for windows, see https://github.com/ziglang/zig/issues/16738 |
| 1138 | const fstat = dir.statPath(t.io(), component.path, .{ | 1171 | const fstat = dirStatPathWindows(t, dir, component.path, .{ |
| 1139 | .follow_symlinks = options.follow_symlinks, | 1172 | .follow_symlinks = options.follow_symlinks, |
| 1140 | }) catch |stat_err| switch (stat_err) { | 1173 | }) catch |stat_err| switch (stat_err) { |
| 1141 | error.IsDir => break :check_dir, | 1174 | error.IsDir => break :check_dir, |
| ... | @@ -1187,6 +1220,13 @@ fn dirStat(userdata: ?*anyopaque, dir: Io.Dir) Io.Dir.StatError!Io.Dir.Stat { | ... | @@ -1187,6 +1220,13 @@ fn dirStat(userdata: ?*anyopaque, dir: Io.Dir) Io.Dir.StatError!Io.Dir.Stat { |
| 1187 | @panic("TODO implement dirStat"); | 1220 | @panic("TODO implement dirStat"); |
| 1188 | } | 1221 | } |
| 1189 | | 1222 | |
| | 1223 | const dirStatPath = switch (native_os) { |
| | 1224 | .linux => dirStatPathLinux, |
| | 1225 | .windows => dirStatPathWindows, |
| | 1226 | .wasi => dirStatPathWasi, |
| | 1227 | else => dirStatPathPosix, |
| | 1228 | }; |
| | 1229 | |
| 1190 | fn dirStatPathLinux( | 1230 | fn dirStatPathLinux( |
| 1191 | userdata: ?*anyopaque, | 1231 | userdata: ?*anyopaque, |
| 1192 | dir: Io.Dir, | 1232 | dir: Io.Dir, |
| ... | @@ -1275,12 +1315,11 @@ fn dirStatPathWindows( | ... | @@ -1275,12 +1315,11 @@ fn dirStatPathWindows( |
| 1275 | options: Io.Dir.StatPathOptions, | 1315 | options: Io.Dir.StatPathOptions, |
| 1276 | ) Io.Dir.StatPathError!Io.File.Stat { | 1316 | ) Io.Dir.StatPathError!Io.File.Stat { |
| 1277 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 1317 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 1278 | const t_io = t.io(); | 1318 | const file = try dirOpenFileWindows(t, dir, sub_path, .{ |
| 1279 | var file = try dir.openFile(t_io, sub_path, .{ | | |
| 1280 | .follow_symlinks = options.follow_symlinks, | 1319 | .follow_symlinks = options.follow_symlinks, |
| 1281 | }); | 1320 | }); |
| 1282 | defer file.close(t_io); | 1321 | defer windows.CloseHandle(file.handle); |
| 1283 | return file.stat(t_io); | 1322 | return fileStatWindows(t, file); |
| 1284 | } | 1323 | } |
| 1285 | | 1324 | |
| 1286 | fn dirStatPathWasi( | 1325 | fn dirStatPathWasi( |
| ... | @@ -1318,6 +1357,13 @@ fn dirStatPathWasi( | ... | @@ -1318,6 +1357,13 @@ fn dirStatPathWasi( |
| 1318 | } | 1357 | } |
| 1319 | } | 1358 | } |
| 1320 | | 1359 | |
| | 1360 | const fileStat = switch (native_os) { |
| | 1361 | .linux => fileStatLinux, |
| | 1362 | .windows => fileStatWindows, |
| | 1363 | .wasi => fileStatWasi, |
| | 1364 | else => fileStatPosix, |
| | 1365 | }; |
| | 1366 | |
| 1321 | fn fileStatPosix(userdata: ?*anyopaque, file: Io.File) Io.File.StatError!Io.File.Stat { | 1367 | fn fileStatPosix(userdata: ?*anyopaque, file: Io.File) Io.File.StatError!Io.File.Stat { |
| 1322 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 1368 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 1323 | | 1369 | |
| ... | @@ -1440,6 +1486,12 @@ fn fileStatWasi(userdata: ?*anyopaque, file: Io.File) Io.File.StatError!Io.File. | ... | @@ -1440,6 +1486,12 @@ fn fileStatWasi(userdata: ?*anyopaque, file: Io.File) Io.File.StatError!Io.File. |
| 1440 | } | 1486 | } |
| 1441 | } | 1487 | } |
| 1442 | | 1488 | |
| | 1489 | const dirAccess = switch (native_os) { |
| | 1490 | .windows => dirAccessWindows, |
| | 1491 | .wasi => dirAccessWasi, |
| | 1492 | else => dirAccessPosix, |
| | 1493 | }; |
| | 1494 | |
| 1443 | fn dirAccessPosix( | 1495 | fn dirAccessPosix( |
| 1444 | userdata: ?*anyopaque, | 1496 | userdata: ?*anyopaque, |
| 1445 | dir: Io.Dir, | 1497 | dir: Io.Dir, |
| ... | @@ -1589,6 +1641,12 @@ fn dirAccessWindows( | ... | @@ -1589,6 +1641,12 @@ fn dirAccessWindows( |
| 1589 | } | 1641 | } |
| 1590 | } | 1642 | } |
| 1591 | | 1643 | |
| | 1644 | const dirCreateFile = switch (native_os) { |
| | 1645 | .windows => dirCreateFileWindows, |
| | 1646 | .wasi => dirCreateFileWasi, |
| | 1647 | else => dirCreateFilePosix, |
| | 1648 | }; |
| | 1649 | |
| 1592 | fn dirCreateFilePosix( | 1650 | fn dirCreateFilePosix( |
| 1593 | userdata: ?*anyopaque, | 1651 | userdata: ?*anyopaque, |
| 1594 | dir: Io.Dir, | 1652 | dir: Io.Dir, |
| ... | @@ -1827,6 +1885,12 @@ fn dirCreateFileWasi( | ... | @@ -1827,6 +1885,12 @@ fn dirCreateFileWasi( |
| 1827 | } | 1885 | } |
| 1828 | } | 1886 | } |
| 1829 | | 1887 | |
| | 1888 | const dirOpenFile = switch (native_os) { |
| | 1889 | .windows => dirOpenFileWindows, |
| | 1890 | .wasi => dirOpenFileWasi, |
| | 1891 | else => dirOpenFilePosix, |
| | 1892 | }; |
| | 1893 | |
| 1830 | fn dirOpenFilePosix( | 1894 | fn dirOpenFilePosix( |
| 1831 | userdata: ?*anyopaque, | 1895 | userdata: ?*anyopaque, |
| 1832 | dir: Io.Dir, | 1896 | dir: Io.Dir, |
| ... | @@ -2077,6 +2141,12 @@ fn dirOpenFileWasi( | ... | @@ -2077,6 +2141,12 @@ fn dirOpenFileWasi( |
| 2077 | } | 2141 | } |
| 2078 | } | 2142 | } |
| 2079 | | 2143 | |
| | 2144 | const dirOpenDir = switch (native_os) { |
| | 2145 | .wasi => dirOpenDirWasi, |
| | 2146 | .haiku => dirOpenDirHaiku, |
| | 2147 | else => dirOpenDirPosix, |
| | 2148 | }; |
| | 2149 | |
| 2080 | fn dirOpenDirPosix( | 2150 | fn dirOpenDirPosix( |
| 2081 | userdata: ?*anyopaque, | 2151 | userdata: ?*anyopaque, |
| 2082 | dir: Io.Dir, | 2152 | dir: Io.Dir, |
| ... | @@ -2320,6 +2390,11 @@ fn fileClose(userdata: ?*anyopaque, file: Io.File) void { | ... | @@ -2320,6 +2390,11 @@ fn fileClose(userdata: ?*anyopaque, file: Io.File) void { |
| 2320 | posix.close(file.handle); | 2390 | posix.close(file.handle); |
| 2321 | } | 2391 | } |
| 2322 | | 2392 | |
| | 2393 | const fileReadStreaming = switch (native_os) { |
| | 2394 | .windows => fileReadStreamingWindows, |
| | 2395 | else => fileReadStreamingPosix, |
| | 2396 | }; |
| | 2397 | |
| 2323 | fn fileReadStreamingPosix(userdata: ?*anyopaque, file: Io.File, data: [][]u8) Io.File.ReadStreamingError!usize { | 2398 | fn fileReadStreamingPosix(userdata: ?*anyopaque, file: Io.File, data: [][]u8) Io.File.ReadStreamingError!usize { |
| 2324 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 2399 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 2325 | | 2400 | |
| ... | @@ -2482,6 +2557,11 @@ fn fileReadPositionalPosix(userdata: ?*anyopaque, file: Io.File, data: [][]u8, o | ... | @@ -2482,6 +2557,11 @@ fn fileReadPositionalPosix(userdata: ?*anyopaque, file: Io.File, data: [][]u8, o |
| 2482 | } | 2557 | } |
| 2483 | } | 2558 | } |
| 2484 | | 2559 | |
| | 2560 | const fileReadPositional = switch (native_os) { |
| | 2561 | .windows => fileReadPositionalWindows, |
| | 2562 | else => fileReadPositionalPosix, |
| | 2563 | }; |
| | 2564 | |
| 2485 | fn fileReadPositionalWindows(userdata: ?*anyopaque, file: Io.File, data: [][]u8, offset: u64) Io.File.ReadPositionalError!usize { | 2565 | fn fileReadPositionalWindows(userdata: ?*anyopaque, file: Io.File, data: [][]u8, offset: u64) Io.File.ReadPositionalError!usize { |
| 2486 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 2566 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 2487 | try t.checkCancel(); | 2567 | try t.checkCancel(); |
| ... | @@ -2652,6 +2732,12 @@ fn nowPosix(userdata: ?*anyopaque, clock: Io.Clock) Io.Clock.Error!Io.Timestamp | ... | @@ -2652,6 +2732,12 @@ fn nowPosix(userdata: ?*anyopaque, clock: Io.Clock) Io.Clock.Error!Io.Timestamp |
| 2652 | } | 2732 | } |
| 2653 | } | 2733 | } |
| 2654 | | 2734 | |
| | 2735 | const now = switch (native_os) { |
| | 2736 | .windows => nowWindows, |
| | 2737 | .wasi => nowWasi, |
| | 2738 | else => nowPosix, |
| | 2739 | }; |
| | 2740 | |
| 2655 | fn nowWindows(userdata: ?*anyopaque, clock: Io.Clock) Io.Clock.Error!Io.Timestamp { | 2741 | fn nowWindows(userdata: ?*anyopaque, clock: Io.Clock) Io.Clock.Error!Io.Timestamp { |
| 2656 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 2742 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 2657 | _ = t; | 2743 | _ = t; |
| ... | @@ -2680,6 +2766,13 @@ fn nowWasi(userdata: ?*anyopaque, clock: Io.Clock) Io.Clock.Error!Io.Timestamp { | ... | @@ -2680,6 +2766,13 @@ fn nowWasi(userdata: ?*anyopaque, clock: Io.Clock) Io.Clock.Error!Io.Timestamp { |
| 2680 | return .fromNanoseconds(ns); | 2766 | return .fromNanoseconds(ns); |
| 2681 | } | 2767 | } |
| 2682 | | 2768 | |
| | 2769 | const sleep = switch (native_os) { |
| | 2770 | .windows => sleepWindows, |
| | 2771 | .wasi => sleepWasi, |
| | 2772 | .linux => sleepLinux, |
| | 2773 | else => sleepPosix, |
| | 2774 | }; |
| | 2775 | |
| 2683 | fn sleepLinux(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void { | 2776 | fn sleepLinux(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void { |
| 2684 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 2777 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 2685 | const clock_id: posix.clockid_t = clockToPosix(switch (timeout) { | 2778 | const clock_id: posix.clockid_t = clockToPosix(switch (timeout) { |
| ... | @@ -2710,9 +2803,10 @@ fn sleepLinux(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void { | ... | @@ -2710,9 +2803,10 @@ fn sleepLinux(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void { |
| 2710 | | 2803 | |
| 2711 | fn sleepWindows(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void { | 2804 | fn sleepWindows(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void { |
| 2712 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 2805 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| | 2806 | const t_io = ioBasic(t); |
| 2713 | try t.checkCancel(); | 2807 | try t.checkCancel(); |
| 2714 | const ms = ms: { | 2808 | const ms = ms: { |
| 2715 | const d = (try timeout.toDurationFromNow(t.io())) orelse | 2809 | const d = (try timeout.toDurationFromNow(t_io)) orelse |
| 2716 | break :ms std.math.maxInt(windows.DWORD); | 2810 | break :ms std.math.maxInt(windows.DWORD); |
| 2717 | break :ms std.math.lossyCast(windows.DWORD, d.raw.toMilliseconds()); | 2811 | break :ms std.math.lossyCast(windows.DWORD, d.raw.toMilliseconds()); |
| 2718 | }; | 2812 | }; |
| ... | @@ -2721,11 +2815,12 @@ fn sleepWindows(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void { | ... | @@ -2721,11 +2815,12 @@ fn sleepWindows(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void { |
| 2721 | | 2815 | |
| 2722 | fn sleepWasi(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void { | 2816 | fn sleepWasi(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void { |
| 2723 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 2817 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| | 2818 | const t_io = ioBasic(t); |
| 2724 | try t.checkCancel(); | 2819 | try t.checkCancel(); |
| 2725 | | 2820 | |
| 2726 | const w = std.os.wasi; | 2821 | const w = std.os.wasi; |
| 2727 | | 2822 | |
| 2728 | const clock: w.subscription_clock_t = if (try timeout.toDurationFromNow(t.io())) |d| .{ | 2823 | const clock: w.subscription_clock_t = if (try timeout.toDurationFromNow(t_io)) |d| .{ |
| 2729 | .id = clockToWasi(d.clock), | 2824 | .id = clockToWasi(d.clock), |
| 2730 | .timeout = std.math.lossyCast(u64, d.raw.nanoseconds), | 2825 | .timeout = std.math.lossyCast(u64, d.raw.nanoseconds), |
| 2731 | .precision = 0, | 2826 | .precision = 0, |
| ... | @@ -2750,11 +2845,12 @@ fn sleepWasi(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void { | ... | @@ -2750,11 +2845,12 @@ fn sleepWasi(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void { |
| 2750 | | 2845 | |
| 2751 | fn sleepPosix(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void { | 2846 | fn sleepPosix(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void { |
| 2752 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 2847 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| | 2848 | const t_io = ioBasic(t); |
| 2753 | const sec_type = @typeInfo(posix.timespec).@"struct".fields[0].type; | 2849 | const sec_type = @typeInfo(posix.timespec).@"struct".fields[0].type; |
| 2754 | const nsec_type = @typeInfo(posix.timespec).@"struct".fields[1].type; | 2850 | const nsec_type = @typeInfo(posix.timespec).@"struct".fields[1].type; |
| 2755 | | 2851 | |
| 2756 | var timespec: posix.timespec = t: { | 2852 | var timespec: posix.timespec = t: { |
| 2757 | const d = (try timeout.toDurationFromNow(t.io())) orelse break :t .{ | 2853 | const d = (try timeout.toDurationFromNow(t_io)) orelse break :t .{ |
| 2758 | .sec = std.math.maxInt(sec_type), | 2854 | .sec = std.math.maxInt(sec_type), |
| 2759 | .nsec = std.math.maxInt(nsec_type), | 2855 | .nsec = std.math.maxInt(nsec_type), |
| 2760 | }; | 2856 | }; |
| ... | @@ -2919,6 +3015,17 @@ fn netListenIpWindows( | ... | @@ -2919,6 +3015,17 @@ fn netListenIpWindows( |
| 2919 | }; | 3015 | }; |
| 2920 | } | 3016 | } |
| 2921 | | 3017 | |
| | 3018 | fn netListenIpUnavailable( |
| | 3019 | userdata: ?*anyopaque, |
| | 3020 | address: IpAddress, |
| | 3021 | options: IpAddress.ListenOptions, |
| | 3022 | ) IpAddress.ListenError!net.Server { |
| | 3023 | _ = userdata; |
| | 3024 | _ = address; |
| | 3025 | _ = options; |
| | 3026 | return error.NetworkDown; |
| | 3027 | } |
| | 3028 | |
| 2922 | fn netListenUnixPosix( | 3029 | fn netListenUnixPosix( |
| 2923 | userdata: ?*anyopaque, | 3030 | userdata: ?*anyopaque, |
| 2924 | address: *const net.UnixAddress, | 3031 | address: *const net.UnixAddress, |
| ... | @@ -2965,6 +3072,17 @@ fn netListenUnixWindows( | ... | @@ -2965,6 +3072,17 @@ fn netListenUnixWindows( |
| 2965 | @panic("TODO implement netListenUnixWindows"); | 3072 | @panic("TODO implement netListenUnixWindows"); |
| 2966 | } | 3073 | } |
| 2967 | | 3074 | |
| | 3075 | fn netListenUnixUnavailable( |
| | 3076 | userdata: ?*anyopaque, |
| | 3077 | address: *const net.UnixAddress, |
| | 3078 | options: net.UnixAddress.ListenOptions, |
| | 3079 | ) net.UnixAddress.ListenError!net.Socket.Handle { |
| | 3080 | _ = userdata; |
| | 3081 | _ = address; |
| | 3082 | _ = options; |
| | 3083 | return error.AddressFamilyUnsupported; |
| | 3084 | } |
| | 3085 | |
| 2968 | fn posixBindUnix(t: *Threaded, fd: posix.socket_t, addr: *const posix.sockaddr, addr_len: posix.socklen_t) !void { | 3086 | fn posixBindUnix(t: *Threaded, fd: posix.socket_t, addr: *const posix.sockaddr, addr_len: posix.socklen_t) !void { |
| 2969 | while (true) { | 3087 | while (true) { |
| 2970 | try t.checkCancel(); | 3088 | try t.checkCancel(); |
| ... | @@ -3235,6 +3353,17 @@ fn netConnectIpWindows( | ... | @@ -3235,6 +3353,17 @@ fn netConnectIpWindows( |
| 3235 | } }; | 3353 | } }; |
| 3236 | } | 3354 | } |
| 3237 | | 3355 | |
| | 3356 | fn netConnectIpUnavailable( |
| | 3357 | userdata: ?*anyopaque, |
| | 3358 | address: *const IpAddress, |
| | 3359 | options: IpAddress.ConnectOptions, |
| | 3360 | ) IpAddress.ConnectError!net.Stream { |
| | 3361 | _ = userdata; |
| | 3362 | _ = address; |
| | 3363 | _ = options; |
| | 3364 | return error.NetworkDown; |
| | 3365 | } |
| | 3366 | |
| 3238 | fn netConnectUnixPosix( | 3367 | fn netConnectUnixPosix( |
| 3239 | userdata: ?*anyopaque, | 3368 | userdata: ?*anyopaque, |
| 3240 | address: *const net.UnixAddress, | 3369 | address: *const net.UnixAddress, |
| ... | @@ -3263,6 +3392,15 @@ fn netConnectUnixWindows( | ... | @@ -3263,6 +3392,15 @@ fn netConnectUnixWindows( |
| 3263 | @panic("TODO implement netConnectUnixWindows"); | 3392 | @panic("TODO implement netConnectUnixWindows"); |
| 3264 | } | 3393 | } |
| 3265 | | 3394 | |
| | 3395 | fn netConnectUnixUnavailable( |
| | 3396 | userdata: ?*anyopaque, |
| | 3397 | address: *const net.UnixAddress, |
| | 3398 | ) net.UnixAddress.ConnectError!net.Socket.Handle { |
| | 3399 | _ = userdata; |
| | 3400 | _ = address; |
| | 3401 | return error.AddressFamilyUnsupported; |
| | 3402 | } |
| | 3403 | |
| 3266 | fn netBindIpPosix( | 3404 | fn netBindIpPosix( |
| 3267 | userdata: ?*anyopaque, | 3405 | userdata: ?*anyopaque, |
| 3268 | address: *const IpAddress, | 3406 | address: *const IpAddress, |
| ... | @@ -3330,6 +3468,17 @@ fn netBindIpWindows( | ... | @@ -3330,6 +3468,17 @@ fn netBindIpWindows( |
| 3330 | }; | 3468 | }; |
| 3331 | } | 3469 | } |
| 3332 | | 3470 | |
| | 3471 | fn netBindIpUnavailable( |
| | 3472 | userdata: ?*anyopaque, |
| | 3473 | address: *const IpAddress, |
| | 3474 | options: IpAddress.BindOptions, |
| | 3475 | ) IpAddress.BindError!net.Socket { |
| | 3476 | _ = userdata; |
| | 3477 | _ = address; |
| | 3478 | _ = options; |
| | 3479 | return error.NetworkDown; |
| | 3480 | } |
| | 3481 | |
| 3333 | fn openSocketPosix( | 3482 | fn openSocketPosix( |
| 3334 | t: *Threaded, | 3483 | t: *Threaded, |
| 3335 | family: posix.sa_family_t, | 3484 | family: posix.sa_family_t, |
| ... | @@ -3498,7 +3647,14 @@ fn netAcceptWindows(userdata: ?*anyopaque, listen_handle: net.Socket.Handle) net | ... | @@ -3498,7 +3647,14 @@ fn netAcceptWindows(userdata: ?*anyopaque, listen_handle: net.Socket.Handle) net |
| 3498 | } | 3647 | } |
| 3499 | } | 3648 | } |
| 3500 | | 3649 | |
| | 3650 | fn netAcceptUnavailable(userdata: ?*anyopaque, listen_handle: net.Socket.Handle) net.Server.AcceptError!net.Stream { |
| | 3651 | _ = userdata; |
| | 3652 | _ = listen_handle; |
| | 3653 | return error.NetworkDown; |
| | 3654 | } |
| | 3655 | |
| 3501 | fn netReadPosix(userdata: ?*anyopaque, fd: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize { | 3656 | fn netReadPosix(userdata: ?*anyopaque, fd: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize { |
| | 3657 | if (!have_networking) return error.NetworkDown; |
| 3502 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 3658 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 3503 | | 3659 | |
| 3504 | var iovecs_buffer: [max_iovecs_len]posix.iovec = undefined; | 3660 | var iovecs_buffer: [max_iovecs_len]posix.iovec = undefined; |
| ... | @@ -3560,7 +3716,7 @@ fn netReadPosix(userdata: ?*anyopaque, fd: net.Socket.Handle, data: [][]u8) net. | ... | @@ -3560,7 +3716,7 @@ fn netReadPosix(userdata: ?*anyopaque, fd: net.Socket.Handle, data: [][]u8) net. |
| 3560 | } | 3716 | } |
| 3561 | | 3717 | |
| 3562 | fn netReadWindows(userdata: ?*anyopaque, handle: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize { | 3718 | fn netReadWindows(userdata: ?*anyopaque, handle: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize { |
| 3563 | if (!have_networking) return .{ error.NetworkDown, 0 }; | 3719 | if (!have_networking) return error.NetworkDown; |
| 3564 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 3720 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 3565 | _ = t; | 3721 | _ = t; |
| 3566 | _ = handle; | 3722 | _ = handle; |
| ... | @@ -3568,6 +3724,13 @@ fn netReadWindows(userdata: ?*anyopaque, handle: net.Socket.Handle, data: [][]u8 | ... | @@ -3568,6 +3724,13 @@ fn netReadWindows(userdata: ?*anyopaque, handle: net.Socket.Handle, data: [][]u8 |
| 3568 | @panic("TODO implement netReadWindows"); | 3724 | @panic("TODO implement netReadWindows"); |
| 3569 | } | 3725 | } |
| 3570 | | 3726 | |
| | 3727 | fn netReadUnavailable(userdata: ?*anyopaque, fd: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize { |
| | 3728 | _ = userdata; |
| | 3729 | _ = fd; |
| | 3730 | _ = data; |
| | 3731 | return error.NetworkDown; |
| | 3732 | } |
| | 3733 | |
| 3571 | fn netSendPosix( | 3734 | fn netSendPosix( |
| 3572 | userdata: ?*anyopaque, | 3735 | userdata: ?*anyopaque, |
| 3573 | handle: net.Socket.Handle, | 3736 | handle: net.Socket.Handle, |
| ... | @@ -3612,6 +3775,19 @@ fn netSendWindows( | ... | @@ -3612,6 +3775,19 @@ fn netSendWindows( |
| 3612 | @panic("TODO netSendWindows"); | 3775 | @panic("TODO netSendWindows"); |
| 3613 | } | 3776 | } |
| 3614 | | 3777 | |
| | 3778 | fn netSendUnavailable( |
| | 3779 | userdata: ?*anyopaque, |
| | 3780 | handle: net.Socket.Handle, |
| | 3781 | messages: []net.OutgoingMessage, |
| | 3782 | flags: net.SendFlags, |
| | 3783 | ) struct { ?net.Socket.SendError, usize } { |
| | 3784 | _ = userdata; |
| | 3785 | _ = handle; |
| | 3786 | _ = messages; |
| | 3787 | _ = flags; |
| | 3788 | return .{ error.NetworkDown, 0 }; |
| | 3789 | } |
| | 3790 | |
| 3615 | fn netSendOne( | 3791 | fn netSendOne( |
| 3616 | t: *Threaded, | 3792 | t: *Threaded, |
| 3617 | handle: net.Socket.Handle, | 3793 | handle: net.Socket.Handle, |
| ... | @@ -3777,6 +3953,7 @@ fn netReceivePosix( | ... | @@ -3777,6 +3953,7 @@ fn netReceivePosix( |
| 3777 | ) struct { ?net.Socket.ReceiveTimeoutError, usize } { | 3953 | ) struct { ?net.Socket.ReceiveTimeoutError, usize } { |
| 3778 | if (!have_networking) return .{ error.NetworkDown, 0 }; | 3954 | if (!have_networking) return .{ error.NetworkDown, 0 }; |
| 3779 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 3955 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| | 3956 | const t_io = io(t); |
| 3780 | | 3957 | |
| 3781 | // recvmmsg is useless, here's why: | 3958 | // recvmmsg is useless, here's why: |
| 3782 | // * [timeout bug](https://bugzilla.kernel.org/show_bug.cgi?id=75371) | 3959 | // * [timeout bug](https://bugzilla.kernel.org/show_bug.cgi?id=75371) |
| ... | @@ -3803,7 +3980,7 @@ fn netReceivePosix( | ... | @@ -3803,7 +3980,7 @@ fn netReceivePosix( |
| 3803 | var message_i: usize = 0; | 3980 | var message_i: usize = 0; |
| 3804 | var data_i: usize = 0; | 3981 | var data_i: usize = 0; |
| 3805 | | 3982 | |
| 3806 | const deadline = timeout.toDeadline(t.io()) catch |err| return .{ err, message_i }; | 3983 | const deadline = timeout.toDeadline(t_io) catch |err| return .{ err, message_i }; |
| 3807 | | 3984 | |
| 3808 | recv: while (true) { | 3985 | recv: while (true) { |
| 3809 | t.checkCancel() catch |err| return .{ err, message_i }; | 3986 | t.checkCancel() catch |err| return .{ err, message_i }; |
| ... | @@ -3849,7 +4026,7 @@ fn netReceivePosix( | ... | @@ -3849,7 +4026,7 @@ fn netReceivePosix( |
| 3849 | | 4026 | |
| 3850 | const max_poll_ms = std.math.maxInt(u31); | 4027 | const max_poll_ms = std.math.maxInt(u31); |
| 3851 | const timeout_ms: u31 = if (deadline) |d| t: { | 4028 | const timeout_ms: u31 = if (deadline) |d| t: { |
| 3852 | const duration = d.durationFromNow(t.io()) catch |err| return .{ err, message_i }; | 4029 | const duration = d.durationFromNow(t_io) catch |err| return .{ err, message_i }; |
| 3853 | if (duration.raw.nanoseconds <= 0) return .{ error.Timeout, message_i }; | 4030 | if (duration.raw.nanoseconds <= 0) return .{ error.Timeout, message_i }; |
| 3854 | break :t @intCast(@min(max_poll_ms, duration.raw.toMilliseconds())); | 4031 | break :t @intCast(@min(max_poll_ms, duration.raw.toMilliseconds())); |
| 3855 | } else max_poll_ms; | 4032 | } else max_poll_ms; |
| ... | @@ -3915,6 +4092,23 @@ fn netReceiveWindows( | ... | @@ -3915,6 +4092,23 @@ fn netReceiveWindows( |
| 3915 | @panic("TODO implement netReceiveWindows"); | 4092 | @panic("TODO implement netReceiveWindows"); |
| 3916 | } | 4093 | } |
| 3917 | | 4094 | |
| | 4095 | fn netReceiveUnavailable( |
| | 4096 | userdata: ?*anyopaque, |
| | 4097 | handle: net.Socket.Handle, |
| | 4098 | message_buffer: []net.IncomingMessage, |
| | 4099 | data_buffer: []u8, |
| | 4100 | flags: net.ReceiveFlags, |
| | 4101 | timeout: Io.Timeout, |
| | 4102 | ) struct { ?net.Socket.ReceiveTimeoutError, usize } { |
| | 4103 | _ = userdata; |
| | 4104 | _ = handle; |
| | 4105 | _ = message_buffer; |
| | 4106 | _ = data_buffer; |
| | 4107 | _ = flags; |
| | 4108 | _ = timeout; |
| | 4109 | return .{ error.NetworkDown, 0 }; |
| | 4110 | } |
| | 4111 | |
| 3918 | fn netWritePosix( | 4112 | fn netWritePosix( |
| 3919 | userdata: ?*anyopaque, | 4113 | userdata: ?*anyopaque, |
| 3920 | fd: net.Socket.Handle, | 4114 | fd: net.Socket.Handle, |
| ... | @@ -4013,6 +4207,21 @@ fn netWriteWindows( | ... | @@ -4013,6 +4207,21 @@ fn netWriteWindows( |
| 4013 | @panic("TODO implement netWriteWindows"); | 4207 | @panic("TODO implement netWriteWindows"); |
| 4014 | } | 4208 | } |
| 4015 | | 4209 | |
| | 4210 | fn netWriteUnavailable( |
| | 4211 | userdata: ?*anyopaque, |
| | 4212 | handle: net.Socket.Handle, |
| | 4213 | header: []const u8, |
| | 4214 | data: []const []const u8, |
| | 4215 | splat: usize, |
| | 4216 | ) net.Stream.Writer.Error!usize { |
| | 4217 | _ = userdata; |
| | 4218 | _ = handle; |
| | 4219 | _ = header; |
| | 4220 | _ = data; |
| | 4221 | _ = splat; |
| | 4222 | return error.NetworkDown; |
| | 4223 | } |
| | 4224 | |
| 4016 | fn addBuf(v: []posix.iovec_const, i: *@FieldType(posix.msghdr_const, "iovlen"), bytes: []const u8) void { | 4225 | fn addBuf(v: []posix.iovec_const, i: *@FieldType(posix.msghdr_const, "iovlen"), bytes: []const u8) void { |
| 4017 | // OS checks ptr addr before length so zero length vectors must be omitted. | 4226 | // OS checks ptr addr before length so zero length vectors must be omitted. |
| 4018 | if (bytes.len == 0) return; | 4227 | if (bytes.len == 0) return; |
| ... | @@ -4030,6 +4239,12 @@ fn netClose(userdata: ?*anyopaque, handle: net.Socket.Handle) void { | ... | @@ -4030,6 +4239,12 @@ fn netClose(userdata: ?*anyopaque, handle: net.Socket.Handle) void { |
| 4030 | } | 4239 | } |
| 4031 | } | 4240 | } |
| 4032 | | 4241 | |
| | 4242 | fn netCloseUnavailable(userdata: ?*anyopaque, handle: net.Socket.Handle) void { |
| | 4243 | _ = userdata; |
| | 4244 | _ = handle; |
| | 4245 | unreachable; // How you gonna close something that was impossible to open? |
| | 4246 | } |
| | 4247 | |
| 4033 | fn netInterfaceNameResolve( | 4248 | fn netInterfaceNameResolve( |
| 4034 | userdata: ?*anyopaque, | 4249 | userdata: ?*anyopaque, |
| 4035 | name: *const net.Interface.Name, | 4250 | name: *const net.Interface.Name, |
| ... | @@ -4089,6 +4304,15 @@ fn netInterfaceNameResolve( | ... | @@ -4089,6 +4304,15 @@ fn netInterfaceNameResolve( |
| 4089 | @panic("unimplemented"); | 4304 | @panic("unimplemented"); |
| 4090 | } | 4305 | } |
| 4091 | | 4306 | |
| | 4307 | fn netInterfaceNameResolveUnavailable( |
| | 4308 | userdata: ?*anyopaque, |
| | 4309 | name: *const net.Interface.Name, |
| | 4310 | ) net.Interface.Name.ResolveError!net.Interface { |
| | 4311 | _ = userdata; |
| | 4312 | _ = name; |
| | 4313 | return error.InterfaceNotFound; |
| | 4314 | } |
| | 4315 | |
| 4092 | fn netInterfaceName(userdata: ?*anyopaque, interface: net.Interface) net.Interface.NameError!net.Interface.Name { | 4316 | fn netInterfaceName(userdata: ?*anyopaque, interface: net.Interface) net.Interface.NameError!net.Interface.Name { |
| 4093 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 4317 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 4094 | try t.checkCancel(); | 4318 | try t.checkCancel(); |
| ... | @@ -4109,6 +4333,12 @@ fn netInterfaceName(userdata: ?*anyopaque, interface: net.Interface) net.Interfa | ... | @@ -4109,6 +4333,12 @@ fn netInterfaceName(userdata: ?*anyopaque, interface: net.Interface) net.Interfa |
| 4109 | @panic("unimplemented"); | 4333 | @panic("unimplemented"); |
| 4110 | } | 4334 | } |
| 4111 | | 4335 | |
| | 4336 | fn netInterfaceNameUnavailable(userdata: ?*anyopaque, interface: net.Interface) net.Interface.NameError!net.Interface.Name { |
| | 4337 | _ = userdata; |
| | 4338 | _ = interface; |
| | 4339 | return error.Unexpected; |
| | 4340 | } |
| | 4341 | |
| 4112 | fn netLookup( | 4342 | fn netLookup( |
| 4113 | userdata: ?*anyopaque, | 4343 | userdata: ?*anyopaque, |
| 4114 | host_name: HostName, | 4344 | host_name: HostName, |
| ... | @@ -4116,17 +4346,31 @@ fn netLookup( | ... | @@ -4116,17 +4346,31 @@ fn netLookup( |
| 4116 | options: HostName.LookupOptions, | 4346 | options: HostName.LookupOptions, |
| 4117 | ) void { | 4347 | ) void { |
| 4118 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 4348 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 4119 | const t_io = t.io(); | 4349 | const t_io = io(t); |
| 4120 | resolved.putOneUncancelable(t_io, .{ .end = netLookupFallible(t, host_name, resolved, options) }); | 4350 | resolved.putOneUncancelable(t_io, .{ .end = netLookupFallible(t, host_name, resolved, options) }); |
| 4121 | } | 4351 | } |
| 4122 | | 4352 | |
| | 4353 | fn netLookupUnavailable( |
| | 4354 | userdata: ?*anyopaque, |
| | 4355 | host_name: HostName, |
| | 4356 | resolved: *Io.Queue(HostName.LookupResult), |
| | 4357 | options: HostName.LookupOptions, |
| | 4358 | ) void { |
| | 4359 | _ = host_name; |
| | 4360 | _ = options; |
| | 4361 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| | 4362 | const t_io = ioBasic(t); |
| | 4363 | resolved.putOneUncancelable(t_io, .{ .end = error.NetworkDown }); |
| | 4364 | } |
| | 4365 | |
| 4123 | fn netLookupFallible( | 4366 | fn netLookupFallible( |
| 4124 | t: *Threaded, | 4367 | t: *Threaded, |
| 4125 | host_name: HostName, | 4368 | host_name: HostName, |
| 4126 | resolved: *Io.Queue(HostName.LookupResult), | 4369 | resolved: *Io.Queue(HostName.LookupResult), |
| 4127 | options: HostName.LookupOptions, | 4370 | options: HostName.LookupOptions, |
| 4128 | ) !void { | 4371 | ) !void { |
| 4129 | const t_io = t.io(); | 4372 | if (!have_networking) return error.NetworkDown; |
| | 4373 | const t_io = io(t); |
| 4130 | const name = host_name.bytes; | 4374 | const name = host_name.bytes; |
| 4131 | assert(name.len <= HostName.max_len); | 4375 | assert(name.len <= HostName.max_len); |
| 4132 | | 4376 | |
| ... | @@ -4637,7 +4881,7 @@ fn lookupDnsSearch( | ... | @@ -4637,7 +4881,7 @@ fn lookupDnsSearch( |
| 4637 | resolved: *Io.Queue(HostName.LookupResult), | 4881 | resolved: *Io.Queue(HostName.LookupResult), |
| 4638 | options: HostName.LookupOptions, | 4882 | options: HostName.LookupOptions, |
| 4639 | ) HostName.LookupError!void { | 4883 | ) HostName.LookupError!void { |
| 4640 | const t_io = t.io(); | 4884 | const t_io = io(t); |
| 4641 | const rc = HostName.ResolvConf.init(t_io) catch return error.ResolvConfParseFailed; | 4885 | const rc = HostName.ResolvConf.init(t_io) catch return error.ResolvConfParseFailed; |
| 4642 | | 4886 | |
| 4643 | // Count dots, suppress search when >=ndots or name ends in | 4887 | // Count dots, suppress search when >=ndots or name ends in |
| ... | @@ -4681,7 +4925,7 @@ fn lookupDns( | ... | @@ -4681,7 +4925,7 @@ fn lookupDns( |
| 4681 | resolved: *Io.Queue(HostName.LookupResult), | 4925 | resolved: *Io.Queue(HostName.LookupResult), |
| 4682 | options: HostName.LookupOptions, | 4926 | options: HostName.LookupOptions, |
| 4683 | ) HostName.LookupError!void { | 4927 | ) HostName.LookupError!void { |
| 4684 | const t_io = t.io(); | 4928 | const t_io = io(t); |
| 4685 | const family_records: [2]struct { af: IpAddress.Family, rr: HostName.DnsRecord } = .{ | 4929 | const family_records: [2]struct { af: IpAddress.Family, rr: HostName.DnsRecord } = .{ |
| 4686 | .{ .af = .ip6, .rr = .A }, | 4930 | .{ .af = .ip6, .rr = .A }, |
| 4687 | .{ .af = .ip4, .rr = .AAAA }, | 4931 | .{ .af = .ip4, .rr = .AAAA }, |
| ... | @@ -4868,7 +5112,7 @@ fn lookupHosts( | ... | @@ -4868,7 +5112,7 @@ fn lookupHosts( |
| 4868 | resolved: *Io.Queue(HostName.LookupResult), | 5112 | resolved: *Io.Queue(HostName.LookupResult), |
| 4869 | options: HostName.LookupOptions, | 5113 | options: HostName.LookupOptions, |
| 4870 | ) !void { | 5114 | ) !void { |
| 4871 | const t_io = t.io(); | 5115 | const t_io = io(t); |
| 4872 | const file = Io.File.openAbsolute(t_io, "/etc/hosts", .{}) catch |err| switch (err) { | 5116 | const file = Io.File.openAbsolute(t_io, "/etc/hosts", .{}) catch |err| switch (err) { |
| 4873 | error.FileNotFound, | 5117 | error.FileNotFound, |
| 4874 | error.NotDir, | 5118 | error.NotDir, |
| ... | @@ -4906,7 +5150,7 @@ fn lookupHostsReader( | ... | @@ -4906,7 +5150,7 @@ fn lookupHostsReader( |
| 4906 | options: HostName.LookupOptions, | 5150 | options: HostName.LookupOptions, |
| 4907 | reader: *Io.Reader, | 5151 | reader: *Io.Reader, |
| 4908 | ) error{ ReadFailed, Canceled, UnknownHostName }!void { | 5152 | ) error{ ReadFailed, Canceled, UnknownHostName }!void { |
| 4909 | const t_io = t.io(); | 5153 | const t_io = io(t); |
| 4910 | var addresses_len: usize = 0; | 5154 | var addresses_len: usize = 0; |
| 4911 | var canonical_name: ?HostName = null; | 5155 | var canonical_name: ?HostName = null; |
| 4912 | while (true) { | 5156 | while (true) { |
| ... | @@ -5374,7 +5618,7 @@ const Wsa = struct { | ... | @@ -5374,7 +5618,7 @@ const Wsa = struct { |
| 5374 | }; | 5618 | }; |
| 5375 | | 5619 | |
| 5376 | fn initializeWsa(t: *Threaded) error{NetworkDown}!void { | 5620 | fn initializeWsa(t: *Threaded) error{NetworkDown}!void { |
| 5377 | const t_io = t.io(); | 5621 | const t_io = io(t); |
| 5378 | const wsa = &t.wsa; | 5622 | const wsa = &t.wsa; |
| 5379 | wsa.mutex.lockUncancelable(t_io); | 5623 | wsa.mutex.lockUncancelable(t_io); |
| 5380 | defer wsa.mutex.unlock(t_io); | 5624 | defer wsa.mutex.unlock(t_io); |