X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=service%2Fother%2Frpc_library%2Flibrary%2Fsrc%2Frpc_marshall.c;fp=service%2Fother%2Frpc_library%2Flibrary%2Fsrc%2Frpc_marshall.c;h=8a4a56af86deebb29d0796c62b3380c5b233fde8;hb=17cf21bcf8a2e29d2cbcf0a313474d2a4ee44f5d;hp=0000000000000000000000000000000000000000;hpb=9e86046cdb356913ae026f616e5bf17f6f238aa5;p=staging%2Fbasesystem.git diff --git a/service/other/rpc_library/library/src/rpc_marshall.c b/service/other/rpc_library/library/src/rpc_marshall.c new file mode 100755 index 0000000..8a4a56a --- /dev/null +++ b/service/other/rpc_library/library/src/rpc_marshall.c @@ -0,0 +1,740 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file rpc_marshall.c + * @brief RPC Library Internal Implementation--Argument Conversion During API Calls + * + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include "rpc_internal.h" + +#include "apidef.tab.h" +#include "apidef.h" + +/** @addtogroup RPClib_in + * @{ + */ +/** Structures for String Add Operations */ +typedef struct { + char *start; + char *wp; + unsigned int units; + unsigned int remain; +} RpcString; + +#ifdef STRETCH_STRING +#define _STRING_ALLOC_UNIT 512 +#else +/* + * Batch allocate total bytes of arguments + data to be added internally + * (maximal 6 bytes per argument) + */ +#define _STRING_ALLOC_UNIT \ + (RPC_MAX_API_ARG_TOTAL_SIZE + RPC_MAX_API_ARG_NUM * (2 + 4)) +#endif + +#define _ENOUGH_SPACE_FOR_ALL_TYPES \ + (sizeof(UINT64) > sizeof(double) ? sizeof(UINT64) : sizeof(double)) + +static RpcString* NewRpcString(void); +#ifdef STRETCH_STRING +static int StretchString(RpcString *str, UINT16 bytes); +#endif +static char *CopyString(RpcString *str, unsigned int *size); +static void DestroyString(RpcString *str); +static inline int AppendString(RpcString *str, + const UINT8 *append, UINT16 applen); +static inline int MarshallUINT8(RpcString *str, UINT8 uc); +static inline int MarshallUINT16(RpcString *str, UINT16 uh); +static inline int MarshallUINT32(RpcString *str, UINT32 ui); +static inline int MarshallUINT64(RpcString *str, UINT64 ul); +static inline int Marshallfloat(RpcString *str, float f); +static inline int Marshalldouble(RpcString *str, double d); +static inline int MarshallUINT8Stream(RpcString *str, const UINT8 *buf, + UINT16 bytes); +static inline int MarshallString(RpcString *str, char *buf, + UINT16 bytes); +static inline int MarshallNullPointer(RpcString *str); +static inline int MarshallPointer(RpcString *str); + +static RpcString * +NewRpcString(void) { + RpcString *str; + + str = rpc_malloc(sizeof(RpcString)); + if (str == NULL) { // LCOV_EXCL_START 5: fail safe for libc malloc + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return NULL; + } // LCOV_EXCL_STOP + + str->start = rpc_malloc(_STRING_ALLOC_UNIT); + if (str->start == NULL) { // LCOV_EXCL_START 5: fail safe for libc malloc + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + rpc_free(str); + return NULL; + } // LCOV_EXCL_STOP + str->start[0] = '\0'; + str->wp = str->start; + str->units = 1; + str->remain = _STRING_ALLOC_UNIT - 1; + + return str; +} + +#ifdef STRETCH_STRING +static int +StretchString(RpcString *str, UINT16 bytes) { + unsigned int oldunits = str->units; + unsigned int units = 1 + (bytes / _STRING_ALLOC_UNIT) + oldunits; + if (units == oldunits) { + return 0; + } + unsigned int length = str->wp - str->start; + char *newp = rpc_malloc(units * _STRING_ALLOC_UNIT); + if (newp == NULL) { + return -1; + } + memcpy(newp, str->start, length); + rpc_free(str->start); + str->start = newp; + str->wp = str->start + length; + *(str->wp) = '\0'; + str->units = units; + str->remain += (units - oldunits) * _STRING_ALLOC_UNIT; + return 0; +} +#endif /* STRETCH_STRING */ + +static inline int +AppendString(RpcString *str, const UINT8 *append, UINT16 applen) { + rpc_assert(append != NULL); // LCOV_EXCL_BR_LINE 6: double check +#ifdef STRETCH_STRING + if (applen > str->remain) { + if (StretchString(str, applen - str->remain) < 0) { + return -1; + } + } +#else + rpc_assert(applen <= str->remain); // LCOV_EXCL_BR_LINE 6: double check +#endif + memcpy(str->wp, append, applen); + str->wp += applen; + str->remain -= applen; + return 0; +} + +static char * +CopyString(RpcString *str, unsigned int *size) { + unsigned int length = (unsigned int)(str->wp - str->start); + char *ret = rpc_malloc(length); + // LCOV_EXCL_BR_START 5: fail safe for libc malloc + if (ret == NULL) { + return NULL; + } + // LCOV_EXCL_BR_STOP + memcpy(ret, str->start, length); + if (size != NULL) { + *size = length; + } + + return ret; +} + +static void +DestroyString(RpcString *str) { + rpc_free(str->start); + rpc_free(str); +} + +static inline int +MarshallUINT8(RpcString *str, UINT8 c) { + UINT8 buf[1 + sizeof(c)]; + buf[0] = 'C'; + buf[1] = c; + return AppendString(str, buf, sizeof(buf)); +} + +static inline int +MarshallUINT8Stream(RpcString *str, const UINT8 *buf, UINT16 bytes) { + int ret = AppendString(str, (const UINT8 *)"B", 1); + if (ret < 0) { // LCOV_EXCL_BR_LINE 15: inline func rpc_marshall.c + return -1; + } + return AppendString(str, buf, bytes); +} + +static inline int +MarshallVararrayStream(RpcString *str, const UINT8 *buf, UINT16 bytes) { + char head_str[1+4+1+1]; /* Area where symbol "V" + size is stored */ + sprintf(head_str, "V%03d ", bytes); + head_str[1+4+1] = '\0'; + + if (AppendString(str, (const UINT8 *)head_str, (UINT16)strlen(head_str)) < 0) { // LCOV_EXCL_BR_LINE 15: inline func rpc_marshall.c + return -1; + } + + if (AppendString(str, buf, bytes) < 0) { // LCOV_EXCL_BR_LINE 15: inline func rpc_marshall.c + return -1; + } + return 0; +} + +static inline int +MarshallString(RpcString *str, char *buf, UINT16 bytes) { + char *p = buf; + UINT16 count = 0; + /* count the number of bytes in the argument */ + while(*p != '\0' && count < (UINT16)(bytes - 1)) { + count++; + p++; + } + + char count_str[1+strlen("1024")+1+1]; + sprintf(count_str, "S%d ", count); + + 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) + return -1; + } + return 0; +} + +static int +MarshallUINT16(RpcString *str, UINT16 uh) { + UINT8 buf[1 + sizeof(uh)]; + buf[0] = 'H'; + memcpy(buf + 1, &uh, sizeof(uh)); + return AppendString(str, buf, sizeof(buf)); +} + +static inline int +MarshallUINT32(RpcString *str, UINT32 ui) { + UINT8 buf[1 + sizeof(ui)]; + buf[0] = 'I'; + memcpy(buf + 1, &ui, sizeof(ui)); + return AppendString(str, buf, sizeof(buf)); +} + +static inline int +Marshallint(RpcString *str, int i) { + return MarshallUINT32(str, (UINT32)i); +} + +static inline int +MarshallUINT64(RpcString *str, UINT64 ul) { + UINT8 buf[1 + sizeof(ul)]; + buf[0] = 'L'; + memcpy(buf + 1, &ul, sizeof(ul)); + return AppendString(str, buf, sizeof(buf)); +} + +static inline int +Marshallfloat(RpcString *str, float f) { + UINT8 buf[1 + sizeof(f)]; + buf[0] = 'F'; + memcpy(buf + 1, &f, sizeof(f)); + return AppendString(str, buf, sizeof(buf)); +} + +static inline int +Marshalldouble(RpcString *str, double d) { + UINT8 buf[1 + sizeof(d)]; + buf[0] = 'D'; + memcpy(buf + 1, &d, sizeof(d)); + return AppendString(str, buf, sizeof(buf)); +} + +static inline int +MarshallPointer(RpcString *str) { + /* only to specify that a non-NULL pointer was delivered */ + return AppendString(str, (const UINT8 *)"P", 1); +} + +static inline int +MarshallNullPointer(RpcString *str /*, int code*/) { + return AppendString(str, (const UINT8 *)"N", 1); +} + +/** @ingroup RPClib_in + */ + +#define MACROMarshallPointer(TYPE) \ + do { \ + TYPE *p = (TYPE *)temp; \ + error = Marshall##TYPE(str, *p); \ + } while(0) + +#define MACROMarshallValue(TYPE, STACK_TYPE) \ + do { \ + TYPE value = (TYPE)va_arg(ap, STACK_TYPE); \ + error = Marshall##TYPE(str, value); \ + } while(0) + +char * +RPC_marshall_arguments(unsigned int *size, int dont_marshall_out_pointer, + int num_args, ...) { + rpc_assert(num_args <= RPC_MAX_API_ARG_NUM); // LCOV_EXCL_BR_LINE 6: double check + va_list ap; + + RpcString *str; + str = NewRpcString(); + if (str == NULL) { // LCOV_EXCL_BR_LINE 5: fail safe for libc malloc + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return NULL; // LCOV_EXCL_LINE 5: fail safe for libc malloc + } + + va_start(ap, num_args); + + int ii, error; + error = 0; + + for(ii = 0 ; ii < num_args && error == 0 ; ii++) { + unsigned int code, is_vararray, is_pointer, in_out, out_only; + UINT16 bytes; + unsigned int val = va_arg(ap, unsigned int); + + RPC_marshall_flag flag; + flag.all = ntohl(val); + code = flag.bits.code; + is_vararray = flag.bits.is_vararray; + is_pointer = flag.bits.is_pointer; + in_out = flag.bits.in_out; + bytes = flag.bits.bytes; + rpc_assert(bytes <= RPC_MAX_API_ARG_SIZE); // LCOV_EXCL_BR_LINE 6: double check + + + out_only = 0; + if (in_out == RPC_OUT_ARG) { /* OUT only argument */ + out_only = 1; + } + + if (is_pointer) { /* Argument passed by pointer */ + + void *temp = (void *)va_arg(ap, void *); + if (temp == NULL) { + /* NULL pointer */ + error = MarshallNullPointer(str); + } else if (dont_marshall_out_pointer && out_only) { + /* Not refer to the contents of a pointer */ + error = MarshallPointer(str); + } else {/* Marshall the contents of pointers */ + if (is_vararray) { + /* Variable-length array */ + error = MarshallVararrayStream(str, temp, bytes); + } else { + switch(code) { + case rpc_CHAR: + case rpc_INT8: + case rpc_UINT8: + MACROMarshallPointer(UINT8); + break; + case rpc_INT16: + case rpc_UINT16: + MACROMarshallPointer(UINT16); + break; + case rpc_INT: + case rpc_SINT: + case rpc_UINT: + MACROMarshallPointer(int); + break; + case rpc_INT32: + case rpc_UINT32: + MACROMarshallPointer(UINT32); + break; + case rpc_INT64: + case rpc_UINT64: + MACROMarshallPointer(UINT64); + break; + case rpc_FLOAT: + MACROMarshallPointer(float); + break; + case rpc_DOUBLE: + MACROMarshallPointer(double); + break; + case rpc_STRING: + error = MarshallString(str, temp, bytes); + break; + case rpc_USER_DEFINED: + error = MarshallUINT8Stream(str, temp, bytes); + break; + default: + error = -1; + break; + } + } + } + } else {/* Argument passed by value */ + + /* Note: In this area, the code depends on the CPU architecture */ + + switch(code) { + case rpc_CHAR: + case rpc_INT8: + case rpc_UINT8: + MACROMarshallValue(UINT8, unsigned int); + break; + case rpc_INT16: + case rpc_UINT16: + MACROMarshallValue(UINT16, unsigned int); + break; + case rpc_INT: + case rpc_SINT: + case rpc_UINT: + MACROMarshallValue(int, int); // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c + break; + case rpc_INT32: + case rpc_UINT32: + MACROMarshallValue(UINT32, UINT32); // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c + break; + case rpc_INT64: + case rpc_UINT64: + MACROMarshallValue(UINT64, UINT64); // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c + break; + case rpc_FLOAT: + MACROMarshallValue(float, double); // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c + break; + case rpc_DOUBLE: + MACROMarshallValue(double, double); // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c + break; + case rpc_USER_DEFINED: + rpc_assert(bytes <= sizeof(UINT64)); + /* This area is very architecture-dependent! */ + if (bytes <= sizeof(UINT32)) { + UINT32 value = (UINT32)va_arg(ap, UINT32); // LCOV_EXCL_BR_LINE 15: macro defined in stdarg.h + error = MarshallUINT8Stream(str, (UINT8 *)&value, bytes); + } else if (bytes <= sizeof(UINT64)) { // LCOV_EXCL_BR_LINE 6: double check + UINT64 value = (UINT64)va_arg(ap, UINT64); // LCOV_EXCL_BR_LINE 15: macro defined in stdarg.h + error = MarshallUINT8Stream(str, (UINT8 *)&value, bytes); + } + break; + default: + error = -1; + break; + } + } + } + va_end(ap); + + if (error != 0) { + DestroyString(str); + return NULL; + } + + char *ret = CopyString(str, size); + DestroyString(str); + return ret; +} + +static inline int DeMarshallUINT8(const char *from, UINT8 *ucp); +static inline int DeMarshallUINT16(const char *from, UINT16 *uhp); +static inline int DeMarshallUINT32(const char *from, UINT32 *uip); +static inline int DeMarshallUINT64(const char *from, UINT64 *ulp); +static inline int DeMarshallfloat(const char *from, float *fp); +static inline int DeMarshalldouble(const char *from, double *dp); +static inline int DeMarshallUINT8Stream(const char *from, UINT8 *buffer, + UINT16 bytes); +static inline int DeMarshallString(const char *from, char *buffer, + UINT16 bytes); + +static inline int +DeMarshallUINT8(const char *from, UINT8 *ucp) { + if (*from == 'C') { + *ucp = *(UINT8 *)(from + 1); + return 1 + sizeof(*ucp); + } else { + return -1; + } +} + +static inline int +DeMarshallUINT16(const char *from, UINT16 *uhp) { + if (*from == 'H') { + memcpy(uhp, from + 1, sizeof(*uhp)); + return 1 + sizeof(*uhp); + } else { + return -1; + } +} + +static inline int +DeMarshallUINT32(const char *from, UINT32 *uip) { + if (*from == 'I') { + memcpy(uip, from + 1, sizeof(*uip)); + return 1 + sizeof(*uip); + } else { + return -1; + } +} + +static inline int +DeMarshallint(const char *from, int *ip) { + return DeMarshallUINT32(from, (UINT32 *)ip); +} + +static inline int +DeMarshallUINT64(const char *from, UINT64 *ulp) { + if (*from == 'L') { + memcpy(ulp, from + 1, sizeof(*ulp)); + return 1 + sizeof(*ulp); + } else { + return -1; + } +} + +static inline int +DeMarshallfloat(const char *from, float *fp) { + if (*from == 'F') { + memcpy(fp, from + 1, sizeof(*fp)); + return 1 + sizeof(*fp); + } else { + return -1; + } +} + +static inline int +DeMarshalldouble(const char *from, double *dp) { + if (*from == 'D') { + memcpy(dp, from + 1, sizeof(*dp)); + + return 1 + sizeof(*dp); + } else { + return -1; + } +} + +static inline int +DeMarshallUINT8Stream(const char *from, UINT8 *buffer, UINT16 bytes) { + if (*from == 'B') { + memcpy(buffer, from + 1, bytes); + return (int)(1 + bytes); + } else { + return -1; + } +} + +static inline int +DeMarshallString(const char *from, char *buffer, UINT16 bytes) { + if (*from == 'S') { + char *start; + long len = strtol(from + 1, &start, 10); + if (len < 0 || len >= bytes) { // LCOV_EXCL_BR_LINE 5: fail safe for libc strtol + return -1; + } + start++; /* skip ' ' */ + int skip = (int)(start - from); + memcpy(buffer, start, (size_t)len); + buffer[len] = '\0'; + return skip + (int)len; + } else { + return -1; + } +} + +/* Variable-length array data */ +static inline int +DemarshallVararrayInfo(const char *from, UINT16 *bytes/* OUT */) { + if (*from == 'V') { + char *end; + long len = strtol((char *)(from + 1), &end, 10); + if (len <= 0 || len > RPC_MAX_API_ARG_SIZE) { // LCOV_EXCL_BR_LINE 5: fail safe for libc strtol + return -1; + } + *bytes = (UINT16)len; + return (int)(end - from + 1); /* skip ' ' */ + } else { + return -1; + } +} + +/** @ingroup RPClib_in + */ + +#define MACRODemarshall(TYPE) \ + do {\ + TYPE *p; \ + if (need_alloc && is_pointer) { \ + p = rpc_malloc(sizeof(TYPE)); \ + *(TYPE **)temp = p; \ + } else { \ + p = (TYPE *)temp; \ + } \ + if (p != NULL) { \ + ret = DeMarshall##TYPE(from, p); \ + } \ + } while(0) + +int +RPC_demarshall_arguments(const char *from, unsigned int size, + int need_alloc, int num_args, ...) { + rpc_assert(num_args <= RPC_MAX_API_ARG_NUM); // LCOV_EXCL_BR_LINE 6: double check + va_list ap; + va_start(ap, num_args); + + int ii, error; + error = 0; + int remain_len = (int)size; + + for(ii = 0 ; ii < num_args && error == 0 && remain_len > 0 ; ii++) { + unsigned int code, is_pointer, is_vararray; + UINT16 bytes; + unsigned int val = va_arg(ap, unsigned int); + RPC_marshall_flag flag; + flag.all = ntohl(val); + code = flag.bits.code; + is_vararray = flag.bits.is_vararray; + is_pointer = flag.bits.is_pointer; + bytes = flag.bits.bytes; + rpc_assert(bytes <= RPC_MAX_API_ARG_SIZE); // LCOV_EXCL_BR_LINE 6: double check + + + void *temp = va_arg(ap, void *); + int ret = -1; + + if (*from == 'N') { /* NULL pointer */ + if (bytes > 0 || is_pointer != 0) { + if (need_alloc) { + *(void **)temp = NULL; + } else { + /* do nothing */ + } + ret = 1; + } + } else if (*from == 'P') { /* Pointer(no content) */ + if (need_alloc) { + if (bytes > 0) { /* String type or user-defined type */ + *(void **)temp = rpc_malloc(bytes); + } else if (is_pointer != 0) { /* Other pointers */ + *(void **)temp = rpc_malloc(_ENOUGH_SPACE_FOR_ALL_TYPES); + } + ret = 1; + } + } else { /* non-NULL pointer */ + if ( is_vararray ) { /* Variable-length array */ + ret = DemarshallVararrayInfo(from, &bytes); + if( ret < 0 ) { + va_end(ap); + return -1; /* pgr0524 */ + } + char *p; + if (need_alloc) { + p = rpc_malloc(sizeof(char)*bytes); + *(char **)temp = p; + } else { + p = (char *)temp; /* pgr0524 */ + } + if (p != NULL) { + memcpy(p, from + ret, bytes); + ret += bytes; + } + } else { + switch(code) { + case rpc_CHAR: + case rpc_INT8: + case rpc_UINT8: + MACRODemarshall(UINT8); /* pgr0524 */ // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c + break; + case rpc_INT16: + case rpc_UINT16: + MACRODemarshall(UINT16); /* pgr0524 */ // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c + break; + case rpc_INT: + case rpc_SINT: + case rpc_UINT: + MACRODemarshall(int); /* pgr0524 */ // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c + break; + case rpc_INT32: + case rpc_UINT32: + MACRODemarshall(UINT32); /* pgr0524 */ // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c + break; + case rpc_INT64: + case rpc_UINT64: + MACRODemarshall(UINT64); /* pgr0524 */ // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c + break; + case rpc_FLOAT: + MACRODemarshall(float); /* pgr0524 */ // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c + break; + case rpc_DOUBLE: + MACRODemarshall(double); /* pgr0524 */ // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c + break; + case rpc_USER_DEFINED: { + UINT8 *p; + if (need_alloc && is_pointer) { + p = rpc_malloc(bytes); + *(UINT8 **)temp = p; + } else { + p = (UINT8 *)temp; /* pgr0524 */ + } + if (p != NULL) { + ret = DeMarshallUINT8Stream(from, p, bytes); + } + break; + } + case rpc_STRING: { + char *p; + if (need_alloc) { + p = rpc_malloc(sizeof(char)*bytes); + *(char **)temp = p; + } else { + p = (char *)temp; /* pgr0524 */ + } + if (p != NULL) { + ret = DeMarshallString(from, p, bytes); + } + break; + } + default: + break; + } + } + } + if (ret < 0) { + error = 1; + } else { + remain_len -= ret; + from += ret; + } + } + va_end(ap); + + if (error) { + return -1; /* pgr0524 */ + } else { + return 0; /* pgr0524 */ + } +} + +void +RPC_marshall_free(int num, ...) { + va_list ap; + va_start(ap, num); + + int i; + for(i = 0 ; i < num ; i++) { + void *ptr = va_arg(ap, void *); // LCOV_EXCL_BR_LINE 15: macro defined in stdarg.h + if (ptr != NULL) { + rpc_free(ptr); + } + } + va_end(ap); +}