- SECoP protocol for scriptcontext
This commit is contained in:
10
ascon.c
10
ascon.c
@ -150,9 +150,11 @@ static void AsconConnect(Ascon * a)
|
||||
ret = CreateSocketAdress(&adr, a->hostport, port);
|
||||
*colon = ':';
|
||||
if (ret == 0) {
|
||||
a->ip = 0;
|
||||
AsconError(a, "bad host specification", 0);
|
||||
return;
|
||||
}
|
||||
a->ip = adr.sin_addr.s_addr;
|
||||
oldopts = fcntl(a->fd, F_GETFL, 0);
|
||||
fcntl(a->fd, F_SETFL, oldopts | O_NONBLOCK);
|
||||
ret =
|
||||
@ -853,6 +855,14 @@ char *AsconHostport(Ascon *a)
|
||||
return a->hostport;
|
||||
}
|
||||
|
||||
unsigned long AsconIP(Ascon *a)
|
||||
{
|
||||
if (a==NULL) {
|
||||
return 0;
|
||||
}
|
||||
return a->ip;
|
||||
}
|
||||
|
||||
double AsconGetSetTimeout(Ascon *a, double timeout, int setmode) {
|
||||
if (setmode) {
|
||||
a->timeout = timeout;
|
||||
|
7
ascon.h
7
ascon.h
@ -109,6 +109,13 @@ int AsconLastState(Ascon *a);
|
||||
*/
|
||||
char *AsconHostport(Ascon *a);
|
||||
|
||||
/**
|
||||
* \brief return IP address
|
||||
* \param a The Ascon to query
|
||||
* \return the IP address
|
||||
*/
|
||||
unsigned long AsconIP(Ascon *a);
|
||||
|
||||
/**
|
||||
* \brief set or get timeout
|
||||
* \param a the Ascon
|
||||
|
1
ascon.i
1
ascon.i
@ -65,6 +65,7 @@ struct Ascon {
|
||||
char *sendTerminator; /**< terminator for sending messages */
|
||||
char *replyTerminator; /**< (std) terminator list for reply. NULL is the special case CR, LF or CR/LF */
|
||||
char *hostport; /**< host:port to connect */
|
||||
in_addr_t ip; /**< the ip address */
|
||||
pDynString errmsg; /**< error message */
|
||||
double start; /**< unix time when read was started */
|
||||
int noResponse; /**< no response expected */
|
||||
|
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;
|
||||
}
|
||||
|
||||
|
4
devser.c
4
devser.c
@ -580,6 +580,10 @@ char *DevHostport(DevSer *devser) {
|
||||
return AsconHostport(devser->ascon);
|
||||
}
|
||||
|
||||
unsigned long DevIP(DevSer *devser) {
|
||||
return AsconIP(devser->ascon);
|
||||
}
|
||||
|
||||
char *DevStatus(DevSer *devser) {
|
||||
char *str, *pos;
|
||||
static char buf[64];
|
||||
|
7
devser.h
7
devser.h
@ -203,6 +203,13 @@ void DevAsconStatistics(DevSer *self, double *avg,
|
||||
*/
|
||||
char *DevHostport(DevSer *devser);
|
||||
|
||||
/**
|
||||
* \brief return IP address
|
||||
* \param a The device serializer to query
|
||||
* \return the IP address
|
||||
*/
|
||||
unsigned long DevIP(DevSer *devser);
|
||||
|
||||
/**
|
||||
* \brief return status of device server ("offline", "unconnected", "")
|
||||
* \param devser The device serializer to query
|
||||
|
8
drive.c
8
drive.c
@ -121,17 +121,17 @@ int Drive(SConnection * pCon, SicsInterp * pInter, char *name, float fNew)
|
||||
if (iRet == DEVINT) {
|
||||
if (SCGetInterrupt(pCon) == eAbortOperation) {
|
||||
SCSetInterrupt(pCon, eContinue);
|
||||
snprintf(pBueffel, 511, "Driving %s aborted at %9.3f", name, fPos);
|
||||
snprintf(pBueffel, 511, "Driving %s aborted at %.6g", name, fPos);
|
||||
SCWrite(pCon, pBueffel, eError);
|
||||
}
|
||||
return 0;
|
||||
} else if (iRet == DEVDONE) {
|
||||
snprintf(pBueffel, 511, "Driving %s to %9.3f done", name, fPos);
|
||||
snprintf(pBueffel, 511, "Driving %s to %.6g done", name, fPos);
|
||||
SCWrite(pCon, pBueffel, eValue);
|
||||
return 1;
|
||||
} else {
|
||||
snprintf(pBueffel, 511,
|
||||
"Driving %s finished with problems, position: %9.3f", name,
|
||||
"Driving %s finished with problems, position: %.6g", name,
|
||||
fPos);
|
||||
SCWrite(pCon, pBueffel, eValue);
|
||||
return 1;
|
||||
@ -341,7 +341,7 @@ int DriveWrapper(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||
|
||||
/* print positions */
|
||||
for (i = 1; i < argc; i += 2) {
|
||||
snprintf(pBueffel,511, "New %s position: %9.3f", argv[i],
|
||||
snprintf(pBueffel,511, "New %s position: %.6g", argv[i],
|
||||
findPosition(pSics, pCon, argv[i]));
|
||||
SCWrite(pCon, pBueffel, eValue);
|
||||
}
|
||||
|
@ -133,13 +133,19 @@ int AnalyzeCommand(char *command) {
|
||||
|
||||
Tcl_SplitList(NULL, command, &argc, &argv);
|
||||
arg0 = 0;
|
||||
if (argc > 0 && strcmp(argv[0], "fulltransact") == 0) {
|
||||
if (argc > 0 && (strcmp(argv[0], "fulltransact") == 0
|
||||
|| strcmp(argv[0], "transact") == 0)) {
|
||||
arg0 = 1;
|
||||
}
|
||||
if (argc <= arg0 + 1) {
|
||||
writable = 0; /* single word -> guess read only */
|
||||
goto Free;
|
||||
}
|
||||
if (strcmp(argv[arg0], "sicsdescriptor") == 0
|
||||
|| strcmp(argv[arg0], "_tcl") == 0) {
|
||||
writable = 0;
|
||||
goto Free;
|
||||
}
|
||||
pDes = FindCommandDescriptor(pServ->pSics, argv[arg0]);
|
||||
if (pDes == NULL) goto Free;
|
||||
if (pDes->parNode == NULL && GetDescriptorKey(pDes, "pardef") == NULL) goto Free;
|
||||
|
@ -31,7 +31,8 @@ static hdbCallbackReturn LoggerUpdateCallback(pHdb node,
|
||||
value = *(mm->v);
|
||||
|
||||
time(&now);
|
||||
if (now > LoggerLastTime(logger)) { /* never write more than once per second */
|
||||
/* testwise >= */
|
||||
if (now >= LoggerLastTime(logger)) { /* never write more than once per second */
|
||||
if (GetHdbProp(node, "geterror") == NULL) {
|
||||
str = formatValue(value, node);
|
||||
LoggerWrite(logger, time(NULL), LoggerPeriod(logger), GetCharArray(str));
|
||||
|
3
make_gen
3
make_gen
@ -45,7 +45,8 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \
|
||||
singlenb.o simindex.o simidx.o uselect.o singletas.o motorsec.o \
|
||||
rwpuffer.o asynnet.o background.o countersec.o hdbtable.o velosec.o \
|
||||
histmemsec.o sansbc.o sicsutil.o strlutil.o genbinprot.o trace.o\
|
||||
singlebinb.o taskobj.o sctcomtask.o tasmono.o multicountersec.o lscprot.o \
|
||||
singlebinb.o taskobj.o sctcomtask.o tasmono.o multicountersec.o\
|
||||
lscprot.o secopprot.o\
|
||||
messagepipe.o sicsget.o remoteobject.o pmacprot.o charbychar.o binprot.o \
|
||||
cnvrt.o tclClock.o tclDate.o tclUnixTime.o stack_trace.o logv2.o outcode.o
|
||||
|
||||
|
2
ofac.c
2
ofac.c
@ -52,6 +52,7 @@ static void InitGeneral(void)
|
||||
INIT(AddPMACProtocoll);
|
||||
INIT(AddCharByCharProtocoll);
|
||||
INIT(AddLscProtocol);
|
||||
INIT(AddSecopProtocol);
|
||||
INIT(MakeTrace);
|
||||
INIT(InitTaskOBJ);
|
||||
INIT(RemoteObjectInit);
|
||||
@ -121,6 +122,7 @@ static void InitIniCommands(SicsInterp * pInter)
|
||||
PCMD("SICSType", SICSType);
|
||||
PCMD("Sics_Exitus", SicsExit);
|
||||
PCMD("silent", SICSSilent);
|
||||
PCMD("json2tcl", SICSjson2tcl);
|
||||
PCMD("status", UserStatus);
|
||||
PCMD("TclReplaceDrivable", TclReplaceDrivable);
|
||||
PCMD("transact", TransactAction);
|
||||
|
64
script.c
64
script.c
@ -43,7 +43,6 @@
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
#include <tcl.h>
|
||||
#include "fortify.h"
|
||||
#include "sics.h"
|
||||
#include "fupa.h"
|
||||
@ -579,3 +578,66 @@ int SICSSilent(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
free(cmd);
|
||||
return 1;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
Tcl_Obj *json2tcl(struct json_object *jobj) {
|
||||
char buf[100];
|
||||
int i, len;
|
||||
Tcl_Obj **list;
|
||||
Tcl_Obj *dict, *kobj, *vobj;
|
||||
Tcl_Obj *val;
|
||||
const char *key;
|
||||
const char *str;
|
||||
|
||||
switch (json_object_get_type(jobj)) {
|
||||
case json_type_boolean:
|
||||
return Tcl_NewBooleanObj(json_object_get_boolean(jobj));
|
||||
case json_type_int:
|
||||
return Tcl_NewLongObj(json_object_get_int(jobj));
|
||||
case json_type_double:
|
||||
return Tcl_NewDoubleObj(json_object_get_double(jobj));
|
||||
case json_type_string:
|
||||
str = json_object_get_string(jobj);
|
||||
return Tcl_NewStringObj((char *)str, json_object_get_string_len(jobj));
|
||||
case json_type_array:
|
||||
len = json_object_array_length(jobj);
|
||||
list = calloc(sizeof *list, len);
|
||||
for (i=0; i<len; i++) {
|
||||
list[i] = json2tcl(json_object_array_get_idx(jobj, i));
|
||||
if (!list[i]) return NULL;
|
||||
}
|
||||
return Tcl_NewListObj(len, list);
|
||||
case json_type_object:
|
||||
dict = Tcl_NewDictObj();
|
||||
if (!dict) return NULL;
|
||||
json_object_object_foreach(jobj, key, val) {
|
||||
kobj = Tcl_NewStringObj(key, strlen(key));
|
||||
vobj = json2tcl(val);
|
||||
if (kobj && vobj) {
|
||||
Tcl_DictObjPut(NULL, dict, kobj, vobj);
|
||||
}
|
||||
}
|
||||
return dict;
|
||||
}
|
||||
return Tcl_NewStringObj("None", 4);
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int SICSjson2tcl(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]) {
|
||||
json_object *jobj;
|
||||
assert(pCon);
|
||||
assert(pSics);
|
||||
|
||||
if (argc != 2) {
|
||||
SCWrite(pCon, "ERROR: should be: json2tcl <string>", eError);
|
||||
return 0;
|
||||
}
|
||||
jobj = json_tokener_parse(argv[1]);
|
||||
if (!jobj) {
|
||||
SCWrite(pCon, "ERROR: no valid JSON", eError);
|
||||
return 0;
|
||||
}
|
||||
/* the result is written only to the interpreter, no output to the client */
|
||||
Tcl_SetObjResult(pSics->pTcl, json2tcl(jobj));
|
||||
json_object_put(jobj);
|
||||
return 1;
|
||||
}
|
||||
|
8
script.h
8
script.h
@ -10,6 +10,9 @@
|
||||
#ifndef SICSSCRIPT
|
||||
#define SICSSCRIPT
|
||||
|
||||
#include <tcl.h>
|
||||
#include <json-c/json.h>
|
||||
|
||||
/* -------------------------- Interrupts -----------------------------------*/
|
||||
int GetSICSInterrupt(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
@ -51,4 +54,9 @@ int SICSDescriptor(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||
/*----------------------------------------------------------------------*/
|
||||
int SICSSilent(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
/*----------------------------------------------------------------------*/
|
||||
Tcl_Obj *json2tcl(struct json_object *jobj);
|
||||
/*----------------------------------------------------------------------*/
|
||||
int SICSjson2tcl(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
#endif
|
||||
|
@ -283,7 +283,11 @@ int SctCommand(SConnection * con, SicsInterp * sics, void *object,
|
||||
if (argc == 3) {
|
||||
node = FindHdbNode(NULL, argv[2], con);
|
||||
}
|
||||
GetHdbPath(node->mama, value, sizeof value);
|
||||
if (node) {
|
||||
GetHdbPath(node->mama, value, sizeof value);
|
||||
} else {
|
||||
value[0] = 0;
|
||||
}
|
||||
/* returns an empty string on error */
|
||||
SCWrite(con, value, eValue);
|
||||
return 1;
|
||||
@ -1733,6 +1737,22 @@ static int SctHostport(pSICSOBJ ccmd, SConnection * con,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int SctIpAddress(pSICSOBJ ccmd, SConnection * con,
|
||||
Hdb * cmdNode, Hdb * par[], int nPar)
|
||||
{
|
||||
SctController *c;
|
||||
uint32_t ip;
|
||||
|
||||
c = (SctController *) ccmd->pPrivate;
|
||||
ip = DevIP(c->devser);
|
||||
SCPrintf(con, eValue, "%d.%d.%d.%d",
|
||||
(int)(ip & 0xff),
|
||||
(int)((ip >> 8) & 0xff),
|
||||
(int)((ip >> 16) & 0xff),
|
||||
(int)((ip >> 24) & 0xff));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int SctTimeout(pSICSOBJ ccmd, SConnection * con,
|
||||
Hdb * cmdNode, Hdb * par[], int nPar)
|
||||
{
|
||||
@ -1909,7 +1929,7 @@ static int SctMakeController(SConnection * con, SicsInterp * sics,
|
||||
assert(controller);
|
||||
controller->debugConn = NULL;
|
||||
|
||||
ccmd = MakeSICSOBJv(objName, "SctController", HIPNONE, usSpy);
|
||||
ccmd = MakeSICSOBJv(objName, "SctController", HIPTEXT, usSpy);
|
||||
controller->node = ccmd->objectNode;
|
||||
controller->conn = SCCreateDummyConnection(pServ->pSics);
|
||||
|
||||
@ -2006,6 +2026,9 @@ static int SctMakeController(SConnection * con, SicsInterp * sics,
|
||||
cmd = AddSICSHdbPar(controller->node,
|
||||
"hostport", usSpy, MakeSICSFunc(SctHostport));
|
||||
|
||||
cmd = AddSICSHdbPar(controller->node,
|
||||
"ip", usSpy, MakeSICSFunc(SctIpAddress));
|
||||
|
||||
cmd = AddSICSHdbPar(controller->node,
|
||||
"status", usSpy, MakeSICSFunc(SctStatus));
|
||||
|
||||
|
85
secopprot.c
Normal file
85
secopprot.c
Normal file
@ -0,0 +1,85 @@
|
||||
#include <errno.h>
|
||||
#include <tcl.h>
|
||||
#include <json-c/json.h>
|
||||
#include "ascon.h"
|
||||
#include "ascon.i"
|
||||
#include "script.h"
|
||||
|
||||
/*
|
||||
* protocol for SECoP
|
||||
*
|
||||
* Markus Zolliker June 2017
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int SecopProtHandler(Ascon *a) {
|
||||
int ret;
|
||||
char *result;
|
||||
char *space;
|
||||
char *json;
|
||||
Tcl_Obj *tcllist[3], *tclobj;
|
||||
int l;
|
||||
struct json_object *jobj;
|
||||
|
||||
switch (a->state) {
|
||||
case AsconWriting:
|
||||
/* do not skip garbage (might be a message!) */
|
||||
l = GetDynStringLength(a->wrBuffer) - a->wrPos;
|
||||
ret = AsconWriteChars(a->fd, GetCharArray(a->wrBuffer) + a->wrPos, l);
|
||||
if (ret < 0) {
|
||||
AsconError(a, "ASC4", errno); /* sets state to AsconFailed */
|
||||
} else {
|
||||
a->wrPos += ret;
|
||||
if (a->wrPos >= GetDynStringLength(a->wrBuffer)) {
|
||||
a->state = AsconWriteDone;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
case AsconWriteStart:
|
||||
if (GetDynStringLength(a->wrBuffer) == 0) {
|
||||
/* do not send empty message */
|
||||
a->state = AsconWriteDone;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
ret = AsconStdHandler(a);
|
||||
switch (a->state) {
|
||||
case AsconReading:
|
||||
if (ret) {
|
||||
if (a->timeout < 1) {
|
||||
/* extend timeout to 1 sec during a message */
|
||||
a->start = DoubleTime() + 1 - a->timeout;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AsconReadDone:
|
||||
result = GetCharArray(a->rdBuffer);
|
||||
space = strchr(result, ' ');
|
||||
if (space) {
|
||||
json = strchr(space+1, ' ');
|
||||
if (json) {
|
||||
json++;
|
||||
jobj = json_tokener_parse(json);
|
||||
if (jobj) {
|
||||
tcllist[0] = Tcl_NewStringObj(result, space - result);
|
||||
tcllist[1] = Tcl_NewStringObj(space + 1, json - space - 2);
|
||||
tcllist[2] = json2tcl(jobj);
|
||||
tclobj = Tcl_NewListObj(3, tcllist);
|
||||
DynStringCopy(a->rdBuffer, Tcl_GetString(tclobj));
|
||||
json_object_put(jobj); /* free jobj */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void AddSecopProtocol() {
|
||||
static AsconProtocol secopprot;
|
||||
secopprot.name = "SECoP";
|
||||
secopprot.handler = SecopProtHandler;
|
||||
secopprot.init = AsconStdInit;
|
||||
AsconInsertProtocol(&secopprot);
|
||||
}
|
Reference in New Issue
Block a user