| ... | @@ -124,8 +124,19 @@ pub fn io(pool: *Pool) Io { | ... | @@ -124,8 +124,19 @@ pub fn io(pool: *Pool) Io { |
| 124 | .now = now, | 124 | .now = now, |
| 125 | .sleep = sleep, | 125 | .sleep = sleep, |
| 126 | | 126 | |
| 127 | .listen = listen, | 127 | .listen = switch (builtin.os.tag) { |
| 128 | .accept = accept, | 128 | .windows => @panic("TODO"), |
| | 129 | else => listenPosix, |
| | 130 | }, |
| | 131 | .accept = switch (builtin.os.tag) { |
| | 132 | .windows => @panic("TODO"), |
| | 133 | else => acceptPosix, |
| | 134 | }, |
| | 135 | .ipBind = switch (builtin.os.tag) { |
| | 136 | .windows => @panic("TODO"), |
| | 137 | else => ipBindPosix, |
| | 138 | }, |
| | 139 | .netClose = netClose, |
| 129 | .netRead = switch (builtin.os.tag) { | 140 | .netRead = switch (builtin.os.tag) { |
| 130 | .windows => @panic("TODO"), | 141 | .windows => @panic("TODO"), |
| 131 | else => netReadPosix, | 142 | else => netReadPosix, |
| ... | @@ -134,7 +145,8 @@ pub fn io(pool: *Pool) Io { | ... | @@ -134,7 +145,8 @@ pub fn io(pool: *Pool) Io { |
| 134 | .windows => @panic("TODO"), | 145 | .windows => @panic("TODO"), |
| 135 | else => netWritePosix, | 146 | else => netWritePosix, |
| 136 | }, | 147 | }, |
| 137 | .netClose = netClose, | 148 | .netSend = netSend, |
| | 149 | .netReceive = netReceive, |
| 138 | .netInterfaceNameResolve = netInterfaceNameResolve, | 150 | .netInterfaceNameResolve = netInterfaceNameResolve, |
| 139 | .netInterfaceName = netInterfaceName, | 151 | .netInterfaceName = netInterfaceName, |
| 140 | }, | 152 | }, |
| ... | @@ -460,7 +472,7 @@ fn asyncDetached( | ... | @@ -460,7 +472,7 @@ fn asyncDetached( |
| 460 | | 472 | |
| 461 | fn await( | 473 | fn await( |
| 462 | userdata: ?*anyopaque, | 474 | userdata: ?*anyopaque, |
| 463 | any_future: *std.Io.AnyFuture, | 475 | any_future: *Io.AnyFuture, |
| 464 | result: []u8, | 476 | result: []u8, |
| 465 | result_alignment: std.mem.Alignment, | 477 | result_alignment: std.mem.Alignment, |
| 466 | ) void { | 478 | ) void { |
| ... | @@ -984,59 +996,228 @@ fn select(userdata: ?*anyopaque, futures: []const *Io.AnyFuture) usize { | ... | @@ -984,59 +996,228 @@ fn select(userdata: ?*anyopaque, futures: []const *Io.AnyFuture) usize { |
| 984 | return result.?; | 996 | return result.?; |
| 985 | } | 997 | } |
| 986 | | 998 | |
| 987 | fn listen(userdata: ?*anyopaque, address: Io.net.IpAddress, options: Io.net.ListenOptions) Io.net.ListenError!Io.net.Server { | 999 | fn listenPosix( |
| | 1000 | userdata: ?*anyopaque, |
| | 1001 | address: Io.net.IpAddress, |
| | 1002 | options: Io.net.IpAddress.ListenOptions, |
| | 1003 | ) Io.net.IpAddress.ListenError!Io.net.Server { |
| 988 | const pool: *Pool = @ptrCast(@alignCast(userdata)); | 1004 | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 989 | try pool.checkCancel(); | 1005 | const family = posixAddressFamily(&address); |
| 990 | | 1006 | const protocol: u32 = posix.IPPROTO.TCP; |
| 991 | const nonblock: u32 = if (options.force_nonblocking) posix.SOCK.NONBLOCK else 0; | 1007 | const socket_fd = while (true) { |
| 992 | const sock_flags = posix.SOCK.STREAM | posix.SOCK.CLOEXEC | nonblock; | 1008 | try pool.checkCancel(); |
| 993 | const proto: u32 = posix.IPPROTO.TCP; | 1009 | const flags: u32 = posix.SOCK.STREAM | if (socket_flags_unsupported) 0 else posix.SOCK.CLOEXEC; |
| 994 | const family = posixAddressFamily(address); | 1010 | const socket_rc = posix.system.socket(family, flags, protocol); |
| 995 | const sockfd = try posix.socket(family, sock_flags, proto); | 1011 | switch (posix.errno(socket_rc)) { |
| 996 | const stream: std.net.Stream = .{ .handle = sockfd }; | 1012 | .SUCCESS => { |
| 997 | errdefer stream.close(); | 1013 | const fd: posix.fd_t = @intCast(socket_rc); |
| | 1014 | errdefer posix.close(fd); |
| | 1015 | if (socket_flags_unsupported) while (true) { |
| | 1016 | try pool.checkCancel(); |
| | 1017 | switch (posix.errno(posix.system.fcntl(fd, posix.F.SETFD, posix.FD_CLOEXEC))) { |
| | 1018 | .SUCCESS => break, |
| | 1019 | .INTR => continue, |
| | 1020 | else => |err| return posix.unexpectedErrno(err), |
| | 1021 | } |
| | 1022 | }; |
| | 1023 | break fd; |
| | 1024 | }, |
| | 1025 | .INTR => continue, |
| | 1026 | .AFNOSUPPORT => return error.AddressFamilyUnsupported, |
| | 1027 | .MFILE => return error.ProcessFdQuotaExceeded, |
| | 1028 | .NFILE => return error.SystemFdQuotaExceeded, |
| | 1029 | .NOBUFS => return error.SystemResources, |
| | 1030 | .NOMEM => return error.SystemResources, |
| | 1031 | else => |err| return posix.unexpectedErrno(err), |
| | 1032 | } |
| | 1033 | }; |
| | 1034 | errdefer posix.close(socket_fd); |
| 998 | | 1035 | |
| 999 | if (options.reuse_address) { | 1036 | if (options.reuse_address) { |
| 1000 | try posix.setsockopt( | 1037 | try setSocketOption(pool, socket_fd, posix.SOL.SOCKET, posix.SO.REUSEADDR, 1); |
| 1001 | sockfd, | 1038 | if (@hasDecl(posix.SO, "REUSEPORT")) |
| 1002 | posix.SOL.SOCKET, | 1039 | try setSocketOption(pool, socket_fd, posix.SOL.SOCKET, posix.SO.REUSEPORT, 1); |
| 1003 | posix.SO.REUSEADDR, | | |
| 1004 | &std.mem.toBytes(@as(c_int, 1)), | | |
| 1005 | ); | | |
| 1006 | if (@hasDecl(posix.SO, "REUSEPORT") and family != posix.AF.UNIX) { | | |
| 1007 | try posix.setsockopt( | | |
| 1008 | sockfd, | | |
| 1009 | posix.SOL.SOCKET, | | |
| 1010 | posix.SO.REUSEPORT, | | |
| 1011 | &std.mem.toBytes(@as(c_int, 1)), | | |
| 1012 | ); | | |
| 1013 | } | | |
| 1014 | } | 1040 | } |
| 1015 | | 1041 | |
| 1016 | var storage: PosixAddress = undefined; | 1042 | var storage: PosixAddress = undefined; |
| 1017 | var socklen = addressToPosix(address, &storage); | 1043 | var socklen = addressToPosix(address, &storage); |
| 1018 | try posix.bind(sockfd, &storage.any, socklen); | 1044 | try posixBind(pool, socket_fd, &storage.any, socklen); |
| 1019 | try posix.listen(sockfd, options.kernel_backlog); | 1045 | |
| 1020 | try posix.getsockname(sockfd, &storage.any, &socklen); | 1046 | while (true) { |
| | 1047 | try pool.checkCancel(); |
| | 1048 | switch (posix.errno(posix.system.listen(socket_fd, options.kernel_backlog))) { |
| | 1049 | .SUCCESS => break, |
| | 1050 | .ADDRINUSE => return error.AddressInUse, |
| | 1051 | .BADF => |err| return errnoBug(err), |
| | 1052 | else => |err| return posix.unexpectedErrno(err), |
| | 1053 | } |
| | 1054 | } |
| | 1055 | |
| | 1056 | try posixGetSockName(pool, socket_fd, &storage.any, &socklen); |
| 1021 | return .{ | 1057 | return .{ |
| 1022 | .listen_address = addressFromPosix(&storage), | 1058 | .socket = .{ |
| 1023 | .stream = .{ .handle = stream.handle }, | 1059 | .handle = socket_fd, |
| | 1060 | .address = addressFromPosix(&storage), |
| | 1061 | }, |
| 1024 | }; | 1062 | }; |
| 1025 | } | 1063 | } |
| 1026 | | 1064 | |
| 1027 | fn accept(userdata: ?*anyopaque, server: *Io.net.Server) Io.net.Server.AcceptError!Io.net.Server.Connection { | 1065 | fn posixBind(pool: *Pool, socket_fd: posix.socket_t, addr: *const posix.sockaddr, addr_len: posix.socklen_t) !void { |
| | 1066 | while (true) { |
| | 1067 | try pool.checkCancel(); |
| | 1068 | switch (posix.errno(posix.system.bind(socket_fd, addr, addr_len))) { |
| | 1069 | .SUCCESS => break, |
| | 1070 | .INTR => continue, |
| | 1071 | .ADDRINUSE => return error.AddressInUse, |
| | 1072 | .BADF => |err| return errnoBug(err), // always a race condition if this error is returned |
| | 1073 | .INVAL => |err| return errnoBug(err), // invalid parameters |
| | 1074 | .NOTSOCK => |err| return errnoBug(err), // invalid `sockfd` |
| | 1075 | .AFNOSUPPORT => return error.AddressFamilyUnsupported, |
| | 1076 | .ADDRNOTAVAIL => return error.AddressUnavailable, |
| | 1077 | .FAULT => |err| return errnoBug(err), // invalid `addr` pointer |
| | 1078 | .NOMEM => return error.SystemResources, |
| | 1079 | else => |err| return posix.unexpectedErrno(err), |
| | 1080 | } |
| | 1081 | } |
| | 1082 | } |
| | 1083 | |
| | 1084 | fn posixGetSockName(pool: *Pool, socket_fd: posix.fd_t, addr: *posix.sockaddr, addr_len: *posix.socklen_t) !void { |
| | 1085 | while (true) { |
| | 1086 | try pool.checkCancel(); |
| | 1087 | switch (posix.errno(posix.system.getsockname(socket_fd, addr, addr_len))) { |
| | 1088 | .SUCCESS => break, |
| | 1089 | .INTR => continue, |
| | 1090 | .BADF => |err| return errnoBug(err), // always a race condition |
| | 1091 | .FAULT => |err| return errnoBug(err), |
| | 1092 | .INVAL => |err| return errnoBug(err), // invalid parameters |
| | 1093 | .NOTSOCK => |err| return errnoBug(err), // always a race condition |
| | 1094 | .NOBUFS => return error.SystemResources, |
| | 1095 | else => |err| return posix.unexpectedErrno(err), |
| | 1096 | } |
| | 1097 | } |
| | 1098 | } |
| | 1099 | |
| | 1100 | fn setSocketOption(pool: *Pool, fd: posix.fd_t, level: i32, opt_name: u32, option: u32) !void { |
| | 1101 | const o: []const u8 = @ptrCast(&option); |
| | 1102 | while (true) { |
| | 1103 | try pool.checkCancel(); |
| | 1104 | switch (posix.errno(posix.system.setsockopt(fd, level, opt_name, o.ptr, @intCast(o.len)))) { |
| | 1105 | .SUCCESS => return, |
| | 1106 | .INTR => continue, |
| | 1107 | .BADF => |err| return errnoBug(err), // always a race condition |
| | 1108 | .NOTSOCK => |err| return errnoBug(err), // always a race condition |
| | 1109 | .INVAL => |err| return errnoBug(err), |
| | 1110 | .FAULT => |err| return errnoBug(err), |
| | 1111 | else => |err| return posix.unexpectedErrno(err), |
| | 1112 | } |
| | 1113 | } |
| | 1114 | } |
| | 1115 | |
| | 1116 | fn ipBindPosix( |
| | 1117 | userdata: ?*anyopaque, |
| | 1118 | address: Io.net.IpAddress, |
| | 1119 | options: Io.net.IpAddress.BindOptions, |
| | 1120 | ) Io.net.IpAddress.BindError!Io.net.Socket { |
| 1028 | const pool: *Pool = @ptrCast(@alignCast(userdata)); | 1121 | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 1029 | try pool.checkCancel(); | 1122 | const mode = posixSocketMode(options.mode); |
| | 1123 | const family = posixAddressFamily(&address); |
| | 1124 | const protocol = posixProtocol(options.protocol); |
| | 1125 | const socket_fd = while (true) { |
| | 1126 | try pool.checkCancel(); |
| | 1127 | const flags: u32 = mode | if (socket_flags_unsupported) 0 else posix.SOCK.CLOEXEC; |
| | 1128 | const socket_rc = posix.system.socket(family, flags, protocol); |
| | 1129 | switch (posix.errno(socket_rc)) { |
| | 1130 | .SUCCESS => { |
| | 1131 | const fd: posix.fd_t = @intCast(socket_rc); |
| | 1132 | errdefer posix.close(fd); |
| | 1133 | if (socket_flags_unsupported) while (true) { |
| | 1134 | try pool.checkCancel(); |
| | 1135 | switch (posix.errno(posix.system.fcntl(fd, posix.F.SETFD, posix.FD_CLOEXEC))) { |
| | 1136 | .SUCCESS => break, |
| | 1137 | .INTR => continue, |
| | 1138 | else => |err| return posix.unexpectedErrno(err), |
| | 1139 | } |
| | 1140 | }; |
| | 1141 | break fd; |
| | 1142 | }, |
| | 1143 | .INTR => continue, |
| | 1144 | .AFNOSUPPORT => return error.AddressFamilyUnsupported, |
| | 1145 | .INVAL => return error.ProtocolUnsupportedBySystem, |
| | 1146 | .MFILE => return error.ProcessFdQuotaExceeded, |
| | 1147 | .NFILE => return error.SystemFdQuotaExceeded, |
| | 1148 | .NOBUFS => return error.SystemResources, |
| | 1149 | .NOMEM => return error.SystemResources, |
| | 1150 | .PROTONOSUPPORT => return error.ProtocolUnsupportedByAddressFamily, |
| | 1151 | .PROTOTYPE => return error.SocketModeUnsupported, |
| | 1152 | else => |err| return posix.unexpectedErrno(err), |
| | 1153 | } |
| | 1154 | }; |
| | 1155 | |
| | 1156 | if (options.ip6_only) { |
| | 1157 | try setSocketOption(pool, socket_fd, posix.IPPROTO.IPV6, posix.IPV6.V6ONLY, 0); |
| | 1158 | } |
| 1030 | | 1159 | |
| 1031 | var storage: PosixAddress = undefined; | 1160 | var storage: PosixAddress = undefined; |
| 1032 | var addr_len: posix.socklen_t = @sizeOf(PosixAddress); | 1161 | var socklen = addressToPosix(address, &storage); |
| 1033 | const fd = try posix.accept(server.stream.handle, &storage.any, &addr_len, posix.SOCK.CLOEXEC); | 1162 | try posixBind(pool, socket_fd, &storage.any, socklen); |
| | 1163 | try posixGetSockName(pool, socket_fd, &storage.any, &socklen); |
| 1034 | return .{ | 1164 | return .{ |
| 1035 | .stream = .{ .handle = fd }, | 1165 | .handle = socket_fd, |
| 1036 | .address = addressFromPosix(&storage), | 1166 | .address = addressFromPosix(&storage), |
| 1037 | }; | 1167 | }; |
| 1038 | } | 1168 | } |
| 1039 | | 1169 | |
| | 1170 | const socket_flags_unsupported = builtin.os.tag.isDarwin() or native_os == .haiku; // 💩💩 |
| | 1171 | const have_accept4 = !socket_flags_unsupported; |
| | 1172 | |
| | 1173 | fn acceptPosix(userdata: ?*anyopaque, server: *Io.net.Server) Io.net.Server.AcceptError!Io.net.Stream { |
| | 1174 | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| | 1175 | const listen_fd = server.socket.handle; |
| | 1176 | var storage: PosixAddress = undefined; |
| | 1177 | var addr_len: posix.socklen_t = @sizeOf(PosixAddress); |
| | 1178 | const fd = while (true) { |
| | 1179 | try pool.checkCancel(); |
| | 1180 | const rc = if (have_accept4) |
| | 1181 | posix.system.accept4(listen_fd, &storage.any, &addr_len, posix.SOCK.CLOEXEC) |
| | 1182 | else |
| | 1183 | posix.system.accept(listen_fd, &storage.any, &addr_len); |
| | 1184 | switch (posix.errno(rc)) { |
| | 1185 | .SUCCESS => { |
| | 1186 | const fd: posix.fd_t = @intCast(rc); |
| | 1187 | errdefer posix.close(fd); |
| | 1188 | if (!have_accept4) while (true) { |
| | 1189 | try pool.checkCancel(); |
| | 1190 | switch (posix.errno(posix.system.fcntl(fd, posix.F.SETFD, posix.FD_CLOEXEC))) { |
| | 1191 | .SUCCESS => break, |
| | 1192 | .INTR => continue, |
| | 1193 | else => |err| return posix.unexpectedErrno(err), |
| | 1194 | } |
| | 1195 | }; |
| | 1196 | break fd; |
| | 1197 | }, |
| | 1198 | .INTR => continue, |
| | 1199 | .AGAIN => |err| return errnoBug(err), |
| | 1200 | .BADF => |err| return errnoBug(err), // always a race condition |
| | 1201 | .CONNABORTED => return error.ConnectionAborted, |
| | 1202 | .FAULT => |err| return errnoBug(err), |
| | 1203 | .INVAL => return error.SocketNotListening, |
| | 1204 | .NOTSOCK => |err| return errnoBug(err), |
| | 1205 | .MFILE => return error.ProcessFdQuotaExceeded, |
| | 1206 | .NFILE => return error.SystemFdQuotaExceeded, |
| | 1207 | .NOBUFS => return error.SystemResources, |
| | 1208 | .NOMEM => return error.SystemResources, |
| | 1209 | .OPNOTSUPP => |err| return errnoBug(err), |
| | 1210 | .PROTO => return error.ProtocolFailure, |
| | 1211 | .PERM => return error.BlockedByFirewall, |
| | 1212 | else => |err| return posix.unexpectedErrno(err), |
| | 1213 | } |
| | 1214 | }; |
| | 1215 | return .{ .socket = .{ |
| | 1216 | .handle = fd, |
| | 1217 | .address = addressFromPosix(&storage), |
| | 1218 | } }; |
| | 1219 | } |
| | 1220 | |
| 1040 | fn netReadPosix(userdata: ?*anyopaque, stream: Io.net.Stream, data: [][]u8) Io.net.Stream.Reader.Error!usize { | 1221 | fn netReadPosix(userdata: ?*anyopaque, stream: Io.net.Stream, data: [][]u8) Io.net.Stream.Reader.Error!usize { |
| 1041 | const pool: *Pool = @ptrCast(@alignCast(userdata)); | 1222 | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 1042 | try pool.checkCancel(); | 1223 | try pool.checkCancel(); |
| ... | @@ -1052,11 +1233,41 @@ fn netReadPosix(userdata: ?*anyopaque, stream: Io.net.Stream, data: [][]u8) Io.n | ... | @@ -1052,11 +1233,41 @@ fn netReadPosix(userdata: ?*anyopaque, stream: Io.net.Stream, data: [][]u8) Io.n |
| 1052 | } | 1233 | } |
| 1053 | const dest = iovecs_buffer[0..i]; | 1234 | const dest = iovecs_buffer[0..i]; |
| 1054 | assert(dest[0].len > 0); | 1235 | assert(dest[0].len > 0); |
| 1055 | const n = try posix.readv(stream.handle, dest); | 1236 | const n = try posix.readv(stream.socket.handle, dest); |
| 1056 | if (n == 0) return error.EndOfStream; | 1237 | if (n == 0) return error.EndOfStream; |
| 1057 | return n; | 1238 | return n; |
| 1058 | } | 1239 | } |
| 1059 | | 1240 | |
| | 1241 | fn netSend( |
| | 1242 | userdata: ?*anyopaque, |
| | 1243 | handle: Io.net.Socket.Handle, |
| | 1244 | address: Io.net.IpAddress, |
| | 1245 | data: []const u8, |
| | 1246 | ) Io.net.Socket.SendError!void { |
| | 1247 | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| | 1248 | try pool.checkCancel(); |
| | 1249 | |
| | 1250 | _ = handle; |
| | 1251 | _ = address; |
| | 1252 | _ = data; |
| | 1253 | @panic("TODO"); |
| | 1254 | } |
| | 1255 | |
| | 1256 | fn netReceive( |
| | 1257 | userdata: ?*anyopaque, |
| | 1258 | handle: Io.net.Socket.Handle, |
| | 1259 | address: Io.net.IpAddress, |
| | 1260 | buffer: []u8, |
| | 1261 | ) Io.net.Socket.ReceiveError!void { |
| | 1262 | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| | 1263 | try pool.checkCancel(); |
| | 1264 | |
| | 1265 | _ = handle; |
| | 1266 | _ = address; |
| | 1267 | _ = buffer; |
| | 1268 | @panic("TODO"); |
| | 1269 | } |
| | 1270 | |
| 1060 | fn netWritePosix( | 1271 | fn netWritePosix( |
| 1061 | userdata: ?*anyopaque, | 1272 | userdata: ?*anyopaque, |
| 1062 | stream: Io.net.Stream, | 1273 | stream: Io.net.Stream, |
| ... | @@ -1106,7 +1317,7 @@ fn netWritePosix( | ... | @@ -1106,7 +1317,7 @@ fn netWritePosix( |
| 1106 | }, | 1317 | }, |
| 1107 | }; | 1318 | }; |
| 1108 | const flags = posix.MSG.NOSIGNAL; | 1319 | const flags = posix.MSG.NOSIGNAL; |
| 1109 | return posix.sendmsg(stream.handle, &msg, flags); | 1320 | return posix.sendmsg(stream.socket.handle, &msg, flags); |
| 1110 | } | 1321 | } |
| 1111 | | 1322 | |
| 1112 | fn addBuf(v: []posix.iovec_const, i: *@FieldType(posix.msghdr_const, "iovlen"), bytes: []const u8) void { | 1323 | fn addBuf(v: []posix.iovec_const, i: *@FieldType(posix.msghdr_const, "iovlen"), bytes: []const u8) void { |
| ... | @@ -1117,11 +1328,13 @@ fn addBuf(v: []posix.iovec_const, i: *@FieldType(posix.msghdr_const, "iovlen"), | ... | @@ -1117,11 +1328,13 @@ fn addBuf(v: []posix.iovec_const, i: *@FieldType(posix.msghdr_const, "iovlen"), |
| 1117 | i.* += 1; | 1328 | i.* += 1; |
| 1118 | } | 1329 | } |
| 1119 | | 1330 | |
| 1120 | fn netClose(userdata: ?*anyopaque, stream: Io.net.Stream) void { | 1331 | fn netClose(userdata: ?*anyopaque, handle: Io.net.Socket.Handle) void { |
| 1121 | const pool: *Pool = @ptrCast(@alignCast(userdata)); | 1332 | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 1122 | _ = pool; | 1333 | _ = pool; |
| 1123 | const net_stream: std.net.Stream = .{ .handle = stream.handle }; | 1334 | switch (native_os) { |
| 1124 | return net_stream.close(); | 1335 | .windows => windows.closesocket(handle) catch recoverableOsBugDetected(), |
| | 1336 | else => posix.close(handle), |
| | 1337 | } |
| 1125 | } | 1338 | } |
| 1126 | | 1339 | |
| 1127 | fn netInterfaceNameResolve( | 1340 | fn netInterfaceNameResolve( |
| ... | @@ -1153,13 +1366,13 @@ fn netInterfaceNameResolve( | ... | @@ -1153,13 +1366,13 @@ fn netInterfaceNameResolve( |
| 1153 | try pool.checkCancel(); | 1366 | try pool.checkCancel(); |
| 1154 | switch (posix.errno(posix.system.ioctl(sock_fd, posix.SIOCGIFINDEX, @intFromPtr(&ifr)))) { | 1367 | switch (posix.errno(posix.system.ioctl(sock_fd, posix.SIOCGIFINDEX, @intFromPtr(&ifr)))) { |
| 1155 | .SUCCESS => return .{ .index = @bitCast(ifr.ifru.ivalue) }, | 1368 | .SUCCESS => return .{ .index = @bitCast(ifr.ifru.ivalue) }, |
| 1156 | .INVAL => |err| return badErrno(err), // Bad parameters. | 1369 | .INVAL => |err| return errnoBug(err), // Bad parameters. |
| 1157 | .NOTTY => |err| return badErrno(err), | 1370 | .NOTTY => |err| return errnoBug(err), |
| 1158 | .NXIO => |err| return badErrno(err), | 1371 | .NXIO => |err| return errnoBug(err), |
| 1159 | .BADF => |err| return badErrno(err), // Always a race condition. | 1372 | .BADF => |err| return errnoBug(err), // Always a race condition. |
| 1160 | .FAULT => |err| return badErrno(err), // Bad pointer parameter. | 1373 | .FAULT => |err| return errnoBug(err), // Bad pointer parameter. |
| 1161 | .INTR => continue, | 1374 | .INTR => continue, |
| 1162 | .IO => |err| return badErrno(err), // sock_fd is not a file descriptor | 1375 | .IO => |err| return errnoBug(err), // sock_fd is not a file descriptor |
| 1163 | .NODEV => return error.InterfaceNotFound, | 1376 | .NODEV => return error.InterfaceNotFound, |
| 1164 | else => |err| return posix.unexpectedErrno(err), | 1377 | else => |err| return posix.unexpectedErrno(err), |
| 1165 | } | 1378 | } |
| ... | @@ -1207,8 +1420,8 @@ const PosixAddress = extern union { | ... | @@ -1207,8 +1420,8 @@ const PosixAddress = extern union { |
| 1207 | in6: posix.sockaddr.in6, | 1420 | in6: posix.sockaddr.in6, |
| 1208 | }; | 1421 | }; |
| 1209 | | 1422 | |
| 1210 | fn posixAddressFamily(a: Io.net.IpAddress) posix.sa_family_t { | 1423 | fn posixAddressFamily(a: *const Io.net.IpAddress) posix.sa_family_t { |
| 1211 | return switch (a) { | 1424 | return switch (a.*) { |
| 1212 | .ip4 => posix.AF.INET, | 1425 | .ip4 => posix.AF.INET, |
| 1213 | .ip6 => posix.AF.INET6, | 1426 | .ip6 => posix.AF.INET6, |
| 1214 | }; | 1427 | }; |
| ... | @@ -1267,9 +1480,27 @@ fn address6ToPosix(a: Io.net.Ip6Address) posix.sockaddr.in6 { | ... | @@ -1267,9 +1480,27 @@ fn address6ToPosix(a: Io.net.Ip6Address) posix.sockaddr.in6 { |
| 1267 | }; | 1480 | }; |
| 1268 | } | 1481 | } |
| 1269 | | 1482 | |
| 1270 | fn badErrno(err: posix.E) Io.UnexpectedError { | 1483 | fn errnoBug(err: posix.E) Io.UnexpectedError { |
| 1271 | switch (builtin.mode) { | 1484 | switch (builtin.mode) { |
| 1272 | .Debug => std.debug.panic("programmer bug caused syscall error: {t}", .{err}), | 1485 | .Debug => std.debug.panic("programmer bug caused syscall error: {t}", .{err}), |
| 1273 | else => return error.Unexpected, | 1486 | else => return error.Unexpected, |
| 1274 | } | 1487 | } |
| 1275 | } | 1488 | } |
| | 1489 | |
| | 1490 | fn posixSocketMode(mode: Io.net.Socket.Mode) u32 { |
| | 1491 | return switch (mode) { |
| | 1492 | .stream => posix.SOCK.STREAM, |
| | 1493 | .dgram => posix.SOCK.DGRAM, |
| | 1494 | .seqpacket => posix.SOCK.SEQPACKET, |
| | 1495 | .raw => posix.SOCK.RAW, |
| | 1496 | .rdm => posix.SOCK.RDM, |
| | 1497 | }; |
| | 1498 | } |
| | 1499 | |
| | 1500 | fn posixProtocol(protocol: ?Io.net.Protocol) u32 { |
| | 1501 | return @intFromEnum(protocol orelse return 0); |
| | 1502 | } |
| | 1503 | |
| | 1504 | fn recoverableOsBugDetected() void { |
| | 1505 | if (builtin.mode == .Debug) unreachable; |
| | 1506 | } |