diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e11b72138..dc79fd19b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -650,6 +650,7 @@ list( util/rsjson.h util/rskbdinput.cc util/rskbdinput.h + util/rsmacrosugar.hpp util/rsmemcache.h util/rsmemory.h util/rsnet.h diff --git a/src/libretroshare.pro b/src/libretroshare.pro index 4549e767f..a70c06316 100644 --- a/src/libretroshare.pro +++ b/src/libretroshare.pro @@ -513,7 +513,8 @@ HEADERS += util/folderiterator.h \ util/cxx14retrocompat.h \ util/cxx17retrocompat.h \ util/cxx23retrocompat.h \ - util/rsurl.h + util/rsurl.h \ + util/rsmacrosugar.hpp SOURCES += ft/ftchunkmap.cc \ ft/ftcontroller.cc \ diff --git a/src/services/broadcastdiscoveryservice.cc b/src/services/broadcastdiscoveryservice.cc index 60869acb0..51dae608b 100644 --- a/src/services/broadcastdiscoveryservice.cc +++ b/src/services/broadcastdiscoveryservice.cc @@ -37,7 +37,6 @@ # include "rs_android/retroshareserviceandroid.hpp" #endif // def __ANDROID__ - /*extern*/ RsBroadcastDiscovery* rsBroadcastDiscovery = nullptr; struct BroadcastDiscoveryPack : RsSerializable @@ -75,18 +74,11 @@ struct BroadcastDiscoveryPack : RsSerializable */ static std::unique_ptr fromSerializedString( const std::string& st, - rs_view_ptr ec ) + rs_view_ptr ec = nullptr) { if(st.empty()) { - if(!ec) - { - RS_FATAL("Attempteted from empty string ", std::errc::no_message); - print_stacktrace(); - exit(static_cast(std::errc::no_message)); - } - - *ec = std::errc::no_message; + rs_error_bubble_or_exit(std::errc::no_message_available, ec); return nullptr; } @@ -98,15 +90,7 @@ struct BroadcastDiscoveryPack : RsSerializable bdp->serial_process(RsGenericSerializer::DESERIALIZE, ctx); if(ctx.mOk) return bdp; - if(!ec) - { - RS_FATAL( "Attempteted from invalid string ", - std::errc::invalid_argument ); - print_stacktrace(); - exit(static_cast(std::errc::invalid_argument)); - } - - *ec = std::errc::invalid_argument; + rs_error_bubble_or_exit(std::errc::invalid_argument, ec); return nullptr; } @@ -125,7 +109,6 @@ struct BroadcastDiscoveryPack : RsSerializable ~BroadcastDiscoveryPack() override; }; - BroadcastDiscoveryService::BroadcastDiscoveryService( RsPeers& pRsPeers ) : mDiscoveredDataMutex("BroadcastDiscoveryService discovered data mutex"), @@ -203,9 +186,8 @@ void BroadcastDiscoveryService::threadTick() currentMap[dEndpoint.ip_port()] = dEndpoint.user_data(); auto findIt = mDiscoveredData.find(dEndpoint.ip_port()); - if( !dEndpoint.user_data().empty() && ( - findIt == mDiscoveredData.end() || - findIt->second != dEndpoint.user_data() ) ) + if( findIt == mDiscoveredData.end() || + findIt->second != dEndpoint.user_data() ) updateMap[dEndpoint.ip_port()] = dEndpoint.user_data(); } mDiscoveredData = currentMap; @@ -258,9 +240,11 @@ BroadcastDiscoveryService::createResult( const UDC::IpPort& ipp, const std::string& uData, rs_view_ptr ec ) { - /* if ec is nullptr the error is treathed downstream otherwise upstream in - * any case should not be treated here */ + /* On error we just return nullptr without handling it here because, it will + * either bubble up via ec or handled downstream if ec is nullptr. + * In any case it should not be treated here. */ auto bdp = BroadcastDiscoveryPack::fromSerializedString(uData, ec); + if(!bdp) return nullptr; auto rbdr = std::make_unique(); rbdr->mPgpFingerprint = bdp->mPgpFingerprint; diff --git a/src/util/rsdebug.h b/src/util/rsdebug.h index 132ca8a2f..c095db085 100644 --- a/src/util/rsdebug.h +++ b/src/util/rsdebug.h @@ -2,8 +2,8 @@ * RetroShare debugging utilities * * * * Copyright (C) 2004-2008 Robert Fernie * - * Copyright (C) 2019-2021 Gioacchino Mazzurco * - * Copyright (C) 2020-2021 Asociación Civil Altermundi * + * Copyright (C) 2019-2022 Gioacchino Mazzurco * + * Copyright (C) 2020-2022 Asociación Civil Altermundi * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -35,6 +35,7 @@ #include "util/rsjson.h" +#include "util/rsmacrosugar.hpp" #ifdef __ANDROID__ @@ -71,7 +72,6 @@ std::string rsErrorNotInCategory(int errNum, const std::string& categoryName); */ std::error_condition rs_errno_to_condition(int errno_code); - template struct t_RsLogger : std::ostringstream { @@ -254,9 +254,31 @@ struct hexDump { } }; - - - +/** + * @def rs_error_bubble_or_exit + * Bubbling up an error condition to be handled upstream if possible or dealing + * it fatally here, is a very common pattern, @see rs_malloc as an example, so + * instead of rewriting the same snippet over and over, increasing the + * possibility of introducing bugs, use this macro to properly deal with that + * situation. + * @param p_error_condition expect something convertible to an + * std::error_condition to be dealt with + * @param p_bubble_storage pointer to a location to store the + * std::error_condition to be bubbled up upstream, if it is nullptr the error + * will be handled with a fatal report end then exiting here + * @param ... optional additional information you want to be printed toghether + * with the error report when is fatal (aka not bubbled up) */ +#define rs_error_bubble_or_exit(p_error_condition, p_bubble_storage, ... ) \ + if(p_bubble_storage) \ + { \ + *p_bubble_storage = p_error_condition; \ + } \ + else \ + { \ + RS_FATAL(p_error_condition, " " RS_OPT_VA_ARGS(__VA_ARGS__)); \ + print_stacktrace(); \ + exit(std::error_condition(p_error_condition).value()); \ + } //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// @@ -266,15 +288,6 @@ struct hexDump { #include "util/rsdeprecate.h" -/** - * Concatenate preprocessor tokens A and B without expanding macro definitions - * (however, if invoked from a macro, macro arguments are expanded). - */ -#define RS_CONCAT_MACRO_NX(A, B) A ## B - -/// Concatenate preprocessor tokens A and B after macro-expanding them. -#define RS_CONCAT_MACRO(A, B) RS_CONCAT_MACRO_NX(A, B) - /** * Set local context debug level. * Avoid copy pasting boilerplate code around @see RsDbg for usage details diff --git a/src/util/rsmacrosugar.hpp b/src/util/rsmacrosugar.hpp new file mode 100644 index 000000000..d2cbb8c22 --- /dev/null +++ b/src/util/rsmacrosugar.hpp @@ -0,0 +1,43 @@ +/******************************************************************************* + * * + * libretroshare: retroshare core library * + * * + * Copyright (C) 2022 Gioacchino Mazzurco * + * Copyright (C) 2022 Asociación Civil Altermundi * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public License * + * along with this program. If not, see . * + * * + *******************************************************************************/ +#pragma once + + +/** Comfortable optional variadic macro arguments + * @see https://www.appsloveworld.com/cplus/100/16/variadic-macros-with-zero-arguments + * C/C++ variadic macros gives error on expansion if no argument is passed, the + * result is that at least one argument must be passed or compilation fails. + * Wrapping __VA_ARGS__ in RS_OPT_VA_ARGS at expansion place omitting the comma + * before solves this issue rendering the variadic arguments effectively + * optionals. + */ +#define RS_OPT_VA_ARGS(...) , ##__VA_ARGS__ + +/** + * Concatenate preprocessor tokens A and B without expanding macro definitions + * (however, if invoked from a macro, macro arguments are expanded). + */ +#define RS_CONCAT_MACRO_NX(A, B) A ## B + +/// Concatenate preprocessor tokens A and B after macro-expanding them. +#define RS_CONCAT_MACRO(A, B) RS_CONCAT_MACRO_NX(A, B) + diff --git a/src/util/rsmemory.h b/src/util/rsmemory.h index 7f7c961dd..117b5ab14 100644 --- a/src/util/rsmemory.h +++ b/src/util/rsmemory.h @@ -4,8 +4,8 @@ * libretroshare: retroshare core library * * * * Copyright (C) 2012 Cyril Soler * - * Copyright (C) 2019-2021 Gioacchino Mazzurco * - * Copyright (C) 2021 Asociación Civil Altermundi * + * Copyright (C) 2019-2022 Gioacchino Mazzurco * + * Copyright (C) 2021-2022 Asociación Civil Altermundi * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -131,43 +131,27 @@ template rs_owner_ptr rs_malloc( { if(size == 0) { - if(!ec) - { - RS_ERR("A chunk of size 0 was requested"); - print_stacktrace(); - exit(static_cast(std::errc::invalid_argument)); - } - - *ec = std::errc::invalid_argument; + rs_error_bubble_or_exit( + std::errc::invalid_argument, ec, + "A chunk of size 0 was requested" ); return nullptr; } if(size > SAFE_MEMALLOC_THRESHOLD) { - if(!ec) - { - RS_ERR( "A chunk of size larger than ", SAFE_MEMALLOC_THRESHOLD, - " was requested" ); - print_stacktrace(); - exit(static_cast(std::errc::argument_out_of_domain)); - } - - *ec = std::errc::argument_out_of_domain; + rs_error_bubble_or_exit( + std::errc::argument_out_of_domain, ec, + "A chunk of size larger than ", SAFE_MEMALLOC_THRESHOLD, + " was requested" ); return nullptr; } void* mem = malloc(size); if(!mem) { - if(!ec) - { - RS_ERR( "Allocation failed for a chunk of ", size, - " bytes with: ", errno); - print_stacktrace(); - exit(errno); - } - - *ec = rs_errno_to_condition(errno); + rs_error_bubble_or_exit( + rs_errno_to_condition(errno), ec, + "malloc failed for a chunk of ", size, " bytes" ); return nullptr; }