27 #include <sys/types.h> 34 # define WINVER 0x0501 36 # include <ws2tcpip.h> 38 # define close closesocket 40 # include <sys/socket.h> 41 # include <sys/ioctl.h> 43 #if defined(__OpenBSD__) || (defined(__FreeBSD__) && __FreeBSD__ < 5) 45 # include <netinet/in_systm.h> 48 # include <netinet/in.h> 49 # include <netinet/ip.h> 50 # include <netinet/tcp.h> 51 # include <arpa/inet.h> 56 #if !defined(MSG_NOSIGNAL) 57 #define MSG_NOSIGNAL 0 66 static int _modbus_tcp_init_win32(
void)
71 if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
72 fprintf(stderr,
"WSAStartup() returned error code %d\n",
73 (
unsigned int)GetLastError());
84 if (slave >= 0 && slave <= 247) {
109 static uint16_t t_id = 0;
112 if (t_id < UINT16_MAX)
117 req[1] = t_id & 0x00ff;
129 req[9] = addr & 0x00ff;
131 req[11] = nb & 0x00ff;
143 rsp[0] = sft->
t_id >> 8;
144 rsp[1] = sft->
t_id & 0x00ff;
162 return (req[0] << 8) + req[1];
168 int mbap_length = req_length - 6;
170 req[4] = mbap_length >> 8;
171 req[5] = mbap_length & 0x00FF;
182 return send(ctx->
s, (
const char*)req, req_length,
MSG_NOSIGNAL);
186 return recv(ctx->
s, (
char *)rsp, rsp_length, 0);
195 const uint8_t *rsp,
int rsp_length)
198 if (req[0] != rsp[0] || req[1] != rsp[1]) {
200 fprintf(stderr,
"Invalid TID received 0x%X (not 0x%X)\n",
201 (rsp[0] << 8) + rsp[1], (req[0] << 8) + req[1]);
218 rc = setsockopt(s, IPPROTO_TCP, TCP_NODELAY,
219 (
const void *)&option,
sizeof(
int));
230 option = IPTOS_LOWDELAY;
231 rc = setsockopt(s, IPPROTO_IP, IP_TOS,
232 (
const void *)&option,
sizeof(
int));
245 struct sockaddr_in addr;
249 if (_modbus_tcp_init_win32() == -1) {
254 ctx->
s = socket(PF_INET, SOCK_STREAM, 0);
266 printf(
"Connecting to %s\n", ctx_tcp->ip);
269 addr.sin_family = AF_INET;
270 addr.sin_port = htons(ctx_tcp->port);
271 addr.sin_addr.s_addr = inet_addr(ctx_tcp->ip);
272 rc = connect(ctx->
s, (
struct sockaddr *)&addr,
273 sizeof(
struct sockaddr_in));
286 struct addrinfo *ai_list;
287 struct addrinfo *ai_ptr;
288 struct addrinfo ai_hints;
292 if (_modbus_tcp_init_win32() == -1) {
297 memset(&ai_hints, 0,
sizeof(ai_hints));
299 ai_hints.ai_flags |= AI_ADDRCONFIG;
301 ai_hints.ai_family = AF_UNSPEC;
302 ai_hints.ai_socktype = SOCK_STREAM;
303 ai_hints.ai_addr = NULL;
304 ai_hints.ai_canonname = NULL;
305 ai_hints.ai_next = NULL;
308 rc = getaddrinfo(ctx_tcp_pi->node, ctx_tcp_pi->service,
309 &ai_hints, &ai_list);
313 for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) {
316 s = socket(ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol);
320 if (ai_ptr->ai_family == AF_INET)
323 rc = connect(s, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
333 freeaddrinfo(ai_list);
345 shutdown(ctx->
s, SHUT_RDWR);
367 FD_SET(ctx->
s, &rfds);
368 rc = select(ctx->
s+1, &rfds, NULL, NULL, &tv);
391 struct sockaddr_in addr;
395 if (_modbus_tcp_init_win32() == -1) {
400 new_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
401 if (new_socket == -1) {
406 if (setsockopt(new_socket, SOL_SOCKET, SO_REUSEADDR,
407 (
char *) &yes,
sizeof(yes)) == -1) {
412 memset(&addr, 0,
sizeof(addr));
413 addr.sin_family = AF_INET;
415 addr.sin_port = htons(ctx_tcp->port);
416 addr.sin_addr.s_addr = INADDR_ANY;
417 if (bind(new_socket, (
struct sockaddr *)&addr,
sizeof(addr)) == -1) {
422 if (listen(new_socket, nb_connection) == -1) {
433 struct addrinfo *ai_list;
434 struct addrinfo *ai_ptr;
435 struct addrinfo ai_hints;
441 if (ctx_tcp_pi->
node[0] == 0)
444 node = ctx_tcp_pi->
node;
446 if (ctx_tcp_pi->
service[0] == 0)
451 memset(&ai_hints, 0,
sizeof (ai_hints));
452 ai_hints.ai_flags |= AI_PASSIVE;
454 ai_hints.ai_flags |= AI_ADDRCONFIG;
456 ai_hints.ai_family = AF_UNSPEC;
457 ai_hints.ai_socktype = SOCK_STREAM;
458 ai_hints.ai_addr = NULL;
459 ai_hints.ai_canonname = NULL;
460 ai_hints.ai_next = NULL;
463 rc = getaddrinfo(node, service, &ai_hints, &ai_list);
468 for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) {
471 s = socket(ai_ptr->ai_family, ai_ptr->ai_socktype,
472 ai_ptr->ai_protocol);
480 rc = setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
481 (
void *) &yes,
sizeof (yes));
485 perror(
"setsockopt");
491 rc = bind(s, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
500 rc = listen(s, nb_connection);
512 freeaddrinfo(ai_list);
514 if (new_socket < 0) {
526 struct sockaddr_in addr;
529 addrlen =
sizeof(addr);
530 ctx->
s = accept(*socket, (
struct sockaddr *)&addr, &addrlen);
538 printf(
"The client connection from %s is accepted\n",
539 inet_ntoa(addr.sin_addr));
547 struct sockaddr_storage addr;
550 addrlen =
sizeof(addr);
551 ctx->
s = accept(*socket, (
void *)&addr, &addrlen);
558 printf(
"The client connection is accepted.\n");
567 while ((s_rc = select(ctx->
s+1, rfds, NULL, NULL, tv)) == -1) {
568 if (errno == EINTR) {
570 fprintf(stderr,
"A non blocked signal was caught\n");
574 FD_SET(ctx->
s, rfds);
648 sa.sa_handler = SIG_IGN;
649 if (sigaction(SIGPIPE, &sa, NULL) < 0) {
651 fprintf(stderr,
"Coud not install SIGPIPE handler.\n");
667 dest_size =
sizeof(
char) * 16;
668 ret_size =
strlcpy(ctx_tcp->
ip, ip, dest_size);
670 fprintf(stderr,
"The IP string is empty\n");
676 if (ret_size >= dest_size) {
677 fprintf(stderr,
"The IP string has been truncated\n");
683 ctx_tcp->
port = port;
708 ret_size =
strlcpy(ctx_tcp_pi->
node, node, dest_size);
710 fprintf(stderr,
"The node string is empty\n");
716 if (ret_size >= dest_size) {
717 fprintf(stderr,
"The node string has been truncated\n");
726 fprintf(stderr,
"The service string is empty\n");
732 if (ret_size >= dest_size) {
733 fprintf(stderr,
"The service string has been truncated\n");
modbus_t * modbus_new_tcp_pi(const char *node, const char *service)
int _modbus_tcp_build_response_basis(sft_t *sft, uint8_t *rsp)
int _modbus_tcp_prepare_response_tid(const uint8_t *req, int *req_length)
static int _modbus_tcp_set_ipv4_options(int s)
int modbus_tcp_pi_accept(modbus_t *ctx, int *socket)
size_t strlcpy(char *dest, const char *src, size_t dest_size)
#define MODBUS_TCP_MAX_ADU_LENGTH
void modbus_free(modbus_t *ctx)
const modbus_backend_t * backend
ssize_t _modbus_tcp_recv(modbus_t *ctx, uint8_t *rsp, int rsp_length)
int _modbus_tcp_check_integrity(modbus_t *ctx, uint8_t *msg, const int msg_length)
int modbus_tcp_listen(modbus_t *ctx, int nb_connection)
modbus_t * modbus_new_tcp(const char *ip, int port)
int _modbus_tcp_flush(modbus_t *ctx)
int _modbus_tcp_send_msg_pre(uint8_t *req, int req_length)
#define _MODBUS_TCP_PI_NODE_LENGTH
#define _MODBUS_TCP_PI_SERVICE_LENGTH
int modbus_tcp_accept(modbus_t *ctx, int *socket)
void _modbus_init_common(modbus_t *ctx)
static int _modbus_tcp_pi_connect(modbus_t *ctx)
static int _modbus_set_slave(modbus_t *ctx, int slave)
int _modbus_tcp_pre_check_confirmation(modbus_t *ctx, const uint8_t *req, const uint8_t *rsp, int rsp_length)
char node[_MODBUS_TCP_PI_NODE_LENGTH]
int _modbus_tcp_filter_request(modbus_t *ctx, int slave)
#define _MODBUS_TCP_HEADER_LENGTH
ssize_t _modbus_tcp_send(modbus_t *ctx, const uint8_t *req, int req_length)
int modbus_tcp_pi_listen(modbus_t *ctx, int nb_connection)
#define _MODBUS_TCP_PRESET_RSP_LENGTH
#define _MODBUS_TCP_PRESET_REQ_LENGTH
static int _modbus_tcp_connect(modbus_t *ctx)
#define _MODBUS_TCP_CHECKSUM_LENGTH
char service[_MODBUS_TCP_PI_SERVICE_LENGTH]
void _modbus_tcp_close(modbus_t *ctx)
const modbus_backend_t _modbus_tcp_pi_backend
const modbus_backend_t _modbus_tcp_backend
int _modbus_tcp_select(modbus_t *ctx, fd_set *rfds, struct timeval *tv, int length_to_read)
int _modbus_tcp_build_request_basis(modbus_t *ctx, int function, int addr, int nb, uint8_t *req)