ua_pubsub_networkmessage_json.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  4. *
  5. * Copyright (c) 2019 Fraunhofer IOSB (Author: Lukas Meling)
  6. */
  7. #include <open62541/types.h>
  8. #include <open62541/types_generated_handling.h>
  9. #include "ua_pubsub_networkmessage.h"
  10. #include "ua_types_encoding_json.h"
  11. /* Json keys for dsm */
  12. const char * UA_DECODEKEY_MESSAGES = ("Messages");
  13. const char * UA_DECODEKEY_MESSAGETYPE = ("MessageType");
  14. const char * UA_DECODEKEY_MESSAGEID = ("MessageId");
  15. const char * UA_DECODEKEY_PUBLISHERID = ("PublisherId");
  16. const char * UA_DECODEKEY_DATASETCLASSID = ("DataSetClassId");
  17. /* Json keys for dsm */
  18. const char * UA_DECODEKEY_DATASETWRITERID = ("DataSetWriterId");
  19. const char * UA_DECODEKEY_SEQUENCENUMBER = ("SequenceNumber");
  20. const char * UA_DECODEKEY_METADATAVERSION = ("MetaDataVersion");
  21. const char * UA_DECODEKEY_TIMESTAMP = ("Timestamp");
  22. const char * UA_DECODEKEY_DSM_STATUS = ("Status");
  23. const char * UA_DECODEKEY_PAYLOAD = ("Payload");
  24. const char * UA_DECODEKEY_DS_TYPE = ("Type");
  25. /* -- json encoding/decoding -- */
  26. static UA_StatusCode writeJsonKey_UA_String(CtxJson *ctx, UA_String *in){
  27. UA_STACKARRAY(char, out, in->length + 1);
  28. memcpy(out, in->data, in->length);
  29. out[in->length] = 0;
  30. return writeJsonKey(ctx, out);
  31. }
  32. static UA_StatusCode
  33. UA_DataSetMessage_encodeJson_internal(const UA_DataSetMessage* src, UA_UInt16 dataSetWriterId,
  34. CtxJson *ctx){
  35. status rv = writeJsonObjStart(ctx);
  36. /* DataSetWriterId */
  37. rv |= writeJsonObjElm(ctx, UA_DECODEKEY_DATASETWRITERID,
  38. &dataSetWriterId, &UA_TYPES[UA_TYPES_UINT16]);
  39. if(rv != UA_STATUSCODE_GOOD)
  40. return rv;
  41. /* DataSetMessageSequenceNr */
  42. if(src->header.dataSetMessageSequenceNrEnabled) {
  43. rv |= writeJsonObjElm(ctx, UA_DECODEKEY_SEQUENCENUMBER,
  44. &src->header.dataSetMessageSequenceNr,
  45. &UA_TYPES[UA_TYPES_UINT16]);
  46. if(rv != UA_STATUSCODE_GOOD)
  47. return rv;
  48. }
  49. /* MetaDataVersion */
  50. if(src->header.configVersionMajorVersionEnabled || src->header.configVersionMinorVersionEnabled) {
  51. UA_ConfigurationVersionDataType cvd;
  52. cvd.majorVersion = src->header.configVersionMajorVersion;
  53. cvd.minorVersion = src->header.configVersionMinorVersion;
  54. rv |= writeJsonObjElm(ctx, UA_DECODEKEY_METADATAVERSION, &cvd,
  55. &UA_TYPES[UA_TYPES_CONFIGURATIONVERSIONDATATYPE]);
  56. if(rv != UA_STATUSCODE_GOOD)
  57. return rv;
  58. }
  59. /* Timestamp */
  60. if(src->header.timestampEnabled) {
  61. rv |= writeJsonObjElm(ctx, UA_DECODEKEY_TIMESTAMP, &src->header.timestamp,
  62. &UA_TYPES[UA_TYPES_DATETIME]);
  63. if(rv != UA_STATUSCODE_GOOD)
  64. return rv;
  65. }
  66. /* Status */
  67. if(src->header.statusEnabled) {
  68. rv |= writeJsonObjElm(ctx, UA_DECODEKEY_DSM_STATUS,
  69. &src->header.status, &UA_TYPES[UA_TYPES_STATUSCODE]);
  70. if(rv != UA_STATUSCODE_GOOD)
  71. return rv;
  72. }
  73. rv |= writeJsonKey(ctx, UA_DECODEKEY_PAYLOAD);
  74. rv |= writeJsonObjStart(ctx);
  75. /* TODO: currently no difference between delta and key frames. Own
  76. * dataSetMessageType for json?. If the field names are not defined, write
  77. * out empty field names. */
  78. if(src->header.dataSetMessageType == UA_DATASETMESSAGE_DATAKEYFRAME) {
  79. if(src->header.fieldEncoding == UA_FIELDENCODING_VARIANT) {
  80. /* KEYFRAME VARIANT */
  81. for (UA_UInt16 i = 0; i < src->data.keyFrameData.fieldCount; i++) {
  82. if(src->data.keyFrameData.fieldNames)
  83. rv |= writeJsonKey_UA_String(ctx, &src->data.keyFrameData.fieldNames[i]);
  84. else
  85. rv |= writeJsonKey(ctx, "");
  86. rv |= encodeJsonInternal(&(src->data.keyFrameData.dataSetFields[i].value),
  87. &UA_TYPES[UA_TYPES_VARIANT], ctx);
  88. if(rv != UA_STATUSCODE_GOOD)
  89. return rv;
  90. }
  91. } else if(src->header.fieldEncoding == UA_FIELDENCODING_DATAVALUE) {
  92. /* KEYFRAME DATAVALUE */
  93. for (UA_UInt16 i = 0; i < src->data.keyFrameData.fieldCount; i++) {
  94. if(src->data.keyFrameData.fieldNames)
  95. rv |= writeJsonKey_UA_String(ctx, &src->data.keyFrameData.fieldNames[i]);
  96. else
  97. rv |= writeJsonKey(ctx, "");
  98. rv |= encodeJsonInternal(&src->data.keyFrameData.dataSetFields[i],
  99. &UA_TYPES[UA_TYPES_DATAVALUE], ctx);
  100. if(rv != UA_STATUSCODE_GOOD)
  101. return rv;
  102. }
  103. } else {
  104. /* RawData */
  105. return UA_STATUSCODE_BADNOTIMPLEMENTED;
  106. }
  107. } else {
  108. /* DeltaFrame */
  109. return UA_STATUSCODE_BADNOTSUPPORTED;
  110. }
  111. rv |= writeJsonObjEnd(ctx); /* Payload */
  112. rv |= writeJsonObjEnd(ctx); /* DataSetMessage */
  113. return rv;
  114. }
  115. static UA_StatusCode
  116. UA_NetworkMessage_encodeJson_internal(const UA_NetworkMessage* src, CtxJson *ctx) {
  117. status rv = UA_STATUSCODE_GOOD;
  118. /* currently only ua-data is supported, no discovery message implemented */
  119. if(src->networkMessageType != UA_NETWORKMESSAGE_DATASET)
  120. return UA_STATUSCODE_BADNOTIMPLEMENTED;
  121. writeJsonObjStart(ctx);
  122. /* Table 91 – JSON NetworkMessage Definition
  123. * MessageId | String | A globally unique identifier for the message.
  124. * This value is mandatory. But we don't check uniqueness in the
  125. * encoding layer. */
  126. rv |= writeJsonObjElm(ctx, UA_DECODEKEY_MESSAGEID,
  127. &src->messageId, &UA_TYPES[UA_TYPES_STRING]);
  128. /* MessageType */
  129. UA_String s = UA_STRING("ua-data");
  130. rv |= writeJsonObjElm(ctx, UA_DECODEKEY_MESSAGETYPE,
  131. &s, &UA_TYPES[UA_TYPES_STRING]);
  132. /* PublisherId */
  133. if(src->publisherIdEnabled) {
  134. rv = writeJsonKey(ctx, UA_DECODEKEY_PUBLISHERID);
  135. switch (src->publisherIdType) {
  136. case UA_PUBLISHERDATATYPE_BYTE:
  137. rv |= encodeJsonInternal(&src->publisherId.publisherIdByte,
  138. &UA_TYPES[UA_TYPES_BYTE], ctx);
  139. break;
  140. case UA_PUBLISHERDATATYPE_UINT16:
  141. rv |= encodeJsonInternal(&src->publisherId.publisherIdUInt16,
  142. &UA_TYPES[UA_TYPES_UINT16], ctx);
  143. break;
  144. case UA_PUBLISHERDATATYPE_UINT32:
  145. rv |= encodeJsonInternal(&src->publisherId.publisherIdUInt32,
  146. &UA_TYPES[UA_TYPES_UINT32], ctx);
  147. break;
  148. case UA_PUBLISHERDATATYPE_UINT64:
  149. rv |= encodeJsonInternal(&src->publisherId.publisherIdUInt64,
  150. &UA_TYPES[UA_TYPES_UINT64], ctx);
  151. break;
  152. case UA_PUBLISHERDATATYPE_STRING:
  153. rv |= encodeJsonInternal(&src->publisherId.publisherIdString,
  154. &UA_TYPES[UA_TYPES_STRING], ctx);
  155. break;
  156. }
  157. }
  158. if(rv != UA_STATUSCODE_GOOD)
  159. return rv;
  160. /* DataSetClassId */
  161. if(src->dataSetClassIdEnabled) {
  162. rv |= writeJsonObjElm(ctx, UA_DECODEKEY_DATASETCLASSID,
  163. &src->dataSetClassId, &UA_TYPES[UA_TYPES_GUID]);
  164. if(rv != UA_STATUSCODE_GOOD)
  165. return rv;
  166. }
  167. /* Payload: DataSetMessages */
  168. UA_Byte count = src->payloadHeader.dataSetPayloadHeader.count;
  169. if(count > 0){
  170. UA_UInt16 *dataSetWriterIds = src->payloadHeader.dataSetPayloadHeader.dataSetWriterIds;
  171. if(!dataSetWriterIds){
  172. return UA_STATUSCODE_BADENCODINGERROR;
  173. }
  174. rv |= writeJsonKey(ctx, UA_DECODEKEY_MESSAGES);
  175. rv |= writeJsonArrStart(ctx); /* start array */
  176. for (UA_UInt16 i = 0; i < count; i++) {
  177. writeJsonCommaIfNeeded(ctx);
  178. rv |= UA_DataSetMessage_encodeJson_internal(&src->payload.dataSetPayload.dataSetMessages[i],
  179. dataSetWriterIds[i], ctx);
  180. if(rv != UA_STATUSCODE_GOOD)
  181. return rv;
  182. /* comma is needed if more dsm are present */
  183. ctx->commaNeeded[ctx->depth] = true;
  184. }
  185. rv |= writeJsonArrEnd(ctx); /* end array */
  186. }
  187. rv |= writeJsonObjEnd(ctx);
  188. return rv;
  189. }
  190. UA_StatusCode
  191. UA_NetworkMessage_encodeJson(const UA_NetworkMessage *src,
  192. UA_Byte **bufPos, const UA_Byte **bufEnd, UA_String *namespaces,
  193. size_t namespaceSize, UA_String *serverUris,
  194. size_t serverUriSize, UA_Boolean useReversible) {
  195. /* Set up the context */
  196. CtxJson ctx;
  197. memset(&ctx, 0, sizeof(ctx));
  198. ctx.pos = *bufPos;
  199. ctx.end = *bufEnd;
  200. ctx.depth = 0;
  201. ctx.namespaces = namespaces;
  202. ctx.namespacesSize = namespaceSize;
  203. ctx.serverUris = serverUris;
  204. ctx.serverUrisSize = serverUriSize;
  205. ctx.useReversible = useReversible;
  206. ctx.calcOnly = false;
  207. status ret = UA_NetworkMessage_encodeJson_internal(src, &ctx);
  208. *bufPos = ctx.pos;
  209. *bufEnd = ctx.end;
  210. return ret;
  211. }
  212. size_t
  213. UA_NetworkMessage_calcSizeJson(const UA_NetworkMessage *src,
  214. UA_String *namespaces, size_t namespaceSize,
  215. UA_String *serverUris, size_t serverUriSize,
  216. UA_Boolean useReversible){
  217. /* Set up the context */
  218. CtxJson ctx;
  219. memset(&ctx, 0, sizeof(ctx));
  220. ctx.pos = 0;
  221. ctx.end = (const UA_Byte*)(uintptr_t)SIZE_MAX;
  222. ctx.depth = 0;
  223. ctx.namespaces = namespaces;
  224. ctx.namespacesSize = namespaceSize;
  225. ctx.serverUris = serverUris;
  226. ctx.serverUrisSize = serverUriSize;
  227. ctx.useReversible = useReversible;
  228. ctx.calcOnly = true;
  229. status ret = UA_NetworkMessage_encodeJson_internal(src, &ctx);
  230. if(ret != UA_STATUSCODE_GOOD)
  231. return 0;
  232. return (size_t)ctx.pos;
  233. }
  234. /* decode json */
  235. static status
  236. MetaDataVersion_decodeJsonInternal(void* cvd, const UA_DataType *type, CtxJson *ctx,
  237. ParseCtx *parseCtx, UA_Boolean moveToken){
  238. return decodeJsonInternal(cvd, &UA_TYPES[UA_TYPES_CONFIGURATIONVERSIONDATATYPE],
  239. ctx, parseCtx, UA_TRUE);
  240. }
  241. static status
  242. DataSetPayload_decodeJsonInternal(void* dsmP, const UA_DataType *type, CtxJson *ctx,
  243. ParseCtx *parseCtx, UA_Boolean moveToken) {
  244. UA_DataSetMessage* dsm = (UA_DataSetMessage*)dsmP;
  245. dsm->header.dataSetMessageValid = UA_TRUE;
  246. if(isJsonNull(ctx, parseCtx)) {
  247. parseCtx->index++;
  248. return UA_STATUSCODE_GOOD;
  249. }
  250. size_t length = (size_t)parseCtx->tokenArray[parseCtx->index].size;
  251. UA_String *fieldNames = (UA_String*)UA_calloc(length, sizeof(UA_String));
  252. dsm->data.keyFrameData.fieldNames = fieldNames;
  253. dsm->data.keyFrameData.fieldCount = (UA_UInt16)length;
  254. dsm->data.keyFrameData.dataSetFields = (UA_DataValue *)
  255. UA_Array_new(dsm->data.keyFrameData.fieldCount, &UA_TYPES[UA_TYPES_DATAVALUE]);
  256. status ret = UA_STATUSCODE_GOOD;
  257. parseCtx->index++; // We go to first Object key!
  258. /* iterate over the key/value pairs in the object. Keys are stored in fieldnames. */
  259. for(size_t i = 0; i < length; ++i) {
  260. ret = getDecodeSignature(UA_TYPES_STRING)(&fieldNames[i], type, ctx, parseCtx, UA_TRUE);
  261. if(ret != UA_STATUSCODE_GOOD)
  262. return ret;
  263. //TODO: Is field value a variant or datavalue? Current check if type and body present.
  264. size_t searchResult = 0;
  265. status foundType = lookAheadForKey("Type", ctx, parseCtx, &searchResult);
  266. status foundBody = lookAheadForKey("Body", ctx, parseCtx, &searchResult);
  267. if(foundType == UA_STATUSCODE_GOOD && foundBody == UA_STATUSCODE_GOOD){
  268. dsm->header.fieldEncoding = UA_FIELDENCODING_VARIANT;
  269. ret = getDecodeSignature(UA_TYPES_VARIANT)
  270. (&dsm->data.keyFrameData.dataSetFields[i].value, type, ctx, parseCtx, UA_TRUE);
  271. dsm->data.keyFrameData.dataSetFields[i].hasValue = UA_TRUE;
  272. } else {
  273. dsm->header.fieldEncoding = UA_FIELDENCODING_DATAVALUE;
  274. ret = getDecodeSignature(UA_TYPES_DATAVALUE)
  275. (&dsm->data.keyFrameData.dataSetFields[i], type, ctx, parseCtx, UA_TRUE);
  276. dsm->data.keyFrameData.dataSetFields[i].hasValue = UA_TRUE;
  277. }
  278. if(ret != UA_STATUSCODE_GOOD)
  279. return ret;
  280. }
  281. return ret;
  282. }
  283. static status
  284. DatasetMessage_Payload_decodeJsonInternal(UA_DataSetMessage* dsm, const UA_DataType *type,
  285. CtxJson *ctx, ParseCtx *parseCtx, UA_Boolean moveToken) {
  286. UA_ConfigurationVersionDataType cvd;
  287. UA_UInt16 dataSetWriterId; /* the id is currently not processed */
  288. dsm->header.fieldEncoding = UA_FIELDENCODING_DATAVALUE;
  289. DecodeEntry entries[6] = {
  290. {UA_DECODEKEY_DATASETWRITERID, &dataSetWriterId,
  291. getDecodeSignature(UA_TYPES_UINT16), false, NULL},
  292. {UA_DECODEKEY_SEQUENCENUMBER, &dsm->header.dataSetMessageSequenceNr,
  293. getDecodeSignature(UA_TYPES_UINT16), false, NULL},
  294. {UA_DECODEKEY_METADATAVERSION, &cvd,
  295. &MetaDataVersion_decodeJsonInternal, false, NULL},
  296. {UA_DECODEKEY_TIMESTAMP, &dsm->header.timestamp,
  297. getDecodeSignature(UA_TYPES_DATETIME), false, NULL},
  298. {UA_DECODEKEY_DSM_STATUS, &dsm->header.status,
  299. getDecodeSignature(UA_TYPES_UINT16), false, NULL},
  300. {UA_DECODEKEY_PAYLOAD, dsm,
  301. &DataSetPayload_decodeJsonInternal, false, NULL}
  302. };
  303. status ret = decodeFields(ctx, parseCtx, entries, 6, NULL);
  304. if(ret != UA_STATUSCODE_GOOD || !entries[0].found){
  305. /* no dataSetwriterid. Is mandatory. Abort. */
  306. return UA_STATUSCODE_BADDECODINGERROR;
  307. }else{
  308. if(parseCtx->custom != NULL){
  309. UA_UInt16* dataSetWriterIdsArray = (UA_UInt16*)parseCtx->custom;
  310. if(*parseCtx->currentCustomIndex < parseCtx->numCustom){
  311. dataSetWriterIdsArray[*parseCtx->currentCustomIndex] = dataSetWriterId;
  312. (*parseCtx->currentCustomIndex)++;
  313. }else{
  314. return UA_STATUSCODE_BADDECODINGERROR;
  315. }
  316. }else{
  317. return UA_STATUSCODE_BADDECODINGERROR;
  318. }
  319. }
  320. dsm->header.dataSetMessageSequenceNrEnabled = entries[1].found;
  321. dsm->header.configVersionMajorVersion = cvd.majorVersion;
  322. dsm->header.configVersionMinorVersion = cvd.minorVersion;
  323. dsm->header.configVersionMajorVersionEnabled = entries[2].found;
  324. dsm->header.configVersionMinorVersionEnabled = entries[2].found;
  325. dsm->header.timestampEnabled = entries[3].found;
  326. dsm->header.statusEnabled = entries[4].found;
  327. if(!entries[5].found){
  328. /* No payload found */
  329. return UA_STATUSCODE_BADDECODINGERROR;
  330. }
  331. dsm->header.dataSetMessageType = UA_DATASETMESSAGE_DATAKEYFRAME;
  332. dsm->header.picoSecondsIncluded = UA_FALSE;
  333. dsm->header.dataSetMessageValid = UA_TRUE;
  334. dsm->header.fieldEncoding = UA_FIELDENCODING_VARIANT;
  335. return ret;
  336. }
  337. static status
  338. DatasetMessage_Array_decodeJsonInternal(void *UA_RESTRICT dst, const UA_DataType *type,
  339. CtxJson *ctx, ParseCtx *parseCtx, UA_Boolean moveToken) {
  340. /* Array! */
  341. if(getJsmnType(parseCtx) != JSMN_ARRAY)
  342. return UA_STATUSCODE_BADDECODINGERROR;
  343. size_t length = (size_t)parseCtx->tokenArray[parseCtx->index].size;
  344. /* Return early for empty arrays */
  345. if(length == 0)
  346. return UA_STATUSCODE_GOOD;
  347. /* Allocate memory */
  348. UA_DataSetMessage *dsm = (UA_DataSetMessage*)UA_calloc(length, sizeof(UA_DataSetMessage));
  349. if(dsm == NULL)
  350. return UA_STATUSCODE_BADOUTOFMEMORY;
  351. /* Copy new Pointer do dest */
  352. memcpy(dst, &dsm, sizeof(void*));
  353. /* We go to first Array member! */
  354. parseCtx->index++;
  355. status ret = UA_STATUSCODE_BADDECODINGERROR;
  356. /* Decode array members */
  357. for(size_t i = 0; i < length; ++i) {
  358. ret = DatasetMessage_Payload_decodeJsonInternal(&dsm[i], NULL, ctx, parseCtx, UA_TRUE);
  359. if(ret != UA_STATUSCODE_GOOD)
  360. return ret;
  361. }
  362. return ret;
  363. }
  364. static status NetworkMessage_decodeJsonInternal(UA_NetworkMessage *dst, CtxJson *ctx,
  365. ParseCtx *parseCtx) {
  366. memset(dst, 0, sizeof(UA_NetworkMessage));
  367. dst->chunkMessage = UA_FALSE;
  368. dst->groupHeaderEnabled = UA_FALSE;
  369. dst->payloadHeaderEnabled = UA_FALSE;
  370. dst->picosecondsEnabled = UA_FALSE;
  371. dst->promotedFieldsEnabled = UA_FALSE;
  372. /* Look forward for publisheId, if present check if type if primitve (Number) or String. */
  373. u8 publishIdTypeIndex = UA_TYPES_STRING;
  374. size_t searchResultPublishIdType = 0;
  375. status found = lookAheadForKey(UA_DECODEKEY_PUBLISHERID, ctx,
  376. parseCtx, &searchResultPublishIdType);
  377. if(found == UA_STATUSCODE_GOOD) {
  378. jsmntok_t publishIdToken = parseCtx->tokenArray[searchResultPublishIdType];
  379. if(publishIdToken.type == JSMN_PRIMITIVE) {
  380. publishIdTypeIndex = UA_TYPES_UINT64;
  381. dst->publisherIdType = UA_PUBLISHERDATATYPE_UINT64; //store in biggest possible
  382. } else if(publishIdToken.type == JSMN_STRING) {
  383. publishIdTypeIndex = UA_TYPES_STRING;
  384. dst->publisherIdType = UA_PUBLISHERDATATYPE_STRING;
  385. } else {
  386. return UA_STATUSCODE_BADDECODINGERROR;
  387. }
  388. }
  389. /* Is Messages an Array? How big? */
  390. size_t messageCount = 0;
  391. size_t searchResultMessages = 0;
  392. found = lookAheadForKey(UA_DECODEKEY_MESSAGES, ctx, parseCtx, &searchResultMessages);
  393. if(found != UA_STATUSCODE_GOOD)
  394. return UA_STATUSCODE_BADNOTIMPLEMENTED;
  395. jsmntok_t bodyToken = parseCtx->tokenArray[searchResultMessages];
  396. if(bodyToken.type != JSMN_ARRAY)
  397. return UA_STATUSCODE_BADNOTIMPLEMENTED;
  398. messageCount = (size_t)parseCtx->tokenArray[searchResultMessages].size;
  399. /* Set up custom context for the dataSetwriterId */
  400. size_t currentCustomIndex = 0;
  401. parseCtx->custom = (void*)UA_calloc(messageCount, sizeof(UA_UInt16));
  402. parseCtx->currentCustomIndex = &currentCustomIndex;
  403. parseCtx->numCustom = messageCount;
  404. /* MessageType */
  405. UA_Boolean isUaData = UA_TRUE;
  406. size_t searchResultMessageType = 0;
  407. found = lookAheadForKey(UA_DECODEKEY_MESSAGETYPE, ctx, parseCtx, &searchResultMessageType);
  408. if(found != UA_STATUSCODE_GOOD)
  409. return UA_STATUSCODE_BADDECODINGERROR;
  410. size_t size = (size_t)(parseCtx->tokenArray[searchResultMessageType].end - parseCtx->tokenArray[searchResultMessageType].start);
  411. char* msgType = (char*)(ctx->pos + parseCtx->tokenArray[searchResultMessageType].start);
  412. if(size == 7) { //ua-data
  413. if(strncmp(msgType, "ua-data", size) != 0)
  414. return UA_STATUSCODE_BADDECODINGERROR;
  415. isUaData = UA_TRUE;
  416. } else if(size == 11) { //ua-metadata
  417. if(strncmp(msgType, "ua-metadata", size) != 0)
  418. return UA_STATUSCODE_BADDECODINGERROR;
  419. isUaData = UA_FALSE;
  420. } else {
  421. return UA_STATUSCODE_BADDECODINGERROR;
  422. }
  423. //TODO: MetaData
  424. if(!isUaData)
  425. return UA_STATUSCODE_BADNOTIMPLEMENTED;
  426. /* Network Message */
  427. UA_String messageType;
  428. DecodeEntry entries[5] = {
  429. {UA_DECODEKEY_MESSAGEID, &dst->messageId, getDecodeSignature(UA_TYPES_STRING), false, NULL},
  430. {UA_DECODEKEY_MESSAGETYPE, &messageType, NULL, false, NULL},
  431. {UA_DECODEKEY_PUBLISHERID, &dst->publisherId.publisherIdString, getDecodeSignature(publishIdTypeIndex), false, NULL},
  432. {UA_DECODEKEY_DATASETCLASSID, &dst->dataSetClassId, getDecodeSignature(UA_TYPES_GUID), false, NULL},
  433. {UA_DECODEKEY_MESSAGES, &dst->payload.dataSetPayload.dataSetMessages, &DatasetMessage_Array_decodeJsonInternal, false, NULL}
  434. };
  435. //Store publisherId in correct union
  436. if(publishIdTypeIndex == UA_TYPES_UINT64)
  437. entries[2].fieldPointer = &dst->publisherId.publisherIdUInt64;
  438. status ret = decodeFields(ctx, parseCtx, entries, 5, NULL);
  439. if(ret != UA_STATUSCODE_GOOD)
  440. return ret;
  441. dst->messageIdEnabled = entries[0].found;
  442. dst->publisherIdEnabled = entries[2].found;
  443. if(dst->publisherIdEnabled)
  444. dst->publisherIdType = UA_PUBLISHERDATATYPE_STRING;
  445. dst->dataSetClassIdEnabled = entries[3].found;
  446. dst->payloadHeaderEnabled = UA_TRUE;
  447. dst->payloadHeader.dataSetPayloadHeader.count = (UA_Byte)messageCount;
  448. //Set the dataSetWriterIds. They are filled in the dataSet decoding.
  449. dst->payloadHeader.dataSetPayloadHeader.dataSetWriterIds = (UA_UInt16*)parseCtx->custom;
  450. return ret;
  451. }
  452. status UA_NetworkMessage_decodeJson(UA_NetworkMessage *dst, const UA_ByteString *src){
  453. /* Set up the context */
  454. CtxJson ctx;
  455. memset(&ctx, 0, sizeof(CtxJson));
  456. ParseCtx parseCtx;
  457. memset(&parseCtx, 0, sizeof(ParseCtx));
  458. parseCtx.tokenArray = (jsmntok_t*)malloc(sizeof(jsmntok_t) * TOKENCOUNT);
  459. memset(parseCtx.tokenArray, 0, sizeof(jsmntok_t) * TOKENCOUNT);
  460. status ret = tokenize(&parseCtx, &ctx, src);
  461. if(ret != UA_STATUSCODE_GOOD){
  462. return ret;
  463. }
  464. ret = NetworkMessage_decodeJsonInternal(dst, &ctx, &parseCtx);
  465. free(parseCtx.tokenArray);
  466. return ret;
  467. }