fix: make router socket non-blocking to prevent poll loop stalls
Validate and Test / validate-patches (push) Failing after 13s

This commit is contained in:
2026-06-24 04:45:15 -07:00
parent 31bd1d497c
commit f70a8701c9
46 changed files with 47584 additions and 1 deletions
+198
View File
@@ -0,0 +1,198 @@
/*
This file is part of the Arduino_RPClite library.
Copyright (C) Arduino s.r.l. and/or its affiliated companies
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/.
*/
#pragma once
#ifndef RPCLITE_UTILS_H
#define RPCLITE_UTILS_H
#include <tuple>
#include <utility>
namespace RpcUtils {
namespace detail {
#define TYPE_ERROR (-1)
#define WRONG_MSG (-2)
#define NO_MSG (-1)
#define CALL_MSG 0
#define RESP_MSG 1
#define NOTIFY_MSG 2
#define REQUEST_SIZE 4
#define RESPONSE_SIZE 4
#define NOTIFY_SIZE 3
///////////////////////////////////////
/// --- deserialization helpers --- ///
///////////////////////////////////////
inline bool isValidRpc(int type, size_t size) {
switch (type) {
case CALL_MSG:
return size == REQUEST_SIZE;
case RESP_MSG:
return size == RESPONSE_SIZE;
case NOTIFY_MSG:
return size == NOTIFY_SIZE;
default:
return false;
}
}
inline bool unpackObject(MsgPack::Unpacker& unpacker);
inline bool unpackTypedArray(MsgPack::Unpacker& unpacker, size_t& size, int& type) {
MsgPack::arr_size_t sz;
if (!unpacker.deserialize(sz)) return false;
size = sz.size();
type = WRONG_MSG;
for (size_t i = 0; i < sz.size(); i++) {
if (i==0 && unpacker.deserialize(type)) {
continue;
}
if (!unpackObject(unpacker)) return false;
}
return true;
}
inline bool unpackArray(MsgPack::Unpacker& unpacker, size_t& size) {
if (!unpacker.isArray()) {
return false; // Not an array
}
MsgPack::arr_size_t sz;
unpacker.deserialize(sz);
size = 0;
for (size_t i=0; i<sz.size(); i++){
if (unpackObject(unpacker)){
size++;
} else {
return false;
}
}
return true;
}
inline bool unpackMap(MsgPack::Unpacker& unpacker, size_t& size) {
if (!unpacker.isMap()) {
return false; // Not a map
}
MsgPack::map_size_t sz;
unpacker.deserialize(sz);
size = 0;
for (size_t i=0; i<sz.size(); i++){
if (unpackObject(unpacker) && unpackObject(unpacker)){ // must unpack key&value
size++;
} else {
return false;
}
}
return true;
}
inline bool unpackObject(MsgPack::Unpacker& unpacker){
if (unpacker.isNil()){
static MsgPack::object::nil_t nil;
return unpacker.deserialize(nil);
}
if (unpacker.isBool()){
static bool b;
return unpacker.deserialize(b);
}
if (unpacker.isUInt() || unpacker.isInt()){
static int integer;
return unpacker.deserialize(integer);
}
if (unpacker.isFloat32()){
static float num32;
return unpacker.deserialize(num32);
}
if (unpacker.isFloat64()){
static double num64;
return unpacker.deserialize(num64);
}
if (unpacker.isStr()){
static MsgPack::str_t string;
return unpacker.deserialize(string);
}
if (unpacker.isBin()){
static MsgPack::bin_t<uint8_t> bytes;
return unpacker.deserialize(bytes);
}
if (unpacker.isArray()){
static size_t arr_sz;
return unpackArray(unpacker, arr_sz);
}
if (unpacker.isMap()){
static size_t map_sz;
return unpackMap(unpacker, map_sz);
}
if (unpacker.isFixExt() || unpacker.isExt()){
static MsgPack::object::ext e;
return unpacker.deserialize(e);
}
if (unpacker.isTimestamp()){
static MsgPack::object::timespec t;
return unpacker.deserialize(t);
}
return false;
}
template<typename T>
int deserialize_single(MsgPack::Unpacker& unpacker, T& value) {
if (!unpacker.unpackable(value)) return TYPE_ERROR;
unpacker.deserialize(value);
return 0;
}
/////////////////////////////
/// --- tuple helpers --- ///
/////////////////////////////
template<std::size_t I = 0, typename... Ts>
typename std::enable_if<I == sizeof...(Ts), int>::type
deserialize_tuple(MsgPack::Unpacker&, std::tuple<Ts...>&) {
return 0;
}
template<std::size_t I = 0, typename... Ts>
typename std::enable_if<I < sizeof...(Ts), int>::type
deserialize_tuple(MsgPack::Unpacker& unpacker, std::tuple<Ts...>& out) {
const int res = deserialize_single(unpacker, std::get<I>(out));
if (res==TYPE_ERROR) return TYPE_ERROR-I;
return deserialize_tuple<I + 1>(unpacker, out);
}
// Helper to invoke a function with a tuple of arguments
template<typename F, typename Tuple, std::size_t... I>
auto invoke_with_tuple(F&& f, Tuple&& t, arx::stdx::index_sequence<I...>)
-> decltype(f(std::get<I>(std::forward<Tuple>(t))...)) {
return f(std::get<I>(std::forward<Tuple>(t))...);
}
} // namespace detail
} // namespace RpcUtils
#endif //RPCLITE_UTILS_H