- SECoP protocol for scriptcontext

This commit is contained in:
2018-05-07 13:53:51 +02:00
parent da2b8c13d4
commit 19b3c71274
15 changed files with 288 additions and 27 deletions

View File

@ -72,9 +72,12 @@
* chksum-crc: simple 8bit checksum
*/
#define SIMULATE_ERROR 0
static int simulate_error = 0;
typedef enum {intType, hexType, floatType, strType,
skipType, codeType, checkType, crcType,
dumpType, endType, errorType} BinDataType; // items on this line stay at end
dumpType, endType, errorType} BinDataType; /* items on this line stay at end */
typedef enum {modbusCrc, kellerCrc, rsportCrc, syconCrc, chksumCrc} CrcAlgorithm;
@ -83,7 +86,8 @@ typedef struct {
CrcAlgorithm algo;
int crcStart;
pDynString inp;
char *nextFmt; // position of next format token
char *nextFmt; /* position of next format token */
char *readFmt; /* position of first read format */
pDynString result;
int expectedChars;
BinDataType type;
@ -94,6 +98,8 @@ typedef struct {
int syconState;
unsigned char chksum;
pDynString data;
int try_again_count;
int try_again_max;
} BinPrivate;
#define MAXDUMP 999
@ -383,6 +389,15 @@ void BinShuffle(char *input, int order) {
break;
}
}
/*----------------------------------------------------------------------------*/
void BinResetWrite(Ascon *a) {
BinPrivate *p = a->private;
p->nextFmt = p->readFmt;
a->wrPos = 0;
a->lineCount = 0;
a->state = AsconWriting;
}
/*----------------------------------------------------------------------------*/
int BinHandler(Ascon *a) {
int res;
@ -408,6 +423,7 @@ int BinHandler(Ascon *a) {
/* exchange buffers */
dyn = p->inp;
p->inp = a->wrBuffer;
p->try_again_count = p->try_again_max;
a->wrBuffer = dyn;
DynStringClear(dyn);
str = GetCharArray(p->inp);
@ -507,10 +523,10 @@ int BinHandler(Ascon *a) {
l += 4;
break;
case strType:
ls = strlen(item);
if (ls > size) {
item[size] = '\0';
}
ls = strlen(item);
if (ls > size) {
item[size] = '\0';
}
DynStringConcat(dyn, item);
if (size == NUL_TERMINATED) {
DynStringConcatChar(dyn, 0);
@ -520,7 +536,7 @@ int BinHandler(Ascon *a) {
DynStringConcatChar(dyn, 0);
}
l += size;
}
}
break;
}
}
@ -530,7 +546,8 @@ int BinHandler(Ascon *a) {
BinToSycon(dyn);
}
p->nextFmt = str + pos;
p->readFmt = str + pos;
p->nextFmt = p->readFmt;
p->type = hexType; /* initialize to anything < dumpType */
do {
res = BinReadItem(a);
@ -540,15 +557,11 @@ int BinHandler(Ascon *a) {
return 1;
}
} while (res == 1);
p->nextFmt = str + pos;
a->wrPos = 0;
BinResetWrite(a);
if (GetDynStringLength(a->wrBuffer) == 0) {
/* prevent to swallow "garbage" */
a->state = AsconWriteDone;
} else {
a->state = AsconWriting;
}
a->lineCount = 0;
return 1;
case AsconReadStart:
DynStringClear(p->result);
@ -558,10 +571,16 @@ int BinHandler(Ascon *a) {
break;
case AsconReading:
res = AsconBaseHandler(a);
if (a->state == AsconTimeout && p->try_again_count > 0) {
p->try_again_count--;
DynStringCopy(a->errmsg, "timeout");
BinResetWrite(a);
return 0;
}
if (res == 0) {
if (GetDynStringLength(a->rdBuffer) == 0) {
/* wait for the first byte - or timeout */
return res;
return 0;
}
if (p->type >= dumpType) {
l = GetDynStringLength(a->rdBuffer);
@ -578,15 +597,23 @@ int BinHandler(Ascon *a) {
DynStringConcat(a->errmsg, GetCharArray(p->result));
a->state = AsconFailed;
} else {
a->state = AsconReadDone;
if (p->try_again_count != p->try_again_max) {
Log(INFO, "com", "sock0:recovered from (%s) after: %s", GetCharArray(a->errmsg), GetCharArray(p->inp));
}
a->state = AsconReadDone;
}
/* exchange buffers */
dyn = a->rdBuffer;
a->rdBuffer = p->result;
p->result = dyn;
if (a->state == AsconFailed && p->try_again_count > 0) {
p->try_again_count--;
BinResetWrite(a);
return 0;
}
return 1;
}
return res;
return 0;
}
if (p->crcAlgorithm == syconCrc) {
switch (p->syconState) {
@ -745,13 +772,23 @@ int BinHandler(Ascon *a) {
p->expectedChars--;
if ((unsigned char)a->lastChar != p->iValue) {
i = GetDynStringLength(a->rdBuffer) - 1;
snprintf(item, sizeof item, "BINERR: response[%d]==%2.2x != %2.2x ", i, (unsigned char)a->lastChar, (unsigned char)p->iValue);
snprintf(item, sizeof item, "BINERR: [%d]==%2.2x != %2.2x ", i, (unsigned char)a->lastChar, (unsigned char)p->iValue);
DynStringCopy(a->errmsg, item);
p->type = errorType;
p->dumpFrom = 0;
/* skip to end */
p->nextFmt = "";
}
#if SIMULATE_ERROR > 0
if (p->try_again_max > 0 && simulate_error++ > SIMULATE_ERROR) {
DynStringCopy(a->errmsg, "simulate ");
p->type = errorType;
p->dumpFrom = 0;
/* skip to end */
p->nextFmt = "";
simulate_error = 0;
}
#endif
}
if (p->expectedChars <= 0) {
BinReadItem(a);
@ -773,6 +810,7 @@ static int BinInit(Ascon * a, SConnection * con, int argc, char *argv[])
{
BinPrivate *p;
/* args: 2 <protocol>, 3 <timeout>, 4 <try_again_max>
/* argv[2] may be modbus-crc (default), keller-crc, rsport-crc or sycon-crc */
if (argc < 2) {
@ -807,6 +845,12 @@ static int BinInit(Ascon * a, SConnection * con, int argc, char *argv[])
} else {
a->timeout = 2.0; /* sec */
}
if (argc > 4) {
p->try_again_max = atoi(argv[4]);
} else {
p->try_again_max = 0;
}
return 1;
}