| ... | ... | @@ -252,7 +252,7 @@ pub fn io(t: *Threaded) Io { |
| 252 | 252 | else => netBindIpPosix, |
| 253 | 253 | }, |
| 254 | 254 | .netConnectIp = switch (builtin.os.tag) { |
| 255 | | .windows => @panic("TODO"), |
| 255 | .windows => netConnectIpWindows, |
| 256 | 256 | else => netConnectIpPosix, |
| 257 | 257 | }, |
| 258 | 258 | .netConnectUnix = netConnectUnix, |
| ... | ... | @@ -2810,28 +2810,10 @@ fn netListenIpWindows( |
| 2810 | 2810 | if (!have_networking) return error.NetworkDown; |
| 2811 | 2811 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 2812 | 2812 | const family = posixAddressFamily(&address); |
| 2813 | | const mode = posixSocketMode(options.mode); |
| 2814 | | const protocol = posixProtocol(options.protocol); |
| 2815 | | |
| 2816 | | const socket_handle = while (true) { |
| 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 | | }; |
| 2813 | const socket_handle = try openSocketWsa(t, family, .{ |
| 2814 | .mode = options.mode, |
| 2815 | .protocol = options.protocol, |
| 2816 | }); |
| 2835 | 2817 | errdefer closeSocketWindows(socket_handle); |
| 2836 | 2818 | |
| 2837 | 2819 | if (options.reuse_address) |
| ... | ... | @@ -2885,24 +2867,7 @@ fn netListenIpWindows( |
| 2885 | 2867 | } |
| 2886 | 2868 | } |
| 2887 | 2869 | |
| 2888 | | while (true) { |
| 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 | | } |
| 2870 | try wsaGetSockName(t, socket_handle, &storage.any, &addr_len); |
| 2906 | 2871 | |
| 2907 | 2872 | return .{ |
| 2908 | 2873 | .socket = .{ |
| ... | ... | @@ -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 | 3065 | fn setSocketOption(t: *Threaded, fd: posix.fd_t, level: i32, opt_name: u32, option: u32) !void { |
| 3080 | 3066 | const o: []const u8 = @ptrCast(&option); |
| 3081 | 3067 | while (true) { |
| ... | ... | @@ -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 | 3183 | fn netConnectUnix( |
| 3143 | 3184 | userdata: ?*anyopaque, |
| 3144 | 3185 | address: *const net.UnixAddress, |
| ... | ... | @@ -3184,28 +3225,12 @@ fn netBindIpWindows( |
| 3184 | 3225 | if (!have_networking) return error.NetworkDown; |
| 3185 | 3226 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 3186 | 3227 | 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 | | }; |
| 3228 | const socket_handle = try openSocketWsa(t, family, .{ |
| 3229 | .mode = options.mode, |
| 3230 | .protocol = options.protocol, |
| 3231 | }); |
| 3208 | 3232 | errdefer closeSocketWindows(socket_handle); |
| 3233 | |
| 3209 | 3234 | var storage: WsaAddress = undefined; |
| 3210 | 3235 | var addr_len = addressToWsa(address, &storage); |
| 3211 | 3236 | |
| ... | ... | @@ -3231,24 +3256,7 @@ fn netBindIpWindows( |
| 3231 | 3256 | } |
| 3232 | 3257 | } |
| 3233 | 3258 | |
| 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 | | } |
| 3259 | try wsaGetSockName(t, socket_handle, &storage.any, &addr_len); |
| 3252 | 3260 | |
| 3253 | 3261 | return .{ |
| 3254 | 3262 | .handle = socket_handle, |
| ... | ... | @@ -3317,6 +3325,30 @@ fn openSocketPosix( |
| 3317 | 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 | 3352 | fn netAcceptPosix(userdata: ?*anyopaque, listen_fd: net.Socket.Handle) net.Server.AcceptError!net.Stream { |
| 3321 | 3353 | if (!have_networking) return error.NetworkDown; |
| 3322 | 3354 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| ... | ... | @@ -3376,11 +3408,11 @@ fn netAcceptWindows(userdata: ?*anyopaque, listen_handle: net.Socket.Handle) net |
| 3376 | 3408 | while (true) { |
| 3377 | 3409 | try t.checkCancel(); |
| 3378 | 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 | 3412 | .handle = rc, |
| 3381 | 3413 | .address = addressFromWsa(&storage), |
| 3382 | 3414 | } }; |
| 3383 | | switch (windows.ws2_32.WSAGetLastError()) { |
| 3415 | switch (ws2_32.WSAGetLastError()) { |
| 3384 | 3416 | .EINTR => continue, |
| 3385 | 3417 | .ECANCELLED, .E_CANCELLED => return error.Canceled, |
| 3386 | 3418 | .NOTINITIALISED => { |