ua_pubsub_networkmessage_json.c 22 KB

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