/* * 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 #include #include #include #include #include #include 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); }