Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 18 additions & 6 deletions src/modbus-rtu.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,12 @@ static int _modbus_set_slave(modbus_t *ctx, int slave)
return 0;
}


int _modbus_rtu_build_request_basis(modbus_t *ctx, int function,
int addr, int nb,
uint8_t *req);
/* Builds a RTU request header */
static int _modbus_rtu_build_request_basis(modbus_t *ctx, int function,
int _modbus_rtu_build_request_basis(modbus_t *ctx, int function,
int addr, int nb,
uint8_t *req)
{
Expand All @@ -118,8 +122,9 @@ static int _modbus_rtu_build_request_basis(modbus_t *ctx, int function,
return _MODBUS_RTU_PRESET_REQ_LENGTH;
}

int _modbus_rtu_build_response_basis(sft_t *sft, uint8_t *rsp);
/* Builds a RTU response header */
static int _modbus_rtu_build_response_basis(sft_t *sft, uint8_t *rsp)
int _modbus_rtu_build_response_basis(sft_t *sft, uint8_t *rsp)
{
/* In this case, the slave is certainly valid because a check is already
* done in _modbus_rtu_listen */
Expand All @@ -129,7 +134,10 @@ static int _modbus_rtu_build_response_basis(sft_t *sft, uint8_t *rsp)
return _MODBUS_RTU_PRESET_RSP_LENGTH;
}

static uint16_t crc16(uint8_t *buffer, uint16_t buffer_length)

uint16_t crc16(uint8_t *buffer, uint16_t buffer_length);

uint16_t crc16(uint8_t *buffer, uint16_t buffer_length)
{
uint8_t crc_hi = 0xFF; /* high CRC byte initialized */
uint8_t crc_lo = 0xFF; /* low CRC byte initialized */
Expand All @@ -145,14 +153,16 @@ static uint16_t crc16(uint8_t *buffer, uint16_t buffer_length)
return (crc_hi << 8 | crc_lo);
}

static int _modbus_rtu_prepare_response_tid(const uint8_t *req, int *req_length)
int _modbus_rtu_prepare_response_tid(const uint8_t *req, int *req_length);
int _modbus_rtu_prepare_response_tid(const uint8_t *req, int *req_length)
{
(*req_length) -= _MODBUS_RTU_CHECKSUM_LENGTH;
/* No TID */
return 0;
}

static int _modbus_rtu_send_msg_pre(uint8_t *req, int req_length)
int _modbus_rtu_send_msg_pre(uint8_t *req, int req_length);
int _modbus_rtu_send_msg_pre(uint8_t *req, int req_length)
{
uint16_t crc = crc16(req, req_length);
req[req_length++] = crc >> 8;
Expand Down Expand Up @@ -352,10 +362,12 @@ static int _modbus_rtu_pre_check_confirmation(modbus_t *ctx, const uint8_t *req,
}
}

int _modbus_rtu_check_integrity(modbus_t *ctx, uint8_t *msg,
const int msg_length);
/* The check_crc16 function shall return 0 is the message is ignored and the
message length if the CRC is valid. Otherwise it shall return -1 and set
errno to EMBADCRC. */
static int _modbus_rtu_check_integrity(modbus_t *ctx, uint8_t *msg,
int _modbus_rtu_check_integrity(modbus_t *ctx, uint8_t *msg,
const int msg_length)
{
uint16_t crc_calculated;
Expand Down
160 changes: 156 additions & 4 deletions src/modbus-tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,8 @@ static int _modbus_tcp_receive(modbus_t *ctx, uint8_t *req) {
return _modbus_receive_msg(ctx, req, MSG_INDICATION);
}

static ssize_t _modbus_tcp_recv(modbus_t *ctx, uint8_t *rsp, int rsp_length) {
ssize_t _modbus_tcp_recv(modbus_t *ctx, uint8_t *rsp, int rsp_length);
ssize_t _modbus_tcp_recv(modbus_t *ctx, uint8_t *rsp, int rsp_length) {
return recv(ctx->s, (char *)rsp, rsp_length, 0);
}

Expand Down Expand Up @@ -292,8 +293,9 @@ static int _connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen,
return rc;
}

int _modbus_tcp_connect(modbus_t *ctx);
/* Establishes a modbus TCP connection with a Modbus server. */
static int _modbus_tcp_connect(modbus_t *ctx)
int _modbus_tcp_connect(modbus_t *ctx)
{
int rc;
/* Specialized version of sockaddr for Internet socket address (same size) */
Expand Down Expand Up @@ -423,7 +425,8 @@ static int _modbus_tcp_pi_connect(modbus_t *ctx)
}

/* Closes the network connection and socket in TCP mode */
static void _modbus_tcp_close(modbus_t *ctx)
void _modbus_tcp_close(modbus_t *ctx);
void _modbus_tcp_close(modbus_t *ctx)
{
if (ctx->s != -1) {
shutdown(ctx->s, SHUT_RDWR);
Expand All @@ -432,7 +435,8 @@ static void _modbus_tcp_close(modbus_t *ctx)
}
}

static int _modbus_tcp_flush(modbus_t *ctx)
static int _modbus_tcp_flush(modbus_t *ctx);
int _modbus_tcp_flush(modbus_t *ctx)
{
int rc;
int rc_sum = 0;
Expand Down Expand Up @@ -751,6 +755,85 @@ const modbus_backend_t _modbus_tcp_backend = {
};







int _modbus_rtu_build_request_basis(modbus_t *ctx, int function,
int addr, int nb,
uint8_t *req);
int _modbus_rtu_build_response_basis(sft_t *sft, uint8_t *rsp);
int _modbus_rtu_prepare_response_tid(const uint8_t *req, int *req_length);
int _modbus_rtu_send_msg_pre(uint8_t *req, int req_length);
int _modbus_rtu_check_integrity(modbus_t *ctx, uint8_t *msg,
const int msg_length);
int _modbus_rtu_filter_request(modbus_t *ctx, int slave);
uint16_t crc16(uint8_t *buffer, uint16_t buffer_length);
int _modbus_rtutcp_check_integrity(modbus_t *ctx, uint8_t *msg,
const int msg_length);

/* The check_crc16 function shall return the message length if the CRC is
valid. Otherwise it shall return -1 and set errno to EMBADCRC. */
int _modbus_rtutcp_check_integrity(modbus_t *ctx, uint8_t *msg,
const int msg_length)
{
uint16_t crc_calculated;
uint16_t crc_received;

crc_calculated = crc16(msg, msg_length - 2);
crc_received = (msg[msg_length - 2] << 8) | msg[msg_length - 1];

/* Check CRC of msg */
if (crc_calculated == crc_received) {
return msg_length;
} else {
if (ctx->debug) {
fprintf(stderr, "ERROR CRC received %0X != CRC calculated %0X\n",
crc_received, crc_calculated);
}
if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_PROTOCOL) {
_modbus_tcp_flush(ctx);
}
errno = EMBBADCRC;
return -1;
}
}



#define MODBUS_RTU_MAX_ADU_LENGTH 256
#define _MODBUS_RTU_CHECKSUM_LENGTH 2
#define _MODBUS_RTU_HEADER_LENGTH 1

const modbus_backend_t _modbus_rtutcp_backend = {
_MODBUS_BACKEND_TYPE_TCP,
_MODBUS_RTU_HEADER_LENGTH,
_MODBUS_RTU_CHECKSUM_LENGTH,
MODBUS_RTU_MAX_ADU_LENGTH,
_modbus_set_slave,
_modbus_rtu_build_request_basis,
_modbus_rtu_build_response_basis,
_modbus_rtu_prepare_response_tid,
_modbus_rtu_send_msg_pre,
_modbus_tcp_send,
_modbus_tcp_receive,
_modbus_tcp_recv,
_modbus_rtu_check_integrity,
NULL,
_modbus_tcp_connect,
_modbus_tcp_close,
_modbus_tcp_flush,
_modbus_tcp_select,
_modbus_tcp_free
};







const modbus_backend_t _modbus_tcp_pi_backend = {
_MODBUS_BACKEND_TYPE_TCP,
_MODBUS_TCP_HEADER_LENGTH,
Expand Down Expand Up @@ -830,6 +913,75 @@ modbus_t* modbus_new_tcp(const char *ip, int port)
}








modbus_t* modbus_new_rtutcp(const char *ip, int port)
{
modbus_t *ctx;
modbus_tcp_t *ctx_tcp;
size_t dest_size;
size_t ret_size;

#if defined(OS_BSD)
/* MSG_NOSIGNAL is unsupported on *BSD so we install an ignore
handler for SIGPIPE. */
struct sigaction sa;

sa.sa_handler = SIG_IGN;
if (sigaction(SIGPIPE, &sa, NULL) < 0) {
/* The debug flag can't be set here... */
fprintf(stderr, "Coud not install SIGPIPE handler.\n");
return NULL;
}
#endif

ctx = (modbus_t *) malloc(sizeof(modbus_t));
_modbus_init_common(ctx);

/* Could be changed after to reach a remote serial Modbus device */
ctx->slave = MODBUS_TCP_SLAVE;

ctx->backend = &(_modbus_rtutcp_backend);

ctx->backend_data = (modbus_tcp_t *) malloc(sizeof(modbus_tcp_t));
ctx_tcp = (modbus_tcp_t *)ctx->backend_data;

dest_size = sizeof(char) * 16;
ret_size = strlcpy(ctx_tcp->ip, ip, dest_size);
if (ret_size == 0) {
fprintf(stderr, "The IP string is empty\n");
modbus_free(ctx);
errno = EINVAL;
return NULL;
}

if (ret_size >= dest_size) {
fprintf(stderr, "The IP string has been truncated\n");
modbus_free(ctx);
errno = EINVAL;
return NULL;
}

ctx_tcp->port = port;

return ctx;
}












modbus_t* modbus_new_tcp_pi(const char *node, const char *service)
{
modbus_t *ctx;
Expand Down
1 change: 1 addition & 0 deletions src/modbus-tcp.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ MODBUS_BEGIN_DECLS
#define MODBUS_TCP_MAX_ADU_LENGTH 260

MODBUS_API modbus_t* modbus_new_tcp(const char *ip_address, int port);
MODBUS_API modbus_t* modbus_new_rtutcp(const char *ip, int port);
MODBUS_API int modbus_tcp_listen(modbus_t *ctx, int nb_connection);
MODBUS_API int modbus_tcp_accept(modbus_t *ctx, int *s);

Expand Down