Commit 31577bbb41064a111be9b84bed79df36f3fe3443

Authored by Tobias Doerffel
Committed by Stéphane Raimbault
1 parent 2f0b8355

Introduced select() operation for backends

Introduced the select() operation for backends as the WAIT_DATA macro
approach is not very extensible and causes trouble when adding platform-
specific codepaths.

Signed-off-by: Stéphane Raimbault <stephane.raimbault@gmail.com>
src/modbus-private.h
@@ -85,6 +85,7 @@ typedef struct _modbus_backend { @@ -85,6 +85,7 @@ typedef struct _modbus_backend {
85 int (*flush) (modbus_t *ctx); 85 int (*flush) (modbus_t *ctx);
86 int (*listen) (modbus_t *ctx, int nb_connection); 86 int (*listen) (modbus_t *ctx, int nb_connection);
87 int (*accept) (modbus_t *ctx, int *socket); 87 int (*accept) (modbus_t *ctx, int *socket);
  88 + int (*select) (modbus_t *ctx, fd_set *rfds, struct timeval *tv, int msg_length_computed, int msg_length);
88 int (*filter_request) (modbus_t *ctx, int slave); 89 int (*filter_request) (modbus_t *ctx, int slave);
89 } modbus_backend_t; 90 } modbus_backend_t;
90 91
src/modbus-rtu.c
@@ -485,6 +485,49 @@ int _modbus_rtu_accept(modbus_t *ctx, int *socket) @@ -485,6 +485,49 @@ int _modbus_rtu_accept(modbus_t *ctx, int *socket)
485 return -1; 485 return -1;
486 } 486 }
487 487
  488 +int _modbus_rtu_select(modbus_t *ctx, fd_set *rfds, struct timeval *tv, int msg_length_computed, int msg_length)
  489 +{
  490 + int s_rc;
  491 + while ((s_rc = select(ctx->s+1, rfds, NULL, NULL, tv)) == -1) {
  492 + if (errno == EINTR) {
  493 + if (ctx->debug) {
  494 + fprintf(stderr, "A non blocked signal was caught\n");
  495 + }
  496 + /* Necessary after an error */
  497 + FD_ZERO(rfds);
  498 + FD_SET(ctx->s, rfds);
  499 + } else {
  500 + _error_print(ctx, "select");
  501 + if (ctx->error_recovery && (errno == EBADF)) {
  502 + modbus_close(ctx);
  503 + modbus_connect(ctx);
  504 + errno = EBADF;
  505 + return -1;
  506 + } else {
  507 + return -1;
  508 + }
  509 + }
  510 + }
  511 +
  512 + if (s_rc == 0) {
  513 + /* Timeout */
  514 + if (msg_length == (ctx->backend->header_length + 2 +
  515 + ctx->backend->checksum_length)) {
  516 + /* Optimization allowed because exception response is
  517 + the smallest trame in modbus protocol (3) so always
  518 + raise a timeout error.
  519 + Temporary error before exception analyze. */
  520 + errno = EMBUNKEXC;
  521 + } else {
  522 + errno = ETIMEDOUT;
  523 + _error_print(ctx, "select");
  524 + }
  525 + return -1;
  526 + }
  527 +
  528 + return s_rc;
  529 +}
  530 +
488 int _modbus_rtu_filter_request(modbus_t *ctx, int slave) 531 int _modbus_rtu_filter_request(modbus_t *ctx, int slave)
489 { 532 {
490 /* Filter on the Modbus unit identifier (slave) in RTU mode */ 533 /* Filter on the Modbus unit identifier (slave) in RTU mode */
@@ -518,6 +561,7 @@ const modbus_backend_t _modbus_rtu_backend = { @@ -518,6 +561,7 @@ const modbus_backend_t _modbus_rtu_backend = {
518 _modbus_rtu_flush, 561 _modbus_rtu_flush,
519 _modbus_rtu_listen, 562 _modbus_rtu_listen,
520 _modbus_rtu_accept, 563 _modbus_rtu_accept,
  564 + _modbus_rtu_select,
521 _modbus_rtu_filter_request 565 _modbus_rtu_filter_request
522 }; 566 };
523 567
src/modbus-tcp.c
@@ -297,6 +297,49 @@ int _modbus_tcp_accept(modbus_t *ctx, int *socket) @@ -297,6 +297,49 @@ int _modbus_tcp_accept(modbus_t *ctx, int *socket)
297 return ctx->s; 297 return ctx->s;
298 } 298 }
299 299
  300 +int _modbus_tcp_select(modbus_t *ctx, fd_set *rfds, struct timeval *tv, int msg_length_computed, int msg_length)
  301 +{
  302 + int s_rc;
  303 + while ((s_rc = select(ctx->s+1, rfds, NULL, NULL, tv)) == -1) {
  304 + if (errno == EINTR) {
  305 + if (ctx->debug) {
  306 + fprintf(stderr, "A non blocked signal was caught\n");
  307 + }
  308 + /* Necessary after an error */
  309 + FD_ZERO(rfds);
  310 + FD_SET(ctx->s, rfds);
  311 + } else {
  312 + _error_print(ctx, "select");
  313 + if (ctx->error_recovery && (errno == EBADF)) {
  314 + modbus_close(ctx);
  315 + modbus_connect(ctx);
  316 + errno = EBADF;
  317 + return -1;
  318 + } else {
  319 + return -1;
  320 + }
  321 + }
  322 + }
  323 +
  324 + if (s_rc == 0) {
  325 + /* Timeout */
  326 + if (msg_length == (ctx->backend->header_length + 2 +
  327 + ctx->backend->checksum_length)) {
  328 + /* Optimization allowed because exception response is
  329 + the smallest trame in modbus protocol (3) so always
  330 + raise a timeout error.
  331 + Temporary error before exception analyze. */
  332 + errno = EMBUNKEXC;
  333 + } else {
  334 + errno = ETIMEDOUT;
  335 + _error_print(ctx, "select");
  336 + }
  337 + return -1;
  338 + }
  339 +
  340 + return s_rc;
  341 +}
  342 +
