@@ -23,9 +23,15 @@ namespace TCP {
2323
2424static constexpr int MAX_REGS = 0x10000 ;
2525
26- Client::Client (const std::string &ip, unsigned short port, modbus_mapping_t *mapping, std::size_t tcp_timeout) {
26+ Client::Client (const std::string &host,
27+ const std::string &service,
28+ modbus_mapping_t *mapping,
29+ std::size_t tcp_timeout) {
30+ const char *host_str = " ::" ;
31+ if (!(host.empty () || host == " any" )) host_str = host.c_str ();
32+
2733 // create modbus object
28- modbus = modbus_new_tcp (ip .c_str (), static_cast < int >(port ));
34+ modbus = modbus_new_tcp_pi (host_str, service .c_str ());
2935 if (modbus == nullptr ) {
3036 const std::string error_msg = modbus_strerror (errno);
3137 throw std::runtime_error (" failed to create modbus instance: " + error_msg);
@@ -62,9 +68,15 @@ Client::Client(const std::string &ip, unsigned short port, modbus_mapping_t *map
6268#endif
6369}
6470
65- Client::Client (const std::string &ip, unsigned short port, modbus_mapping_t **mappings, std::size_t tcp_timeout) {
71+ Client::Client (const std::string &host,
72+ const std::string &service,
73+ modbus_mapping_t **mappings,
74+ std::size_t tcp_timeout) {
75+ const char *host_str = " ::" ;
76+ if (!(host.empty () || host == " any" )) host_str = host.c_str ();
77+
6678 // create modbus object
67- modbus = modbus_new_tcp (ip .c_str (), static_cast < int >(port ));
79+ modbus = modbus_new_tcp_pi (host_str, service .c_str ());
6880 if (modbus == nullptr ) {
6981 const std::string error_msg = modbus_strerror (errno);
7082 throw std::runtime_error (" failed to create modbus instance: " + error_msg);
@@ -100,10 +112,14 @@ Client::Client(const std::string &ip, unsigned short port, modbus_mapping_t **ma
100112
101113void Client::listen () {
102114 // create tcp socket
103- socket = modbus_tcp_listen (modbus, 1 );
115+ socket = modbus_tcp_pi_listen (modbus, 1 );
104116 if (socket == -1 ) {
105- const std::string error_msg = modbus_strerror (errno);
106- throw std::runtime_error (" failed to create tcp socket: " + error_msg);
117+ if (errno == ECONNREFUSED) {
118+ throw std::runtime_error (" failed to create tcp socket: unknown or invalid service" );
119+ } else {
120+ const std::string error_msg = modbus_strerror (errno);
121+ throw std::runtime_error (" failed to create tcp socket: " + error_msg);
122+ }
107123 }
108124
109125 // set socket options
@@ -147,7 +163,6 @@ void Client::set_tcp_timeout(std::size_t tcp_timeout) {
147163}
148164#endif
149165
150-
151166Client::~Client () {
152167 if (modbus != nullptr ) {
153168 modbus_close (modbus);
@@ -164,27 +179,68 @@ void Client::set_debug(bool debug) {
164179 }
165180}
166181
182+ /* *
183+ * @brief convert socket address to string
184+ * @param sa socket address
185+ * @return sa as string
186+ */
187+ static std::string sockaddr_to_str (const sockaddr_storage &sa) {
188+ char buffer[INET6_ADDRSTRLEN + 1 ];
189+ if (sa.ss_family == AF_INET) {
190+ auto peer_in = reinterpret_cast <const struct sockaddr_in *>(&sa);
191+ inet_ntop (sa.ss_family , &peer_in->sin_addr , buffer, sizeof (buffer));
192+ std::ostringstream sstr;
193+ return buffer;
194+ } else if (sa.ss_family == AF_INET6) {
195+ auto peer_in6 = reinterpret_cast <const struct sockaddr_in6 *>(&sa);
196+ inet_ntop (sa.ss_family , &peer_in6->sin6_addr , buffer, sizeof (buffer));
197+ std::ostringstream sstr;
198+ sstr << ' [' << buffer << ' ]' ;
199+ return sstr.str ();
200+ } else {
201+ return " UNKNOWN" ;
202+ }
203+ }
204+
205+ std::string Client::get_listen_addr () {
206+ struct sockaddr_storage sock_addr;
207+ socklen_t len = sizeof (sock_addr);
208+ int tmp = getsockname (socket, reinterpret_cast <struct sockaddr *>(&sock_addr), &len);
209+
210+ if (tmp < 0 ) {
211+ const std::string error_msg = modbus_strerror (errno);
212+ throw std::runtime_error (" getsockname failed: " + error_msg);
213+ }
214+
215+ std::ostringstream sstr;
216+ sstr << sockaddr_to_str (sock_addr);
217+ // the port entries have the same offset and size in sockaddr_in and sockaddr_in6
218+ sstr << ' :' << htons (reinterpret_cast <const struct sockaddr_in *>(&sock_addr)->sin_port );
219+
220+ return sstr.str ();
221+ }
222+
167223std::string Client::connect_client () {
168- int tmp = modbus_tcp_accept (modbus, &socket);
224+ int tmp = modbus_tcp_pi_accept (modbus, &socket);
169225 if (tmp < 0 ) {
170226 const std::string error_msg = modbus_strerror (errno);
171227 throw std::runtime_error (" modbus_tcp_accept failed: " + error_msg);
172228 }
173229
174- struct sockaddr_in peer_addr;
175- socklen_t len = sizeof (peer_addr);
230+ struct sockaddr_storage peer_addr;
231+ socklen_t len = sizeof (peer_addr);
176232 tmp = getpeername (modbus_get_socket (modbus), reinterpret_cast <struct sockaddr *>(&peer_addr), &len);
177233
178234 if (tmp < 0 ) {
179235 const std::string error_msg = modbus_strerror (errno);
180236 throw std::runtime_error (" getpeername failed: " + error_msg);
181237 }
182238
183- char buffer[INET_ADDRSTRLEN];
184- inet_ntop (peer_addr.sin_family , &peer_addr.sin_addr , buffer, sizeof (buffer));
185-
186239 std::ostringstream sstr;
187- sstr << buffer << ' :' << htons (peer_addr.sin_port );
240+
241+ sstr << sockaddr_to_str (peer_addr);
242+ // the port entries have the same offset and size in sockaddr_in and sockaddr_in6
243+ sstr << ' :' << htons (reinterpret_cast <const struct sockaddr_in *>(&peer_addr)->sin_port );
188244
189245 return sstr.str ();
190246}
0 commit comments