From c93876877c12a2b88d3da6d53e6303255f1d10f2 Mon Sep 17 00:00:00 2001 From: Keith Marshall Date: Wed, 8 Nov 2017 17:46:34 +0000 Subject: [PATCH] Overhaul WinSock fd_set content management macros. --- w32api/ChangeLog | 17 +++++++++++++ w32api/include/winsock.h | 64 ++++++++++++++++++++++++++++-------------------- w32api/tests/winsock.at | 2 +- 3 files changed, 56 insertions(+), 27 deletions(-) diff --git a/w32api/ChangeLog b/w32api/ChangeLog index d81c326..092ff33 100644 --- a/w32api/ChangeLog +++ b/w32api/ChangeLog @@ -1,3 +1,20 @@ +2017-11-08 Keith Marshall + + Overhaul WinSock fd_set content management macros. + + * include/winsock.h (FD_SET, FD_ISSET, FD_CLR, FD_ZERO): Replace the + original implementations of each of these macros, redirecting to... + (__FD_SET, __FD_ISSET, __FD_CLR, __FD_ZERO): ...these new, equivalent + inline functions, respectively; these are more robust, and correct a + defect in the original FD_SET macro implementation, whereby duplicate + descriptors could be added to an fd_set array, but would not then be + removed by the corresponding FD_CLR macro. + + * tests/winsock.at (MINGW_AT_CHECK_WINSOCK): Ensure that all test + programs are linked with -lwsock32 or -lws2_32, as appropriate; the + __FD_SET and __FD_ISSET functions are dependent on the __WSAFDIsSet() + function, which is implemented in each of these libraries. + 2017-11-07 Keith Marshall Identify features which have been deprecated in WinSock v2. diff --git a/w32api/include/winsock.h b/w32api/include/winsock.h index 789ab04..7049230 100644 --- a/w32api/include/winsock.h +++ b/w32api/include/winsock.h @@ -120,39 +120,51 @@ struct fd_set SOCKET fd_array[FD_SETSIZE]; } fd_set; -int PASCAL __WSAFDIsSet (SOCKET, fd_set *); +#ifndef FD_ISSET +int FD_ISSET (SOCKET, fd_set *); +#define FD_ISSET( __fd, __set ) __FD_ISSET ((__fd), (__set)) -#ifndef FD_CLR -#define FD_CLR( fd, set ) do \ - { u_int __i; \ - for (__i = 0; __i < ((fd_set *)(set))->fd_count ; __i++) \ - { if (((fd_set *)(set))->fd_array[__i] == (fd)) \ - { while (__i < ((fd_set *)(set))->fd_count-1) \ - { ((fd_set *)(set))->fd_array[__i] \ - = ((fd_set *)(set))->fd_array[__i + 1]; __i++; \ - } \ - ((fd_set *)(set))->fd_count--; \ - break; \ - } \ - } \ - } while (0) -#endif /* ! defined FD_CLR */ +/* Microsoft provide this library function equivalent of the FD_ISSET + * macro, and erroneously claim that it is neccessary to implement the + * macro. We could just as easily implement it entirely inline... + */ +int PASCAL __WSAFDIsSet (SOCKET, fd_set *); +/* ...but, given the availability of the library function, we may just + * as well use it. + */ +__CRT_ALIAS int __FD_ISSET( SOCKET __fd, fd_set *__set ) +{ return __WSAFDIsSet (__fd, __set); } +#endif /* ! defined FD_ISSET */ #ifndef FD_SET -#define FD_SET( fd, set ) do \ - { if (((fd_set *)(set))->fd_count < FD_SETSIZE) \ - ((fd_set *)(set))->fd_array[((fd_set *)(set))->fd_count++] = (fd); \ - } while (0) +void FD_SET (SOCKET, fd_set *); +#define FD_SET( __fd, __set ) __FD_SET ((__fd), (__set)) +__CRT_ALIAS void __FD_SET (SOCKET __fd, fd_set *__set) +{ if( (__set->fd_count < FD_SETSIZE) && ! FD_ISSET (__fd, __set) ) + __set->fd_array[__set->fd_count++] = __fd; +} #endif /* ! defined FD_SET */ +#ifndef FD_CLR +void FD_CLR (SOCKET, fd_set *); +#define FD_CLR( __fd, __set ) __FD_CLR ((__fd), (__set)) +__CRT_ALIAS void __FD_CLR (SOCKET __fd, fd_set *__set) +{ u_int __m, __n; for (__m = __n = 0; __n < __set->fd_count; __n++) + { if (__fd != __set->fd_array[__n]) + { if (__m < __n) __set->fd_array[__m] = __set->fd_array[__n]; + ++__m; + } + } __set->fd_count = __m; +} +#endif /* ! defined FD_CLR */ + #ifndef FD_ZERO -#define FD_ZERO( set ) (((fd_set *)(set))->fd_count = 0) +void FD_ZERO (fd_set *); +#define FD_ZERO( __set ) __FD_ZERO (__set) +__CRT_ALIAS void __FD_ZERO (fd_set *__set) +{ __set->fd_count = 0; } #endif /* ! defined FD_ZERO */ -#ifndef FD_ISSET -#define FD_ISSET( fd, set ) __WSAFDIsSet((SOCKET)(fd), (fd_set *)(set)) -#endif /* ! defined FD_ISSET */ - #elif ! defined _USE_SYS_TYPES_FD_SET /* Definitions from probably aren't what the user wants; * if they know what they are doing, and they are sure that this really @@ -562,7 +574,7 @@ int PASCAL gethostname (char *, int ); #define WSAGETSELECTEVENT(l) LOWORD(l) #define WSAGETSELECTERROR(l) HIWORD(l) -typedef struct fd_set FD_SET, *PFD_SET, *LPFD_SET; +typedef struct fd_set /* FD_SET, */ *PFD_SET, *LPFD_SET; typedef struct sockaddr SOCKADDR, *PSOCKADDR, *LPSOCKADDR; typedef struct sockaddr_in SOCKADDR_IN, *PSOCKADDR_IN, *LPSOCKADDR_IN; typedef struct linger LINGER, *PLINGER, *LPLINGER; diff --git a/w32api/tests/winsock.at b/w32api/tests/winsock.at index e92c31b..9879f60 100644 --- a/w32api/tests/winsock.at +++ b/w32api/tests/winsock.at @@ -97,6 +97,7 @@ AT_CLEANUP]) # m4_define([MINGW_AT_CHECK_WINSOCK],[dnl AT_BANNER([Windows Sockets $1 fd_set macro checks.]) +MINGW_AT_LINK_LIBS([m4_case([$1],[v2],[-lws2_32],[-lwsock32])]) # Verify that the FD_ZERO macro clears all descriptors from the # predefined, non-empty fd_set {1, 2, 3, 4} @@ -157,7 +158,6 @@ MINGW_AT_CHECK_FD_MACRO([$2],[FD_CLR],dnl # function, we must ensure that the test code is linked with # the appropriate version of the WinSock library. # -MINGW_AT_LINK_LIBS([m4_case([$1],[v2],[-lws2_32],[-lwsock32])]) MINGW_AT_CHECK_FD_ISSET_MACRO([$2],[4]) MINGW_AT_CHECK_FD_ISSET_MACRO([$2],[2]) -- 2.11.0