Commit 9d5344cf42e425b33028cae11d5b74e4754af9c2
1 parent
a6e63d7d
Move RTU filtering in CRC check to avoid useless call to modbus_reply
Warning, modbus_receive returns 0 when a query is ignored. - function removed from TCP and RTU code and from backend structure - updated documentation - updated examples
Showing
10 changed files
with
38 additions
and
53 deletions
doc/modbus_receive.txt
| @@ -25,8 +25,9 @@ context 'ctx', see the function linkmb:modbus_set_socket[3]. | @@ -25,8 +25,9 @@ context 'ctx', see the function linkmb:modbus_set_socket[3]. | ||
| 25 | RETURN VALUE | 25 | RETURN VALUE |
| 26 | ------------ | 26 | ------------ |
| 27 | The _modbus_receive()_ function shall store the indication request in 'req' and | 27 | The _modbus_receive()_ function shall store the indication request in 'req' and |
| 28 | -return the request length if sucessful. Otherwise it shall return -1 and set | ||
| 29 | -errno. | 28 | +return the request length if sucessful. The returned request length can be zero |
| 29 | +if the indication request is ignored (eg. a query for another slave in RTU | ||
| 30 | +mode). Otherwise it shall return -1 and set errno. | ||
| 30 | 31 | ||
| 31 | 32 | ||
| 32 | SEE ALSO | 33 | SEE ALSO |
doc/modbus_receive_confirmation.txt
| @@ -23,8 +23,9 @@ function can be used to receive request not handled by the library. | @@ -23,8 +23,9 @@ function can be used to receive request not handled by the library. | ||
| 23 | RETURN VALUE | 23 | RETURN VALUE |
| 24 | ------------ | 24 | ------------ |
| 25 | The _modbus_receive_confirmation()_ function shall store the confirmation | 25 | The _modbus_receive_confirmation()_ function shall store the confirmation |
| 26 | -request in 'rsp' and return the response length if sucessful. Otherwise it shall | ||
| 27 | -return -1 and set errno. | 26 | +request in 'rsp' and return the response length if sucessful. The returned |
| 27 | +request length can be zero if the indication request is ignored (eg. a query for | ||
| 28 | +another slave in RTU mode). Otherwise it shall return -1 and set errno. | ||
| 28 | 29 | ||
| 29 | 30 | ||
| 30 | SEE ALSO | 31 | SEE ALSO |
src/modbus-private.h
| @@ -97,7 +97,6 @@ typedef struct _modbus_backend { | @@ -97,7 +97,6 @@ typedef struct _modbus_backend { | ||
| 97 | void (*close) (modbus_t *ctx); | 97 | void (*close) (modbus_t *ctx); |
| 98 | int (*flush) (modbus_t *ctx); | 98 | int (*flush) (modbus_t *ctx); |
| 99 | int (*select) (modbus_t *ctx, fd_set *rfds, struct timeval *tv, int msg_length); | 99 | int (*select) (modbus_t *ctx, fd_set *rfds, struct timeval *tv, int msg_length); |
| 100 | - int (*filter_request) (modbus_t *ctx, int slave); | ||
| 101 | } modbus_backend_t; | 100 | } modbus_backend_t; |
| 102 | 101 | ||
| 103 | struct _modbus { | 102 | struct _modbus { |
src/modbus-rtu.c
| @@ -328,7 +328,7 @@ int _modbus_rtu_pre_check_confirmation(modbus_t *ctx, const uint8_t *req, | @@ -328,7 +328,7 @@ int _modbus_rtu_pre_check_confirmation(modbus_t *ctx, const uint8_t *req, | ||
| 328 | if (req[0] != 0 && req[0] != rsp[0]) { | 328 | if (req[0] != 0 && req[0] != rsp[0]) { |
| 329 | if (ctx->debug) { | 329 | if (ctx->debug) { |
| 330 | fprintf(stderr, | 330 | fprintf(stderr, |
| 331 | - "The responding slave %d it not the requested slave %d", | 331 | + "The responding slave %d isn't the requested slave %d", |
| 332 | rsp[0], req[0]); | 332 | rsp[0], req[0]); |
| 333 | } | 333 | } |
| 334 | errno = EMBBADSLAVE; | 334 | errno = EMBBADSLAVE; |
| @@ -338,13 +338,24 @@ int _modbus_rtu_pre_check_confirmation(modbus_t *ctx, const uint8_t *req, | @@ -338,13 +338,24 @@ int _modbus_rtu_pre_check_confirmation(modbus_t *ctx, const uint8_t *req, | ||
| 338 | } | 338 | } |
| 339 | } | 339 | } |
| 340 | 340 | ||
| 341 | -/* The check_crc16 function shall return the message length if the CRC is | ||
| 342 | - valid. Otherwise it shall return -1 and set errno to EMBADCRC. */ | 341 | +/* The check_crc16 function shall return 0 is the message is ignored and the |
| 342 | + message length if the CRC is valid. Otherwise it shall return -1 and set | ||
| 343 | + errno to EMBADCRC. */ | ||
| 343 | int _modbus_rtu_check_integrity(modbus_t *ctx, uint8_t *msg, | 344 | int _modbus_rtu_check_integrity(modbus_t *ctx, uint8_t *msg, |
| 344 | const int msg_length) | 345 | const int msg_length) |
| 345 | { | 346 | { |
| 346 | uint16_t crc_calculated; | 347 | uint16_t crc_calculated; |
| 347 | uint16_t crc_received; | 348 | uint16_t crc_received; |
| 349 | + int slave = msg[0]; | ||
| 350 | + | ||
| 351 | + /* Filter on the Modbus unit identifier (slave) in RTU mode */ | ||
| 352 | + if (slave != ctx->slave && slave != MODBUS_BROADCAST_ADDRESS) { | ||
| 353 | + /* Ignores the request (not for me) */ | ||
| 354 | + if (ctx->debug) { | ||
| 355 | + printf("Request for slave %d ignored (not %d)\n", slave, ctx->slave); | ||
| 356 | + } | ||
| 357 | + return 0; | ||
| 358 | + } | ||
| 348 | 359 | ||
| 349 | crc_calculated = crc16(msg, msg_length - 2); | 360 | crc_calculated = crc16(msg, msg_length - 2); |
| 350 | crc_received = (msg[msg_length - 2] << 8) | msg[msg_length - 1]; | 361 | crc_received = (msg[msg_length - 2] << 8) | msg[msg_length - 1]; |
| @@ -948,21 +959,6 @@ int _modbus_rtu_select(modbus_t *ctx, fd_set *rfds, | @@ -948,21 +959,6 @@ int _modbus_rtu_select(modbus_t *ctx, fd_set *rfds, | ||
| 948 | return s_rc; | 959 | return s_rc; |
| 949 | } | 960 | } |
| 950 | 961 | ||
| 951 | -int _modbus_rtu_filter_request(modbus_t *ctx, int slave) | ||
| 952 | -{ | ||
| 953 | - /* Filter on the Modbus unit identifier (slave) in RTU mode */ | ||
| 954 | - if (slave != ctx->slave && slave != MODBUS_BROADCAST_ADDRESS) { | ||
| 955 | - /* Ignores the request (not for me) */ | ||
| 956 | - if (ctx->debug) { | ||
| 957 | - printf("Request for slave %d ignored (not %d)\n", | ||
| 958 | - slave, ctx->slave); | ||
| 959 | - } | ||
| 960 | - return 1; | ||
| 961 | - } else { | ||
| 962 | - return 0; | ||
| 963 | - } | ||
| 964 | -} | ||
| 965 | - | ||
| 966 | const modbus_backend_t _modbus_rtu_backend = { | 962 | const modbus_backend_t _modbus_rtu_backend = { |
| 967 | _MODBUS_BACKEND_TYPE_RTU, | 963 | _MODBUS_BACKEND_TYPE_RTU, |
| 968 | _MODBUS_RTU_HEADER_LENGTH, | 964 | _MODBUS_RTU_HEADER_LENGTH, |
| @@ -980,8 +976,7 @@ const modbus_backend_t _modbus_rtu_backend = { | @@ -980,8 +976,7 @@ const modbus_backend_t _modbus_rtu_backend = { | ||
| 980 | _modbus_rtu_connect, | 976 | _modbus_rtu_connect, |
| 981 | _modbus_rtu_close, | 977 | _modbus_rtu_close, |
| 982 | _modbus_rtu_flush, | 978 | _modbus_rtu_flush, |
| 983 | - _modbus_rtu_select, | ||
| 984 | - _modbus_rtu_filter_request | 979 | + _modbus_rtu_select |
| 985 | }; | 980 | }; |
| 986 | 981 | ||
| 987 | modbus_t* modbus_new_rtu(const char *device, | 982 | modbus_t* modbus_new_rtu(const char *device, |
src/modbus-tcp.c
| @@ -586,11 +586,6 @@ int _modbus_tcp_select(modbus_t *ctx, fd_set *rfds, struct timeval *tv, int leng | @@ -586,11 +586,6 @@ int _modbus_tcp_select(modbus_t *ctx, fd_set *rfds, struct timeval *tv, int leng | ||
| 586 | return s_rc; | 586 | return s_rc; |
| 587 | } | 587 | } |
| 588 | 588 | ||
| 589 | -int _modbus_tcp_filter_request(modbus_t *ctx, int slave) | ||
| 590 | -{ | ||
| 591 | - return 0; | ||
| 592 | -} | ||
| 593 | - | ||
| 594 | const modbus_backend_t _modbus_tcp_backend = { | 589 | const modbus_backend_t _modbus_tcp_backend = { |
| 595 | _MODBUS_BACKEND_TYPE_TCP, | 590 | _MODBUS_BACKEND_TYPE_TCP, |
| 596 | _MODBUS_TCP_HEADER_LENGTH, | 591 | _MODBUS_TCP_HEADER_LENGTH, |
| @@ -608,8 +603,7 @@ const modbus_backend_t _modbus_tcp_backend = { | @@ -608,8 +603,7 @@ const modbus_backend_t _modbus_tcp_backend = { | ||
| 608 | _modbus_tcp_connect, | 603 | _modbus_tcp_connect, |
| 609 | _modbus_tcp_close, | 604 | _modbus_tcp_close, |
| 610 | _modbus_tcp_flush, | 605 | _modbus_tcp_flush, |
| 611 | - _modbus_tcp_select, | ||
| 612 | - _modbus_tcp_filter_request | 606 | + _modbus_tcp_select |
| 613 | }; | 607 | }; |
| 614 | 608 | ||
| 615 | 609 | ||
| @@ -630,8 +624,7 @@ const modbus_backend_t _modbus_tcp_pi_backend = { | @@ -630,8 +624,7 @@ const modbus_backend_t _modbus_tcp_pi_backend = { | ||
| 630 | _modbus_tcp_pi_connect, | 624 | _modbus_tcp_pi_connect, |
| 631 | _modbus_tcp_close, | 625 | _modbus_tcp_close, |
| 632 | _modbus_tcp_flush, | 626 | _modbus_tcp_flush, |
| 633 | - _modbus_tcp_select, | ||
| 634 | - _modbus_tcp_filter_request | 627 | + _modbus_tcp_select |
| 635 | }; | 628 | }; |
| 636 | 629 | ||
| 637 | modbus_t* modbus_new_tcp(const char *ip, int port) | 630 | modbus_t* modbus_new_tcp(const char *ip, int port) |
src/modbus.c
| @@ -661,11 +661,6 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req, | @@ -661,11 +661,6 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req, | ||
| 661 | int rsp_length = 0; | 661 | int rsp_length = 0; |
| 662 | sft_t sft; | 662 | sft_t sft; |
| 663 | 663 | ||
| 664 | - if (ctx->backend->filter_request(ctx, slave) == 1) { | ||
| 665 | - /* Filtered */ | ||
| 666 | - return 0; | ||
| 667 | - } | ||
| 668 | - | ||
| 669 | sft.slave = slave; | 664 | sft.slave = slave; |
| 670 | sft.function = function; | 665 | sft.function = function; |
| 671 | sft.t_id = ctx->backend->prepare_response_tid(req, &req_length); | 666 | sft.t_id = ctx->backend->prepare_response_tid(req, &req_length); |
| @@ -935,11 +930,6 @@ int modbus_reply_exception(modbus_t *ctx, const uint8_t *req, | @@ -935,11 +930,6 @@ int modbus_reply_exception(modbus_t *ctx, const uint8_t *req, | ||
| 935 | int dummy_length = 99; | 930 | int dummy_length = 99; |
| 936 | sft_t sft; | 931 | sft_t sft; |
| 937 | 932 | ||
| 938 | - if (ctx->backend->filter_request(ctx, slave) == 1) { | ||
| 939 | - /* Filtered */ | ||
| 940 | - return 0; | ||
| 941 | - } | ||
| 942 | - | ||
| 943 | sft.slave = slave; | 933 | sft.slave = slave; |
| 944 | sft.function = function + 0x80;; | 934 | sft.function = function + 0x80;; |
| 945 | sft.t_id = ctx->backend->prepare_response_tid(req, &dummy_length); | 935 | sft.t_id = ctx->backend->prepare_response_tid(req, &dummy_length); |
tests/bandwidth-server-many-up.c
| @@ -120,10 +120,11 @@ int main(void) | @@ -120,10 +120,11 @@ int main(void) | ||
| 120 | 120 | ||
| 121 | modbus_set_socket(ctx, master_socket); | 121 | modbus_set_socket(ctx, master_socket); |
| 122 | rc = modbus_receive(ctx, query); | 122 | rc = modbus_receive(ctx, query); |
| 123 | - if (rc != -1) { | 123 | + if (rc > 0) { |
| 124 | modbus_reply(ctx, query, rc, mb_mapping); | 124 | modbus_reply(ctx, query, rc, mb_mapping); |
| 125 | - } else { | ||
| 126 | - /* Connection closed by the client, end of server */ | 125 | + } else if (rc == -1) { |
| 126 | + /* This example server in ended on connection closing or | ||
| 127 | + * any errors. */ | ||
| 127 | printf("Connection closed on socket %d\n", master_socket); | 128 | printf("Connection closed on socket %d\n", master_socket); |
| 128 | close(master_socket); | 129 | close(master_socket); |
| 129 | 130 |
tests/bandwidth-server-one.c
| @@ -75,10 +75,10 @@ int main(int argc, char *argv[]) | @@ -75,10 +75,10 @@ int main(int argc, char *argv[]) | ||
| 75 | uint8_t query[MODBUS_TCP_MAX_ADU_LENGTH]; | 75 | uint8_t query[MODBUS_TCP_MAX_ADU_LENGTH]; |
| 76 | 76 | ||
| 77 | rc = modbus_receive(ctx, query); | 77 | rc = modbus_receive(ctx, query); |
| 78 | - if (rc >= 0) { | 78 | + if (rc > 0) { |
| 79 | modbus_reply(ctx, query, rc, mb_mapping); | 79 | modbus_reply(ctx, query, rc, mb_mapping); |
| 80 | - } else { | ||
| 81 | - /* Connection closed by the client or server */ | 80 | + } else if (rc == -1) { |
| 81 | + /* Connection closed by the client or error */ | ||
| 82 | break; | 82 | break; |
| 83 | } | 83 | } |
| 84 | } | 84 | } |
tests/random-test-server.c
| @@ -47,10 +47,10 @@ int main(void) | @@ -47,10 +47,10 @@ int main(void) | ||
| 47 | int rc; | 47 | int rc; |
| 48 | 48 | ||
| 49 | rc = modbus_receive(ctx, query); | 49 | rc = modbus_receive(ctx, query); |
| 50 | - if (rc != -1) { | 50 | + if (rc > 0) { |
| 51 | /* rc is the query size */ | 51 | /* rc is the query size */ |
| 52 | modbus_reply(ctx, query, rc, mb_mapping); | 52 | modbus_reply(ctx, query, rc, mb_mapping); |
| 53 | - } else { | 53 | + } else if (rc == -1) { |
| 54 | /* Connection closed by the client or error */ | 54 | /* Connection closed by the client or error */ |
| 55 | break; | 55 | break; |
| 56 | } | 56 | } |
tests/unit-test-server.c
| @@ -114,12 +114,17 @@ int main(int argc, char*argv[]) | @@ -114,12 +114,17 @@ int main(int argc, char*argv[]) | ||
| 114 | } | 114 | } |
| 115 | 115 | ||
| 116 | for (;;) { | 116 | for (;;) { |
| 117 | - rc = modbus_receive(ctx, query); | 117 | + do { |
| 118 | + rc = modbus_receive(ctx, query); | ||
| 119 | + /* Filtered queries return 0 */ | ||
| 120 | + } while (rc == 0); | ||
| 121 | + | ||
| 118 | if (rc == -1) { | 122 | if (rc == -1) { |
| 119 | /* Connection closed by the client or error */ | 123 | /* Connection closed by the client or error */ |
| 120 | break; | 124 | break; |
| 121 | } | 125 | } |
| 122 | 126 | ||
| 127 | + | ||
| 123 | /* Read holding registers */ | 128 | /* Read holding registers */ |
| 124 | if (query[header_length] == 0x03) { | 129 | if (query[header_length] == 0x03) { |
| 125 | if (MODBUS_GET_INT16_FROM_INT8(query, header_length + 3) | 130 | if (MODBUS_GET_INT16_FROM_INT8(query, header_length + 3) |