300 int _modbus_tcp_filter_request(modbus_t *ctx, int slave) 343 int _modbus_tcp_filter_request(modbus_t *ctx, int slave)
301 { 344 {
302 return 0; 345 return 0;
@@ -320,6 +363,7 @@ const modbus_backend_t _modbus_tcp_backend = { @@ -320,6 +363,7 @@ const modbus_backend_t _modbus_tcp_backend = {
320 _modbus_tcp_flush, 363 _modbus_tcp_flush,
321 _modbus_tcp_listen, 364 _modbus_tcp_listen,
322 _modbus_tcp_accept, 365 _modbus_tcp_accept,
  366 + _modbus_tcp_select,
323 _modbus_tcp_filter_request 367 _modbus_tcp_filter_request
324 }; 368 };
325 369
src/modbus.c
@@ -226,44 +226,6 @@ static int compute_data_length(modbus_t *ctx, uint8_t *msg) @@ -226,44 +226,6 @@ static int compute_data_length(modbus_t *ctx, uint8_t *msg)
226 return length; 226 return length;
227 } 227 }
228 228
229 -#define WAIT_DATA() { \  
230 - while ((s_rc = select(ctx->s+1, &rfds, NULL, NULL, &tv)) == -1) { \  
231 - if (errno == EINTR) { \  
232 - if (ctx->debug) { \  
233 - fprintf(stderr, "A non blocked signal was caught\n"); \  
234 - } \  
235 - /* Necessary after an error */ \  
236 - FD_ZERO(&rfds); \  
237 - FD_SET(ctx->s, &rfds); \  
238 - } else { \  
239 - _error_print(ctx, "select"); \  
240 - if (ctx->error_recovery && (errno == EBADF)) { \  
241 - modbus_close(ctx); \  
242 - modbus_connect(ctx); \  
243 - errno = EBADF; \  
244 - return -1; \  
245 - } else { \  
246 - return -1; \  
247 - } \  
248 - } \  
249 - } \  
250 - \  
251 - if (s_rc == 0) { \  
252 - /* Timeout */ \  
253 - if (msg_length == (ctx->backend->header_length + 2 + \  
254 - ctx->backend->checksum_length)) { \  
255 - /* Optimization allowed because exception response is \  
256 - the smallest trame in modbus protocol (3) so always \  
257 - raise a timeout error. \  
258 - Temporary error before exception analyze. */ \  
259 - errno = EMBUNKEXC; \  
260 - } else { \  
261 - errno = ETIMEDOUT; \  
262 - _error_print(ctx, "select"); \  
263 - } \  
264 - return -1; \  
265 - } \  
266 -}  
267 229
268 /* Waits a response from a modbus server or a request from a modbus client. 230 /* Waits a response from a modbus server or a request from a modbus client.
269 This function blocks if there is no replies (3 timeouts). 231 This function blocks if there is no replies (3 timeouts).
@@ -330,8 +292,10 @@ static int receive_msg(modbus_t *ctx, int msg_length_computed, @@ -330,8 +292,10 @@ static int receive_msg(modbus_t *ctx, int msg_length_computed,
330 292
331 length_to_read = msg_length_computed; 293 length_to_read = msg_length_computed;
332 294
333 - s_rc = 0;  
334 - WAIT_DATA(); 295 + s_rc = ctx->backend->select(ctx, &rfds, &tv, msg_length_computed, msg_length);
  296 + if (s_rc == -1) {
  297 + return -1;
  298 + }
335 299
336 p_msg = msg; 300 p_msg = msg;
337 while (s_rc) { 301 while (s_rc) {
@@ -405,7 +369,10 @@ static int receive_msg(modbus_t *ctx, int msg_length_computed, @@ -405,7 +369,10 @@ static int receive_msg(modbus_t *ctx, int msg_length_computed,
405 tv.tv_sec = ctx->timeout_end.tv_sec; 369 tv.tv_sec = ctx->timeout_end.tv_sec;
406 tv.tv_usec = ctx->timeout_end.tv_usec; 370 tv.tv_usec = ctx->timeout_end.tv_usec;
407 371
408 - WAIT_DATA(); 372 + s_rc = ctx->backend->select(ctx, &rfds, &tv, msg_length_computed, msg_length);
  373 + if (s_rc == -1) {
  374 + return -1;
  375 + }
409 } else { 376 } else {
410 /* All chars are received */ 377 /* All chars are received */
411 s_rc = FALSE; 378 s_rc = FALSE;