* Copyright (c) 2025 Huawei Technologies Co.,Ltd.
*
* CBB is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
* -------------------------------------------------------------------------
*
* hcom4db.cpp
*
*
* IDENTIFICATION
* src/hcom4db.cpp
*
* -------------------------------------------------------------------------
*/
#include <map>
#include <vector>
#include <mutex>
#include <shared_mutex>
#include <atomic>
#include <string>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <climits>
#include "securec.h"
#include "hcom4db_log.h"
#include "hcom4db_define.h"
#include "hcom4db_utils.h"
#include "hcom4db_hcom.h"
#include "hcom4db_dlopen_hcom.h"
#include "hcom4db.h"
using namespace hcom4dbDefine;
namespace {
constexpr uint16_t OCK_MAX_PORT_NUM = 65535;
constexpr uint16_t OCK_MIN_PORT_NUM = 1024;
constexpr uint32_t OCK_MAX_MESSAG_SIZE = 64 * 1024;
constexpr uint32_t OCK_MAX_MESSAG_COUNT = 1024;
constexpr uint32_t OCK_MAX_SEND_QUEUE_SIZE = 2048;
constexpr uint32_t OCK_MAX_RECEIVE_QUEUE_SIZE = 2048;
constexpr uint32_t OCK_MAX_PRE_SEND_RECEIVE_SIZE = 1024;
constexpr uint32_t OCK_MAX_COMPLETE_QUEUE_SIZE = 8192;
constexpr uint32_t OCK_MAX_PORT_RANGE_STR_LEN = 16;
constexpr uint64_t MR_ADDRESS_SIZE = static_cast<unsigned long long>(OCK_MAX_MESSAG_SIZE * OCK_MAX_MESSAG_COUNT);
constexpr uint32_t MR_MAX_SIZE = OCK_MAX_MESSAG_SIZE;
constexpr uint32_t MR_MIN_SIZE = 4 * 1024;
constexpr uint32_t MR_PRE_ALLOC_CNT = 10;
constexpr uint32_t MR_BUCKET_MAP_SIZE = 1024;
constexpr uint32_t IP_MAX_LEN = 64;
constexpr uint32_t OCK_MAX_IOV_COUNT = 4;
constexpr uint16_t DEFAULT_CONNECTION_EP_SIZE = 1;
constexpr uint16_t DEFAULT_HEARTBEAT_IDLE_TIME = 1;
constexpr uint16_t MAX_MESSAGE_ID_SIZE = 1000;
constexpr uint32_t MAX_SEGMENT_SIZE = 943718400;
constexpr uint32_t MAX_SEGMENT_COUNT = 65535;
constexpr uint16_t ALIGNED_SIZE = 4096;
constexpr uint16_t MAX_CALL_WITH_PARAMS_COUNT = 8;
constexpr uint16_t MAX_MESSAGE_SGL_COUNT = 4;
constexpr const char *HCOM4DB_SO_NAME = "libhcom.so";
constexpr const char *HCOM4DB_ENV_PATH = "HCOM4DB_LIB_PATH";
constexpr int32_t DEFAULT_TIMEOUT_TIME = 1000;
constexpr int32_t MILLOSECOND_PER_SECOND = 1000;
}
static OckRpcLogHandler g_logFunc = nullptr;
static TlsFuncs g_tlsFunc = TlsFuncs();
static Service_Options g_options = Service_Options();
static Service_Type g_connectionType = C_SERVICE_RDMA;
static std::map<int16_t, OckRpcMsgHandler> g_handleMap;
static std::map<int16_t, OckRpcMsgRndvHandler> g_rndvHandleMap;
static std::map<std::string, Net_Service> g_serviceMap;
static std::shared_mutex serviceMutex;
static std::shared_mutex serviceAddMutex;
static std::shared_mutex serviceAddRndvMutex;
static std::map<OckRpcClient, Net_MemoryAllocator> g_memoryAllocator;
static std::map<OckRpcClient, OckRpcMrInfo> g_memoryRegion;
static int32_t g_timeoutTime = DEFAULT_TIMEOUT_TIME;
static int Hcom4dbGetLibPath(char* rpcPath, uint32_t rpcPathLen)
{
char* tmp = getenv(HCOM4DB_ENV_PATH);
if (tmp == nullptr) {
OCK_RPC_LOG_ERROR("Hcom4db getenv " << HCOM4DB_ENV_PATH << " failed.");
return OCK_RPC_ERR;
}
if (rpcPathLen < strlen(tmp)) {
OCK_RPC_LOG_ERROR("ENV len is more than path arr size:" << rpcPathLen);
return OCK_RPC_ERR;
}
if (realpath(tmp, rpcPath) == nullptr) {
OCK_RPC_LOG_ERROR("realpath HCOM4DB_ENV_PATH failed");
return OCK_RPC_ERR;
}
return OCK_RPC_OK;
}
static int Hcom4dbInitDlopenSo(void)
{
char rpcPath[PATH_MAX] = {0};
int ret = Hcom4dbGetLibPath(rpcPath, sizeof(rpcPath));
if (ret != OCK_RPC_OK) {
return OCK_RPC_ERR;
}
char ockRpcDlPath[PATH_MAX] = {0};
ret = snprintf_s(ockRpcDlPath, PATH_MAX, PATH_MAX - 1, "%s/%s", rpcPath, HCOM4DB_SO_NAME);
if (ret < 0) {
OCK_RPC_LOG_ERROR("construct hcom dl failed, ret " << ret);
return OCK_RPC_ERR;
}
ret = InitOckRpcDl(ockRpcDlPath, PATH_MAX);
if (ret != OCK_RPC_OK) {
OCK_RPC_LOG_ERROR("Hcom4db init hcomDl failed, ret " << ret);
return OCK_RPC_ERR;
}
return OCK_RPC_OK;
}
OckRpcServerContext OckRpcServerCtxBuilderThreadLocal(OckRpcServer server)
{
return 0;
}
void OckRpcServerCtxCleanupThreadLocal(OckRpcServer server, OckRpcServerContext ctx)
{
return;
}
static int OckRpcRegisterMr(OckRpcServer server, uintptr_t address, size_t memSize, Service_MemoryRegionInfo* info,
Service_MemoryRegion* mr)
{
int ret = Service_RegisterAssignMemoryRegion(server, address, memSize, mr);
if (ret != OCK_RPC_OK) {
OCK_RPC_LOG_ERROR("Register mr failed, ret(" << ret << ").");
return OCK_RPC_ERR;
}
ret = Service_GetMemoryRegionInfo(*mr, info);
if (ret != OCK_RPC_OK) {
OCK_RPC_LOG_ERROR("Get mr info failed, ret(" << ret << ").");
return OCK_RPC_ERR;
}
return OCK_RPC_OK;
}
static int OckRpcString2Num(std::map<std::string, const char *> &configMap, const char *key, uint32_t &size)
{
auto iter = configMap.find(key);
if (iter != configMap.end()) {
try {
size = std::stoi(iter->second);
} catch (const std::invalid_argument &e) {
OCK_RPC_LOG_ERROR("Invalid argument " << key << " :" << e.what());
return OCK_RPC_ERR;
} catch (const std::out_of_range &e) {
OCK_RPC_LOG_ERROR("Out of range " << key << " :" << e.what());
return OCK_RPC_ERR;
}
}
return OCK_RPC_OK;
}
static int OckRpcSetAllocatorOption(std::map<std::string, const char *> &configMap, Net_MemoryAllocatorOptions *option)
{
uint32_t maxSize = OCK_MAX_MESSAG_SIZE;
int ret = OckRpcString2Num(configMap, OCK_RPC_STR_PRE_SEGMENT_SIZE, maxSize);
if (ret != OCK_RPC_OK) {
return OCK_RPC_ERR;
}
if (maxSize > MAX_SEGMENT_SIZE) {
OCK_RPC_LOG_ERROR("Invalid params, OCK_RPC_STR_PRE_SEGMENT_SIZE should be less than " << MAX_SEGMENT_SIZE);
return OCK_RPC_ERR;
}
uint32_t maxCount = OCK_MAX_MESSAG_COUNT;
ret = OckRpcString2Num(configMap, OCK_RPC_STR_PRE_SEGMENT_COUNT, maxCount);
if (ret != OCK_RPC_OK) {
return OCK_RPC_ERR;
}
if (maxCount > MAX_SEGMENT_COUNT) {
OCK_RPC_LOG_ERROR("Invalid params, OCK_RPC_STR_PRE_SEGMENT_COUNT should be less than " << MAX_SEGMENT_COUNT);
return OCK_RPC_ERR;
}
uint64_t allocatorSize = static_cast<uint64_t>(maxSize * maxCount);
if (allocatorSize == 0) {
OCK_RPC_LOG_WARN("Memory size for CallWithParams is 0, check it.");
return OCK_RPC_ERR_INVALID_PARAM;
}
if (allocatorSize < MR_MIN_SIZE) {
allocatorSize = MR_MIN_SIZE;
OCK_RPC_LOG_WARN("Memory size < 4096, has setted it to min size 4096");
}
uintptr_t beginAddr = reinterpret_cast<uintptr_t>(aligned_alloc(ALIGNED_SIZE, allocatorSize));
if (beginAddr == 0) {
OCK_RPC_LOG_ERROR("Memory allocator malloc failed, size:" << allocatorSize);
return OCK_RPC_ERR;
}
option->address = beginAddr;
option->size = allocatorSize;
option->minBlockSize = MR_MIN_SIZE;
option->alignedAddress = true;
uint32_t multiple = maxSize / MR_MIN_SIZE;
option->cacheTierCount = Calculate2PowerTimes(multiple);
option->cacheBlockCountPerTier = MR_PRE_ALLOC_CNT;
option->bucketCount = MR_BUCKET_MAP_SIZE;
option->cacheTierPolicy = C_TIER_POWER;
return OCK_RPC_OK;
}
static int OckRpcPrepareMemAllocator(
OckRpcServer server, OckRpcClient client, std::map<std::string, const char *> &configMap)
{
Net_MemoryAllocatorOptions option;
int ret = OckRpcSetAllocatorOption(configMap, &option);
if (ret == OCK_RPC_ERR_INVALID_PARAM) {
return OCK_RPC_OK;
}
if (ret != OCK_RPC_OK) {
return OCK_RPC_ERR;
}
Net_MemoryAllocator allocator = 0;
ret = Net_MemoryAllocatorCreate(C_DYNAMIC_SIZE_WITH_CACHE, &option, &allocator);
if (ret != OCK_RPC_OK) {
OCK_RPC_LOG_ERROR("Failed to create memory allocator.");
return OCK_RPC_ERR;
}
Service_MemoryRegionInfo info;
Service_MemoryRegion mr;
ret = OckRpcRegisterMr(server, option.address, option.size, &info, &mr);
if (ret != OCK_RPC_OK) {
OCK_RPC_LOG_ERROR("Failed to register memory region.");
return OCK_RPC_ERR;
}
ret = Net_MemoryAllocatorSetMrKey(allocator, info.lKey);
if (ret != OCK_RPC_OK) {
OCK_RPC_LOG_ERROR("Failed to set key for allocator.");
return OCK_RPC_ERR;
}
auto iter = g_memoryAllocator.find(client);
if (iter == g_memoryAllocator.end()) {
g_memoryAllocator.insert(std::make_pair(client, allocator));
}
OckRpcMrInfo mrInfo = OckRpcMrInfo();
mrInfo.mr = mr;
mrInfo.mrInfo = info;
mrInfo.server = server;
auto iterMr = g_memoryRegion.find(client);
if (iterMr == g_memoryRegion.end()) {
g_memoryRegion.insert(std::make_pair(client, mrInfo));
}
return OCK_RPC_OK;
}
static int OckRpcMemAlloc(OckRpcClient client, uint64_t memSize, uintptr_t *addr, uint32_t *key)
{
int ret = Net_MemoryAllocatorAllocate(g_memoryAllocator[client], memSize, addr, key);
if (ret != OCK_RPC_OK) {
OCK_RPC_LOG_ERROR("Hcom memory allocate failed, ret(" << ret << ").");
return OCK_RPC_ERR;
}
return OCK_RPC_OK;
}
static void OckRpcMemFree(OckRpcClient client, uintptr_t addr)
{
int32_t ret = Net_MemoryAllocatorFree(g_memoryAllocator[client], addr);
if (ret != OCK_RPC_OK) {
OCK_RPC_LOG_ERROR("Hcom memory free failed, ret(" << ret << ").");
}
return;
}
static int OckRpcTlsGetCertCb(const char *name, char **certPath)
{
g_tlsFunc.getCert(const_cast<const char **>(certPath));
if (*certPath == nullptr) {
OCK_RPC_LOG_ERROR("Cert path is nullptr, check your set.");
return OCK_RPC_ERR;
}
return OCK_RPC_OK;
}
static void OckRpcTlsKeypassEraseCb(char *keyPass, int len)
{
g_tlsFunc.eraseKeyPass(keyPass);
}
static int OckRpcTlsGetPrivateKeyCb(const char *name, char **priKeyPath, char **keyPass, Net_TlsKeyPassErase *erase)
{
g_tlsFunc.getPriKey(const_cast<const char **>(priKeyPath), keyPass, &g_tlsFunc.eraseKeyPass);
*erase = OckRpcTlsKeypassEraseCb;
if (*priKeyPath == nullptr || *keyPass == nullptr || *erase == nullptr) {
OCK_RPC_LOG_ERROR("Private key is nullptr, check your set.");
return OCK_RPC_ERR;
}
return OCK_RPC_OK;
}
static int OckRpcTlsGetCACb(
const char *name, char **caPath, char **crlPath, Net_PeerCertVerifyType *verifyType, Net_TlsCertVerify *verify)
{
g_tlsFunc.getCaAndVerify(const_cast<const char **>(caPath), const_cast<const char **>(crlPath), verify);
*verifyType = C_VERIFY_BY_CUSTOM_FUNC;
if (*caPath == nullptr || *crlPath == nullptr || verify == nullptr) {
OCK_RPC_LOG_ERROR("Ca path or crl path is nullptr, check your set.");
return OCK_RPC_ERR;
}
return OCK_RPC_OK;
}
static int32_t OckRpcNewChannel(Net_Channel newCh, uint64_t usrCtx, const char *payLoad)
{
OCK_RPC_LOG_INFO("channel new.");
return OCK_RPC_OK;
}
static int32_t OckRpcBrokenChannel(Net_Channel newCh, uint64_t usrCtx, const char *payLoad)
{
Channel_DeRefer(newCh);
OCK_RPC_LOG_INFO("channel broken.");
return OCK_RPC_OK;
}
static int OckRpcReceiveHandle(Service_Context ctx, uint64_t usrCtx)
{
int ret;
OckRpcMessage msg;
msg.data = Service_GetMessageData(ctx);
if (msg.data == nullptr) {
OCK_RPC_LOG_ERROR("Receiver get nullptr message.");
return OCK_RPC_ERR;
}
msg.len = Service_GetMessageDataLen(ctx);
Service_ContextType ctxType;
ret = Service_GetContextType(ctx, &ctxType);
if (ret != OCK_RPC_OK) {
OCK_RPC_LOG_ERROR("Get context type failed.");
return OCK_RPC_ERR;
}
uint16_t msgId = 0;
if (ctxType == SERVICE_RECEIVED_RAW) {
RawMessageHeader *head = (RawMessageHeader *)msg.data;
msgId = head->msgId;
msg.data = (uint8_t *)msg.data + sizeof(RawMessageHeader);
msg.len -= sizeof(RawMessageHeader);
} else {
Service_OpInfo opInfo;
ret = Service_GetOpInfo(ctx, &opInfo);
if (ret != OCK_RPC_OK) {
OCK_RPC_LOG_ERROR("Receiver get opInfo failed, ret(" << ret << ").");
return OCK_RPC_ERR;
}
msgId = opInfo.opCode;
}
serviceAddMutex.lock_shared();
auto iter = g_handleMap.find(msgId);
if (iter != g_handleMap.end()) {
iter->second(ctx, msg);
} else {
OCK_RPC_LOG_INFO("No match msg handle id:" << msgId << ", do nothing.");
}
serviceAddMutex.unlock();
return OCK_RPC_OK;
}
static int OckRpcPostHandle(Service_Context ctx, uint64_t usrCtx)
{
return 0;
}
static int OckRpcOneSideDone(Service_Context ctx, uint64_t usrCtx)
{
return 0;
}
static int OckRpcInitConfigMap(OckRpcCreateConfig *configs, std::map<std::string, const char *> &configMap)
{
if (configs->mask & OCK_RPC_CONFIG_USE_RPC_CONFIGS) {
if (configs->configs.pairs == nullptr) {
OCK_RPC_LOG_ERROR("Invalid configs, pairs is nullptr");
return OCK_RPC_ERR;
}
if (configs->configs.size < 0) {
OCK_RPC_LOG_ERROR("Invalid configs size.");
return OCK_RPC_ERR;
}
for (int i = 0; i < configs->configs.size; i++) {
if (configs->configs.pairs[i].key == nullptr || configs->configs.pairs[i].value == nullptr) {
OCK_RPC_LOG_ERROR("Invalid configs, key or value is nullptr, check");
return OCK_RPC_ERR;
}
configMap.insert(std::make_pair(configs->configs.pairs[i].key, configs->configs.pairs[i].value));
}
}
return OCK_RPC_OK;
}
static int OckRpcCreateServer(std::map<std::string, const char *> &configMap, OckRpcServer *server)
{
const char* serviceName = "service";
auto iter = configMap.find(OCK_RPC_STR_SERVER_NAME);
if (iter != configMap.end()) {
serviceName = iter->second;
}
if (strlen(serviceName) > NUM_64) {
OCK_RPC_LOG_ERROR("Invalid serviceName, bigger than 64");
return OCK_RPC_ERR_INVALID_PARAM;
}
Service_Type type = C_SERVICE_RDMA;
auto iterType = configMap.find(OCK_RPC_STR_COMMUNICATION_TYPE);
const char *expectType = "TCP";
const char *expectTypeRdma = "RDMA";
const char *expectTypeUbc = "UBC";
if (iterType != configMap.end()) {
if (!strcmp(iterType->second, expectType)) {
type = C_SERVICE_TCP;
g_connectionType = C_SERVICE_TCP;
OCK_RPC_LOG_INFO("Create transport type TCP");
} else if (!strcmp(iterType->second, expectTypeRdma)) {
type = C_SERVICE_RDMA;
g_connectionType = C_SERVICE_RDMA;
OCK_RPC_LOG_INFO("Create transport type RDMA");
} else if (!strcmp(iterType->second, expectTypeUbc)) {
type = C_SERVICE_UBC;
g_connectionType = C_SERVICE_UBC;
OCK_RPC_LOG_INFO("Create transport type UBC");
} else {
OCK_RPC_LOG_ERROR("Invalid transport type, should be TCP or RDMA");
return OCK_RPC_ERR_INVALID_PARAM;
}
}
int ret = Service_Create(type, serviceName, true, server);
if (ret != OCK_RPC_OK) {
OCK_RPC_LOG_ERROR("Create server failed, ret(" << ret << ").");
return OCK_RPC_ERR;
}
serviceMutex.lock_shared();
auto iterName = g_serviceMap.find(serviceName);
if (iterName == g_serviceMap.end()) {
g_serviceMap.insert(std::make_pair(serviceName, *server));
}
serviceMutex.unlock_shared();
return OCK_RPC_OK;
}
static void OckRpcRegisterChannelHandle(Net_Service service, std::map<std::string, const char *> &configMap)
{
OckRpcClientHandler newFunc = OckRpcNewChannel;
auto newIter = configMap.find(OCK_RPC_STR_CLIENT_NEW);
if (newIter != configMap.end()) {
uintptr_t newPtr = (uintptr_t)const_cast<char *>(newIter->second);
newFunc = reinterpret_cast<OckRpcClientHandler>(newPtr);
}
OckRpcClientHandler breakFunc = OckRpcBrokenChannel;
auto breakIter = configMap.find(OCK_RPC_STR_CLIENT_BREAK);
if (breakIter != configMap.end()) {
uintptr_t breakPtr = (uintptr_t)const_cast<char *>(breakIter->second);
breakFunc = reinterpret_cast<OckRpcClientHandler>(breakPtr);
}
Service_RegisterChannelHandler(service, C_CHANNEL_NEW, newFunc, C_CHANNEL_BROKEN_ALL, 1);
Service_RegisterChannelHandler(service, C_CHANNEL_BROKEN, breakFunc, C_CHANNEL_BROKEN_ALL, 1);
}
static int OckRpcSetWorkThreadConfigs(std::map<std::string, const char *> &configMap, Service_Options *options)
{
int ret;
options->mode = C_SERVICE_EVENT_POLLING;
const char *expectType = "yes";
const char *expectTypeNo = "no";
auto iter = configMap.find(OCK_RPC_STR_ENABLE_POLL_WORKER);
if (iter != configMap.end()) {
if (!strcmp(iter->second, expectType)) {
OCK_RPC_LOG_INFO("Set busy polling");
options->mode = C_SERVICE_BUSY_POLLING;
} else if (!strcmp(iter->second, expectTypeNo)) {
OCK_RPC_LOG_INFO("Set event polling");
options->mode = C_SERVICE_EVENT_POLLING;
} else {
OCK_RPC_LOG_ERROR("Invalid param, CK_RPC_STR_ENABLE_POLL_WORKER should be yes or no");
return OCK_RPC_ERR;
}
} else {
OCK_RPC_LOG_INFO("Set event polling");
}
iter = configMap.find(OCK_RPC_STR_WRK_THR_GRP);
if (iter != configMap.end()) {
ret = strcpy_s(options->workerGroups, NUM_64, iter->second);
if (ret != OCK_RPC_OK) {
OCK_RPC_LOG_ERROR("Set worker group option failed, check config:" << OCK_RPC_STR_WRK_THR_GRP << ".");
return OCK_RPC_ERR;
}
}
iter = configMap.find(OCK_RPC_STR_WRK_CPU_SET);
if (iter != configMap.end()) {
ret = strcpy_s(options->workerGroupsCpuSet, NUM_128, iter->second);
if (ret != OCK_RPC_OK) {
OCK_RPC_LOG_ERROR("Set worker cpu option failed, check config:" << OCK_RPC_STR_WRK_CPU_SET << ".");
return OCK_RPC_ERR;
}
}
return OCK_RPC_OK;
}
static int OckRpcRndvReceiveHandler(Service_RndvContext ctx)
{
int ret;
Service_RndvMessage rndvMsg;
ret = Service_GetRndvMessage(ctx, &rndvMsg);
if (ret != OCK_RPC_OK) {
OCK_RPC_LOG_ERROR("Rndv Get message failed, ret(" << ret << ").");
return OCK_RPC_ERR;
}
OckRpcRndvMessage msg = OckRpcRndvMessage();
msg.cnt = rndvMsg.cnt;
for (int i = 0; i < msg.cnt; i++) {
msg.msg[i].data = rndvMsg.msg[i].data;
msg.msg[i].len = rndvMsg.msg[i].size;
}
Service_RndvType ctxType;
ret = Service_GetRndvCtxType(ctx, &ctxType);
if (ret != OCK_RPC_OK) {
OCK_RPC_LOG_ERROR("Rndv Get context type failed, ret(" << ret << ").");
return OCK_RPC_ERR;
}
if (ctxType == C_SER_RNDV_SGL) {
OCK_RPC_LOG_INFO("Handler receive SGL");
}
Service_OpInfo opInfo;
ret = Service_GetRndvOpInfo(ctx, &opInfo);
if (ret != OCK_RPC_OK) {
OCK_RPC_LOG_ERROR("Rndv Get option info failed, ret(" << ret << ").");
return OCK_RPC_ERR;
}
serviceAddRndvMutex.lock_shared();
auto iter = g_rndvHandleMap.find(opInfo.opCode);
if (iter != g_rndvHandleMap.end()) {
iter->second(ctx, msg);
} else {
OCK_RPC_LOG_INFO("No match msg handle id:" << opInfo.opCode << ", do nothing.");
}
serviceAddRndvMutex.unlock();
return OCK_RPC_OK;
}
static int32_t SetRndvOpHandler(Net_Service service, const std::map<std::string, const char *> &configMap)
{
auto mallocIter = configMap.find(OCK_RPC_STR_RNDV_MALLOC);
if (mallocIter == configMap.end()) {
OCK_RPC_LOG_ERROR("Param key:" << OCK_RPC_STR_RNDV_MALLOC << " not find, check your set.");
return OCK_RPC_ERR;
}
auto freeIter = configMap.find(OCK_RPC_STR_RNDV_MFREE);
if (freeIter == configMap.end()) {
OCK_RPC_LOG_ERROR("Param key:" << OCK_RPC_STR_RNDV_MFREE << " not find, check your set.");
return OCK_RPC_ERR;
}
uintptr_t mallocPtr = (uintptr_t)const_cast<char *>(mallocIter->second);
OckRpcRndvMemAllocate allcFunc = reinterpret_cast<OckRpcRndvMemAllocate>(mallocPtr);
uintptr_t freePtr = (uintptr_t)const_cast<char *>(freeIter->second);
OckRpcRndvMemFree freeFunc = reinterpret_cast<OckRpcRndvMemFree>(freePtr);
Service_RegisterAllocateHandler(service, allcFunc);
Service_RegisterFreeHandler(service, freeFunc);
Service_RegisterRndvOpHandler(service, &OckRpcRndvReceiveHandler);
return OCK_RPC_OK;
}
static int32_t OckRpcDefaultOptionInit(
std::map<std::string, const char *> &configMap, Service_Options *options, const char *ip)
{
char ipMask[IP_MAX_LEN] = {0};
int ret = snprintf_s(ipMask, IP_MAX_LEN, IP_MAX_LEN - 1, "%s/24", ip);
if (ret < 0) {
OCK_RPC_LOG_ERROR("Init default option, snprintf ip failed, ret(" << ret << ").");
return OCK_RPC_ERR_INVALID_PARAM;
}
options->mrSendReceiveSegSize = OCK_MAX_MESSAG_SIZE;
options->mrSendReceiveSegCount = OCK_MAX_MESSAG_COUNT;
ret = OckRpcString2Num(configMap, OCK_RPC_STR_PRE_SEGMENT_SIZE, options->mrSendReceiveSegSize);
if (ret != OCK_RPC_OK) {
return OCK_RPC_ERR;
}
ret = OckRpcString2Num(configMap, OCK_RPC_STR_PRE_SEGMENT_COUNT, options->mrSendReceiveSegCount);
if (ret != OCK_RPC_OK) {
return OCK_RPC_ERR;
}
options->qpSendQueueSize = OCK_MAX_SEND_QUEUE_SIZE;
options->qpReceiveQueueSize = OCK_MAX_RECEIVE_QUEUE_SIZE;
options->prePostReceiveSizePerQP = OCK_MAX_PRE_SEND_RECEIVE_SIZE;
options->completionQueueDepth = OCK_MAX_COMPLETE_QUEUE_SIZE;
auto iter = configMap.find(OCK_RPC_STR_SERVER_PORT_RANGE);
if (iter != configMap.end()) {
const char *portRange = iter->second;
ret = memcpy_s(options->oobPortRange, NUM_16, portRange, strlen(portRange));
} else {
OCK_RPC_LOG_INFO("Set Default port range 4000-5000");
ret = memcpy_s(options->oobPortRange, NUM_16, "4000-5000", strlen("4000-5000"));
}
if (ret != OCK_RPC_OK) {
OCK_RPC_LOG_ERROR("Memcpy port range failed, ret:" << ret);
return OCK_RPC_ERR;
}
ret = strcpy_s(options->netDeviceIpMask, NUM_256, ipMask);
if (ret != OCK_RPC_OK) {
OCK_RPC_LOG_ERROR("Set option failed, config ip mask is invalid, check your ip.");
return OCK_RPC_ERR;
}
return OCK_RPC_OK;
}
static int OckRpcSetTlsConfigs(OckRpcServer service, OckRpcCreateConfig *configs,
std::map<std::string, const char *> &configMap, Service_Options *options)
{
const char *expectSet = "yes";
const char *expectSetNo = "no";
options->enableTls = true;
options->tlsVersion = C_SERVICE_TLS_1_3;
auto tlsIter = configMap.find(OCK_RPC_STR_ENABLE_TLS);
if (tlsIter != configMap.end()) {
if (!strcmp(tlsIter->second, expectSetNo)) {
options->enableTls = false;
} else if (!strcmp(tlsIter->second, expectSet)) {
options->enableTls = true;
} else {
OCK_RPC_LOG_ERROR("Invalid param, OCK_RPC_STR_ENABLE_TLS should be yes or no");
return OCK_RPC_ERR;
}
}
if ((configs->mask & OCK_RPC_CONFIG_USE_SSL_CALLBACK) && options->enableTls) {
if (configs->getCaAndVerify == nullptr || configs->getCert == nullptr || configs->getPriKey == nullptr) {
OCK_RPC_LOG_ERROR("Expand option init failed, tls function is invalid.");
return OCK_RPC_ERR;
}
g_tlsFunc.getCaAndVerify = configs->getCaAndVerify;
g_tlsFunc.getCert = configs->getCert;
g_tlsFunc.getPriKey = configs->getPriKey;
(void)Service_RegisterTLSCb(service, &OckRpcTlsGetCertCb, &OckRpcTlsGetPrivateKeyCb, &OckRpcTlsGetCACb);
OCK_RPC_LOG_INFO("Expand option init, tls function is registered.");
} else {
options->enableTls = false;
}
return OCK_RPC_OK;
}
static int32_t OckRpcExpandOptionInit(OckRpcServer service, OckRpcCreateConfig *configs,
std::map<std::string, const char *> &configMap, Service_Options *options)
{
int ret = 0;
if (configs->mask & OCK_RPC_CONFIG_USE_RPC_CONFIGS) {
ret = OckRpcSetWorkThreadConfigs(configMap, options);
if (ret != OCK_RPC_OK) {
return OCK_RPC_ERR;
}
}
uint32_t heartBeatIdleTime = DEFAULT_HEARTBEAT_IDLE_TIME;
ret = OckRpcString2Num(configMap, OCK_RPC_STR_HEATBEAT_IDLE, heartBeatIdleTime);
if (ret != OCK_RPC_OK) {
return OCK_RPC_ERR;
}
options->heartBeatIdleTime = heartBeatIdleTime;
OCK_RPC_LOG_INFO("Now Heartbeat idle time is " << options->heartBeatIdleTime);
options->enableRndv = false;
auto rndvIter = configMap.find(OCK_RPC_STR_ENABLE_SEND_RNDV);
const char *expectSet = "yes";
const char *expectSetNo = "no";
if (rndvIter != configMap.end()) {
if (!strcmp(rndvIter->second, expectSet)) {
ret = SetRndvOpHandler(service, configMap);
if (ret != OCK_RPC_OK) {
return OCK_RPC_ERR;
}
options->enableRndv = true;
} else if (!strcmp(rndvIter->second, expectSetNo)) {
options->enableRndv = false;
} else {
OCK_RPC_LOG_ERROR("Invalid param, OCK_RPC_STR_ENABLE_SEND_RNDV should be yes or no");
return OCK_RPC_ERR;
}
}
ret = OckRpcSetTlsConfigs(service, configs, configMap, options);
if (ret != OCK_RPC_OK) {
return OCK_RPC_ERR;
}
return OCK_RPC_OK;
}
static void HcomLog(int level, const char *msg)
{
OCK_RPC_HCOM_LOG(level, msg);
}
void OckRpcSetExternalLogger(OckRpcLogHandler h)
{
Hcom4dbLog::Hcom4dbLog::Instance()->SetExternalLogFunction(h);
g_logFunc = h;
}
static int32_t OckRpcCheckServerCreateCfg(
const char *ip, uint16_t port, OckRpcServer *server, OckRpcCreateConfig *configs)
{
if (ip == nullptr) {
OCK_RPC_LOG_ERROR("Invalid param, ip is null.");
return OCK_RPC_ERR_INVALID_PARAM;
}
if (port != 0 && port < OCK_MIN_PORT_NUM) {
OCK_RPC_LOG_ERROR("Invalid param, port should be 1024 to 65535 or 0.");
return OCK_RPC_ERR_INVALID_PARAM;
}
if (server == nullptr) {
OCK_RPC_LOG_ERROR("Invalid param, server is null.");
return OCK_RPC_ERR_INVALID_PARAM;
}
if (configs == nullptr) {
OCK_RPC_LOG_ERROR("Invalid param, configs is null.");
return OCK_RPC_ERR_INVALID_PARAM;
}
return OCK_RPC_OK;
}
OckRpcStatus OckRpcServerCreateWithCfg(const char *ip, uint16_t port, OckRpcServer *server, OckRpcCreateConfig *configs)
{
int ret = Hcom4dbInitDlopenSo();
if (ret != OCK_RPC_OK) {
OCK_RPC_LOG_ERROR("Dlopen so failed");
return OCK_RPC_ERR;
}
if (OckRpcCheckServerCreateCfg(ip, port, server, configs) != OCK_RPC_OK) {
return OCK_RPC_ERR_INVALID_PARAM;
}
std::map<std::string, const char *> configMap;
ret = OckRpcInitConfigMap(configs, configMap);
if (ret != OCK_RPC_OK) {
return OCK_RPC_ERR_INVALID_PARAM;
}
if (g_logFunc == nullptr) {
g_logFunc = &HcomLog;
}
Service_SetExternalLogger(g_logFunc);
ret = OckRpcCreateServer(configMap, server);
if (ret == OCK_RPC_ERR_INVALID_PARAM) {
return OCK_RPC_ERR_INVALID_PARAM;
} else if (ret != OCK_RPC_OK) {
return OCK_RPC_ERR;
}
Net_Service service = *server;
Service_SetOobIpAndPort(service, ip, port);
OckRpcRegisterChannelHandle(service, configMap);
Service_RegisterOpHandler(service, 0, C_SERVICE_REQUEST_RECEIVED, &OckRpcReceiveHandle, 1);
Service_RegisterOpHandler(service, 0, C_SERVICE_REQUEST_POSTED, &OckRpcPostHandle, 1);
Service_RegisterOpHandler(service, 0, C_SERVICE_READWRITE_DONE, &OckRpcOneSideDone, 1);
Service_Options *options = &g_options;
ret = OckRpcDefaultOptionInit(configMap, options, ip);
if (ret != OCK_RPC_OK) {
OckRpcServerDestroy(service);
return OCK_RPC_ERR_INVALID_PARAM;
}
ret = OckRpcExpandOptionInit(service, configs, configMap, options);
if (ret != OCK_RPC_OK) {
OckRpcServerDestroy(service);
return OCK_RPC_ERR_INVALID_PARAM;
}
OCK_RPC_LOG_INFO("Server create success.");
return OCK_RPC_OK;
}
bool OckRpcGetOobIpAndPort(OckRpcServer server, char ***ipArray, uint16_t **portArray, int *length)
{
return Service_GetOobIpAndPort(server, ipArray, portArray, length);
}
OckRpcStatus OckRpcServerAddService(OckRpcServer server, OckRpcService *service)
{
serviceAddMutex.lock();
auto iter = std::find_if(g_serviceMap.begin(),
g_serviceMap.end(),
[server](const std::pair<std::string, Net_Service> &p) { return p.second == server; });
if (iter == g_serviceMap.end()) {
OCK_RPC_LOG_ERROR("Invalid param, server is invalid.");
serviceAddMutex.unlock();
return OCK_RPC_ERR_INVALID_PARAM;
}
if (service == nullptr) {
OCK_RPC_LOG_ERROR("Invalid param, service is nullptr.");
serviceAddMutex.unlock();
return OCK_RPC_ERR_INVALID_PARAM;
}
if (service->id >= MAX_MESSAGE_ID_SIZE) {
OCK_RPC_LOG_ERROR("Invalid param, service msgId is more than 999.");
serviceAddMutex.unlock();
return OCK_RPC_ERR_INVALID_PARAM;
}
if (service->handler == nullptr) {
OCK_RPC_LOG_ERROR("Invalid param, service handler is nullptr.");
serviceAddMutex.unlock();
return OCK_RPC_ERR_INVALID_PARAM;
}
auto mapIter = g_handleMap.find(service->id);
if (mapIter != g_handleMap.end()) {
OCK_RPC_LOG_INFO("Service id " << service->id << " exists, will replace old service.");
}
g_handleMap[service->id] = service->handler;
serviceAddMutex.unlock();
return OCK_RPC_OK;
}
OckRpcStatus OckRpcServerAddRndvService(OckRpcServer server, OckRpcRndvService *service)
{
serviceAddRndvMutex.lock();
auto iter = std::find_if(g_serviceMap.begin(),
g_serviceMap.end(),
[server](const std::pair<std::string, Net_Service> &p) { return p.second == server; });
if (iter == g_serviceMap.end()) {
OCK_RPC_LOG_ERROR("Invalid param, server is invalid.");
serviceAddRndvMutex.unlock();
return OCK_RPC_ERR_INVALID_PARAM;
}
if (service == nullptr) {
OCK_RPC_LOG_ERROR("Invalid param, service is nullptr.");
serviceAddRndvMutex.unlock();
return OCK_RPC_ERR_INVALID_PARAM;
}
if (service->id >= MAX_MESSAGE_ID_SIZE) {
OCK_RPC_LOG_ERROR("Invalid param, service msgId is more than 999.");
serviceAddRndvMutex.unlock();
return OCK_RPC_ERR_INVALID_PARAM;
}
if (service->handler == nullptr) {
OCK_RPC_LOG_ERROR("Invalid param, service handler is nullptr.");
serviceAddRndvMutex.unlock();
return OCK_RPC_ERR_INVALID_PARAM;
}
auto mapIter = g_rndvHandleMap.find(service->id);
if (mapIter != g_rndvHandleMap.end()) {
OCK_RPC_LOG_INFO("Service id " << service->id << " exists, will replace old service.");
}
g_rndvHandleMap[service->id] = service->handler;
serviceAddRndvMutex.unlock();
return OCK_RPC_OK;
}
OckRpcStatus OckRpcServerStart(OckRpcServer server)
{
int32_t ret = Service_Start(server, g_options);
if (ret != OCK_RPC_OK) {
OCK_RPC_LOG_ERROR("Server start failed, ret(" << ret << ").");
return OCK_RPC_ERR;
}
return OCK_RPC_OK;
}
void OckRpcServerDestroy(OckRpcServer server)
{
serviceMutex.lock();
auto iter = std::find_if(g_serviceMap.begin(),
g_serviceMap.end(),
[server](const std::pair<std::string, Net_Service> &p) { return p.second == server; });
if (iter == g_serviceMap.end()) {
OCK_RPC_LOG_ERROR("Invalid server, check your status.");
serviceMutex.unlock();
return;
}
Service_Stop(server);
int ret = Service_Destroy(server);
if (ret != OCK_RPC_OK) {
OCK_RPC_LOG_ERROR("Service destroy failed, ret(" << ret << ")");
serviceMutex.unlock();
return;
}
g_serviceMap.erase(iter);
serviceMutex.unlock();
g_options = Service_Options();
g_tlsFunc = TlsFuncs();
}
OckRpcServerContext OckRpcCloneCtx(OckRpcServerContext ctx)
{
return Service_ContextClone(ctx);
}
void OckRpcDeCloneCtx(OckRpcServerContext ctx)
{
Service_ContextDeClone(ctx);
}
void OckRpcServerCleanupCtx(OckRpcServerContext ctx)
{
return;
}
static int OckRpcGetCurService(std::map<std::string, const char *> &configMap, Net_Service *service)
{
std::string serviceName = "service";
auto iter = configMap.find(OCK_RPC_STR_SERVER_NAME);
if (iter != configMap.end()) {
serviceName = iter->second;
}
if (serviceName.size() > NUM_64) {
OCK_RPC_LOG_ERROR("Invalid serviceName, bigger than 64");
return OCK_RPC_ERR_INVALID_PARAM;
}
serviceMutex.lock_shared();
auto iterService = g_serviceMap.find(serviceName);
if (iterService == g_serviceMap.end()) {
OCK_RPC_LOG_ERROR("Connect failed, check whether the value of OCK_RPC_STR_SERVER_NAME is the same as that of "
"the created server.");
serviceMutex.unlock_shared();
return OCK_RPC_ERR;
}
serviceMutex.unlock_shared();
*service = iterService->second;
return OCK_RPC_OK;
}
static int OckRpcSetConnectionOption(std::map<std::string, const char *> &configMap, Service_ConnectOpt *connOption)
{
connOption->epSize = DEFAULT_CONNECTION_EP_SIZE;
connOption->flags = SER_C_CHANNEL_SELF_POLLING;
const char *expectType = "no";
const char *expectTypeYes = "yes";
auto pollingTypeIter = configMap.find(OCK_RPC_STR_ENABLE_SELFPOLLING);
if (pollingTypeIter != configMap.end()) {
if (!strcmp(pollingTypeIter->second, expectType)) {
connOption->flags = 0;
OCK_RPC_LOG_INFO("Set worker polling");
} else if (!strcmp(pollingTypeIter->second, expectTypeYes)) {
connOption->flags = SER_C_CHANNEL_SELF_POLLING;
OCK_RPC_LOG_INFO("Set self polling");
} else {
OCK_RPC_LOG_ERROR("Invalid param, OCK_RPC_STR_ENABLE_SELFPOLLING should be yes or no");
return OCK_RPC_ERR;
}
} else {
OCK_RPC_LOG_INFO("Set self polling");
}
return OCK_RPC_OK;
}
static int32_t OckRpcCheckClientCreateCfg(
const char *ip, uint16_t port, OckRpcClient *client, OckRpcCreateConfig *configs)
{
if (ip == nullptr) {
OCK_RPC_LOG_ERROR("Invalid param, ip is null.");
return OCK_RPC_ERR_INVALID_PARAM;
}
if (port != 0 && port < OCK_MIN_PORT_NUM) {
OCK_RPC_LOG_ERROR("Invalid param, port should be 1024 to 65535 or 0.");
return OCK_RPC_ERR_INVALID_PARAM;
}
if (client == nullptr) {
OCK_RPC_LOG_ERROR("Invalid param, client is null.");
return OCK_RPC_ERR_INVALID_PARAM;
}
if (configs == nullptr) {
OCK_RPC_LOG_ERROR("Invalid param, configs is null.");
return OCK_RPC_ERR_INVALID_PARAM;
}
return OCK_RPC_OK;
}
OckRpcStatus OckRpcClientConnectWithCfg(
const char *ip, uint16_t port, OckRpcClient *client, OckRpcCreateConfig *configs)
{
if (OckRpcCheckClientCreateCfg(ip, port, client, configs) != OCK_RPC_OK) {
return OCK_RPC_ERR_INVALID_PARAM;
}
int ret;
std::map<std::string, const char *> configMap;
ret = OckRpcInitConfigMap(configs, configMap);
if (ret != OCK_RPC_OK) {
return OCK_RPC_ERR_INVALID_PARAM;
}
Net_Service service = 0;
ret = OckRpcGetCurService(configMap, &service);
if (ret != OCK_RPC_OK) {
return OCK_RPC_ERR_INVALID_PARAM;
}
const char *payLoad = "hello";
auto payLoadIter = configMap.find(OCK_RPC_STR_CLIENT_CREATE_INFO);
if (payLoadIter != configMap.end()) {
payLoad = payLoadIter->second;
}
Service_ConnectOpt connOption = Service_ConnectOpt();
ret = OckRpcSetConnectionOption(configMap, &connOption);
if (ret != OCK_RPC_OK) {
return OCK_RPC_ERR_INVALID_PARAM;
}
ret = Service_Connect(service, ip, port, payLoad, client, &connOption);
if (ret != OCK_RPC_OK) {
OCK_RPC_LOG_ERROR("Connect failed, ret(" << ret << ").");
return OCK_RPC_ERR;
}
ret = OckRpcPrepareMemAllocator(service, *client, configMap);
if (ret != OCK_RPC_OK) {
return OCK_RPC_ERR;
}
return OCK_RPC_OK;
}
void OckRpcClientDisconnect(OckRpcClient client)
{
int ret = 0;
auto iter = g_memoryAllocator.find(client);
if (iter != g_memoryAllocator.end()) {
ret = Net_MemoryAllocatorDestroy(iter->second);
if (ret != OCK_RPC_OK) {
OCK_RPC_LOG_ERROR("Disconnect destroy allocator failed.");
}
g_memoryAllocator.erase(client);
}
auto iterMr = g_memoryRegion.find(client);
if (iterMr != g_memoryRegion.end()) {
OckRpcMrInfo mrInfo = iterMr->second;
std::free(reinterpret_cast<void *>(mrInfo.mrInfo.lAddress));
Service_DestroyMemoryRegion(mrInfo.server, mrInfo.mr);
g_memoryRegion.erase(client);
}
Channel_Close(client);
}
void OckRpcClientDisconnectBreakHandler(OckRpcClient client)
{
Channel_DeRefer(client);
}
int OckRpcSetUpCtx(OckRpcClient client, uint64_t ctx)
{
return Channel_SetUpCtx(client, ctx);
}
int OckRpcGetUpCtx(OckRpcClient client, uint64_t *ctx)
{
return Channel_GetUpCtx(client, ctx);
}
static void ResponseCallBack(void *arg, Service_Context context)
{
AsyncCbInfo *cbInfo = (AsyncCbInfo *)arg;
OckRpcDoneCallback cb = cbInfo->cb;
void *doneArg = cbInfo->arg;
if (cb != nullptr) {
int result = OCK_RPC_OK;
if (Service_GetResult(context, &result) != OCK_RPC_OK) {
OCK_RPC_LOG_ERROR("Reply call async failed:" << result);
}
cb(static_cast<OckRpcStatus>(result), doneArg);
}
std::free(cbInfo);
return;
}
OckRpcStatus OckRpcServerReply(OckRpcServerContext ctx, uint16_t msgId, OckRpcMessage *reply, OckRpcCallDone *done)
{
if (reply == nullptr) {
OCK_RPC_LOG_ERROR("Invalid param, reply is nullptr.");
return OCK_RPC_ERR_INVALID_PARAM;
}
if (reply->len > UINT32_MAX) {
OCK_RPC_LOG_ERROR("Invalid param, reply len should be less than UINT32_MAX.");
return OCK_RPC_ERR_INVALID_PARAM;
}
Net_Channel channel;
Service_RspCtx rspCtx;
Service_ContextType ctxType;
if (Service_GetChannel(ctx, &channel) != OCK_RPC_OK || Service_GetRspCtx(ctx, &rspCtx) != OCK_RPC_OK ||
Service_GetContextType(ctx, &ctxType) != OCK_RPC_OK) {
OCK_RPC_LOG_ERROR("Reply get info with ctx failed");
return OCK_RPC_ERR;
}
Service_OpInfo rspOpInfo = Service_OpInfo();
AsyncCbInfo *cbInfo = nullptr;
cbInfo = (AsyncCbInfo *)std::malloc(sizeof(AsyncCbInfo));
if (cbInfo == nullptr) {
OCK_RPC_LOG_ERROR("Malloc call back info size " << sizeof(AsyncCbInfo) << " failed");
return OCK_RPC_ERR;
}
if (done != nullptr) {
cbInfo->cb = done->cb;
cbInfo->arg = done->arg;
} else {
cbInfo->cb = nullptr;
cbInfo->arg = nullptr;
}
Channel_Callback rspCb = {.cb = ResponseCallBack, .arg = static_cast<void *>(cbInfo)};
Service_Message req;
req.data = reply->data;
req.size = reply->len;
int ret = 0;
if (ctxType == SERVICE_RECEIVED_RAW) {
ret = Channel_PostResponseRaw(channel, rspCtx, &req, &rspCb);
} else {
ret = Channel_PostResponse(channel, rspCtx, &rspOpInfo, &req, &rspCb);
}
if (ret != 0) {
free(cbInfo);
OCK_RPC_LOG_ERROR("Reply failed, ret(" << ret << ")");
return OCK_RPC_ERR;
}
return OCK_RPC_OK;
}
static void OckRpcCallbackFunc(void *arg, Service_Context context)
{
int result = OCK_RPC_OK;
Service_ContextType cbType;
if (Service_GetResult(context, &result) != OCK_RPC_OK || Service_GetContextType(context, &cbType) != OCK_RPC_OK) {
OCK_RPC_LOG_ERROR("CallBack get failed.");
std::free(arg);
return;
}
if (cbType == SERVICE_ONE_SIDE) {
AsyncCbInfo *cbInfo = (AsyncCbInfo *)arg;
cbInfo->cb(static_cast<OckRpcStatus>(result), cbInfo->arg);
std::free(cbInfo);
return;
}
AsyncCbInfo *cbInfo = (AsyncCbInfo *)arg;
OckRpcDoneCallback cb = cbInfo->cb;
void *doneArg = cbInfo->arg;
OckRpcClient client = cbInfo->client;
uintptr_t *reqAddr = cbInfo->reqAddr;
uint32_t reqCnt = cbInfo->reqCnt;
OckRpcMessage *rspMsg = cbInfo->rsp;
std::free(cbInfo);
int ret = 0;
if (reqAddr != nullptr) {
for (uint32_t i = 0; i < reqCnt; i++) {
OckRpcMemFree(client, reqAddr[i]);
}
std::free(reqAddr);
}
if (rspMsg != nullptr) {
rspMsg->len = Service_GetMessageDataLen(context);
if (rspMsg->data == nullptr) {
rspMsg->data = malloc(rspMsg->len);
}
ret = memcpy_s(rspMsg->data, rspMsg->len, Service_GetMessageData(context), Service_GetMessageDataLen(context));
if (ret != OCK_RPC_OK) {
OCK_RPC_LOG_ERROR(
"Memcpy response data failed, ret:" << ret << ", rsp->data:" << rspMsg->data << ", len:" << rspMsg->len);
}
}
if (cb == nullptr) {
OCK_RPC_LOG_ERROR("Invalid cb nullptr.");
return;
}
cb(static_cast<OckRpcStatus>(result), doneArg);
}
static int32_t OckRpcCallSync(
OckRpcClient client, Service_OpInfo *reqOpInfo, Service_Message *request, OckRpcMessage *response)
{
int ret;
if (response != nullptr) {
Service_OpInfo rspOpInfo = Service_OpInfo();
Service_Message rsp = {.data = response->data, .size = static_cast<uint32_t>(response->len)};
ret = Channel_SyncCall(client, reqOpInfo, request, &rspOpInfo, &rsp);
if (ret != OCK_RPC_OK) {
OCK_RPC_LOG_ERROR("OckRpcCallSync needs response failed, ret(" << ret << ").");
return OCK_RPC_ERR;
}
response->data = rsp.data;
response->len = rsp.size;
} else {
ret = Channel_PostSend(client, reqOpInfo, request, nullptr);
if (ret != OCK_RPC_OK) {
OCK_RPC_LOG_ERROR("OckRpcCallSync ignores response failed, ret(" << ret << ").");
return OCK_RPC_ERR;
}
}
return OCK_RPC_OK;
}
static int32_t OckRpcCallASync(OckRpcClient client, Service_OpInfo *reqOpInfo, Service_Message *request,
OckRpcMessage *response, OckRpcCallDone *done)
{
int ret;
AsyncCbInfo *cbInfo = nullptr;
cbInfo = (AsyncCbInfo *)std::malloc(sizeof(AsyncCbInfo));
if (cbInfo == nullptr) {
OCK_RPC_LOG_ERROR("Malloc call back info size " << sizeof(AsyncCbInfo) << " failed");
return OCK_RPC_ERR;
}
cbInfo->cb = done->cb;
cbInfo->arg = done->arg;
cbInfo->reqAddr = nullptr;
cbInfo->reqCnt = 0;
cbInfo->rsp = response;
Channel_Callback cb = {.cb = OckRpcCallbackFunc, .arg = static_cast<void *>(cbInfo)};
if (response != nullptr) {
ret = Channel_AsyncCall(client, reqOpInfo, request, &cb);
if (ret != OCK_RPC_OK) {
std::free(cbInfo);
OCK_RPC_LOG_ERROR("OckRpcCallAsync needs response failed, ret(" << ret << ").");
return OCK_RPC_ERR;
}
} else {
ret = Channel_PostSend(client, reqOpInfo, request, &cb);
if (ret != OCK_RPC_OK) {
std::free(cbInfo);
OCK_RPC_LOG_ERROR("OckRpcCallAsync ignores response failed, ret(" << ret << ").");
return OCK_RPC_ERR;
}
}
return OCK_RPC_OK;
}
OckRpcStatus OckRpcClientCall(
OckRpcClient client, uint16_t msgId, OckRpcMessage *request, OckRpcMessage *response, OckRpcCallDone *done)
{
if (request == nullptr) {
OCK_RPC_LOG_ERROR("Invalid param, request is null.");
return OCK_RPC_ERR_INVALID_PARAM;
}
if (request->len > UINT32_MAX) {
OCK_RPC_LOG_ERROR("Invalid param, request len should be less than UINT32_MAX.");
return OCK_RPC_ERR_INVALID_PARAM;
}
int32_t ret = 0;
Service_OpInfo reqOpInfo = Service_OpInfo();
reqOpInfo.opCode = msgId;
reqOpInfo.timeout = g_timeoutTime;
Service_Message req = {.data = request->data, .size = static_cast<uint32_t>(request->len)};
if (done == nullptr) {
ret = OckRpcCallSync(client, &reqOpInfo, &req, response);
if (ret != OCK_RPC_OK) {
return OCK_RPC_ERR;
}
} else {
ret = OckRpcCallASync(client, &reqOpInfo, &req, response, done);
if (ret != OCK_RPC_OK) {
return OCK_RPC_ERR;
}
}
return OCK_RPC_OK;
}
static int32_t OckRpcCallSyncSgl(OckRpcClient client, Service_SglRequest *request, OckRpcMessage *response)
{
int ret = 0;
if (response != nullptr) {
Service_Message rsp = {.data = response->data, .size = static_cast<uint32_t>(response->len)};
ret = Channel_SyncCallRawSgl(client, request, &rsp);
if (ret != OCK_RPC_OK) {
OCK_RPC_LOG_ERROR("OckRpcCallSyncSgl needs response failed, ret(" << ret << ").");
return OCK_RPC_ERR;
}
response->data = rsp.data;
response->len = rsp.size;
} else {
ret = Channel_PostSendRawSgl(client, request, nullptr);
if (ret != OCK_RPC_OK) {
OCK_RPC_LOG_ERROR("OckRpcCallSyncSgl ignores response failed, ret(" << ret << ").");
return OCK_RPC_ERR;
}
}
return OCK_RPC_OK;
}
static int32_t OckRpcCallAsyncSgl(
OckRpcClient client, Service_SglRequest *request, OckRpcMessage *response, OckRpcCallDone *done)
{
int ret;
AsyncCbInfo *cbInfo = nullptr;
cbInfo = (AsyncCbInfo *)std::malloc(sizeof(AsyncCbInfo));
if (cbInfo == nullptr) {
OCK_RPC_LOG_ERROR("Malloc call back info size " << sizeof(AsyncCbInfo) << " failed");
return OCK_RPC_ERR;
}
cbInfo->client = client;
cbInfo->cb = done->cb;
cbInfo->arg = done->arg;
cbInfo->reqCnt = request->iovCount;
cbInfo->reqAddr = nullptr;
cbInfo->reqAddr = (uintptr_t *)std::malloc(sizeof(uintptr_t) * cbInfo->reqCnt);
if (cbInfo->reqAddr == nullptr) {
OCK_RPC_LOG_ERROR("Malloc call back info size " << sizeof(uintptr_t) * cbInfo->reqCnt << " failed");
free(cbInfo);
return OCK_RPC_ERR;
}
for (uint32_t i = 0; i < cbInfo->reqCnt; i++) {
cbInfo->reqAddr[i] = request->iov[i].lAddress;
}
cbInfo->rsp = response;
Channel_Callback cb = {.cb = OckRpcCallbackFunc, .arg = static_cast<void *>(cbInfo)};
if (response != nullptr) {
ret = Channel_AsyncCallRawSgl(client, request, &cb);
if (ret != OCK_RPC_OK) {
free(cbInfo->reqAddr);
free(cbInfo);
OCK_RPC_LOG_ERROR("OckRpcCallAsyncSgl needs response failed, ret(" << ret << ").");
return OCK_RPC_ERR;
}
} else {
ret = Channel_PostSendRawSgl(client, request, &cb);
if (ret != OCK_RPC_OK) {
free(cbInfo->reqAddr);
free(cbInfo);
OCK_RPC_LOG_ERROR("OckRpcCallAsyncSgl ignores response failed, ret(" << ret << ").");
return OCK_RPC_ERR;
}
}
return OCK_RPC_OK;
}
static int32_t SetReqInfo(OckRpcClient client, OckRpcMessageIov *reqIov, uint32_t count, Service_SglRequest *serviceReq)
{
int ret = OCK_RPC_OK;
uintptr_t addrArr[count] = {};
uint32_t keyArr[count] = {};
uint32_t size = 0;
for (uint32_t i = 0; i < count; i++) {
uint32_t reqPos = i + 1;
size = (i == count - 1) ? g_options.mrSendReceiveSegSize : reqIov->msgs[i].len;
ret = OckRpcMemAlloc(client, size, &addrArr[i], &keyArr[i]);
if (ret != OCK_RPC_OK) {
OCK_RPC_LOG_ERROR("Alloc failed, message id " << i << " size " << size << " is too large.");
for (uint32_t j = 0; j < i; j++) {
OckRpcMemFree(client, addrArr[i]);
}
return OCK_RPC_ERR;
}
ret = memcpy_s(reinterpret_cast<void *>(addrArr[i]),
g_options.mrSendReceiveSegSize,
reqIov->msgs[i].data,
reqIov->msgs[i].len);
if (ret != OCK_RPC_OK) {
OCK_RPC_LOG_ERROR("Memcpy multi data failed, ret(" << ret << ").");
for (uint32_t j = 0; j <= i; j++) {
OckRpcMemFree(client, addrArr[i]);
}
return OCK_RPC_ERR;
}
serviceReq->iovCount++;
serviceReq->iov[reqPos].lAddress = addrArr[i];
serviceReq->iov[reqPos].lKey = keyArr[i];
serviceReq->iov[reqPos].size = reqIov->msgs[i].len;
}
return OCK_RPC_OK;
}
static void FreeAllMemory(OckRpcClient client, const Service_SglRequest *serviceReq)
{
for (uint32_t i = 0; i < OCK_MAX_IOV_COUNT; i++) {
OckRpcMemFree(client, serviceReq->iov[i].lAddress);
}
}
static int32_t PackReqInfo(
OckRpcClient client, OckRpcMessageIov *reqIov, uint16_t msgId, Service_SglRequest *serviceReq)
{
int32_t ret = OCK_RPC_OK;
uint32_t curSglReqPos = 0;
uintptr_t headAddr = 0;
uint32_t headKey = 0;
ret = OckRpcMemAlloc(client, sizeof(RawMessageHeader), &headAddr, &headKey);
if (ret != OCK_RPC_OK) {
OCK_RPC_LOG_ERROR("Pack, message header allocate failed.");
return OCK_RPC_ERR;
}
auto* head = reinterpret_cast<RawMessageHeader*>(headAddr);
head->msgId = msgId;
serviceReq->iovCount++;
serviceReq->iov[curSglReqPos].lAddress = headAddr;
serviceReq->iov[curSglReqPos].lKey = headKey;
serviceReq->iov[curSglReqPos].size = sizeof(RawMessageHeader);
curSglReqPos += 1;
uint32_t maxCount = OCK_MAX_IOV_COUNT - curSglReqPos;
if (reqIov->count > maxCount) {
ret = SetReqInfo(client, reqIov, maxCount, serviceReq);
if (ret != OCK_RPC_OK) {
OckRpcMemFree(client, headAddr);
return OCK_RPC_ERR;
}
for (uint32_t i = maxCount; i < reqIov->count; i++) {
ret = memcpy_s(
reinterpret_cast<uint8_t *>(serviceReq->iov[maxCount].lAddress) + serviceReq->iov[maxCount].size,
g_options.mrSendReceiveSegSize - serviceReq->iov[maxCount].size,
reqIov->msgs[i].data,
reqIov->msgs[i].len);
if (ret != OCK_RPC_OK) {
OCK_RPC_LOG_ERROR("Memcpy append multi data faild, ret(" << ret << ").");
FreeAllMemory(client, serviceReq);
return OCK_RPC_ERR;
}
serviceReq->iov[maxCount].size += reqIov->msgs[i].len;
}
} else {
ret = SetReqInfo(client, reqIov, reqIov->count, serviceReq);
if (ret != OCK_RPC_OK) {
FreeAllMemory(client, serviceReq);
return OCK_RPC_ERR;
}
}
return OCK_RPC_OK;
}
OckRpcStatus OckRpcClientCallWithParam(OckRpcClientCallParams *params)
{
if (params == nullptr) {
OCK_RPC_LOG_ERROR("Invalid param, params is null.");
return OCK_RPC_ERR_INVALID_PARAM;
}
if (params->reqIov.msgs == nullptr) {
OCK_RPC_LOG_ERROR("Invalid param, params reqIov.msgs is null.");
return OCK_RPC_ERR_INVALID_PARAM;
}
if (params->reqIov.count > MAX_CALL_WITH_PARAMS_COUNT || params->reqIov.count <= 0) {
OCK_RPC_LOG_ERROR("Invalid param, params messages count should be [1, 8].");
return OCK_RPC_ERR_INVALID_PARAM;
}
for (size_t i = 0; i < params->reqIov.count; i++) {
if (params->reqIov.msgs[i].len > g_options.mrSendReceiveSegSize) {
OCK_RPC_LOG_ERROR(
"Invalid param, params messages count should be less than setting:OCK_RPC_STR_PRE_SEGMENT_SIZE");
return OCK_RPC_ERR_INVALID_PARAM;
}
}
int ret = OCK_RPC_OK;
OckRpcMessageIov *reqIov = ¶ms->reqIov;
Service_SglRequest serviceReq = Service_SglRequest();
Service_Request iovArr[OCK_MAX_IOV_COUNT] = {Service_Request()};
serviceReq.iov = iovArr;
ret = PackReqInfo(params->client, reqIov, params->msgId, &serviceReq);
if (ret != OCK_RPC_OK) {
return OCK_RPC_ERR;
}
OckRpcMessage *response = params->rspIov.msgs;
if (params->done == nullptr) {
ret = OckRpcCallSyncSgl(params->client, &serviceReq, response);
for (uint32_t i = 0; i < serviceReq.iovCount; i++) {
OckRpcMemFree(params->client, serviceReq.iov[i].lAddress);
}
if (ret != OCK_RPC_OK) {
return OCK_RPC_ERR;
}
} else {
ret = OckRpcCallAsyncSgl(params->client, &serviceReq, response, params->done);
if (ret != OCK_RPC_OK) {
return OCK_RPC_ERR;
}
}
return OCK_RPC_OK;
}
int OckRpcMemoryAllocatorCreate(
OckRpcMemoryAllocatorType t, OckRpcMemoryAllocatorOptions *options, OckRpcMemoryAllocator *allocator)
{
Net_MemoryAllocatorType type = Net_MemoryAllocatorType();
if (t == MEM_DYNAMIC_SIZE) {
type = C_DYNAMIC_SIZE;
} else if (t == MEM_DYNAMIC_SIZE_WITH_CACHE) {
type = C_DYNAMIC_SIZE_WITH_CACHE;
}
if (options == nullptr) {
OCK_RPC_LOG_ERROR("Invalid param, option is null.");
return OCK_RPC_ERR_INVALID_PARAM;
}
Net_MemoryAllocatorOptions memOptions = Net_MemoryAllocatorOptions();
memOptions.address = options->address;
memOptions.alignedAddress = options->alignedAddress;
memOptions.size = options->size;
memOptions.minBlockSize = options->minBlockSize;
memOptions.bucketCount = options->bucketCount;
memOptions.cacheBlockCountPerTier = options->cacheBlockCountPerTier;
if (options->cacheTierPolicy == MEM_TIER_TIMES) {
memOptions.cacheTierPolicy = C_TIER_TIMES;
} else if (options->cacheTierPolicy == MEM_TIER_POWER) {
memOptions.cacheTierPolicy = C_TIER_POWER;
}
memOptions.cacheTierCount = options->cacheTierCount;
return Net_MemoryAllocatorCreate(type, &memOptions, allocator);
}
int OckRpcMemoryAllocatorDestroy(OckRpcMemoryAllocator allocator)
{
return Net_MemoryAllocatorDestroy(allocator);
}
int OckRpcMemoryAllocatorSetMrKey(OckRpcMemoryAllocator allocator, uint32_t mrKey)
{
return Net_MemoryAllocatorSetMrKey(allocator, mrKey);
}
int OckRpcMemoryAllocatorMemOffset(OckRpcMemoryAllocator allocator, uintptr_t address, uintptr_t *offset)
{
return Net_MemoryAllocatorMemOffset(allocator, address, offset);
}
int OckRpcMemoryAllocatorFreeSize(OckRpcMemoryAllocator allocator, uintptr_t *size)
{
return Net_MemoryAllocatorFreeSize(allocator, size);
}
int OckRpcMemoryAllocatorAllocate(OckRpcMemoryAllocator allocator, uint64_t size, uintptr_t *address, uint32_t *key)
{
return Net_MemoryAllocatorAllocate(allocator, size, address, key);
}
int OckRpcMemoryAllocatorFree(OckRpcMemoryAllocator allocator, uintptr_t address)
{
return Net_MemoryAllocatorFree(allocator, address);
}
void OckRpcDisableSecureHmac(void)
{
return;
}
OckRpcStatus OckRpcServerReplyRndv(
OckRpcServerRndvContext ctx, uint16_t msgId, OckRpcMessage *reply, OckRpcCallDone *done)
{
if (reply == nullptr) {
OCK_RPC_LOG_ERROR("Invalid param, reply is nullptr.");
return OCK_RPC_ERR_INVALID_PARAM;
}
if (reply->len > UINT32_MAX) {
OCK_RPC_LOG_ERROR("Invlid param, rndv reply len should be less than UINT32_MAX.");
return OCK_RPC_ERR_INVALID_PARAM;
}
Service_OpInfo rspOpInfo = Service_OpInfo();
AsyncCbInfo *cbInfo = nullptr;
cbInfo = (AsyncCbInfo *)std::malloc(sizeof(AsyncCbInfo));
if (cbInfo == nullptr) {
OCK_RPC_LOG_ERROR("Malloc call back info size " << sizeof(AsyncCbInfo) << " failed");
return OCK_RPC_ERR;
}
if (done != nullptr) {
cbInfo->cb = done->cb;
cbInfo->arg = done->arg;
} else {
cbInfo->cb = nullptr;
cbInfo->arg = nullptr;
}
Channel_Callback rspCb = {.cb = ResponseCallBack, .arg = static_cast<void *>(cbInfo)};
Service_Message rsp;
rsp.data = reply->data;
rsp.size = reply->len;
int32_t ret = Service_RndvReply(ctx, &rspOpInfo, &rsp, &rspCb);
if (ret != 0) {
OCK_RPC_LOG_ERROR("Reply failed, ret(" << ret << ").");
free(cbInfo);
return OCK_RPC_ERR;
}
return OCK_RPC_OK;
}
OckRpcStatus OckRpcClientCallRndv(
OckRpcClient client, uint16_t msgId, OckRpcMessageInfo *request, OckRpcMessage *response, OckRpcCallDone *done)
{
if (request == nullptr) {
OCK_RPC_LOG_ERROR("Invalid param, request is null.");
return OCK_RPC_ERR_INVALID_PARAM;
}
if (response == nullptr) {
OCK_RPC_LOG_ERROR("Invalid param, response is null.");
return OCK_RPC_ERR_INVALID_PARAM;
}
int32_t ret = 0;
Service_OpInfo reqOpInfo = Service_OpInfo();
reqOpInfo.opCode = msgId;
reqOpInfo.timeout = g_timeoutTime;
Service_Request req = Service_Request();
req.lAddress = request->lAddress;
req.lKey = request->lKey;
req.size = request->size;
if (done == nullptr) {
Service_OpInfo rspOpInfo = Service_OpInfo();
Service_Message rsp = {.data = response->data, .size = static_cast<uint32_t>(response->len)};
ret = Channel_SyncRndvCall(client, &reqOpInfo, &req, &rspOpInfo, &rsp);
if (ret != OCK_RPC_OK) {
return OCK_RPC_ERR;
}
response->data = rsp.data;
response->len = rsp.size;
} else {
AsyncCbInfo *cbInfo = nullptr;
cbInfo = (AsyncCbInfo *)std::malloc(sizeof(AsyncCbInfo));
if (cbInfo == nullptr) {
OCK_RPC_LOG_ERROR("Malloc call back info size " << sizeof(AsyncCbInfo) << " failed");
return OCK_RPC_ERR;
}
cbInfo->cb = done->cb;
cbInfo->arg = done->arg;
cbInfo->reqAddr = nullptr;
cbInfo->reqCnt = 0;
cbInfo->rsp = response;
Channel_Callback cb = {.cb = OckRpcCallbackFunc, .arg = static_cast<void *>(cbInfo)};
ret = Channel_AsyncRndvCall(client, &reqOpInfo, &req, &cb);
if (ret != OCK_RPC_OK) {
free(cbInfo);
return OCK_RPC_ERR;
}
}
return OCK_RPC_OK;
}
static int OckRpcRndvIovCheckParams(OckRpcMessageInfoIov *request, OckRpcMessage *response)
{
if (request == nullptr) {
OCK_RPC_LOG_ERROR("Invalid param, request is null.");
return OCK_RPC_ERR;
}
if (response == nullptr) {
OCK_RPC_LOG_ERROR("Invalid param, response is null.");
return OCK_RPC_ERR;
}
if (request->count > MAX_MESSAGE_SGL_COUNT || request->count <= 0) {
OCK_RPC_LOG_ERROR("Invalid param, params messages len should be [1, 4]");
return OCK_RPC_ERR;
}
if (request->reqs == nullptr) {
OCK_RPC_LOG_ERROR("Invalid param, reqs is null.");
return OCK_RPC_ERR;
}
return OCK_RPC_OK;
}
OckRpcStatus OckRpcClientCallRndvIov(
OckRpcClient client, uint16_t msgId, OckRpcMessageInfoIov *request, OckRpcMessage *response, OckRpcCallDone *done)
{
if (OckRpcRndvIovCheckParams(request, response) != OCK_RPC_OK) {
return OCK_RPC_ERR_INVALID_PARAM;
}
Service_OpInfo reqOpInfo = Service_OpInfo();
reqOpInfo.opCode = msgId;
Service_SglRequest req;
req.iovCount = request->count;
Service_Request msg[req.iovCount] = {Service_Request()};
for (int i = 0; i < req.iovCount; i++) {
msg[i].lAddress = request->reqs[i].lAddress;
msg[i].lKey = request->reqs[i].lKey;
msg[i].size = request->reqs[i].size;
}
req.iov = msg;
if (done == nullptr) {
Service_OpInfo rspOpInfo = Service_OpInfo();
Service_Message rsp = {.data = response->data, .size = static_cast<uint32_t>(response->len)};
int ret = Channel_SyncRndvSglCall(client, &reqOpInfo, &req, &rspOpInfo, &rsp);
if (ret != OCK_RPC_OK) {
return OCK_RPC_ERR;
}
response->data = rsp.data;
response->len = rsp.size;
} else {
AsyncCbInfo *cbInfo = nullptr;
cbInfo = (AsyncCbInfo *)std::malloc(sizeof(AsyncCbInfo));
if (cbInfo == nullptr) {
OCK_RPC_LOG_ERROR("Malloc call back info size " << sizeof(AsyncCbInfo) << " failed");
return OCK_RPC_ERR;
}
cbInfo->cb = done->cb;
cbInfo->arg = done->arg;
cbInfo->reqAddr = nullptr;
cbInfo->reqCnt = 0;
cbInfo->rsp = response;
Channel_Callback cb = {.cb = OckRpcCallbackFunc, .arg = static_cast<void *>(cbInfo)};
int ret = Channel_AsyncRndvSglCall(client, &reqOpInfo, &req, &cb);
if (ret != OCK_RPC_OK) {
free(cbInfo);
return OCK_RPC_ERR;
}
}
return OCK_RPC_OK;
}
void OckRpcClientSetTimeout(OckRpcClient client, int64_t timeout)
{
int32_t timeoutSeconds = 0;
if (timeout < 0) {
timeoutSeconds = timeout;
} else {
timeoutSeconds = static_cast<int32_t>(timeout / MILLOSECOND_PER_SECOND);
}
g_timeoutTime = timeoutSeconds;
Channel_SetOneSideTimeout(client, g_timeoutTime);
Channel_SetTwoSideTimeout(client, g_timeoutTime);
OCK_RPC_LOG_INFO("Set timeout " << g_timeoutTime << " s");
}
int OckRpcGetClient(OckRpcServerContext ctx, OckRpcClient *client)
{
return Service_GetChannel(ctx, client);
}
int OckRpcGetRndvClient(OckRpcServerRndvContext ctx, OckRpcClient *client)
{
return Service_GetRndvChannel(ctx, client);
}
int OckRpcServerCleanupRndvCtx(OckRpcServerRndvContext ctx)
{
return Service_RndvFreeContext(ctx);
}
int OckRpcRegisterMemoryRegion(OckRpcServer server, uint64_t size, OckRpcMemoryRegion *mr)
{
return Service_RegisterMemoryRegion(server, size, mr);
}
int OckRpcRegisterAssignMemoryRegion(OckRpcServer server, uintptr_t address, uint64_t size, OckRpcMemoryRegion *mr)
{
return Service_RegisterAssignMemoryRegion(server, address, size, mr);
}
int OckRpcGetMemoryRegionInfo(OckRpcMemoryRegion mr, OckRpcMemoryRegionInfo *info)
{
if (info == nullptr) {
OCK_RPC_LOG_ERROR("Invalid param, info is null.");
return OCK_RPC_ERR_INVALID_PARAM;
}
Service_MemoryRegionInfo serviceInfo = Service_MemoryRegionInfo();
int ret = Service_GetMemoryRegionInfo(mr, &serviceInfo);
if (ret != OCK_RPC_OK) {
OCK_RPC_LOG_ERROR("Hcom service get memory region failed, ret:" << ret);
return OCK_RPC_ERR;
}
info->lAddress = serviceInfo.lAddress;
info->lKey = serviceInfo.lKey;
info->size = serviceInfo.size;
return OCK_RPC_OK;
}
void OckRpcDestroyMemoryRegion(OckRpcServer server, OckRpcMemoryRegion mr)
{
Service_DestroyMemoryRegion(server, mr);
}
int OckRpcRead(OckRpcClient client, OckRpcRequest *req, OckRpcCallDone *cb)
{
if (req == nullptr) {
OCK_RPC_LOG_ERROR("Invalid param, req is null.");
return OCK_RPC_ERR_INVALID_PARAM;
}
Service_Request reqMsg = Service_Request();
reqMsg.lAddress = req->lAddress;
reqMsg.rAddress = req->rAddress;
reqMsg.lKey = req->lKey;
reqMsg.rKey = req->rKey;
reqMsg.size = req->size;
if (cb == nullptr) {
return Channel_Read(client, &reqMsg, nullptr);
}
AsyncCbInfo *cbInfo = nullptr;
cbInfo = reinterpret_cast<AsyncCbInfo *>(malloc(sizeof(AsyncCbInfo)));
if (cbInfo == nullptr) {
OCK_RPC_LOG_ERROR("Read malloc call back info size " << sizeof(AsyncCbInfo) << " failed");
return OCK_RPC_ERR;
}
cbInfo->cb = cb->cb;
cbInfo->arg = cb->arg;
Channel_Callback callBack = {.cb = OckRpcCallbackFunc, .arg = static_cast<void *>(cbInfo)};
int ret = 0;
ret = Channel_Read(client, &reqMsg, &callBack);
if (ret != OCK_RPC_OK) {
free(cbInfo);
return ret;
}
return OCK_RPC_OK;
}
int OckRpcReadSgl(OckRpcClient client, OckRpcSglRequest *req, OckRpcCallDone *cb)
{
if (cb == nullptr) {
return Channel_ReadSgl(client, reinterpret_cast<Service_SglRequest *>(req), nullptr);
}
AsyncCbInfo *cbInfo = nullptr;
cbInfo = reinterpret_cast<AsyncCbInfo *>(malloc(sizeof(AsyncCbInfo)));
if (cbInfo == nullptr) {
OCK_RPC_LOG_ERROR("ReadSgl malloc call back info size " << sizeof(AsyncCbInfo) << " failed");
return OCK_RPC_ERR;
}
cbInfo->cb = cb->cb;
cbInfo->arg = cb->arg;
Channel_Callback callBack = {.cb = OckRpcCallbackFunc, .arg = static_cast<void *>(cbInfo)};
int ret = 0;
ret = Channel_ReadSgl(client, reinterpret_cast<Service_SglRequest *>(req), &callBack);
if (ret != OCK_RPC_OK) {
free(cbInfo);
return ret;
}
return OCK_RPC_OK;
}
int OckRpcWrite(OckRpcClient client, OckRpcRequest *req, OckRpcCallDone *cb)
{
if (req == nullptr) {
OCK_RPC_LOG_ERROR("Invalid param, req is null.");
return OCK_RPC_ERR_INVALID_PARAM;
}
Service_Request reqMsg = Service_Request();
reqMsg.lAddress = req->lAddress;
reqMsg.rAddress = req->rAddress;
reqMsg.lKey = req->lKey;
reqMsg.rKey = req->rKey;
reqMsg.size = req->size;
if (cb == nullptr) {
return Channel_Write(client, &reqMsg, nullptr);
}
AsyncCbInfo *cbInfo = nullptr;
cbInfo = reinterpret_cast<AsyncCbInfo *>(malloc(sizeof(AsyncCbInfo)));
if (cbInfo == nullptr) {
OCK_RPC_LOG_ERROR("Write malloc call back info size " << sizeof(AsyncCbInfo) << " failed");
return OCK_RPC_ERR;
}
cbInfo->cb = cb->cb;
cbInfo->arg = cb->arg;
Channel_Callback callBack = {.cb = OckRpcCallbackFunc, .arg = static_cast<void *>(cbInfo)};
int ret = 0;
ret = Channel_Write(client, &reqMsg, &callBack);
if (ret != OCK_RPC_OK) {
free(cbInfo);
return ret;
}
return OCK_RPC_OK;
}
int OckRpcWriteSgl(OckRpcClient client, OckRpcSglRequest *req, OckRpcCallDone *cb)
{
if (cb == nullptr) {
return Channel_WriteSgl(client, reinterpret_cast<Service_SglRequest *>(req), nullptr);
}
AsyncCbInfo *cbInfo = nullptr;
cbInfo = reinterpret_cast<AsyncCbInfo *>(malloc(sizeof(AsyncCbInfo)));
if (cbInfo == nullptr) {
OCK_RPC_LOG_ERROR("WriteSgl malloc call back info size " << sizeof(AsyncCbInfo) << " failed");
return OCK_RPC_ERR;
}
cbInfo->cb = cb->cb;
cbInfo->arg = cb->arg;
Channel_Callback callBack = {.cb = OckRpcCallbackFunc, .arg = static_cast<void *>(cbInfo)};
int ret = 0;
ret = Channel_WriteSgl(client, reinterpret_cast<Service_SglRequest *>(req), &callBack);
if (ret != OCK_RPC_OK) {
free(cbInfo);
return ret;
}
return OCK_RPC_OK;
}