diff --git a/protocol.c b/protocol.c index 6f9099b5..ab9ee6ec 100644 --- a/protocol.c +++ b/protocol.c @@ -16,11 +16,13 @@ #include #include "commandlog.h" #include "protocol.h" +#include "json.h" #define MAXMSG 1024 #define INIT_STR_SIZE 256 #define STR_RESIZE_LENGTH 256 - +#define NUMPROS 5 +#define PROLISTLEN 6 typedef struct __Protocol { pObjectDescriptor pDes; /* required as first field */ char *name; /* protocol handler name */ @@ -28,7 +30,7 @@ typedef struct __Protocol { int iNumPros; /* number of valid protocols? */ writeFunc defaultWriter; /* default write function */ int isDefaultSet; - char *pProList[5]; /* list of valid protocols? */ + char *pProList[PROLISTLEN]; /* list of valid protocols? */ } Protocol; char *pEventType[]={ @@ -95,15 +97,17 @@ static int InitDefaultProtocol(SConnection* pCon, Protocol *pPro); /* Signatures for protocol writers implemented in this file */ int SCWriteSycamore(SConnection *pCon, char *pBuffer, int iOut); +int SCWriteJSON_String(SConnection *pCon, char *pBuffer, int iOut); /*--------------------------------------------------------------------------*/ pProtocol CreateProtocol(void) { - int i, iNumPros = 4; - char *pPros[5] = {"default", + int i, iNumPros = NUMPROS; + char *pPros[] = {"default", "normal", "withcode", "sycamore", + "json", NULL }; pProtocol pNew = NULL; @@ -276,7 +280,9 @@ static int ProtocolSet(SConnection* pCon, Protocol* pPro, char *pProName) case 3: /* sycamore */ SCSetWriteFunc(pCon,SCWriteSycamore); break; - + case 4: /* json */ + SCSetWriteFunc(pCon,SCWriteJSON_String); + break; case 0: /* default = psi_sics */ default: SCSetWriteFunc(pCon,pPro->defaultWriter); @@ -351,10 +357,10 @@ int ProtocolAction(SConnection *pCon, SicsInterp *pSics, void *pData, {NULL} }; - assert(pCon); - assert(pSics); + assert(pCon != NULL); + assert(pSics != NULL); pPro = (pProtocol)pData; - assert(pPro); + assert(pPro != NULL); /* You need to have User level access rights to use this facility */ if(!SCMatchRights(pCon,usSpy)) @@ -427,8 +433,6 @@ static int InitDefaultProtocol(SConnection* pCon, Protocol *pPro) } /*---------------------------------------------------------------------*/ void sycformat(char *tag, OutCode msgFlag, pDynString msgString, pDynString msgOut) { - char typePrefix[] = "type."; - char statusPrefix[] = "status."; DynStringConcat(msgOut," "); switch (msgFlag) { eEvent: @@ -445,19 +449,13 @@ void sycformat(char *tag, OutCode msgFlag, pDynString msgString, pDynString msgO } int SCWriteSycamore(SConnection *pCon, char *pBuffer, int iOut) { - int i, iPtr, iRet; - int bDevIDdone = 0; - int bFlagDone = 0; + int iRet; char pBueffel[MAXMSG], *pBufferFrom, *pBufferTo; long taskID = 0; /* char pPrefix[40];*/ pDynString pMsg = NULL; pDynString pMsgString = NULL; - SicsInterp *pSics; - TokenList *pList = NULL; - TokenList *pCurrent; commandContext comCon; - char *savedTclResult = NULL; if (strlen(pBuffer) == 0) { @@ -517,11 +515,6 @@ int SCWriteSycamore(SConnection *pCon, char *pBuffer, int iOut) return 0; } - /* - build the Tcl-command to execute for formatting the - data into a sycamore string - */ - pSics = GetInterpreter(); taskID = comCon.transID; pMsg = CreateDynString(INIT_STR_SIZE, STR_RESIZE_LENGTH); @@ -582,6 +575,135 @@ int SCWriteSycamore(SConnection *pCon, char *pBuffer, int iOut) return 1; } +/* Only work for hipadaba commands, hlist, hset, hget, hnotify + * A multiline string (ie have crnl) will be converted to an array. + * Strings with '=' will be converted to name value pairs + */ +struct json_object *mkJSON_Object(SConnection *pCon, char *pBuffer, int iOut) +{ + int linenum = __LINE__; + char pBueffel[MAXMSG], *pBufferFrom, *pBufferTo; + long taskID = 0; + struct json_object *msg_json=NULL, *tmp_json=NULL; + + commandContext comCon; + char pError[256]; + pError[0]='\0'; + + + if (strlen(pBuffer) == 0) { + return 0; + } + + if(!SCVerifyConnection(pCon)) + { + return 0; + } + comCon = SCGetContext(pCon); + + /* Return 0 without dying if no message data */ + if(pBuffer == NULL) + { + return 0; + } + + /* + build the Tcl-command to execute for formatting the + data into a sycamore string + */ + taskID = comCon.transID; + + pBueffel[0] = '\0'; + msg_json = json_object_new_object(); + if (is_error(msg_json)) { linenum = __LINE__; goto reporterr; } +/* field 1: connID */ + json_object_object_add(msg_json, "con", json_object_new_int(pCon->ident)); +/* field 2: taskID */ + json_object_object_add(msg_json, "trans", json_object_new_int(taskID)); + /* deviceID */ + json_object_object_add(msg_json, "object", json_object_new_string(comCon.deviceID)); + + /* msgFlag */ + switch(iOut) { + case 5: /* eValue */ + json_object_object_add(msg_json, "flag", json_object_new_string("out")); + break; + default: + json_object_object_add(msg_json, "flag", json_object_new_string(pCode[iOut])); + break; + } + if (iOut == eStatus || iOut == eError || iOut == eWarning) { + /* Strip \r and \n */ + for (pBufferFrom=pBufferTo=pBuffer; ; pBufferFrom++) { + if (*pBufferFrom == '\r' || *pBufferFrom == '\n') + continue; + *pBufferTo = *pBufferFrom; + if (*pBufferTo == '\0') + break; + pBufferTo++; + } + tmp_json = json_object_new_string(pBuffer); + if (is_error(msg_json)) { linenum = __LINE__; goto reporterr; } + } else { + tmp_json = json_tokener_parse(pBuffer); + if (is_error(msg_json)) { linenum = __LINE__; goto reporterr; } + } + json_object_object_add(msg_json, "data", tmp_json); + return msg_json; + +reporterr: + SCSetWriteFunc(pCon,SCNormalWrite); + snprintf(pError, 256,"%s:%d Error making json object", __FILE__, linenum); + SCWrite(pCon,pError,eError); +cleanup: + if (tmp_json != NULL) + json_object_put(tmp_json); + if (msg_json != NULL) + json_object_put(msg_json); + return NULL; +} + +int SCWriteJSON_String(SConnection *pCon, char *pBuffer, int iOut) +{ + struct json_object *my_object=NULL; + char pBueffel[MAXMSG]; + int iRet; + + if (strlen(pBuffer) == 0) + return 1; + + /* log it for any case */ + if(pCon->pSock) + { + iRet = pCon->pSock->sockid; + } + else + { + iRet = 0; + } + sprintf(pBueffel,"Next line intended for socket: %d",iRet); + SICSLogWrite(pBueffel,eInternal); + SICSLogWrite(pBuffer,iOut); + + /* write to commandlog if user or manager privilege */ + if(SCGetRights(pCon) <= usUser) + { + sprintf(pBueffel,"To sock %d :",iRet); + WriteToCommandLog(pBueffel,pBuffer); + } + + if(SCinMacro(pCon)) + { + InterpWrite(pServ->pSics,pBuffer); + } else { + my_object = mkJSON_Object(pCon, pBuffer, iOut); + iRet = SCDoSockWrite(pCon,json_object_to_json_string(my_object)); + SCWriteToLogFiles(pCon,pBuffer); + } + if (my_object != NULL) + json_object_put(my_object); + return 1; +} /*------------------------------------------------------------------------*/ /* Protocol API */ char * GetProtocolName(SConnection* pCon)