* openUBMC 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.
*/
#include "common.h"
#include "luafilter/l_callbacks.h"
#include "transfer/spdm_dbus.h"
unordered_map<string, unique_ptr<LCallbacks::st_cb>> LCallbacks::cb_map;
void LCallbacks::register_to(lua_State* L, luawrap::stack_table& t)
{
luawrap::restore_stack_top _s(L);
auto cls = luawrap::lua_class<LCallbacks>(L);
cls.ctor<>();
cls.def("set_send_recv_cb", c_func_wrap(L, LCallbacks::set_send_recv_cb));
cls.def("set_send_recv_dbus", c_func_wrap(L, LCallbacks::set_send_recv_dbus));
t.set("callbacks", cls);
}
void LCallbacks::set_send_recv_cb(const string& device_name, optional<t_send_recv_cb> cb)
{
auto it = cb_map.find(device_name);
if (it == cb_map.end()) {
unique_ptr<st_cb> s_cb = make_unique<LCallbacks::st_cb>();
cb_map.emplace(device_name, move(s_cb));
it = cb_map.find(device_name);
if (it == cb_map.end()) {
return;
}
}
auto& s_cb = *it->second;
unique_lock<mutex> guard(s_cb.send_recv_mutex);
s_cb.mode = CallMode::LUA_CALLBACK;
s_cb.send_recv_cb = move(cb);
}
void LCallbacks::set_send_recv_dbus(const string& device_name, const string& object_path)
{
auto it = cb_map.find(device_name);
if (it == cb_map.end()) {
unique_ptr<st_cb> s_cb = make_unique<LCallbacks::st_cb>();
cb_map.emplace(device_name, move(s_cb));
it = cb_map.find(device_name);
if (it == cb_map.end()) {
return;
}
}
auto& s_cb = *it->second;
unique_lock<mutex> guard(s_cb.send_recv_mutex);
s_cb.mode = CallMode::DBUS_SYNC;
s_cb.object_path = object_path;
}
static int32_t lua_callback_send_recv(LCallbacks::st_cb& s_sb, const string& device_name, const uint8_t* request,
size_t request_size, uint8_t* response, size_t* response_size)
{
if (!s_sb.send_recv_cb) {
debug_log(DLOG_ERROR, "lua callback is null");
return RET_ERR;
}
string_view req_data(reinterpret_cast<const char*>(request), request_size);
int32_t result;
optional<string_view> rsp_data;
uint32_t timeout = 30000;
tie(result, rsp_data) = (*s_sb.send_recv_cb)(device_name, request_size, req_data, timeout);
if (result != RET_OK) {
debug_log(DLOG_ERROR, "lua callback send message failed, result: %d", result);
return RET_ERR;
}
result = memcpy_s(response, *response_size, rsp_data->data(), rsp_data->size());
if (result != RET_OK) {
debug_log(DLOG_ERROR, "memcpy_s failed, ret = %d", result);
*response_size = 0;
} else {
*response_size = rsp_data->size();
}
return result;
}
int32_t LCallbacks::send_recv(const string& device_name, const uint8_t* request, size_t request_size, uint8_t* response,
size_t* response_size)
{
auto it = cb_map.find(device_name);
if (it == cb_map.end()) {
debug_log(DLOG_ERROR, "can not found send/recv callback for device %s", device_name.c_str());
return RET_ERR;
}
auto& s_cb = *it->second;
unique_lock<mutex> guard(s_cb.send_recv_mutex);
switch (s_cb.mode) {
case CallMode::DBUS_SYNC:
return dbus_sync_send_recv(s_cb.object_path, request, request_size, response, response_size);
case CallMode::LUA_CALLBACK:
return lua_callback_send_recv(s_cb, device_name, request, request_size, response, response_size);
default:
debug_log(DLOG_ERROR, "unknown call mode");
return RET_ERR;
}
}