Commit ea80f74094e3b313e348897a0f972fb3aa5df434

Authored by Stéphane Raimbault
1 parent 8941a84c

New API for set/get response and byte timeouts

- update documentation
- 5 new tests
- updated NEWS file
- avoid include of time.h
  1 +libmodbus 3.1.2 (2013-XX-XX)
  2 +============================
  3 +
  4 +This release introduces API changes on modbus_get_byte_timeout,
  5 +modbus_get_response_timeout, modbus_set_byte_timeout,
  6 +modbus_set_response_timeout to ease writing of language bindings.
  7 +
  8 +- New API to set/get response and byte timeouts.
  9 + New unit tests and updated documentation.
  10 +- Export Modbus function codes supported by libmodbus
  11 +- Fix bandwidth-server-one (closes #152)
  12 +- Check debug flag in RTU code
  13 +- Sync packaging with official from Debian (closes #134)
  14 +- Remove warnings caused by shadowed 'index' variable.
  15 + Thanks to Åke Forslund.
  16 +- Use accept4 in TCP PI if available
  17 +- Add documentation for tcp[_pi]_accept (closes #31)
  18 +- Fix mistake in modbus_tcp_listen documentation
  19 +- Add documentation for modbus_tcp_pi_listen
  20 +
1 libmodbus 3.1.1 (2013-10-06) 21 libmodbus 3.1.1 (2013-10-06)
2 ============================ 22 ============================
3 23
doc/modbus_get_byte_timeout.txt
@@ -9,28 +9,31 @@ modbus_get_byte_timeout - get timeout between bytes @@ -9,28 +9,31 @@ modbus_get_byte_timeout - get timeout between bytes
9 9
10 SYNOPSIS 10 SYNOPSIS
11 -------- 11 --------
12 -*int modbus_get_byte_timeout(modbus_t *'ctx', struct timeval *'timeout');* 12 +*int modbus_get_byte_timeout(modbus_t *'ctx', long *'to_sec', long *'to_usec');*
13 13
14 14
15 DESCRIPTION 15 DESCRIPTION
16 ----------- 16 -----------
17 The _modbus_get_byte_timeout()_ function shall store the timeout interval 17 The _modbus_get_byte_timeout()_ function shall store the timeout interval
18 -between two consecutive bytes of the same message in the 'timeout' argument. 18 +between two consecutive bytes of the same message in the _to_sec_ and _to_usec_
  19 +arguments.
19 20
20 21
21 RETURN VALUE 22 RETURN VALUE
22 ------------ 23 ------------
23 -The function shall return 0 if successful. Otherwise it shall return -1 and set errno. 24 +The function shall return 0 if successful. Otherwise it shall return -1 and set
  25 +errno.
24 26
25 27
26 EXAMPLE 28 EXAMPLE
27 ------- 29 -------
28 [source,c] 30 [source,c]
29 ------------------- 31 -------------------
30 -struct timeval byte_timeout; 32 +long to_sec;
  33 +long to_usec;
31 34
32 /* Save original timeout */ 35 /* Save original timeout */
33 -modbus_get_byte_timeout(ctx, &byte_timeout); 36 +modbus_get_byte_timeout(ctx, &to_sec, &to_usec);
34 ------------------- 37 -------------------
35 38
36 39
doc/modbus_get_response_timeout.txt
@@ -9,34 +9,33 @@ modbus_get_response_timeout - get timeout for response @@ -9,34 +9,33 @@ modbus_get_response_timeout - get timeout for response
9 9
10 SYNOPSIS 10 SYNOPSIS
11 -------- 11 --------
12 -*int modbus_get_response_timeout(modbus_t *'ctx', struct timeval *'timeout');* 12 +*int modbus_get_response_timeout(modbus_t *'ctx', long *'to_sec', long *'to_usec');*
13 13
14 14
15 DESCRIPTION 15 DESCRIPTION
16 ----------- 16 -----------
17 -The _modbus_get_response_timeout()_ function shall store the timeout interval  
18 -used to wait for a response in the 'timeout' argument. 17 +The _modbus_get_response_timeout()_ function shall return the timeout interval
  18 +used to wait for a response in the _to_sec_ and _to_usec_ arguments.
19 19
20 20
21 RETURN VALUE 21 RETURN VALUE
22 ------------ 22 ------------
23 -The function shall return 0 if successful. Otherwise it shall return -1 and set errno. 23 +The function shall return 0 if successful. Otherwise it shall return -1 and set
  24 +errno.
24 25
25 26
26 EXAMPLE 27 EXAMPLE
27 ------- 28 -------
28 [source,c] 29 [source,c]
29 ------------------- 30 -------------------
30 -struct timeval old_response_timeout;  
31 -struct timeval response_timeout; 31 +long old_response_to_sec;
  32 +long old_response_to_usec;
32 33
33 /* Save original timeout */ 34 /* Save original timeout */
34 -modbus_get_response_timeout(ctx, &old_response_timeout); 35 +modbus_get_response_timeout(ctx, &old_response_to_sec, &old_response_to_usec);
35 36
36 /* Define a new and too short timeout! */ 37 /* Define a new and too short timeout! */
37 -response_timeout.tv_sec = 0;  
38 -response_timeout.tv_usec = 0;  
39 -modbus_set_response_timeout(ctx, &response_timeout); 38 +modbus_set_response_timeout(ctx, 0, 0);
40 ------------------- 39 -------------------
41 40
42 41
doc/modbus_set_byte_timeout.txt
@@ -9,23 +9,35 @@ modbus_set_byte_timeout - set timeout between bytes @@ -9,23 +9,35 @@ modbus_set_byte_timeout - set timeout between bytes
9 9
10 SYNOPSIS 10 SYNOPSIS
11 -------- 11 --------
12 -*void modbus_set_byte_timeout(modbus_t *'ctx', struct timeval *'timeout');* 12 +*void modbus_set_byte_timeout(modbus_t *'ctx', long 'to_sec', long 'to_usec');*
13 13
14 14
15 DESCRIPTION 15 DESCRIPTION
16 ----------- 16 -----------
17 The _modbus_set_byte_timeout()_ function shall set the timeout interval between 17 The _modbus_set_byte_timeout()_ function shall set the timeout interval between
18 -two consecutive bytes of the same message. If the delay between is longer than  
19 -the given timeout, an error will be raised. 18 +two consecutive bytes of the same message. If the delay between bytes is longer
  19 +than the given timeout, the 'ETIMEDOUT' error will be raised by the the function
  20 +waiting for a response.
20 21
21 -If the timeout value has a tv_sec of -1 then this timeout will not be used at  
22 -all. This results in modbus_set_response_timeout governing the entire timeout  
23 -duration of an operation. 22 +The value of _to_usec_ argument must be in the range 0 to 999999.
  23 +
  24 +If _to_sec_ is set to -1 then this timeout will not be used at all. In this
  25 +case, _modbus_set_response_timeout()_ governs the entire handling of the
  26 +response, the full confirmation response must be received before expiration of
  27 +the response timeout. When a byte timeout is set, the response timeout is only
  28 +used to wait for the first byte of the respone.
24 29
25 30
26 RETURN VALUE 31 RETURN VALUE
27 ------------ 32 ------------
28 -The function shall return 0 if successful. Otherwise it shall return -1 and set errno. 33 +The function shall return 0 if successful. Otherwise it shall return -1 and set
  34 +errno.
  35 +
  36 +
  37 +ERRORS
  38 +------
  39 +*EINVAL*::
  40 +The argument _ctx_ is NULL or _to_usec_ is not smaller than 1000000.
29 41
30 42
31 SEE ALSO 43 SEE ALSO
doc/modbus_set_response_timeout.txt
@@ -9,35 +9,47 @@ modbus_set_response_timeout - set timeout for response @@ -9,35 +9,47 @@ modbus_set_response_timeout - set timeout for response
9 9
10 SYNOPSIS 10 SYNOPSIS
11 -------- 11 --------
12 -*int modbus_set_response_timeout(modbus_t *'ctx', struct timeval *'timeout');* 12 +*int modbus_set_response_timeout(modbus_t *'ctx', long 'to_sec', long 'to_usec');*
13 13
14 14
15 DESCRIPTION 15 DESCRIPTION
16 ----------- 16 -----------
  17 +
17 The _modbus_set_response_timeout()_ function shall set the timeout interval used 18 The _modbus_set_response_timeout()_ function shall set the timeout interval used
18 -to wait for a response. If the waiting before receiving the response is longer than  
19 -the given timeout, an error will be raised. 19 +to wait for a response. When a byte timeout is set, if the waiting before
  20 +receiving the first byte of response is longer than the given timeout, the
  21 +'ETIMEDOUT' error will be raised by the function waiting for a response. When
  22 +byte timeout is disabled, the full confirmation response must be received before
  23 +expiration of the response timeout.
  24 +
  25 +The value of to_usec argument must be in the range 0 to 999999.
20 26
21 27
22 RETURN VALUE 28 RETURN VALUE
23 ------------ 29 ------------
24 -The function shall return 0 if successful. Otherwise it shall return -1 and set errno. 30 +The function shall return 0 if successful. Otherwise it shall return -1 and set
  31 +errno.
  32 +
  33 +
  34 +ERRORS
  35 +------
  36 +*EINVAL*::
  37 +The argument _ctx_ is NULL or _to_sec_/_to_usec_ aren't equal or greater than 0 or
  38 +_to_usec_ is not smaller than 1000000.
25 39
26 40
27 EXAMPLE 41 EXAMPLE
28 ------- 42 -------
29 [source,c] 43 [source,c]
30 ------------------- 44 -------------------
31 -struct timeval old_response_timeout;  
32 -struct timeval response_timeout; 45 +long old_response_to_sec;
  46 +long old_response_to_usec;
33 47
34 /* Save original timeout */ 48 /* Save original timeout */
35 -modbus_get_response_timeout(ctx, &old_response_timeout); 49 +modbus_get_response_timeout(ctx, &old_response_to_sec, &old_response_to_usec);
36 50
37 /* Define a new and too short timeout! */ 51 /* Define a new and too short timeout! */
38 -response_timeout.tv_sec = 0;  
39 -response_timeout.tv_usec = 0;  
40 -modbus_set_response_timeout(ctx, &response_timeout); 52 +modbus_set_response_timeout(ctx, 0, 0);
41 ------------------- 53 -------------------
42 54
43 55
src/modbus.c
@@ -104,6 +104,7 @@ void _error_print(modbus_t *ctx, const char *context) @@ -104,6 +104,7 @@ void _error_print(modbus_t *ctx, const char *context)
104 104
105 static void _sleep_response_timeout(modbus_t *ctx) 105 static void _sleep_response_timeout(modbus_t *ctx)
106 { 106 {
  107 + /* Response timeout is always positive */
107 #ifdef _WIN32 108 #ifdef _WIN32
108 /* usleep doesn't exist on Windows */ 109 /* usleep doesn't exist on Windows */
109 Sleep((ctx->response_timeout.tv_sec * 1000) + 110 Sleep((ctx->response_timeout.tv_sec * 1000) +
@@ -112,10 +113,10 @@ static void _sleep_response_timeout(modbus_t *ctx) @@ -112,10 +113,10 @@ static void _sleep_response_timeout(modbus_t *ctx)
112 /* usleep source code */ 113 /* usleep source code */
113 struct timespec request, remaining; 114 struct timespec request, remaining;
114 request.tv_sec = ctx->response_timeout.tv_sec; 115 request.tv_sec = ctx->response_timeout.tv_sec;
115 - request.tv_nsec = ((long int)ctx->response_timeout.tv_usec % 1000000)  
116 - * 1000;  
117 - while (nanosleep(&request, &remaining) == -1 && errno == EINTR) 116 + request.tv_nsec = ((long int)ctx->response_timeout.tv_usec) * 1000;
  117 + while (nanosleep(&request, &remaining) == -1 && errno == EINTR) {
118 request = remaining; 118 request = remaining;
  119 + }
119 #endif 120 #endif
120 } 121 }
121 122
@@ -459,7 +460,7 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type) @@ -459,7 +460,7 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type)
459 } 460 }
460 } 461 }
461 462
462 - if (length_to_read > 0 && ctx->byte_timeout.tv_sec != -1) { 463 + if (length_to_read > 0 && ctx->byte_timeout.tv_sec >= 0 && ctx->byte_timeout.tv_usec >= 0) {
463 /* If there is no character in the buffer, the allowed timeout 464 /* If there is no character in the buffer, the allowed timeout
464 interval between two consecutive bytes is defined by 465 interval between two consecutive bytes is defined by
465 byte_timeout */ 466 byte_timeout */
@@ -467,6 +468,8 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type) @@ -467,6 +468,8 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type)
467 tv.tv_usec = ctx->byte_timeout.tv_usec; 468 tv.tv_usec = ctx->byte_timeout.tv_usec;
468 p_tv = &tv; 469 p_tv = &tv;
469 } 470 }
  471 + /* else timeout isn't set again, the full response must be read before
  472 + expiration of response timeout (for CONFIRMATION only) */
