Commit 8f1cc7b3c8de8ef64b2ea35676d3e6ac039dbc3d
1 parent
652b5b05
Allow to listen any hosts in IPv6 (closes #32)
- allow an empty string or NULL for node argument - protect against NULL in service argument - new test for NULL service - update documentation
Showing
4 changed files
with
48 additions
and
27 deletions
doc/modbus_new_tcp_pi.txt
| ... | ... | @@ -14,11 +14,12 @@ SYNOPSIS |
| 14 | 14 | |
| 15 | 15 | DESCRIPTION |
| 16 | 16 | ----------- |
| 17 | -The _modbus_new_tcp_pi()_ function shall allocate and initialize a modbus_t | |
| 18 | -structure to communicate with a Modbus TCP IPv4 or Ipv6 server. | |
| 17 | +The *modbus_new_tcp_pi()* function shall allocate and initialize a modbus_t | |
| 18 | +structure to communicate with a Modbus TCP IPv4 or IPv6 server. | |
| 19 | 19 | |
| 20 | 20 | The _node_ argument specifies the host name or IP address of the host to connect |
| 21 | -to, eg. '192.168.0.5' , '::1' or 'server.com'. | |
| 21 | +to, eg. "192.168.0.5" , "::1" or "server.com". A NULL value can be used to | |
| 22 | +listen any addresses in server mode. | |
| 22 | 23 | |
| 23 | 24 | The _service_ argument is the service name/port number to connect to. To use the |
| 24 | 25 | default Modbus port use the string "502". On many Unix systems, it’s |
| ... | ... | @@ -28,7 +29,7 @@ necessary to have administrator privileges. |
| 28 | 29 | |
| 29 | 30 | RETURN VALUE |
| 30 | 31 | ------------ |
| 31 | -The _modbus_new_tcp_pi()_ function shall return a pointer to a *modbus_t* structure | |
| 32 | +The *modbus_new_tcp_pi()* function shall return a pointer to a *modbus_t* structure | |
| 32 | 33 | if successful. Otherwise it shall return NULL and set errno to one of the values |
| 33 | 34 | defined below. |
| 34 | 35 | |
| ... | ... | @@ -62,7 +63,7 @@ if (modbus_connect(ctx) == -1) { |
| 62 | 63 | SEE ALSO |
| 63 | 64 | -------- |
| 64 | 65 | linkmb:modbus_new_tcp[3] |
| 65 | -linkmb:modbus_new_rtu[3] | |
| 66 | +linkmb:modbus_tcp_pi_listen[3] | |
| 66 | 67 | linkmb:modbus_free[3] |
| 67 | 68 | |
| 68 | 69 | ... | ... |
doc/modbus_tcp_pi_listen.txt
| ... | ... | @@ -14,13 +14,16 @@ SYNOPSIS |
| 14 | 14 | |
| 15 | 15 | DESCRIPTION |
| 16 | 16 | ----------- |
| 17 | -The _modbus_tcp_pi_listen()_ function shall create a socket and listen for | |
| 18 | -'nb_connection' incoming connections. | |
| 17 | +The *modbus_tcp_pi_listen()* function shall create a socket and listen to | |
| 18 | +maximum _nb_connection_ incoming connections on the specified nodes. The | |
| 19 | +context *ctx* must be allocated and initialized with linkmb:modbus_new_tcp_pi[3] | |
| 20 | +before to set the node to listen, if node is set to NULL, any addresses will be | |
| 21 | +listen. | |
| 19 | 22 | |
| 20 | 23 | |
| 21 | 24 | RETURN VALUE |
| 22 | 25 | ------------ |
| 23 | -The _modbus_tcp_listen()_ function shall return a new socket if | |
| 26 | +The *modbus_tcp_listen()* function shall return a new socket if | |
| 24 | 27 | successful. Otherwise it shall return -1 and set errno. |
| 25 | 28 | |
| 26 | 29 | |
| ... | ... | @@ -54,8 +57,8 @@ modbus_free(ctx); |
| 54 | 57 | |
| 55 | 58 | SEE ALSO |
| 56 | 59 | -------- |
| 60 | +linkmb:modbus_new_tcp_pi[3] | |
| 57 | 61 | linkmb:modbus_tcp_pi_accept[3] |
| 58 | -linkmb:modbus_tcp_accept[3] | |
| 59 | 62 | linkmb:modbus_tcp_listen[3] |
| 60 | 63 | |
| 61 | 64 | AUTHORS | ... | ... |
src/modbus-tcp.c
| ... | ... | @@ -553,17 +553,20 @@ int modbus_tcp_pi_listen(modbus_t *ctx, int nb_connection) |
| 553 | 553 | } |
| 554 | 554 | #endif |
| 555 | 555 | |
| 556 | - if (ctx_tcp_pi->node[0] == 0) | |
| 556 | + if (ctx_tcp_pi->node[0] == 0) { | |
| 557 | 557 | node = NULL; /* == any */ |
| 558 | - else | |
| 558 | + } else { | |
| 559 | 559 | node = ctx_tcp_pi->node; |
| 560 | + } | |
| 560 | 561 | |
| 561 | - if (ctx_tcp_pi->service[0] == 0) | |
| 562 | + if (ctx_tcp_pi->service[0] == 0) { | |
| 562 | 563 | service = "502"; |
| 563 | - else | |
| 564 | + } else { | |
| 564 | 565 | service = ctx_tcp_pi->service; |
| 566 | + } | |
| 565 | 567 | |
| 566 | 568 | memset(&ai_hints, 0, sizeof (ai_hints)); |
| 569 | + /* If node is not NULL, than the AI_PASSIVE flag is ignored. */ | |
| 567 | 570 | ai_hints.ai_flags |= AI_PASSIVE; |
| 568 | 571 | #ifdef AI_ADDRCONFIG |
| 569 | 572 | ai_hints.ai_flags |= AI_ADDRCONFIG; |
| ... | ... | @@ -845,24 +848,35 @@ modbus_t* modbus_new_tcp_pi(const char *node, const char *service) |
| 845 | 848 | ctx->backend_data = (modbus_tcp_pi_t *) malloc(sizeof(modbus_tcp_pi_t)); |
| 846 | 849 | ctx_tcp_pi = (modbus_tcp_pi_t *)ctx->backend_data; |
| 847 | 850 | |
| 848 | - dest_size = sizeof(char) * _MODBUS_TCP_PI_NODE_LENGTH; | |
| 849 | - ret_size = strlcpy(ctx_tcp_pi->node, node, dest_size); | |
| 850 | - if (ret_size == 0) { | |
| 851 | - fprintf(stderr, "The node string is empty\n"); | |
| 852 | - modbus_free(ctx); | |
| 853 | - errno = EINVAL; | |
| 854 | - return NULL; | |
| 851 | + if (node == NULL) { | |
| 852 | + /* The node argument can be empty to indicate any hosts */ | |
| 853 | + ctx_tcp_pi->node[0] = '0'; | |
| 854 | + } else { | |
| 855 | + dest_size = sizeof(char) * _MODBUS_TCP_PI_NODE_LENGTH; | |
| 856 | + ret_size = strlcpy(ctx_tcp_pi->node, node, dest_size); | |
| 857 | + if (ret_size == 0) { | |
| 858 | + fprintf(stderr, "The node string is empty\n"); | |
| 859 | + modbus_free(ctx); | |
| 860 | + errno = EINVAL; | |
| 861 | + return NULL; | |
| 862 | + } | |
| 863 | + | |
| 864 | + if (ret_size >= dest_size) { | |
| 865 | + fprintf(stderr, "The node string has been truncated\n"); | |
| 866 | + modbus_free(ctx); | |
| 867 | + errno = EINVAL; | |
| 868 | + return NULL; | |
| 869 | + } | |
| 855 | 870 | } |
| 856 | 871 | |
| 857 | - if (ret_size >= dest_size) { | |
| 858 | - fprintf(stderr, "The node string has been truncated\n"); | |
| 859 | - modbus_free(ctx); | |
| 860 | - errno = EINVAL; | |
| 861 | - return NULL; | |
| 872 | + if (service != NULL) { | |
| 873 | + dest_size = sizeof(char) * _MODBUS_TCP_PI_SERVICE_LENGTH; | |
| 874 | + ret_size = strlcpy(ctx_tcp_pi->service, service, dest_size); | |
| 875 | + } else { | |
| 876 | + /* Empty service is not allowed, error catched below. */ | |
| 877 | + ret_size = 0; | |
| 862 | 878 | } |
| 863 | 879 | |
| 864 | - dest_size = sizeof(char) * _MODBUS_TCP_PI_SERVICE_LENGTH; | |
| 865 | - ret_size = strlcpy(ctx_tcp_pi->service, service, dest_size); | |
| 866 | 880 | if (ret_size == 0) { |
| 867 | 881 | fprintf(stderr, "The service string is empty\n"); |
| 868 | 882 | modbus_free(ctx); | ... | ... |
tests/unit-test-client.c
| ... | ... | @@ -600,6 +600,9 @@ int main(int argc, char *argv[]) |
| 600 | 600 | ctx = modbus_new_rtu(NULL, 0, 'A', 0, 0); |
| 601 | 601 | ASSERT_TRUE(ctx == NULL && errno == EINVAL, ""); |
| 602 | 602 | |
| 603 | + ctx = modbus_new_tcp_pi(NULL, NULL); | |
| 604 | + ASSERT_TRUE(ctx == NULL && errno == EINVAL, ""); | |
| 605 | + | |
| 603 | 606 | printf("\nALL TESTS PASS WITH SUCCESS.\n"); |
| 604 | 607 | |
| 605 | 608 | close: | ... | ... |