Browse Source

Error conventions of POSIX systems and error recovery

- returns -1 on error and set errno
- error recovery system was flawed
- error recovery disabled by default
- remove a malloc
Stéphane Raimbault 14 years ago
parent
commit
f0e7ad217d

File diff suppressed because it is too large
+ 344 - 271
modbus/modbus.c


+ 54 - 154
modbus/modbus.h

@@ -120,36 +120,47 @@ extern "C" {
 #define FC_PRESET_MULTIPLE_REGISTERS 0x10
 #define FC_PRESET_MULTIPLE_REGISTERS 0x10
 #define FC_REPORT_SLAVE_ID           0x11
 #define FC_REPORT_SLAVE_ID           0x11
 
 
+/* Random number to avoid errno conflicts */
+#define MODBUS_ENOBASE 112345678
+
 /* Protocol exceptions */
 /* Protocol exceptions */
-#define ILLEGAL_FUNCTION        -0x01
-#define ILLEGAL_DATA_ADDRESS    -0x02
-#define ILLEGAL_DATA_VALUE      -0x03
-#define SLAVE_DEVICE_FAILURE    -0x04
-#define SERVER_FAILURE          -0x04
-#define ACKNOWLEDGE             -0x05
-#define SLAVE_DEVICE_BUSY       -0x06
-#define SERVER_BUSY             -0x06
-#define NEGATIVE_ACKNOWLEDGE    -0x07
-#define MEMORY_PARITY_ERROR     -0x08
-#define GATEWAY_PROBLEM_PATH    -0x0A
-#define GATEWAY_PROBLEM_TARGET  -0x0B
-
-/* Local */
-#define INVALID_DATA            -0x10
-#define INVALID_CRC             -0x11
-#define INVALID_EXCEPTION_CODE  -0x12
-
-#define SELECT_TIMEOUT          -0x13
-#define SELECT_FAILURE          -0x14
-#define SOCKET_FAILURE          -0x15
-#define CONNECTION_CLOSED       -0x16
-#define MB_EXCEPTION             -0x17
+enum {
+        MODBUS_EXCEPTION_ILLEGAL_FUNCTION = 0x01,
+        MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS,
+        MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE,
+        MODBUS_EXCEPTION_SLAVE_OR_SERVER_FAILURE,
+        MODBUS_EXCEPTION_ACKNOWLEDGE,
+        MODBUS_EXCEPTION_SLAVE_OR_SERVER_BUSY,
+        MODBUS_EXCEPTION_NEGATIVE_ACKNOWLEDGE,
+        MODBUS_EXCEPTION_MEMORY_PARITY,
+        MODBUS_EXCEPTION_NOT_DEFINED,
+        MODBUS_EXCEPTION_GATEWAY_PATH,
+        MODBUS_EXCEPTION_GATEWAY_TARGET,
+        MODBUS_EXCEPTION_MAX
+};
+
+#define EMBXILFUN  (MODBUS_ENOBASE + MODBUS_EXCEPTION_ILLEGAL_FUNCTION)
+#define EMBXILADD  (MODBUS_ENOBASE + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS)
+#define EMBXILVAL  (MODBUS_ENOBASE + MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE)
+#define EMBXSFAIL  (MODBUS_ENOBASE + MODBUS_EXCEPTION_SLAVE_OR_SERVER_FAILURE)
+#define EMBXACK    (MODBUS_ENOBASE + MODBUS_EXCEPTION_ACKNOWLEDGE)
+#define EMBXSBUSY  (MODBUS_ENOBASE + MODBUS_EXCEPTION_SLAVE_OR_SERVER_BUSY)
+#define EMBXNACK   (MODBUS_ENOBASE + MODBUS_EXCEPTION_NEGATIVE_ACKNOWLEDGE)
+#define EMBXMEMPAR (MODBUS_ENOBASE + MODBUS_EXCEPTION_MEMORY_PARITY)
+#define EMBXGPATH  (MODBUS_ENOBASE + MODBUS_EXCEPTION_GATEWAY_PATH)
+#define EMBXGTAR   (MODBUS_ENOBASE + MODBUS_EXCEPTION_GATEWAY_TARGET)
+
+/* Native libmodbus error codes */
+#define EMBBADCRC  (EMBXGTAR + 1)
+#define EMBBADDATA (EMBXGTAR + 2)
+#define EMBBADEXC  (EMBXGTAR + 3)
+#define EMBUNKEXC  (EMBXGTAR + 4)
+#define EMBMDATA   (EMBXGTAR + 5)
 
 
 /* Internal using */
 /* Internal using */
 #define MSG_LENGTH_UNDEFINED -1
 #define MSG_LENGTH_UNDEFINED -1
 
 
 typedef enum { RTU=0, TCP } type_com_t;
 typedef enum { RTU=0, TCP } type_com_t;
-typedef enum { FLUSH_OR_CONNECT_ON_ERROR, NOP_ON_ERROR } error_handling_t;
 
 
 /* This structure is byte-aligned */
 /* This structure is byte-aligned */
 typedef struct {
 typedef struct {
@@ -183,7 +194,7 @@ typedef struct {
         /* Parity: "even", "odd", "none" */
         /* Parity: "even", "odd", "none" */
         char parity[5];
         char parity[5];
         /* In error_treat with TCP, do a reconnect or just dump the error */
         /* In error_treat with TCP, do a reconnect or just dump the error */
-        uint8_t error_handling;
+        uint8_t error_recovery;
         /* IP address */
         /* IP address */
         char ip[16];
         char ip[16];
         /* Save old termios settings */
         /* Save old termios settings */
@@ -201,171 +212,60 @@ typedef struct {
         uint16_t *tab_holding_registers;
         uint16_t *tab_holding_registers;
 } modbus_mapping_t;
 } modbus_mapping_t;
 
 
+void modbus_init_rtu(modbus_param_t *mb_param, const char *device,
+                     int baud, const char *parity, int data_bit,
+                     int stop_bit, int slave);
+void modbus_init_tcp(modbus_param_t *mb_param, const char *ip_address, int port,
+                     int slave);
+void modbus_set_slave(modbus_param_t *mb_param, int slave);
+int modbus_set_error_recovery(modbus_param_t *mb_param, int enabled);
 
 
-/* All functions used for sending or receiving data return:
-   - the numbers of values (bits or word) if success (0 or more)
-   - less than 0 for exceptions errors
-*/
+int modbus_connect(modbus_param_t *mb_param);
+void modbus_close(modbus_param_t *mb_param);
+
+int modbus_flush(modbus_param_t *mb_param);
+void modbus_set_debug(modbus_param_t *mb_param, int boolean);
+
+const char *modbus_strerror(int errnum);
 
 
-/* Reads the boolean status of coils and sets the array elements in
-   the destination to TRUE or FALSE */
 int read_coil_status(modbus_param_t *mb_param, int start_addr, int nb,
 int read_coil_status(modbus_param_t *mb_param, int start_addr, int nb,
                      uint8_t *dest);
                      uint8_t *dest);
-
-/* Same as read_coil_status but reads the slaves input table */
 int read_input_status(modbus_param_t *mb_param, int start_addr, int nb,
 int read_input_status(modbus_param_t *mb_param, int start_addr, int nb,
                       uint8_t *dest);
                       uint8_t *dest);
-
-/* Reads the holding registers in a slave and put the data into an
-   array */
 int read_holding_registers(modbus_param_t *mb_param, int start_addr, int nb,
 int read_holding_registers(modbus_param_t *mb_param, int start_addr, int nb,
                            uint16_t *dest);
                            uint16_t *dest);
-
-/* Reads the input registers in a slave and put the data into an
-   array */
 int read_input_registers(modbus_param_t *mb_param, int start_addr, int nb,
 int read_input_registers(modbus_param_t *mb_param, int start_addr, int nb,
                          uint16_t *dest);
                          uint16_t *dest);
-
-/* Turns ON or OFF a single coil in the slave device */
 int force_single_coil(modbus_param_t *mb_param, int coil_addr, int state);
 int force_single_coil(modbus_param_t *mb_param, int coil_addr, int state);
 
 
-/* Sets a value in one holding register in the slave device */
 int preset_single_register(modbus_param_t *mb_param, int reg_addr, int value);
 int preset_single_register(modbus_param_t *mb_param, int reg_addr, int value);
-
-/* Sets/resets the coils in the slave from an array in argument */
 int force_multiple_coils(modbus_param_t *mb_param, int start_addr, int nb,
 int force_multiple_coils(modbus_param_t *mb_param, int start_addr, int nb,
                          const uint8_t *data);
                          const uint8_t *data);
-
-/* Copies the values in the slave from the array given in argument */
 int preset_multiple_registers(modbus_param_t *mb_param, int start_addr, int nb,
 int preset_multiple_registers(modbus_param_t *mb_param, int start_addr, int nb,
                               const uint16_t *data);
                               const uint16_t *data);
-
-/* Returns the slave id! */
 int report_slave_id(modbus_param_t *mb_param, uint8_t *dest);
 int report_slave_id(modbus_param_t *mb_param, uint8_t *dest);
 
 
-/* Initializes the modbus_param_t structure for RTU.
-   - device: "/dev/ttyS0"
-   - baud:   9600, 19200, 57600, 115200, etc
-   - parity: "even", "odd" or "none"
-   - data_bits: 5, 6, 7, 8
-   - stop_bits: 1, 2
-*/
-void modbus_init_rtu(modbus_param_t *mb_param, const char *device,
-                     int baud, const char *parity, int data_bit,
-                     int stop_bit, int slave);
-
-/* Initializes the modbus_param_t structure for TCP.
-   - ip: "192.168.0.5"
-   - port: 1099
-   - slave: 5
-
-   Set the port to MODBUS_TCP_DEFAULT_PORT to use the default one
-   (502). It's convenient to use a port number greater than or equal
-   to 1024 because it's not necessary to be root to use this port
-   number.
-*/
-void modbus_init_tcp(modbus_param_t *mb_param, const char *ip_address, int port,
-                     int slave);
-
-/* Define the slave number.
-   The special value MODBUS_BROADCAST_ADDRESS can be used. */
-void modbus_set_slave(modbus_param_t *mb_param, int slave);
-
-/* By default, the error handling mode used is CONNECT_ON_ERROR.
-
-   With FLUSH_OR_CONNECT_ON_ERROR, the library will attempt an immediate
-   reconnection which may hang for several seconds if the network to
-   the remote target unit is down.
-
-   With NOP_ON_ERROR, it is expected that the application will
-   check for network error returns and deal with them as necessary.
-
-   This function is only useful in TCP mode.
- */
-void modbus_set_error_handling(modbus_param_t *mb_param, error_handling_t error_handling);
-
-/* Establishes a modbus connexion.
-   Returns 0 on success or -1 on failure. */
-int modbus_connect(modbus_param_t *mb_param);
-
-/* Closes a modbus connection */
-void modbus_close(modbus_param_t *mb_param);
-
-/* Flush the pending request */
-void modbus_flush(modbus_param_t *mb_param);
-
-/* Activates the debug messages */
-void modbus_set_debug(modbus_param_t *mb_param, int boolean);
-
-/**
- * SLAVE/CLIENT FUNCTIONS
- **/
-
-/* Allocates 4 arrays to store coils, input status, input registers and
-   holding registers. The pointers are stored in modbus_mapping structure.
-
-   Returns 0 on success and -1 on failure
- */
 int modbus_mapping_new(modbus_mapping_t *mb_mapping,
 int modbus_mapping_new(modbus_mapping_t *mb_mapping,
                        int nb_coil_status, int nb_input_status,
                        int nb_coil_status, int nb_input_status,
                        int nb_holding_registers, int nb_input_registers);
                        int nb_holding_registers, int nb_input_registers);
-
-/* Frees the 4 arrays */
 void modbus_mapping_free(modbus_mapping_t *mb_mapping);
 void modbus_mapping_free(modbus_mapping_t *mb_mapping);
 
 
-/* Listens for any query from one or many modbus masters in TCP.
-
-   Returns: socket
- */
 int modbus_slave_listen_tcp(modbus_param_t *mb_param, int nb_connection);
 int modbus_slave_listen_tcp(modbus_param_t *mb_param, int nb_connection);
-
-/* Waits for a connection */
 int modbus_slave_accept_tcp(modbus_param_t *mb_param, int *socket);
 int modbus_slave_accept_tcp(modbus_param_t *mb_param, int *socket);
-
-/* Listens for any query from a modbus master in TCP, requires the socket file
-   descriptor etablished with the master device in argument or -1 to use the
-   internal one of modbus_param_t.
-
-   Returns:
-   - byte length of the message on success, or a negative error number if the
-     request fails
-   - query, message received
-*/
 int modbus_slave_receive(modbus_param_t *mb_param, int sockfd, uint8_t *query);
 int modbus_slave_receive(modbus_param_t *mb_param, int sockfd, uint8_t *query);
-
-/* Manages the received query.
-   Analyses the query and constructs a response.
-
-   If an error occurs, this function construct the response
-   accordingly.
-*/
-void modbus_slave_manage(modbus_param_t *mb_param, const uint8_t *query,
-                         int query_length, modbus_mapping_t *mb_mapping);
-
-/* Closes a TCP socket */
+int modbus_slave_manage(modbus_param_t *mb_param, const uint8_t *query,
+                        int query_length, modbus_mapping_t *mb_mapping);
 void modbus_slave_close_tcp(int socket);
 void modbus_slave_close_tcp(int socket);
 
 
 /**
 /**
  * UTILS FUNCTIONS
  * UTILS FUNCTIONS
  **/
  **/
 
 
-/* Sets many input/coil status from a single byte value (all 8 bits of
-   the byte value are set) */
 void set_bits_from_byte(uint8_t *dest, int address, const uint8_t value);
 void set_bits_from_byte(uint8_t *dest, int address, const uint8_t value);
-
-/* Sets many input/coil status from a table of bytes (only the bits
-   between address and address + nb_bits are set) */
-void set_bits_from_bytes(uint8_t *dest, int address, int nb_bits,
+void set_bits_from_bytes(uint8_t *dest, int address, unsigned int nb_bits,
                          const uint8_t *tab_byte);
                          const uint8_t *tab_byte);
-
-/* Gets the byte value from many input/coil status.
-   To obtain a full byte, set nb_bits to 8. */
-uint8_t get_byte_from_bits(const uint8_t *src, int address, int nb_bits);
-
-/* Read a float from 4 bytes in Modbus format */
+uint8_t get_byte_from_bits(const uint8_t *src, int address, unsigned int nb_bits);
 float modbus_read_float(const uint16_t *src);
 float modbus_read_float(const uint16_t *src);
-
-/* Write a float to 4 bytes in Modbus format */
 void modbus_write_float(float real, uint16_t *dest);
 void modbus_write_float(float real, uint16_t *dest);
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus

+ 17 - 5
tests/bandwidth-master.c

@@ -21,6 +21,7 @@
 #include <stdlib.h>
 #include <stdlib.h>
 #include <time.h>
 #include <time.h>
 #include <sys/time.h>
 #include <sys/time.h>
+#include <errno.h>
 
 
 #include <modbus/modbus.h>
 #include <modbus/modbus.h>
 
 
@@ -44,18 +45,21 @@ int main(void)
         uint16_t *tab_rp_registers;
         uint16_t *tab_rp_registers;
         modbus_param_t mb_param;
         modbus_param_t mb_param;
         int i;
         int i;
-        int ret;
         int nb_points;
         int nb_points;
         double elapsed;
         double elapsed;
         uint32_t start;
         uint32_t start;
         uint32_t end;
         uint32_t end;
         uint32_t bytes;
         uint32_t bytes;
         uint32_t rate;
         uint32_t rate;
+        int rc;
 
 
         /* TCP */
         /* TCP */
         modbus_init_tcp(&mb_param, "127.0.0.1", 1502, SLAVE);
         modbus_init_tcp(&mb_param, "127.0.0.1", 1502, SLAVE);
-        if (modbus_connect(&mb_param) == -1) {
-                exit(1);
+        rc = modbus_connect(&mb_param);
+        if (rc == -1) {
+                fprintf(stderr, "Connexion failed: %s\n",
+                        modbus_strerror(errno));
+                return -1;
         }
         }
 
 
         /* Allocate and initialize the memory to store the status */
         /* Allocate and initialize the memory to store the status */
@@ -71,7 +75,11 @@ int main(void)
         nb_points = MAX_STATUS;
         nb_points = MAX_STATUS;
         start = gettime_ms();
         start = gettime_ms();
         for (i=0; i<NB_LOOPS; i++) {
         for (i=0; i<NB_LOOPS; i++) {
-                ret = read_coil_status(&mb_param, 0, nb_points, tab_rp_status);
+                rc = read_coil_status(&mb_param, 0, nb_points, tab_rp_status);
+                if (rc == -1) {
+                        fprintf(stderr, modbus_strerror(errno));
+                        return -1;
+                }
         }
         }
         end = gettime_ms();
         end = gettime_ms();
         elapsed = end - start;
         elapsed = end - start;
@@ -104,7 +112,11 @@ int main(void)
         nb_points = MAX_REGISTERS;
         nb_points = MAX_REGISTERS;
         start = gettime_ms();
         start = gettime_ms();
         for (i=0; i<NB_LOOPS; i++) {
         for (i=0; i<NB_LOOPS; i++) {
-                ret = read_holding_registers(&mb_param, 0, nb_points, tab_rp_registers);
+                rc = read_holding_registers(&mb_param, 0, nb_points, tab_rp_registers);
+                if (rc == -1) {
+                        fprintf(stderr, modbus_strerror(errno));
+                        return -1;
+                }
         }
         }
         end = gettime_ms();
         end = gettime_ms();
         elapsed = end - start;
         elapsed = end - start;

+ 9 - 8
tests/bandwidth-slave-many-up.c

@@ -42,7 +42,7 @@ int main(void)
 {
 {
         int master_socket;
         int master_socket;
         modbus_param_t mb_param;
         modbus_param_t mb_param;
-        int ret;
+        int rc;
         fd_set refset;
         fd_set refset;
         fd_set rdset;
         fd_set rdset;
 
 
@@ -51,10 +51,11 @@ int main(void)
 
 
         modbus_init_tcp(&mb_param, "127.0.0.1", 1502, SLAVE);
         modbus_init_tcp(&mb_param, "127.0.0.1", 1502, SLAVE);
 
 
-        ret = modbus_mapping_new(&mb_mapping,  MAX_STATUS, 0, MAX_REGISTERS, 0);
-        if (ret < 0) {
-                fprintf(stderr, "Memory allocation failure\n");
-                exit(1);
+        rc = modbus_mapping_new(&mb_mapping,  MAX_STATUS, 0, MAX_REGISTERS, 0);
+        if (rc == -1) {
+                fprintf(stderr, "Failed to allocate the mapping: %s\n",
+                        modbus_strerror(errno));
+                return -1;
         }
         }
 
 
         slave_socket = modbus_slave_listen_tcp(&mb_param, NB_CONNECTION);
         slave_socket = modbus_slave_listen_tcp(&mb_param, NB_CONNECTION);
@@ -107,9 +108,9 @@ int main(void)
                                         /* An already connected master has sent a new query */
                                         /* An already connected master has sent a new query */
                                         uint8_t query[MAX_MESSAGE_LENGTH];
                                         uint8_t query[MAX_MESSAGE_LENGTH];
 
 
-                                        ret = modbus_slave_receive(&mb_param, master_socket, query);
-                                        if (ret >= 0) {
-                                                modbus_slave_manage(&mb_param, query, ret, &mb_mapping);
+                                        rc = modbus_slave_receive(&mb_param, master_socket, query);
+                                        if (rc != -1) {
+                                                modbus_slave_manage(&mb_param, query, rc, &mb_mapping);
                                         } else {
                                         } else {
                                                 /* Connection closed by the client, end of server */
                                                 /* Connection closed by the client, end of server */
                                                 printf("Connection closed on socket %d\n", master_socket);
                                                 printf("Connection closed on socket %d\n", master_socket);

+ 15 - 13
tests/bandwidth-slave-one.c

@@ -19,6 +19,7 @@
 #include <unistd.h>
 #include <unistd.h>
 #include <string.h>
 #include <string.h>
 #include <stdlib.h>
 #include <stdlib.h>
+#include <errno.h>
 
 
 #include <modbus/modbus.h>
 #include <modbus/modbus.h>
 
 
@@ -29,33 +30,34 @@ int main(void)
         int socket;
         int socket;
         modbus_param_t mb_param;
         modbus_param_t mb_param;
         modbus_mapping_t mb_mapping;
         modbus_mapping_t mb_mapping;
-        int ret;
+        int rc;
 
 
         modbus_init_tcp(&mb_param, "127.0.0.1", 1502, SLAVE);
         modbus_init_tcp(&mb_param, "127.0.0.1", 1502, SLAVE);
 
 
-        ret = modbus_mapping_new(&mb_mapping,  MAX_STATUS, 0, MAX_REGISTERS, 0);
-        if (ret < 0) {
-                fprintf(stderr, "Memory allocation failed\n");
-                exit(1);
+        rc = modbus_mapping_new(&mb_mapping,  MAX_STATUS, 0, MAX_REGISTERS, 0);
+        if (rc == -1) {
+                fprintf(stderr, "Failed to allocate the mapping: %s\n",
+                        modbus_strerror(errno));
+                return -1;
         }
         }
 
 
         socket = modbus_slave_listen_tcp(&mb_param, 1);
         socket = modbus_slave_listen_tcp(&mb_param, 1);
         modbus_slave_accept_tcp(&mb_param, &socket);
         modbus_slave_accept_tcp(&mb_param, &socket);
 
 
-        while (1) {
+        for(;;) {
                 uint8_t query[MAX_MESSAGE_LENGTH];
                 uint8_t query[MAX_MESSAGE_LENGTH];
 
 
-                ret = modbus_slave_receive(&mb_param, -1, query);
-                if (ret >= 0) {
-                        modbus_slave_manage(&mb_param, query, ret, &mb_mapping);
-                } else if (ret == CONNECTION_CLOSED) {
-                        /* Connection closed by the client, end of server */
-                        break;
+                rc = modbus_slave_receive(&mb_param, -1, query);
+                if (rc >= 0) {
+                        modbus_slave_manage(&mb_param, query, rc, &mb_mapping);
                 } else {
                 } else {
-                        fprintf(stderr, "Error in modbus_listen (%d)\n", ret);
+                        /* Connection closed by the client or server */
+                        break;
                 }
                 }
         }
         }
 
 
+        printf("Quit the loop: %s\n", modbus_strerror(errno));
+
         close(socket);
         close(socket);
         modbus_mapping_free(&mb_mapping);
         modbus_mapping_free(&mb_mapping);
         modbus_close(&mb_param);
         modbus_close(&mb_param);

+ 28 - 25
tests/random-test-master.c

@@ -19,6 +19,7 @@
 #include <unistd.h>
 #include <unistd.h>
 #include <string.h>
 #include <string.h>
 #include <stdlib.h>
 #include <stdlib.h>
+#include <errno.h>
 
 
 #include <modbus/modbus.h>
 #include <modbus/modbus.h>
 
 
@@ -45,7 +46,7 @@
  */
  */
 int main(void)
 int main(void)
 {
 {
-        int ret;
+        int rc;
         int nb_fail;
         int nb_fail;
         int nb_loop;
         int nb_loop;
         int addr;
         int addr;
@@ -63,7 +64,9 @@ int main(void)
         modbus_init_tcp(&mb_param, "127.0.0.1", 1502, SLAVE);
         modbus_init_tcp(&mb_param, "127.0.0.1", 1502, SLAVE);
         modbus_set_debug(&mb_param, TRUE);
         modbus_set_debug(&mb_param, TRUE);
         if (modbus_connect(&mb_param) == -1) {
         if (modbus_connect(&mb_param) == -1) {
-                exit(1);
+                fprintf(stderr, "Connection failed: %s\n",
+                        modbus_strerror(errno));
+                return -1;
         }
         }
 
 
         /* Allocate and initialize the different memory spaces */
         /* Allocate and initialize the different memory spaces */
@@ -94,16 +97,16 @@ int main(void)
                         nb = ADDRESS_END - addr;
                         nb = ADDRESS_END - addr;
 
 
                         /* SINGLE COIL */
                         /* SINGLE COIL */
-                        ret = force_single_coil(&mb_param, addr, tab_rq_status[0]);
-                        if (ret != 1) {
-                                printf("ERROR force_single_coil (%d)\n", ret);
+                        rc = force_single_coil(&mb_param, addr, tab_rq_status[0]);
+                        if (rc != 1) {
+                                printf("ERROR force_single_coil (%d)\n", rc);
                                 printf("Slave = %d, address = %d, value = %d\n",
                                 printf("Slave = %d, address = %d, value = %d\n",
                                        SLAVE, addr, tab_rq_status[0]);
                                        SLAVE, addr, tab_rq_status[0]);
                                 nb_fail++;
                                 nb_fail++;
                         } else {
                         } else {
-                                ret = read_coil_status(&mb_param, addr, 1, tab_rp_status);
-                                if (ret != 1 || tab_rq_status[0] != tab_rp_status[0]) {
-                                        printf("ERROR read_coil_status single (%d)\n", ret);
+                                rc = read_coil_status(&mb_param, addr, 1, tab_rp_status);
+                                if (rc != 1 || tab_rq_status[0] != tab_rp_status[0]) {
+                                        printf("ERROR read_coil_status single (%d)\n", rc);
                                         printf("Slave = %d, address = %d\n",
                                         printf("Slave = %d, address = %d\n",
                                                SLAVE, addr);
                                                SLAVE, addr);
                                         nb_fail++;
                                         nb_fail++;
@@ -111,15 +114,15 @@ int main(void)
                         }
                         }
 
 
                         /* MULTIPLE COILS */
                         /* MULTIPLE COILS */
-                        ret = force_multiple_coils(&mb_param, addr, nb, tab_rq_status);
-                        if (ret != nb) {
-                                printf("ERROR force_multiple_coils (%d)\n", ret);
+                        rc = force_multiple_coils(&mb_param, addr, nb, tab_rq_status);
+                        if (rc != nb) {
+                                printf("ERROR force_multiple_coils (%d)\n", rc);
                                 printf("Slave = %d, address = %d, nb = %d\n",
                                 printf("Slave = %d, address = %d, nb = %d\n",
                                        SLAVE, addr, nb);
                                        SLAVE, addr, nb);
                                 nb_fail++;
                                 nb_fail++;
                         } else {
                         } else {
-                                ret = read_coil_status(&mb_param, addr, nb, tab_rp_status);
-                                if (ret != nb) {
+                                rc = read_coil_status(&mb_param, addr, nb, tab_rp_status);
+                                if (rc != nb) {
                                         printf("ERROR read_coil_status\n");
                                         printf("ERROR read_coil_status\n");
                                         printf("Slave = %d, address = %d, nb = %d\n",
                                         printf("Slave = %d, address = %d, nb = %d\n",
                                                SLAVE, addr, nb);
                                                SLAVE, addr, nb);
@@ -139,16 +142,16 @@ int main(void)
                         }
                         }
 
 
                         /* SINGLE REGISTER */
                         /* SINGLE REGISTER */
-                        ret = preset_single_register(&mb_param, addr, tab_rq_registers[0]);
-                        if (ret != 1) {
-                                printf("ERROR preset_single_register (%d)\n", ret);
+                        rc = preset_single_register(&mb_param, addr, tab_rq_registers[0]);
+                        if (rc != 1) {
+                                printf("ERROR preset_single_register (%d)\n", rc);
                                 printf("Slave = %d, address = %d, value = %d (0x%X)\n",
                                 printf("Slave = %d, address = %d, value = %d (0x%X)\n",
                                        SLAVE, addr, tab_rq_registers[0], tab_rq_registers[0]);
                                        SLAVE, addr, tab_rq_registers[0], tab_rq_registers[0]);
                                 nb_fail++;
                                 nb_fail++;
                         } else {
                         } else {
-                                ret = read_holding_registers(&mb_param, addr, 1, tab_rp_registers);
-                                if (ret != 1) {
-                                        printf("ERROR read_holding_registers single (%d)\n", ret);
+                                rc = read_holding_registers(&mb_param, addr, 1, tab_rp_registers);
+                                if (rc != 1) {
+                                        printf("ERROR read_holding_registers single (%d)\n", rc);
                                         printf("Slave = %d, address = %d\n",
                                         printf("Slave = %d, address = %d\n",
                                                SLAVE, addr);
                                                SLAVE, addr);
                                         nb_fail++;
                                         nb_fail++;
@@ -165,18 +168,18 @@ int main(void)
                         }
                         }
 
 
                         /* MULTIPLE REGISTERS */
                         /* MULTIPLE REGISTERS */
-                        ret = preset_multiple_registers(&mb_param, addr, nb,
+                        rc = preset_multiple_registers(&mb_param, addr, nb,
                                                         tab_rq_registers);
                                                         tab_rq_registers);
-                        if (ret != nb) {
-                                printf("ERROR preset_multiple_registers (%d)\n", ret);
+                        if (rc != nb) {
+                                printf("ERROR preset_multiple_registers (%d)\n", rc);
                                 printf("Slave = %d, address = %d, nb = %d\n",
                                 printf("Slave = %d, address = %d, nb = %d\n",
                                                SLAVE, addr, nb);
                                                SLAVE, addr, nb);
                                 nb_fail++;
                                 nb_fail++;
                         } else {
                         } else {
-                                ret = read_holding_registers(&mb_param, addr, nb,
+                                rc = read_holding_registers(&mb_param, addr, nb,
                                                              tab_rp_registers);
                                                              tab_rp_registers);
-                                if (ret != nb) {
-                                        printf("ERROR read_holding_registers (%d)\n", ret);
+                                if (rc != nb) {
+                                        printf("ERROR read_holding_registers (%d)\n", rc);
                                         printf("Slave = %d, address = %d, nb = %d\n",
                                         printf("Slave = %d, address = %d, nb = %d\n",
                                                SLAVE, addr, nb);
                                                SLAVE, addr, nb);
                                         nb_fail++;
                                         nb_fail++;

+ 17 - 15
tests/random-test-slave.c

@@ -18,6 +18,7 @@
 #include <stdio.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <stdlib.h>
+#include <errno.h>
 
 
 #include <modbus/modbus.h>
 #include <modbus/modbus.h>
 
 
@@ -28,36 +29,37 @@ int main(void)
         int socket;
         int socket;
         modbus_param_t mb_param;
         modbus_param_t mb_param;
         modbus_mapping_t mb_mapping;
         modbus_mapping_t mb_mapping;
-        int ret;
+        int rc;
 
 
         modbus_init_tcp(&mb_param, "127.0.0.1", 1502, SLAVE);
         modbus_init_tcp(&mb_param, "127.0.0.1", 1502, SLAVE);
         /* modbus_set_debug(&mb_param, TRUE); */
         /* modbus_set_debug(&mb_param, TRUE); */
 
 
-        ret = modbus_mapping_new(&mb_mapping, 500, 500, 500, 500);
-        if (ret < 0) {
-                fprintf(stderr, "Memory allocation failed\n");
-                exit(1);
+        rc = modbus_mapping_new(&mb_mapping, 500, 500, 500, 500);
+        if (rc == -1) {
+                fprintf(stderr, "Failed to allocate the mapping: %s\n",
+                        modbus_strerror(errno));
+                return -1;
         }
         }
 
 
         socket = modbus_slave_listen_tcp(&mb_param, 1);
         socket = modbus_slave_listen_tcp(&mb_param, 1);
         modbus_slave_accept_tcp(&mb_param, &socket);
         modbus_slave_accept_tcp(&mb_param, &socket);
 
 
-        while (1) {
+        for (;;) {
                 uint8_t query[MAX_MESSAGE_LENGTH];
                 uint8_t query[MAX_MESSAGE_LENGTH];
-                int ret;
+                int rc;
 
 
-                ret = modbus_slave_receive(&mb_param, -1, query);
-                if (ret >= 0) {
-                        /* ret is the query size */
-                        modbus_slave_manage(&mb_param, query, ret, &mb_mapping);
-                } else if (ret == CONNECTION_CLOSED) {
-                        /* Connection closed by the client, end of server */
-                        break;
+                rc = modbus_slave_receive(&mb_param, -1, query);
+                if (rc != -1) {
+                        /* rc is the query size */
+                        modbus_slave_manage(&mb_param, query, rc, &mb_mapping);
                 } else {
                 } else {
-                        fprintf(stderr, "Error in modbus_listen (%d)\n", ret);
+                        /* Connection closed by the client or error */
+                        break;
                 }
                 }
         }
         }
 
 
+        printf("Quit the loop: %s\n", modbus_strerror(errno));
+
         close(socket);
         close(socket);
         modbus_mapping_free(&mb_mapping);
         modbus_mapping_free(&mb_mapping);
         modbus_close(&mb_param);
         modbus_close(&mb_param);

+ 129 - 126
tests/unit-test-master.c

@@ -19,6 +19,7 @@
 #include <unistd.h>
 #include <unistd.h>
 #include <string.h>
 #include <string.h>
 #include <stdlib.h>
 #include <stdlib.h>
+#include <errno.h>
 
 
 #include <modbus/modbus.h>
 #include <modbus/modbus.h>
 #include "unit-test.h"
 #include "unit-test.h"
@@ -36,7 +37,7 @@ int main(void)
         uint8_t value;
         uint8_t value;
         int address;
         int address;
         int nb_points;
         int nb_points;
-        int ret;
+        int rc;
         float real;
         float real;
 
 
         /* RTU parity : none, even, odd */
         /* RTU parity : none, even, odd */
@@ -44,10 +45,12 @@ int main(void)
 
 
         /* TCP */
         /* TCP */
         modbus_init_tcp(&mb_param, "127.0.0.1", 1502, SLAVE);
         modbus_init_tcp(&mb_param, "127.0.0.1", 1502, SLAVE);
-/*        modbus_set_debug(&mb_param, TRUE); */
+        modbus_set_debug(&mb_param, TRUE);
 
 
         if (modbus_connect(&mb_param) == -1) {
         if (modbus_connect(&mb_param) == -1) {
-                exit(1);
+                fprintf(stderr, "Connection failed: %s\n",
+                        modbus_strerror(errno));
+                return -1;
         }
         }
 
 
         /* Allocate and initialize the memory to store the status */
         /* Allocate and initialize the memory to store the status */
@@ -70,20 +73,20 @@ int main(void)
         /** COIL STATUS **/
         /** COIL STATUS **/
 
 
         /* Single */
         /* Single */
-        ret = force_single_coil(&mb_param, UT_COIL_STATUS_ADDRESS, ON);
+        rc = force_single_coil(&mb_param, UT_COIL_STATUS_ADDRESS, ON);
         printf("1/2 force_single_coil: ");
         printf("1/2 force_single_coil: ");
-        if (ret == 1) {
+        if (rc == 1) {
                 printf("OK\n");
                 printf("OK\n");
         } else {
         } else {
                 printf("FAILED\n");
                 printf("FAILED\n");
                 goto close;
                 goto close;
         }
         }
 
 
-        ret = read_coil_status(&mb_param, UT_COIL_STATUS_ADDRESS, 1,
-                               tab_rp_status);
+        rc = read_coil_status(&mb_param, UT_COIL_STATUS_ADDRESS, 1,
+                              tab_rp_status);
         printf("2/2 read_coil_status: ");
         printf("2/2 read_coil_status: ");
-        if (ret != 1) {
-                printf("FAILED (nb points %d)\n", ret);
+        if (rc != 1) {
+                printf("FAILED (nb points %d)\n", rc);
                 goto close;
                 goto close;
         }
         }
 
 
@@ -100,12 +103,12 @@ int main(void)
 
 
                 set_bits_from_bytes(tab_value, 0, UT_COIL_STATUS_NB_POINTS,
                 set_bits_from_bytes(tab_value, 0, UT_COIL_STATUS_NB_POINTS,
                                     UT_COIL_STATUS_TAB);
                                     UT_COIL_STATUS_TAB);
-                ret = force_multiple_coils(&mb_param,
-                                           UT_COIL_STATUS_ADDRESS,
-                                           UT_COIL_STATUS_NB_POINTS,
-                                           tab_value);
+                rc = force_multiple_coils(&mb_param,
+                                          UT_COIL_STATUS_ADDRESS,
+                                          UT_COIL_STATUS_NB_POINTS,
+                                          tab_value);
                 printf("1/2 force_multiple_coils: ");
                 printf("1/2 force_multiple_coils: ");
-                if (ret == UT_COIL_STATUS_NB_POINTS) {
+                if (rc == UT_COIL_STATUS_NB_POINTS) {
                         printf("OK\n");
                         printf("OK\n");
                 } else {
                 } else {
                         printf("FAILED\n");
                         printf("FAILED\n");
@@ -113,11 +116,11 @@ int main(void)
                 }
                 }
         }
         }
 
 
-        ret = read_coil_status(&mb_param, UT_COIL_STATUS_ADDRESS,
-                               UT_COIL_STATUS_NB_POINTS, tab_rp_status);
+        rc = read_coil_status(&mb_param, UT_COIL_STATUS_ADDRESS,
+                              UT_COIL_STATUS_NB_POINTS, tab_rp_status);
         printf("2/2 read_coil_status: ");
         printf("2/2 read_coil_status: ");
-        if (ret != UT_COIL_STATUS_NB_POINTS) {
-                printf("FAILED (nb points %d)\n", ret);
+        if (rc != UT_COIL_STATUS_NB_POINTS) {
+                printf("FAILED (nb points %d)\n", rc);
                 goto close;
                 goto close;
         }
         }
 
 
@@ -141,12 +144,12 @@ int main(void)
         /* End of multiple coils */
         /* End of multiple coils */
 
 
         /** INPUT STATUS **/
         /** INPUT STATUS **/
-        ret = read_input_status(&mb_param, UT_INPUT_STATUS_ADDRESS,
-                                UT_INPUT_STATUS_NB_POINTS, tab_rp_status);
+        rc = read_input_status(&mb_param, UT_INPUT_STATUS_ADDRESS,
+                               UT_INPUT_STATUS_NB_POINTS, tab_rp_status);
         printf("1/1 read_input_status: ");
         printf("1/1 read_input_status: ");
 
 
-        if (ret != UT_INPUT_STATUS_NB_POINTS) {
-                printf("FAILED (nb points %d)\n", ret);
+        if (rc != UT_INPUT_STATUS_NB_POINTS) {
+                printf("FAILED (nb points %d)\n", rc);
                 goto close;
                 goto close;
         }
         }
 
 
@@ -171,22 +174,22 @@ int main(void)
         /** HOLDING REGISTERS **/
         /** HOLDING REGISTERS **/
 
 
         /* Single register */
         /* Single register */
-        ret = preset_single_register(&mb_param,
-                                     UT_HOLDING_REGISTERS_ADDRESS, 0x1234);
+        rc = preset_single_register(&mb_param,
+                                    UT_HOLDING_REGISTERS_ADDRESS, 0x1234);
         printf("1/2 preset_single_register: ");
         printf("1/2 preset_single_register: ");
-        if (ret == 1) {
+        if (rc == 1) {
                 printf("OK\n");
                 printf("OK\n");
         } else {
         } else {
                 printf("FAILED\n");
                 printf("FAILED\n");
                 goto close;
                 goto close;
         }
         }
 
 
-        ret = read_holding_registers(&mb_param,
-                                     UT_HOLDING_REGISTERS_ADDRESS,
-                                     1, tab_rp_registers);
+        rc = read_holding_registers(&mb_param,
+                                    UT_HOLDING_REGISTERS_ADDRESS,
+                                    1, tab_rp_registers);
         printf("2/2 read_holding_registers: ");
         printf("2/2 read_holding_registers: ");
-        if (ret != 1) {
-                printf("FAILED (nb points %d)\n", ret);
+        if (rc != 1) {
+                printf("FAILED (nb points %d)\n", rc);
                 goto close;
                 goto close;
         }
         }
 
 
@@ -199,25 +202,25 @@ int main(void)
         /* End of single register */
         /* End of single register */
 
 
         /* Many registers */
         /* Many registers */
-        ret = preset_multiple_registers(&mb_param,
-                                        UT_HOLDING_REGISTERS_ADDRESS,
-                                        UT_HOLDING_REGISTERS_NB_POINTS,
-                                        UT_HOLDING_REGISTERS_TAB);
+        rc = preset_multiple_registers(&mb_param,
+                                       UT_HOLDING_REGISTERS_ADDRESS,
+                                       UT_HOLDING_REGISTERS_NB_POINTS,
+                                       UT_HOLDING_REGISTERS_TAB);
         printf("1/2 preset_multiple_registers: ");
         printf("1/2 preset_multiple_registers: ");
-        if (ret == UT_HOLDING_REGISTERS_NB_POINTS) {
+        if (rc == UT_HOLDING_REGISTERS_NB_POINTS) {
                 printf("OK\n");
                 printf("OK\n");
         } else {
         } else {
                 printf("FAILED\n");
                 printf("FAILED\n");
                 goto close;
                 goto close;
         }
         }
 
 
-        ret = read_holding_registers(&mb_param,
-                                     UT_HOLDING_REGISTERS_ADDRESS,
-                                     UT_HOLDING_REGISTERS_NB_POINTS,
-                                     tab_rp_registers);
+        rc = read_holding_registers(&mb_param,
+                                    UT_HOLDING_REGISTERS_ADDRESS,
+                                    UT_HOLDING_REGISTERS_NB_POINTS,
+                                    tab_rp_registers);
         printf("2/2 read_holding_registers: ");
         printf("2/2 read_holding_registers: ");
-        if (ret != UT_HOLDING_REGISTERS_NB_POINTS) {
-                printf("FAILED (nb points %d)\n", ret);
+        if (rc != UT_HOLDING_REGISTERS_NB_POINTS) {
+                printf("FAILED (nb points %d)\n", rc);
                 goto close;
                 goto close;
         }
         }
 
 
@@ -234,13 +237,13 @@ int main(void)
 
 
 
 
         /** INPUT REGISTERS **/
         /** INPUT REGISTERS **/
-        ret = read_input_registers(&mb_param,
-                                   UT_INPUT_REGISTERS_ADDRESS,
-                                   UT_INPUT_REGISTERS_NB_POINTS,
-                                   tab_rp_registers);
+        rc = read_input_registers(&mb_param,
+                                  UT_INPUT_REGISTERS_ADDRESS,
+                                  UT_INPUT_REGISTERS_NB_POINTS,
+                                  tab_rp_registers);
         printf("1/1 read_input_registers: ");
         printf("1/1 read_input_registers: ");
-        if (ret != UT_INPUT_REGISTERS_NB_POINTS) {
-                printf("FAILED (nb points %d)\n", ret);
+        if (rc != UT_INPUT_REGISTERS_NB_POINTS) {
+                printf("FAILED (nb points %d)\n", rc);
                 goto close;
                 goto close;
         }
         }
 
 
@@ -284,83 +287,83 @@ int main(void)
         /* The mapping begins at 0 and ending at address + nb_points so
         /* The mapping begins at 0 and ending at address + nb_points so
          * the addresses below are not valid. */
          * the addresses below are not valid. */
 
 
-        ret = read_coil_status(&mb_param,
-                               UT_COIL_STATUS_ADDRESS,
-                               UT_COIL_STATUS_NB_POINTS + 1,
-                               tab_rp_status);
+        rc = read_coil_status(&mb_param,
+                              UT_COIL_STATUS_ADDRESS,
+                              UT_COIL_STATUS_NB_POINTS + 1,
+                              tab_rp_status);
         printf("* read_coil_status: ");
         printf("* read_coil_status: ");
-        if (ret == ILLEGAL_DATA_ADDRESS)
+        if (rc == -1 && errno == EMBXILADD)
                 printf("OK\n");
                 printf("OK\n");
         else {
         else {
                 printf("FAILED\n");
                 printf("FAILED\n");
                 goto close;
                 goto close;
         }
         }
 
 
-        ret = read_input_status(&mb_param,
-                                UT_INPUT_STATUS_ADDRESS,
-                                UT_INPUT_STATUS_NB_POINTS + 1,
-                                tab_rp_status);
+        rc = read_input_status(&mb_param,
+                               UT_INPUT_STATUS_ADDRESS,
+                               UT_INPUT_STATUS_NB_POINTS + 1,
+                               tab_rp_status);
         printf("* read_input_status: ");
         printf("* read_input_status: ");
-        if (ret == ILLEGAL_DATA_ADDRESS)
+        if (rc == -1 && errno == EMBXILADD)
                 printf("OK\n");
                 printf("OK\n");
         else {
         else {
                 printf("FAILED\n");
                 printf("FAILED\n");
                 goto close;
                 goto close;
         }
         }
 
 
-        ret = read_holding_registers(&mb_param,
-                                     UT_HOLDING_REGISTERS_ADDRESS,
-                                     UT_HOLDING_REGISTERS_NB_POINTS + 1,
-                                     tab_rp_registers);
+        rc = read_holding_registers(&mb_param,
+                                    UT_HOLDING_REGISTERS_ADDRESS,
+                                    UT_HOLDING_REGISTERS_NB_POINTS + 1,
+                                    tab_rp_registers);
         printf("* read_holding_registers: ");
         printf("* read_holding_registers: ");
-        if (ret == ILLEGAL_DATA_ADDRESS)
+        if (rc == -1 && errno == EMBXILADD)
                 printf("OK\n");
                 printf("OK\n");
         else {
         else {
                 printf("FAILED\n");
                 printf("FAILED\n");
                 goto close;
                 goto close;
         }
         }
 
 
-        ret = read_input_registers(&mb_param,
-                                   UT_INPUT_REGISTERS_ADDRESS,
-                                   UT_INPUT_REGISTERS_NB_POINTS + 1,
-                                   tab_rp_registers);
+        rc = read_input_registers(&mb_param,
+                                  UT_INPUT_REGISTERS_ADDRESS,
+                                  UT_INPUT_REGISTERS_NB_POINTS + 1,
+                                  tab_rp_registers);
         printf("* read_input_registers: ");
         printf("* read_input_registers: ");
-        if (ret == ILLEGAL_DATA_ADDRESS)
+        if (rc == -1 && errno == EMBXILADD)
                 printf("OK\n");
                 printf("OK\n");
         else {
         else {
                 printf("FAILED\n");
                 printf("FAILED\n");
                 goto close;
                 goto close;
         }
         }
 
 
-        ret = force_single_coil(&mb_param,
-                                UT_COIL_STATUS_ADDRESS + UT_COIL_STATUS_NB_POINTS,
-                                ON);
+        rc = force_single_coil(&mb_param,
+                               UT_COIL_STATUS_ADDRESS + UT_COIL_STATUS_NB_POINTS,
+                               ON);
         printf("* force_single_coil: ");
         printf("* force_single_coil: ");
-        if (ret == ILLEGAL_DATA_ADDRESS) {
+        if (rc == -1 && errno == EMBXILADD) {
                 printf("OK\n");
                 printf("OK\n");
         } else {
         } else {
                 printf("FAILED\n");
                 printf("FAILED\n");
                 goto close;
                 goto close;
         }
         }
 
 
-        ret = force_multiple_coils(&mb_param,
-                                   UT_COIL_STATUS_ADDRESS + UT_COIL_STATUS_NB_POINTS,
-                                   UT_COIL_STATUS_NB_POINTS,
-                                   tab_rp_status);
+        rc = force_multiple_coils(&mb_param,
+                                  UT_COIL_STATUS_ADDRESS + UT_COIL_STATUS_NB_POINTS,
+                                  UT_COIL_STATUS_NB_POINTS,
+                                  tab_rp_status);
         printf("* force_multiple_coils: ");
         printf("* force_multiple_coils: ");
-        if (ret == ILLEGAL_DATA_ADDRESS) {
+        if (rc == -1 && errno == EMBXILADD) {
                 printf("OK\n");
                 printf("OK\n");
         } else {
         } else {
                 printf("FAILED\n");
                 printf("FAILED\n");
                 goto close;
                 goto close;
         }
         }
 
 
-        ret = preset_multiple_registers(&mb_param,
-                                        UT_HOLDING_REGISTERS_ADDRESS + UT_HOLDING_REGISTERS_NB_POINTS,
-                                        UT_HOLDING_REGISTERS_NB_POINTS,
-                                        tab_rp_registers);
+        rc = preset_multiple_registers(&mb_param,
+                                       UT_HOLDING_REGISTERS_ADDRESS + UT_HOLDING_REGISTERS_NB_POINTS,
+                                       UT_HOLDING_REGISTERS_NB_POINTS,
+                                       tab_rp_registers);
         printf("* preset_multiple_registers: ");
         printf("* preset_multiple_registers: ");
-        if (ret == ILLEGAL_DATA_ADDRESS) {
+        if (rc == -1 && errno == EMBXILADD) {
                 printf("OK\n");
                 printf("OK\n");
         } else {
         } else {
                 printf("FAILED\n");
                 printf("FAILED\n");
@@ -371,72 +374,72 @@ int main(void)
         /** TOO MANY DATA **/
         /** TOO MANY DATA **/
         printf("\nTEST TOO MANY DATA ERROR:\n");
         printf("\nTEST TOO MANY DATA ERROR:\n");
 
 
-        ret = read_coil_status(&mb_param,
-                               UT_COIL_STATUS_ADDRESS,
-                               MAX_STATUS + 1,
-                               tab_rp_status);
+        rc = read_coil_status(&mb_param,
+                              UT_COIL_STATUS_ADDRESS,
+                              MAX_STATUS + 1,
+                              tab_rp_status);
         printf("* read_coil_status: ");
         printf("* read_coil_status: ");
-        if (ret == INVALID_DATA) {
+        if (rc == -1 && errno == EMBMDATA) {
                 printf("OK\n");
                 printf("OK\n");
         } else {
         } else {
                 printf("FAILED\n");
                 printf("FAILED\n");
                 goto close;
                 goto close;
         }
         }
 
 
-        ret = read_input_status(&mb_param,
-                                UT_INPUT_STATUS_ADDRESS,
-                                MAX_STATUS + 1,
-                                tab_rp_status);
+        rc = read_input_status(&mb_param,
+                               UT_INPUT_STATUS_ADDRESS,
+                               MAX_STATUS + 1,
+                               tab_rp_status);
         printf("* read_input_status: ");
         printf("* read_input_status: ");
-        if (ret == INVALID_DATA) {
+        if (rc == -1 && errno == EMBMDATA) {
                 printf("OK\n");
                 printf("OK\n");
         } else {
         } else {
                 printf("FAILED\n");
                 printf("FAILED\n");
                 goto close;
                 goto close;
         }
         }
 
 
-        ret = read_holding_registers(&mb_param,
-                                     UT_HOLDING_REGISTERS_ADDRESS,
-                                     MAX_REGISTERS + 1,
-                                     tab_rp_registers);
+        rc = read_holding_registers(&mb_param,
+                                    UT_HOLDING_REGISTERS_ADDRESS,
+                                    MAX_REGISTERS + 1,
+                                    tab_rp_registers);
         printf("* read_holding_registers: ");
         printf("* read_holding_registers: ");
-        if (ret == INVALID_DATA) {
+        if (rc == -1 && errno == EMBMDATA) {
                 printf("OK\n");
                 printf("OK\n");
         } else {
         } else {
                 printf("FAILED\n");
                 printf("FAILED\n");
                 goto close;
                 goto close;
         }
         }
 
 
-        ret = read_input_registers(&mb_param,
-                                   UT_INPUT_REGISTERS_ADDRESS,
-                                   MAX_REGISTERS + 1,
-                                   tab_rp_registers);
+        rc = read_input_registers(&mb_param,
+                                  UT_INPUT_REGISTERS_ADDRESS,
+                                  MAX_REGISTERS + 1,
+                                  tab_rp_registers);
         printf("* read_input_registers: ");
         printf("* read_input_registers: ");
-        if (ret == INVALID_DATA) {
+        if (rc == -1 && errno == EMBMDATA) {
                 printf("OK\n");
                 printf("OK\n");
         } else {
         } else {
                 printf("FAILED\n");
                 printf("FAILED\n");
                 goto close;
                 goto close;
         }
         }
 
 
-        ret = force_multiple_coils(&mb_param,
-                                   UT_COIL_STATUS_ADDRESS,
-                                   MAX_STATUS + 1,
-                                   tab_rp_status);
+        rc = force_multiple_coils(&mb_param,
+                                  UT_COIL_STATUS_ADDRESS,
+                                  MAX_STATUS + 1,
+                                  tab_rp_status);
         printf("* force_multiple_coils: ");
         printf("* force_multiple_coils: ");
-        if (ret == INVALID_DATA) {
+        if (rc == -1 && errno == EMBMDATA) {
                 printf("OK\n");
                 printf("OK\n");
         } else {
         } else {
                 goto close;
                 goto close;
                 printf("FAILED\n");
                 printf("FAILED\n");
         }
         }
 
 
-        ret = preset_multiple_registers(&mb_param,
-                                        UT_HOLDING_REGISTERS_ADDRESS,
-                                        MAX_REGISTERS + 1,
-                                        tab_rp_registers);
+        rc = preset_multiple_registers(&mb_param,
+                                       UT_HOLDING_REGISTERS_ADDRESS,
+                                       MAX_REGISTERS + 1,
+                                       tab_rp_registers);
         printf("* preset_multiple_registers: ");
         printf("* preset_multiple_registers: ");
-        if (ret == INVALID_DATA) {
+        if (rc == -1 && errno == EMBMDATA) {
                 printf("OK\n");
                 printf("OK\n");
         } else {
         } else {
                 printf("FAILED\n");
                 printf("FAILED\n");
@@ -446,12 +449,12 @@ int main(void)
         /** SLAVE REPLY **/
         /** SLAVE REPLY **/
         printf("\nTEST SLAVE REPLY:\n");
         printf("\nTEST SLAVE REPLY:\n");
         modbus_set_slave(&mb_param, 18);
         modbus_set_slave(&mb_param, 18);
-        ret = read_holding_registers(&mb_param,
-                                     UT_HOLDING_REGISTERS_ADDRESS+1,
-                                     UT_HOLDING_REGISTERS_NB_POINTS,
-                                     tab_rp_registers);
+        rc = read_holding_registers(&mb_param,
+                                    UT_HOLDING_REGISTERS_ADDRESS+1,
+                                    UT_HOLDING_REGISTERS_NB_POINTS,
+                                    tab_rp_registers);
         printf("1/2 No reply from slave %d: ", mb_param.slave);
         printf("1/2 No reply from slave %d: ", mb_param.slave);
-        if (ret == SELECT_TIMEOUT) {
+        if (rc == -1 && errno == ETIMEDOUT) {
                 printf("OK\n");
                 printf("OK\n");
         } else {
         } else {
                 printf("FAILED\n");
                 printf("FAILED\n");
@@ -459,12 +462,12 @@ int main(void)
         }
         }
 
 
         modbus_set_slave(&mb_param, MODBUS_BROADCAST_ADDRESS);
         modbus_set_slave(&mb_param, MODBUS_BROADCAST_ADDRESS);
-        ret = read_holding_registers(&mb_param,
-                                     UT_HOLDING_REGISTERS_ADDRESS,
-                                     UT_HOLDING_REGISTERS_NB_POINTS,
-                                     tab_rp_registers);
+        rc = read_holding_registers(&mb_param,
+                                    UT_HOLDING_REGISTERS_ADDRESS,
+                                    UT_HOLDING_REGISTERS_NB_POINTS,
+                                    tab_rp_registers);
         printf("2/2 Reply after a broadcast query: ");
         printf("2/2 Reply after a broadcast query: ");
-        if (ret == UT_HOLDING_REGISTERS_NB_POINTS) {
+        if (rc == UT_HOLDING_REGISTERS_NB_POINTS) {
                 printf("OK\n");
                 printf("OK\n");
         } else {
         } else {
                 goto close;
                 goto close;
@@ -477,12 +480,12 @@ int main(void)
         /* Allocate only the required space */
         /* Allocate only the required space */
         tab_rp_registers_bad = (uint16_t *) malloc(
         tab_rp_registers_bad = (uint16_t *) malloc(
                 UT_HOLDING_REGISTERS_NB_POINTS_SPECIAL * sizeof(uint16_t));
                 UT_HOLDING_REGISTERS_NB_POINTS_SPECIAL * sizeof(uint16_t));
-        ret = read_holding_registers(&mb_param,
-                                     UT_HOLDING_REGISTERS_ADDRESS,
-                                     UT_HOLDING_REGISTERS_NB_POINTS_SPECIAL,
-                                     tab_rp_registers_bad);
+        rc = read_holding_registers(&mb_param,
+                                    UT_HOLDING_REGISTERS_ADDRESS,
+                                    UT_HOLDING_REGISTERS_NB_POINTS_SPECIAL,
+                                    tab_rp_registers_bad);
         printf("* read_holding_registers: ");
         printf("* read_holding_registers: ");
-        if (ret == INVALID_DATA) {
+        if (rc == -1 && errno == EMBBADDATA) {
                 printf("OK\n");
                 printf("OK\n");
         } else {
         } else {
                 printf("FAILED\n");
                 printf("FAILED\n");

+ 19 - 13
tests/unit-test-slave.c

@@ -19,6 +19,7 @@
 #include <unistd.h>
 #include <unistd.h>
 #include <string.h>
 #include <string.h>
 #include <stdlib.h>
 #include <stdlib.h>
+#include <errno.h>
 
 
 #include <modbus/modbus.h>
 #include <modbus/modbus.h>
 #include "unit-test.h"
 #include "unit-test.h"
@@ -28,20 +29,22 @@ int main(void)
         int socket;
         int socket;
         modbus_param_t mb_param;
         modbus_param_t mb_param;
         modbus_mapping_t mb_mapping;
         modbus_mapping_t mb_mapping;
-        int ret;
+        int rc;
         int i;
         int i;
 
 
         modbus_init_tcp(&mb_param, "127.0.0.1", 1502, SLAVE);
         modbus_init_tcp(&mb_param, "127.0.0.1", 1502, SLAVE);
         modbus_set_debug(&mb_param, TRUE);
         modbus_set_debug(&mb_param, TRUE);
+        modbus_set_error_recovery(&mb_param, TRUE);
 
 
-        ret = modbus_mapping_new(&mb_mapping,
+        rc = modbus_mapping_new(&mb_mapping,
                                  UT_COIL_STATUS_ADDRESS + UT_COIL_STATUS_NB_POINTS,
                                  UT_COIL_STATUS_ADDRESS + UT_COIL_STATUS_NB_POINTS,
                                  UT_INPUT_STATUS_ADDRESS + UT_INPUT_STATUS_NB_POINTS,
                                  UT_INPUT_STATUS_ADDRESS + UT_INPUT_STATUS_NB_POINTS,
                                  UT_HOLDING_REGISTERS_ADDRESS + UT_HOLDING_REGISTERS_NB_POINTS,
                                  UT_HOLDING_REGISTERS_ADDRESS + UT_HOLDING_REGISTERS_NB_POINTS,
                                  UT_INPUT_REGISTERS_ADDRESS + UT_INPUT_REGISTERS_NB_POINTS);
                                  UT_INPUT_REGISTERS_ADDRESS + UT_INPUT_REGISTERS_NB_POINTS);
-        if (ret < 0) {
-                printf("Memory allocation failed\n");
-                exit(1);
+        if (rc == -1) {
+                fprintf(stderr, "Failed to allocate the mapping: %s\n",
+                        modbus_strerror(errno));
+                return -1;
         }
         }
 
 
         /* Examples from PI_MODBUS_300.pdf.
         /* Examples from PI_MODBUS_300.pdf.
@@ -61,11 +64,11 @@ int main(void)
         socket = modbus_slave_listen_tcp(&mb_param, 1);
         socket = modbus_slave_listen_tcp(&mb_param, 1);
         modbus_slave_accept_tcp(&mb_param, &socket);
         modbus_slave_accept_tcp(&mb_param, &socket);
 
 
-        while (1) {
+        for (;;) {
                 uint8_t query[MAX_MESSAGE_LENGTH];
                 uint8_t query[MAX_MESSAGE_LENGTH];
 
 
-                ret = modbus_slave_receive(&mb_param, -1, query);
-                if (ret >= 0) {
+                rc = modbus_slave_receive(&mb_param, -1, query);
+                if (rc > 0) {
                         if (((query[HEADER_LENGTH_TCP + 3] << 8) + query[HEADER_LENGTH_TCP + 4])
                         if (((query[HEADER_LENGTH_TCP + 3] << 8) + query[HEADER_LENGTH_TCP + 4])
                             == UT_HOLDING_REGISTERS_NB_POINTS_SPECIAL) {
                             == UT_HOLDING_REGISTERS_NB_POINTS_SPECIAL) {
                                 /* Change the number of values (offset
                                 /* Change the number of values (offset
@@ -74,15 +77,18 @@ int main(void)
                                 query[HEADER_LENGTH_TCP + 4] = UT_HOLDING_REGISTERS_NB_POINTS;
                                 query[HEADER_LENGTH_TCP + 4] = UT_HOLDING_REGISTERS_NB_POINTS;
                         }
                         }
 
 
-                        modbus_slave_manage(&mb_param, query, ret, &mb_mapping);
-                } else if (ret == CONNECTION_CLOSED) {
-                        /* Connection closed by the client, end of server */
-                        break;
+                        rc = modbus_slave_manage(&mb_param, query, rc, &mb_mapping);
+                        if (rc == -1) {
+                                return -1;
+                        }
                 } else {
                 } else {
-                        fprintf(stderr, "Error in modbus_listen (%d)\n", ret);
+                        /* Connection closed by the client or error */
+                        break;
                 }
                 }
         }
         }
 
 
+        printf("Quit the loop: %s\n", modbus_strerror(errno));
+
         close(socket);
         close(socket);
         modbus_mapping_free(&mb_mapping);
         modbus_mapping_free(&mb_mapping);
         modbus_close(&mb_param);
         modbus_close(&mb_param);

Some files were not shown because too many files changed in this diff