Commit ef3c4bc989a4774402b89880d1afd54b1b6a1b67

Authored by Stéphane Raimbault
1 parent 9b679b7c

Reduce memory use of TCP PI backend (closes #621)

- allocate exact memory required to store node and service strings
  instead of around 1kb of static memory.
- accept NULL value of service to use default Modbus port number (502)
- unit test updated

The new documentation will be updated in another commit.
src/modbus-tcp-private.h
... ... @@ -27,18 +27,15 @@ typedef struct _modbus_tcp {
27 27 char ip[16];
28 28 } modbus_tcp_t;
29 29  
30   -#define _MODBUS_TCP_PI_NODE_LENGTH 1025
31   -#define _MODBUS_TCP_PI_SERVICE_LENGTH 32
32   -
33 30 typedef struct _modbus_tcp_pi {
34 31 /* Transaction ID */
35 32 uint16_t t_id;
36 33 /* TCP port */
37 34 int port;
38 35 /* Node */
39   - char node[_MODBUS_TCP_PI_NODE_LENGTH];
  36 + char *node;
40 37 /* Service */
41   - char service[_MODBUS_TCP_PI_SERVICE_LENGTH];
  38 + char *service;
42 39 } modbus_tcp_pi_t;
43 40  
44 41 #endif /* MODBUS_TCP_PRIVATE_H */
... ...
src/modbus-tcp.c
... ... @@ -740,7 +740,20 @@ static int _modbus_tcp_select(modbus_t *ctx, fd_set *rset, struct timeval *tv, i
740 740 }
741 741  
742 742 static void _modbus_tcp_free(modbus_t *ctx) {
743   - free(ctx->backend_data);
  743 + if (ctx->backend_data) {
  744 + free(ctx->backend_data);
  745 + }
  746 + free(ctx);
  747 +}
  748 +
  749 +static void _modbus_tcp_pi_free(modbus_t *ctx) {
  750 + if (ctx->backend_data) {
  751 + modbus_tcp_pi_t *ctx_tcp_pi = ctx->backend_data;
  752 + free(ctx_tcp_pi->node);
  753 + free(ctx_tcp_pi->service);
  754 + free(ctx->backend_data);
  755 + }
  756 +
744 757 free(ctx);
745 758 }
746 759  
... ... @@ -786,7 +799,7 @@ const modbus_backend_t _modbus_tcp_pi_backend = {
786 799 _modbus_tcp_close,
787 800 _modbus_tcp_flush,
788 801 _modbus_tcp_select,
789   - _modbus_tcp_free
  802 + _modbus_tcp_pi_free
790 803 };
791 804  
792 805 modbus_t* modbus_new_tcp(const char *ip, int port)
... ... @@ -858,8 +871,6 @@ modbus_t* modbus_new_tcp_pi(const char *node, const char *service)
858 871 {
859 872 modbus_t *ctx;
860 873 modbus_tcp_pi_t *ctx_tcp_pi;
861   - size_t dest_size;
862   - size_t ret_size;
863 874  
864 875 ctx = (modbus_t *)malloc(sizeof(modbus_t));
865 876 if (ctx == NULL) {
... ... @@ -879,47 +890,32 @@ modbus_t* modbus_new_tcp_pi(const char *node, const char *service)
879 890 return NULL;
880 891 }
881 892 ctx_tcp_pi = (modbus_tcp_pi_t *)ctx->backend_data;
  893 + ctx_tcp_pi->node = NULL;
  894 + ctx_tcp_pi->service = NULL;
882 895  
883   - if (node == NULL) {
884   - /* The node argument can be empty to indicate any hosts */
885   - ctx_tcp_pi->node[0] = 0;
886   - } else {
887   - dest_size = sizeof(char) * _MODBUS_TCP_PI_NODE_LENGTH;
888   - ret_size = strlcpy(ctx_tcp_pi->node, node, dest_size);
889   - if (ret_size == 0) {
890   - fprintf(stderr, "The node string is empty\n");
891   - modbus_free(ctx);
892   - errno = EINVAL;
893   - return NULL;
894   - }
895   -
896   - if (ret_size >= dest_size) {
897   - fprintf(stderr, "The node string has been truncated\n");
898   - modbus_free(ctx);
899   - errno = EINVAL;
900   - return NULL;
901   - }
902   - }
903   -
904   - if (service != NULL) {
905   - dest_size = sizeof(char) * _MODBUS_TCP_PI_SERVICE_LENGTH;
906   - ret_size = strlcpy(ctx_tcp_pi->service, service, dest_size);
  896 + if (node != NULL) {
  897 + ctx_tcp_pi->node = strdup(node);
907 898 } else {
908   - /* Empty service is not allowed, error caught below. */
909   - ret_size = 0;
  899 + /* The node argument can be empty to indicate any hosts */
  900 + ctx_tcp_pi->node = strdup("");
910 901 }
911 902  
912   - if (ret_size == 0) {
913   - fprintf(stderr, "The service string is empty\n");
  903 + if (ctx_tcp_pi->node == NULL) {
914 904 modbus_free(ctx);
915   - errno = EINVAL;
  905 + errno = ENOMEM;
916 906 return NULL;
917 907 }
918 908  
919   - if (ret_size >= dest_size) {
920   - fprintf(stderr, "The service string has been truncated\n");
  909 + if (service != NULL && service[0] != '\0') {
  910 + ctx_tcp_pi->service = strdup(service);
  911 + } else {
  912 + /* Default Modbus port number */
  913 + ctx_tcp_pi->service = strdup("502");
  914 + }
  915 +
  916 + if (ctx_tcp_pi->service == NULL) {
921 917 modbus_free(ctx);
922   - errno = EINVAL;
  918 + errno = ENOMEM;
923 919 return NULL;
924 920 }
925 921  
... ...
tests/unit-test-client.c
... ... @@ -681,9 +681,6 @@ int main(int argc, char *argv[])
681 681 ctx = modbus_new_rtu("/dev/dummy", 0, 'A', 0, 0);
682 682 ASSERT_TRUE(ctx == NULL && errno == EINVAL, "");
683 683  
684   - ctx = modbus_new_tcp_pi(NULL, NULL);
685   - ASSERT_TRUE(ctx == NULL && errno == EINVAL, "");
686   -
687 684 printf("\nALL TESTS PASS WITH SUCCESS.\n");
688 685 success = TRUE;
689 686  
... ...