diff --git a/CHANGELOG b/CHANGELOG index f024532..2fc311b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -10,6 +10,7 @@ Changes to version 1.1.0 - IEC 61850 server: added IedModel_getDeviceByInst function - SV subscriber: added subscriber side handling for RefrTm - SV publisher: Changed SampledValuesPublisher_create to support setting of Communication parameters at runtime +- socket-win32: updated WSA initialization handling - all: small fixes and code optimizations diff --git a/src/hal/socket/win32/socket_win32.c b/src/hal/socket/win32/socket_win32.c index a8d6560..777d17c 100644 --- a/src/hal/socket/win32/socket_win32.c +++ b/src/hal/socket/win32/socket_win32.c @@ -24,6 +24,7 @@ #include #include #include +#include #pragma comment (lib, "Ws2_32.lib") @@ -104,6 +105,9 @@ Handleset_destroy(HandleSet self) GLOBAL_FREEMEM(self); } +static bool wsaStartupCalled = false; +static int socketCount = 0; + static void activateKeepAlive(SOCKET s) { @@ -162,19 +166,47 @@ prepareServerAddress(const char* address, int port, struct sockaddr_in* sockaddr return true; } +static bool wsaStartUp() +{ + if (wsaStartupCalled == false) { + int ec; + WSADATA wsa; + + if ((ec = WSAStartup(MAKEWORD(2, 0), &wsa)) != 0) { + if (DEBUG_SOCKET) + printf("WIN32_SOCKET: winsock error: code %i\n", ec); + return false; + } + else { + wsaStartupCalled = true; + return true; + } + + } + else + return true; +} + +static void wsaShutdown() +{ + if (wsaStartupCalled) { + if (socketCount == 0) { + WSACleanup(); + wsaStartupCalled = false; + } + + } +} + ServerSocket TcpServerSocket_create(const char* address, int port) { ServerSocket serverSocket = NULL; int ec; - WSADATA wsa; SOCKET listen_socket = INVALID_SOCKET; - if ((ec = WSAStartup(MAKEWORD(2,0), &wsa)) != 0) { - if (DEBUG_SOCKET) - printf("WIN32_SOCKET: winsock error: code %i\n", ec); + if (wsaStartUp() == false) return NULL; - } struct sockaddr_in server_addr; @@ -190,7 +222,9 @@ TcpServerSocket_create(const char* address, int port) if (listen_socket == INVALID_SOCKET) { if (DEBUG_SOCKET) printf("WIN32_SOCKET: socket failed with error: %i\n", WSAGetLastError()); - WSACleanup(); + + wsaShutdown(); + return NULL; } @@ -203,7 +237,9 @@ TcpServerSocket_create(const char* address, int port) if (DEBUG_SOCKET) printf("WIN32_SOCKET: bind failed with error:%i\n", WSAGetLastError()); closesocket(listen_socket); - WSACleanup(); + + wsaShutdown(); + return NULL; } @@ -214,6 +250,8 @@ TcpServerSocket_create(const char* address, int port) setSocketNonBlocking((Socket) serverSocket); + socketCount++; + return serverSocket; } @@ -252,7 +290,8 @@ void ServerSocket_destroy(ServerSocket self) { closesocket(self->fd); - WSACleanup(); + socketCount--; + wsaShutdown(); GLOBAL_FREEMEM(self); } @@ -264,6 +303,8 @@ TcpSocket_create() self->fd = INVALID_SOCKET; self->connectTimeout = 5000; + socketCount++; + return self; } @@ -277,14 +318,10 @@ bool Socket_connect(Socket self, const char* address, int port) { struct sockaddr_in serverAddress; - WSADATA wsa; int ec; - if ((ec = WSAStartup(MAKEWORD(2,0), &wsa)) != 0) { - if (DEBUG_SOCKET) - printf("WIN32_SOCKET: winsock error: code %i\n", ec); + if (wsaStartUp() == false) return false; - } if (!prepareServerAddress(address, port, &serverAddress)) return false; @@ -401,5 +438,8 @@ Socket_destroy(Socket self) closesocket(self->fd); } + socketCount--; + wsaShutdown(); + GLOBAL_FREEMEM(self); }