| ... | @@ -252,7 +252,7 @@ pub fn io(t: *Threaded) Io { | ... | @@ -252,7 +252,7 @@ pub fn io(t: *Threaded) Io { |
| 252 | else => netBindIpPosix, | 252 | else => netBindIpPosix, |
| 253 | }, | 253 | }, |
| 254 | .netConnectIp = switch (builtin.os.tag) { | 254 | .netConnectIp = switch (builtin.os.tag) { |
| 255 | .windows => @panic("TODO"), | 255 | .windows => netConnectIpWindows, |
| 256 | else => netConnectIpPosix, | 256 | else => netConnectIpPosix, |
| 257 | }, | 257 | }, |
| 258 | .netConnectUnix = netConnectUnix, | 258 | .netConnectUnix = netConnectUnix, |
| ... | @@ -2810,28 +2810,10 @@ fn netListenIpWindows( | ... | @@ -2810,28 +2810,10 @@ fn netListenIpWindows( |
| 2810 | if (!have_networking) return error.NetworkDown; | 2810 | if (!have_networking) return error.NetworkDown; |
| 2811 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 2811 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 2812 | const family = posixAddressFamily(&address); | 2812 | const family = posixAddressFamily(&address); |
| 2813 | const mode = posixSocketMode(options.mode); | 2813 | const socket_handle = try openSocketWsa(t, family, .{ |
| 2814 | const protocol = posixProtocol(options.protocol); | 2814 | .mode = options.mode, |
| 2815 | | 2815 | .protocol = options.protocol, |
| 2816 | const socket_handle = while (true) { | 2816 | }); |
| 2817 | try t.checkCancel(); | | |
| 2818 | const flags: u32 = ws2_32.WSA_FLAG_OVERLAPPED | ws2_32.WSA_FLAG_NO_HANDLE_INHERIT; | | |
| 2819 | const rc = ws2_32.WSASocketW(family, @bitCast(mode), @bitCast(protocol), null, 0, flags); | | |
| 2820 | if (rc != ws2_32.INVALID_SOCKET) break rc; | | |
| 2821 | switch (ws2_32.WSAGetLastError()) { | | |
| 2822 | .EINTR => continue, | | |
| 2823 | .ECANCELLED, .E_CANCELLED => return error.Canceled, | | |
| 2824 | .NOTINITIALISED => { | | |
| 2825 | try initializeWsa(t); | | |
| 2826 | continue; | | |
| 2827 | }, | | |
| 2828 | .EAFNOSUPPORT => return error.AddressFamilyUnsupported, | | |
| 2829 | .EMFILE => return error.ProcessFdQuotaExceeded, | | |
| 2830 | .ENOBUFS => return error.SystemResources, | | |
| 2831 | .EPROTONOSUPPORT => return error.ProtocolUnsupportedByAddressFamily, | | |
| 2832 | else => |err| return windows.unexpectedWSAError(err), | | |
| 2833 | } | | |
| 2834 | }; | | |
| 2835 | errdefer closeSocketWindows(socket_handle); | 2817 | errdefer closeSocketWindows(socket_handle); |
| 2836 | | 2818 | |
| 2837 | if (options.reuse_address) | 2819 | if (options.reuse_address) |
| ... | @@ -2885,24 +2867,7 @@ fn netListenIpWindows( | ... | @@ -2885,24 +2867,7 @@ fn netListenIpWindows( |
| 2885 | } | 2867 | } |
| 2886 | } | 2868 | } |
| 2887 | | 2869 | |
| 2888 | while (true) { | 2870 | try wsaGetSockName(t, socket_handle, &storage.any, &addr_len); |
| 2889 | try t.checkCancel(); | | |
| 2890 | const rc = ws2_32.getsockname(socket_handle, &storage.any, &addr_len); | | |
| 2891 | if (rc != ws2_32.SOCKET_ERROR) break; | | |
| 2892 | switch (ws2_32.WSAGetLastError()) { | | |
| 2893 | .EINTR => continue, | | |
| 2894 | .ECANCELLED, .E_CANCELLED => return error.Canceled, | | |
| 2895 | .NOTINITIALISED => { | | |
| 2896 | try initializeWsa(t); | | |
| 2897 | continue; | | |
| 2898 | }, | | |
| 2899 | .ENETDOWN => return error.NetworkDown, | | |
| 2900 | .EFAULT => |err| return wsaErrorBug(err), | | |
| 2901 | .ENOTSOCK => |err| return wsaErrorBug(err), | | |
| 2902 | .EINVAL => |err| return wsaErrorBug(err), | | |
| 2903 | else => |err| return windows.unexpectedWSAError(err), | | |
| 2904 | } | | |
| 2905 | } | | |
| 2906 | | 2871 | |
| 2907 | return .{ | 2872 | return .{ |
| 2908 | .socket = .{ | 2873 | .socket = .{ |
| ... | @@ -3076,6 +3041,27 @@ fn posixGetSockName(t: *Threaded, socket_fd: posix.fd_t, addr: *posix.sockaddr, | ... | @@ -3076,6 +3041,27 @@ fn posixGetSockName(t: *Threaded, socket_fd: posix.fd_t, addr: *posix.sockaddr, |
| 3076 | } | 3041 | } |
| 3077 | } | 3042 | } |
| 3078 | | 3043 | |
| | 3044 | fn wsaGetSockName(t: *Threaded, handle: ws2_32.SOCKET, addr: *ws2_32.sockaddr, addr_len: *i32) !void { |
| | 3045 | while (true) { |
| | 3046 | try t.checkCancel(); |
| | 3047 | const rc = ws2_32.getsockname(handle, addr, addr_len); |
| | 3048 | if (rc != ws2_32.SOCKET_ERROR) break; |
| | 3049 | switch (ws2_32.WSAGetLastError()) { |
| | 3050 | .EINTR => continue, |
| | 3051 | .ECANCELLED, .E_CANCELLED => return error.Canceled, |
| | 3052 | .NOTINITIALISED => { |
| | 3053 | try initializeWsa(t); |
| | 3054 | continue; |
| | 3055 | }, |
| | 3056 | .ENETDOWN => return error.NetworkDown, |
| | 3057 | .EFAULT => |err| return wsaErrorBug(err), |
| | 3058 | .ENOTSOCK => |err| return wsaErrorBug(err), |
| | 3059 | .EINVAL => |err| return wsaErrorBug(err), |
| | 3060 | else => |err| return windows.unexpectedWSAError(err), |
| | 3061 | } |
| | 3062 | } |
| | 3063 | } |
| | 3064 | |
| 3079 | fn setSocketOption(t: *Threaded, fd: posix.fd_t, level: i32, opt_name: u32, option: u32) !void { | 3065 | fn setSocketOption(t: *Threaded, fd: posix.fd_t, level: i32, opt_name: u32, option: u32) !void { |
| 3080 | const o: []const u8 = @ptrCast(&option); | 3066 | const o: []const u8 = @ptrCast(&option); |
| 3081 | while (true) { | 3067 | while (true) { |
| ... | @@ -3139,6 +3125,61 @@ fn netConnectIpPosix( | ... | @@ -3139,6 +3125,61 @@ fn netConnectIpPosix( |
| 3139 | } }; | 3125 | } }; |
| 3140 | } | 3126 | } |
| 3141 | | 3127 | |
| | 3128 | fn netConnectIpWindows( |
| | 3129 | userdata: ?*anyopaque, |
| | 3130 | address: *const IpAddress, |
| | 3131 | options: IpAddress.ConnectOptions, |
| | 3132 | ) IpAddress.ConnectError!net.Stream { |
| | 3133 | if (!have_networking) return error.NetworkDown; |
| | 3134 | if (options.timeout != .none) @panic("TODO"); |
| | 3135 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| | 3136 | const family = posixAddressFamily(address); |
| | 3137 | const socket_handle = try openSocketWsa(t, family, .{ |
| | 3138 | .mode = options.mode, |
| | 3139 | .protocol = options.protocol, |
| | 3140 | }); |
| | 3141 | errdefer closeSocketWindows(socket_handle); |
| | 3142 | |
| | 3143 | var storage: WsaAddress = undefined; |
| | 3144 | var addr_len = addressToWsa(address, &storage); |
| | 3145 | |
| | 3146 | while (true) { |
| | 3147 | const rc = ws2_32.connect(socket_handle, &storage.any, addr_len); |
| | 3148 | if (rc != ws2_32.SOCKET_ERROR) break; |
| | 3149 | switch (ws2_32.WSAGetLastError()) { |
| | 3150 | .EINTR => continue, |
| | 3151 | .ECANCELLED, .E_CANCELLED => return error.Canceled, |
| | 3152 | .NOTINITIALISED => { |
| | 3153 | try initializeWsa(t); |
| | 3154 | continue; |
| | 3155 | }, |
| | 3156 | |
| | 3157 | .EADDRNOTAVAIL => return error.AddressUnavailable, |
| | 3158 | .ECONNREFUSED => return error.ConnectionRefused, |
| | 3159 | .ECONNRESET => return error.ConnectionResetByPeer, |
| | 3160 | .ETIMEDOUT => return error.Timeout, |
| | 3161 | .EHOSTUNREACH => return error.HostUnreachable, |
| | 3162 | .ENETUNREACH => return error.NetworkUnreachable, |
| | 3163 | .EFAULT => |err| return wsaErrorBug(err), |
| | 3164 | .EINVAL => |err| return wsaErrorBug(err), |
| | 3165 | .EISCONN => |err| return wsaErrorBug(err), |
| | 3166 | .ENOTSOCK => |err| return wsaErrorBug(err), |
| | 3167 | .EWOULDBLOCK => return error.WouldBlock, |
| | 3168 | .EACCES => return error.AccessDenied, |
| | 3169 | .ENOBUFS => return error.SystemResources, |
| | 3170 | .EAFNOSUPPORT => return error.AddressFamilyUnsupported, |
| | 3171 | else => |err| return windows.unexpectedWSAError(err), |
| | 3172 | } |
| | 3173 | } |
| | 3174 | |
| | 3175 | try wsaGetSockName(t, socket_handle, &storage.any, &addr_len); |
| | 3176 | |
| | 3177 | return .{ .socket = .{ |
| | 3178 | .handle = socket_handle, |
| | 3179 | .address = addressFromWsa(&storage), |
| | 3180 | } }; |
| | 3181 | } |
| | 3182 | |
| 3142 | fn netConnectUnix( | 3183 | fn netConnectUnix( |
| 3143 | userdata: ?*anyopaque, | 3184 | userdata: ?*anyopaque, |
| 3144 | address: *const net.UnixAddress, | 3185 | address: *const net.UnixAddress, |
| ... | @@ -3184,28 +3225,12 @@ fn netBindIpWindows( | ... | @@ -3184,28 +3225,12 @@ fn netBindIpWindows( |
| 3184 | if (!have_networking) return error.NetworkDown; | 3225 | if (!have_networking) return error.NetworkDown; |
| 3185 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 3226 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 3186 | const family = posixAddressFamily(address); | 3227 | const family = posixAddressFamily(address); |
| 3187 | const mode = posixSocketMode(options.mode); | 3228 | const socket_handle = try openSocketWsa(t, family, .{ |
| 3188 | const protocol = posixProtocol(options.protocol); | 3229 | .mode = options.mode, |
| 3189 | const socket_handle = while (true) { | 3230 | .protocol = options.protocol, |
| 3190 | try t.checkCancel(); | 3231 | }); |
| 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); | 3232 | errdefer closeSocketWindows(socket_handle); |
| | 3233 | |
| 3209 | var storage: WsaAddress = undefined; | 3234 | var storage: WsaAddress = undefined; |
| 3210 | var addr_len = addressToWsa(address, &storage); | 3235 | var addr_len = addressToWsa(address, &storage); |
| 3211 | | 3236 | |
| ... | @@ -3231,24 +3256,7 @@ fn netBindIpWindows( | ... | @@ -3231,24 +3256,7 @@ fn netBindIpWindows( |
| 3231 | } | 3256 | } |
| 3232 | } | 3257 | } |
| 3233 | | 3258 | |
| 3234 | while (true) { | 3259 | try wsaGetSockName(t, socket_handle, &storage.any, &addr_len); |
| 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 | | 3260 | |
| 3253 | return .{ | 3261 | return .{ |
| 3254 | .handle = socket_handle, | 3262 | .handle = socket_handle, |
| ... | @@ -3317,6 +3325,30 @@ fn openSocketPosix( | ... | @@ -3317,6 +3325,30 @@ fn openSocketPosix( |
| 3317 | return socket_fd; | 3325 | return socket_fd; |
| 3318 | } | 3326 | } |
| 3319 | | 3327 | |
| | 3328 | fn openSocketWsa(t: *Threaded, family: posix.sa_family_t, options: IpAddress.BindOptions) !ws2_32.SOCKET { |
| | 3329 | const mode = posixSocketMode(options.mode); |
| | 3330 | const protocol = posixProtocol(options.protocol); |
| | 3331 | const flags: u32 = ws2_32.WSA_FLAG_OVERLAPPED | ws2_32.WSA_FLAG_NO_HANDLE_INHERIT; |
| | 3332 | while (true) { |
| | 3333 | try t.checkCancel(); |
| | 3334 | const rc = ws2_32.WSASocketW(family, @bitCast(mode), @bitCast(protocol), null, 0, flags); |
| | 3335 | if (rc != ws2_32.INVALID_SOCKET) return rc; |
| | 3336 | switch (ws2_32.WSAGetLastError()) { |
| | 3337 | .EINTR => continue, |
| | 3338 | .ECANCELLED, .E_CANCELLED => return error.Canceled, |
| | 3339 | .NOTINITIALISED => { |
| | 3340 | try initializeWsa(t); |
| | 3341 | continue; |
| | 3342 | }, |
| | 3343 | .EAFNOSUPPORT => return error.AddressFamilyUnsupported, |
| | 3344 | .EMFILE => return error.ProcessFdQuotaExceeded, |
| | 3345 | .ENOBUFS => return error.SystemResources, |
| | 3346 | .EPROTONOSUPPORT => return error.ProtocolUnsupportedByAddressFamily, |
| | 3347 | else => |err| return windows.unexpectedWSAError(err), |
| | 3348 | } |
| | 3349 | } |
| | 3350 | } |
| | 3351 | |
| 3320 | fn netAcceptPosix(userdata: ?*anyopaque, listen_fd: net.Socket.Handle) net.Server.AcceptError!net.Stream { | 3352 | fn netAcceptPosix(userdata: ?*anyopaque, listen_fd: net.Socket.Handle) net.Server.AcceptError!net.Stream { |
| 3321 | if (!have_networking) return error.NetworkDown; | 3353 | if (!have_networking) return error.NetworkDown; |
| 3322 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 3354 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| ... | @@ -3376,11 +3408,11 @@ fn netAcceptWindows(userdata: ?*anyopaque, listen_handle: net.Socket.Handle) net | ... | @@ -3376,11 +3408,11 @@ fn netAcceptWindows(userdata: ?*anyopaque, listen_handle: net.Socket.Handle) net |
| 3376 | while (true) { | 3408 | while (true) { |
| 3377 | try t.checkCancel(); | 3409 | try t.checkCancel(); |
| 3378 | const rc = ws2_32.accept(listen_handle, &storage.any, &addr_len); | 3410 | const rc = ws2_32.accept(listen_handle, &storage.any, &addr_len); |
| 3379 | if (rc != windows.ws2_32.INVALID_SOCKET) return .{ .socket = .{ | 3411 | if (rc != ws2_32.INVALID_SOCKET) return .{ .socket = .{ |
| 3380 | .handle = rc, | 3412 | .handle = rc, |
| 3381 | .address = addressFromWsa(&storage), | 3413 | .address = addressFromWsa(&storage), |
| 3382 | } }; | 3414 | } }; |
| 3383 | switch (windows.ws2_32.WSAGetLastError()) { | 3415 | switch (ws2_32.WSAGetLastError()) { |
| 3384 | .EINTR => continue, | 3416 | .EINTR => continue, |
| 3385 | .ECANCELLED, .E_CANCELLED => return error.Canceled, | 3417 | .ECANCELLED, .E_CANCELLED => return error.Canceled, |
| 3386 | .NOTINITIALISED => { | 3418 | .NOTINITIALISED => { |