If a socket manager finds winsock uninitialized, it will initialize it and remember to deinitialize it at cleanup
This commit is contained in:
@@ -1997,13 +1997,30 @@ static char *state_to_str(SocketState state)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int create_socket_pair(NATIVE_SOCKET *a, NATIVE_SOCKET *b)
|
static int create_socket_pair(NATIVE_SOCKET *a, NATIVE_SOCKET *b, bool *global_cleanup)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
SOCKET sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
SOCKET sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
if (sock == INVALID_SOCKET)
|
|
||||||
|
*global_cleanup = false;
|
||||||
|
if (sock == INVALID_SOCKET && WSAGetLastError() == WSANOTINITIALISED) {
|
||||||
|
|
||||||
|
WSADATA wsaData;
|
||||||
|
WORD wVersionRequested = MAKEWORD(2, 2);
|
||||||
|
if (WSAStartup(wVersionRequested, &wsaData))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
|
if (sock == INVALID_SOCKET && *global_cleanup)
|
||||||
|
WSACleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sock == INVALID_SOCKET) {
|
||||||
|
if (*global_cleanup)
|
||||||
|
WSACleanup();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
// Bind to loopback address with port 0 (dynamic port assignment)
|
// Bind to loopback address with port 0 (dynamic port assignment)
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in addr;
|
||||||
int addr_len = sizeof(addr);
|
int addr_len = sizeof(addr);
|
||||||
@@ -2014,16 +2031,22 @@ static int create_socket_pair(NATIVE_SOCKET *a, NATIVE_SOCKET *b)
|
|||||||
|
|
||||||
if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR) {
|
if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR) {
|
||||||
closesocket(sock);
|
closesocket(sock);
|
||||||
|
if (*global_cleanup)
|
||||||
|
WSACleanup();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getsockname(sock, (struct sockaddr*)&addr, &addr_len) == SOCKET_ERROR) {
|
if (getsockname(sock, (struct sockaddr*)&addr, &addr_len) == SOCKET_ERROR) {
|
||||||
closesocket(sock);
|
closesocket(sock);
|
||||||
|
if (*global_cleanup)
|
||||||
|
WSACleanup();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR) {
|
if (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR) {
|
||||||
closesocket(sock);
|
closesocket(sock);
|
||||||
|
if (*global_cleanup)
|
||||||
|
WSACleanup();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2032,6 +2055,8 @@ static int create_socket_pair(NATIVE_SOCKET *a, NATIVE_SOCKET *b)
|
|||||||
u_long mode = 1;
|
u_long mode = 1;
|
||||||
if (ioctlsocket(sock, FIONBIO, &mode) == SOCKET_ERROR) {
|
if (ioctlsocket(sock, FIONBIO, &mode) == SOCKET_ERROR) {
|
||||||
closesocket(sock);
|
closesocket(sock);
|
||||||
|
if (*global_cleanup)
|
||||||
|
WSACleanup();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2039,6 +2064,7 @@ static int create_socket_pair(NATIVE_SOCKET *a, NATIVE_SOCKET *b)
|
|||||||
*b = sock;
|
*b = sock;
|
||||||
return 0;
|
return 0;
|
||||||
#else
|
#else
|
||||||
|
*global_cleanup = false;
|
||||||
int fds[2];
|
int fds[2];
|
||||||
if (pipe(fds) < 0)
|
if (pipe(fds) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
@@ -2140,7 +2166,8 @@ int socket_manager_init(SocketManager *sm, Socket *socks,
|
|||||||
return -1;
|
return -1;
|
||||||
sm->plain_sock = NATIVE_SOCKET_INVALID;
|
sm->plain_sock = NATIVE_SOCKET_INVALID;
|
||||||
sm->secure_sock = NATIVE_SOCKET_INVALID;
|
sm->secure_sock = NATIVE_SOCKET_INVALID;
|
||||||
if (create_socket_pair(&sm->wait_sock, &sm->signal_sock) < 0)
|
if (create_socket_pair(&sm->wait_sock, &sm->signal_sock,
|
||||||
|
&sm->global_cleanup) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
sm->at_least_one_secure_connect = false;
|
sm->at_least_one_secure_connect = false;
|
||||||
|
|
||||||
@@ -2171,6 +2198,11 @@ void socket_manager_free(SocketManager *sm)
|
|||||||
if (sm->secure_sock != NATIVE_SOCKET_INVALID)
|
if (sm->secure_sock != NATIVE_SOCKET_INVALID)
|
||||||
CLOSE_NATIVE_SOCKET(sm->secure_sock);
|
CLOSE_NATIVE_SOCKET(sm->secure_sock);
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
if (sm->global_cleanup)
|
||||||
|
WSACleanup();
|
||||||
|
#endif
|
||||||
|
|
||||||
mutex_free(&sm->mutex);
|
mutex_free(&sm->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -530,6 +530,12 @@ typedef struct {
|
|||||||
ClientSecureContext client_secure_context;
|
ClientSecureContext client_secure_context;
|
||||||
ServerSecureContext server_secure_context;
|
ServerSecureContext server_secure_context;
|
||||||
|
|
||||||
|
// If the socket manager needed to initialize some
|
||||||
|
// global state for its initialization, this flag
|
||||||
|
// will be set so that it will remember to cleanup
|
||||||
|
// that state during deinitialization.
|
||||||
|
bool global_cleanup;
|
||||||
|
|
||||||
// Array of sockets. Structs with state FREE
|
// Array of sockets. Structs with state FREE
|
||||||
// are unused.
|
// are unused.
|
||||||
int num_used;
|
int num_used;
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ int main(void)
|
|||||||
HTTP_ResponseBuilder builder;
|
HTTP_ResponseBuilder builder;
|
||||||
if (http_server_next_request(&server, &request, &builder)) {
|
if (http_server_next_request(&server, &request, &builder)) {
|
||||||
http_response_builder_status(builder, 200);
|
http_response_builder_status(builder, 200);
|
||||||
|
http_response_builder_body(builder, HTTP_STR("Hello, world!"));
|
||||||
http_response_builder_send(builder);
|
http_response_builder_send(builder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+35
-3
@@ -28,13 +28,30 @@ static char *state_to_str(SocketState state)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int create_socket_pair(NATIVE_SOCKET *a, NATIVE_SOCKET *b)
|
static int create_socket_pair(NATIVE_SOCKET *a, NATIVE_SOCKET *b, bool *global_cleanup)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
SOCKET sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
SOCKET sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
if (sock == INVALID_SOCKET)
|
|
||||||
|
*global_cleanup = false;
|
||||||
|
if (sock == INVALID_SOCKET && WSAGetLastError() == WSANOTINITIALISED) {
|
||||||
|
|
||||||
|
WSADATA wsaData;
|
||||||
|
WORD wVersionRequested = MAKEWORD(2, 2);
|
||||||
|
if (WSAStartup(wVersionRequested, &wsaData))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
|
if (sock == INVALID_SOCKET && *global_cleanup)
|
||||||
|
WSACleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sock == INVALID_SOCKET) {
|
||||||
|
if (*global_cleanup)
|
||||||
|
WSACleanup();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
// Bind to loopback address with port 0 (dynamic port assignment)
|
// Bind to loopback address with port 0 (dynamic port assignment)
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in addr;
|
||||||
int addr_len = sizeof(addr);
|
int addr_len = sizeof(addr);
|
||||||
@@ -45,16 +62,22 @@ static int create_socket_pair(NATIVE_SOCKET *a, NATIVE_SOCKET *b)
|
|||||||
|
|
||||||
if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR) {
|
if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR) {
|
||||||
closesocket(sock);
|
closesocket(sock);
|
||||||
|
if (*global_cleanup)
|
||||||
|
WSACleanup();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getsockname(sock, (struct sockaddr*)&addr, &addr_len) == SOCKET_ERROR) {
|
if (getsockname(sock, (struct sockaddr*)&addr, &addr_len) == SOCKET_ERROR) {
|
||||||
closesocket(sock);
|
closesocket(sock);
|
||||||
|
if (*global_cleanup)
|
||||||
|
WSACleanup();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR) {
|
if (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR) {
|
||||||
closesocket(sock);
|
closesocket(sock);
|
||||||
|
if (*global_cleanup)
|
||||||
|
WSACleanup();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,6 +86,8 @@ static int create_socket_pair(NATIVE_SOCKET *a, NATIVE_SOCKET *b)
|
|||||||
u_long mode = 1;
|
u_long mode = 1;
|
||||||
if (ioctlsocket(sock, FIONBIO, &mode) == SOCKET_ERROR) {
|
if (ioctlsocket(sock, FIONBIO, &mode) == SOCKET_ERROR) {
|
||||||
closesocket(sock);
|
closesocket(sock);
|
||||||
|
if (*global_cleanup)
|
||||||
|
WSACleanup();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,6 +95,7 @@ static int create_socket_pair(NATIVE_SOCKET *a, NATIVE_SOCKET *b)
|
|||||||
*b = sock;
|
*b = sock;
|
||||||
return 0;
|
return 0;
|
||||||
#else
|
#else
|
||||||
|
*global_cleanup = false;
|
||||||
int fds[2];
|
int fds[2];
|
||||||
if (pipe(fds) < 0)
|
if (pipe(fds) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
@@ -171,7 +197,8 @@ int socket_manager_init(SocketManager *sm, Socket *socks,
|
|||||||
return -1;
|
return -1;
|
||||||
sm->plain_sock = NATIVE_SOCKET_INVALID;
|
sm->plain_sock = NATIVE_SOCKET_INVALID;
|
||||||
sm->secure_sock = NATIVE_SOCKET_INVALID;
|
sm->secure_sock = NATIVE_SOCKET_INVALID;
|
||||||
if (create_socket_pair(&sm->wait_sock, &sm->signal_sock) < 0)
|
if (create_socket_pair(&sm->wait_sock, &sm->signal_sock,
|
||||||
|
&sm->global_cleanup) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
sm->at_least_one_secure_connect = false;
|
sm->at_least_one_secure_connect = false;
|
||||||
|
|
||||||
@@ -202,6 +229,11 @@ void socket_manager_free(SocketManager *sm)
|
|||||||
if (sm->secure_sock != NATIVE_SOCKET_INVALID)
|
if (sm->secure_sock != NATIVE_SOCKET_INVALID)
|
||||||
CLOSE_NATIVE_SOCKET(sm->secure_sock);
|
CLOSE_NATIVE_SOCKET(sm->secure_sock);
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
if (sm->global_cleanup)
|
||||||
|
WSACleanup();
|
||||||
|
#endif
|
||||||
|
|
||||||
mutex_free(&sm->mutex);
|
mutex_free(&sm->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -213,6 +213,12 @@ typedef struct {
|
|||||||
ClientSecureContext client_secure_context;
|
ClientSecureContext client_secure_context;
|
||||||
ServerSecureContext server_secure_context;
|
ServerSecureContext server_secure_context;
|
||||||
|
|
||||||
|
// If the socket manager needed to initialize some
|
||||||
|
// global state for its initialization, this flag
|
||||||
|
// will be set so that it will remember to cleanup
|
||||||
|
// that state during deinitialization.
|
||||||
|
bool global_cleanup;
|
||||||
|
|
||||||
// Array of sockets. Structs with state FREE
|
// Array of sockets. Structs with state FREE
|
||||||
// are unused.
|
// are unused.
|
||||||
int num_used;
|
int num_used;
|
||||||
|
|||||||
Reference in New Issue
Block a user