2 * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 * @file rpc_marshall.c
19 * @brief RPC Library Internal Implementation--Argument Conversion During API Calls
27 #include <netinet/in.h>
30 #include <other_service/rpc.h>
31 #include "rpc_internal.h"
33 #include "apidef.tab.h"
36 /** @addtogroup RPClib_in
39 /** Structures for String Add Operations */
48 #define _STRING_ALLOC_UNIT 512
51 * Batch allocate total bytes of arguments + data to be added internally
52 * (maximal 6 bytes per argument)
54 #define _STRING_ALLOC_UNIT \
55 (RPC_MAX_API_ARG_TOTAL_SIZE + RPC_MAX_API_ARG_NUM * (2 + 4))
58 #define _ENOUGH_SPACE_FOR_ALL_TYPES \
59 (sizeof(UINT64) > sizeof(double) ? sizeof(UINT64) : sizeof(double))
61 static RpcString* NewRpcString(void);
63 static int StretchString(RpcString *str, UINT16 bytes);
65 static char *CopyString(RpcString *str, unsigned int *size);
66 static void DestroyString(RpcString *str);
67 static inline int AppendString(RpcString *str,
68 const UINT8 *append, UINT16 applen);
69 static inline int MarshallUINT8(RpcString *str, UINT8 uc);
70 static inline int MarshallUINT16(RpcString *str, UINT16 uh);
71 static inline int MarshallUINT32(RpcString *str, UINT32 ui);
72 static inline int MarshallUINT64(RpcString *str, UINT64 ul);
73 static inline int Marshallfloat(RpcString *str, float f);
74 static inline int Marshalldouble(RpcString *str, double d);
75 static inline int MarshallUINT8Stream(RpcString *str, const UINT8 *buf,
77 static inline int MarshallString(RpcString *str, char *buf,
79 static inline int MarshallNullPointer(RpcString *str);
80 static inline int MarshallPointer(RpcString *str);
86 str = rpc_malloc(sizeof(RpcString));
87 if (str == NULL) { // LCOV_EXCL_START 5: fail safe for libc malloc
88 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
92 str->start = rpc_malloc(_STRING_ALLOC_UNIT);
93 if (str->start == NULL) { // LCOV_EXCL_START 5: fail safe for libc malloc
94 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
101 str->remain = _STRING_ALLOC_UNIT - 1;
106 #ifdef STRETCH_STRING
108 StretchString(RpcString *str, UINT16 bytes) {
109 unsigned int oldunits = str->units;
110 unsigned int units = 1 + (bytes / _STRING_ALLOC_UNIT) + oldunits;
111 if (units == oldunits) {
114 unsigned int length = str->wp - str->start;
115 char *newp = rpc_malloc(units * _STRING_ALLOC_UNIT);
119 memcpy(newp, str->start, length);
120 rpc_free(str->start);
122 str->wp = str->start + length;
125 str->remain += (units - oldunits) * _STRING_ALLOC_UNIT;
128 #endif /* STRETCH_STRING */
131 AppendString(RpcString *str, const UINT8 *append, UINT16 applen) {
132 rpc_assert(append != NULL); // LCOV_EXCL_BR_LINE 6: double check
133 #ifdef STRETCH_STRING
134 if (applen > str->remain) {
135 if (StretchString(str, applen - str->remain) < 0) {
140 rpc_assert(applen <= str->remain); // LCOV_EXCL_BR_LINE 6: double check
142 memcpy(str->wp, append, applen);
144 str->remain -= applen;
149 CopyString(RpcString *str, unsigned int *size) {
150 unsigned int length = (unsigned int)(str->wp - str->start);
151 char *ret = rpc_malloc(length);
152 // LCOV_EXCL_BR_START 5: fail safe for libc malloc
157 memcpy(ret, str->start, length);
166 DestroyString(RpcString *str) {
167 rpc_free(str->start);
172 MarshallUINT8(RpcString *str, UINT8 c) {
173 UINT8 buf[1 + sizeof(c)];
176 return AppendString(str, buf, sizeof(buf));
180 MarshallUINT8Stream(RpcString *str, const UINT8 *buf, UINT16 bytes) {
181 int ret = AppendString(str, (const UINT8 *)"B", 1);
182 if (ret < 0) { // LCOV_EXCL_BR_LINE 15: inline func rpc_marshall.c
185 return AppendString(str, buf, bytes);
189 MarshallVararrayStream(RpcString *str, const UINT8 *buf, UINT16 bytes) {
190 char head_str[1+4+1+1]; /* Area where symbol "V" + size is stored */
191 sprintf(head_str, "V%03d ", bytes);
192 head_str[1+4+1] = '\0';
194 if (AppendString(str, (const UINT8 *)head_str, (UINT16)strlen(head_str)) < 0) { // LCOV_EXCL_BR_LINE 15: inline func rpc_marshall.c
198 if (AppendString(str, buf, bytes) < 0) { // LCOV_EXCL_BR_LINE 15: inline func rpc_marshall.c
205 MarshallString(RpcString *str, char *buf, UINT16 bytes) {
208 /* count the number of bytes in the argument */
209 while(*p != '\0' && count < (UINT16)(bytes - 1)) {
214 char count_str[1+strlen("1024")+1+1];
215 sprintf(count_str, "S%d ", count);
217 if (AppendString(str, (const UINT8 *)count_str, (UINT16)strlen(count_str)) < 0 || AppendString(str, (const UINT8 *)buf, count) < 0) { // LCOV_EXCL_BR_LINE 11: Unexpected branch // NOLINT(readability/nolint)
224 MarshallUINT16(RpcString *str, UINT16 uh) {
225 UINT8 buf[1 + sizeof(uh)];
227 memcpy(buf + 1, &uh, sizeof(uh));
228 return AppendString(str, buf, sizeof(buf));
232 MarshallUINT32(RpcString *str, UINT32 ui) {
233 UINT8 buf[1 + sizeof(ui)];
235 memcpy(buf + 1, &ui, sizeof(ui));
236 return AppendString(str, buf, sizeof(buf));
240 Marshallint(RpcString *str, int i) {
241 return MarshallUINT32(str, (UINT32)i);
245 MarshallUINT64(RpcString *str, UINT64 ul) {
246 UINT8 buf[1 + sizeof(ul)];
248 memcpy(buf + 1, &ul, sizeof(ul));
249 return AppendString(str, buf, sizeof(buf));
253 Marshallfloat(RpcString *str, float f) {
254 UINT8 buf[1 + sizeof(f)];
256 memcpy(buf + 1, &f, sizeof(f));
257 return AppendString(str, buf, sizeof(buf));
261 Marshalldouble(RpcString *str, double d) {
262 UINT8 buf[1 + sizeof(d)];
264 memcpy(buf + 1, &d, sizeof(d));
265 return AppendString(str, buf, sizeof(buf));
269 MarshallPointer(RpcString *str) {
270 /* only to specify that a non-NULL pointer was delivered */
271 return AppendString(str, (const UINT8 *)"P", 1);
275 MarshallNullPointer(RpcString *str /*, int code*/) {
276 return AppendString(str, (const UINT8 *)"N", 1);
279 /** @ingroup RPClib_in
282 #define MACROMarshallPointer(TYPE) \
284 TYPE *p = (TYPE *)temp; \
285 error = Marshall##TYPE(str, *p); \
288 #define MACROMarshallValue(TYPE, STACK_TYPE) \
290 TYPE value = (TYPE)va_arg(ap, STACK_TYPE); \
291 error = Marshall##TYPE(str, value); \
295 RPC_marshall_arguments(unsigned int *size, int dont_marshall_out_pointer,
297 rpc_assert(num_args <= RPC_MAX_API_ARG_NUM); // LCOV_EXCL_BR_LINE 6: double check
301 str = NewRpcString();
302 if (str == NULL) { // LCOV_EXCL_BR_LINE 5: fail safe for libc malloc
303 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
304 return NULL; // LCOV_EXCL_LINE 5: fail safe for libc malloc
307 va_start(ap, num_args);
312 for(ii = 0 ; ii < num_args && error == 0 ; ii++) {
313 unsigned int code, is_vararray, is_pointer, in_out, out_only;
315 unsigned int val = va_arg(ap, unsigned int);
317 RPC_marshall_flag flag;
318 flag.all = ntohl(val);
319 code = flag.bits.code;
320 is_vararray = flag.bits.is_vararray;
321 is_pointer = flag.bits.is_pointer;
322 in_out = flag.bits.in_out;
323 bytes = flag.bits.bytes;
324 rpc_assert(bytes <= RPC_MAX_API_ARG_SIZE); // LCOV_EXCL_BR_LINE 6: double check
328 if (in_out == RPC_OUT_ARG) { /* OUT only argument */
332 if (is_pointer) { /* Argument passed by pointer */
334 void *temp = (void *)va_arg(ap, void *);
337 error = MarshallNullPointer(str);
338 } else if (dont_marshall_out_pointer && out_only) {
339 /* Not refer to the contents of a pointer */
340 error = MarshallPointer(str);
341 } else {/* Marshall the contents of pointers */
343 /* Variable-length array */
344 error = MarshallVararrayStream(str, temp, bytes);
350 MACROMarshallPointer(UINT8);
354 MACROMarshallPointer(UINT16);
359 MACROMarshallPointer(int);
363 MACROMarshallPointer(UINT32);
367 MACROMarshallPointer(UINT64);
370 MACROMarshallPointer(float);
373 MACROMarshallPointer(double);
376 error = MarshallString(str, temp, bytes);
378 case rpc_USER_DEFINED:
379 error = MarshallUINT8Stream(str, temp, bytes);
387 } else {/* Argument passed by value */
389 /* Note: In this area, the code depends on the CPU architecture */
395 MACROMarshallValue(UINT8, unsigned int);
399 MACROMarshallValue(UINT16, unsigned int);
404 MACROMarshallValue(int, int); // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c
408 MACROMarshallValue(UINT32, UINT32); // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c
412 MACROMarshallValue(UINT64, UINT64); // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c
415 MACROMarshallValue(float, double); // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c
418 MACROMarshallValue(double, double); // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c
420 case rpc_USER_DEFINED:
421 rpc_assert(bytes <= sizeof(UINT64));
422 /* This area is very architecture-dependent! */
423 if (bytes <= sizeof(UINT32)) {
424 UINT32 value = (UINT32)va_arg(ap, UINT32); // LCOV_EXCL_BR_LINE 15: macro defined in stdarg.h
425 error = MarshallUINT8Stream(str, (UINT8 *)&value, bytes);
426 } else if (bytes <= sizeof(UINT64)) { // LCOV_EXCL_BR_LINE 6: double check
427 UINT64 value = (UINT64)va_arg(ap, UINT64); // LCOV_EXCL_BR_LINE 15: macro defined in stdarg.h
428 error = MarshallUINT8Stream(str, (UINT8 *)&value, bytes);
444 char *ret = CopyString(str, size);
449 static inline int DeMarshallUINT8(const char *from, UINT8 *ucp);
450 static inline int DeMarshallUINT16(const char *from, UINT16 *uhp);
451 static inline int DeMarshallUINT32(const char *from, UINT32 *uip);
452 static inline int DeMarshallUINT64(const char *from, UINT64 *ulp);
453 static inline int DeMarshallfloat(const char *from, float *fp);
454 static inline int DeMarshalldouble(const char *from, double *dp);
455 static inline int DeMarshallUINT8Stream(const char *from, UINT8 *buffer,
457 static inline int DeMarshallString(const char *from, char *buffer,
461 DeMarshallUINT8(const char *from, UINT8 *ucp) {
463 *ucp = *(UINT8 *)(from + 1);
464 return 1 + sizeof(*ucp);
471 DeMarshallUINT16(const char *from, UINT16 *uhp) {
473 memcpy(uhp, from + 1, sizeof(*uhp));
474 return 1 + sizeof(*uhp);
481 DeMarshallUINT32(const char *from, UINT32 *uip) {
483 memcpy(uip, from + 1, sizeof(*uip));
484 return 1 + sizeof(*uip);
491 DeMarshallint(const char *from, int *ip) {
492 return DeMarshallUINT32(from, (UINT32 *)ip);
496 DeMarshallUINT64(const char *from, UINT64 *ulp) {
498 memcpy(ulp, from + 1, sizeof(*ulp));
499 return 1 + sizeof(*ulp);
506 DeMarshallfloat(const char *from, float *fp) {
508 memcpy(fp, from + 1, sizeof(*fp));
509 return 1 + sizeof(*fp);
516 DeMarshalldouble(const char *from, double *dp) {
518 memcpy(dp, from + 1, sizeof(*dp));
520 return 1 + sizeof(*dp);
527 DeMarshallUINT8Stream(const char *from, UINT8 *buffer, UINT16 bytes) {
529 memcpy(buffer, from + 1, bytes);
530 return (int)(1 + bytes);
537 DeMarshallString(const char *from, char *buffer, UINT16 bytes) {
540 long len = strtol(from + 1, &start, 10);
541 if (len < 0 || len >= bytes) { // LCOV_EXCL_BR_LINE 5: fail safe for libc strtol
544 start++; /* skip ' ' */
545 int skip = (int)(start - from);
546 memcpy(buffer, start, (size_t)len);
548 return skip + (int)len;
554 /* Variable-length array data */
556 DemarshallVararrayInfo(const char *from, UINT16 *bytes/* OUT */) {
559 long len = strtol((char *)(from + 1), &end, 10);
560 if (len <= 0 || len > RPC_MAX_API_ARG_SIZE) { // LCOV_EXCL_BR_LINE 5: fail safe for libc strtol
563 *bytes = (UINT16)len;
564 return (int)(end - from + 1); /* skip ' ' */
570 /** @ingroup RPClib_in
573 #define MACRODemarshall(TYPE) \
576 if (need_alloc && is_pointer) { \
577 p = rpc_malloc(sizeof(TYPE)); \
578 *(TYPE **)temp = p; \
583 ret = DeMarshall##TYPE(from, p); \
588 RPC_demarshall_arguments(const char *from, unsigned int size,
589 int need_alloc, int num_args, ...) {
590 rpc_assert(num_args <= RPC_MAX_API_ARG_NUM); // LCOV_EXCL_BR_LINE 6: double check
592 va_start(ap, num_args);
596 int remain_len = (int)size;
598 for(ii = 0 ; ii < num_args && error == 0 && remain_len > 0 ; ii++) {
599 unsigned int code, is_pointer, is_vararray;
601 unsigned int val = va_arg(ap, unsigned int);
602 RPC_marshall_flag flag;
603 flag.all = ntohl(val);
604 code = flag.bits.code;
605 is_vararray = flag.bits.is_vararray;
606 is_pointer = flag.bits.is_pointer;
607 bytes = flag.bits.bytes;
608 rpc_assert(bytes <= RPC_MAX_API_ARG_SIZE); // LCOV_EXCL_BR_LINE 6: double check
611 void *temp = va_arg(ap, void *);
614 if (*from == 'N') { /* NULL pointer */
615 if (bytes > 0 || is_pointer != 0) {
617 *(void **)temp = NULL;
623 } else if (*from == 'P') { /* Pointer(no content) */
625 if (bytes > 0) { /* String type or user-defined type */
626 *(void **)temp = rpc_malloc(bytes);
627 } else if (is_pointer != 0) { /* Other pointers */
628 *(void **)temp = rpc_malloc(_ENOUGH_SPACE_FOR_ALL_TYPES);
632 } else { /* non-NULL pointer */
633 if ( is_vararray ) { /* Variable-length array */
634 ret = DemarshallVararrayInfo(from, &bytes);
637 return -1; /* pgr0524 */
641 p = rpc_malloc(sizeof(char)*bytes);
644 p = (char *)temp; /* pgr0524 */
647 memcpy(p, from + ret, bytes);
655 MACRODemarshall(UINT8); /* pgr0524 */ // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c
659 MACRODemarshall(UINT16); /* pgr0524 */ // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c
664 MACRODemarshall(int); /* pgr0524 */ // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c
668 MACRODemarshall(UINT32); /* pgr0524 */ // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c
672 MACRODemarshall(UINT64); /* pgr0524 */ // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c
675 MACRODemarshall(float); /* pgr0524 */ // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c
678 MACRODemarshall(double); /* pgr0524 */ // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c
680 case rpc_USER_DEFINED: {
682 if (need_alloc && is_pointer) {
683 p = rpc_malloc(bytes);
686 p = (UINT8 *)temp; /* pgr0524 */
689 ret = DeMarshallUINT8Stream(from, p, bytes);
696 p = rpc_malloc(sizeof(char)*bytes);
699 p = (char *)temp; /* pgr0524 */
702 ret = DeMarshallString(from, p, bytes);
721 return -1; /* pgr0524 */
723 return 0; /* pgr0524 */
728 RPC_marshall_free(int num, ...) {
733 for(i = 0 ; i < num ; i++) {
734 void *ptr = va_arg(ap, void *); // LCOV_EXCL_BR_LINE 15: macro defined in stdarg.h