15 #include <sys/types.h> 22 # define WINVER 0x0501 25 # include <winsock2.h> 26 # include <ws2tcpip.h> 28 # define close closesocket 30 # include <sys/socket.h> 31 # include <sys/ioctl.h> 33 #if defined(__OpenBSD__) || (defined(__FreeBSD__) && __FreeBSD__ < 5) 35 # include <netinet/in_systm.h> 38 # include <netinet/in.h> 39 # include <netinet/ip.h> 40 # include <netinet/tcp.h> 41 # include <arpa/inet.h> 45 #if !defined(MSG_NOSIGNAL) 46 #define MSG_NOSIGNAL 0 49 #if defined(_AIX) && !defined(MSG_DONTWAIT) 50 #define MSG_DONTWAIT MSG_NONBLOCK 59 static int _modbus_tcp_init_win32(
void)
64 if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
65 fprintf(stderr,
"WSAStartup() returned error code %d\n",
66 (
unsigned int)GetLastError());
74 static int _modbus_set_slave(
modbus_t *ctx,
int slave)
77 if (slave >= 0 && slave <= 247) {
92 static int _modbus_tcp_build_request_basis(
modbus_t *ctx,
int function,
99 if (ctx_tcp->
t_id < UINT16_MAX)
103 req[0] = ctx_tcp->
t_id >> 8;
104 req[1] = ctx_tcp->
t_id & 0x00ff;
116 req[9] = addr & 0x00ff;
118 req[11] = nb & 0x00ff;
124 static int _modbus_tcp_build_response_basis(
sft_t *sft, uint8_t *rsp)
130 rsp[0] = sft->
t_id >> 8;
131 rsp[1] = sft->
t_id & 0x00ff;
147 static int _modbus_tcp_prepare_response_tid(
const uint8_t *req,
int *req_length)
149 return (req[0] << 8) + req[1];
152 static int _modbus_tcp_send_msg_pre(uint8_t *req,
int req_length)
155 int mbap_length = req_length - 6;
157 req[4] = mbap_length >> 8;
158 req[5] = mbap_length & 0x00FF;
163 static ssize_t _modbus_tcp_send(
modbus_t *ctx,
const uint8_t *req,
int req_length)
169 return send(ctx->
s, (
const char *)req, req_length,
MSG_NOSIGNAL);
172 static int _modbus_tcp_receive(
modbus_t *ctx, uint8_t *req) {
176 static ssize_t _modbus_tcp_recv(
modbus_t *ctx, uint8_t *rsp,
int rsp_length) {
177 return recv(ctx->
s, (
char *)rsp, rsp_length, 0);
180 static int _modbus_tcp_check_integrity(
modbus_t *ctx, uint8_t *msg,
const int msg_length)
185 static int _modbus_tcp_pre_check_confirmation(
modbus_t *ctx,
const uint8_t *req,
186 const uint8_t *rsp,
int rsp_length)
189 if (req[0] != rsp[0] || req[1] != rsp[1]) {
191 fprintf(stderr,
"Invalid transaction ID received 0x%X (not 0x%X)\n",
192 (rsp[0] << 8) + rsp[1], (req[0] << 8) + req[1]);
199 if (rsp[2] != 0x0 && rsp[3] != 0x0) {
201 fprintf(stderr,
"Invalid protocol ID received 0x%X (not 0x0)\n",
202 (rsp[2] << 8) + rsp[3]);
211 static int _modbus_tcp_set_ipv4_options(
int s)
219 rc = setsockopt(s, IPPROTO_TCP, TCP_NODELAY,
220 (
const void *)&option,
sizeof(
int));
228 #if !defined(SOCK_NONBLOCK) && defined(FIONBIO) 233 ioctlsocket(s, FIONBIO, &loption);
237 ioctl(s, FIONBIO, &option);
247 option = IPTOS_LOWDELAY;
248 rc = setsockopt(s, IPPROTO_IP, IP_TOS,
249 (
const void *)&option,
sizeof(
int));
258 static int _connect(
int sockfd,
const struct sockaddr *addr, socklen_t addrlen,
259 const struct timeval *ro_tv)
261 int rc = connect(sockfd, addr, addrlen);
266 wsaError = WSAGetLastError();
269 if (wsaError == WSAEWOULDBLOCK || wsaError == WSAEINPROGRESS) {
271 if (rc == -1 && errno == EINPROGRESS) {
275 socklen_t optlen =
sizeof(optval);
276 struct timeval tv = *ro_tv;
280 FD_SET(sockfd, &wset);
281 rc = select(sockfd + 1, NULL, &wset, NULL, &tv);
288 rc = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (
void *)&optval, &optlen);
289 if (rc == 0 && optval == 0) {
292 errno = ECONNREFUSED;
300 static int _modbus_tcp_connect(
modbus_t *ctx)
304 struct sockaddr_in addr;
306 int flags = SOCK_STREAM;
309 if (_modbus_tcp_init_win32() == -1) {
315 flags |= SOCK_CLOEXEC;
319 flags |= SOCK_NONBLOCK;
322 ctx->
s = socket(PF_INET, flags, 0);
327 rc = _modbus_tcp_set_ipv4_options(ctx->
s);
335 printf(
"Connecting to %s:%d\n", ctx_tcp->ip, ctx_tcp->port);
338 addr.sin_family = AF_INET;
339 addr.sin_port = htons(ctx_tcp->port);
340 addr.sin_addr.s_addr = inet_addr(ctx_tcp->ip);
341 rc = _connect(ctx->
s, (
struct sockaddr *)&addr,
sizeof(addr), &ctx->
response_timeout);
352 static int _modbus_tcp_pi_connect(
modbus_t *ctx)
355 struct addrinfo *ai_list;
356 struct addrinfo *ai_ptr;
357 struct addrinfo ai_hints;
361 if (_modbus_tcp_init_win32() == -1) {
366 memset(&ai_hints, 0,
sizeof(ai_hints));
368 ai_hints.ai_flags |= AI_ADDRCONFIG;
370 ai_hints.ai_family = AF_UNSPEC;
371 ai_hints.ai_socktype = SOCK_STREAM;
372 ai_hints.ai_addr = NULL;
373 ai_hints.ai_canonname = NULL;
374 ai_hints.ai_next = NULL;
377 rc = getaddrinfo(ctx_tcp_pi->node, ctx_tcp_pi->service,
378 &ai_hints, &ai_list);
381 fprintf(stderr,
"Error returned by getaddrinfo: %s\n", gai_strerror(rc));
383 errno = ECONNREFUSED;
387 for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) {
388 int flags = ai_ptr->ai_socktype;
392 flags |= SOCK_CLOEXEC;
396 flags |= SOCK_NONBLOCK;
399 s = socket(ai_ptr->ai_family, flags, ai_ptr->ai_protocol);
403 if (ai_ptr->ai_family == AF_INET)
404 _modbus_tcp_set_ipv4_options(s);
407 printf(
"Connecting to [%s]:%s\n", ctx_tcp_pi->node, ctx_tcp_pi->service);
410 rc = _connect(s, ai_ptr->ai_addr, ai_ptr->ai_addrlen, &ctx->
response_timeout);
420 freeaddrinfo(ai_list);
430 static void _modbus_tcp_close(
modbus_t *ctx)
433 shutdown(ctx->
s, SHUT_RDWR);
439 static int _modbus_tcp_flush(
modbus_t *ctx)
457 FD_SET(ctx->
s, &rset);
458 rc = select(ctx->
s+1, &rset, NULL, NULL, &tv);
481 struct sockaddr_in addr;
492 if (_modbus_tcp_init_win32() == -1) {
497 new_s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
503 if (setsockopt(new_s, SOL_SOCKET, SO_REUSEADDR,
504 (
char *)&enable,
sizeof(enable)) == -1) {
509 memset(&addr, 0,
sizeof(addr));
510 addr.sin_family = AF_INET;
512 addr.sin_port = htons(ctx_tcp->port);
513 if (ctx_tcp->ip[0] ==
'0') {
515 addr.sin_addr.s_addr = htonl(INADDR_ANY);
518 addr.sin_addr.s_addr = inet_addr(ctx_tcp->ip);
520 if (bind(new_s, (
struct sockaddr *)&addr,
sizeof(addr)) == -1) {
525 if (listen(new_s, nb_connection) == -1) {
536 struct addrinfo *ai_list;
537 struct addrinfo *ai_ptr;
538 struct addrinfo ai_hints;
552 if (_modbus_tcp_init_win32() == -1) {
557 if (ctx_tcp_pi->
node[0] == 0) {
560 node = ctx_tcp_pi->
node;
563 if (ctx_tcp_pi->
service[0] == 0) {
569 memset(&ai_hints, 0,
sizeof (ai_hints));
571 ai_hints.ai_flags |= AI_PASSIVE;
573 ai_hints.ai_flags |= AI_ADDRCONFIG;
575 ai_hints.ai_family = AF_UNSPEC;
576 ai_hints.ai_socktype = SOCK_STREAM;
577 ai_hints.ai_addr = NULL;
578 ai_hints.ai_canonname = NULL;
579 ai_hints.ai_next = NULL;
582 rc = getaddrinfo(node, service, &ai_hints, &ai_list);
585 fprintf(stderr,
"Error returned by getaddrinfo: %s\n", gai_strerror(rc));
587 errno = ECONNREFUSED;
592 for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) {
595 s = socket(ai_ptr->ai_family, ai_ptr->ai_socktype,
596 ai_ptr->ai_protocol);
604 rc = setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
605 (
void *)&enable,
sizeof (enable));
609 perror(
"setsockopt");
615 rc = bind(s, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
624 rc = listen(s, nb_connection);
636 freeaddrinfo(ai_list);
647 struct sockaddr_in addr;
655 addrlen =
sizeof(addr);
658 ctx->
s = accept4(*s, (
struct sockaddr *)&addr, &addrlen, SOCK_CLOEXEC);
660 ctx->
s = accept(*s, (
struct sockaddr *)&addr, &addrlen);
670 printf(
"The client connection from %s is accepted\n",
671 inet_ntoa(addr.sin_addr));
679 struct sockaddr_storage addr;
687 addrlen =
sizeof(addr);
690 ctx->
s = accept4(*s, (
struct sockaddr *)&addr, &addrlen, SOCK_CLOEXEC);
692 ctx->
s = accept(*s, (
struct sockaddr *)&addr, &addrlen);
700 printf(
"The client connection is accepted.\n");
706 static int _modbus_tcp_select(
modbus_t *ctx, fd_set *rset,
struct timeval *tv,
int length_to_read)
709 while ((s_rc = select(ctx->
s+1, rset, NULL, NULL, tv)) == -1) {
710 if (errno == EINTR) {
712 fprintf(stderr,
"A non blocked signal was caught\n");
716 FD_SET(ctx->
s, rset);
730 static void _modbus_tcp_free(
modbus_t *ctx) {
741 _modbus_tcp_build_request_basis,
742 _modbus_tcp_build_response_basis,
743 _modbus_tcp_prepare_response_tid,
744 _modbus_tcp_send_msg_pre,
748 _modbus_tcp_check_integrity,
749 _modbus_tcp_pre_check_confirmation,
764 _modbus_tcp_build_request_basis,
765 _modbus_tcp_build_response_basis,
766 _modbus_tcp_prepare_response_tid,
767 _modbus_tcp_send_msg_pre,
771 _modbus_tcp_check_integrity,
772 _modbus_tcp_pre_check_confirmation,
773 _modbus_tcp_pi_connect,
792 sa.sa_handler = SIG_IGN;
793 if (sigaction(SIGPIPE, &sa, NULL) < 0) {
795 fprintf(stderr,
"Coud not install SIGPIPE handler.\n");
812 dest_size =
sizeof(char) * 16;
813 ret_size =
strlcpy(ctx_tcp->
ip, ip, dest_size);
815 fprintf(stderr,
"The IP string is empty\n");
821 if (ret_size >= dest_size) {
822 fprintf(stderr,
"The IP string has been truncated\n");
828 ctx_tcp->
ip[0] =
'0';
830 ctx_tcp->
port = port;
857 ctx_tcp_pi->
node[0] = 0;
860 ret_size =
strlcpy(ctx_tcp_pi->
node, node, dest_size);
862 fprintf(stderr,
"The node string is empty\n");
868 if (ret_size >= dest_size) {
869 fprintf(stderr,
"The node string has been truncated\n");
876 if (service != NULL) {
885 fprintf(stderr,
"The service string is empty\n");
891 if (ret_size >= dest_size) {
892 fprintf(stderr,
"The service string has been truncated\n");
898 ctx_tcp_pi->
t_id = 0;
modbus_t * modbus_new_tcp_pi(const char *node, const char *service)
size_t strlcpy(char *dest, const char *src, size_t dest_size)
#define MODBUS_TCP_MAX_ADU_LENGTH
const modbus_backend_t * backend
int modbus_tcp_listen(modbus_t *ctx, int nb_connection)
modbus_t * modbus_new_tcp(const char *ip, int port)
int modbus_tcp_accept(modbus_t *ctx, int *s)
#define _MODBUS_TCP_PI_NODE_LENGTH
#define _MODBUS_TCP_PI_SERVICE_LENGTH
void _modbus_init_common(modbus_t *ctx)
char node[_MODBUS_TCP_PI_NODE_LENGTH]
int modbus_tcp_pi_accept(modbus_t *ctx, int *s)
int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type)
#define _MODBUS_TCP_HEADER_LENGTH
int modbus_tcp_pi_listen(modbus_t *ctx, int nb_connection)
#define _MODBUS_TCP_PRESET_RSP_LENGTH
#define _MODBUS_TCP_PRESET_REQ_LENGTH
#define _MODBUS_TCP_CHECKSUM_LENGTH
char service[_MODBUS_TCP_PI_SERVICE_LENGTH]
void modbus_free(modbus_t *ctx)
const modbus_backend_t _modbus_tcp_pi_backend
const modbus_backend_t _modbus_tcp_backend
struct timeval response_timeout