/* * This is a testing and simulation protocol for use with * scriptcontext. This protocol does not build a network * connection. Rather it has two modes of operation: * - In the simplest mode of operation it just returns an echo of the * command given. * - When initialized with a filename it reads that file as a dictionary * of commands and responses. Thus responses can be programmed. Through * a special escape, stored as tclescape in the dictionary it executes * the response as a Tcl function with the command string as a parameter. * Thus replies can be programmed for software testing. * * testprot.c * * Created on: Feb 2, 2010 * Author: Mark Koennecke */ #include #include #include #include #include #include /*--------------------------------------------------------------------------*/ static void killDict(void *data) { pStringDict dict = NULL; if(data != NULL){ dict = (pStringDict)data; DeleteStringDict(dict); } } /*--------------------------------------------------------------------------*/ static void readDictionary(Ascon *a, SConnection *con, char *filename) { pStringDict dict = NULL; FILE *fd = NULL; char pLine[256], *c; fd = fopen(filename,"r"); if(fd == NULL){ SCPrintf(con,eError,"ERROR: dictionary file %s not found!", filename); return; } dict = CreateStringDict(); if(dict == NULL){ SCWrite(con,"ERROR: failed to allocate dictionary", eError); return; } while(fgets(pLine,256,fd) != NULL){ /* * get rid of the trailing \n */ c = strrchr(pLine,'\n'); if(c != NULL){ *c = '\0'; } /* split at = */ c = strchr(pLine,'='); if(c == NULL){ SCPrintf(con,eWarning, "WARNING: Invalid line %s in %s", pLine, filename); continue; } *c = '\0'; StringDictAddPair(dict,pLine,c+1); } fclose(fd); a->private = dict; a->killPrivate = killDict; } /*--------------------------------------------------------------------------*/ static int TestProtInit(Ascon *a, SConnection *con, int argc, char *argv[]) { a->hostport = strdup("None"); a->sendTerminator = strdup("\n"); a->timeout = 0; a->reconnectInterval = -1; /* immediate */ a->replyTerminator = strdup("\n"); if(argc > 0){ readDictionary(a,con,argv[1]); } return 1; } /*---------------------------------------------------------------------------*/ static void findResponse(Ascon *a) { pStringDict dict = NULL; char tclEscape[80], response[256], *test = NULL, command[512]; int status; DynStringClear(a->rdBuffer); DynStringClear(a->errmsg); /* simple echo operation */ if(a->private == NULL){ DynStringConcat(a->rdBuffer,GetCharArray(a->wrBuffer)); return; } /* dictionary operation */ memset(response,0,sizeof(response)); memset(tclEscape,0,sizeof(tclEscape)); dict = (pStringDict)a->private; status = StringDictGet(dict,GetCharArray(a->wrBuffer),response, sizeof(response)); if(status != 1){ a->state = AsconFailed; DynStringConcat(a->errmsg,"ERROR: no response found in dictionary for "); DynStringConcat(a->errmsg,GetCharArray(a->wrBuffer)); return; } status = StringDictGet(dict,"tclescape",tclEscape,sizeof(tclEscape)); if(status == 1){ test = strstr(response, tclEscape); if(test != NULL){ /* Tcl operation! */ test += strlen(tclEscape); snprintf(command,sizeof(command),"%s %s", test, GetCharArray(a->wrBuffer)); status = Tcl_Eval(InterpGetTcl(pServ->pSics), command); if(status != TCL_OK){ DynStringConcat(a->errmsg, "ERROR:"); DynStringConcat(a->errmsg, (char *)Tcl_GetStringResult(InterpGetTcl(pServ->pSics))); a->state = AsconFailed; } else { DynStringConcat(a->rdBuffer,(char *)Tcl_GetStringResult(InterpGetTcl(pServ->pSics))); } } else { DynStringConcat(a->rdBuffer,response); } } else { DynStringConcat(a->rdBuffer,response); } } /*---------------------------------------------------------------------------*/ static int TestProtHandler(Ascon * a) { int i; switch (a->state) { case AsconConnectStart: case AsconConnecting: a->state = AsconConnectDone; break; case AsconWriteStart: a->state = AsconWriting; break; case AsconWriting: a->state = AsconWriteDone; findResponse(a); break; case AsconReadStart: for(i = 0; i < 100; i++){ TaskYield(pServ->pTasker); } a->state = AsconReading; break; case AsconReading: a->state = AsconReadDone; break; default: break; } return 1; } /*-------------------------------------------------------------------------*/ void AddTestProt() { AsconProtocol *prot = NULL; prot = calloc(sizeof(AsconProtocol), 1); prot->name = strdup("testprot"); prot->init = TestProtInit; prot->handler = TestProtHandler; AsconInsertProtocol(prot); }