diff --git a/NEWS b/NEWS index 81e0a6d..d25a97c 100644 --- a/NEWS +++ b/NEWS @@ -7,8 +7,10 @@ libmodbus 2.2.0 (2009-05-01) - modbus_param_t is smaller (2 int removed) - Better error management - Faster -- Fix #333455 reported by Jeff Laughlin +- Fix #333455 reported by Jeff Laughlin and Yishin Li. Cygwin IPTOS_LOWDELAY not supported on cygwin +- Fix #375926 - modbus.c:164: error: `MSG_DONTWAIT' undeclared + Reported and tested by Yishin Li. libmodbus 2.0.3 (2009-03-22) ============================ diff --git a/configure.ac b/configure.ac index 288deb3..1ba1855 100644 --- a/configure.ac +++ b/configure.ac @@ -26,9 +26,10 @@ AC_HEADER_TIME AC_TYPE_UINT16_T AC_TYPE_UINT32_T AC_TYPE_UINT8_T -AC_CHECK_DECLS([IPTOS_LOWDELAY], - [have_iptos_lowdelay=yes], [have_iptos_lowdelay=no], - [#include ]) + +# Cygwin defines IPTOS_LOWDELAY but can't handle that flag so it's necessary to +# workaround that problem and Cygwin doesn't define MSG_DONTWAIT. +AC_CHECK_DECLS([__CYGWIN__]) # Checks for library functions. AC_FUNC_FORK diff --git a/src/modbus.c b/src/modbus.c index 004ce49..d9c88fb 100644 --- a/src/modbus.c +++ b/src/modbus.c @@ -152,23 +152,6 @@ static const int TAB_MAX_ADU_LENGTH[2] = { MAX_ADU_LENGTH_TCP, }; -void modbus_flush(modbus_param_t *mb_param) -{ - if (mb_param->type_com == RTU) { - tcflush(mb_param->fd, TCIOFLUSH); - } else { - int ret; - do { - /* Extract the garbage from the socket */ - char devnull[MAX_ADU_LENGTH_TCP]; - ret = recv(mb_param->fd, devnull, MAX_ADU_LENGTH_TCP, MSG_DONTWAIT); - if (mb_param->debug && ret > 0) { - printf("%d bytes flushed\n", ret); - } - } while (ret > 0); - } -} - /* Treats errors and flush or close connection if necessary */ static void error_treat(modbus_param_t *mb_param, int code, const char *string) { @@ -194,6 +177,42 @@ static void error_treat(modbus_param_t *mb_param, int code, const char *string) } } +void modbus_flush(modbus_param_t *mb_param) +{ + if (mb_param->type_com == RTU) { + tcflush(mb_param->fd, TCIOFLUSH); + } else { + int ret; + do { + /* Extract the garbage from the socket */ + char devnull[MAX_ADU_LENGTH_TCP]; +#if (!HAVE_DECL___CYGWIN__) + ret = recv(mb_param->fd, devnull, MAX_ADU_LENGTH_TCP, MSG_DONTWAIT); +#else + /* On Cygwin, it's a bit more complicated to not wait */ + fd_set rfds; + struct timeval tv; + + tv.tv_sec = 0; + tv.tv_usec = 0; + FD_ZERO(&rfds); + FD_SET(mb_param->fd, &rfds); + ret = select(mb_param->fd+1, &rfds, NULL, NULL, &tv); + if (ret > 0) { + ret = recv(mb_param->fd, devnull, MAX_ADU_LENGTH_TCP, 0); + } else if (ret == -1) { + /* error_treat() doesn't call modbus_flush() in + this case (avoid infinite loop) */ + error_treat(mb_param, SELECT_FAILURE, "Select failure"); + } +#endif + if (mb_param->debug && ret > 0) { + printf("%d bytes flushed\n", ret); + } + } while (ret > 0); + } +} + /* Computes the length of the expected response */ static unsigned int compute_response_length(modbus_param_t *mb_param, uint8_t *query) @@ -1686,7 +1705,11 @@ static int modbus_connect_tcp(modbus_param_t *mb_param) return ret; } -#ifdef HAVE_DECL_IPTOS_LOWDELAY +#if (!HAVE_DECL___CYGWIN__) + /** + * Cygwin defines IPTOS_LOWDELAY but can't handle that flag so it's + * necessary to workaround that problem. + **/ /* Set the IP low delay option */ option = IPTOS_LOWDELAY; ret = setsockopt(mb_param->fd, IPPROTO_TCP, IP_TOS,