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,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
|
||||
Reference in New Issue
Block a user