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 109 int (*connect) (modbus_t *ctx);
110 110 void (*close) (modbus_t *ctx);
111 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 113 } modbus_backend_t;
114 114  
115 115 struct _modbus {
... ...
src/modbus-rtu.c
... ... @@ -945,7 +945,7 @@ int _modbus_rtu_flush(modbus_t *ctx)
945 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 949 struct timeval *tv, int length_to_read)
950 950 {
951 951 int s_rc;
... ... @@ -961,14 +961,14 @@ int _modbus_rtu_select(modbus_t *ctx, fd_set *rfds,
961 961 return -1;
962 962 }
963 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 965 if (errno == EINTR) {
966 966 if (ctx->debug) {
967 967 fprintf(stderr, "A non blocked signal was caught\n");
968 968 }
969 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 972 } else {
973 973 return -1;
974 974 }
... ...
src/modbus-tcp.c
... ... @@ -238,10 +238,37 @@ static int _modbus_tcp_set_ipv4_options(int s)
238 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 267 /* Establishes a modbus TCP connection with a Modbus server. */
242 268 static int _modbus_tcp_connect(modbus_t *ctx)
243 269 {
244 270 int rc;
  271 + /* Specialized version of sockaddr for Internet socket address (same size) */
245 272 struct sockaddr_in addr;
246 273 modbus_tcp_t *ctx_tcp = ctx->backend_data;
247 274 int flags = SOCK_STREAM;
... ... @@ -256,6 +283,10 @@ static int _modbus_tcp_connect(modbus_t *ctx)
256 283 flags |= SOCK_CLOEXEC;
257 284 #endif
258 285  
  286 +#ifdef SOCK_NONBLOCK
  287 + flags |= SOCK_NONBLOCK;
  288 +#endif
  289 +
259 290 ctx->s = socket(PF_INET, flags, 0);
260 291 if (ctx->s == -1) {
261 292 return -1;
... ... @@ -274,8 +305,7 @@ static int _modbus_tcp_connect(modbus_t *ctx)
274 305 addr.sin_family = AF_INET;
275 306 addr.sin_port = htons(ctx_tcp->port);
276 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 309 if (rc == -1) {
280 310 close(ctx->s);
281 311 return -1;
... ... @@ -317,6 +347,10 @@ static int _modbus_tcp_pi_connect(modbus_t *ctx)
317 347 flags |= SOCK_CLOEXEC;
318 348 #endif
319 349  
  350 +#ifdef SOCK_NONBLOCK
  351 + flags |= SOCK_NONBLOCK;
  352 +#endif
  353 +
320 354 s = socket(ai_ptr->ai_family, flags, ai_ptr->ai_protocol);
321 355 if (s < 0)
322 356 continue;
... ... @@ -324,8 +358,8 @@ static int _modbus_tcp_pi_connect(modbus_t *ctx)
324 358 if (ai_ptr->ai_family == AF_INET)
325 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 363 close(s);
330 364 continue;
331 365 }
... ... @@ -362,14 +396,14 @@ int _modbus_tcp_flush(modbus_t *ctx)
362 396 rc = recv(ctx->s, devnull, MODBUS_TCP_MAX_ADU_LENGTH, MSG_DONTWAIT);
363 397 #else
364 398 /* On Win32, it's a bit more complicated to not wait */
365   - fd_set rfds;
  399 + fd_set rset;
366 400 struct timeval tv;
367 401  
368 402 tv.tv_sec = 0;
369 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 407 if (rc == -1) {
374 408 return -1;
375 409 }
... ... @@ -571,17 +605,17 @@ int modbus_tcp_pi_accept(modbus_t *ctx, int *socket)
571 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 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 612 if (errno == EINTR) {
579 613 if (ctx->debug) {
580 614 fprintf(stderr, "A non blocked signal was caught\n");
581 615 }
582 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 619 } else {
586 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 326 int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type)
327 327 {
328 328 int rc;
329   - fd_set rfds;
  329 + fd_set rset;
330 330 struct timeval tv;
331 331 struct timeval *p_tv;
332 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 342 }
343 343  
344 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 348 /* We need to analyse the message step by step. At the first step, we want
349 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 362 }
363 363  
364 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 366 if (rc == -1) {
367 367 _error_print(ctx, "select");
368 368 if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) {
... ...