fix: make router socket non-blocking to prevent poll loop stalls
Validate and Test / validate-patches (push) Failing after 13s
Validate and Test / validate-patches (push) Failing after 13s
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
This file is part of the Arduino_RPClite library.
|
||||
|
||||
Copyright (c) 2025 Arduino SA
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef RPCLITE_WRAPPER_H
|
||||
#define RPCLITE_WRAPPER_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "error.h"
|
||||
#include "rpclite_utils.h"
|
||||
|
||||
using namespace RpcUtils::detail;
|
||||
|
||||
#ifdef HANDLE_RPC_ERRORS
|
||||
#include <stdexcept>
|
||||
#endif
|
||||
|
||||
class IFunctionWrapper {
|
||||
public:
|
||||
virtual ~IFunctionWrapper() = default;
|
||||
virtual bool operator()(MsgPack::Unpacker& unpacker, MsgPack::Packer& packer) = 0;
|
||||
};
|
||||
|
||||
template<typename F>
|
||||
class RpcFunctionWrapper;
|
||||
|
||||
template<typename R, typename... Args>
|
||||
class RpcFunctionWrapper<std::function<R(Args...)>>: public IFunctionWrapper {
|
||||
public:
|
||||
explicit RpcFunctionWrapper(std::function<R(Args...)> func) : _func(func) {}
|
||||
|
||||
R operator()(Args... args) {
|
||||
return _func(args...);
|
||||
}
|
||||
|
||||
bool operator()(MsgPack::Unpacker& unpacker, MsgPack::Packer& packer) override {
|
||||
|
||||
MsgPack::object::nil_t nil;
|
||||
|
||||
#ifdef HANDLE_RPC_ERRORS
|
||||
try {
|
||||
#endif
|
||||
|
||||
// First check the parameters size
|
||||
if (!unpacker.isArray()){
|
||||
RpcError error(MALFORMED_CALL_ERR, "Unserializable parameters array");
|
||||
packer.serialize(error, nil);
|
||||
return false;
|
||||
}
|
||||
|
||||
MsgPack::arr_size_t param_size;
|
||||
|
||||
unpacker.deserialize(param_size);
|
||||
if (param_size.size() < sizeof...(Args)){
|
||||
RpcError error(MALFORMED_CALL_ERR, "Missing call parameters (WARNING: Default param resolution is not implemented)");
|
||||
packer.serialize(error, nil);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (param_size.size() > sizeof...(Args)){
|
||||
RpcError error(MALFORMED_CALL_ERR, "Too many parameters");
|
||||
packer.serialize(error, nil);
|
||||
return false;
|
||||
}
|
||||
|
||||
const int res = handle_call(unpacker, packer);
|
||||
if (res<0) {
|
||||
MsgPack::str_t err_msg = "Wrong type parameter in position: ";
|
||||
#ifdef ARDUINO
|
||||
err_msg += String(TYPE_ERROR-res);
|
||||
#else
|
||||
err_msg += std::to_string(TYPE_ERROR-res);
|
||||
#endif
|
||||
RpcError error(MALFORMED_CALL_ERR, err_msg);
|
||||
packer.serialize(error, nil);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
#ifdef HANDLE_RPC_ERRORS
|
||||
} catch (const std::exception& e) {
|
||||
// Should be specialized according to the exception type
|
||||
RpcError error(GENERIC_ERR, "RPC error");
|
||||
packer.serialize(error, nil);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
std::function<R(Args...)> _func;
|
||||
|
||||
template<typename Dummy = R>
|
||||
typename std::enable_if<std::is_void<Dummy>::value, int>::type
|
||||
handle_call(MsgPack::Unpacker& unpacker, MsgPack::Packer& packer) {
|
||||
//unpacker not ready if deserialization fails at this point
|
||||
std::tuple<Args...> args;
|
||||
const int res = deserialize_tuple(unpacker, args);
|
||||
if (res<0) return res;
|
||||
MsgPack::object::nil_t nil;
|
||||
invoke_with_tuple(_func, args, arx::stdx::make_index_sequence<sizeof...(Args)>{});
|
||||
packer.serialize(nil, nil);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename Dummy = R>
|
||||
typename std::enable_if<!std::is_void<Dummy>::value, int>::type
|
||||
handle_call(MsgPack::Unpacker& unpacker, MsgPack::Packer& packer) {
|
||||
//unpacker not ready if deserialization fails at this point
|
||||
std::tuple<Args...> args;
|
||||
const int res = deserialize_tuple(unpacker, args);
|
||||
if (res<0) return res;
|
||||
MsgPack::object::nil_t nil;
|
||||
R out = invoke_with_tuple(_func, args, arx::stdx::make_index_sequence<sizeof...(Args)>{});
|
||||
packer.serialize(nil, out);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename F, typename Signature = typename arx::function_traits<typename std::decay<F>::type>::function_type>
|
||||
auto wrap(F&& f) -> RpcFunctionWrapper<Signature>* {
|
||||
return new RpcFunctionWrapper<Signature>(std::forward<F>(f));
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user