ソースを参照

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
Stéphane Raimbault 11 年 前
コミット
8f1cc7b3c8
4 ファイル変更48 行追加27 行削除
  1. 6 5
      doc/modbus_new_tcp_pi.txt
  2. 7 4
      doc/modbus_tcp_pi_listen.txt
  3. 32 18
      src/modbus-tcp.c
  4. 3 0
      tests/unit-test-client.c

+ 6 - 5
doc/modbus_new_tcp_pi.txt

@@ -14,11 +14,12 @@ SYNOPSIS
 
 DESCRIPTION
 -----------
-The _modbus_new_tcp_pi()_ function shall allocate and initialize a modbus_t
-structure to communicate with a Modbus TCP IPv4 or Ipv6 server.
+The *modbus_new_tcp_pi()* function shall allocate and initialize a modbus_t
+structure to communicate with a Modbus TCP IPv4 or IPv6 server.
 
 The _node_ argument specifies the host name or IP address of the host to connect
-to, eg. '192.168.0.5' , '::1' or 'server.com'.
+to, eg. "192.168.0.5" , "::1" or "server.com". A NULL value can be used to
+listen any addresses in server mode.
 
 The _service_ argument is the service name/port number to connect to. To use the
 default Modbus port use the string "502". On many Unix systems, it’s
@@ -28,7 +29,7 @@ necessary to have administrator privileges.
 
 RETURN VALUE
 ------------
-The _modbus_new_tcp_pi()_ function shall return a pointer to a *modbus_t* structure
+The *modbus_new_tcp_pi()* function shall return a pointer to a *modbus_t* structure
 if successful. Otherwise it shall return NULL and set errno to one of the values
 defined below.
 
@@ -62,7 +63,7 @@ if (modbus_connect(ctx) == -1) {
 SEE ALSO
 --------
 linkmb:modbus_new_tcp[3]
-linkmb:modbus_new_rtu[3]
+linkmb:modbus_tcp_pi_listen[3]
 linkmb:modbus_free[3]
 
 

+ 7 - 4
doc/modbus_tcp_pi_listen.txt

@@ -14,13 +14,16 @@ SYNOPSIS
 
 DESCRIPTION
 -----------
-The _modbus_tcp_pi_listen()_ function shall create a socket and listen for
-'nb_connection' incoming connections.
+The *modbus_tcp_pi_listen()* function shall create a socket and listen to
+maximum _nb_connection_ incoming connections on the specified nodes.  The
+context *ctx* must be allocated and initialized with linkmb:modbus_new_tcp_pi[3]
+before to set the node to listen, if node is set to NULL, any addresses will be
+listen.
 
 
 RETURN VALUE
 ------------
-The _modbus_tcp_listen()_ function shall return a new socket if
+The *modbus_tcp_listen()* function shall return a new socket if
 successful. Otherwise it shall return -1 and set errno.
 
 
@@ -54,8 +57,8 @@ modbus_free(ctx);
 
 SEE ALSO
 --------
+linkmb:modbus_new_tcp_pi[3]
 linkmb:modbus_tcp_pi_accept[3]
-linkmb:modbus_tcp_accept[3]
 linkmb:modbus_tcp_listen[3]
 
 AUTHORS

+ 32 - 18
src/modbus-tcp.c

@@ -553,17 +553,20 @@ int modbus_tcp_pi_listen(modbus_t *ctx, int nb_connection)
     }
 #endif
 
-    if (ctx_tcp_pi->node[0] == 0)
+    if (ctx_tcp_pi->node[0] == 0) {
         node = NULL; /* == any */
-    else
+    } else {
         node = ctx_tcp_pi->node;
+    }
 
-    if (ctx_tcp_pi->service[0] == 0)
+    if (ctx_tcp_pi->service[0] == 0) {
         service = "502";
-    else
+    } else {
         service = ctx_tcp_pi->service;
+    }
 
     memset(&ai_hints, 0, sizeof (ai_hints));
+    /* If node is not NULL, than the AI_PASSIVE flag is ignored. */
     ai_hints.ai_flags |= AI_PASSIVE;
 #ifdef AI_ADDRCONFIG
     ai_hints.ai_flags |= AI_ADDRCONFIG;
@@ -845,24 +848,35 @@ modbus_t* modbus_new_tcp_pi(const char *node, const char *service)
     ctx->backend_data = (modbus_tcp_pi_t *) malloc(sizeof(modbus_tcp_pi_t));
     ctx_tcp_pi = (modbus_tcp_pi_t *)ctx->backend_data;
 
-    dest_size = sizeof(char) * _MODBUS_TCP_PI_NODE_LENGTH;
-    ret_size = strlcpy(ctx_tcp_pi->node, node, dest_size);
-    if (ret_size == 0) {
-        fprintf(stderr, "The node string is empty\n");
-        modbus_free(ctx);
-        errno = EINVAL;
-        return NULL;
+    if (node == NULL) {
+        /* The node argument can be empty to indicate any hosts */
+        ctx_tcp_pi->node[0] = '0';
+    } else {
+        dest_size = sizeof(char) * _MODBUS_TCP_PI_NODE_LENGTH;
+        ret_size = strlcpy(ctx_tcp_pi->node, node, dest_size);
+        if (ret_size == 0) {
+            fprintf(stderr, "The node string is empty\n");
+            modbus_free(ctx);
+            errno = EINVAL;
+            return NULL;
+        }
+
+        if (ret_size >= dest_size) {
+            fprintf(stderr, "The node string has been truncated\n");
+            modbus_free(ctx);
+            errno = EINVAL;
+            return NULL;
+        }
     }
 
-    if (ret_size >= dest_size) {
-        fprintf(stderr, "The node string has been truncated\n");
-        modbus_free(ctx);
-        errno = EINVAL;
-        return NULL;
+    if (service != NULL) {
+        dest_size = sizeof(char) * _MODBUS_TCP_PI_SERVICE_LENGTH;
+        ret_size = strlcpy(ctx_tcp_pi->service, service, dest_size);
+    } else {
+        /* Empty service is not allowed, error catched below. */
+        ret_size = 0;
     }
 
-    dest_size = sizeof(char) * _MODBUS_TCP_PI_SERVICE_LENGTH;
-    ret_size = strlcpy(ctx_tcp_pi->service, service, dest_size);
     if (ret_size == 0) {
         fprintf(stderr, "The service string is empty\n");
         modbus_free(ctx);

+ 3 - 0
tests/unit-test-client.c

@@ -600,6 +600,9 @@ int main(int argc, char *argv[])
     ctx = modbus_new_rtu(NULL, 0, 'A', 0, 0);
     ASSERT_TRUE(ctx == NULL && errno == EINVAL, "");
 
+    ctx = modbus_new_tcp_pi(NULL, NULL);
+    ASSERT_TRUE(ctx == NULL && errno == EINVAL, "");
+
     printf("\nALL TESTS PASS WITH SUCCESS.\n");
 
 close: