| ... | @@ -2724,6 +2724,9 @@ pub const SocketError = error{ | ... | @@ -2724,6 +2724,9 @@ pub const SocketError = error{ |
| 2724 | | 2724 | |
| 2725 | /// The socket type is not supported by the protocol. | 2725 | /// The socket type is not supported by the protocol. |
| 2726 | SocketTypeNotSupported, | 2726 | SocketTypeNotSupported, |
| | 2727 | |
| | 2728 | /// The environment for socket control has not been initialised. |
| | 2729 | NotInitialised, |
| 2727 | } || UnexpectedError; | 2730 | } || UnexpectedError; |
| 2728 | | 2731 | |
| 2729 | pub fn socket(domain: u32, socket_type: u32, protocol: u32) SocketError!socket_t { | 2732 | pub fn socket(domain: u32, socket_type: u32, protocol: u32) SocketError!socket_t { |
| ... | @@ -2731,7 +2734,19 @@ pub fn socket(domain: u32, socket_type: u32, protocol: u32) SocketError!socket_t | ... | @@ -2731,7 +2734,19 @@ pub fn socket(domain: u32, socket_type: u32, protocol: u32) SocketError!socket_t |
| 2731 | // NOTE: windows translates the SOCK_NONBLOCK/SOCK_CLOEXEC flags into windows-analagous operations | 2734 | // NOTE: windows translates the SOCK_NONBLOCK/SOCK_CLOEXEC flags into windows-analagous operations |
| 2732 | const filtered_sock_type = socket_type & ~@as(u32, SOCK_NONBLOCK | SOCK_CLOEXEC); | 2735 | const filtered_sock_type = socket_type & ~@as(u32, SOCK_NONBLOCK | SOCK_CLOEXEC); |
| 2733 | const flags: u32 = if ((socket_type & SOCK_CLOEXEC) != 0) windows.ws2_32.WSA_FLAG_NO_HANDLE_INHERIT else 0; | 2736 | const flags: u32 = if ((socket_type & SOCK_CLOEXEC) != 0) windows.ws2_32.WSA_FLAG_NO_HANDLE_INHERIT else 0; |
| 2734 | const rc = try windows.WSASocketW(@bitCast(i32, domain), @bitCast(i32, filtered_sock_type), @bitCast(i32, protocol), null, 0, flags); | 2737 | const rc = windows.WSASocketW(@bitCast(i32, domain), @bitCast(i32, filtered_sock_type), @bitCast(i32, protocol), null, 0, flags) catch |err| switch (err) { |
| | 2738 | error.NotInitialised => again: { |
| | 2739 | // Before a socket is made Windows requires WSAStartup to be called. |
| | 2740 | // Let's try doing that now, then make the socket again. If socket creation still fails then there is an underlying issue we cannot solve. |
| | 2741 | // WSAStartup is supposed to have a pair in the form of WSACleanup to call once all socket operations concluded. |
| | 2742 | // As of writing that function is never called. |
| | 2743 | _ = windows.WSAStartup(2, 2) catch { |
| | 2744 | return error.NotInitialised; |
| | 2745 | }; |
| | 2746 | break :again try windows.WSASocketW(@bitCast(i32, domain), @bitCast(i32, filtered_sock_type), @bitCast(i32, protocol), null, 0, flags); |
| | 2747 | }, |
| | 2748 | else => return err, |
| | 2749 | }; |
| 2735 | errdefer windows.closesocket(rc) catch unreachable; | 2750 | errdefer windows.closesocket(rc) catch unreachable; |
| 2736 | if ((socket_type & SOCK_NONBLOCK) != 0) { | 2751 | if ((socket_type & SOCK_NONBLOCK) != 0) { |
| 2737 | var mode: c_ulong = 1; // nonblocking | 2752 | var mode: c_ulong = 1; // nonblocking |