ua_types_encoding_binary.c 62 KB

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