Commit 8dc21ddaf51bace2030f5f06b51754eb4de6e87d

Authored by Stéphane Raimbault
1 parent e90f906b

TCP - Socket in non blocking mode by default

Original patch for new connect function by Thomas Stalder.
src/modbus-private.h
@@ -109,7 +109,7 @@ typedef struct _modbus_backend { @@ -109,7 +109,7 @@ typedef struct _modbus_backend {
109 int (*connect) (modbus_t *ctx); 109 int (*connect) (modbus_t *ctx);
110 void (*close) (modbus_t *ctx); 110 void (*close) (modbus_t *ctx);
111 int (*flush) (modbus_t *ctx); 111 int (*flush) (modbus_t *ctx);
112 - int (*select) (modbus_t *ctx, fd_set *rfds, struct timeval *tv, int msg_length); 112 + int (*select) (modbus_t *ctx, fd_set *rset, struct timeval *tv, int msg_length);
113 } modbus_backend_t; 113 } modbus_backend_t;
114 114
115 struct _modbus { 115 struct _modbus {
src/modbus-rtu.c
@@ -945,7 +945,7 @@ int _modbus_rtu_flush(modbus_t *ctx) @@ -945,7 +945,7 @@ int _modbus_rtu_flush(modbus_t *ctx)
945 #endif 945 #endif
946 } 946 }
947 947
948 -int _modbus_rtu_select(modbus_t *ctx, fd_set *rfds, 948 +int _modbus_rtu_select(modbus_t *ctx, fd_set *rset,
949 struct timeval *tv, int length_to_read) 949 struct timeval *tv, int length_to_read)
950 { 950 {
951 int s_rc; 951 int s_rc;
@@ -961,14 +961,14 @@ int _modbus_rtu_select(modbus_t *ctx, fd_set *rfds, @@ -961,14 +961,14 @@ int _modbus_rtu_select(modbus_t *ctx, fd_set *rfds,
961 return -1; 961 return -1;
962 } 962 }
963 #else 963 #else
964 - while ((s_rc = select(ctx->s+1, rfds, NULL, NULL, tv)) == -1) { 964 + while ((s_rc = select(ctx->s+1, rset, NULL, NULL, tv)) == -1) {
965 if (errno == EINTR) { 965 if (errno == EINTR) {
966 if (ctx->debug) { 966 if (ctx->debug) {
967 fprintf(stderr, "A non blocked signal was caught\n"); 967 fprintf(stderr, "A non blocked signal was caught\n");
968 } 968 }
969 /* Necessary after an error */ 969 /* Necessary after an error */
970 - FD_ZERO(rfds);  
971 - FD_SET(ctx->s, rfds); 970 + FD_ZERO(rset);
  971 + FD_SET(ctx->s, rset);
972 } else { 972 } else {
973 return -1; 973 return -1;
974 } 974 }
src/modbus-tcp.c
@@ -238,10 +238,37 @@ static int _modbus_tcp_set_ipv4_options(int s) @@ -238,10 +238,37 @@ static int _modbus_tcp_set_ipv4_options(int s)
238 return 0; 238 return 0;
239 } 239 }
240 240
  241 +static int _connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen,
  242 + struct timeval *tv)
  243 +{
  244 + int rc;
  245 +
  246 + rc = connect(sockfd, addr, addrlen);
  247 + if (rc == -1 && errno == EINPROGRESS) {
  248 + fd_set wset;
  249 + int err;
  250 + socklen_t errlen = sizeof(err);
  251 +
  252 + FD_ZERO(&wset);
  253 + FD_SET(sockfd, &wset);
  254 + rc = select(sockfd + 1, NULL, &wset, NULL, tv);
  255 + if (rc < 0) {
  256 + /* Timeout or fail */
  257 + return -1;
  258 + }
  259 +
  260 + /* The socket is available for writing if it returns 0 */
  261 + return getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen);
  262 + }
  263 + /* 0 or (-1 and errno != EINPROGRESS) */
  264 + return rc;
  265 +}
  266 +
