ua_pubsub_networkmessage_json.c 21 KB

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