- SECoP protocol for scriptcontext
This commit is contained in:
78
binprot.c
78
binprot.c
@ -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;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user