ua_types_encoding_binary.c 61 KB

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