From 743e39eb1c5ab4fb1d6ab94aeb673e8ac463c243 Mon Sep 17 00:00:00 2001 From: ToshikazuOhiwa Date: Mon, 30 Mar 2020 09:32:57 +0900 Subject: ns-frameworkunified branch --- .../NS_MessageCenter/src/makefile_PosixBasedOS001 | 214 ++++ .../NS_MessageCenter/src/ns_message_center.c | 1245 ++++++++++++++++++++ 2 files changed, 1459 insertions(+) create mode 100644 framework_unified/client/NS_MessageCenter/src/makefile_PosixBasedOS001 create mode 100644 framework_unified/client/NS_MessageCenter/src/ns_message_center.c (limited to 'framework_unified/client/NS_MessageCenter/src') diff --git a/framework_unified/client/NS_MessageCenter/src/makefile_PosixBasedOS001 b/framework_unified/client/NS_MessageCenter/src/makefile_PosixBasedOS001 new file mode 100644 index 00000000..cfe15a70 --- /dev/null +++ b/framework_unified/client/NS_MessageCenter/src/makefile_PosixBasedOS001 @@ -0,0 +1,214 @@ +# +# @copyright Copyright (c) 2016-2019 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. +# + +# +# Standard Module Makefile version 2.0 +# + +# Name of the componet (team/domain prefix '_' component name) +COMPONENT_NAME = NS_MessageCenter + +ifndef PRJ_ROOT +export PRJ_ROOT = $(CURDIR)/../ +endif +include $(PRJ_ROOT)cfg/depends.mk + +# Name of the componet (team/domain prefix '_' component name) +# This must be the same as the RTC Component name and Eclipse Project Name +COMPONENT_NAME = NS_MessageCenter + + +# Additive Compile Flags (Flags from initiating make process will still apply) +DEFS += + +# Set local includes and then the reference includes (priority order determines search path) +# Default pattern are any configuration includes (which would be things like PosixBasedOS001), local (Team) component directories, +# dependencies includes (other teams) +# Local (current component references should be in the form of +# $(CC_IFLAG)$(TEAM_ROOT)$(COMPONENT_NAME)/directory +# Example your public include directory would be +# $(CC_IFLAG)$(TEAM_ROOT)$(COMPONENT_NAME)/inc +# Team references should only be to other's public includes such as +# $(CC_IFLAG)$(TEAM_ROOT)NS_MessageCenter/inc +# Global (non-team) references should be only to other's public includes such +# these are found in the depends include file and captured in the (DEPENDS_INCLUDES) variable +INCLUDES = \ + $(CFG_INCS) \ + $(CC_IFLAG)./ \ + $(DEPENDS_INCLUDES) \ + $(CC_IFLAG)$(TEAM_ROOT)NS_MessageQueue/inc \ + $(CC_IFLAG)$(TEAM_ROOT)NS_SharedMemIf/inc \ + $(CC_IFLAG)$(TEAM_ROOT)$(COMPONENT_NAME)/inc + + +# Do the same if you need to include library paths as well +# Do an incremental in case additional library paths are defined +# at the top-level make. Use similar guidelines as for includes +# for example to include a team component library it would be +# $(TEAM_ROOT)NS_MessageCenter/lib/NS_MessageCenter/ +LIB_PATHS += \ + $(DEPENDS_LIB_PATHS) \ + + + +# Define binary outputs. These can be libraries or executables. +# Name a variable for each deliverable. Suffixes should be +# EXEC - For Executables -> output to the bin directory +#TIME_EXEC = $(BIN_PATH)time +# LIB - For Static Libraries -> output to lib directory with specific naming +#MATH_LIB = $(LIB_PATH)$(LIB_PREFIX)math.$(LIB_EXT) +# SLIB - For Shared Objects +#FRMWRK_SLIB = $(SLIB_PATH)frmwrk.$(SO_EXT) +# LIB - Define the static library for Message Queue +# +# +ifdef DYNAMIC + COMPONENT_LIB = $(SLIB_PATH)$(LIB_PREFIX)$(COMPONENT_NAME)$(DEBUG_EXT).$(SO_EXT) +else + COMPONENT_LIB = $(LIB_PATH)$(LIB_PREFIX)$(COMPONENT_NAME)$(DEBUG_EXT).$(LIB_EXT) +endif + +## Sources Section + +# Define Library & Executable Sources (on a per deliverable basis) +# This includes sources located in subdirectories. + +# Define generic line that pulls all c, cc, cpp files +# since your in the src folder is pull only files from there +COMPONENT_SRCS = \ + $(wildcard *.c) \ + $(wildcard *.cpp) + +# Define sources that my not be local to your component +# here, you can define indivial files or wildcard from +# a different folder. +NON_LOCAL_SRCS = \ + + +# List of all sources to be built. Can be assembled from the other defintitions. +# This only defines sources for the current directory, so if there are subdirectories +# those are not included. (Those are found in simple subdirectory makefiles that only +# direct the building of sources, but no linking into a binary) +SOURCES = \ + $(COMPONENT_SRCS) \ + $(NON_LOCAL_SRCS) \ + + + +# +# Convert the source files to object files with correct folder location. +# +# +C_LANG_OBJECTS = $(addprefix $(BLD_PATH),$(addsuffix .$(OBJ_EXT),$(basename $(filter %.c ,$(SOURCES) ) ) ) ) +CPP_LANG_OBJECTS = $(addprefix $(BLD_PATH),$(addsuffix .$(OBJ_EXT),$(basename $(filter %.cpp %.cc %.cxx,$(SOURCES) ) ) ) ) + + +# List of all sources to be generated. Can be assembled from the other defintitions. +OBJECTS = \ + $(C_LANG_OBJECTS) \ + $(CPP_LANG_OBJECTS) + + + +# All headers that are dependencies. Wildcard is easy to pickup local headers. +# This is only to automate the rebuilding, all builds on the servers are cleans +# So this is not a huge deal when building on a component level. +HEADERS = \ + $(wildcard *.h) \ + $(wildcard $(TEAM_ROOT)$(COMPONENT_NAME)/inc/*.h) \ + $(wildcard $(TEAM_ROOT)NativeServices/inc/*.h) \ + $(wildcard $(TEAM_ROOT)NativeServices/inc/native/*.h) \ + $(wildcard $(TEAM_ROOT)NS_MessageQueue/inc/*.h) \ + $(wildcard $(TEAM_ROOT)NS_SharedMemIf/inc/*.h) \ + + +LIBRARIES = \ + $(COMPONENT_LIB) \ + +ifdef DYNAMIC + DYNAMIC_LIBS += \ + NS_SharedMemIf$(DEBUG_EXT) \ + NS_MessageQueue$(DEBUG_EXT) +else + STATIC_LIBS += +endif + + +# Make targets +# Standard +all: banner module_dirs subdirs local library binary + +debug: + $(MAKE) TARGET=arm DEBUG=TRUE all + +base: banner module_dirs subdirs local + +# Standard Building of Source Files (Default builds for all objects defined above) +$(C_LANG_OBJECTS): $(SOURCES) $(HEADERS) + $(CC_CMD) + +$(CPP_LANG_OBJECTS): $(SOURCES) $(HEADERS) + $(CPP_CMD) + +local: $(OBJECTS) + +# Defines specific for each deliverable + +$(COMPONENT_LIB): $(OBJECTS) +ifdef DYNAMIC +# For a dynamic library + $(SLIB_CMD) + $(HIDE_ECHO_FLAG)$(OBJCPY) --only-keep-debug $(@) $(@).debug + $(HIDE_ECHO_FLAG)$(OBJCPY) --strip-all $(@) + $(HIDE_ECHO_FLAG)$(OBJCPY) --add-gnu-debuglink=$(@).debug $(@) +else +# For a static library + $(AR_CMD) +endif + +# Standard set of derived targets +library: base \ + $(LIBRARIES) + @echo "***** `date` Done building library: $(COMPONENT_NAME) ******" + +binary: base \ + $(BINARIES) + +# Subdirs should be to jump to subdirectories +# standard form is of +# $(MAKE) -C subdirectory_name $(MAKECMDGOALS) +subdirs: + +clean: + -rm -f $(BINARIES) + -rm -f $(LIBRARIES) + -rm -f $(OBJECTS) + -rm -f $(COMPONENT_LIB).map + -rm -f $(COMPONENT_LIB).debug + +-v: + @echo "objs: --> $(OBJECTS)" + @echo "sources: --> $(SOURCES)" + @echo "headers: --> $(HEADERS)" + @echo "includes: --> $(INCLUDES)" + @echo "lib paths: --> $(LIB_PATHS)" + @echo "static libs: --> $(LD_STATIC_LIBS)" + @echo "dynamic libs: --> $(LD_DYNAMIC_LIBS)" + @echo "lib: --> $(LIBRARIES)" + @echo "bin: --> $(BINARIES)" + +module_dirs: build_dirs + diff --git a/framework_unified/client/NS_MessageCenter/src/ns_message_center.c b/framework_unified/client/NS_MessageCenter/src/ns_message_center.c new file mode 100644 index 00000000..32510f37 --- /dev/null +++ b/framework_unified/client/NS_MessageCenter/src/ns_message_center.c @@ -0,0 +1,1245 @@ +/* + * @copyright Copyright (c) 2016-2019 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. + */ + +/////////////////////////////////////////////////////////////////////////////// +/// \ingroup tag_NSMessageCenter +/// \brief +/// +/// APIs to Open\Close and Send\Receive on message queues and shared memory. +/// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include "ns_msg_queue.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define assert_static(e) \ + do { \ + enum { assert_static__ = 1/(e) }; \ + } while (0) + +#define MC_INVOKE_SYNC_TIMEOUT (60 * 1000) + +typedef struct { + UI_32 seq_id; + EFrameworkunifiedStatus ret_val; + UI_32 res_size; +} ResponseHeader; + +static unsigned int mcSeed[4]; + +HANDLE McOpenReceiverNotBlocked(PCSTR name) { + return OpenReceiverNotBlocked(name); +} + +HANDLE McOpenReceiver(PCSTR name) { + return OpenReceiver(name); +} + +HANDLE McOpenSyncReceiver(PCSTR name) { + return openSyncReceiver(name); +} + + +HANDLE McOpenSender(PCSTR name) { + return OpenSender(name); +} + +HANDLE McOpenSenderNotBlocked(PCSTR name) { + return OpenSender(name); +} + +HANDLE McOpenSyncSender(PCSTR name) { + return openSyncSender(name); +} + +static int mcSetMonitorName(char *str, PCSTR name) { + int len; + *str = '\0'; + len = sprintf(str + 1, "monitorS_%s", name != 0 ? name : NULL); + return len + 1; +} + +static int OpenMonitor(PCSTR name) { + int monitor_sock = -1; + int monitor_sa_len; + struct sockaddr_un monitor_sa_un; + + if ((monitor_sock = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0)) < 0) { + FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __func__, "socket:%s", strerror(errno)); + goto error; + } + + memset(&monitor_sa_un, 0, sizeof(monitor_sa_un)); + monitor_sa_un.sun_family = AF_UNIX; + monitor_sa_len = mcSetMonitorName(monitor_sa_un.sun_path, name); + monitor_sa_len += (int)offsetof(struct sockaddr_un, sun_path); + + if (bind(monitor_sock, (struct sockaddr *)&monitor_sa_un, (socklen_t)monitor_sa_len) < 0) { + FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __func__, "bind:%s:%s", name, strerror(errno)); // LCOV_EXCL_BR_LINE 15:marco defined in "native_service/ns_logger_if.h" + goto error; + } + + if (listen(monitor_sock, SOMAXCONN) < 0) { + FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __func__, "listen:%s", strerror(errno)); // LCOV_EXCL_BR_LINE 15:marco defined in "native_service/ns_logger_if.h" + goto error; + } + return monitor_sock; + +error: + if (monitor_sock >= 0) { + close(monitor_sock); + } + return -1; +} + +int mcOpenMonitor(PCSTR name) { + long monitor_sock; + + if (frameworkunifiedAcquireResouce(FRAMEWORKUNIFIED_RES_ABNMLMON, name, &monitor_sock) < 0) { + if ((monitor_sock = OpenMonitor(name)) != -1) { + if (frameworkunifiedRegistResouce(FRAMEWORKUNIFIED_RES_ABNMLMON, name, monitor_sock, 1) < 0) { + close(monitor_sock); + monitor_sock = -1; + } + } + } + + return (int)monitor_sock; +} + +int mcCloseMonitor(PCSTR name) { + long monitor_sock; + + if (frameworkunifiedGetResource(FRAMEWORKUNIFIED_RES_ABNMLMON, name, &monitor_sock) < 0) { + return -1; + } + + frameworkunifiedUnregistResouce(FRAMEWORKUNIFIED_RES_ABNMLMON, name); + close((int)monitor_sock); + + return 0; +} + +static int mcSetClientName(char *str, PCSTR serverName, PCSTR clientName) { + int len; + *str = '\0'; + len = sprintf(str + 1, "monitorC_%s:%s", serverName != 0 ? serverName : NULL, clientName != 0 ? clientName : NULL); + return len + 1; +} + +static int ConnectMonitor(PCSTR serverName, PCSTR clientName) { + int client_sock = -1; + int client_sa_len, monitor_sa_len; + struct sockaddr_un client_sa_un, monitor_sa_un; + + if ((client_sock = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0)) < 0) { // LCOV_EXCL_BR_LINE 5: socket's error case + // LCOV_EXCL_START 5:socket's error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __func__, "socket:%s", strerror(errno)); + return -1; + // LCOV_EXCL_STOP + } + + memset(&client_sa_un, 0, sizeof(client_sa_un)); + client_sa_un.sun_family = AF_UNIX; + client_sa_len = mcSetClientName(client_sa_un.sun_path, serverName, clientName); + client_sa_len += (int)offsetof(struct sockaddr_un, sun_path); + + if (bind(client_sock, (struct sockaddr *)&client_sa_un, (socklen_t)client_sa_len) < 0) { + FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __func__, "bind:%s:%s", client_sa_un.sun_path + 1, strerror(errno)); + goto error; + } + + memset(&monitor_sa_un, 0, sizeof(monitor_sa_un)); + monitor_sa_un.sun_family = AF_UNIX; + monitor_sa_len = mcSetMonitorName(monitor_sa_un.sun_path, serverName); + monitor_sa_len += (int)offsetof(struct sockaddr_un, sun_path); + + if (connect(client_sock, (struct sockaddr *)&monitor_sa_un, (socklen_t)monitor_sa_len) < 0) { + FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __func__, "connect:%s", strerror(errno)); + goto error; + } + return client_sock; + +error: + close(client_sock); + return -1; +} + +int mcSetConnectKey(char *buf, size_t size, PCSTR serverName, PCSTR clientName) { + int len = snprintf(buf, size, "%s:%s", serverName != 0 ? serverName : NULL, clientName != 0 ? clientName : NULL); + buf[size - 1] = '\0'; + return len; +} + +int mcConnectMonitor(PCSTR serverName, PCSTR clientName) { + long client_sock; + char connect_key[32]; + + mcSetConnectKey(connect_key, sizeof(connect_key), serverName, clientName); + + if (frameworkunifiedAcquireResouce(FRAMEWORKUNIFIED_RES_ABNMLMON, connect_key, &client_sock) < 0) { + if ((client_sock = ConnectMonitor(serverName, clientName)) != -1) { + if (frameworkunifiedRegistResouce(FRAMEWORKUNIFIED_RES_ABNMLMON, connect_key, client_sock, 1) < 0) { + close(client_sock); + client_sock = -1; + } + } + } + + return (int)client_sock; +} + +int mcCloseConnectMonitor(PCSTR serverName, PCSTR clientName) { // LCOV_EXCL_START 8: dead code + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + long client_sock; + char connect_key[32]; + + mcSetConnectKey(connect_key, sizeof(connect_key), serverName, clientName); + + if (frameworkunifiedGetResource(FRAMEWORKUNIFIED_RES_ABNMLMON, connect_key, &client_sock) == -1) { + return -1; + } + + if (frameworkunifiedReleaseResouce(FRAMEWORKUNIFIED_RES_ABNMLMON, connect_key) == 0) { + frameworkunifiedUnregistResouce(FRAMEWORKUNIFIED_RES_ABNMLMON, connect_key); + close((int)client_sock); + } + + return 0; +} +// LCOV_EXCL_STOP +static void mcGetClientName(const char *str, char *client_name, size_t size, int pathlen) { + size_t len = size - 1; + size_t str_len; + char *p_div = strchr(str + 1, ':'); + if (p_div == NULL) { + return; + } + str_len = (size_t)(pathlen - (p_div - str + 1)); + if (len > str_len) { + len = str_len; + } + strncpy(client_name, p_div + 1, len); + client_name[len] = '\0'; +} + +int mcAcceptMonitor(PCSTR serverName, int listenMonitorFd) { + int accept_sock = -1; + struct sockaddr_un client_sa_un; + socklen_t client_sa_len = sizeof(client_sa_un); + char client_name[16]; + char connect_key[32]; + + if ((accept_sock = accept4(listenMonitorFd, (struct sockaddr *)&client_sa_un, &client_sa_len, SOCK_CLOEXEC)) < 0) { + FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __func__, "accept:%s", strerror(errno)); + return -1; + } + + mcGetClientName(client_sa_un.sun_path, client_name, sizeof(client_name), (int)(client_sa_len - offsetof(struct sockaddr_un, + sun_path))); + mcSetConnectKey(connect_key, sizeof(connect_key), serverName, client_name); + + frameworkunifiedRegistResouce(FRAMEWORKUNIFIED_RES_ABNMLMON, connect_key, accept_sock, 0); + return accept_sock; +} + +int mcGetAcceptMonitor(PCSTR serverName, PCSTR clientName) { + long accept_sock; + char connect_key[32]; + + mcSetConnectKey(connect_key, sizeof(connect_key), serverName, clientName); + + if (frameworkunifiedAcquireResouce(FRAMEWORKUNIFIED_RES_ABNMLMON, connect_key, &accept_sock) < 0) { + return -1; + } + + return (int)accept_sock; +} + +int mcGetClientNameFromConnectKey(PCSTR connectKey, PCHAR clientName, size_t len) { + char *p_div = strchr(connectKey, ':'); + if (p_div == NULL) { + return -1; + } + + strncpy(clientName, p_div + 1, len); + clientName[len - 1] = '\0'; + return 0; +} + +int mcGetServerNameFromConnectKey(PCSTR connectKey, PCHAR serverName, size_t len) { + char *p_div = strchr(connectKey, ':'); + size_t min_len; + + if (p_div == NULL) { + return -1; + } + + min_len = ((len - 1) < (p_div - connectKey)) ? len - 1 : (size_t)(p_div - connectKey); + strncpy(serverName, connectKey, min_len); + serverName[min_len] = '\0'; + return 0; +} + +///////////////////////////////////////// +HANDLE McOpenSenderChild(PCSTR name, pthread_t childid) { + return OpenSenderChild(name, childid); +} + +EFrameworkunifiedStatus McJoinChild(HANDLE hChildApp) { + EFrameworkunifiedStatus eStatus = eFrameworkunifiedStatusOK; + + if (INVALID_HANDLE != hChildApp) { // LCOV_EXCL_BR_LINE 6: impossible to confirm because hChildApp checked is passed in the FrameworkunifiedDestroyChildThread function of the frameworkunified_multithreading.cpp + eStatus = JoinChild(hChildApp); + } else { + // LCOV_EXCL_START 6: impossible to confirm because hChildApp checked is passed in the FrameworkunifiedDestroyChildThread function of the frameworkunified_multithreading.cpp + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + eStatus = eFrameworkunifiedStatusInvldHandle; + // LCOV_EXCL_STOP + } + + return eStatus; +} + +EFrameworkunifiedStatus McGetChildThreadPriority(HANDLE hChildApp, PSI_32 threadPrio) { + EFrameworkunifiedStatus eStatus = eFrameworkunifiedStatusOK; + + if (INVALID_HANDLE != hChildApp) { + eStatus = GetChildThreadPriority(hChildApp, threadPrio); + } else { + eStatus = eFrameworkunifiedStatusInvldHandle; + } + + return eStatus; +} + +/// endhack... +///////////////////////////////////////// + +static EFrameworkunifiedStatus mcReceiveInternal(HANDLE hMessage, PSTR source, UI_32 *cmd, UI_32 *sessionid, UI_32 length, + PVOID data) { + PSSystemMsgHeader sysHdr = NULL; + + // check if handle is valid + if (hMessage == INVALID_HANDLE) { + return eFrameworkunifiedStatusInvldHandle; + } + + // check if buffer is null + if (data == NULL) { + return eFrameworkunifiedStatusInvldBuf; + } + + // check for invalid length. + if (length <= 0) { + return eFrameworkunifiedStatusInvldBuf; + } + + // check if the source is null + if (source == NULL) { + return eFrameworkunifiedStatusInvldQName; + } + + if (cmd == NULL) { + return eFrameworkunifiedStatusInvldParam; + } + + if (-1 != ReceiveMessage(hMessage, length, data)) { + sysHdr = (PSSystemMsgHeader)data; + if (strlen(sysHdr->info.source) < MAX_QUEUE_NAME_SIZE) { + *cmd = sysHdr->info.command; + if (sessionid) { + *sessionid = sysHdr->info.sessionid; + } + strlcpy(source, sysHdr->info.source, MAX_NAME_SIZE_APP); + return eFrameworkunifiedStatusOK; + } else { + return eFrameworkunifiedStatusInvldBuf; + } + } else { + return TranslateError(errno); + } + + return eFrameworkunifiedStatusFail; +} + +EFrameworkunifiedStatus McReceive(HANDLE hMessage, PSTR source, UI_32 *cmd, UI_32 length, PVOID data) { + return mcReceiveInternal(hMessage, source, cmd, NULL, length, data); +} + +EFrameworkunifiedStatus McReceiveWithSession(HANDLE hMessage, PSTR source, UI_32 *cmd, UI_32 *sessionid, UI_32 length, PVOID data) { + if (sessionid == NULL) { + return eFrameworkunifiedStatusInvldParam; + } + return mcReceiveInternal(hMessage, source, cmd, sessionid, length, data); +} + +static EFrameworkunifiedStatus mcSendInternal(HANDLE hMessage, PCSTR source, UI_32 cmd, PCSTR sysInfo, UI_32 length, PCVOID data, + EFrameworkunifiedMessagePriorties priority, UI_32 sessionid, BOOL is_sync) { + assert_static(_NSFW_MSG_LEN_ == sizeof(SSystemMsgHeader)); + assert_static(_NSFW_SYSINFO_SIZE_ == MAX_SYS_INFO_SIZE); + assert_static(_NSFW_SYSINFO_FLAG_ == MC_EMSGT_SYSINFO_MASK); + + // check if handle is valid + if (mqCheckValidHandle(hMessage) == FALSE) { + return eFrameworkunifiedStatusInvldHandle; + } + + // check if buffer is null + if (data == NULL && length > 0) { + return eFrameworkunifiedStatusInvldBuf; + } + + // check if the source is null + if (source == NULL) { + return eFrameworkunifiedStatusInvldQName; + } + + // check if the source length exceeds than expected + /** + * @todo + * Although a send message queue handle can be created using a 19-byte message queue name, messages cannot be sent using the created send message queue handle. + * Because "/" is added to the queue name in the send message queue handle, a judgment error of MAX_QUEUE_NAME_SIZE (20 bytes) occurs during transmission and transmission cannot be performed. + */ + if (strlen(source) >= MAX_QUEUE_NAME_SIZE) { + return eFrameworkunifiedStatusInvldQName; + } + + // notification name size should be less than MAX_SYS_INFO_SIZE + // data length check + UI_32 max_length = 0; + if (NULL != sysInfo) { + if (strlen(sysInfo) >= MAX_SYS_INFO_SIZE) { + return eFrameworkunifiedStatusInvldParam; + } + // If there is an sysInfo, the maximum send data length is the maximum send data length of UI_32 minus (header + sysInfo size). + max_length = 0xFFFFFFFF - sizeof(SSystemMsgHeader) - sizeof(TSysMsgSystemInfo); + } else { + // If there is no sysInfo, the maximum send data length is the maximum value of UI_32 minus the headers. + max_length = 0xFFFFFFFF - sizeof(SSystemMsgHeader); + } + + if (length > max_length) { + return eFrameworkunifiedStatusInvldParam; + } + EFrameworkunifiedStatus rtnStatus = eFrameworkunifiedStatusOK; + + UI_8 sndBuf[ MAX_QUEUE_MSG_SIZE ]; + SQhandle *sndHndl = (SQhandle *)hMessage; + SSystemMsgHeader *msgHdr = (SSystemMsgHeader *)sndBuf; + UI_32 send_length = 0; + UI_32 offset = sizeof(SSystemMsgHeader); + + if (NULL == sndHndl->q_name) { + return eFrameworkunifiedStatusInvldHandle; + } + + // check if the dest length exceeds than expected + if (strlen(sndHndl->q_name) >= MAX_QUEUE_NAME_SIZE) { + return eFrameworkunifiedStatusInvldHandle; + } + + // compose header + strcpy(msgHdr->info.source, source); + msgHdr->info.length = length; // this is length of the messages data... + msgHdr->info.command = cmd; + msgHdr->info.sessionid = sessionid; + + msgHdr->eType = (UI_32)MC_EMSGT_VALID_TOKEN; + msgHdr->memId = 0; // not set... + if (NULL != sysInfo) { + msgHdr->eType |= MC_EMSGT_SYSINFO_MASK; + strcpy((char *)(sndBuf + offset), sysInfo); + offset += (UI_32)sizeof(TSysMsgSystemInfo); + } + if (is_sync) { + msgHdr->eType |= MC_EMSGT_SYNC_MASK; + } + + // Build buffer to send... + + // copy to buffer + /* + * @todo + * Do not throw an error even if the data size of the argument is set to 0. + * When "length + offset" is MAX_QUEUE_MSG_SIZE (4096) or more, the length becomes 0 in the process that is executed cannot be checked. + * Sizeof(SSystemMsgHeader) is 40, sizeof(TSysMsgSystemInfo) is 64, maximal. offset is 104, min. is 40 + */ + if ((length + offset) >= MAX_QUEUE_MSG_SIZE) { + // set the shared mem info in header.... + msgHdr->eType |= MC_EMSGT_SHM_MASK; + + // send data to shm + msgHdr->memId = SetDataToShared(data, length, source, sndHndl->q_name); + + if (BAD_MEM_ID != msgHdr->memId) { + // update the send length + send_length += offset; + } else { + rtnStatus = eFrameworkunifiedStatusErrOther; + } + } else { // was less than the max + // update the send length + send_length += offset; + + /** + * @todo + * If UINT_MAX (4294967295) is specified in the iLength of FrameworkunifiedNPPublishNotification, + * the comparison by (length + offset) >= MAX_QUEUE_MSG_SIZE fails to compare correctly because of an overflow, + * and the comparison is judged to be less than the max. + * Once in the else block, the data is treated as a sysHeader block of up to 4096 bytes, + * and the memcpy is performed again without size checking, resulting in a segmentation fault. + * Maximum message length that can be sent by FrameworkunifiedNPPublishNotification must be specified and the maximum message length must be checked. + */ + // copy the msg to send buffer + memcpy(&sndBuf[0] + offset, data, length); + + // update the send length + send_length += length; + } + + if (eFrameworkunifiedStatusOK == rtnStatus) { + rtnStatus = SendMessageWithPriority(hMessage, send_length, (PVOID)&sndBuf[0], priority); + } + + if (rtnStatus != eFrameworkunifiedStatusOK) { + // remove the shared mem since this failed. + McClearData(msgHdr); + } + + return rtnStatus; +} + +EFrameworkunifiedStatus McSendPrioWithSysInfo(HANDLE hMessage, PCSTR source, UI_32 cmd, PCSTR sysInfo, UI_32 length, PCVOID data, + EFrameworkunifiedMessagePriorties priority, UI_32 sessionid) { + if (NULL == sysInfo) { + return eFrameworkunifiedStatusInvldParam; + } + return mcSendInternal(hMessage, source, cmd, sysInfo, length, data, priority, sessionid, FALSE); +} + +EFrameworkunifiedStatus McSendWithSysInfo(HANDLE hMessage, PCSTR source, UI_32 cmd, PCSTR sysInfo, UI_32 length, PCVOID data, + UI_32 sessionid) { + if (NULL == sysInfo) { + return eFrameworkunifiedStatusInvldParam; + } + return mcSendInternal(hMessage, source, cmd, sysInfo, length, data, eFrameworkunifiedMsgPrioNormal, sessionid, FALSE); +} + +EFrameworkunifiedStatus McSend(HANDLE hMessage, PCSTR source, UI_32 cmd, UI_32 length, PCVOID data) { + return mcSendInternal(hMessage, source, cmd, NULL, length, data, eFrameworkunifiedMsgPrioNormal, 0, FALSE); +} + +EFrameworkunifiedStatus McSendWithPriority(HANDLE hMessage, PCSTR source, UI_32 cmd, UI_32 length, PCVOID data, + EFrameworkunifiedMessagePriorties priority, UI_32 sessionid) { + return mcSendInternal(hMessage, source, cmd, NULL, length, data, priority, sessionid, FALSE); +} + +EFrameworkunifiedStatus McSendWithSession(HANDLE hMessage, PCSTR source, UI_32 cmd, UI_32 length, PCVOID data, UI_32 sessionid) { + return mcSendInternal(hMessage, source, cmd, NULL, length, data, eFrameworkunifiedMsgPrioNormal, sessionid, FALSE); +} + +EFrameworkunifiedStatus McSendSyncResponse(HANDLE hMessage, PCSTR source, UI_32 cmd, UI_32 seq_id, EFrameworkunifiedStatus ret_val, UI_32 length, + PCVOID data) { + EFrameworkunifiedStatus eStatus; + ResponseHeader *resHdr; + UI_8 *res_data; + + if ((UINT_MAX - sizeof(ResponseHeader)) < length) { + return eFrameworkunifiedStatusInvldBufSize; + } + + // check if buffer is null + if (data == NULL && length > 0) { + return eFrameworkunifiedStatusInvldBuf; + } + + if ((res_data = calloc(length + sizeof(ResponseHeader), 1)) == NULL) { // LCOV_EXCL_BR_LINE 5: calloc's error case + // LCOV_EXCL_START 5: calloc's error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + eStatus = eFrameworkunifiedStatusFail; + goto exit; + // LCOV_EXCL_STOP + } + + resHdr = (ResponseHeader *)res_data; + resHdr->seq_id = seq_id; + resHdr->ret_val = ret_val; + resHdr->res_size = length; + + memcpy(res_data + sizeof(ResponseHeader), data, length); + + eStatus = mcSendInternal(hMessage, source, cmd, NULL, (UI_32)(length + sizeof(ResponseHeader)), res_data, eFrameworkunifiedMsgPrioNormal, 0, + TRUE); + +exit: + free(res_data); + res_data = NULL; + resHdr = NULL; + + return eStatus; +} + +/* + * Xorshift + */ +static inline unsigned int xor128(void) { + unsigned int t; + t = (mcSeed[0] ^ (mcSeed[0] << 11)); + mcSeed[0] = mcSeed[1]; + mcSeed[1] = mcSeed[2]; + mcSeed[2] = mcSeed[3]; + return (mcSeed[3] = (mcSeed[3] ^ (mcSeed[3] >> 19)) ^ (t ^ (t >> 8))); +} + +static inline char *ultoa(unsigned long value, char *buf, int radix) { + const static char c[] = "0123456789abcdef"; + char b[65]; + char *p = b + sizeof(b); + + *--p = '\0'; + do { + *--p = c[value % (unsigned long)radix]; + value /= (unsigned long)radix; + } while (value); + strcpy(buf, p); + + return buf; +} + +EFrameworkunifiedStatus McInvokeSync(HANDLE hMessage, PCSTR source, UI_32 cmd, UI_32 msgLength, PCVOID msgData, UI_32 sessionid, + HANDLE hRcvMessage, UI_32 responseLength, PVOID responseData, UI_32 *receivedLength) { + EFrameworkunifiedStatus eStatus; + TSysMsgSystemInfo sysInfo; + UI_32 seq_id; + ResponseHeader *resHdr; + UI_8 *rcv_buf = NULL; + CHAR resSource[MAX_NAME_SIZE_APP]; + int efd = -1; + struct epoll_event events[2]; + struct epoll_event ev; + int connect_sock = -1; + SQhandle *sndHndl = (SQhandle *)hMessage; + + if (mqCheckValidHandle(hMessage) == FALSE || mqCheckValidHandle(hRcvMessage) == FALSE || (responseLength != 0 && + responseData == NULL)) { + eStatus = eFrameworkunifiedStatusInvldHandle; + + /** + * @todo + * The system performs rcv_buf free without NULL determination. + */ + goto exit; + } + + if (NULL == receivedLength) { + eStatus = eFrameworkunifiedStatusInvldParam; + goto exit; + } + if ((rcv_buf = malloc(MAX_QUEUE_MSG_SIZE)) == NULL) { // LCOV_EXCL_BR_LINE 5: malloc's error case. + // LCOV_EXCL_START 5: malloc's error case. + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + eStatus = eFrameworkunifiedStatusFail; + goto exit; + // LCOV_EXCL_STOP + } + + if (mcSeed[0] == 0) { + int fd; + if ((fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC)) < 0) { + eStatus = eFrameworkunifiedStatusFail; + goto exit; + } + + if (read(fd, &mcSeed, sizeof(mcSeed)) < 0) { + close(fd); + eStatus = eFrameworkunifiedStatusFail; + goto exit; + } + close(fd); + } + seq_id = xor128(); + + sysInfo[0] = '0'; + sysInfo[1] = 'x'; + ultoa(seq_id, &sysInfo[2], 16); + + Flush(hRcvMessage); + + eStatus = mcSendInternal(hMessage, source, cmd, sysInfo, msgLength, msgData, eFrameworkunifiedMsgPrioNormal, sessionid, TRUE); + if (eStatus != eFrameworkunifiedStatusOK) { + goto exit; + } + + if ((connect_sock = mcConnectMonitor(sndHndl->q_name + 1, source)) < 0) { + FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __func__, "connect:%s", strerror(errno)); + eStatus = eFrameworkunifiedStatusFail; + goto exit; + } + + if ((efd = epoll_create1(EPOLL_CLOEXEC)) < 0) { // LCOV_EXCL_BR_LINE 5: epoll_create1's error case. + // LCOV_EXCL_START 5: epoll_create1's error case. + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __func__, "epoll_create1:%s", strerror(errno)); + eStatus = eFrameworkunifiedStatusFail; + goto exit; + // LCOV_EXCL_STOP + } + ev.events = EPOLLIN; + ev.data.fd = McGetQueueFD(hRcvMessage); + if (epoll_ctl(efd, EPOLL_CTL_ADD, ev.data.fd, &ev) < 0) { // LCOV_EXCL_BR_LINE 5: epoll_ctl's error case. + // LCOV_EXCL_START 5: epoll_ctl's error case. + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __func__, "epoll_ctl:%s", strerror(errno)); + eStatus = eFrameworkunifiedStatusFail; + goto exit; + // LCOV_EXCL_STOP + } + ev.events = EPOLLRDHUP; + ev.data.fd = connect_sock; + if (epoll_ctl(efd, EPOLL_CTL_ADD, ev.data.fd, &ev) < 0) { // LCOV_EXCL_BR_LINE 5: epoll_ctl's error case. + // LCOV_EXCL_START 5: epoll_ctl's error case. + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __func__, "epoll_ctl:%s", strerror(errno)); + eStatus = eFrameworkunifiedStatusFail; + goto exit; + // LCOV_EXCL_STOP + } + + while (1) { + int nfds, n; + + nfds = epoll_wait(efd, events, 2, MC_INVOKE_SYNC_TIMEOUT); + if (nfds == -1) { // LCOV_EXCL_BR_LINE 5: epoll_wait's error case. + // LCOV_EXCL_START 5: epoll_wait's error case. + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + if (errno == EINTR) { + continue; + } + FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __func__, "epoll_wait:%s", strerror(errno)); + eStatus = eFrameworkunifiedStatusFail; + goto exit; + // LCOV_EXCL_STOP + } else if (nfds == 0) { // LCOV_EXCL_BR_LINE 5: epoll_wait return value equal 0. + // LCOV_EXCL_START 5: epoll_wait return value equal 0. + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __func__, "epoll_wait:time out"); + eStatus = eFrameworkunifiedStatusAccessError; + goto exit; + // LCOV_EXCL_STOP + } + + for (n = 0; n < nfds; n++) { + if (events[n].data.fd == connect_sock) { + /* + * connection fail + */ + char connect_key[32]; + mcSetConnectKey(connect_key, sizeof(connect_key), sndHndl->q_name + 1, source); + + if (epoll_ctl(efd, EPOLL_CTL_DEL, connect_sock, events) < 0) { + FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __func__, "epoll_ctl:%s", strerror(errno)); + } + if (close(connect_sock) < 0) { + FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __func__, "close:%s", strerror(errno)); + } + frameworkunifiedUnregistResouce(FRAMEWORKUNIFIED_RES_ABNMLMON, connect_key); + + if ((connect_sock = mcConnectMonitor(sndHndl->q_name + 1, source)) < 0) { + eStatus = eFrameworkunifiedStatusBadConnection; + goto exit; + } + ev.events = EPOLLRDHUP; + ev.data.fd = connect_sock; + if (epoll_ctl(efd, EPOLL_CTL_ADD, ev.data.fd, &ev) < 0) { + FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __func__, "epoll_ctl:%s", strerror(errno)); + eStatus = eFrameworkunifiedStatusFail; + goto exit; + } + } else { + /* + * response receive + */ + if ((eStatus = McReceive(hRcvMessage, resSource, &cmd, MAX_QUEUE_MSG_SIZE, rcv_buf)) != eFrameworkunifiedStatusOK) { + goto exit; + } + + PSSystemMsgHeader sysHdr = (PSSystemMsgHeader)rcv_buf; + if (MC_EMSGT_IS_SHM(sysHdr->eType)) { + UI_32 shmLength = GetLengthOfDataFromShared(sysHdr->memId); + TMemID memId = sysHdr->memId; + + if (shmLength == 0) { + eStatus = eFrameworkunifiedStatusErrOther; + goto exit; + } + + free(rcv_buf); + if ((rcv_buf = calloc(shmLength, 1)) == NULL) { + eStatus = eFrameworkunifiedStatusFail; + goto exit; + } + + if ((eStatus = GetDataFromShared(memId, rcv_buf, shmLength)) != eFrameworkunifiedStatusOK) { + eStatus = eFrameworkunifiedStatusErrOther; + goto exit; + } + + DiscardDataFromShared(memId); + resHdr = (ResponseHeader *)rcv_buf; + } else { + resHdr = (ResponseHeader *)(rcv_buf + sizeof(SSystemMsgHeader)); + } + + if (resHdr->seq_id == seq_id) { + if (resHdr->res_size > 0 && responseLength > 0) + memcpy(responseData, (const void *)((char *)resHdr + sizeof(ResponseHeader)), + resHdr->res_size > responseLength ? responseLength : resHdr->res_size); + + *receivedLength = resHdr->res_size; + eStatus = resHdr->ret_val; + goto exit; // success + } + } + } + } + +exit: + free(rcv_buf); + rcv_buf = NULL; + resHdr = NULL; + + if (efd >= 0) { + close(efd); + } + + return eStatus; +} + +EFrameworkunifiedStatus McCreateInvokerName(PCSTR source, UI_32 sessionid, PSTR invokerName, UI_32 size) { + if (source == NULL || invokerName == NULL) { + return eFrameworkunifiedStatusInvldParam; + } + + // When the size of the synchronous communication message queue name storage area is 0. + if (0 == size) { + return eFrameworkunifiedStatusInvldParam; + } + snprintf(invokerName, size - 1, "%s_r0", source); + return eFrameworkunifiedStatusOK; +} + +EFrameworkunifiedStatus McForward(HANDLE hMessage, PCSTR source, UI_32 iCmd, TMemID USID) { + // check if handle is valid + if (mqCheckValidHandle(hMessage) == FALSE) { + return eFrameworkunifiedStatusInvldHandle; + } + + // check if the source is null + if (source == NULL) { + return eFrameworkunifiedStatusInvldQName; + } + + // check the shared memory id + if (USID == BAD_MEM_ID) { + return eFrameworkunifiedStatusErrOther; + } + + // check if the source length exceeds than expected + if (strlen(source) >= MAX_QUEUE_NAME_SIZE) { + return eFrameworkunifiedStatusInvldQName; + } + + UI_8 sndBuf[ MAX_QUEUE_MSG_SIZE ] = {}; + SQhandle *sndHndl = (SQhandle *)hMessage; + SSystemMsgHeader msgHdr = {}; + + // check if the dest length exceeds than expected + if (strlen(sndHndl->q_name) >= MAX_QUEUE_NAME_SIZE) { + return eFrameworkunifiedStatusInvldHandle; + } + + // compose header + strlcpy(msgHdr.info.source, source, sizeof(msgHdr.info.source)); + msgHdr.info.length = GetLengthOfDataFromShared(USID); // this is length of the messages data... + msgHdr.info.command = iCmd; + msgHdr.eType = (UI_32)(MC_EMSGT_VALID_TOKEN | MC_EMSGT_SHM_MASK); + msgHdr.memId = USID; + msgHdr.info.sessionid = 0; + + // copy to buffer + UI_8 offset = sizeof(SSystemMsgHeader); + // write header to send buffer + memcpy(&sndBuf[0], &msgHdr, offset); + + return SendMessage(hMessage, MAX_QUEUE_MSG_SIZE, (PVOID)&sndBuf[0]); +} + +PCSTR McGetMsgSrc(PVOID data) { + // check if buffer is null + if (data == NULL) { + return NULL; // The data is invalid return zero length. + } + + PSSystemMsgHeader sysHdr = (PSSystemMsgHeader)data; + return (PCSTR)sysHdr->info.source; +} + +UI_32 mcGetMsgSsessionId(PVOID data) { + // check if buffer is null + if (data == NULL) { + return 0; // The data is invalid return zero. + } + + PSSystemMsgHeader sysHdr = (PSSystemMsgHeader)data; + return sysHdr->info.sessionid; +} + +UI_32 McGetLength(PVOID data) { + // check if buffer is null + if (data == NULL) { + return 0; // The data is invalid return zero length. + } + + PSSystemMsgHeader sysHdr = (PSSystemMsgHeader)data; + return sysHdr->info.length; +} + +PVOID McGetDataPointer(PVOID data) { + if (data == NULL) { + return NULL; + } + + PSSystemMsgHeader sysHdr = (PSSystemMsgHeader)data; + int offset = sizeof(SSystemMsgHeader); + + if (MC_EMSGT_HAS_SYSINFO(sysHdr->eType)) { + offset += (int)sizeof(TSysMsgSystemInfo); + } + + return (PVOID)((long)data + offset); +} + +EFrameworkunifiedStatus McGetSysInfoData(PVOID data, PVOID to) { + // check if buffers are null + if (data == NULL || to == NULL) { + return eFrameworkunifiedStatusInvldBuf; + } + + PSSystemMsgHeader sysHdr = (PSSystemMsgHeader)data; + if (MC_EMSGT_VALID((int)sysHdr->eType)) { + if (MC_EMSGT_HAS_SYSINFO(sysHdr->eType)) { + strlcpy(to, (char *)data + sizeof(SSystemMsgHeader), MAX_SYS_INFO_SIZE); + } else { + *(char *)to = '\0'; + } + return eFrameworkunifiedStatusOK; + } + + return eFrameworkunifiedStatusInvldHandle; +} + +EFrameworkunifiedStatus McGetDataOfSize(PVOID data, PVOID to, UI_32 uiSize) { + if (McGetLength(data) > uiSize) { + return eFrameworkunifiedStatusInvldBufSize; + } + return GetData(data, to, FALSE); +} + +EFrameworkunifiedStatus McGetDataOfSizeWithSMRetain(PVOID data, PVOID to, UI_32 uiSize) { + if (McGetLength(data) > uiSize) { + return eFrameworkunifiedStatusInvldBufSize; + } + return GetData(data, to, TRUE); +} + +BOOL mcGetIsTypeOfSync(PVOID data) { + if (data == NULL) { + return FALSE; + } + + PSSystemMsgHeader sysHdr = (PSSystemMsgHeader)data; + + if (MC_EMSGT_VALID((int)sysHdr->eType)) { + if (MC_EMSGT_IS_SYNC(sysHdr->eType)) { + return TRUE; + } + } + + return FALSE; +} + +EFrameworkunifiedStatus McClearData(PVOID data) { + // check if buffers are null + if (data == NULL) { + return eFrameworkunifiedStatusInvldBuf; + } + + PSSystemMsgHeader sysHdr = (PSSystemMsgHeader)data; + + if (MC_EMSGT_VALID((int)sysHdr->eType)) { + if (MC_EMSGT_IS_SHM(sysHdr->eType)) { + return DiscardDataFromShared(sysHdr->memId); + } else { + return eFrameworkunifiedStatusOK; + } + } + + return eFrameworkunifiedStatusInvldParam; +} + +EFrameworkunifiedStatus McClose(HANDLE hMessage) { + EFrameworkunifiedStatus rtnStatus = eFrameworkunifiedStatusInvldHandle; + + if (NULL != hMessage) { + EQType qType = GetQueueType(hMessage); + + if (eQTypeSender == qType) { + rtnStatus = CloseSender(hMessage); + } else if (eQTypeReveiver == qType) { + rtnStatus = CloseReceiver(hMessage); + } + } + + return rtnStatus; +} + + +void McFlushReceiver(HANDLE hMessage) { + if (hMessage != INVALID_HANDLE) { + // proxy to the real function in msg queue + Flush(hMessage); + } +} + +TMemID McGetDataUSID(PVOID pData) { + // check if buffer is null + if (pData == NULL) { + return BAD_MEM_ID; + } + + PSSystemMsgHeader sysHdr = (PSSystemMsgHeader)pData; + + if (MC_EMSGT_VALID((int)sysHdr->eType)) { + if (MC_EMSGT_IS_SHM(sysHdr->eType)) { + return sysHdr->memId; + } else { + return BAD_MEM_ID; + } + } + + return 0; +} + +//////////////////////////////////////////////////////////////////////////////////////////// +/// GetData +//////////////////////////////////////////////////////////////////////////////////////////// +EFrameworkunifiedStatus GetData(PVOID data, PVOID to, BOOL retain) { + EFrameworkunifiedStatus rtnStatus = eFrameworkunifiedStatusInvldHandle; + + // check if buffers are null + if (data == NULL || to == NULL) { + return eFrameworkunifiedStatusInvldBuf; + } + + PSSystemMsgHeader sysHdr = (PSSystemMsgHeader)data; + int offset = sizeof(SSystemMsgHeader); + + if (MC_EMSGT_VALID((int)sysHdr->eType)) { + if (MC_EMSGT_HAS_SYSINFO(sysHdr->eType)) { + offset += (int)sizeof(TSysMsgSystemInfo); + } + + if (MC_EMSGT_IS_SHM(sysHdr->eType)) { + // need to get the message from shared memory + + // get the length based on the memId + UI_32 shmLength = GetLengthOfDataFromShared(sysHdr->memId); + /* + * todo + * When a eFrameworkunifiedStatusInvldID error occurs in GetDataFromShared, the abnormal values are also returned in eFrameworkunifiedStatusErrOther. + */ + if (0 != shmLength && eFrameworkunifiedStatusOK == GetDataFromShared(sysHdr->memId, to, shmLength)) { + if (!retain) { + // now that the data has been retrieved we may now discard it. + McClearData(data); + } + rtnStatus = eFrameworkunifiedStatusOK; + } else { + rtnStatus = eFrameworkunifiedStatusErrOther; + } + } else { + // memcpy the data to the buffer provided. + memcpy(to, (PVOID)((long)data + offset), sysHdr->info.length); + rtnStatus = eFrameworkunifiedStatusOK; + } + } else { + rtnStatus = eFrameworkunifiedStatusInvldHndlType; + } + + return rtnStatus; +} + +PCSTR McGetQueueName(HANDLE hMessage) { + PCSTR name = NULL; + + if (NULL != hMessage) { + name = GetQueueName(hMessage); + } + + return name; +} + +int McGetQueueFD(HANDLE hMessage) { + int fd = -1; + + if (NULL != hMessage) { + fd = GetQueueFD(hMessage); + } + + return fd; +} + +EFrameworkunifiedStatus McTranslateError(int error) { + return TranslateError(error); +} + +EFrameworkunifiedStatus McZcSetParam(HANDLE handle, UI_32 cmd, UI_32 length) { + if (handle == NULL) { + return eFrameworkunifiedStatusInvldHandle; + } + + SQhandle *sndHndl = (SQhandle *)handle; + SSystemMsgHeader *msgHdr = (SSystemMsgHeader *)(sndHndl->sendbuf); + + // QueueType checking + EQType qType = GetQueueType(handle); + if (eQTypeSender != qType) { + return eFrameworkunifiedStatusInvldHndlType; + } + + if (mqCheckValidHandle(handle) == FALSE) { + return eFrameworkunifiedStatusInvldHandle; + } + if (sndHndl->sendbuf == NULL) { + return eFrameworkunifiedStatusInvldBuf; + } + if (length > (MAX_QUEUE_MSG_SIZE - sizeof(SSystemMsgHeader))) { + return eFrameworkunifiedStatusInvldBufSize; + } + + msgHdr->info.command = cmd; + msgHdr->info.length = length; + return eFrameworkunifiedStatusOK; +} + +PVOID McZcGetBuf(HANDLE handle) { + if (handle == NULL) { + return NULL; + } + + SQhandle *sndHndl = (SQhandle *)handle; + + // QueueType checking + EQType qType = GetQueueType(handle); + if (eQTypeSender != qType) { + return NULL; + } + + if (mqCheckValidHandle(handle) == FALSE) { + return NULL; + } + if (sndHndl->sendbuf == NULL) { + return NULL; + } + return (char *)(sndHndl->sendbuf) + sizeof(SSystemMsgHeader); +} + +EFrameworkunifiedStatus McZcSend(HANDLE hMessage) { + if (hMessage == NULL) { + return eFrameworkunifiedStatusInvldHandle; + } + + // QueueType checking + EQType qType = GetQueueType(hMessage); + if (eQTypeSender != qType) { + return eFrameworkunifiedStatusInvldHndlType; + } + + SQhandle *sndHndl = (SQhandle *)hMessage; + + SSystemMsgHeader *msgHdr = (SSystemMsgHeader *)(sndHndl->sendbuf); + + if (mqCheckValidHandle(hMessage) == FALSE) { + return eFrameworkunifiedStatusInvldHandle; + } + if (sndHndl->sendbuf == NULL) { + return eFrameworkunifiedStatusInvldBuf; + } + + return SendMessageWithPriority(hMessage, (UI_32)(msgHdr->info.length + sizeof(SSystemMsgHeader)), sndHndl->sendbuf, + eFrameworkunifiedMsgPrioNormal); +} + +HANDLE McZcOpenSender(PCSTR source) { + HANDLE handle = openSenderZc(source); + + if (handle != NULL) { + SQhandle *sndHndl = (SQhandle *)handle; + SSystemMsgHeader *msgHdr = (SSystemMsgHeader *)(sndHndl->sendbuf); + + strlcpy(msgHdr->info.source, source, sizeof(msgHdr->info.source)); + msgHdr->info.command = 0; + msgHdr->info.length = 0; + msgHdr->info.sessionid = 0; + msgHdr->eType = (UI_32)MC_EMSGT_VALID_TOKEN; + msgHdr->memId = 0; + } + + return handle; +} + +EFrameworkunifiedStatus McZcClose(HANDLE handle) { + return CloseSender(handle); +} -- cgit 1.2.3-korg