134 lines
3.7 KiB
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);
|
|
}
|