470 } 473 }
471 474
472 if (ctx->debug) 475 if (ctx->debug)
@@ -1639,48 +1642,54 @@ int modbus_get_socket(modbus_t *ctx) @@ -1639,48 +1642,54 @@ int modbus_get_socket(modbus_t *ctx)
1639 } 1642 }
1640 1643
1641 /* Get the timeout interval used to wait for a response */ 1644 /* Get the timeout interval used to wait for a response */
1642 -int modbus_get_response_timeout(modbus_t *ctx, struct timeval *timeout) 1645 +int modbus_get_response_timeout(modbus_t *ctx, long *to_sec, long *to_usec)
1643 { 1646 {
1644 if (ctx == NULL) { 1647 if (ctx == NULL) {
1645 errno = EINVAL; 1648 errno = EINVAL;
1646 return -1; 1649 return -1;
1647 } 1650 }
1648 1651
1649 - *timeout = ctx->response_timeout; 1652 + *to_sec = ctx->response_timeout.tv_sec;
  1653 + *to_usec = ctx->response_timeout.tv_usec;
1650 return 0; 1654 return 0;
1651 } 1655 }
1652 1656
1653 -int modbus_set_response_timeout(modbus_t *ctx, const struct timeval *timeout) 1657 +int modbus_set_response_timeout(modbus_t *ctx, long to_sec, long to_usec)
1654 { 1658 {
1655 - if (ctx == NULL) { 1659 + if (ctx == NULL ||
  1660 + to_sec < 0 || to_usec < 0 || to_usec > 999999) {
1656 errno = EINVAL; 1661 errno = EINVAL;
1657 return -1; 1662 return -1;
1658 } 1663 }
1659 1664
1660 - ctx->response_timeout = *timeout; 1665 + ctx->response_timeout.tv_sec = to_sec;
  1666 + ctx->response_timeout.tv_usec = to_usec;
1661 return 0; 1667 return 0;
1662 } 1668 }
1663 1669
1664 /* Get the timeout interval between two consecutive bytes of a message */ 1670 /* Get the timeout interval between two consecutive bytes of a message */
1665 -int modbus_get_byte_timeout(modbus_t *ctx, struct timeval *timeout) 1671 +int modbus_get_byte_timeout(modbus_t *ctx, long *to_sec, long *to_usec)
1666 { 1672 {
1667 if (ctx == NULL) { 1673 if (ctx == NULL) {
1668 errno = EINVAL; 1674 errno = EINVAL;
1669 return -1; 1675 return -1;
1670 } 1676 }
1671 1677
1672 - *timeout = ctx->byte_timeout; 1678 + *to_sec = ctx->byte_timeout.tv_sec;
  1679 + *to_usec = ctx->byte_timeout.tv_usec;
1673 return 0; 1680 return 0;
1674 } 1681 }
1675 1682
1676 -int modbus_set_byte_timeout(modbus_t *ctx, const struct timeval *timeout) 1683 +int modbus_set_byte_timeout(modbus_t *ctx, long to_sec, long to_usec)
1677 { 1684 {
1678 - if (ctx == NULL) { 1685 + /* Byte timeout can be disabled with negative values */
  1686 + if (ctx == NULL || to_usec > 999999) {
1679 errno = EINVAL; 1687 errno = EINVAL;
1680 return -1; 1688 return -1;
1681 } 1689 }
1682 1690
1683 - ctx->byte_timeout = *timeout; 1691 + ctx->byte_timeout.tv_sec = to_sec;
  1692 + ctx->byte_timeout.tv_usec = to_usec;
1684 return 0; 1693 return 0;
1685 } 1694 }
1686 1695
src/modbus.h
@@ -26,10 +26,8 @@ @@ -26,10 +26,8 @@
26 26
27 #ifndef _MSC_VER 27 #ifndef _MSC_VER
28 #include <stdint.h> 28 #include <stdint.h>
29 -#include <sys/time.h>  
30 #else 29 #else
31 #include "stdint.h" 30 #include "stdint.h"
32 -#include <time.h>  
33 #endif 31 #endif
34 32
35 #include "modbus-version.h" 33 #include "modbus-version.h"
@@ -174,11 +172,11 @@ MODBUS_API int modbus_set_error_recovery(modbus_t *ctx, modbus_error_recovery_mo @@ -174,11 +172,11 @@ MODBUS_API int modbus_set_error_recovery(modbus_t *ctx, modbus_error_recovery_mo
174 MODBUS_API int modbus_set_socket(modbus_t *ctx, int s); 172 MODBUS_API int modbus_set_socket(modbus_t *ctx, int s);
175 MODBUS_API int modbus_get_socket(modbus_t *ctx); 173 MODBUS_API int modbus_get_socket(modbus_t *ctx);
176 174
177 -MODBUS_API int modbus_get_response_timeout(modbus_t *ctx, struct timeval *timeout);  
178 -MODBUS_API int modbus_set_response_timeout(modbus_t *ctx, const struct timeval *timeout); 175 +MODBUS_API int modbus_get_response_timeout(modbus_t *ctx, long *to_sec, long *to_usec);
  176 +MODBUS_API int modbus_set_response_timeout(modbus_t *ctx, long to_sec, long to_usec);
179 177
180 -MODBUS_API int modbus_get_byte_timeout(modbus_t *ctx, struct timeval *timeout);  
181 -MODBUS_API int modbus_set_byte_timeout(modbus_t *ctx, const struct timeval *timeout); 178 +MODBUS_API int modbus_get_byte_timeout(modbus_t *ctx, long *to_sec, long *to_usec);
  179 +MODBUS_API int modbus_set_byte_timeout(modbus_t *ctx, long to_sec, long to_usec);
182 180
183 MODBUS_API int modbus_get_header_length(modbus_t *ctx); 181 MODBUS_API int modbus_get_header_length(modbus_t *ctx);
184 182
@@ -202,8 +200,8 @@ MODBUS_API int modbus_write_bits(modbus_t *ctx, int addr, int nb, const uint8_t @@ -202,8 +200,8 @@ MODBUS_API int modbus_write_bits(modbus_t *ctx, int addr, int nb, const uint8_t
202 MODBUS_API int modbus_write_registers(modbus_t *ctx, int addr, int nb, const uint16_t *data); 200 MODBUS_API int modbus_write_registers(modbus_t *ctx, int addr, int nb, const uint16_t *data);
203 MODBUS_API int modbus_mask_write_register(modbus_t *ctx, int addr, uint16_t and_mask, uint16_t or_mask); 201 MODBUS_API int modbus_mask_write_register(modbus_t *ctx, int addr, uint16_t and_mask, uint16_t or_mask);
204 MODBUS_API int modbus_write_and_read_registers(modbus_t *ctx, int write_addr, int write_nb, 202 MODBUS_API int modbus_write_and_read_registers(modbus_t *ctx, int write_addr, int write_nb,
205 - const uint16_t *src, int read_addr, int read_nb,  
206 - uint16_t *dest); 203 + const uint16_t *src, int read_addr, int read_nb,
  204 + uint16_t *dest);
207 MODBUS_API int modbus_report_slave_id(modbus_t *ctx, uint8_t *dest); 205 MODBUS_API int modbus_report_slave_id(modbus_t *ctx, uint8_t *dest);
208 206
209 MODBUS_API modbus_mapping_t* modbus_mapping_new(int nb_bits, int nb_input_bits, 207 MODBUS_API modbus_mapping_t* modbus_mapping_new(int nb_bits, int nb_input_bits,
@@ -218,9 +216,9 @@ MODBUS_API int modbus_receive_from(modbus_t *ctx, int sockfd, uint8_t *req); @@ -218,9 +216,9 @@ MODBUS_API int modbus_receive_from(modbus_t *ctx, int sockfd, uint8_t *req);
218 MODBUS_API int modbus_receive_confirmation(modbus_t *ctx, uint8_t *rsp); 216 MODBUS_API int modbus_receive_confirmation(modbus_t *ctx, uint8_t *rsp);
219 217
220 MODBUS_API int modbus_reply(modbus_t *ctx, const uint8_t *req, 218 MODBUS_API int modbus_reply(modbus_t *ctx, const uint8_t *req,
221 - int req_length, modbus_mapping_t *mb_mapping); 219 + int req_length, modbus_mapping_t *mb_mapping);
222 MODBUS_API int modbus_reply_exception(modbus_t *ctx, const uint8_t *req, 220 MODBUS_API int modbus_reply_exception(modbus_t *ctx, const uint8_t *req,
223 - unsigned int exception_code); 221 + unsigned int exception_code);
224 222
225 /** 223 /**
226 * UTILS FUNCTIONS 224 * UTILS FUNCTIONS
tests/unit-test-client.c
@@ -44,8 +44,8 @@ int main(int argc, char *argv[]) @@ -44,8 +44,8 @@ int main(int argc, char *argv[])
44 int rc; 44 int rc;
45 float real; 45 float real;
46 uint32_t ireal; 46 uint32_t ireal;
47 - struct timeval old_response_timeout;  
48 - struct timeval response_timeout; 47 + long old_response_timeout_sec;
  48 + long old_response_timeout_usec;
49 int use_backend; 49 int use_backend;
50 50
51 if (argc > 1) { 51 if (argc > 1) {
@@ -647,27 +647,82 @@ int main(int argc, char *argv[]) @@ -647,27 +647,82 @@ int main(int argc, char *argv[])
647 } 647 }
648 648
649 /* Save original timeout */ 649 /* Save original timeout */
650 - modbus_get_response_timeout(ctx, &old_response_timeout); 650 + modbus_get_response_timeout(ctx, &old_response_timeout_sec, &old_response_timeout_usec);
651 651
652 - /* Define a new and too short timeout */  
653 - response_timeout.tv_sec = 0;  
654 - response_timeout.tv_usec = 0;  
655 - modbus_set_response_timeout(ctx, &response_timeout); 652 + rc = modbus_set_response_timeout(ctx, -1, 0);
  653 + printf("1/6 Invalid response timeout (negative): ");
  654 + if (rc == -1 && errno == EINVAL) {
  655 + printf("OK\n");
  656 + } else {
  657 + printf("FAILED\n");
  658 + goto close;
  659 + }
  660 +
  661 + rc = modbus_set_response_timeout(ctx, 0, 1000000);
  662 + printf("2/6 Invalid response timeout (too large): ");
  663 + if (rc == -1 && errno == EINVAL) {
  664 + printf("OK\n");
  665 + } else {
  666 + printf("FAILED\n");
  667 + goto close;
  668 + }
656 669
  670 + rc = modbus_set_byte_timeout(ctx, 0, 1000000);
  671 + printf("3/6 Invalid byte timeout (too large): ");
  672 + if (rc == -1 && errno == EINVAL) {
  673 + printf("OK\n");
  674 + } else {
  675 + printf("FAILED\n");
  676 + goto close;
  677 + }
  678 +
  679 + modbus_set_response_timeout(ctx, 0, 0);
657 rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS, 680 rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
658 UT_REGISTERS_NB, tab_rp_registers); 681 UT_REGISTERS_NB, tab_rp_registers);
659 - printf("4/4 Too short timeout: "); 682 + printf("4/6 Zero response timeout: ");
660 if (rc == -1 && errno == ETIMEDOUT) { 683 if (rc == -1 && errno == ETIMEDOUT) {
661 printf("OK\n"); 684 printf("OK\n");
662 } else { 685 } else {
663 printf("FAILED (can fail on slow systems or Windows)\n"); 686 printf("FAILED (can fail on slow systems or Windows)\n");
664 } 687 }
665 688
666 - /* Restore original timeout */  
667 - modbus_set_response_timeout(ctx, &old_response_timeout);  
668 -  
669 /* A wait and flush operation is done by the error recovery code of 689 /* A wait and flush operation is done by the error recovery code of
670 - * libmodbus */ 690 + * libmodbus but after a sleep of current response timeout
  691 + * so 0 can't be too short!
  692 + */
  693 + usleep(old_response_timeout_sec * 1000000 + old_response_timeout_usec);
  694 + modbus_flush(ctx);
  695 +
  696 + /* Trigger a special behaviour on server to wait for 0.5 second before
  697 + * replying whereas allowed timeout is 0.2 second */
  698 + modbus_set_response_timeout(ctx, 0, 200000);
  699 + rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS_SLEEP_500_MS,
  700 + 1, tab_rp_registers);
  701 + printf("5/6 Too short response timeout (0.2s < 0.5s): ");
  702 + if (rc == -1 && errno == ETIMEDOUT) {
  703 + printf("OK\n");
  704 + } else {
  705 + printf("FAILED\n");
  706 + goto close;
  707 + }
  708 +
  709 + /* Wait for reply (0.2 + 0.4 > 0.5 s) and flush before continue */
  710 + usleep(400000);
  711 + modbus_flush(ctx);
  712 +
  713 + modbus_set_response_timeout(ctx, 0, 600000);
  714 + rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS_SLEEP_500_MS,
  715 + 1, tab_rp_registers);
  716 + printf("6/6 Adequate response timeout (0.6s > 0.5s): ");
  717 + if (rc == 1) {
  718 + printf("OK\n");
  719 + } else {
  720 + printf("FAILED\n");
  721 + goto close;
  722 + }
  723 +
  724 + /* Restore original timeout */
  725 + modbus_set_response_timeout(ctx, old_response_timeout_sec, old_response_timeout_usec);
671 726
672 /** BAD RESPONSE **/ 727 /** BAD RESPONSE **/
673 printf("\nTEST BAD RESPONSE ERROR:\n"); 728 printf("\nTEST BAD RESPONSE ERROR:\n");
@@ -675,6 +730,7 @@ int main(int argc, char *argv[]) @@ -675,6 +730,7 @@ int main(int argc, char *argv[])
675 /* Allocate only the required space */ 730 /* Allocate only the required space */
676 tab_rp_registers_bad = (uint16_t *) malloc( 731 tab_rp_registers_bad = (uint16_t *) malloc(
677 UT_REGISTERS_NB_SPECIAL * sizeof(uint16_t)); 732 UT_REGISTERS_NB_SPECIAL * sizeof(uint16_t));
  733 +
678 rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS, 734 rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
679 UT_REGISTERS_NB_SPECIAL, tab_rp_registers_bad); 735 UT_REGISTERS_NB_SPECIAL, tab_rp_registers_bad);
680 printf("* modbus_read_registers: "); 736 printf("* modbus_read_registers: ");
@@ -684,14 +740,13 @@ int main(int argc, char *argv[]) @@ -684,14 +740,13 @@ int main(int argc, char *argv[])
684 printf("FAILED\n"); 740 printf("FAILED\n");
685 goto close; 741 goto close;
686 } 742 }
687 -  
688 free(tab_rp_registers_bad); 743 free(tab_rp_registers_bad);
689 744
690 /** MANUAL EXCEPTION **/ 745 /** MANUAL EXCEPTION **/
691 printf("\nTEST MANUAL EXCEPTION:\n"); 746 printf("\nTEST MANUAL EXCEPTION:\n");
692 -  
693 rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS_SPECIAL, 747 rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS_SPECIAL,
694 UT_REGISTERS_NB, tab_rp_registers); 748 UT_REGISTERS_NB, tab_rp_registers);
  749 +
