| ... | @@ -248,7 +248,7 @@ pub fn io(t: *Threaded) Io { | ... | @@ -248,7 +248,7 @@ pub fn io(t: *Threaded) Io { |
| 248 | else => netAcceptPosix, | 248 | else => netAcceptPosix, |
| 249 | }, | 249 | }, |
| 250 | .netBindIp = switch (builtin.os.tag) { | 250 | .netBindIp = switch (builtin.os.tag) { |
| 251 | .windows => @panic("TODO"), | 251 | .windows => netBindIpWindows, |
| 252 | else => netBindIpPosix, | 252 | else => netBindIpPosix, |
| 253 | }, | 253 | }, |
| 254 | .netConnectIp = switch (builtin.os.tag) { | 254 | .netConnectIp = switch (builtin.os.tag) { |
| ... | @@ -2828,7 +2828,7 @@ fn netListenIpWindows( | ... | @@ -2828,7 +2828,7 @@ fn netListenIpWindows( |
| 2828 | .EAFNOSUPPORT => return error.AddressFamilyUnsupported, | 2828 | .EAFNOSUPPORT => return error.AddressFamilyUnsupported, |
| 2829 | .EMFILE => return error.ProcessFdQuotaExceeded, | 2829 | .EMFILE => return error.ProcessFdQuotaExceeded, |
| 2830 | .ENOBUFS => return error.SystemResources, | 2830 | .ENOBUFS => return error.SystemResources, |
| 2831 | .EPROTONOSUPPORT => return error.ProtocolUnsupportedBySystem, | 2831 | .EPROTONOSUPPORT => return error.ProtocolUnsupportedByAddressFamily, |
| 2832 | else => |err| return windows.unexpectedWSAError(err), | 2832 | else => |err| return windows.unexpectedWSAError(err), |
| 2833 | } | 2833 | } |
| 2834 | }; | 2834 | }; |
| ... | @@ -3176,6 +3176,86 @@ fn netBindIpPosix( | ... | @@ -3176,6 +3176,86 @@ fn netBindIpPosix( |
| 3176 | }; | 3176 | }; |
| 3177 | } | 3177 | } |
| 3178 | | 3178 | |
| | 3179 | fn netBindIpWindows( |
| | 3180 | userdata: ?*anyopaque, |
| | 3181 | address: *const IpAddress, |
| | 3182 | options: IpAddress.BindOptions, |
| | 3183 | ) IpAddress.BindError!net.Socket { |
| | 3184 | if (!have_networking) return error.NetworkDown; |
| | 3185 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| | 3186 | const family = posixAddressFamily(address); |
| | 3187 | const mode = posixSocketMode(options.mode); |
| | 3188 | const protocol = posixProtocol(options.protocol); |
| | 3189 | const socket_handle = while (true) { |
| | 3190 | try t.checkCancel(); |
| | 3191 | const flags: u32 = ws2_32.WSA_FLAG_OVERLAPPED | ws2_32.WSA_FLAG_NO_HANDLE_INHERIT; |
| | 3192 | const rc = ws2_32.WSASocketW(family, @bitCast(mode), @bitCast(protocol), null, 0, flags); |
| | 3193 | if (rc != ws2_32.INVALID_SOCKET) break rc; |
| | 3194 | switch (ws2_32.WSAGetLastError()) { |
| | 3195 | .EINTR => continue, |
| | 3196 | .ECANCELLED, .E_CANCELLED => return error.Canceled, |
| | 3197 | .NOTINITIALISED => { |
| | 3198 | try initializeWsa(t); |
| | 3199 | continue; |
| | 3200 | }, |
| | 3201 | .EAFNOSUPPORT => return error.AddressFamilyUnsupported, |
| | 3202 | .EMFILE => return error.ProcessFdQuotaExceeded, |
| | 3203 | .ENOBUFS => return error.SystemResources, |
| | 3204 | .EPROTONOSUPPORT => return error.ProtocolUnsupportedByAddressFamily, |
| | 3205 | else => |err| return windows.unexpectedWSAError(err), |
| | 3206 | } |
| | 3207 | }; |
| | 3208 | errdefer closeSocketWindows(socket_handle); |
| | 3209 | var storage: WsaAddress = undefined; |
| | 3210 | var addr_len = addressToWsa(address, &storage); |
| | 3211 | |
| | 3212 | while (true) { |
| | 3213 | try t.checkCancel(); |
| | 3214 | const rc = ws2_32.bind(socket_handle, &storage.any, addr_len); |
| | 3215 | if (rc != ws2_32.SOCKET_ERROR) break; |
| | 3216 | switch (ws2_32.WSAGetLastError()) { |
| | 3217 | .EINTR => continue, |
| | 3218 | .ECANCELLED, .E_CANCELLED => return error.Canceled, |
| | 3219 | .NOTINITIALISED => { |
| | 3220 | try initializeWsa(t); |
| | 3221 | continue; |
| | 3222 | }, |
| | 3223 | .EADDRINUSE => return error.AddressInUse, |
| | 3224 | .EADDRNOTAVAIL => return error.AddressUnavailable, |
| | 3225 | .ENOTSOCK => |err| return wsaErrorBug(err), |
| | 3226 | .EFAULT => |err| return wsaErrorBug(err), |
| | 3227 | .EINVAL => |err| return wsaErrorBug(err), |
| | 3228 | .ENOBUFS => return error.SystemResources, |
| | 3229 | .ENETDOWN => return error.NetworkDown, |
| | 3230 | else => |err| return windows.unexpectedWSAError(err), |
| | 3231 | } |
| | 3232 | } |
| | 3233 | |
| | 3234 | while (true) { |
| | 3235 | try t.checkCancel(); |
| | 3236 | const rc = ws2_32.getsockname(socket_handle, &storage.any, &addr_len); |
| | 3237 | if (rc != ws2_32.SOCKET_ERROR) break; |
| | 3238 | switch (ws2_32.WSAGetLastError()) { |
| | 3239 | .EINTR => continue, |
| | 3240 | .ECANCELLED, .E_CANCELLED => return error.Canceled, |
| | 3241 | .NOTINITIALISED => { |
| | 3242 | try initializeWsa(t); |
| | 3243 | continue; |
| | 3244 | }, |
| | 3245 | .ENETDOWN => return error.NetworkDown, |
| | 3246 | .EFAULT => |err| return wsaErrorBug(err), |
| | 3247 | .ENOTSOCK => |err| return wsaErrorBug(err), |
| | 3248 | .EINVAL => |err| return wsaErrorBug(err), |
| | 3249 | else => |err| return windows.unexpectedWSAError(err), |
| | 3250 | } |
| | 3251 | } |
| | 3252 | |
| | 3253 | return .{ |
| | 3254 | .handle = socket_handle, |
| | 3255 | .address = addressFromWsa(&storage), |
| | 3256 | }; |
| | 3257 | } |
| | 3258 | |
| 3179 | fn openSocketPosix( | 3259 | fn openSocketPosix( |
| 3180 | t: *Threaded, | 3260 | t: *Threaded, |
| 3181 | family: posix.sa_family_t, | 3261 | family: posix.sa_family_t, |