Commit ef3c4bc989a4774402b89880d1afd54b1b6a1b67
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.
Showing
3 changed files
with
34 additions
and
44 deletions
src/modbus-tcp-private.h
| @@ -27,18 +27,15 @@ typedef struct _modbus_tcp { | @@ -27,18 +27,15 @@ typedef struct _modbus_tcp { | ||
| 27 | char ip[16]; | 27 | char ip[16]; |
| 28 | } modbus_tcp_t; | 28 | } modbus_tcp_t; |
| 29 | 29 | ||
| 30 | -#define _MODBUS_TCP_PI_NODE_LENGTH 1025 | ||
| 31 | -#define _MODBUS_TCP_PI_SERVICE_LENGTH 32 | ||
| 32 | - | ||
| 33 | typedef struct _modbus_tcp_pi { | 30 | typedef struct _modbus_tcp_pi { |
| 34 | /* Transaction ID */ | 31 | /* Transaction ID */ |
| 35 | uint16_t t_id; | 32 | uint16_t t_id; |
| 36 | /* TCP port */ | 33 | /* TCP port */ |
| 37 | int port; | 34 | int port; |
| 38 | /* Node */ | 35 | /* Node */ |
| 39 | - char node[_MODBUS_TCP_PI_NODE_LENGTH]; | 36 | + char *node; |
| 40 | /* Service */ | 37 | /* Service */ |
| 41 | - char service[_MODBUS_TCP_PI_SERVICE_LENGTH]; | 38 | + char *service; |
| 42 | } modbus_tcp_pi_t; | 39 | } modbus_tcp_pi_t; |
| 43 | 40 | ||
| 44 | #endif /* MODBUS_TCP_PRIVATE_H */ | 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,7 +740,20 @@ static int _modbus_tcp_select(modbus_t *ctx, fd_set *rset, struct timeval *tv, i | ||
| 740 | } | 740 | } |
| 741 | 741 | ||
| 742 | static void _modbus_tcp_free(modbus_t *ctx) { | 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 | free(ctx); | 757 | free(ctx); |
| 745 | } | 758 | } |
| 746 | 759 | ||
| @@ -786,7 +799,7 @@ const modbus_backend_t _modbus_tcp_pi_backend = { | @@ -786,7 +799,7 @@ const modbus_backend_t _modbus_tcp_pi_backend = { | ||
| 786 | _modbus_tcp_close, | 799 | _modbus_tcp_close, |
| 787 | _modbus_tcp_flush, | 800 | _modbus_tcp_flush, |
| 788 | _modbus_tcp_select, | 801 | _modbus_tcp_select, |
| 789 | - _modbus_tcp_free | 802 | + _modbus_tcp_pi_free |
| 790 | }; | 803 | }; |
| 791 | 804 | ||
| 792 | modbus_t* modbus_new_tcp(const char *ip, int port) | 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,8 +871,6 @@ modbus_t* modbus_new_tcp_pi(const char *node, const char *service) | ||
| 858 | { | 871 | { |
| 859 | modbus_t *ctx; | 872 | modbus_t *ctx; |
| 860 | modbus_tcp_pi_t *ctx_tcp_pi; | 873 | modbus_tcp_pi_t *ctx_tcp_pi; |
| 861 | - size_t dest_size; | ||
| 862 | - size_t ret_size; | ||
| 863 | 874 | ||
| 864 | ctx = (modbus_t *)malloc(sizeof(modbus_t)); | 875 | ctx = (modbus_t *)malloc(sizeof(modbus_t)); |
| 865 | if (ctx == NULL) { | 876 | if (ctx == NULL) { |
| @@ -879,47 +890,32 @@ modbus_t* modbus_new_tcp_pi(const char *node, const char *service) | @@ -879,47 +890,32 @@ modbus_t* modbus_new_tcp_pi(const char *node, const char *service) | ||
| 879 | return NULL; | 890 | return NULL; |
| 880 | } | 891 | } |
| 881 | ctx_tcp_pi = (modbus_tcp_pi_t *)ctx->backend_data; | 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 | } else { | 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 | modbus_free(ctx); | 904 | modbus_free(ctx); |
| 915 | - errno = EINVAL; | 905 | + errno = ENOMEM; |
| 916 | return NULL; | 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 | modbus_free(ctx); | 917 | modbus_free(ctx); |
| 922 | - errno = EINVAL; | 918 | + errno = ENOMEM; |
| 923 | return NULL; | 919 | return NULL; |
| 924 | } | 920 | } |
| 925 | 921 |
tests/unit-test-client.c
| @@ -681,9 +681,6 @@ int main(int argc, char *argv[]) | @@ -681,9 +681,6 @@ int main(int argc, char *argv[]) | ||
| 681 | ctx = modbus_new_rtu("/dev/dummy", 0, 'A', 0, 0); | 681 | ctx = modbus_new_rtu("/dev/dummy", 0, 'A', 0, 0); |
| 682 | ASSERT_TRUE(ctx == NULL && errno == EINVAL, ""); | 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 | printf("\nALL TESTS PASS WITH SUCCESS.\n"); | 684 | printf("\nALL TESTS PASS WITH SUCCESS.\n"); |
| 688 | success = TRUE; | 685 | success = TRUE; |
| 689 | 686 |