diff --git a/libretroshare/src/chat/distributedchat.cc b/libretroshare/src/chat/distributedchat.cc index 5bc640fd7..2726e8ec0 100644 --- a/libretroshare/src/chat/distributedchat.cc +++ b/libretroshare/src/chat/distributedchat.cc @@ -1292,15 +1292,15 @@ void DistributedChatService::handleRecvLobbyInvite_Deprecated(RsChatLobbyInviteI #ifdef DEBUG_CHAT_LOBBIES std::cerr << "Received deprecated invite to lobby from " << item->PeerId() << " to lobby " << std::hex << item->lobby_id << std::dec << ", named " << item->lobby_name << item->lobby_topic << std::endl; #endif - RsChatLobbyInviteItem* newItem = new RsChatLobbyInviteItem(); + RsChatLobbyInviteItem newItem ; - newItem->lobby_id = item->lobby_id ; - newItem->lobby_name = item->lobby_name ; - newItem->lobby_topic = item->lobby_topic ; - newItem->lobby_flags = item->lobby_flags ; - newItem->PeerId( item->PeerId() ); + newItem.lobby_id = item->lobby_id ; + newItem.lobby_name = item->lobby_name ; + newItem.lobby_topic = item->lobby_topic ; + newItem.lobby_flags = item->lobby_flags ; + newItem.PeerId( item->PeerId() ); - handleRecvLobbyInvite(newItem); + handleRecvLobbyInvite(&newItem); // The item is not deleted inside this function. } void DistributedChatService::handleRecvLobbyInvite(RsChatLobbyInviteItem *item) diff --git a/libretroshare/src/gxs/rsgxsnettunnel.cc b/libretroshare/src/gxs/rsgxsnettunnel.cc index 9d96454c5..5bd89900d 100644 --- a/libretroshare/src/gxs/rsgxsnettunnel.cc +++ b/libretroshare/src/gxs/rsgxsnettunnel.cc @@ -541,6 +541,7 @@ void RsGxsNetTunnelService::receiveTurtleData(const RsTurtleGenericTunnelItem *i if(!pid_item) // this handles the case of a KeepAlive packet. { delete decrypted_item ; + free(data); return ; } diff --git a/libretroshare/src/pqi/pqissludp.cc b/libretroshare/src/pqi/pqissludp.cc index 6ba24b6f6..f8fefc499 100644 --- a/libretroshare/src/pqi/pqissludp.cc +++ b/libretroshare/src/pqi/pqissludp.cc @@ -248,54 +248,34 @@ int pqissludp::Initiate_Connection() } else if (mConnectFlags & RS_CB_FLAG_MODE_UDP_RELAY) { - std::cerr << "Calling tou_connect_via_relay("; - std::cerr << sockaddr_storage_tostring(mConnectSrcAddr) << ","; - std::cerr << sockaddr_storage_tostring(mConnectProxyAddr) << ","; - std::cerr << sockaddr_storage_tostring(remote_addr) << ")" << std::endl; + std::cerr << __PRETTY_FUNCTION__ << " Calling tou_connect_via_relay(" + << sockaddr_storage_tostring(mConnectSrcAddr) << "," + << sockaddr_storage_tostring(mConnectProxyAddr) << "," + << sockaddr_storage_tostring(remote_addr) << ")" << std::endl; - + if(!sockaddr_storage_ipv6_to_ipv4(mConnectSrcAddr)) { - struct sockaddr_in srcaddr; - struct sockaddr_in proxyaddr; - struct sockaddr_in remoteaddr; - - if(!sockaddr_storage_ipv6_to_ipv4(mConnectSrcAddr)) - { - std::cerr << __PRETTY_FUNCTION__ << "Error: mConnectSrcAddr is " - << "not valid IPv4!" << std::endl; - sockaddr_storage_dump(mConnectSrcAddr); - print_stacktrace(); - return -EINVAL; - } - if(!sockaddr_storage_ipv6_to_ipv4(mConnectProxyAddr)) - { - std::cerr << __PRETTY_FUNCTION__ << "Error: mConnectProxyAddr " - << "is not valid IPv4!" << std::endl; - sockaddr_storage_dump(mConnectProxyAddr); - print_stacktrace(); - return -EINVAL; - - } - - struct sockaddr_in *rap = (struct sockaddr_in *) &remote_addr; - struct sockaddr_in *pap = (struct sockaddr_in *) &mConnectProxyAddr; - struct sockaddr_in *sap = (struct sockaddr_in *) &mConnectSrcAddr; - - srcaddr.sin_family = AF_INET; - proxyaddr.sin_family = AF_INET; - remoteaddr.sin_family = AF_INET; - - srcaddr.sin_addr = sap->sin_addr; - proxyaddr.sin_addr = pap->sin_addr; - remoteaddr.sin_addr = rap->sin_addr; - - srcaddr.sin_port = sap->sin_port; - proxyaddr.sin_port = pap->sin_port; - remoteaddr.sin_port = rap->sin_port; - - err = tou_connect_via_relay(sockfd, &srcaddr, &proxyaddr, &remoteaddr); - + std::cerr << __PRETTY_FUNCTION__ << " ERROR mConnectSrcAddr is " + << "not a valid IPv4!" << std::endl; + sockaddr_storage_dump(mConnectSrcAddr); + print_stacktrace(); + return -EINVAL; } + if(!sockaddr_storage_ipv6_to_ipv4(mConnectProxyAddr)) + { + std::cerr << __PRETTY_FUNCTION__ << " ERROR mConnectProxyAddr " + << "is not a valid IPv4!" << std::endl; + sockaddr_storage_dump(mConnectProxyAddr); + print_stacktrace(); + return -EINVAL; + + } + + err = tou_connect_via_relay( + sockfd, + reinterpret_cast(mConnectSrcAddr), + reinterpret_cast(mConnectProxyAddr), + reinterpret_cast(remote_addr) ); /*** It seems that the UDP Layer sees x 1.2 the traffic of the SSL layer. * We need to compensate somewhere... we drop the maximum traffic to 75% of limit diff --git a/libretroshare/src/tcponudp/bss_tou.c b/libretroshare/src/tcponudp/bss_tou.c index 7e9274c51..2f1c29d4f 100644 --- a/libretroshare/src/tcponudp/bss_tou.c +++ b/libretroshare/src/tcponudp/bss_tou.c @@ -99,48 +99,55 @@ static int BIO_get_init(BIO *a) { return a->init; } static int BIO_get_shutdown(BIO *a) { return a->shutdown; } static void BIO_set_init(BIO *a,int i) { a->init=i; } static void BIO_set_data(BIO *a,void *p) { a->ptr = p; } +long (*BIO_meth_get_ctrl(const BIO_METHOD* biom)) (BIO*, int, long, void*) +{ return biom->ctrl; } #endif -#else +static BIO_METHOD methods_tou_sockp = +{ + BIO_TYPE_TOU_SOCKET, + "tou_socket", + tou_socket_write, + tou_socket_read, + tou_socket_puts, + NULL, /* tou_gets, */ + tou_socket_ctrl, + tou_socket_new, + tou_socket_free, + NULL, +}; -typedef struct bio_method_st { - int type; - const char *name; - int (*bwrite) (BIO *, const char *, int); - int (*bread) (BIO *, char *, int); - int (*bputs) (BIO *, const char *); - int (*bgets) (BIO *, char *, int); - long (*ctrl) (BIO *, int, long, void *); - int (*create) (BIO *); - int (*destroy) (BIO *); - long (*callback_ctrl) (BIO *, int, bio_info_cb *); -} BIO_METHOD; - -#endif - -static BIO_METHOD methods_tou_sockp= - { - BIO_TYPE_TOU_SOCKET, - "tou_socket", - tou_socket_write, - tou_socket_read, - tou_socket_puts, - NULL, /* tou_gets, */ - tou_socket_ctrl, - tou_socket_new, - tou_socket_free, - NULL, - }; - -BIO_METHOD *BIO_s_tou_socket(void) - { +BIO_METHOD* BIO_s_tou_socket(void) +{ #ifdef DEBUG_TOU_BIO fprintf(stderr, "BIO_s_tou_socket(void)\n"); #endif return(&methods_tou_sockp); +} + +#else + +BIO_METHOD* BIO_s_tou_socket(void) +{ + static BIO_METHOD* methods_tou_sockp_ptr = NULL; + if(!methods_tou_sockp_ptr) + { + methods_tou_sockp_ptr = BIO_meth_new(BIO_TYPE_TOU_SOCKET, "tou_socket"); + + BIO_meth_set_write( methods_tou_sockp_ptr, tou_socket_write ); + BIO_meth_set_read( methods_tou_sockp_ptr, tou_socket_read ); + BIO_meth_set_puts( methods_tou_sockp_ptr, tou_socket_puts ); + BIO_meth_set_ctrl( methods_tou_sockp_ptr, tou_socket_ctrl ); + BIO_meth_set_create( methods_tou_sockp_ptr, tou_socket_new ); + BIO_meth_set_destroy( methods_tou_sockp_ptr, tou_socket_free ); } + return methods_tou_sockp_ptr; +} + +#endif + BIO *BIO_new_tou_socket(int fd, int close_flag) { BIO *ret; @@ -260,17 +267,16 @@ static long tou_socket_ctrl(BIO *b, int cmd, long num, void *ptr) break; case BIO_C_SET_FD: tou_socket_free(b); - ret = BIO_s_fd()->ctrl(b,cmd,num,ptr) ; - + ret = BIO_meth_get_ctrl((BIO_METHOD*)BIO_s_fd())(b,cmd,num,ptr); break; case BIO_C_GET_FD: - ret = BIO_s_fd()->ctrl(b,cmd,num,ptr) ; + ret = BIO_meth_get_ctrl((BIO_METHOD*)BIO_s_fd())(b,cmd,num,ptr); break; case BIO_CTRL_GET_CLOSE: - ret = BIO_s_fd()->ctrl(b,cmd,num,ptr) ; + ret = BIO_meth_get_ctrl((BIO_METHOD*)BIO_s_fd())(b,cmd,num,ptr); break; case BIO_CTRL_SET_CLOSE: - ret = BIO_s_fd()->ctrl(b,cmd,num,ptr) ; + ret = BIO_meth_get_ctrl((BIO_METHOD*)BIO_s_fd())(b,cmd,num,ptr); break; case BIO_CTRL_PENDING: ret = tou_maxread(BIO_get_fd(b,NULL)); diff --git a/libretroshare/src/tcponudp/tou.cc b/libretroshare/src/tcponudp/tou.cc index 0ff394c0a..96c8797d9 100644 --- a/libretroshare/src/tcponudp/tou.cc +++ b/libretroshare/src/tcponudp/tou.cc @@ -25,15 +25,15 @@ static const int kInitStreamTable = 5; #include #include -#include "util/rstime.h" +#include +#include +#include +#include "util/rstime.h" #include "udp/udpstack.h" #include "pqi/pqinetwork.h" #include "tcpstream.h" -#include -#include - -#include +#include "util/stacktrace.h" #define DEBUG_TOU_INTERFACE 1 #define EUSERS 87 @@ -54,7 +54,7 @@ static RsMutex touMutex("touMutex"); // Mutex is used to control addition / removals from tou_streams. // Lookup should be okay - as long as you stick to your allocated ID! -static std::vector tou_streams; +static std::vector tou_streams; static int tou_inited = 0; @@ -171,19 +171,30 @@ int tou_socket(uint32_t recvIdx, uint32_t type, int /*protocol*/) bool tou_stream_check(int sockfd) { - if (sockfd < 0) + if(sockfd < 0) { - std::cerr << "tou_stream_check() ERROR sockfd < 0"; - std::cerr << std::endl; + std::cerr << __PRETTY_FUNCTION__ << " ERROR sockfd: " << sockfd + << " < 0" << std::endl; + print_stacktrace(); return false; } - if (tou_streams[sockfd] == NULL) + if(sockfd >= tou_streams.size()) { - std::cerr << "tou_stream_check() ERROR tou_streams[sockfd] == NULL"; - std::cerr << std::endl; + std::cerr << __PRETTY_FUNCTION__ << " ERROR sockfd: " << sockfd + << " out of bound!" << std::endl; + print_stacktrace(); return false; } + + if(!tou_streams[sockfd]) + { + std::cerr << __PRETTY_FUNCTION__ << " ERROR tou_streams[sockfd] == NULL" + << std::endl; + print_stacktrace(); + return false; + } + return true; } @@ -370,62 +381,55 @@ int tou_listen(int /* sockfd */ , int /* backlog */ ) */ #define DEFAULT_RELAY_CONN_PERIOD 1 -int tou_connect_via_relay(int sockfd, - const struct sockaddr_in *own_addr, - const struct sockaddr_in *proxy_addr, - const struct sockaddr_in *dest_addr) +int tou_connect_via_relay( int sockfd, const sockaddr_in& own_addr, + const sockaddr_in& proxy_addr, + const sockaddr_in& dest_addr ) { - if (!tou_stream_check(sockfd)) - { - return -1; - } - TcpOnUdp *tous = tou_streams[sockfd]; + std::cerr << __PRETTY_FUNCTION__ << std::endl; + + if (!tou_stream_check(sockfd)) return -EINVAL; + + TcpOnUdp& tous = *tou_streams[sockfd]; /* enforce that the udptype is correct */ - if (tous -> udptype != TOU_RECEIVER_TYPE_UDPRELAY) + if (tous.udptype != TOU_RECEIVER_TYPE_UDPRELAY) { - std::cerr << "tou_connect() ERROR connect method invalid for udptype"; - std::cerr << std::endl; - tous -> lasterrno = EINVAL; - return -1; + std::cerr << __PRETTY_FUNCTION__ << " ERROR connect method invalid for " + << "udptype" << std::endl; + tous.lasterrno = EINVAL; + return -EINVAL; } -#ifdef TOU_DYNAMIC_CAST_CHECK - /* extra checking -> for testing purposes (dynamic cast) */ - UdpRelayReceiver *urr = dynamic_cast(tous->udpsr); - if (!urr) + UdpRelayReceiver* urr_ptr = dynamic_cast(tous.udpsr); + if(!urr_ptr) { - std::cerr << "tou_connect() ERROR cannot convert type to UdpRelayReceiver"; - std::cerr << std::endl; - tous -> lasterrno = EINVAL; - return -1; + std::cerr << __PRETTY_FUNCTION__ << " ERROR cannot convert to " + << "UdpRelayReceiver" << std::endl; + tous.lasterrno = EINVAL; + return -EINVAL; } -#else - UdpRelayReceiver *urr = (UdpRelayReceiver *) (tous->udpsr); -#endif + + UdpRelayReceiver& urr = *urr_ptr; urr_ptr = nullptr; /* create a TCP stream to connect with. */ - if (!tous->tcp) + if (!tous.tcp) { - tous->tcp = new TcpStream(tous->udpsr); + tous.tcp = new TcpStream(tous.udpsr); - UdpRelayAddrSet addrSet(own_addr, dest_addr); - urr->addUdpPeer(tous->tcp, &addrSet, proxy_addr); + UdpRelayAddrSet addrSet(&own_addr, &dest_addr); + urr.addUdpPeer(tous.tcp, &addrSet, &proxy_addr); } /* We Point it at the Destination Address. * The UdpRelayReceiver wraps and re-directs the packets to the proxy */ - tous->tcp->connect(*dest_addr, DEFAULT_RELAY_CONN_PERIOD); - tous->tcp->tick(); - if (tous->tcp->isConnected()) - { - return 0; - } + tous.tcp->connect(dest_addr, DEFAULT_RELAY_CONN_PERIOD); + tous.tcp->tick(); + if (tous.tcp->isConnected()) return 0; - tous -> lasterrno = EINPROGRESS; - return -1; + tous.lasterrno = EINPROGRESS; + return -EINPROGRESS; } diff --git a/libretroshare/src/tcponudp/tou.h b/libretroshare/src/tcponudp/tou.h index 0c09ce159..5635c50c5 100644 --- a/libretroshare/src/tcponudp/tou.h +++ b/libretroshare/src/tcponudp/tou.h @@ -103,12 +103,6 @@ int tou_connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen, uint32_t conn_period); int tou_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); - /* for relay connections */ -int tou_connect_via_relay(int sockfd, - const struct sockaddr_in *own_addr, - const struct sockaddr_in *proxy_addr, - const struct sockaddr_in *dest_addr); - /* non-standard bonuses */ int tou_connected(int sockfd); int tou_listenfor(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen); @@ -131,6 +125,14 @@ int tou_maxwrite(int sockfd); #ifdef __cplusplus } + +typedef struct sockaddr_in sockaddr_in; + +/// for relay connections +int tou_connect_via_relay( int sockfd, const sockaddr_in& own_addr, + const sockaddr_in& proxy_addr, + const sockaddr_in& dest_addr ); + #endif #endif diff --git a/libretroshare/src/util/stacktrace.h b/libretroshare/src/util/stacktrace.h index f7284e7f9..aa0702dd8 100644 --- a/libretroshare/src/util/stacktrace.h +++ b/libretroshare/src/util/stacktrace.h @@ -1,9 +1,7 @@ /******************************************************************************* - * libretroshare/src/util: smallobject.h * + * libretroshare * * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2016 Gioacchino Mazzurco * + * Copyright (C) 2016-2018 Gioacchino Mazzurco * * Copyright (C) 2008 Timo Bingmann http://idlebox.net/ * * * * This program is free software: you can redistribute it and/or modify * @@ -20,24 +18,39 @@ * along with this program. If not, see . * * * *******************************************************************************/ -#ifndef _STACKTRACE_H_ -#define _STACKTRACE_H_ +#pragma once -#include +#include +#include +#include #if defined(__linux__) && defined(__GLIBC__) -#include #include #include -/** Print a demangled stack backtrace of the caller function to FILE* out. */ -static inline void print_stacktrace(FILE *out = stderr, unsigned int max_frames = 63) +/** + * @brief Print a backtrace to FILE* out. + * @param[in] demangle true to demangle C++ symbols requires malloc working, in + * some patological cases like a SIGSEGV received during a malloc this would + * cause deadlock so pass false if you may be in such situation (like in a + * SIGSEGV handler ) + * @param[in] out output file + * @param[in] maxFrames maximum number of stack frames you want to bu printed + */ +static inline void print_stacktrace( + bool demangle = true, FILE *out = stderr, unsigned int maxFrames = 63 ) { + if(!out) + { + fprintf(stderr, "print_stacktrace invalid output file!\n"); + return; + } + fprintf(out, "stack trace:\n"); // storage array for stack trace address data - void* addrlist[max_frames+1]; + void* addrlist[maxFrames+1]; // retrieve current stack addresses int addrlen = backtrace(addrlist, sizeof(addrlist) / sizeof(void*)); @@ -48,6 +61,19 @@ static inline void print_stacktrace(FILE *out = stderr, unsigned int max_frames return; } + if(!demangle) + { + int outFd = fileno(out); + if(outFd < 0) + { + fprintf(stderr, "print_stacktrace invalid output file descriptor!\n"); + return; + } + + backtrace_symbols_fd(addrlist, addrlen, outFd); + return; + } + // resolve addresses into strings containing "filename(function+address)", // this array must be free()-ed char** symbollist = backtrace_symbols(addrlist, addrlen); @@ -62,8 +88,8 @@ static inline void print_stacktrace(FILE *out = stderr, unsigned int max_frames { char *begin_name = 0, *begin_offset = 0, *end_offset = 0; - // find parentheses and +address offset surrounding the mangled name: - // ./module(function+0x15c) [0x8048a6d] + /* find parentheses and +address offset surrounding the mangled + * name: ./module(function+0x15c) [0x8048a6d] */ for (char *p = symbollist[i]; *p; ++p) { if (*p == '(') begin_name = p; @@ -75,7 +101,8 @@ static inline void print_stacktrace(FILE *out = stderr, unsigned int max_frames } } - if (begin_name && begin_offset && end_offset && begin_name < begin_offset) + if ( begin_name && begin_offset && end_offset + && begin_name < begin_offset ) { *begin_name++ = '\0'; *begin_offset++ = '\0'; @@ -86,17 +113,20 @@ static inline void print_stacktrace(FILE *out = stderr, unsigned int max_frames // __cxa_demangle(): int status; - char* ret = abi::__cxa_demangle(begin_name, funcname, &funcnamesize, &status); + char* ret = abi::__cxa_demangle( + begin_name, funcname, &funcnamesize, &status ); if (status == 0) { funcname = ret; // use possibly realloc()-ed string - fprintf(out, " %s : %s+%s\n", symbollist[i], funcname, begin_offset); + fprintf( out, " %s : %s+%s\n", + symbollist[i], funcname, begin_offset ); } else { // demangling failed. Output function name as a C function with // no arguments. - fprintf(out, " %s : %s()+%s\n", symbollist[i], begin_name, begin_offset); + fprintf( out, " %s : %s()+%s\n", + symbollist[i], begin_name, begin_offset ); } } else @@ -111,12 +141,61 @@ static inline void print_stacktrace(FILE *out = stderr, unsigned int max_frames } #else // defined(__linux__) && defined(__GLIBC__) -static inline void print_stacktrace(FILE *out = stderr, unsigned int max_frames = 63) +static inline void print_stacktrace( + bool demangle = true, FILE *out = stderr, unsigned int max_frames = 63 ) { + (void) demangle; (void) max_frames; fprintf(out, "TODO: 2016/01/01 print_stacktrace not implemented yet for WINDOWS_SYS and ANDROID\n"); } #endif // defined(__linux__) && defined(__GLIBC__) -#endif // _STACKTRACE_H_ +/** + * @brief CrashStackTrace catch crash signals and print stack trace + * Inspired too https://oroboro.com/stack-trace-on-crash/ + */ +struct CrashStackTrace +{ + CrashStackTrace() + { + signal(SIGABRT, &CrashStackTrace::abortHandler); + signal(SIGSEGV, &CrashStackTrace::abortHandler); + signal(SIGILL, &CrashStackTrace::abortHandler); + signal(SIGFPE, &CrashStackTrace::abortHandler); +#ifdef SIGBUS + signal(SIGBUS, &CrashStackTrace::abortHandler); +#endif + } + + static void abortHandler(int signum) + { + // associate each signal with a signal name string. + const char* name = nullptr; + switch(signum) + { + case SIGABRT: name = "SIGABRT"; break; + case SIGSEGV: name = "SIGSEGV"; break; + case SIGILL: name = "SIGILL"; break; + case SIGFPE: name = "SIGFPE"; break; +#ifdef SIGBUS + case SIGBUS: name = "SIGBUS"; break; +#endif + } + + /** Notify the user which signal was caught. We use printf, because this + * is the most basic output function. Once you get a crash, it is + * possible that more complex output systems like streams and the like + * may be corrupted. So we make the most basic call possible to the + * lowest level, most standard print function. */ + if(name) + fprintf(stderr, "Caught signal %d (%s)\n", signum, name); + else + fprintf(stderr, "Caught signal %d\n", signum); + + print_stacktrace(false); + + exit(-signum); + } +}; + diff --git a/retroshare-gui/src/main.cpp b/retroshare-gui/src/main.cpp index ae0019e80..acb8d390d 100644 --- a/retroshare-gui/src/main.cpp +++ b/retroshare-gui/src/main.cpp @@ -19,6 +19,10 @@ * Boston, MA 02110-1301, USA. ****************************************************************/ +#include "util/stacktrace.h" + +CrashStackTrace gCrashStackTrace; + #include #include #include diff --git a/retroshare-service/src/retroshare-service.cc b/retroshare-service/src/retroshare-service.cc index 9b7bc7d65..bcacb5880 100644 --- a/retroshare-service/src/retroshare-service.cc +++ b/retroshare-service/src/retroshare-service.cc @@ -16,6 +16,10 @@ * along with this program. If not, see . */ +#include "util/stacktrace.h" + +CrashStackTrace gCrashStackTrace; + #include #include #include