Browse Source

Fixed MODBUS_ERROR_RECOVERY_LINK not working on Windows.

Mohamed Amine Mzoughi 2 years ago
parent
commit
db1cbc5935
1 changed files with 44 additions and 2 deletions
  1. 44 2
      src/modbus.c

+ 44 - 2
src/modbus.c

@@ -182,7 +182,21 @@ static int send_msg(modbus_t *ctx, uint8_t *msg, int msg_length)
         rc = ctx->backend->send(ctx, msg, msg_length);
         if (rc == -1) {
             _error_print(ctx, NULL);
-            if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) {
+            if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK &&
+                ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_TCP) {
+#ifdef _WIN32
+                const int wsa_err = WSAGetLastError();
+                if (wsa_err == WSAENETRESET || wsa_err == WSAENOTCONN || wsa_err == WSAENOTSOCK ||
+                    wsa_err == WSAESHUTDOWN || wsa_err == WSAEHOSTUNREACH || wsa_err == WSAECONNABORTED ||
+                    wsa_err == WSAECONNRESET || wsa_err == WSAETIMEDOUT) {
+                    modbus_close(ctx);
+                    _sleep_response_timeout(ctx);
+                    modbus_connect(ctx);
+                } else {
+                    _sleep_response_timeout(ctx);
+                    modbus_flush(ctx);
+                }
+#else
                 int saved_errno = errno;
 
                 if ((errno == EBADF || errno == ECONNRESET || errno == EPIPE)) {
@@ -194,6 +208,7 @@ static int send_msg(modbus_t *ctx, uint8_t *msg, int msg_length)
                     modbus_flush(ctx);
                 }
                 errno = saved_errno;
+#endif
             }
         }
     } while ((ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) &&
@@ -345,6 +360,9 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type)
     int length_to_read;
     int msg_length = 0;
     _step_t step;
+#ifdef _WIN32
+    int wsa_err;
+#endif
 
     if (ctx->debug) {
         if (msg_type == MSG_INDICATION) {
@@ -386,7 +404,17 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type)
         rc = ctx->backend->select(ctx, &rset, p_tv, length_to_read);
         if (rc == -1) {
             _error_print(ctx, "select");
-            if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) {
+            if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK &&
+                ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_TCP) {
+#ifdef _WIN32
+                wsa_err = WSAGetLastError();
+
+                // no equivalent to ETIMEDOUT when select fails on Windows
+                if (wsa_err == WSAENETDOWN || wsa_err == WSAENOTSOCK) {
+                    modbus_close(ctx);
+                    modbus_connect(ctx);
+                }
+#else
                 int saved_errno = errno;
 
                 if (errno == ETIMEDOUT) {
@@ -397,6 +425,7 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type)
                     modbus_connect(ctx);
                 }
                 errno = saved_errno;
+#endif
             }
             return -1;
         }
@@ -409,7 +438,19 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type)
 
         if (rc == -1) {
             _error_print(ctx, "read");
+#ifdef _WIN32
+            wsa_err = WSAGetLastError();
             if ((ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) &&
+                (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_TCP) &&
+                (wsa_err == WSAENOTCONN || wsa_err == WSAENETRESET || wsa_err == WSAENOTSOCK ||
+                wsa_err == WSAESHUTDOWN || wsa_err == WSAECONNABORTED || wsa_err == WSAETIMEDOUT ||
+                wsa_err == WSAECONNRESET)) {
+                modbus_close(ctx);
+                modbus_connect(ctx);
+            }
+#else
+            if ((ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) &&
+                (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_TCP) &&
                 (errno == ECONNRESET || errno == ECONNREFUSED ||
                  errno == EBADF)) {
                 int saved_errno = errno;
@@ -418,6 +459,7 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type)
                 /* Could be removed by previous calls */
                 errno = saved_errno;
             }
+#endif
             return -1;
         }