ua_types_encoding_binary.c 61 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765
  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 2014-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
  6. * Copyright 2014-2017 (c) Florian Palm
  7. * Copyright 2014-2016 (c) Sten Grüner
  8. * Copyright 2014 (c) Leon Urbas
  9. * Copyright 2015 (c) LEvertz
  10. * Copyright 2015 (c) Chris Iatrou
  11. * Copyright 2015-2016 (c) Oleksiy Vasylyev
  12. * Copyright 2016-2017 (c) Stefan Profanter, fortiss GmbH
  13. * Copyright 2016 (c) Lorenz Haas
  14. * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
  15. * Copyright 2017 (c) Henrik Norrman
  16. */
  17. #include "ua_types_encoding_binary.h"
  18. #include <open62541/types_generated.h>
  19. #include <open62541/types_generated_handling.h>
  20. #include "ua_util_internal.h"
  21. /**
  22. * Type Encoding and Decoding
  23. * --------------------------
  24. * The following methods contain encoding and decoding functions for the builtin
  25. * data types and generic functions that operate on all types and arrays. This
  26. * requires the type description from a UA_DataType structure.
  27. *
  28. * Encoding Context
  29. * ^^^^^^^^^^^^^^^^
  30. * If possible, the encoding context is stored in a thread-local variable to
  31. * speed up encoding. If thread-local variables are not supported, the context
  32. * is "looped through" every method call. The ``_``-macro accesses either the
  33. * thread-local or the "looped through" context . */
  34. /* Part 6 §5.1.5: Decoders shall support at least 100 nesting levels */
  35. #define UA_ENCODING_MAX_RECURSION 100
  36. typedef struct {
  37. /* Pointers to the current position and the last position in the buffer */
  38. u8 *pos;
  39. const u8 *end;
  40. u8 **oldpos; /* Sentinel for a lower stacktrace exchanging the buffer */
  41. u16 depth; /* How often did we en-/decoding recurse? */
  42. const UA_DataTypeArray *customTypes;
  43. UA_exchangeEncodeBuffer exchangeBufferCallback;
  44. void *exchangeBufferCallbackHandle;
  45. } Ctx;
  46. typedef status
  47. (*encodeBinarySignature)(const void *UA_RESTRICT src, const UA_DataType *type,
  48. Ctx *UA_RESTRICT ctx);
  49. typedef status
  50. (*decodeBinarySignature)(void *UA_RESTRICT dst, const UA_DataType *type,
  51. Ctx *UA_RESTRICT ctx);
  52. typedef size_t
  53. (*calcSizeBinarySignature)(const void *UA_RESTRICT p, const UA_DataType *contenttype);
  54. #define ENCODE_BINARY(TYPE) static status \
  55. TYPE##_encodeBinary(const UA_##TYPE *UA_RESTRICT src, \
  56. const UA_DataType *type, Ctx *UA_RESTRICT ctx)
  57. #define DECODE_BINARY(TYPE) static status \
  58. TYPE##_decodeBinary(UA_##TYPE *UA_RESTRICT dst, \
  59. const UA_DataType *type, Ctx *UA_RESTRICT ctx)
  60. #define CALCSIZE_BINARY(TYPE) static size_t \
  61. TYPE##_calcSizeBinary(const UA_##TYPE *UA_RESTRICT src, \
  62. const UA_DataType *_)
  63. #define ENCODE_DIRECT(SRC, TYPE) TYPE##_encodeBinary((const UA_##TYPE*)SRC, NULL, ctx)
  64. #define DECODE_DIRECT(DST, TYPE) TYPE##_decodeBinary((UA_##TYPE*)DST, NULL, ctx)
  65. /* Jumptables for de-/encoding and computing the buffer length. The methods in
  66. * the decoding jumptable do not all clean up their allocated memory when an
  67. * error occurs. So a final _clear needs to be called before returning to the
  68. * user. */
  69. extern const encodeBinarySignature encodeBinaryJumpTable[UA_DATATYPEKINDS];
  70. extern const decodeBinarySignature decodeBinaryJumpTable[UA_DATATYPEKINDS];
  71. extern const calcSizeBinarySignature calcSizeBinaryJumpTable[UA_DATATYPEKINDS];
  72. /* Breaking a message up into chunks is integrated with the encoding. When the
  73. * end of a buffer is reached, a callback is executed that sends the current
  74. * buffer as a chunk and exchanges the encoding buffer "underneath" the ongoing
  75. * encoding. This reduces the RAM requirements and unnecessary copying. */
  76. /* Send the current chunk and replace the buffer */
  77. static status exchangeBuffer(Ctx *ctx) {
  78. if(!ctx->exchangeBufferCallback)
  79. return UA_STATUSCODE_BADENCODINGERROR;
  80. return ctx->exchangeBufferCallback(ctx->exchangeBufferCallbackHandle,
  81. &ctx->pos, &ctx->end);
  82. }
  83. /* If encoding fails, exchange the buffer and try again. */
  84. static status
  85. encodeWithExchangeBuffer(const void *ptr, const UA_DataType *type, Ctx *ctx) {
  86. u8 *oldpos = ctx->pos; /* Last known good position */
  87. ctx->oldpos = &oldpos;
  88. status ret = encodeBinaryJumpTable[type->typeKind](ptr, type, ctx);
  89. if(ret == UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED && ctx->oldpos == &oldpos) {
  90. ctx->pos = oldpos; /* Send the position to the last known good position
  91. * and switch */
  92. ret = exchangeBuffer(ctx);
  93. if(ret != UA_STATUSCODE_GOOD)
  94. return ret;
  95. ret = encodeBinaryJumpTable[type->typeKind](ptr, type, ctx);
  96. }
  97. return ret;
  98. }
  99. #define ENCODE_WITHEXCHANGE(VAR, TYPE) \
  100. encodeWithExchangeBuffer((const void*)VAR, &UA_TYPES[TYPE], ctx)
  101. /*****************/
  102. /* Integer Types */
  103. /*****************/
  104. #if !UA_BINARY_OVERLAYABLE_INTEGER
  105. #pragma message "Integer endianness could not be detected to be little endian. Use slow generic encoding."
  106. /* These en/decoding functions are only used when the architecture isn't little-endian. */
  107. static void
  108. UA_encode16(const u16 v, u8 buf[2]) {
  109. buf[0] = (u8)v;
  110. buf[1] = (u8)(v >> 8);
  111. }
  112. static void
  113. UA_decode16(const u8 buf[2], u16 *v) {
  114. *v = (u16)((u16)buf[0] + (((u16)buf[1]) << 8));
  115. }
  116. static void
  117. UA_encode32(const u32 v, u8 buf[4]) {
  118. buf[0] = (u8)v;
  119. buf[1] = (u8)(v >> 8);
  120. buf[2] = (u8)(v >> 16);
  121. buf[3] = (u8)(v >> 24);
  122. }
  123. static void
  124. UA_decode32(const u8 buf[4], u32 *v) {
  125. *v = (u32)((u32)buf[0] + (((u32)buf[1]) << 8) +
  126. (((u32)buf[2]) << 16) + (((u32)buf[3]) << 24));
  127. }
  128. static void
  129. UA_encode64(const u64 v, u8 buf[8]) {
  130. buf[0] = (u8)v;
  131. buf[1] = (u8)(v >> 8);
  132. buf[2] = (u8)(v >> 16);
  133. buf[3] = (u8)(v >> 24);
  134. buf[4] = (u8)(v >> 32);
  135. buf[5] = (u8)(v >> 40);
  136. buf[6] = (u8)(v >> 48);
  137. buf[7] = (u8)(v >> 56);
  138. }
  139. static void
  140. UA_decode64(const u8 buf[8], u64 *v) {
  141. *v = (u64)((u64)buf[0] + (((u64)buf[1]) << 8) +
  142. (((u64)buf[2]) << 16) + (((u64)buf[3]) << 24) +
  143. (((u64)buf[4]) << 32) + (((u64)buf[5]) << 40) +
  144. (((u64)buf[6]) << 48) + (((u64)buf[7]) << 56));
  145. }
  146. #endif /* !UA_BINARY_OVERLAYABLE_INTEGER */
  147. /* Boolean */
  148. /* Note that sizeof(bool) != 1 on some platforms. Overlayable integer encoding
  149. * is disabled in those cases. */
  150. ENCODE_BINARY(Boolean) {
  151. if(ctx->pos + 1 > ctx->end)
  152. return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
  153. *ctx->pos = *(const u8*)src;
  154. ++ctx->pos;
  155. return UA_STATUSCODE_GOOD;
  156. }
  157. DECODE_BINARY(Boolean) {
  158. if(ctx->pos + 1 > ctx->end)
  159. return UA_STATUSCODE_BADDECODINGERROR;
  160. *dst = (*ctx->pos > 0) ? true : false;
  161. ++ctx->pos;
  162. return UA_STATUSCODE_GOOD;
  163. }
  164. /* Byte */
  165. ENCODE_BINARY(Byte) {
  166. if(ctx->pos + sizeof(u8) > ctx->end)
  167. return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
  168. *ctx->pos = *(const u8*)src;
  169. ++ctx->pos;
  170. return UA_STATUSCODE_GOOD;
  171. }
  172. DECODE_BINARY(Byte) {
  173. if(ctx->pos + sizeof(u8) > ctx->end)
  174. return UA_STATUSCODE_BADDECODINGERROR;
  175. *dst = *ctx->pos;
  176. ++ctx->pos;
  177. return UA_STATUSCODE_GOOD;
  178. }
  179. /* UInt16 */
  180. ENCODE_BINARY(UInt16) {
  181. if(ctx->pos + sizeof(u16) > ctx->end)
  182. return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
  183. #if UA_BINARY_OVERLAYABLE_INTEGER
  184. memcpy(ctx->pos, src, sizeof(u16));
  185. #else
  186. UA_encode16(*src, ctx->pos);
  187. #endif
  188. ctx->pos += 2;
  189. return UA_STATUSCODE_GOOD;
  190. }
  191. DECODE_BINARY(UInt16) {
  192. if(ctx->pos + sizeof(u16) > ctx->end)
  193. return UA_STATUSCODE_BADDECODINGERROR;
  194. #if UA_BINARY_OVERLAYABLE_INTEGER
  195. memcpy(dst, ctx->pos, sizeof(u16));
  196. #else
  197. UA_decode16(ctx->pos, dst);
  198. #endif
  199. ctx->pos += 2;
  200. return UA_STATUSCODE_GOOD;
  201. }
  202. /* UInt32 */
  203. ENCODE_BINARY(UInt32) {
  204. if(ctx->pos + sizeof(u32) > ctx->end)
  205. return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
  206. #if UA_BINARY_OVERLAYABLE_INTEGER
  207. memcpy(ctx->pos, src, sizeof(u32));
  208. #else
  209. UA_encode32(*src, ctx->pos);
  210. #endif
  211. ctx->pos += 4;
  212. return UA_STATUSCODE_GOOD;
  213. }
  214. DECODE_BINARY(UInt32) {
  215. if(ctx->pos + sizeof(u32) > ctx->end)
  216. return UA_STATUSCODE_BADDECODINGERROR;
  217. #if UA_BINARY_OVERLAYABLE_INTEGER
  218. memcpy(dst, ctx->pos, sizeof(u32));
  219. #else
  220. UA_decode32(ctx->pos, dst);
  221. #endif
  222. ctx->pos += 4;
  223. return UA_STATUSCODE_GOOD;
  224. }
  225. /* UInt64 */
  226. ENCODE_BINARY(UInt64) {
  227. if(ctx->pos + sizeof(u64) > ctx->end)
  228. return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
  229. #if UA_BINARY_OVERLAYABLE_INTEGER
  230. memcpy(ctx->pos, src, sizeof(u64));
  231. #else
  232. UA_encode64(*src, ctx->pos);
  233. #endif
  234. ctx->pos += 8;
  235. return UA_STATUSCODE_GOOD;
  236. }
  237. DECODE_BINARY(UInt64) {
  238. if(ctx->pos + sizeof(u64) > ctx->end)
  239. return UA_STATUSCODE_BADDECODINGERROR;
  240. #if UA_BINARY_OVERLAYABLE_INTEGER
  241. memcpy(dst, ctx->pos, sizeof(u64));
  242. #else
  243. UA_decode64(ctx->pos, dst);
  244. #endif
  245. ctx->pos += 8;
  246. return UA_STATUSCODE_GOOD;
  247. }
  248. /************************/
  249. /* Floating Point Types */
  250. /************************/
  251. /* Can we reuse the integer encoding mechanism by casting floating point
  252. * values? */
  253. #if (UA_FLOAT_IEEE754 == 1) && (UA_LITTLE_ENDIAN == UA_FLOAT_LITTLE_ENDIAN)
  254. # define Float_encodeBinary UInt32_encodeBinary
  255. # define Float_decodeBinary UInt32_decodeBinary
  256. # define Double_encodeBinary UInt64_encodeBinary
  257. # define Double_decodeBinary UInt64_decodeBinary
  258. #else
  259. #include <math.h>
  260. #pragma message "No native IEEE 754 format detected. Use slow generic encoding."
  261. /* Handling of IEEE754 floating point values was taken from Beej's Guide to
  262. * Network Programming (http://beej.us/guide/bgnet/) and enhanced to cover the
  263. * edge cases +/-0, +/-inf and nan. */
  264. static uint64_t
  265. pack754(long double f, unsigned bits, unsigned expbits) {
  266. unsigned significandbits = bits - expbits - 1;
  267. long double fnorm;
  268. long long sign;
  269. if(f < 0) { sign = 1; fnorm = -f; }
  270. else { sign = 0; fnorm = f; }
  271. int shift = 0;
  272. while(fnorm >= 2.0) { fnorm /= 2.0; ++shift; }
  273. while(fnorm < 1.0) { fnorm *= 2.0; --shift; }
  274. fnorm = fnorm - 1.0;
  275. long long significand = (long long)(fnorm * ((float)(1LL<<significandbits) + 0.5f));
  276. long long exponent = shift + ((1<<(expbits-1)) - 1);
  277. return (uint64_t)((sign<<(bits-1)) | (exponent<<(bits-expbits-1)) | significand);
  278. }
  279. static long double
  280. unpack754(uint64_t i, unsigned bits, unsigned expbits) {
  281. unsigned significandbits = bits - expbits - 1;
  282. long double result = (long double)(i&(uint64_t)((1LL<<significandbits)-1));
  283. result /= (1LL<<significandbits);
  284. result += 1.0f;
  285. unsigned bias = (unsigned)(1<<(expbits-1)) - 1;
  286. long long shift = (long long)((i>>significandbits) & (uint64_t)((1LL<<expbits)-1)) - bias;
  287. while(shift > 0) { result *= 2.0; --shift; }
  288. while(shift < 0) { result /= 2.0; ++shift; }
  289. result *= ((i>>(bits-1))&1)? -1.0: 1.0;
  290. return result;
  291. }
  292. /* Float */
  293. #define FLOAT_NAN 0xffc00000
  294. #define FLOAT_INF 0x7f800000
  295. #define FLOAT_NEG_INF 0xff800000
  296. #define FLOAT_NEG_ZERO 0x80000000
  297. ENCODE_BINARY(Float) {
  298. UA_Float f = *src;
  299. u32 encoded;
  300. /* cppcheck-suppress duplicateExpression */
  301. if(f != f) encoded = FLOAT_NAN;
  302. else if(f == 0.0f) encoded = signbit(f) ? FLOAT_NEG_ZERO : 0;
  303. else if(f/f != f/f) encoded = f > 0 ? FLOAT_INF : FLOAT_NEG_INF;
  304. else encoded = (u32)pack754(f, 32, 8);
  305. return ENCODE_DIRECT(&encoded, UInt32);
  306. }
  307. DECODE_BINARY(Float) {
  308. u32 decoded;
  309. status ret = DECODE_DIRECT(&decoded, UInt32);
  310. if(ret != UA_STATUSCODE_GOOD)
  311. return ret;
  312. if(decoded == 0) *dst = 0.0f;
  313. else if(decoded == FLOAT_NEG_ZERO) *dst = -0.0f;
  314. else if(decoded == FLOAT_INF) *dst = INFINITY;
  315. else if(decoded == FLOAT_NEG_INF) *dst = -INFINITY;
  316. else if((decoded >= 0x7f800001 && decoded <= 0x7fffffff) ||
  317. (decoded >= 0xff800001)) *dst = NAN;
  318. else *dst = (UA_Float)unpack754(decoded, 32, 8);
  319. return UA_STATUSCODE_GOOD;
  320. }
  321. /* Double */
  322. #define DOUBLE_NAN 0xfff8000000000000L
  323. #define DOUBLE_INF 0x7ff0000000000000L
  324. #define DOUBLE_NEG_INF 0xfff0000000000000L
  325. #define DOUBLE_NEG_ZERO 0x8000000000000000L
  326. ENCODE_BINARY(Double) {
  327. UA_Double d = *src;
  328. u64 encoded;
  329. /* cppcheck-suppress duplicateExpression */
  330. if(d != d) encoded = DOUBLE_NAN;
  331. else if(d == 0.0) encoded = signbit(d) ? DOUBLE_NEG_ZERO : 0;
  332. else if(d/d != d/d) encoded = d > 0 ? DOUBLE_INF : DOUBLE_NEG_INF;
  333. else encoded = pack754(d, 64, 11);
  334. return ENCODE_DIRECT(&encoded, UInt64);
  335. }
  336. DECODE_BINARY(Double) {
  337. u64 decoded;
  338. status ret = DECODE_DIRECT(&decoded, UInt64);
  339. if(ret != UA_STATUSCODE_GOOD)
  340. return ret;
  341. if(decoded == 0) *dst = 0.0;
  342. else if(decoded == DOUBLE_NEG_ZERO) *dst = -0.0;
  343. else if(decoded == DOUBLE_INF) *dst = INFINITY;
  344. else if(decoded == DOUBLE_NEG_INF) *dst = -INFINITY;
  345. else if((decoded >= 0x7ff0000000000001L && decoded <= 0x7fffffffffffffffL) ||
  346. (decoded >= 0xfff0000000000001L)) *dst = NAN;
  347. else *dst = (UA_Double)unpack754(decoded, 64, 11);
  348. return UA_STATUSCODE_GOOD;
  349. }
  350. #endif
  351. /******************/
  352. /* Array Handling */
  353. /******************/
  354. static status
  355. Array_encodeBinaryOverlayable(uintptr_t ptr, size_t length,
  356. size_t elementMemSize, Ctx *ctx) {
  357. /* Store the number of already encoded elements */
  358. size_t finished = 0;
  359. /* Loop as long as more elements remain than fit into the chunk */
  360. while(ctx->end < ctx->pos + (elementMemSize * (length-finished))) {
  361. size_t possible = ((uintptr_t)ctx->end - (uintptr_t)ctx->pos) / (sizeof(u8) * elementMemSize);
  362. size_t possibleMem = possible * elementMemSize;
  363. memcpy(ctx->pos, (void*)ptr, possibleMem);
  364. ctx->pos += possibleMem;
  365. ptr += possibleMem;
  366. finished += possible;
  367. status ret = exchangeBuffer(ctx);
  368. ctx->oldpos = NULL; /* Set the sentinel so that no upper stack frame
  369. * with a saved pos attempts to exchange from an
  370. * invalid position in the old buffer. */
  371. if(ret != UA_STATUSCODE_GOOD)
  372. return ret;
  373. }
  374. /* Encode the remaining elements */
  375. memcpy(ctx->pos, (void*)ptr, elementMemSize * (length-finished));
  376. ctx->pos += elementMemSize * (length-finished);
  377. return UA_STATUSCODE_GOOD;
  378. }
  379. static status
  380. Array_encodeBinaryComplex(uintptr_t ptr, size_t length,
  381. const UA_DataType *type, Ctx *ctx) {
  382. /* Encode every element */
  383. for(size_t i = 0; i < length; ++i) {
  384. status ret = encodeWithExchangeBuffer((const void*)ptr, type, ctx);
  385. ptr += type->memSize;
  386. if(ret != UA_STATUSCODE_GOOD)
  387. return ret; /* Unrecoverable fail */
  388. }
  389. return UA_STATUSCODE_GOOD;
  390. }
  391. static status
  392. Array_encodeBinary(const void *src, size_t length,
  393. const UA_DataType *type, Ctx *ctx) {
  394. /* Check and convert the array length to int32 */
  395. i32 signed_length = -1;
  396. if(length > UA_INT32_MAX)
  397. return UA_STATUSCODE_BADINTERNALERROR;
  398. if(length > 0)
  399. signed_length = (i32)length;
  400. else if(src == UA_EMPTY_ARRAY_SENTINEL)
  401. signed_length = 0;
  402. /* Encode the array length */
  403. status ret = ENCODE_WITHEXCHANGE(&signed_length, UA_TYPES_INT32);
  404. /* Quit early? */
  405. if(ret != UA_STATUSCODE_GOOD || length == 0)
  406. return ret;
  407. /* Encode the content */
  408. if(!type->overlayable)
  409. return Array_encodeBinaryComplex((uintptr_t)src, length, type, ctx);
  410. return Array_encodeBinaryOverlayable((uintptr_t)src, length, type->memSize, ctx);
  411. }
  412. static status
  413. Array_decodeBinary(void *UA_RESTRICT *UA_RESTRICT dst, size_t *out_length,
  414. const UA_DataType *type, Ctx *ctx) {
  415. /* Decode the length */
  416. i32 signed_length;
  417. status ret = DECODE_DIRECT(&signed_length, UInt32); /* Int32 */
  418. if(ret != UA_STATUSCODE_GOOD)
  419. return ret;
  420. /* Return early for empty arrays */
  421. if(signed_length <= 0) {
  422. *out_length = 0;
  423. if(signed_length < 0)
  424. *dst = NULL;
  425. else
  426. *dst = UA_EMPTY_ARRAY_SENTINEL;
  427. return UA_STATUSCODE_GOOD;
  428. }
  429. /* Filter out arrays that can obviously not be decoded, because the message
  430. * is too small for the array length. This prevents the allocation of very
  431. * long arrays for bogus messages.*/
  432. size_t length = (size_t)signed_length;
  433. if(ctx->pos + ((type->memSize * length) / 32) > ctx->end)
  434. return UA_STATUSCODE_BADDECODINGERROR;
  435. /* Allocate memory */
  436. *dst = UA_calloc(length, type->memSize);
  437. if(!*dst)
  438. return UA_STATUSCODE_BADOUTOFMEMORY;
  439. if(type->overlayable) {
  440. /* memcpy overlayable array */
  441. if(ctx->end < ctx->pos + (type->memSize * length)) {
  442. UA_free(*dst);
  443. *dst = NULL;
  444. return UA_STATUSCODE_BADDECODINGERROR;
  445. }
  446. memcpy(*dst, ctx->pos, type->memSize * length);
  447. ctx->pos += type->memSize * length;
  448. } else {
  449. /* Decode array members */
  450. uintptr_t ptr = (uintptr_t)*dst;
  451. for(size_t i = 0; i < length; ++i) {
  452. ret = decodeBinaryJumpTable[type->typeKind]((void*)ptr, type, ctx);
  453. if(ret != UA_STATUSCODE_GOOD) {
  454. /* +1 because last element is also already initialized */
  455. UA_Array_delete(*dst, i+1, type);
  456. *dst = NULL;
  457. return ret;
  458. }
  459. ptr += type->memSize;
  460. }
  461. }
  462. *out_length = length;
  463. return UA_STATUSCODE_GOOD;
  464. }
  465. /*****************/
  466. /* Builtin Types */
  467. /*****************/
  468. ENCODE_BINARY(String) {
  469. return Array_encodeBinary(src->data, src->length, &UA_TYPES[UA_TYPES_BYTE], ctx);
  470. }
  471. DECODE_BINARY(String) {
  472. return Array_decodeBinary((void**)&dst->data, &dst->length, &UA_TYPES[UA_TYPES_BYTE], ctx);
  473. }
  474. /* Guid */
  475. ENCODE_BINARY(Guid) {
  476. status ret = UA_STATUSCODE_GOOD;
  477. ret |= ENCODE_DIRECT(&src->data1, UInt32);
  478. ret |= ENCODE_DIRECT(&src->data2, UInt16);
  479. ret |= ENCODE_DIRECT(&src->data3, UInt16);
  480. if(ctx->pos + (8*sizeof(u8)) > ctx->end)
  481. return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
  482. memcpy(ctx->pos, src->data4, 8*sizeof(u8));
  483. ctx->pos += 8;
  484. return ret;
  485. }
  486. DECODE_BINARY(Guid) {
  487. status ret = UA_STATUSCODE_GOOD;
  488. ret |= DECODE_DIRECT(&dst->data1, UInt32);
  489. ret |= DECODE_DIRECT(&dst->data2, UInt16);
  490. ret |= DECODE_DIRECT(&dst->data3, UInt16);
  491. if(ctx->pos + (8*sizeof(u8)) > ctx->end)
  492. return UA_STATUSCODE_BADDECODINGERROR;
  493. memcpy(dst->data4, ctx->pos, 8*sizeof(u8));
  494. ctx->pos += 8;
  495. return ret;
  496. }
  497. /* NodeId */
  498. #define UA_NODEIDTYPE_NUMERIC_TWOBYTE 0u
  499. #define UA_NODEIDTYPE_NUMERIC_FOURBYTE 1u
  500. #define UA_NODEIDTYPE_NUMERIC_COMPLETE 2u
  501. #define UA_EXPANDEDNODEID_SERVERINDEX_FLAG 0x40u
  502. #define UA_EXPANDEDNODEID_NAMESPACEURI_FLAG 0x80u
  503. /* For ExpandedNodeId, we prefill the encoding mask. */
  504. static status
  505. NodeId_encodeBinaryWithEncodingMask(UA_NodeId const *src, u8 encoding, Ctx *ctx) {
  506. status ret = UA_STATUSCODE_GOOD;
  507. switch(src->identifierType) {
  508. case UA_NODEIDTYPE_NUMERIC:
  509. if(src->identifier.numeric > UA_UINT16_MAX || src->namespaceIndex > UA_BYTE_MAX) {
  510. encoding |= UA_NODEIDTYPE_NUMERIC_COMPLETE;
  511. ret |= ENCODE_DIRECT(&encoding, Byte);
  512. ret |= ENCODE_DIRECT(&src->namespaceIndex, UInt16);
  513. ret |= ENCODE_DIRECT(&src->identifier.numeric, UInt32);
  514. } else if(src->identifier.numeric > UA_BYTE_MAX || src->namespaceIndex > 0) {
  515. encoding |= UA_NODEIDTYPE_NUMERIC_FOURBYTE;
  516. ret |= ENCODE_DIRECT(&encoding, Byte);
  517. u8 nsindex = (u8)src->namespaceIndex;
  518. ret |= ENCODE_DIRECT(&nsindex, Byte);
  519. u16 identifier16 = (u16)src->identifier.numeric;
  520. ret |= ENCODE_DIRECT(&identifier16, UInt16);
  521. } else {
  522. encoding |= UA_NODEIDTYPE_NUMERIC_TWOBYTE;
  523. ret |= ENCODE_DIRECT(&encoding, Byte);
  524. u8 identifier8 = (u8)src->identifier.numeric;
  525. ret |= ENCODE_DIRECT(&identifier8, Byte);
  526. }
  527. break;
  528. case UA_NODEIDTYPE_STRING:encoding |= (u8)UA_NODEIDTYPE_STRING;
  529. ret |= ENCODE_DIRECT(&encoding, Byte);
  530. ret |= ENCODE_DIRECT(&src->namespaceIndex, UInt16);
  531. if(ret != UA_STATUSCODE_GOOD)
  532. return ret;
  533. ret = ENCODE_DIRECT(&src->identifier.string, String);
  534. break;
  535. case UA_NODEIDTYPE_GUID:encoding |= (u8)UA_NODEIDTYPE_GUID;
  536. ret |= ENCODE_DIRECT(&encoding, Byte);
  537. ret |= ENCODE_DIRECT(&src->namespaceIndex, UInt16);
  538. ret |= ENCODE_DIRECT(&src->identifier.guid, Guid);
  539. break;
  540. case UA_NODEIDTYPE_BYTESTRING:encoding |= (u8)UA_NODEIDTYPE_BYTESTRING;
  541. ret |= ENCODE_DIRECT(&encoding, Byte);
  542. ret |= ENCODE_DIRECT(&src->namespaceIndex, UInt16);
  543. if(ret != UA_STATUSCODE_GOOD)
  544. return ret;
  545. ret = ENCODE_DIRECT(&src->identifier.byteString, String); /* ByteString */
  546. break;
  547. default:
  548. return UA_STATUSCODE_BADINTERNALERROR;
  549. }
  550. return ret;
  551. }
  552. ENCODE_BINARY(NodeId) {
  553. return NodeId_encodeBinaryWithEncodingMask(src, 0, ctx);
  554. }
  555. DECODE_BINARY(NodeId) {
  556. u8 dstByte = 0, encodingByte = 0;
  557. u16 dstUInt16 = 0;
  558. /* Decode the encoding bitfield */
  559. status ret = DECODE_DIRECT(&encodingByte, Byte);
  560. if(ret != UA_STATUSCODE_GOOD)
  561. return ret;
  562. /* Filter out the bits used only for ExpandedNodeIds */
  563. encodingByte &= (u8)~(u8)(UA_EXPANDEDNODEID_SERVERINDEX_FLAG |
  564. UA_EXPANDEDNODEID_NAMESPACEURI_FLAG);
  565. /* Decode the namespace and identifier */
  566. switch(encodingByte) {
  567. case UA_NODEIDTYPE_NUMERIC_TWOBYTE:
  568. dst->identifierType = UA_NODEIDTYPE_NUMERIC;
  569. ret = DECODE_DIRECT(&dstByte, Byte);
  570. dst->identifier.numeric = dstByte;
  571. dst->namespaceIndex = 0;
  572. break;
  573. case UA_NODEIDTYPE_NUMERIC_FOURBYTE:
  574. dst->identifierType = UA_NODEIDTYPE_NUMERIC;
  575. ret |= DECODE_DIRECT(&dstByte, Byte);
  576. dst->namespaceIndex = dstByte;
  577. ret |= DECODE_DIRECT(&dstUInt16, UInt16);
  578. dst->identifier.numeric = dstUInt16;
  579. break;
  580. case UA_NODEIDTYPE_NUMERIC_COMPLETE:
  581. dst->identifierType = UA_NODEIDTYPE_NUMERIC;
  582. ret |= DECODE_DIRECT(&dst->namespaceIndex, UInt16);
  583. ret |= DECODE_DIRECT(&dst->identifier.numeric, UInt32);
  584. break;
  585. case UA_NODEIDTYPE_STRING:
  586. dst->identifierType = UA_NODEIDTYPE_STRING;
  587. ret |= DECODE_DIRECT(&dst->namespaceIndex, UInt16);
  588. ret |= DECODE_DIRECT(&dst->identifier.string, String);
  589. break;
  590. case UA_NODEIDTYPE_GUID:
  591. dst->identifierType = UA_NODEIDTYPE_GUID;
  592. ret |= DECODE_DIRECT(&dst->namespaceIndex, UInt16);
  593. ret |= DECODE_DIRECT(&dst->identifier.guid, Guid);
  594. break;
  595. case UA_NODEIDTYPE_BYTESTRING:
  596. dst->identifierType = UA_NODEIDTYPE_BYTESTRING;
  597. ret |= DECODE_DIRECT(&dst->namespaceIndex, UInt16);
  598. ret |= DECODE_DIRECT(&dst->identifier.byteString, String); /* ByteString */
  599. break;
  600. default:
  601. ret |= UA_STATUSCODE_BADINTERNALERROR;
  602. break;
  603. }
  604. return ret;
  605. }
  606. /* ExpandedNodeId */
  607. ENCODE_BINARY(ExpandedNodeId) {
  608. /* Set up the encoding mask */
  609. u8 encoding = 0;
  610. if((void*)src->namespaceUri.data > UA_EMPTY_ARRAY_SENTINEL)
  611. encoding |= UA_EXPANDEDNODEID_NAMESPACEURI_FLAG;
  612. if(src->serverIndex > 0)
  613. encoding |= UA_EXPANDEDNODEID_SERVERINDEX_FLAG;
  614. /* Encode the NodeId */
  615. status ret = NodeId_encodeBinaryWithEncodingMask(&src->nodeId, encoding, ctx);
  616. if(ret != UA_STATUSCODE_GOOD)
  617. return ret;
  618. /* Encode the namespace. */
  619. if((void*)src->namespaceUri.data > UA_EMPTY_ARRAY_SENTINEL) {
  620. ret = ENCODE_DIRECT(&src->namespaceUri, String);
  621. if(ret != UA_STATUSCODE_GOOD)
  622. return ret;
  623. }
  624. /* Encode the serverIndex */
  625. if(src->serverIndex > 0)
  626. ret = ENCODE_WITHEXCHANGE(&src->serverIndex, UA_TYPES_UINT32);
  627. return ret;
  628. }
  629. DECODE_BINARY(ExpandedNodeId) {
  630. /* Decode the encoding mask */
  631. if(ctx->pos >= ctx->end)
  632. return UA_STATUSCODE_BADDECODINGERROR;
  633. u8 encoding = *ctx->pos;
  634. /* Decode the NodeId */
  635. status ret = DECODE_DIRECT(&dst->nodeId, NodeId);
  636. /* Decode the NamespaceUri */
  637. if(encoding & UA_EXPANDEDNODEID_NAMESPACEURI_FLAG) {
  638. dst->nodeId.namespaceIndex = 0;
  639. ret |= DECODE_DIRECT(&dst->namespaceUri, String);
  640. }
  641. /* Decode the ServerIndex */
  642. if(encoding & UA_EXPANDEDNODEID_SERVERINDEX_FLAG)
  643. ret |= DECODE_DIRECT(&dst->serverIndex, UInt32);
  644. return ret;
  645. }
  646. /* QualifiedName */
  647. ENCODE_BINARY(QualifiedName) {
  648. status ret = ENCODE_DIRECT(&src->namespaceIndex, UInt16);
  649. ret |= ENCODE_DIRECT(&src->name, String);
  650. return ret;
  651. }
  652. DECODE_BINARY(QualifiedName) {
  653. status ret = DECODE_DIRECT(&dst->namespaceIndex, UInt16);
  654. ret |= DECODE_DIRECT(&dst->name, String);
  655. return ret;
  656. }
  657. /* LocalizedText */
  658. #define UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE 0x01u
  659. #define UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT 0x02u
  660. ENCODE_BINARY(LocalizedText) {
  661. /* Set up the encoding mask */
  662. u8 encoding = 0;
  663. if(src->locale.data)
  664. encoding |= UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE;
  665. if(src->text.data)
  666. encoding |= UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT;
  667. /* Encode the encoding byte */
  668. status ret = ENCODE_DIRECT(&encoding, Byte);
  669. if(ret != UA_STATUSCODE_GOOD)
  670. return ret;
  671. /* Encode the strings */
  672. if(encoding & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE)
  673. ret |= ENCODE_DIRECT(&src->locale, String);
  674. if(encoding & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT)
  675. ret |= ENCODE_DIRECT(&src->text, String);
  676. return ret;
  677. }
  678. DECODE_BINARY(LocalizedText) {
  679. /* Decode the encoding mask */
  680. u8 encoding = 0;
  681. status ret = DECODE_DIRECT(&encoding, Byte);
  682. /* Decode the content */
  683. if(encoding & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE)
  684. ret |= DECODE_DIRECT(&dst->locale, String);
  685. if(encoding & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT)
  686. ret |= DECODE_DIRECT(&dst->text, String);
  687. return ret;
  688. }
  689. /* The binary encoding has a different nodeid from the data type. So it is not
  690. * possible to reuse UA_findDataType */
  691. static const UA_DataType *
  692. UA_findDataTypeByBinaryInternal(const UA_NodeId *typeId, Ctx *ctx) {
  693. /* We only store a numeric identifier for the encoding nodeid of data types */
  694. if(typeId->identifierType != UA_NODEIDTYPE_NUMERIC)
  695. return NULL;
  696. /* Always look in built-in types first
  697. * (may contain data types from all namespaces) */
  698. for(size_t i = 0; i < UA_TYPES_COUNT; ++i) {
  699. if(UA_TYPES[i].binaryEncodingId == typeId->identifier.numeric &&
  700. UA_TYPES[i].typeId.namespaceIndex == typeId->namespaceIndex)
  701. return &UA_TYPES[i];
  702. }
  703. const UA_DataTypeArray *customTypes = ctx->customTypes;
  704. while(customTypes) {
  705. for(size_t i = 0; i < customTypes->typesSize; ++i) {
  706. if(customTypes->types[i].binaryEncodingId == typeId->identifier.numeric &&
  707. customTypes->types[i].typeId.namespaceIndex == typeId->namespaceIndex)
  708. return &customTypes->types[i];
  709. }
  710. customTypes = customTypes->next;
  711. }
  712. return NULL;
  713. }
  714. const UA_DataType *
  715. UA_findDataTypeByBinary(const UA_NodeId *typeId) {
  716. Ctx ctx;
  717. ctx.customTypes = NULL;
  718. return UA_findDataTypeByBinaryInternal(typeId, &ctx);
  719. }
  720. /* ExtensionObject */
  721. ENCODE_BINARY(ExtensionObject) {
  722. u8 encoding = (u8)src->encoding;
  723. /* No content or already encoded content. */
  724. if(encoding <= UA_EXTENSIONOBJECT_ENCODED_XML) {
  725. status ret = ENCODE_DIRECT(&src->content.encoded.typeId, NodeId);
  726. if(ret != UA_STATUSCODE_GOOD)
  727. return ret;
  728. ret = ENCODE_WITHEXCHANGE(&encoding, UA_TYPES_BYTE);
  729. if(ret != UA_STATUSCODE_GOOD)
  730. return ret;
  731. switch(src->encoding) {
  732. case UA_EXTENSIONOBJECT_ENCODED_NOBODY:
  733. break;
  734. case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING:
  735. case UA_EXTENSIONOBJECT_ENCODED_XML:
  736. ret = ENCODE_DIRECT(&src->content.encoded.body, String); /* ByteString */
  737. break;
  738. default:
  739. ret = UA_STATUSCODE_BADINTERNALERROR;
  740. }
  741. return ret;
  742. }
  743. /* Cannot encode with no data or no type description */
  744. if(!src->content.decoded.type || !src->content.decoded.data)
  745. return UA_STATUSCODE_BADENCODINGERROR;
  746. /* Write the NodeId for the binary encoded type. The NodeId is always
  747. * numeric, so no buffer replacement is taking place. */
  748. UA_NodeId typeId = src->content.decoded.type->typeId;
  749. if(typeId.identifierType != UA_NODEIDTYPE_NUMERIC)
  750. return UA_STATUSCODE_BADENCODINGERROR;
  751. typeId.identifier.numeric = src->content.decoded.type->binaryEncodingId;
  752. status ret = ENCODE_DIRECT(&typeId, NodeId);
  753. /* Write the encoding byte */
  754. encoding = UA_EXTENSIONOBJECT_ENCODED_BYTESTRING;
  755. ret |= ENCODE_DIRECT(&encoding, Byte);
  756. /* Compute the content length */
  757. const UA_DataType *contentType = src->content.decoded.type;
  758. size_t len = UA_calcSizeBinary(src->content.decoded.data, contentType);
  759. /* Encode the content length */
  760. if(len > UA_INT32_MAX)
  761. return UA_STATUSCODE_BADENCODINGERROR;
  762. i32 signed_len = (i32)len;
  763. ret |= ENCODE_DIRECT(&signed_len, UInt32); /* Int32 */
  764. /* Return early upon failures (no buffer exchange until here) */
  765. if(ret != UA_STATUSCODE_GOOD)
  766. return ret;
  767. /* Encode the content */
  768. return encodeWithExchangeBuffer(src->content.decoded.data, contentType, ctx);
  769. }
  770. static status
  771. ExtensionObject_decodeBinaryContent(UA_ExtensionObject *dst, const UA_NodeId *typeId, Ctx *ctx) {
  772. /* Lookup the datatype */
  773. const UA_DataType *type = UA_findDataTypeByBinaryInternal(typeId, ctx);
  774. /* Unknown type, just take the binary content */
  775. if(!type) {
  776. dst->encoding = UA_EXTENSIONOBJECT_ENCODED_BYTESTRING;
  777. UA_NodeId_copy(typeId, &dst->content.encoded.typeId);
  778. return DECODE_DIRECT(&dst->content.encoded.body, String); /* ByteString */
  779. }
  780. /* Allocate memory */
  781. dst->content.decoded.data = UA_new(type);
  782. if(!dst->content.decoded.data)
  783. return UA_STATUSCODE_BADOUTOFMEMORY;
  784. /* Jump over the length field (TODO: check if the decoded length matches) */
  785. ctx->pos += 4;
  786. /* Decode */
  787. dst->encoding = UA_EXTENSIONOBJECT_DECODED;
  788. dst->content.decoded.type = type;
  789. return decodeBinaryJumpTable[type->typeKind](dst->content.decoded.data, type, ctx);
  790. }
  791. DECODE_BINARY(ExtensionObject) {
  792. u8 encoding = 0;
  793. UA_NodeId binTypeId; /* Can contain a string nodeid. But no corresponding
  794. * type is then found in open62541. We only store
  795. * numerical nodeids of the binary encoding identifier.
  796. * The extenionobject will be decoded to contain a
  797. * binary blob. */
  798. UA_NodeId_init(&binTypeId);
  799. status ret = UA_STATUSCODE_GOOD;
  800. ret |= DECODE_DIRECT(&binTypeId, NodeId);
  801. ret |= DECODE_DIRECT(&encoding, Byte);
  802. if(ret != UA_STATUSCODE_GOOD) {
  803. UA_NodeId_clear(&binTypeId);
  804. return ret;
  805. }
  806. switch(encoding) {
  807. case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING:
  808. ret = ExtensionObject_decodeBinaryContent(dst, &binTypeId, ctx);
  809. UA_NodeId_deleteMembers(&binTypeId);
  810. break;
  811. case UA_EXTENSIONOBJECT_ENCODED_NOBODY:
  812. dst->encoding = (UA_ExtensionObjectEncoding)encoding;
  813. dst->content.encoded.typeId = binTypeId; /* move to dst */
  814. dst->content.encoded.body = UA_BYTESTRING_NULL;
  815. break;
  816. case UA_EXTENSIONOBJECT_ENCODED_XML:
  817. dst->encoding = (UA_ExtensionObjectEncoding)encoding;
  818. dst->content.encoded.typeId = binTypeId; /* move to dst */
  819. ret = DECODE_DIRECT(&dst->content.encoded.body, String); /* ByteString */
  820. if(ret != UA_STATUSCODE_GOOD)
  821. UA_NodeId_clear(&dst->content.encoded.typeId);
  822. break;
  823. default:
  824. UA_NodeId_clear(&binTypeId);
  825. ret = UA_STATUSCODE_BADDECODINGERROR;
  826. break;
  827. }
  828. return ret;
  829. }
  830. /* Variant */
  831. static status
  832. Variant_encodeBinaryWrapExtensionObject(const UA_Variant *src,
  833. const UA_Boolean isArray, Ctx *ctx) {
  834. /* Default to 1 for a scalar. */
  835. size_t length = 1;
  836. /* Encode the array length if required */
  837. status ret = UA_STATUSCODE_GOOD;
  838. if(isArray) {
  839. if(src->arrayLength > UA_INT32_MAX)
  840. return UA_STATUSCODE_BADENCODINGERROR;
  841. length = src->arrayLength;
  842. i32 encodedLength = (i32)src->arrayLength;
  843. ret = ENCODE_DIRECT(&encodedLength, UInt32); /* Int32 */
  844. if(ret != UA_STATUSCODE_GOOD)
  845. return ret;
  846. }
  847. /* Set up the ExtensionObject */
  848. UA_ExtensionObject eo;
  849. UA_ExtensionObject_init(&eo);
  850. eo.encoding = UA_EXTENSIONOBJECT_DECODED;
  851. eo.content.decoded.type = src->type;
  852. const u16 memSize = src->type->memSize;
  853. uintptr_t ptr = (uintptr_t)src->data;
  854. /* Iterate over the array */
  855. for(size_t i = 0; i < length && ret == UA_STATUSCODE_GOOD; ++i) {
  856. eo.content.decoded.data = (void*)ptr;
  857. ret = encodeWithExchangeBuffer(&eo, &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], ctx);
  858. ptr += memSize;
  859. }
  860. return ret;
  861. }
  862. enum UA_VARIANT_ENCODINGMASKTYPE {
  863. UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK = 0x3Fu, /* bits 0:5 */
  864. UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS = (u8)(0x01u << 6u), /* bit 6 */
  865. UA_VARIANT_ENCODINGMASKTYPE_ARRAY = (u8)(0x01u << 7u) /* bit 7 */
  866. };
  867. ENCODE_BINARY(Variant) {
  868. /* Quit early for the empty variant */
  869. u8 encoding = 0;
  870. if(!src->type)
  871. return ENCODE_DIRECT(&encoding, Byte);
  872. /* Set the content type in the encoding mask */
  873. const UA_Boolean isBuiltin = (src->type->typeKind <= UA_DATATYPEKIND_DIAGNOSTICINFO);
  874. const UA_Boolean isEnum = (src->type->typeKind == UA_DATATYPEKIND_ENUM);
  875. if(isBuiltin)
  876. encoding = (u8)(encoding | (u8)((u8)UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK & (u8)(src->type->typeKind + 1u)));
  877. else if(isEnum)
  878. encoding = (u8)(encoding | (u8)((u8)UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK & (u8)(UA_TYPES_INT32 + 1u)));
  879. else
  880. encoding = (u8)(encoding | (u8)((u8)UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK & (u8)(UA_TYPES_EXTENSIONOBJECT + 1u)));
  881. /* Set the array type in the encoding mask */
  882. const UA_Boolean isArray = src->arrayLength > 0 || src->data <= UA_EMPTY_ARRAY_SENTINEL;
  883. const UA_Boolean hasDimensions = isArray && src->arrayDimensionsSize > 0;
  884. if(isArray) {
  885. encoding |= (u8)UA_VARIANT_ENCODINGMASKTYPE_ARRAY;
  886. if(hasDimensions)
  887. encoding |= (u8)UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS;
  888. }
  889. /* Encode the encoding byte */
  890. status ret = ENCODE_DIRECT(&encoding, Byte);
  891. if(ret != UA_STATUSCODE_GOOD)
  892. return ret;
  893. /* Encode the content */
  894. if(!isBuiltin && !isEnum)
  895. ret = Variant_encodeBinaryWrapExtensionObject(src, isArray, ctx);
  896. else if(!isArray)
  897. ret = encodeWithExchangeBuffer(src->data, src->type, ctx);
  898. else
  899. ret = Array_encodeBinary(src->data, src->arrayLength, src->type, ctx);
  900. /* Encode the array dimensions */
  901. if(hasDimensions && ret == UA_STATUSCODE_GOOD)
  902. ret = Array_encodeBinary(src->arrayDimensions, src->arrayDimensionsSize,
  903. &UA_TYPES[UA_TYPES_INT32], ctx);
  904. return ret;
  905. }
  906. static status
  907. Variant_decodeBinaryUnwrapExtensionObject(UA_Variant *dst, Ctx *ctx) {
  908. /* Save the position in the ByteString. If unwrapping is not possible, start
  909. * from here to decode a normal ExtensionObject. */
  910. u8 *old_pos = ctx->pos;
  911. /* Decode the DataType */
  912. UA_NodeId typeId;
  913. UA_NodeId_init(&typeId);
  914. status ret = DECODE_DIRECT(&typeId, NodeId);
  915. if(ret != UA_STATUSCODE_GOOD)
  916. return ret;
  917. /* Decode the EncodingByte */
  918. u8 encoding;
  919. ret = DECODE_DIRECT(&encoding, Byte);
  920. if(ret != UA_STATUSCODE_GOOD) {
  921. UA_NodeId_clear(&typeId);
  922. return ret;
  923. }
  924. /* Search for the datatype. Default to ExtensionObject. */
  925. if(encoding == UA_EXTENSIONOBJECT_ENCODED_BYTESTRING &&
  926. (dst->type = UA_findDataTypeByBinaryInternal(&typeId, ctx)) != NULL) {
  927. /* Jump over the length field (TODO: check if length matches) */
  928. ctx->pos += 4;
  929. } else {
  930. /* Reset and decode as ExtensionObject */
  931. dst->type = &UA_TYPES[UA_TYPES_EXTENSIONOBJECT];
  932. ctx->pos = old_pos;
  933. UA_NodeId_clear(&typeId);
  934. }
  935. /* Allocate memory */
  936. dst->data = UA_new(dst->type);
  937. if(!dst->data)
  938. return UA_STATUSCODE_BADOUTOFMEMORY;
  939. /* Decode the content */
  940. return decodeBinaryJumpTable[dst->type->typeKind](dst->data, dst->type, ctx);
  941. }
  942. /* The resulting variant always has the storagetype UA_VARIANT_DATA. */
  943. DECODE_BINARY(Variant) {
  944. /* Decode the encoding byte */
  945. u8 encodingByte;
  946. status ret = DECODE_DIRECT(&encodingByte, Byte);
  947. if(ret != UA_STATUSCODE_GOOD)
  948. return ret;
  949. /* Return early for an empty variant (was already _inited) */
  950. if(encodingByte == 0)
  951. return UA_STATUSCODE_GOOD;
  952. /* Does the variant contain an array? */
  953. const UA_Boolean isArray = (encodingByte & (u8)UA_VARIANT_ENCODINGMASKTYPE_ARRAY) > 0;
  954. /* Get the datatype of the content. The type must be a builtin data type.
  955. * All not-builtin types are wrapped in an ExtensionObject. The "type kind"
  956. * for types up to DiagnsticInfo equals to the index in the encoding
  957. * byte. */
  958. size_t typeKind = (size_t)((encodingByte & (u8)UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK) - 1);
  959. if(typeKind > UA_DATATYPEKIND_DIAGNOSTICINFO)
  960. return UA_STATUSCODE_BADDECODINGERROR;
  961. /* A variant cannot contain a variant. But it can contain an array of
  962. * variants */
  963. if(typeKind == UA_DATATYPEKIND_VARIANT && !isArray)
  964. return UA_STATUSCODE_BADDECODINGERROR;
  965. /* Check the recursion limit */
  966. if(ctx->depth > UA_ENCODING_MAX_RECURSION)
  967. return UA_STATUSCODE_BADENCODINGERROR;
  968. ctx->depth++;
  969. /* Decode the content */
  970. dst->type = &UA_TYPES[typeKind];
  971. if(isArray) {
  972. ret = Array_decodeBinary(&dst->data, &dst->arrayLength, dst->type, ctx);
  973. } else if(typeKind != UA_DATATYPEKIND_EXTENSIONOBJECT) {
  974. dst->data = UA_new(dst->type);
  975. if(!dst->data)
  976. return UA_STATUSCODE_BADOUTOFMEMORY;
  977. ret = decodeBinaryJumpTable[typeKind](dst->data, dst->type, ctx);
  978. } else {
  979. ret = Variant_decodeBinaryUnwrapExtensionObject(dst, ctx);
  980. }
  981. /* Decode array dimensions */
  982. if(isArray && (encodingByte & (u8)UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS) > 0)
  983. ret |= Array_decodeBinary((void**)&dst->arrayDimensions, &dst->arrayDimensionsSize,
  984. &UA_TYPES[UA_TYPES_INT32], ctx);
  985. ctx->depth--;
  986. return ret;
  987. }
  988. /* DataValue */
  989. ENCODE_BINARY(DataValue) {
  990. /* Set up the encoding mask */
  991. u8 encodingMask = src->hasValue;
  992. encodingMask |= (u8)(src->hasStatus << 1u);
  993. encodingMask |= (u8)(src->hasSourceTimestamp << 2u);
  994. encodingMask |= (u8)(src->hasServerTimestamp << 3u);
  995. encodingMask |= (u8)(src->hasSourcePicoseconds << 4u);
  996. encodingMask |= (u8)(src->hasServerPicoseconds << 5u);
  997. /* Encode the encoding byte */
  998. status ret = ENCODE_DIRECT(&encodingMask, Byte);
  999. if(ret != UA_STATUSCODE_GOOD)
  1000. return ret;
  1001. /* Encode the variant. */
  1002. if(src->hasValue) {
  1003. ret = ENCODE_DIRECT(&src->value, Variant);
  1004. if(ret != UA_STATUSCODE_GOOD)
  1005. return ret;
  1006. }
  1007. if(src->hasStatus)
  1008. ret |= ENCODE_WITHEXCHANGE(&src->status, UA_TYPES_STATUSCODE);
  1009. if(src->hasSourceTimestamp)
  1010. ret |= ENCODE_WITHEXCHANGE(&src->sourceTimestamp, UA_TYPES_DATETIME);
  1011. if(src->hasSourcePicoseconds)
  1012. ret |= ENCODE_WITHEXCHANGE(&src->sourcePicoseconds, UA_TYPES_UINT16);
  1013. if(src->hasServerTimestamp)
  1014. ret |= ENCODE_WITHEXCHANGE(&src->serverTimestamp, UA_TYPES_DATETIME);
  1015. if(src->hasServerPicoseconds)
  1016. ret |= ENCODE_WITHEXCHANGE(&src->serverPicoseconds, UA_TYPES_UINT16);
  1017. return ret;
  1018. }
  1019. #define MAX_PICO_SECONDS 9999
  1020. DECODE_BINARY(DataValue) {
  1021. /* Decode the encoding mask */
  1022. u8 encodingMask;
  1023. status ret = DECODE_DIRECT(&encodingMask, Byte);
  1024. if(ret != UA_STATUSCODE_GOOD)
  1025. return ret;
  1026. /* Check the recursion limit */
  1027. if(ctx->depth > UA_ENCODING_MAX_RECURSION)
  1028. return UA_STATUSCODE_BADENCODINGERROR;
  1029. ctx->depth++;
  1030. /* Decode the content */
  1031. if(encodingMask & 0x01u) {
  1032. dst->hasValue = true;
  1033. ret |= DECODE_DIRECT(&dst->value, Variant);
  1034. }
  1035. if(encodingMask & 0x02u) {
  1036. dst->hasStatus = true;
  1037. ret |= DECODE_DIRECT(&dst->status, UInt32); /* StatusCode */
  1038. }
  1039. if(encodingMask & 0x04u) {
  1040. dst->hasSourceTimestamp = true;
  1041. ret |= DECODE_DIRECT(&dst->sourceTimestamp, UInt64); /* DateTime */
  1042. }
  1043. if(encodingMask & 0x10u) {
  1044. dst->hasSourcePicoseconds = true;
  1045. ret |= DECODE_DIRECT(&dst->sourcePicoseconds, UInt16);
  1046. if(dst->sourcePicoseconds > MAX_PICO_SECONDS)
  1047. dst->sourcePicoseconds = MAX_PICO_SECONDS;
  1048. }
  1049. if(encodingMask & 0x08u) {
  1050. dst->hasServerTimestamp = true;
  1051. ret |= DECODE_DIRECT(&dst->serverTimestamp, UInt64); /* DateTime */
  1052. }
  1053. if(encodingMask & 0x20u) {
  1054. dst->hasServerPicoseconds = true;
  1055. ret |= DECODE_DIRECT(&dst->serverPicoseconds, UInt16);
  1056. if(dst->serverPicoseconds > MAX_PICO_SECONDS)
  1057. dst->serverPicoseconds = MAX_PICO_SECONDS;
  1058. }
  1059. ctx->depth--;
  1060. return ret;
  1061. }
  1062. /* DiagnosticInfo */
  1063. ENCODE_BINARY(DiagnosticInfo) {
  1064. /* Set up the encoding mask */
  1065. u8 encodingMask = src->hasSymbolicId;
  1066. encodingMask |= (u8)(src->hasNamespaceUri << 1u);
  1067. encodingMask |= (u8)(src->hasLocalizedText << 2u);
  1068. encodingMask |= (u8)(src->hasLocale << 3u);
  1069. encodingMask |= (u8)(src->hasAdditionalInfo << 4u);
  1070. encodingMask |= (u8)(src->hasInnerDiagnosticInfo << 5u);
  1071. /* Encode the numeric content */
  1072. status ret = ENCODE_DIRECT(&encodingMask, Byte);
  1073. if(src->hasSymbolicId)
  1074. ret |= ENCODE_DIRECT(&src->symbolicId, UInt32); /* Int32 */
  1075. if(src->hasNamespaceUri)
  1076. ret |= ENCODE_DIRECT(&src->namespaceUri, UInt32); /* Int32 */
  1077. if(src->hasLocalizedText)
  1078. ret |= ENCODE_DIRECT(&src->localizedText, UInt32); /* Int32 */
  1079. if(src->hasLocale)
  1080. ret |= ENCODE_DIRECT(&src->locale, UInt32); /* Int32 */
  1081. if(ret != UA_STATUSCODE_GOOD)
  1082. return ret;
  1083. /* Encode the additional info */
  1084. if(src->hasAdditionalInfo) {
  1085. ret = ENCODE_DIRECT(&src->additionalInfo, String);
  1086. if(ret != UA_STATUSCODE_GOOD)
  1087. return ret;
  1088. }
  1089. /* Encode the inner status code */
  1090. if(src->hasInnerStatusCode) {
  1091. ret = ENCODE_WITHEXCHANGE(&src->innerStatusCode, UA_TYPES_UINT32);
  1092. if(ret != UA_STATUSCODE_GOOD)
  1093. return ret;
  1094. }
  1095. /* Encode the inner diagnostic info */
  1096. if(src->hasInnerDiagnosticInfo)
  1097. // innerDiagnosticInfo is already a pointer, so don't use the & reference here
  1098. ret = ENCODE_WITHEXCHANGE(src->innerDiagnosticInfo,
  1099. UA_TYPES_DIAGNOSTICINFO);
  1100. return ret;
  1101. }
  1102. DECODE_BINARY(DiagnosticInfo) {
  1103. /* Decode the encoding mask */
  1104. u8 encodingMask;
  1105. status ret = DECODE_DIRECT(&encodingMask, Byte);
  1106. if(ret != UA_STATUSCODE_GOOD)
  1107. return ret;
  1108. /* Decode the content */
  1109. if(encodingMask & 0x01u) {
  1110. dst->hasSymbolicId = true;
  1111. ret |= DECODE_DIRECT(&dst->symbolicId, UInt32); /* Int32 */
  1112. }
  1113. if(encodingMask & 0x02u) {
  1114. dst->hasNamespaceUri = true;
  1115. ret |= DECODE_DIRECT(&dst->namespaceUri, UInt32); /* Int32 */
  1116. }
  1117. if(encodingMask & 0x04u) {
  1118. dst->hasLocalizedText = true;
  1119. ret |= DECODE_DIRECT(&dst->localizedText, UInt32); /* Int32 */
  1120. }
  1121. if(encodingMask & 0x08u) {
  1122. dst->hasLocale = true;
  1123. ret |= DECODE_DIRECT(&dst->locale, UInt32); /* Int32 */
  1124. }
  1125. if(encodingMask & 0x10u) {
  1126. dst->hasAdditionalInfo = true;
  1127. ret |= DECODE_DIRECT(&dst->additionalInfo, String);
  1128. }
  1129. if(encodingMask & 0x20u) {
  1130. dst->hasInnerStatusCode = true;
  1131. ret |= DECODE_DIRECT(&dst->innerStatusCode, UInt32); /* StatusCode */
  1132. }
  1133. if(encodingMask & 0x40u) {
  1134. /* innerDiagnosticInfo is allocated on the heap */
  1135. dst->innerDiagnosticInfo = (UA_DiagnosticInfo*)
  1136. UA_calloc(1, sizeof(UA_DiagnosticInfo));
  1137. if(!dst->innerDiagnosticInfo)
  1138. return UA_STATUSCODE_BADOUTOFMEMORY;
  1139. dst->hasInnerDiagnosticInfo = true;
  1140. /* Check the recursion limit */
  1141. if(ctx->depth > UA_ENCODING_MAX_RECURSION)
  1142. return UA_STATUSCODE_BADENCODINGERROR;
  1143. ctx->depth++;
  1144. ret |= DECODE_DIRECT(dst->innerDiagnosticInfo, DiagnosticInfo);
  1145. ctx->depth--;
  1146. }
  1147. return ret;
  1148. }
  1149. static status
  1150. encodeBinaryStruct(const void *src, const UA_DataType *type, Ctx *ctx) {
  1151. /* Check the recursion limit */
  1152. if(ctx->depth > UA_ENCODING_MAX_RECURSION)
  1153. return UA_STATUSCODE_BADENCODINGERROR;
  1154. ctx->depth++;
  1155. uintptr_t ptr = (uintptr_t)src;
  1156. status ret = UA_STATUSCODE_GOOD;
  1157. u8 membersSize = type->membersSize;
  1158. const UA_DataType *typelists[2] = { UA_TYPES, &type[-type->typeIndex] };
  1159. /* Loop over members */
  1160. for(size_t i = 0; i < membersSize; ++i) {
  1161. const UA_DataTypeMember *m = &type->members[i];
  1162. const UA_DataType *mt = &typelists[!m->namespaceZero][m->memberTypeIndex];
  1163. ptr += m->padding;
  1164. /* Array. Buffer-exchange is done inside Array_encodeBinary if required. */
  1165. if(m->isArray) {
  1166. const size_t length = *((const size_t*)ptr);
  1167. ptr += sizeof(size_t);
  1168. ret = Array_encodeBinary(*(void *UA_RESTRICT const *)ptr, length, mt, ctx);
  1169. ptr += sizeof(void*);
  1170. continue;
  1171. }
  1172. /* Scalar */
  1173. ret = encodeWithExchangeBuffer((const void*)ptr, mt, ctx);
  1174. ptr += mt->memSize;
  1175. }
  1176. ctx->depth--;
  1177. return ret;
  1178. }
  1179. static status
  1180. encodeBinaryNotImplemented(const void *src, const UA_DataType *type, Ctx *ctx) {
  1181. (void)src, (void)type, (void)ctx;
  1182. return UA_STATUSCODE_BADNOTIMPLEMENTED;
  1183. }
  1184. /********************/
  1185. /* Structured Types */
  1186. /********************/
  1187. const encodeBinarySignature encodeBinaryJumpTable[UA_DATATYPEKINDS] = {
  1188. (encodeBinarySignature)Boolean_encodeBinary,
  1189. (encodeBinarySignature)Byte_encodeBinary, /* SByte */
  1190. (encodeBinarySignature)Byte_encodeBinary,
  1191. (encodeBinarySignature)UInt16_encodeBinary, /* Int16 */
  1192. (encodeBinarySignature)UInt16_encodeBinary,
  1193. (encodeBinarySignature)UInt32_encodeBinary, /* Int32 */
  1194. (encodeBinarySignature)UInt32_encodeBinary,
  1195. (encodeBinarySignature)UInt64_encodeBinary, /* Int64 */
  1196. (encodeBinarySignature)UInt64_encodeBinary,
  1197. (encodeBinarySignature)Float_encodeBinary,
  1198. (encodeBinarySignature)Double_encodeBinary,
  1199. (encodeBinarySignature)String_encodeBinary,
  1200. (encodeBinarySignature)UInt64_encodeBinary, /* DateTime */
  1201. (encodeBinarySignature)Guid_encodeBinary,
  1202. (encodeBinarySignature)String_encodeBinary, /* ByteString */
  1203. (encodeBinarySignature)String_encodeBinary, /* XmlElement */
  1204. (encodeBinarySignature)NodeId_encodeBinary,
  1205. (encodeBinarySignature)ExpandedNodeId_encodeBinary,
  1206. (encodeBinarySignature)UInt32_encodeBinary, /* StatusCode */
  1207. (encodeBinarySignature)QualifiedName_encodeBinary,
  1208. (encodeBinarySignature)LocalizedText_encodeBinary,
  1209. (encodeBinarySignature)ExtensionObject_encodeBinary,
  1210. (encodeBinarySignature)DataValue_encodeBinary,
  1211. (encodeBinarySignature)Variant_encodeBinary,
  1212. (encodeBinarySignature)DiagnosticInfo_encodeBinary,
  1213. (encodeBinarySignature)encodeBinaryNotImplemented, /* Decimal */
  1214. (encodeBinarySignature)UInt32_encodeBinary, /* Enumeration */
  1215. (encodeBinarySignature)encodeBinaryStruct,
  1216. (encodeBinarySignature)encodeBinaryNotImplemented, /* Structure with Optional Fields */
  1217. (encodeBinarySignature)encodeBinaryStruct, /* Union */
  1218. (encodeBinarySignature)encodeBinaryStruct /* BitfieldCluster */
  1219. };
  1220. status
  1221. UA_encodeBinary(const void *src, const UA_DataType *type,
  1222. u8 **bufPos, const u8 **bufEnd,
  1223. UA_exchangeEncodeBuffer exchangeCallback, void *exchangeHandle) {
  1224. /* Set up the context */
  1225. Ctx ctx;
  1226. ctx.pos = *bufPos;
  1227. ctx.end = *bufEnd;
  1228. ctx.depth = 0;
  1229. ctx.exchangeBufferCallback = exchangeCallback;
  1230. ctx.exchangeBufferCallbackHandle = exchangeHandle;
  1231. if(!ctx.pos)
  1232. return UA_STATUSCODE_BADINVALIDARGUMENT;
  1233. /* Encode */
  1234. status ret = encodeWithExchangeBuffer(src, type, &ctx);
  1235. /* Set the new buffer position for the output. Beware that the buffer might
  1236. * have been exchanged internally. */
  1237. *bufPos = ctx.pos;
  1238. *bufEnd = ctx.end;
  1239. return ret;
  1240. }
  1241. static status
  1242. decodeBinaryNotImplemented(void *dst, const UA_DataType *type, Ctx *ctx) {
  1243. (void)dst, (void)type, (void)ctx;
  1244. return UA_STATUSCODE_BADNOTIMPLEMENTED;
  1245. }
  1246. static status
  1247. decodeBinaryStructure(void *dst, const UA_DataType *type, Ctx *ctx) {
  1248. /* Check the recursion limit */
  1249. if(ctx->depth > UA_ENCODING_MAX_RECURSION)
  1250. return UA_STATUSCODE_BADENCODINGERROR;
  1251. ctx->depth++;
  1252. uintptr_t ptr = (uintptr_t)dst;
  1253. status ret = UA_STATUSCODE_GOOD;
  1254. u8 membersSize = type->membersSize;
  1255. const UA_DataType *typelists[2] = { UA_TYPES, &type[-type->typeIndex] };
  1256. /* Loop over members */
  1257. for(size_t i = 0; i < membersSize && ret == UA_STATUSCODE_GOOD; ++i) {
  1258. const UA_DataTypeMember *m = &type->members[i];
  1259. const UA_DataType *mt = &typelists[!m->namespaceZero][m->memberTypeIndex];
  1260. ptr += m->padding;
  1261. /* Array */
  1262. if(m->isArray) {
  1263. size_t *length = (size_t*)ptr;
  1264. ptr += sizeof(size_t);
  1265. ret = Array_decodeBinary((void *UA_RESTRICT *UA_RESTRICT)ptr, length, mt , ctx);
  1266. ptr += sizeof(void*);
  1267. continue;
  1268. }
  1269. /* Scalar */
  1270. ret = decodeBinaryJumpTable[mt->typeKind]((void *UA_RESTRICT)ptr, mt, ctx);
  1271. ptr += mt->memSize;
  1272. }
  1273. ctx->depth--;
  1274. return ret;
  1275. }
  1276. const decodeBinarySignature decodeBinaryJumpTable[UA_DATATYPEKINDS] = {
  1277. (decodeBinarySignature)Boolean_decodeBinary,
  1278. (decodeBinarySignature)Byte_decodeBinary, /* SByte */
  1279. (decodeBinarySignature)Byte_decodeBinary,
  1280. (decodeBinarySignature)UInt16_decodeBinary, /* Int16 */
  1281. (decodeBinarySignature)UInt16_decodeBinary,
  1282. (decodeBinarySignature)UInt32_decodeBinary, /* Int32 */
  1283. (decodeBinarySignature)UInt32_decodeBinary,
  1284. (decodeBinarySignature)UInt64_decodeBinary, /* Int64 */
  1285. (decodeBinarySignature)UInt64_decodeBinary,
  1286. (decodeBinarySignature)Float_decodeBinary,
  1287. (decodeBinarySignature)Double_decodeBinary,
  1288. (decodeBinarySignature)String_decodeBinary,
  1289. (decodeBinarySignature)UInt64_decodeBinary, /* DateTime */
  1290. (decodeBinarySignature)Guid_decodeBinary,
  1291. (decodeBinarySignature)String_decodeBinary, /* ByteString */
  1292. (decodeBinarySignature)String_decodeBinary, /* XmlElement */
  1293. (decodeBinarySignature)NodeId_decodeBinary,
  1294. (decodeBinarySignature)ExpandedNodeId_decodeBinary,
  1295. (decodeBinarySignature)UInt32_decodeBinary, /* StatusCode */
  1296. (decodeBinarySignature)QualifiedName_decodeBinary,
  1297. (decodeBinarySignature)LocalizedText_decodeBinary,
  1298. (decodeBinarySignature)ExtensionObject_decodeBinary,
  1299. (decodeBinarySignature)DataValue_decodeBinary,
  1300. (decodeBinarySignature)Variant_decodeBinary,
  1301. (decodeBinarySignature)DiagnosticInfo_decodeBinary,
  1302. (decodeBinarySignature)decodeBinaryNotImplemented, /* Decimal */
  1303. (decodeBinarySignature)UInt32_decodeBinary, /* Enumeration */
  1304. (decodeBinarySignature)decodeBinaryStructure,
  1305. (decodeBinarySignature)decodeBinaryNotImplemented, /* Structure with optional fields */
  1306. (decodeBinarySignature)decodeBinaryNotImplemented, /* Union */
  1307. (decodeBinarySignature)decodeBinaryNotImplemented /* BitfieldCluster */
  1308. };
  1309. status
  1310. UA_decodeBinary(const UA_ByteString *src, size_t *offset, void *dst,
  1311. const UA_DataType *type, const UA_DataTypeArray *customTypes) {
  1312. /* Set up the context */
  1313. Ctx ctx;
  1314. ctx.pos = &src->data[*offset];
  1315. ctx.end = &src->data[src->length];
  1316. ctx.depth = 0;
  1317. ctx.customTypes = customTypes;
  1318. /* Decode */
  1319. memset(dst, 0, type->memSize); /* Initialize the value */
  1320. status ret = decodeBinaryJumpTable[type->typeKind](dst, type, &ctx);
  1321. if(ret == UA_STATUSCODE_GOOD) {
  1322. /* Set the new offset */
  1323. *offset = (size_t)(ctx.pos - src->data) / sizeof(u8);
  1324. } else {
  1325. /* Clean up */
  1326. UA_clear(dst, type);
  1327. memset(dst, 0, type->memSize);
  1328. }
  1329. return ret;
  1330. }
  1331. /**
  1332. * Compute the Message Size
  1333. * ------------------------
  1334. * The following methods are used to compute the length of a datum in binary
  1335. * encoding. */
  1336. static size_t
  1337. Array_calcSizeBinary(const void *src, size_t length, const UA_DataType *type) {
  1338. size_t s = 4; /* length */
  1339. if(type->overlayable) {
  1340. s += type->memSize * length;
  1341. return s;
  1342. }
  1343. uintptr_t ptr = (uintptr_t)src;
  1344. for(size_t i = 0; i < length; ++i) {
  1345. s += calcSizeBinaryJumpTable[type->typeKind]((const void*)ptr, type);
  1346. ptr += type->memSize;
  1347. }
  1348. return s;
  1349. }
  1350. static size_t calcSizeBinary1(const void *_, const UA_DataType *__) { (void)_, (void)__; return 1; }
  1351. static size_t calcSizeBinary2(const void *_, const UA_DataType *__) { (void)_, (void)__; return 2; }
  1352. static size_t calcSizeBinary4(const void *_, const UA_DataType *__) { (void)_, (void)__; return 4; }
  1353. static size_t calcSizeBinary8(const void *_, const UA_DataType *__) { (void)_, (void)__; return 8; }
  1354. CALCSIZE_BINARY(String) { return 4 + src->length; }
  1355. CALCSIZE_BINARY(Guid) { return 16; }
  1356. CALCSIZE_BINARY(NodeId) {
  1357. size_t s = 1; /* Encoding byte */
  1358. switch(src->identifierType) {
  1359. case UA_NODEIDTYPE_NUMERIC:
  1360. if(src->identifier.numeric > UA_UINT16_MAX || src->namespaceIndex > UA_BYTE_MAX) {
  1361. s += 6;
  1362. } else if(src->identifier.numeric > UA_BYTE_MAX || src->namespaceIndex > 0) {
  1363. s += 3;
  1364. } else {
  1365. s += 1;
  1366. }
  1367. break;
  1368. case UA_NODEIDTYPE_BYTESTRING:
  1369. case UA_NODEIDTYPE_STRING:
  1370. s += 2;
  1371. s += String_calcSizeBinary(&src->identifier.string, NULL);
  1372. break;
  1373. case UA_NODEIDTYPE_GUID:
  1374. s += 18;
  1375. break;
  1376. default:
  1377. return 0;
  1378. }
  1379. return s;
  1380. }
  1381. CALCSIZE_BINARY(ExpandedNodeId) {
  1382. size_t s = NodeId_calcSizeBinary(&src->nodeId, NULL);
  1383. if(src->namespaceUri.length > 0)
  1384. s += String_calcSizeBinary(&src->namespaceUri, NULL);
  1385. if(src->serverIndex > 0)
  1386. s += 4;
  1387. return s;
  1388. }
  1389. CALCSIZE_BINARY(QualifiedName) {
  1390. return 2 + String_calcSizeBinary(&src->name, NULL);
  1391. }
  1392. CALCSIZE_BINARY(LocalizedText) {
  1393. size_t s = 1; /* Encoding byte */
  1394. if(src->locale.data)
  1395. s += String_calcSizeBinary(&src->locale, NULL);
  1396. if(src->text.data)
  1397. s += String_calcSizeBinary(&src->text, NULL);
  1398. return s;
  1399. }
  1400. CALCSIZE_BINARY(ExtensionObject) {
  1401. size_t s = 1; /* Encoding byte */
  1402. /* Encoded content */
  1403. if(src->encoding <= UA_EXTENSIONOBJECT_ENCODED_XML) {
  1404. s += NodeId_calcSizeBinary(&src->content.encoded.typeId, NULL);
  1405. switch(src->encoding) {
  1406. case UA_EXTENSIONOBJECT_ENCODED_NOBODY:
  1407. break;
  1408. case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING:
  1409. case UA_EXTENSIONOBJECT_ENCODED_XML:
  1410. s += String_calcSizeBinary(&src->content.encoded.body, NULL);
  1411. break;
  1412. default:
  1413. return 0;
  1414. }
  1415. return s;
  1416. }
  1417. /* Decoded content */
  1418. if(!src->content.decoded.type || !src->content.decoded.data)
  1419. return 0;
  1420. if(src->content.decoded.type->typeId.identifierType != UA_NODEIDTYPE_NUMERIC)
  1421. return 0;
  1422. s += NodeId_calcSizeBinary(&src->content.decoded.type->typeId, NULL); /* Type encoding length */
  1423. s += 4; /* Encoding length field */
  1424. const UA_DataType *type = src->content.decoded.type;
  1425. s += calcSizeBinaryJumpTable[type->typeKind](src->content.decoded.data, type); /* Encoding length */
  1426. return s;
  1427. }
  1428. CALCSIZE_BINARY(Variant) {
  1429. size_t s = 1; /* Encoding byte */
  1430. if(!src->type)
  1431. return s;
  1432. const UA_Boolean isArray = src->arrayLength > 0 || src->data <= UA_EMPTY_ARRAY_SENTINEL;
  1433. if(isArray)
  1434. s += Array_calcSizeBinary(src->data, src->arrayLength, src->type);
  1435. else
  1436. s += calcSizeBinaryJumpTable[src->type->typeKind](src->data, src->type);
  1437. const UA_Boolean isBuiltin = (src->type->typeKind <= UA_DATATYPEKIND_DIAGNOSTICINFO);
  1438. const UA_Boolean isEnum = (src->type->typeKind == UA_DATATYPEKIND_ENUM);
  1439. if(!isBuiltin && !isEnum) {
  1440. /* The type is wrapped inside an extensionobject */
  1441. /* (NodeId + encoding byte + extension object length) * array length */
  1442. size_t length = isArray ? src->arrayLength : 1;
  1443. s += (NodeId_calcSizeBinary(&src->type->typeId, NULL) + 1 + 4) * length;
  1444. }
  1445. const UA_Boolean hasDimensions = isArray && src->arrayDimensionsSize > 0;
  1446. if(hasDimensions)
  1447. s += Array_calcSizeBinary(src->arrayDimensions, src->arrayDimensionsSize,
  1448. &UA_TYPES[UA_TYPES_INT32]);
  1449. return s;
  1450. }
  1451. CALCSIZE_BINARY(DataValue) {
  1452. size_t s = 1; /* Encoding byte */
  1453. if(src->hasValue)
  1454. s += Variant_calcSizeBinary(&src->value, NULL);
  1455. if(src->hasStatus)
  1456. s += 4;
  1457. if(src->hasSourceTimestamp)
  1458. s += 8;
  1459. if(src->hasSourcePicoseconds)
  1460. s += 2;
  1461. if(src->hasServerTimestamp)
  1462. s += 8;
  1463. if(src->hasServerPicoseconds)
  1464. s += 2;
  1465. return s;
  1466. }
  1467. CALCSIZE_BINARY(DiagnosticInfo) {
  1468. size_t s = 1; /* Encoding byte */
  1469. if(src->hasSymbolicId)
  1470. s += 4;
  1471. if(src->hasNamespaceUri)
  1472. s += 4;
  1473. if(src->hasLocalizedText)
  1474. s += 4;
  1475. if(src->hasLocale)
  1476. s += 4;
  1477. if(src->hasAdditionalInfo)
  1478. s += String_calcSizeBinary(&src->additionalInfo, NULL);
  1479. if(src->hasInnerStatusCode)
  1480. s += 4;
  1481. if(src->hasInnerDiagnosticInfo)
  1482. s += DiagnosticInfo_calcSizeBinary(src->innerDiagnosticInfo, NULL);
  1483. return s;
  1484. }
  1485. static size_t
  1486. calcSizeBinaryStructure(const void *p, const UA_DataType *type) {
  1487. size_t s = 0;
  1488. uintptr_t ptr = (uintptr_t)p;
  1489. u8 membersSize = type->membersSize;
  1490. const UA_DataType *typelists[2] = { UA_TYPES, &type[-type->typeIndex] };
  1491. /* Loop over members */
  1492. for(size_t i = 0; i < membersSize; ++i) {
  1493. const UA_DataTypeMember *member = &type->members[i];
  1494. const UA_DataType *membertype = &typelists[!member->namespaceZero][member->memberTypeIndex];
  1495. ptr += member->padding;
  1496. /* Array */
  1497. if(member->isArray) {
  1498. const size_t length = *((const size_t*)ptr);
  1499. ptr += sizeof(size_t);
  1500. s += Array_calcSizeBinary(*(void *UA_RESTRICT const *)ptr, length, membertype);
  1501. ptr += sizeof(void*);
  1502. continue;
  1503. }
  1504. /* Scalar */
  1505. s += calcSizeBinaryJumpTable[membertype->typeKind]((const void*)ptr, membertype);
  1506. ptr += membertype->memSize;
  1507. }
  1508. return s;
  1509. }
  1510. static size_t
  1511. calcSizeBinaryNotImplemented(const void *p, const UA_DataType *type) {
  1512. (void)p, (void)type;
  1513. return 0;
  1514. }
  1515. const calcSizeBinarySignature calcSizeBinaryJumpTable[UA_DATATYPEKINDS] = {
  1516. (calcSizeBinarySignature)calcSizeBinary1, /* Boolean */
  1517. (calcSizeBinarySignature)calcSizeBinary1, /* SByte */
  1518. (calcSizeBinarySignature)calcSizeBinary1, /* Byte */
  1519. (calcSizeBinarySignature)calcSizeBinary2, /* Int16 */
  1520. (calcSizeBinarySignature)calcSizeBinary2, /* UInt16 */
  1521. (calcSizeBinarySignature)calcSizeBinary4, /* Int32 */
  1522. (calcSizeBinarySignature)calcSizeBinary4, /* UInt32 */
  1523. (calcSizeBinarySignature)calcSizeBinary8, /* Int64 */
  1524. (calcSizeBinarySignature)calcSizeBinary8, /* UInt64 */
  1525. (calcSizeBinarySignature)calcSizeBinary4, /* Float */
  1526. (calcSizeBinarySignature)calcSizeBinary8, /* Double */
  1527. (calcSizeBinarySignature)String_calcSizeBinary,
  1528. (calcSizeBinarySignature)calcSizeBinary8, /* DateTime */
  1529. (calcSizeBinarySignature)Guid_calcSizeBinary,
  1530. (calcSizeBinarySignature)String_calcSizeBinary, /* ByteString */
  1531. (calcSizeBinarySignature)String_calcSizeBinary, /* XmlElement */
  1532. (calcSizeBinarySignature)NodeId_calcSizeBinary,
  1533. (calcSizeBinarySignature)ExpandedNodeId_calcSizeBinary,
  1534. (calcSizeBinarySignature)calcSizeBinary4, /* StatusCode */
  1535. (calcSizeBinarySignature)QualifiedName_calcSizeBinary,
  1536. (calcSizeBinarySignature)LocalizedText_calcSizeBinary,
  1537. (calcSizeBinarySignature)ExtensionObject_calcSizeBinary,
  1538. (calcSizeBinarySignature)DataValue_calcSizeBinary,
  1539. (calcSizeBinarySignature)Variant_calcSizeBinary,
  1540. (calcSizeBinarySignature)DiagnosticInfo_calcSizeBinary,
  1541. (calcSizeBinarySignature)calcSizeBinaryNotImplemented, /* Decimal */
  1542. (calcSizeBinarySignature)calcSizeBinary4, /* Enumeration */
  1543. (calcSizeBinarySignature)calcSizeBinaryStructure,
  1544. (calcSizeBinarySignature)calcSizeBinaryNotImplemented, /* Structure with Optional Fields */
  1545. (calcSizeBinarySignature)calcSizeBinaryNotImplemented, /* Union */
  1546. (calcSizeBinarySignature)calcSizeBinaryNotImplemented /* BitfieldCluster */
  1547. };
  1548. size_t
  1549. UA_calcSizeBinary(const void *p, const UA_DataType *type) {
  1550. return calcSizeBinaryJumpTable[type->typeKind](p, type);
  1551. }