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 85 int (*flush) (modbus_t *ctx);
86 86 int (*listen) (modbus_t *ctx, int nb_connection);
87 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 89 int (*filter_request) (modbus_t *ctx, int slave);
89 90 } modbus_backend_t;
90 91  
... ...
src/modbus-rtu.c
... ... @@ -485,6 +485,49 @@ int _modbus_rtu_accept(modbus_t *ctx, int *socket)
485 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 531 int _modbus_rtu_filter_request(modbus_t *ctx, int slave)
489 532 {
490 533 /* Filter on the Modbus unit identifier (slave) in RTU mode */
... ... @@ -518,6 +561,7 @@ const modbus_backend_t _modbus_rtu_backend = {
518 561 _modbus_rtu_flush,
519 562 _modbus_rtu_listen,
520 563 _modbus_rtu_accept,
  564 + _modbus_rtu_select,
521 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 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 343 int _modbus_tcp_filter_request(modbus_t *ctx, int slave)
301 344 {
302 345 return 0;
... ... @@ -320,6 +363,7 @@ const modbus_backend_t _modbus_tcp_backend = {
320 363 _modbus_tcp_flush,
321 364 _modbus_tcp_listen,
322 365 _modbus_tcp_accept,
  366 + _modbus_tcp_select,
323 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 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 230 /* Waits a response from a modbus server or a request from a modbus client.
269 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 292  
331 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 300 p_msg = msg;
337 301 while (s_rc) {
... ... @@ -405,7 +369,10 @@ static int receive_msg(modbus_t *ctx, int msg_length_computed,
405 369 tv.tv_sec = ctx->timeout_end.tv_sec;
406 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 376 } else {
410 377 /* All chars are received */
411 378 s_rc = FALSE;
... ...