695 printf("* modbus_read_registers at special address: "); 750 printf("* modbus_read_registers at special address: ");
696 if (rc == -1 && errno == EMBXSBUSY) { 751 if (rc == -1 && errno == EMBXSBUSY) {
697 printf("OK\n"); 752 printf("OK\n");
tests/unit-test-server.c
@@ -175,6 +175,10 @@ int main(int argc, char*argv[]) @@ -175,6 +175,10 @@ int main(int argc, char*argv[])
175 printf("Reply with an invalid TID or slave\n"); 175 printf("Reply with an invalid TID or slave\n");
176 modbus_send_raw_request(ctx, raw_req, RAW_REQ_LENGTH * sizeof(uint8_t)); 176 modbus_send_raw_request(ctx, raw_req, RAW_REQ_LENGTH * sizeof(uint8_t));
177 continue; 177 continue;
  178 + } else if (MODBUS_GET_INT16_FROM_INT8(query, header_length + 1)
  179 + == UT_REGISTERS_ADDRESS_SLEEP_500_MS) {
  180 + printf("Sleep 0.5 s before replying\n");
  181 + usleep(500000);
178 } 182 }
179 } 183 }
180 184
tests/unit-test.h.in
@@ -50,6 +50,8 @@ const uint16_t UT_REGISTERS_ADDRESS = 0x16B; @@ -50,6 +50,8 @@ const uint16_t UT_REGISTERS_ADDRESS = 0x16B;
50 const uint16_t UT_REGISTERS_ADDRESS_SPECIAL = 0x6C; 50 const uint16_t UT_REGISTERS_ADDRESS_SPECIAL = 0x6C;
51 /* The response of the server will contains an invalid TID or slave */ 51 /* The response of the server will contains an invalid TID or slave */
52 const uint16_t UT_REGISTERS_ADDRESS_INVALID_TID_OR_SLAVE = 0x6D; 52 const uint16_t UT_REGISTERS_ADDRESS_INVALID_TID_OR_SLAVE = 0x6D;
  53 +/* The server will wait for 1 second before replying to test timeout */
  54 +const uint16_t UT_REGISTERS_ADDRESS_SLEEP_500_MS = 0x6E;
53 55
54 const uint16_t UT_REGISTERS_NB = 0x3; 56 const uint16_t UT_REGISTERS_NB = 0x3;
55 const uint16_t UT_REGISTERS_TAB[] = { 0x022B, 0x0001, 0x0064 }; 57 const uint16_t UT_REGISTERS_TAB[] = { 0x022B, 0x0001, 0x0064 };