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 | 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 | ... | ... |