浏览代码

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
 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
 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
 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
 default Modbus port use the string "502". On many Unix systems, it’s
@@ -28,7 +29,7 @@ necessary to have administrator privileges.
 
 
 RETURN VALUE
 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
 if successful. Otherwise it shall return NULL and set errno to one of the values
 defined below.
 defined below.
 
 
@@ -62,7 +63,7 @@ if (modbus_connect(ctx) == -1) {
 SEE ALSO
 SEE ALSO
 --------
 --------
 linkmb:modbus_new_tcp[3]
 linkmb:modbus_new_tcp[3]
-linkmb:modbus_new_rtu[3]
+linkmb:modbus_tcp_pi_listen[3]
 linkmb:modbus_free[3]
 linkmb:modbus_free[3]
 
 
 
 

+ 7 - 4
doc/modbus_tcp_pi_listen.txt

@@ -14,13 +14,16 @@ SYNOPSIS
 
 
 DESCRIPTION
 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
 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.
 successful. Otherwise it shall return -1 and set errno.
 
 
 
 
@@ -54,8 +57,8 @@ modbus_free(ctx);
 
 
 SEE ALSO
 SEE ALSO
 --------
 --------
+linkmb:modbus_new_tcp_pi[3]
 linkmb:modbus_tcp_pi_accept[3]
 linkmb:modbus_tcp_pi_accept[3]
-linkmb:modbus_tcp_accept[3]
 linkmb:modbus_tcp_listen[3]
 linkmb:modbus_tcp_listen[3]
 
 
 AUTHORS
 AUTHORS

+ 32 - 18
src/modbus-tcp.c

@@ -553,17 +553,20 @@ int modbus_tcp_pi_listen(modbus_t *ctx, int nb_connection)
     }
     }
 #endif
 #endif
 
 
-    if (ctx_tcp_pi->node[0] == 0)
+    if (ctx_tcp_pi->node[0] == 0) {
         node = NULL; /* == any */
         node = NULL; /* == any */
-    else
+    } else {
         node = ctx_tcp_pi->node;
         node = ctx_tcp_pi->node;
+    }
 
 
-    if (ctx_tcp_pi->service[0] == 0)
+    if (ctx_tcp_pi->service[0] == 0) {
         service = "502";
         service = "502";
-    else
+    } else {
         service = ctx_tcp_pi->service;
         service = ctx_tcp_pi->service;
+    }
 
 
     memset(&ai_hints, 0, sizeof (ai_hints));
     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;
     ai_hints.ai_flags |= AI_PASSIVE;
 #ifdef AI_ADDRCONFIG
 #ifdef AI_ADDRCONFIG
     ai_hints.ai_flags |= 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->backend_data = (modbus_tcp_pi_t *) malloc(sizeof(modbus_tcp_pi_t));
     ctx_tcp_pi = (modbus_tcp_pi_t *)ctx->backend_data;
     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) {
     if (ret_size == 0) {
         fprintf(stderr, "The service string is empty\n");
         fprintf(stderr, "The service string is empty\n");
         modbus_free(ctx);
         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);
     ctx = modbus_new_rtu(NULL, 0, 'A', 0, 0);
     ASSERT_TRUE(ctx == NULL && errno == EINVAL, "");
     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");
     printf("\nALL TESTS PASS WITH SUCCESS.\n");
 
 
 close:
 close: