Commit c7a6ffb357dd0f31e0ab61f4462af2ee84f355db

Authored by Stéphane Raimbault
1 parent fe8d9de6

New slave able to manage many connections on uniprocessor architecture

- new functions modbus_slave_init_listen_tcp, modbus_slave_accept_tcp,
  modbus_slave_slave_receive.
- removed printf in modbus.c: 'Connection closed'
- new slave test, bandwith-slave-many-up
- updated build scripts
- updated MIGRATION document file
MIGRATION
  1 +=============================
  2 +Migration from the 2.0 series
  3 +=============================
  4 +
  5 +modbus_init_listen_tcp() has been renamed to modbus_slave_listen_tcp() and
  6 +requires a new argument, the maximal number of connections:
  7 +
  8 +int modbus_slave_init_tcp(modbus_param_t *mb_param, int nb_connection);
  9 +
  10 +
  11 +New function modbus_slave_accept_tcp() to etablish a new connection (previously
  12 +in modbus_init_listen_tcp()):
  13 +
  14 +int modbus_slave_accept_tcp(modbus_param_t *mb_param, int *socket);
  15 +
  16 +
  17 +modbus_listen() has been renamed to modbus_slave_receive() and requires a new
  18 +argument, the socket file descriptor to listen on. If the sockfd is -1, the
  19 +internal fd of modbus_param_t is used:
  20 +
  21 +int modbus_slave_receive(modbus_param_t *mb_param, int sockfd,
  22 + uint8_t *query, int *query_length);
  23 +
  24 +
1 =================================== 25 ===================================
2 Migration notes from the 1.2 series 26 Migration notes from the 1.2 series
3 =================================== 27 ===================================
modbus/modbus.c
@@ -498,7 +498,7 @@ static int receive_msg(modbus_param_t *mb_param, @@ -498,7 +498,7 @@ static int receive_msg(modbus_param_t *mb_param,
498 tv.tv_usec = TIME_OUT_BEGIN_OF_TRAME; 498 tv.tv_usec = TIME_OUT_BEGIN_OF_TRAME;
499 state = COMPLETE; 499 state = COMPLETE;
500 } 500 }
501 - 501 +
502 length_to_read = msg_length_computed; 502 length_to_read = msg_length_computed;
503 503
504 select_ret = 0; 504 select_ret = 0;
@@ -515,7 +515,6 @@ static int receive_msg(modbus_param_t *mb_param, @@ -515,7 +515,6 @@ static int receive_msg(modbus_param_t *mb_param,
515 read_ret = recv(mb_param->fd, p_msg, length_to_read, 0); 515 read_ret = recv(mb_param->fd, p_msg, length_to_read, 0);
516 516
517 if (read_ret == 0) { 517 if (read_ret == 0) {
518 - printf("Connection closed\n");  
519 return CONNECTION_CLOSED; 518 return CONNECTION_CLOSED;
520 } else if (read_ret < 0) { 519 } else if (read_ret < 0) {
521 /* The only negative possible value is -1 */ 520 /* The only negative possible value is -1 */
@@ -524,7 +523,7 @@ static int receive_msg(modbus_param_t *mb_param, @@ -524,7 +523,7 @@ static int receive_msg(modbus_param_t *mb_param,
524 return PORT_SOCKET_FAILURE; 523 return PORT_SOCKET_FAILURE;
525 } 524 }
526 525
527 - /* Sums bytes received */ 526 + /* Sums bytes received */
528 (*p_msg_length) += read_ret; 527 (*p_msg_length) += read_ret;
529 528
530 /* Display the hex code of each character received */ 529 /* Display the hex code of each character received */
@@ -590,6 +589,28 @@ static int receive_msg(modbus_param_t *mb_param, @@ -590,6 +589,28 @@ static int receive_msg(modbus_param_t *mb_param,
590 return 0; 589 return 0;
591 } 590 }
592 591
  592 +/* Listens for any query from a modbus master in TCP, requires the socket file
  593 + descriptor etablished with the master device in argument or -1 to use the
  594 + internal one of modbus_param_t.
  595 +
  596 + Returns:
  597 + - 0 if OK, or a negative error number if the request fails
  598 + - query, message received
  599 + - query_length, length in bytes of the message */
  600 +int modbus_slave_receive(modbus_param_t *mb_param, int sockfd,
  601 + uint8_t *query, int *query_length)
  602 +{
  603 + int ret;
  604 +
  605 + if (sockfd != -1) {
  606 + mb_param->fd = sockfd;
  607 + }
  608 +
  609 + /* The length of the query to receive isn't known. */
  610 + ret = receive_msg(mb_param, MSG_LENGTH_UNDEFINED, query, query_length);
  611 +
  612 + return ret;
  613 +}
593 614
594 /* Receives the response and checks values (and checksum in RTU). 615 /* Receives the response and checks values (and checksum in RTU).
595 616
@@ -757,6 +778,7 @@ static int response_exception(modbus_param_t *mb_param, sft_t *sft, @@ -757,6 +778,7 @@ static int response_exception(modbus_param_t *mb_param, sft_t *sft,
757 778
758 /* Manages the received query. 779 /* Manages the received query.
759 Analyses the query and constructs a response. 780 Analyses the query and constructs a response.
  781 +
760 If an error occurs, this function construct the response 782 If an error occurs, this function construct the response
761 accordingly. 783 accordingly.
762 */ 784 */
@@ -948,21 +970,6 @@ void modbus_manage_query(modbus_param_t *mb_param, const uint8_t *query, @@ -948,21 +970,6 @@ void modbus_manage_query(modbus_param_t *mb_param, const uint8_t *query,
948 modbus_send(mb_param, response, resp_length); 970 modbus_send(mb_param, response, resp_length);
949 } 971 }
950 972
951 -/* Listens any message on a socket or file descriptor.  
952 - Returns:  
953 - - 0 if OK, or a negative error number if the request fails  
954 - - query, message received  
955 - - query_length, length in bytes of the message */  
956 -int modbus_listen(modbus_param_t *mb_param, uint8_t *query, int *query_length)  
957 -{  
958 - int ret;  
959 -  
960 - /* The length of the query to receive isn't known. */  
961 - ret = receive_msg(mb_param, MSG_LENGTH_UNDEFINED, query, query_length);  
962 -  
963 - return ret;  
964 -}  
965 -  
966 /* Reads IO status */ 973 /* Reads IO status */
967 static int read_io_status(modbus_param_t *mb_param, int slave, int function, 974 static int read_io_status(modbus_param_t *mb_param, int slave, int function,
968 int start_addr, int nb, uint8_t *data_dest) 975 int start_addr, int nb, uint8_t *data_dest)
@@ -1628,10 +1635,6 @@ static int modbus_connect_tcp(modbus_param_t *mb_param) @@ -1628,10 +1635,6 @@ static int modbus_connect_tcp(modbus_param_t *mb_param)
1628 int option; 1635 int option;
1629 struct sockaddr_in addr; 1636 struct sockaddr_in addr;
1630 1637
1631 - addr.sin_family = AF_INET;  
1632 - addr.sin_port = htons(mb_param->port);  
1633 - addr.sin_addr.s_addr = inet_addr(mb_param->ip);  
1634 -  
1635 mb_param->fd = socket(AF_INET, SOCK_STREAM, 0); 1638 mb_param->fd = socket(AF_INET, SOCK_STREAM, 0);
1636 if (mb_param->fd < 0) { 1639 if (mb_param->fd < 0) {
1637 return mb_param->fd; 1640 return mb_param->fd;
@@ -1661,7 +1664,10 @@ static int modbus_connect_tcp(modbus_param_t *mb_param) @@ -1661,7 +1664,10 @@ static int modbus_connect_tcp(modbus_param_t *mb_param)
1661 if (mb_param->debug) { 1664 if (mb_param->debug) {
1662 printf("Connecting to %s\n", mb_param->ip); 1665 printf("Connecting to %s\n", mb_param->ip);
1663 } 1666 }
1664 - 1667 +
  1668 + addr.sin_family = AF_INET;
  1669 + addr.sin_port = htons(mb_param->port);
  1670 + addr.sin_addr.s_addr = inet_addr(mb_param->ip);
1665 ret = connect(mb_param->fd, (struct sockaddr *)&addr, 1671 ret = connect(mb_param->fd, (struct sockaddr *)&addr,
1666 sizeof(struct sockaddr_in)); 1672 sizeof(struct sockaddr_in));
1667 if (ret < 0) { 1673 if (ret < 0) {
@@ -1784,60 +1790,64 @@ void modbus_mapping_free(modbus_mapping_t *mb_mapping) @@ -1784,60 +1790,64 @@ void modbus_mapping_free(modbus_mapping_t *mb_mapping)
1784 free(mb_mapping->tab_input_registers); 1790 free(mb_mapping->tab_input_registers);
1785 } 1791 }
1786 1792
1787 -/* Listens for any query from a modbus master in TCP */  
1788 -int modbus_init_listen_tcp(modbus_param_t *mb_param) 1793 +/* Listens for any query from one or many modbus masters in TCP */
  1794 +int modbus_slave_listen_tcp(modbus_param_t *mb_param, int nb_connection)
1789 { 1795 {
1790 - int ret;  
1791 int new_socket; 1796 int new_socket;
  1797 + int yes;
1792 struct sockaddr_in addr; 1798 struct sockaddr_in addr;
1793 - socklen_t addrlen;  
1794 -  
1795 - addr.sin_family = AF_INET;  
1796 - /* If the modbus port is < to 1024, we need the setuid root. */  
1797 - addr.sin_port = htons(mb_param->port);  
1798 - addr.sin_addr.s_addr = INADDR_ANY;  
1799 - memset(&(addr.sin_zero), '\0', 8);  
1800 1799
1801 new_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 1800 new_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
1802 if (new_socket < 0) { 1801 if (new_socket < 0) {
1803 perror("socket"); 1802 perror("socket");
1804 - exit(1);  
1805 - } else {  
1806 - printf("Socket OK\n"); 1803 + return -1;
1807 } 1804 }
1808 1805
1809 - ret = bind(new_socket, (struct sockaddr *)&addr,  
1810 - sizeof(struct sockaddr_in));  
1811 - if (ret < 0) { 1806 + yes = 1;
  1807 + if (setsockopt(new_socket, SOL_SOCKET, SO_REUSEADDR,
  1808 + (char *) &yes, sizeof(yes)) < 0) {
  1809 + perror("setsockopt");
  1810 + close(new_socket);
  1811 + return -1;
  1812 + }
  1813 +
  1814 + memset(&addr, 0, sizeof(addr));
  1815 + addr.sin_family = AF_INET;
  1816 + /* If the modbus port is < to 1024, we need the setuid root. */
  1817 + addr.sin_port = htons(mb_param->port);
  1818 + addr.sin_addr.s_addr = INADDR_ANY;
  1819 + if (bind(new_socket, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
1812 perror("bind"); 1820 perror("bind");
1813 close(new_socket); 1821 close(new_socket);
1814 - exit(1);  
1815 - } else {  
1816 - printf("Bind OK\n"); 1822 + return -1;
1817 } 1823 }
1818 1824
1819 - ret = listen(new_socket, 1);  
1820 - if (ret != 0) { 1825 + if (listen(new_socket, nb_connection) < 0) {
1821 perror("listen"); 1826 perror("listen");
1822 close(new_socket); 1827 close(new_socket);
1823 - exit(1);  
1824 - } else {  
1825 - printf("Listen OK\n"); 1828 + return -1;
1826 } 1829 }
1827 1830
  1831 + return new_socket;
  1832 +}
  1833 +
  1834 +int modbus_slave_accept_tcp(modbus_param_t *mb_param, int *socket)
  1835 +{
  1836 + struct sockaddr_in addr;
  1837 + socklen_t addrlen;
  1838 +
1828 addrlen = sizeof(struct sockaddr_in); 1839 addrlen = sizeof(struct sockaddr_in);
1829 - mb_param->fd = accept(new_socket, (struct sockaddr *)&addr, &addrlen); 1840 + mb_param->fd = accept(*socket, (struct sockaddr *)&addr, &addrlen);
1830 if (mb_param->fd < 0) { 1841 if (mb_param->fd < 0) {
1831 perror("accept"); 1842 perror("accept");
1832 - close(new_socket);  
1833 - new_socket = 0;  
1834 - exit(1); 1843 + close(*socket);
  1844 + *socket = 0;
1835 } else { 1845 } else {
1836 printf("The client %s is connected\n", 1846 printf("The client %s is connected\n",
1837 inet_ntoa(addr.sin_addr)); 1847 inet_ntoa(addr.sin_addr));
1838 } 1848 }
1839 1849
1840 - return new_socket; 1850 + return mb_param->fd;
1841 } 1851 }
1842 1852
1843 /** Utils **/ 1853 /** Utils **/
modbus/modbus.h
@@ -279,12 +279,25 @@ int modbus_mapping_new(modbus_mapping_t *mb_mapping, @@ -279,12 +279,25 @@ int modbus_mapping_new(modbus_mapping_t *mb_mapping,
279 /* Frees the 4 arrays */ 279 /* Frees the 4 arrays */
280 void modbus_mapping_free(modbus_mapping_t *mb_mapping); 280 void modbus_mapping_free(modbus_mapping_t *mb_mapping);
281 281
282 -/* Initializes the modbus_param_t structure for a TCP slave (server) */  
283 -int modbus_init_listen_tcp(modbus_param_t *mb_param); 282 +/* Listens for any query from one or many modbus masters in TCP.
284 283
285 -/* Listens for any query from a modbus master in TCP  
286 - Not tested in RTU communication. */  
287 -int modbus_listen(modbus_param_t *mb_param, uint8_t *query, int *query_length); 284 + Returns: socket
  285 + */
  286 +int modbus_slave_listen_tcp(modbus_param_t *mb_param, int nb_connection);
  287 +
  288 +/* Waits for a connection */
  289 +int modbus_slave_accept_tcp(modbus_param_t *mb_param, int *socket);
  290 +
  291 +/* Listens for any query from a modbus master in TCP, requires the socket file
  292 + descriptor etablished with the master device in argument.
  293 +
  294 + Returns:
  295 + - 0 if OK, or a negative error number if the request fails
  296 + - query, message received
  297 + - query_length, length in bytes of the message
  298 +*/
  299 +int modbus_slave_receive(modbus_param_t *mb_param, int sockfd,
  300 + uint8_t *query, int *query_length);
288 301
289 /* Manages the received query. 302 /* Manages the received query.
290 Analyses the query and constructs a response. 303 Analyses the query and constructs a response.
tests/Makefile.am
@@ -5,8 +5,9 @@ noinst_PROGRAMS = \ @@ -5,8 +5,9 @@ noinst_PROGRAMS = \
5 random-test-master \ 5 random-test-master \
6 unit-test-slave \ 6 unit-test-slave \
7 unit-test-master \ 7 unit-test-master \
8 - bench-bandwidth-slave \  
9 - bench-bandwidth-master 8 + bandwidth-slave-one \
  9 + bandwidth-slave-many-up \
  10 + bandwidth-master
10 11
11 common_ldflags = \ 12 common_ldflags = \
12 $(top_builddir)/modbus/libmodbus.la 13 $(top_builddir)/modbus/libmodbus.la
@@ -23,11 +24,14 @@ unit_test_slave_LDADD = $(common_ldflags) @@ -23,11 +24,14 @@ unit_test_slave_LDADD = $(common_ldflags)
23 unit_test_master_SOURCES = unit-test-master.c unit-test.h 24 unit_test_master_SOURCES = unit-test-master.c unit-test.h
24 unit_test_master_LDADD = $(common_ldflags) 25 unit_test_master_LDADD = $(common_ldflags)
25 26
26 -bench_bandwidth_slave_SOURCES = bench-bandwidth-slave.c  
27 -bench_bandwidth_slave_LDADD = $(common_ldflags) 27 +bandwidth_slave_one_SOURCES = bandwidth-slave-one.c
  28 +bandwidth_slave_one_LDADD = $(common_ldflags)
28 29
29 -bench_bandwidth_master_SOURCES = bench-bandwidth-master.c  
30 -bench_bandwidth_master_LDADD = $(common_ldflags) 30 +bandwidth_slave_many_up_SOURCES = bandwidth-slave-many-up.c
  31 +bandwidth_slave_many_up_LDADD = $(common_ldflags)
  32 +
  33 +bandwidth_master_SOURCES = bandwidth-master.c
  34 +bandwidth_master_LDADD = $(common_ldflags)
31 35
32 INCLUDES = -I$(top_srcdir) 36 INCLUDES = -I$(top_srcdir)
33 CLEANFILES = *~ 37 CLEANFILES = *~
tests/bench-bandwidth-master.c renamed to tests/bandwidth-master.c
@@ -33,7 +33,7 @@ uint32_t gettime(void) @@ -33,7 +33,7 @@ uint32_t gettime(void)
33 { 33 {
34 struct timeval tv; 34 struct timeval tv;
35 gettimeofday (&tv, NULL); 35 gettimeofday (&tv, NULL);
36 - 36 +
37 return (uint32_t) tv.tv_sec * G_USEC_PER_SEC + tv.tv_usec; 37 return (uint32_t) tv.tv_sec * G_USEC_PER_SEC + tv.tv_usec;
38 } 38 }
39 39
@@ -61,7 +61,7 @@ int main(void) @@ -61,7 +61,7 @@ int main(void)
61 /* Allocate and initialize the memory to store the status */ 61 /* Allocate and initialize the memory to store the status */
62 tab_rp_status = (uint8_t *) malloc(MAX_STATUS * sizeof(uint8_t)); 62 tab_rp_status = (uint8_t *) malloc(MAX_STATUS * sizeof(uint8_t));
63 memset(tab_rp_status, 0, MAX_STATUS * sizeof(uint8_t)); 63 memset(tab_rp_status, 0, MAX_STATUS * sizeof(uint8_t));
64 - 64 +
65 /* Allocate and initialize the memory to store the registers */ 65 /* Allocate and initialize the memory to store the registers */
66 tab_rp_registers = (uint16_t *) malloc(MAX_REGISTERS * sizeof(uint16_t)); 66 tab_rp_registers = (uint16_t *) malloc(MAX_REGISTERS * sizeof(uint16_t));
67 memset(tab_rp_registers, 0, MAX_REGISTERS * sizeof(uint16_t)); 67 memset(tab_rp_registers, 0, MAX_REGISTERS * sizeof(uint16_t));
@@ -78,7 +78,7 @@ int main(void) @@ -78,7 +78,7 @@ int main(void)
78 78
79 rate = (NB_LOOPS * nb_points) * G_USEC_PER_SEC / (end - start); 79 rate = (NB_LOOPS * nb_points) * G_USEC_PER_SEC / (end - start);
80 printf("Transfert rate in points/seconds:\n"); 80 printf("Transfert rate in points/seconds:\n");
81 - printf("* %'d points/s\n", rate); 81 + printf("* %'d points/s\n", rate);
82 printf("\n"); 82 printf("\n");
83 83
84 bytes = NB_LOOPS * (nb_points / 8) + ((nb_points % 8) ? 1 : 0); 84 bytes = NB_LOOPS * (nb_points / 8) + ((nb_points % 8) ? 1 : 0);
@@ -88,7 +88,7 @@ int main(void) @@ -88,7 +88,7 @@ int main(void)
88 printf("* %.3f ms for %d bytes\n", elapsed, bytes); 88 printf("* %.3f ms for %d bytes\n", elapsed, bytes);
89 printf("* %'d KiB/s\n", rate); 89 printf("* %'d KiB/s\n", rate);
90 printf("\n"); 90 printf("\n");
91 - 91 +
92 /* TCP: Query and reponse header and values */ 92 /* TCP: Query and reponse header and values */
93 bytes = 12 + 9 + (nb_points / 8) + ((nb_points % 8) ? 1 : 0); 93 bytes = 12 + 9 + (nb_points / 8) + ((nb_points % 8) ? 1 : 0);
94 printf("Values and TCP Modbus overhead:\n"); 94 printf("Values and TCP Modbus overhead:\n");
@@ -111,7 +111,7 @@ int main(void) @@ -111,7 +111,7 @@ int main(void)
111 111
112 rate = (NB_LOOPS * nb_points) * G_USEC_PER_SEC / (end - start); 112 rate = (NB_LOOPS * nb_points) * G_USEC_PER_SEC / (end - start);
113 printf("Transfert rate in points/seconds:\n"); 113 printf("Transfert rate in points/seconds:\n");
114 - printf("* %'d registers/s\n", rate); 114 + printf("* %'d registers/s\n", rate);
115 printf("\n"); 115 printf("\n");
116 116
117 bytes = NB_LOOPS * nb_points * sizeof(uint16_t); 117 bytes = NB_LOOPS * nb_points * sizeof(uint16_t);
@@ -121,7 +121,7 @@ int main(void) @@ -121,7 +121,7 @@ int main(void)
121 printf("* %.3f ms for %d bytes\n", elapsed, bytes); 121 printf("* %.3f ms for %d bytes\n", elapsed, bytes);
122 printf("* %'d KiB/s\n", rate); 122 printf("* %'d KiB/s\n", rate);
123 printf("\n"); 123 printf("\n");
124 - 124 +
125 /* TCP:Query and reponse header and values */ 125 /* TCP:Query and reponse header and values */
126 bytes = 12 + 9 + (nb_points * sizeof(uint16_t)); 126 bytes = 12 + 9 + (nb_points * sizeof(uint16_t));
127 printf("Values and TCP Modbus overhead:\n"); 127 printf("Values and TCP Modbus overhead:\n");
@@ -133,11 +133,11 @@ int main(void) @@ -133,11 +133,11 @@ int main(void)
133 printf("\n"); 133 printf("\n");
134 134
135 /* Free the memory */ 135 /* Free the memory */
136 - free(tab_rp_status); 136 + free(tab_rp_status);
137 free(tab_rp_registers); 137 free(tab_rp_registers);
138 138
139 /* Close the connection */ 139 /* Close the connection */
140 modbus_close(&mb_param); 140 modbus_close(&mb_param);
141 - 141 +
142 return 0; 142 return 0;
143 } 143 }
tests/bandwidth-slave-many-up.c 0 → 100644
  1 +/*
  2 + * Copyright © 2009 Stéphane Raimbault <stephane.raimbault@gmail.com>
  3 + *
  4 + * This program is free software: you can redistribute it and/or modify
  5 + * it under the terms of the GNU General Public License as published by
  6 + * the Free Software Foundation; either version 3 of the License, or
  7 + * (at your option) any later version.
  8 + *
  9 + * This program is distributed in the hope that it will be useful,
  10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12 + * GNU General Public License for more details.
  13 + *
  14 + * You should have received a copy of the GNU General Public License
  15 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16 + */
  17 +
  18 +#include <stdio.h>
  19 +#include <unistd.h>
  20 +#include <string.h>
  21 +#include <stdlib.h>
  22 +#include <errno.h>
  23 +#include <signal.h>
  24 +
  25 +#include <modbus/modbus.h>
  26 +
  27 +#define NB_CONNECTION 5
  28 +int slave_socket;
  29 +modbus_mapping_t mb_mapping;
  30 +
  31 +static void close_sigint(int dummy)
  32 +{
  33 + shutdown(slave_socket, SHUT_RDWR);
  34 + close(slave_socket);
  35 + modbus_mapping_free(&mb_mapping);
  36 +
  37 + exit(dummy);
  38 +}
  39 +
  40 +int main(void)
  41 +{
  42 + int master_socket;
  43 + modbus_param_t mb_param;
  44 + int ret;
  45 + fd_set refset;
  46 + fd_set rdset;
  47 +
  48 + /* Maximum file descriptor number */
  49 + int fdmax;
  50 +
  51 + modbus_init_tcp(&mb_param, "127.0.0.1", 1502);
  52 +
  53 + ret = modbus_mapping_new(&mb_mapping, MAX_STATUS, 0, MAX_REGISTERS, 0);
  54 + if (ret == FALSE) {
  55 + printf("Memory allocation failure\n");
  56 + exit(1);
  57 + }
  58 +
  59 + slave_socket = modbus_slave_listen_tcp(&mb_param, NB_CONNECTION);
  60 +
  61 + signal(SIGINT, close_sigint);
  62 +
  63 + /* Clear the reference set of socket */
  64 + FD_ZERO(&refset);
  65 + /* Add the slave socket */
  66 + FD_SET(slave_socket, &refset);
  67 +
  68 + /* Keep track of the max file descriptor */
  69 + fdmax = slave_socket;
  70 +
  71 + for (;;) {
  72 + rdset = refset;
  73 + if (select(fdmax+1, &rdset, NULL, NULL, NULL) == -1) {
  74 + perror("Slave select() failure.");
  75 + close_sigint(1);
  76 + }
  77 +
  78 + /* Run through the existing connections looking for data to be
  79 + * read */
  80 + for (master_socket = 0; master_socket <= fdmax; master_socket++) {
  81 +
  82 + if (FD_ISSET(master_socket, &rdset)) {
  83 + if (master_socket == slave_socket) {
  84 + /* A client is asking a new connection */
  85 + socklen_t addrlen;
  86 + struct sockaddr_in clientaddr;
  87 + int newfd;
  88 +
  89 + /* Handle new connections */
  90 + addrlen = sizeof(clientaddr);
  91 + memset(&clientaddr, 0, sizeof(clientaddr));
  92 + newfd = accept(slave_socket, (struct sockaddr *)&clientaddr, &addrlen);
  93 + if (newfd == -1) {
  94 + perror("Server accept() error");
  95 + } else {
  96 + FD_SET(newfd, &refset);
  97 +
  98 + if (newfd > fdmax) {
  99 + /* Keep track of the maximum */
  100 + fdmax = newfd;
  101 + }
  102 + printf("New connection from %s:%d on socket %d\n",
  103 + inet_ntoa(clientaddr.sin_addr), clientaddr.sin_port, newfd);
  104 + }
  105 + } else {
  106 + /* An already connected master has sent a new query */
  107 + uint8_t query[MAX_MESSAGE_LENGTH];
  108 + int query_size;
  109 +
  110 + ret = modbus_slave_receive(&mb_param, master_socket, query, &query_size);
  111 + if (ret == 0) {
  112 + modbus_manage_query(&mb_param, query, query_size, &mb_mapping);
  113 + } else {
  114 + /* Connection closed by the client, end of server */
  115 + printf("Connection closed on socket %d\n", master_socket);
  116 + shutdown(master_socket, SHUT_RDWR);
  117 + close(master_socket);
  118 +
  119 + /* Remove from reference set */
  120 + FD_CLR(master_socket, &refset);
  121 +
  122 + if (master_socket == fdmax) {
  123 + fdmax--;
  124 + }
  125 + }
  126 + }
  127 + }
  128 + }
  129 + }
  130 +
  131 + return 0;
  132 +}
tests/bench-bandwidth-slave.c renamed to tests/bandwidth-slave-one.c
@@ -37,13 +37,14 @@ int main(void) @@ -37,13 +37,14 @@ int main(void)
37 exit(1); 37 exit(1);
38 } 38 }
39 39
40 - socket = modbus_init_listen_tcp(&mb_param);  
41 - 40 + socket = modbus_slave_listen_tcp(&mb_param, 1);
  41 + modbus_slave_accept_tcp(&mb_param, &socket);
  42 +
42 while (1) { 43 while (1) {
43 uint8_t query[MAX_MESSAGE_LENGTH]; 44 uint8_t query[MAX_MESSAGE_LENGTH];
44 int query_size; 45 int query_size;
45 46
46 - ret = modbus_listen(&mb_param, query, &query_size); 47 + ret = modbus_slave_receive(&mb_param, -1, query, &query_size);
47 if (ret == 0) { 48 if (ret == 0) {
48 modbus_manage_query(&mb_param, query, query_size, &mb_mapping); 49 modbus_manage_query(&mb_param, query, query_size, &mb_mapping);
49 } else if (ret == CONNECTION_CLOSED) { 50 } else if (ret == CONNECTION_CLOSED) {
tests/random-test-slave.c
@@ -37,13 +37,14 @@ int main(void) @@ -37,13 +37,14 @@ int main(void)
37 exit(1); 37 exit(1);
38 } 38 }
39 39
40 - socket = modbus_init_listen_tcp(&mb_param);  
41 - 40 + socket = modbus_slave_listen_tcp(&mb_param, 1);
  41 + modbus_slave_accept_tcp(&mb_param, &socket);
  42 +
42 while (1) { 43 while (1) {
43 uint8_t query[MAX_MESSAGE_LENGTH]; 44 uint8_t query[MAX_MESSAGE_LENGTH];
44 int query_size; 45 int query_size;
45 46
46 - ret = modbus_listen(&mb_param, query, &query_size); 47 + ret = modbus_slave_receive(&mb_param, -1, query, &query_size);
47 if (ret == 0) { 48 if (ret == 0) {
48 modbus_manage_query(&mb_param, query, query_size, &mb_mapping); 49 modbus_manage_query(&mb_param, query, query_size, &mb_mapping);
49 } else if (ret == CONNECTION_CLOSED) { 50 } else if (ret == CONNECTION_CLOSED) {
tests/unit-test-slave.c
@@ -59,13 +59,14 @@ int main(void) @@ -59,13 +59,14 @@ int main(void)
59 UT_INPUT_REGISTERS_TAB[i];; 59 UT_INPUT_REGISTERS_TAB[i];;
60 } 60 }
61 61
62 - socket = modbus_init_listen_tcp(&mb_param);  
63 - 62 + socket = modbus_slave_listen_tcp(&mb_param, 1);
  63 + modbus_slave_accept_tcp(&mb_param, &socket);
  64 +
64 while (1) { 65 while (1) {
65 uint8_t query[MAX_MESSAGE_LENGTH]; 66 uint8_t query[MAX_MESSAGE_LENGTH];
66 int query_size; 67 int query_size;
67 68
68 - ret = modbus_listen(&mb_param, query, &query_size); 69 + ret = modbus_slave_receive(&mb_param, -1, query, &query_size);
69 if (ret == 0) { 70 if (ret == 0) {
70 if (((query[HEADER_LENGTH_TCP + 4] << 8) + query[HEADER_LENGTH_TCP + 5]) 71 if (((query[HEADER_LENGTH_TCP + 4] << 8) + query[HEADER_LENGTH_TCP + 5])
71 == UT_HOLDING_REGISTERS_NB_POINTS_SPECIAL) { 72 == UT_HOLDING_REGISTERS_NB_POINTS_SPECIAL) {
tests/wscript
@@ -28,15 +28,22 @@ def build(bld): @@ -28,15 +28,22 @@ def build(bld):
28 obj.inst_var = 0 28 obj.inst_var = 0
29 29
30 obj = bld.create_obj('cc', 'program') 30 obj = bld.create_obj('cc', 'program')
31 - obj.source = 'bench-bandwidth-slave.c' 31 + obj.source = 'bandwidth-slave-one.c'
32 obj.includes = '. ..' 32 obj.includes = '. ..'
33 obj.uselib_local = 'modbus' 33 obj.uselib_local = 'modbus'
34 - obj.target = 'bench-bandwidth-slave' 34 + obj.target = 'bandwidth-slave-one'
35 obj.inst_var = 0 35 obj.inst_var = 0
36 36
37 obj = bld.create_obj('cc', 'program') 37 obj = bld.create_obj('cc', 'program')
38 - obj.source = 'bench-bandwidth-master.c' 38 + obj.source = 'bandwidth-slave-many-up.c'
39 obj.includes = '. ..' 39 obj.includes = '. ..'
40 obj.uselib_local = 'modbus' 40 obj.uselib_local = 'modbus'
41 - obj.target = 'bench-bandwidth-master' 41 + obj.target = 'bandwidth-slave-many-up'
  42 + obj.inst_var = 0
  43 +
  44 + obj = bld.create_obj('cc', 'program')
  45 + obj.source = 'bandwidth-master.c'
  46 + obj.includes = '. ..'
  47 + obj.uselib_local = 'modbus'
  48 + obj.target = 'bandwidth-master'
42 obj.inst_var = 0 49 obj.inst_var = 0