229 lines
6.7 KiB
C
Executable File
229 lines
6.7 KiB
C
Executable File
/*
|
|
* Copyright (c) 2020 Huawei Device Co., Ltd.
|
|
* 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.
|
|
*/
|
|
#include "message_inner.h"
|
|
#include <ohos_errno.h>
|
|
#include <log.h>
|
|
#include "memory_adapter.h"
|
|
#include "queue_adapter.h"
|
|
#include "securec.h"
|
|
#include "task_manager.h"
|
|
|
|
#undef LOG_TAG
|
|
#undef LOG_DOMAIN
|
|
#define LOG_TAG "Samgr"
|
|
#define LOG_DOMAIN 0xD001800
|
|
|
|
#define DONT_WAIT 0
|
|
#define WAIT_FOREVER (-1)
|
|
static int32 SharedSend(MQueueId queueId, Exchange *exchange, int initRef);
|
|
static BOOL FreeReference(Exchange *exchange);
|
|
|
|
int32 SAMGR_SendRequest(const Identity *identity, const Request *request, Handler handler)
|
|
{
|
|
if (request == NULL || identity == NULL) {
|
|
return EC_INVALID;
|
|
}
|
|
|
|
Exchange exchange = {*identity, *request, {NULL, 0}, MSG_NON, handler, NULL};
|
|
exchange.id.queueId = NULL;
|
|
if (handler != NULL) {
|
|
exchange.id.queueId = SAMGR_GetCurrentQueueID();
|
|
exchange.type = MSG_CON;
|
|
}
|
|
|
|
return QUEUE_Put(identity->queueId, &exchange, 0, DONT_WAIT);
|
|
}
|
|
|
|
int32 SAMGR_SendResponse(const Request *request, const Response *response)
|
|
{
|
|
// we need send the default the con message or not?
|
|
if (request == NULL) {
|
|
return EC_INVALID;
|
|
}
|
|
|
|
Exchange *exchange = GET_OBJECT(request, Exchange, request);
|
|
if (exchange->type != MSG_CON) {
|
|
return EC_INVALID;
|
|
}
|
|
|
|
if (exchange->handler == NULL) {
|
|
return EC_SUCCESS;
|
|
}
|
|
|
|
exchange->type = MSG_ACK;
|
|
exchange->response.data = NULL;
|
|
exchange->response.len = 0;
|
|
if (response != NULL) {
|
|
exchange->response = *response;
|
|
}
|
|
|
|
// If there is no task queue, we will call the response processor in current task.
|
|
if (exchange->id.queueId == NULL) {
|
|
exchange->handler(&exchange->request, &exchange->response);
|
|
return EC_SUCCESS;
|
|
}
|
|
|
|
// Send back to the origin to process the task.
|
|
int32 ret = SharedSend(exchange->id.queueId, exchange, 1);
|
|
if (ret != EC_SUCCESS) {
|
|
exchange->handler(&exchange->request, &exchange->response);
|
|
(void)FreeReference(exchange);
|
|
}
|
|
return EC_SUCCESS;
|
|
}
|
|
|
|
int32 SAMGR_MsgRecv(MQueueId queueId, uint8 *interMsg, uint32 size)
|
|
{
|
|
if (queueId == NULL || interMsg == NULL || size == 0) {
|
|
return EC_INVALID;
|
|
}
|
|
|
|
if (memset_s(interMsg, size, 0x00, size) != EOK) {
|
|
return EC_FAILURE;
|
|
}
|
|
|
|
return QUEUE_Pop(queueId, interMsg, 0, WAIT_FOREVER);
|
|
}
|
|
|
|
int32 SAMGR_FreeMsg(Exchange *exchange)
|
|
{
|
|
if (!FreeReference(exchange)) {
|
|
return EC_SUCCESS;
|
|
}
|
|
|
|
if (exchange->request.len > 0) {
|
|
SAMGR_Free(exchange->request.data);
|
|
exchange->request.data = NULL;
|
|
}
|
|
|
|
if (exchange->response.len > 0) {
|
|
SAMGR_Free(exchange->response.data);
|
|
exchange->response.data = NULL;
|
|
}
|
|
return EC_SUCCESS;
|
|
}
|
|
|
|
uint32 *SAMGR_SendSharedRequest(const Identity *identity, const Request *request, uint32 *token, Handler handler)
|
|
{
|
|
if (identity == NULL || request == NULL) {
|
|
return NULL;
|
|
}
|
|
Exchange exchange = {*identity, *request, {NULL, 0}, MSG_NON, handler, token};
|
|
exchange.type = (handler == NULL) ? MSG_NON : MSG_CON;
|
|
exchange.id.queueId = NULL;
|
|
int32 err = SharedSend(identity->queueId, &exchange, 0);
|
|
if (err != EC_SUCCESS) {
|
|
HILOG_ERROR(HILOG_MODULE_SAMGR, "SharedSend failed(%d)!", err);
|
|
(void)FreeReference(&exchange);
|
|
}
|
|
return exchange.sharedRef;
|
|
}
|
|
|
|
int32 SAMGR_SendSharedDirectRequest(const Identity *id, const Request *req, const Response *resp, uint32 **ref,
|
|
Handler handler)
|
|
{
|
|
if (handler == NULL || ref == NULL) {
|
|
return EC_INVALID;
|
|
}
|
|
|
|
Exchange exchange = {0};
|
|
if (req != NULL) {
|
|
exchange.request = *req;
|
|
}
|
|
|
|
if (resp != NULL) {
|
|
exchange.response = *resp;
|
|
}
|
|
|
|
exchange.handler = handler;
|
|
exchange.sharedRef = *ref;
|
|
exchange.type = MSG_DIRECT;
|
|
exchange.id = *id;
|
|
exchange.id.queueId = NULL;
|
|
int32 err = SharedSend(id->queueId, &exchange, 0);
|
|
if (err != EC_SUCCESS) {
|
|
HILOG_ERROR(HILOG_MODULE_SAMGR, "SharedSend failed(%d)!", err);
|
|
(void)FreeReference(&exchange);
|
|
}
|
|
*ref = exchange.sharedRef;
|
|
return err;
|
|
}
|
|
|
|
int32 SAMGR_SendResponseByIdentity(const Identity *id, const Request *request, const Response *response)
|
|
{
|
|
// we need send the default the con message or not?
|
|
if (request == NULL || id == NULL) {
|
|
return EC_INVALID;
|
|
}
|
|
|
|
Exchange *exchange = GET_OBJECT(request, Exchange, request);
|
|
if (exchange->type == MSG_NON) {
|
|
return EC_INVALID;
|
|
}
|
|
exchange->id.queueId = id->queueId;
|
|
|
|
return SAMGR_SendResponse(request, response);
|
|
}
|
|
|
|
static int32 SharedSend(MQueueId queueId, Exchange *exchange, int initRef)
|
|
{
|
|
/* if the msg data and response is NULL, we just direct copy, no need shared the message. */
|
|
if ((exchange->request.data == NULL || exchange->request.len <= 0) &&
|
|
(exchange->response.data == NULL || exchange->response.len <= 0)) {
|
|
return QUEUE_Put(queueId, exchange, 0, DONT_WAIT);
|
|
}
|
|
|
|
/* 1.add reference */
|
|
MUTEX_GlobalLock();
|
|
if (exchange->sharedRef == NULL) {
|
|
exchange->sharedRef = (uint32*)SAMGR_Malloc(sizeof(uint32));
|
|
if (exchange->sharedRef == NULL) {
|
|
MUTEX_GlobalUnlock();
|
|
return EC_NOMEMORY;
|
|
}
|
|
*(exchange->sharedRef) = initRef;
|
|
}
|
|
(*(exchange->sharedRef))++;
|
|
MUTEX_GlobalUnlock();
|
|
|
|
return QUEUE_Put(queueId, exchange, 0, DONT_WAIT);
|
|
}
|
|
|
|
static BOOL FreeReference(Exchange *exchange)
|
|
{
|
|
if (exchange == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL needFree = TRUE;
|
|
/* 1. check the shared reference */
|
|
MUTEX_GlobalLock();
|
|
if (exchange->sharedRef != NULL) {
|
|
if (*(exchange->sharedRef) > 0) {
|
|
(*(exchange->sharedRef))--;
|
|
}
|
|
|
|
if (*(exchange->sharedRef) > 0) {
|
|
needFree = FALSE;
|
|
}
|
|
}
|
|
MUTEX_GlobalUnlock();
|
|
|
|
if (needFree) {
|
|
SAMGR_Free(exchange->sharedRef);
|
|
exchange->sharedRef = NULL;
|
|
}
|
|
return needFree;
|
|
} |