241 /* Establishes a modbus TCP connection with a Modbus server. */ 267 /* Establishes a modbus TCP connection with a Modbus server. */
242 static int _modbus_tcp_connect(modbus_t *ctx) 268 static int _modbus_tcp_connect(modbus_t *ctx)
243 { 269 {
244 int rc; 270 int rc;
  271 + /* Specialized version of sockaddr for Internet socket address (same size) */
245 struct sockaddr_in addr; 272 struct sockaddr_in addr;
246 modbus_tcp_t *ctx_tcp = ctx->backend_data; 273 modbus_tcp_t *ctx_tcp = ctx->backend_data;
247 int flags = SOCK_STREAM; 274 int flags = SOCK_STREAM;
@@ -256,6 +283,10 @@ static int _modbus_tcp_connect(modbus_t *ctx) @@ -256,6 +283,10 @@ static int _modbus_tcp_connect(modbus_t *ctx)
256 flags |= SOCK_CLOEXEC; 283 flags |= SOCK_CLOEXEC;
257 #endif 284 #endif
258 285
  286 +#ifdef SOCK_NONBLOCK
  287 + flags |= SOCK_NONBLOCK;
  288 +#endif
  289 +
259 ctx->s = socket(PF_INET, flags, 0); 290 ctx->s = socket(PF_INET, flags, 0);
260 if (ctx->s == -1) { 291 if (ctx->s == -1) {
261 return -1; 292 return -1;
@@ -274,8 +305,7 @@ static int _modbus_tcp_connect(modbus_t *ctx) @@ -274,8 +305,7 @@ static int _modbus_tcp_connect(modbus_t *ctx)
274 addr.sin_family = AF_INET; 305 addr.sin_family = AF_INET;
275 addr.sin_port = htons(ctx_tcp->port); 306 addr.sin_port = htons(ctx_tcp->port);
276 addr.sin_addr.s_addr = inet_addr(ctx_tcp->ip); 307 addr.sin_addr.s_addr = inet_addr(ctx_tcp->ip);
277 - rc = connect(ctx->s, (struct sockaddr *)&addr,  
278 - sizeof(struct sockaddr_in)); 308 + rc = _connect(ctx->s, (struct sockaddr *)&addr, sizeof(addr), &ctx->response_timeout);
279 if (rc == -1) { 309 if (rc == -1) {
280 close(ctx->s); 310 close(ctx->s);
281 return -1; 311 return -1;
@@ -317,6 +347,10 @@ static int _modbus_tcp_pi_connect(modbus_t *ctx) @@ -317,6 +347,10 @@ static int _modbus_tcp_pi_connect(modbus_t *ctx)
317 flags |= SOCK_CLOEXEC; 347 flags |= SOCK_CLOEXEC;
318 #endif 348 #endif
319 349
  350 +#ifdef SOCK_NONBLOCK
  351 + flags |= SOCK_NONBLOCK;
  352 +#endif
  353 +
320 s = socket(ai_ptr->ai_family, flags, ai_ptr->ai_protocol); 354 s = socket(ai_ptr->ai_family, flags, ai_ptr->ai_protocol);
321 if (s < 0) 355 if (s < 0)
322 continue; 356 continue;
@@ -324,8 +358,8 @@ static int _modbus_tcp_pi_connect(modbus_t *ctx) @@ -324,8 +358,8 @@ static int _modbus_tcp_pi_connect(modbus_t *ctx)
324 if (ai_ptr->ai_family == AF_INET) 358 if (ai_ptr->ai_family == AF_INET)
325 _modbus_tcp_set_ipv4_options(s); 359 _modbus_tcp_set_ipv4_options(s);
326 360
327 - rc = connect(s, ai_ptr->ai_addr, ai_ptr->ai_addrlen);  
328 - if (rc != 0) { 361 + rc = _connect(s, ai_ptr->ai_addr, ai_ptr->ai_addrlen, &ctx->response_timeout);
  362 + if (rc == -1) {
329 close(s); 363 close(s);
330 continue; 364 continue;
331 } 365 }
@@ -362,14 +396,14 @@ int _modbus_tcp_flush(modbus_t *ctx) @@ -362,14 +396,14 @@ int _modbus_tcp_flush(modbus_t *ctx)
362 rc = recv(ctx->s, devnull, MODBUS_TCP_MAX_ADU_LENGTH, MSG_DONTWAIT); 396 rc = recv(ctx->s, devnull, MODBUS_TCP_MAX_ADU_LENGTH, MSG_DONTWAIT);
363 #else 397 #else
364 /* On Win32, it's a bit more complicated to not wait */ 398 /* On Win32, it's a bit more complicated to not wait */
365 - fd_set rfds; 399 + fd_set rset;
366 struct timeval tv; 400 struct timeval tv;
367 401
368 tv.tv_sec = 0; 402 tv.tv_sec = 0;
369 tv.tv_usec = 0; 403 tv.tv_usec = 0;
370 - FD_ZERO(&rfds);  
371 - FD_SET(ctx->s, &rfds);  
372 - rc = select(ctx->s+1, &rfds, NULL, NULL, &tv); 404 + FD_ZERO(&rset);
  405 + FD_SET(ctx->s, &rset);
  406 + rc = select(ctx->s+1, &rset, NULL, NULL, &tv);
373 if (rc == -1) { 407 if (rc == -1) {
374 return -1; 408 return -1;
375 } 409 }
@@ -571,17 +605,17 @@ int modbus_tcp_pi_accept(modbus_t *ctx, int *socket) @@ -571,17 +605,17 @@ int modbus_tcp_pi_accept(modbus_t *ctx, int *socket)
571 return ctx->s; 605 return ctx->s;
572 } 606 }
573 607
574 -int _modbus_tcp_select(modbus_t *ctx, fd_set *rfds, struct timeval *tv, int length_to_read) 608 +int _modbus_tcp_select(modbus_t *ctx, fd_set *rset, struct timeval *tv, int length_to_read)
575 { 609 {
576 int s_rc; 610 int s_rc;
577 - while ((s_rc = select(ctx->s+1, rfds, NULL, NULL, tv)) == -1) { 611 + while ((s_rc = select(ctx->s+1, rset, NULL, NULL, tv)) == -1) {
578 if (errno == EINTR) { 612 if (errno == EINTR) {
579 if (ctx->debug) { 613 if (ctx->debug) {
580 fprintf(stderr, "A non blocked signal was caught\n"); 614 fprintf(stderr, "A non blocked signal was caught\n");
581 } 615 }
582 /* Necessary after an error */ 616 /* Necessary after an error */
583 - FD_ZERO(rfds);  
584 - FD_SET(ctx->s, rfds); 617 + FD_ZERO(rset);
  618 + FD_SET(ctx->s, rset);
585 } else { 619 } else {
586 return -1; 620 return -1;
587 } 621 }
src/modbus.c
@@ -326,7 +326,7 @@ static int compute_data_length_after_meta(modbus_t *ctx, uint8_t *msg, @@ -326,7 +326,7 @@ static int compute_data_length_after_meta(modbus_t *ctx, uint8_t *msg,
326 int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type) 326 int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type)
327 { 327 {
328 int rc; 328 int rc;
329 - fd_set rfds; 329 + fd_set rset;
330 struct timeval tv; 330 struct timeval tv;
331 struct timeval *p_tv; 331 struct timeval *p_tv;
332 int length_to_read; 332 int length_to_read;
@@ -342,8 +342,8 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type) @@ -342,8 +342,8 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type)
342 } 342 }
343 343
344 /* Add a file descriptor to the set */ 344 /* Add a file descriptor to the set */
345 - FD_ZERO(&rfds);  
346 - FD_SET(ctx->s, &rfds); 345 + FD_ZERO(&rset);
  346 + FD_SET(ctx->s, &rset);
347 347
348 /* We need to analyse the message step by step. At the first step, we want 348 /* We need to analyse the message step by step. At the first step, we want
349 * to reach the function code because all packets contain this 349 * to reach the function code because all packets contain this
@@ -362,7 +362,7 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type) @@ -362,7 +362,7 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type)
362 } 362 }
363 363
364 while (length_to_read != 0) { 364 while (length_to_read != 0) {
365 - rc = ctx->backend->select(ctx, &rfds, p_tv, length_to_read); 365 + rc = ctx->backend->select(ctx, &rset, p_tv, length_to_read);
366 if (rc == -1) { 366 if (rc == -1) {
367 _error_print(ctx, "select"); 367 _error_print(ctx, "select");
368 if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) { 368 if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) {