Files
sicspsi/zwickroll.c

134 lines
3.7 KiB
C

/*
* zwickroll.c
*
* This is a variation of the standard AsonHandler which does not
* clear the garbage away before writing. This lead to lost data with
* the zwickroll machine.
*
* This is actually a fix rather then a solution. The Zwickroll test rig
* sends unsolicited messages. A better way to deal with this is to store them all
* in a queue which clients can inspect and consume from. Or use a callback system
* for processing incoming messages.
*
* Created on: December, 4, 2013
* Author: koennecke
*
* Revised to identify out-of-band messages and to pass them on to a separate
* handler script
*
* Mark Koennecke, December 2014
*/
#include <errno.h>
#include <ascon.h>
#include <ascon.i>
#include <lld.h>
#include <lld_str.h>
#include <stptok.h>
#include <trace.h>
static char *outofBandHandler = NULL;
static int outofBandList = -1;
/*----------------------------------------------------------------------------*/
static int outofBandHandled(Ascon *a)
{
int status;
char testString[80];
char command[1024];
char *toTest;
if(outofBandList < 0){
return 0;
}
status = LLDnodePtr2First(outofBandList);
toTest = GetCharArray(a->rdBuffer);
/* printf("outofBandHandler processing: %s\n", toTest); */
while(status != 0){
LLDstringData(outofBandList, testString);
if(strstr(toTest, testString) != NULL){
strcpy(command,outofBandHandler);
strncat(command," \"",sizeof(command));
strncat(command,GetCharArray(a->rdBuffer),sizeof(command));
strncat(command,"\"",sizeof(command));
/* printf("outofBandHandler found match with %s\n", testString); */
status = Tcl_Eval(InterpGetTcl(pServ->pSics), command);
if(status != TCL_OK){
traceIO("zwickroll","Tcl Error %s while processing out-of-band", Tcl_GetStringResult(InterpGetTcl(pServ->pSics)));
/* printf("Tcl Error %s while processing out-of-band\n", Tcl_GetStringResult(InterpGetTcl(pServ->pSics))); */
}
DynStringClear(a->rdBuffer);
return 1;
}
status = LLDnodePtr2Next(outofBandList);
}
return 0;
}
/*----------------------------------------------------------------------------*/
static int ZwickrollHandler(Ascon *a)
{
int ret, l;
switch(a->state){
case AsconWriting:
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;
}
}
break;
case AsconReading:
ret = AsconStdHandler(a);
if(a->state == AsconReadDone){
if(outofBandHandled(a)){
a->state = AsconReading;
}
}
return ret;
default:
return AsconStdHandler(a);
}
return 1;
}
/*------------------------------------------------------------------------*/
static int ZwickRollInit(Ascon *a, SConnection *con, int argc, char *argv[])
{
char token[80], *pPtr;
assert(argc>1);
a->hostport = strdup(argv[1]);
a->sendTerminator = strdup("\r\n");
a->replyTerminator = strdup("\n");
a->timeout = 2.;
if(argc > 3){
outofBandHandler = strdup(argv[3]);
outofBandList = LLDstringCreate();
pPtr = argv[2];
while(pPtr != NULL){
pPtr = stptok(pPtr,token,sizeof(token),":");
if(pPtr != NULL){
LLDstringAdd(outofBandList,token);
}
}
}
return 1;
}
/*------------------------------------------------------------------------*/
void AddZwickrollProtocoll()
{
AsconProtocol *prot = NULL;
prot = calloc(sizeof(AsconProtocol), 1);
prot->name = strdup("zwickroll");
prot->init = ZwickRollInit;
prot->handler = ZwickrollHandler;
AsconInsertProtocol(prot);
}