Ver Fonte

Truncate data from response in report_slave_id to new max arg (closes #167)

Change API of function for libmodbus v3.2.0
Stéphane Raimbault há 11 anos atrás
pai
commit
52a82f8cfe
4 ficheiros alterados com 47 adições e 27 exclusões
  1. 13 3
      doc/modbus_report_slave_id.txt
  2. 5 5
      src/modbus.c
  3. 1 1
      src/modbus.h
  4. 28 18
      tests/unit-test-client.c

+ 13 - 3
doc/modbus_report_slave_id.txt

@@ -9,7 +9,7 @@ modbus_report_slave_id - returns a description of the controller
 
 SYNOPSIS
 --------
-*int modbus_report_slave_id(modbus_t *'ctx', uint8_t *'dest');*
+*int modbus_report_slave_id(modbus_t *'ctx', int 'max_dest', uint8_t *'dest');*
 
 
 DESCRIPTION
@@ -26,25 +26,35 @@ The response stored in 'dest' contains:
 * additional data specific to each controller. For example, libmodbus returns
   the version of the library as a string.
 
+The function write at most 'max_dest' bytes from the response to 'dest'.
 
 RETURN VALUE
 ------------
 The _modbus_report_slave_id()_ function shall return the number of read data if
-successful. Otherwise it shall return -1 and set errno.
+successful.
 
+If the output was truncated due to the 'max_dest' limit then the return value is
+the number of bytes which would have been written to 'dest' if enough space had
+been available. Thus, a return value greater than 'max_dest' means that the
+response data was truncated.
+
+Otherwise it shall return -1 and set errno.
 
 EXAMPLE
 -------
 [source,c]
 -------------------
+uint8_t nb = 128;
 uint8_t *tab_bytes;
 
 ...
 
-rc = modbus_report_slave_id(ctx, tab_bytes);
+tab_bytes = (uint8_t *) malloc(nb * sizeof(uint8_t));
+rc = modbus_report_slave_id(ctx, nb, tab_bytes);
 if (rc > 1) {
     printf("Run Status Indicator: %s\n", tab_bytes[1] ? "ON" : "OFF");
 }
+free(tab_bytes);
 -------------------
 
 

+ 5 - 5
src/modbus.c

@@ -1540,13 +1540,13 @@ int modbus_write_and_read_registers(modbus_t *ctx,
 
 /* Send a request to get the slave ID of the device (only available in serial
    communication). */
-int modbus_report_slave_id(modbus_t *ctx, uint8_t *dest)
+int modbus_report_slave_id(modbus_t *ctx, int max_dest, uint8_t *dest)
 {
     int rc;
     int req_length;
     uint8_t req[_MIN_REQ_LENGTH];
 
-    if (ctx == NULL) {
+    if (ctx == NULL || max_dest <= 0) {
         errno = EINVAL;
         return -1;
     }
@@ -1573,9 +1573,9 @@ int modbus_report_slave_id(modbus_t *ctx, uint8_t *dest)
 
         offset = ctx->backend->header_length + 2;
 
-        /* Byte count, slave id, run indicator status,
-           additional data */
-        for (i=0; i < rc; i++) {
+        /* Byte count, slave id, run indicator status and
+           additional data. Truncate copy to max_dest. */
+        for (i=0; i < rc && i < max_dest; i++) {
             dest[i] = rsp[offset + i];
         }
     }

+ 1 - 1
src/modbus.h

@@ -202,7 +202,7 @@ MODBUS_API int modbus_mask_write_register(modbus_t *ctx, int addr, uint16_t and_
 MODBUS_API int modbus_write_and_read_registers(modbus_t *ctx, int write_addr, int write_nb,
                                                const uint16_t *src, int read_addr, int read_nb,
                                                uint16_t *dest);
-MODBUS_API int modbus_report_slave_id(modbus_t *ctx, uint8_t *dest);
+MODBUS_API int modbus_report_slave_id(modbus_t *ctx, int max_dest, uint8_t *dest);
 
 MODBUS_API modbus_mapping_t* modbus_mapping_new(int nb_bits, int nb_input_bits,
                                             int nb_registers, int nb_input_registers);

+ 28 - 18
tests/unit-test-client.c

@@ -34,6 +34,7 @@ int test_raw_request(modbus_t *, int);
 
 int main(int argc, char *argv[])
 {
+    const int NB_REPORT_SLAVE_ID = 10;
     uint8_t *tab_rp_bits = NULL;
     uint16_t *tab_rp_registers = NULL;
     uint16_t *tab_rp_registers_bad = NULL;
@@ -539,7 +540,7 @@ int main(int argc, char *argv[])
         uint8_t rsp[MODBUS_RTU_MAX_ADU_LENGTH];
 
         /* No response in RTU mode */
-        printf("1/5-A No response from slave %d: ", INVALID_SERVER_ID);
+        printf("1-A/3 No response from slave %d: ", INVALID_SERVER_ID);
 
         if (rc == -1 && errno == ETIMEDOUT) {
             printf("OK\n");
@@ -560,7 +561,7 @@ int main(int argc, char *argv[])
         modbus_send_raw_request(ctx, raw_rep, RAW_REP_LENGTH * sizeof(uint8_t));
         rc = modbus_receive_confirmation(ctx, rsp);
 
-        printf("1/5-B No response from slave %d on indication/confirmation messages: ",
+        printf("1-B/3 No response from slave %d on indication/confirmation messages: ",
                INVALID_SERVER_ID);
 
         if (rc == -1 && errno == ETIMEDOUT) {
@@ -574,7 +575,7 @@ int main(int argc, char *argv[])
         modbus_send_raw_request(ctx, raw_invalid_req, RAW_REQ_LENGTH * sizeof(uint8_t));
         rc = modbus_receive_confirmation(ctx, rsp);
 
-        printf("1/5-C No response from slave %d with invalid request: ",
+        printf("1-C/3 No response from slave %d with invalid request: ",
                INVALID_SERVER_ID);
 
         if (rc == -1 && errno == ETIMEDOUT) {
@@ -585,7 +586,7 @@ int main(int argc, char *argv[])
         }
     } else {
         /* Response in TCP mode */
-        printf("1/4 Response from slave %d: ", INVALID_SERVER_ID);
+        printf("1/3 Response from slave %d: ", INVALID_SERVER_ID);
 
         if (rc == UT_REGISTERS_NB) {
             printf("OK\n");
@@ -603,7 +604,7 @@ int main(int argc, char *argv[])
 
     rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
                                UT_REGISTERS_NB, tab_rp_registers);
-    printf("2/5 Reply after a broadcast query: ");
+    printf("2/3 Reply after a broadcast query: ");
     if (rc == UT_REGISTERS_NB) {
         printf("OK\n");
     } else {
@@ -618,10 +619,29 @@ int main(int argc, char *argv[])
         modbus_set_slave(ctx, MODBUS_TCP_SLAVE);
     }
 
-    printf("3/5 Report slave ID: \n");
-    /* tab_rp_bits is used to store bytes */
-    rc = modbus_report_slave_id(ctx, tab_rp_bits);
+    printf("3/3 Response with an invalid TID or slave: ");
+    rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS_INVALID_TID_OR_SLAVE,
+                               1, tab_rp_registers);
     if (rc == -1) {
+        printf("OK\n");
+    } else {
+        printf("FAILED\n");
+        goto close;
+    }
+
+    printf("1/2 Report slave ID truncated: \n");
+    /* Set a marker to ensure limit is respected */
+    tab_rp_bits[NB_REPORT_SLAVE_ID - 1] = 42;
+    rc = modbus_report_slave_id(ctx, NB_REPORT_SLAVE_ID - 1, tab_rp_bits);
+    if (rc != NB_REPORT_SLAVE_ID && tab_rp_bits[NB_REPORT_SLAVE_ID - 1] != 42) {
+        printf("FAILED\n");
+        goto close;
+    }
+
+    printf("2/2 Report slave ID: \n");
+    /* tab_rp_bits is used to store bytes */
+    rc = modbus_report_slave_id(ctx, NB_REPORT_SLAVE_ID, tab_rp_bits);
+    if (rc != NB_REPORT_SLAVE_ID) {
         printf("FAILED\n");
         goto close;
     }
@@ -651,16 +671,6 @@ int main(int argc, char *argv[])
         printf("\n");
     }
 
-    printf("5/5 Response with an invalid TID or slave: ");
-    rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS_INVALID_TID_OR_SLAVE,
-                               1, tab_rp_registers);
-    if (rc == -1) {
-        printf("OK\n");
-    } else {
-        printf("FAILED\n");
-        goto close;
-    }
-
     /* Save original timeout */
     modbus_get_response_timeout(ctx, &old_response_to_sec, &old_response_to_usec);
     modbus_get_byte_timeout(ctx, &old_byte_to_sec, &old_byte_to_usec);