Found cause of OSX network resets / lost connections: inet_ntoa is not thread-safe.

* Added thread-safe rs_inet_ntoa function (util/rsnet.cc)
 * Switched all calls to this function (most of the changes)
 * Modified getLocalInterfaces() and getPreferredInterface() to avoid string conversions.
   - NB: Modified windows functions too, but unable to test (hope it compiles!)

Also:
 * Added  EVP_CIPHER_CTX_rand_key() replacement function for old versions of SSL (pre 0.9.8)  (for OSX 10.5)
   - NB: This code should be reworked to remove these calls anyway.
 * Updated tests/pqi to handle above changes.



git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@3281 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
drbob 2010-07-10 20:34:03 +00:00
parent 0b298f6ca1
commit 648e15bcf7
34 changed files with 360 additions and 235 deletions

View file

@ -174,8 +174,8 @@ virtual bool dhtPublish(std::string id,
uint32_t type, std::string sign)
{
std::cerr << "DhtMgrTester::dhtPublish() id: " << RsUtil::BinToHex(id);
std::cerr << " laddr: " << inet_ntoa(laddr.sin_addr) << " lport: " << ntohs(laddr.sin_port);
std::cerr << " raddr: " << inet_ntoa(raddr.sin_addr) << " rport: " << ntohs(raddr.sin_port);
std::cerr << " laddr: " << rs_inet_ntoa(laddr.sin_addr) << " lport: " << ntohs(laddr.sin_port);
std::cerr << " raddr: " << rs_inet_ntoa(raddr.sin_addr) << " rport: " << ntohs(raddr.sin_port);
std::cerr << " type: " << type << " sign: " << sign;
std::cerr << std::endl;

View file

@ -170,8 +170,8 @@ virtual bool dhtPublish(std::string id,
uint32_t type, std::string sign)
{
std::cerr << "DhtMgrTester::dhtPublish() id: " << RsUtil::BinToHex(id);
std::cerr << " laddr: " << inet_ntoa(laddr.sin_addr) << " lport: " << ntohs(laddr.sin_port);
std::cerr << " raddr: " << inet_ntoa(raddr.sin_addr) << " rport: " << ntohs(raddr.sin_port);
std::cerr << " laddr: " << rs_inet_ntoa(laddr.sin_addr) << " lport: " << ntohs(laddr.sin_port);
std::cerr << " raddr: " << rs_inet_ntoa(raddr.sin_addr) << " rport: " << ntohs(raddr.sin_port);
std::cerr << " type: " << type << " sign: " << sign;
std::cerr << std::endl;

View file

@ -112,16 +112,16 @@ bool test_local_address_manipulation()
inet_aton(localnet4_addrstr, &(localnet4_addr.sin_addr));
std::cerr << "Loopback Addr " << inet_ntoa(loopback_addr.sin_addr);
std::cerr << "Loopback Addr " << rs_inet_ntoa(loopback_addr.sin_addr);
std::cerr << std::endl;
std::cerr << "Localnet1 Addr " << inet_ntoa(localnet1_addr.sin_addr);
std::cerr << "Localnet1 Addr " << rs_inet_ntoa(localnet1_addr.sin_addr);
std::cerr << std::endl;
std::cerr << "Localnet2 Addr " << inet_ntoa(localnet2_addr.sin_addr);
std::cerr << "Localnet2 Addr " << rs_inet_ntoa(localnet2_addr.sin_addr);
std::cerr << std::endl;
std::cerr << "Localnet3 Addr " << inet_ntoa(localnet3_addr.sin_addr);
std::cerr << "Localnet3 Addr " << rs_inet_ntoa(localnet3_addr.sin_addr);
std::cerr << std::endl;
std::cerr << "Localnet4 Addr " << inet_ntoa(localnet4_addr.sin_addr);
std::cerr << "Localnet4 Addr " << rs_inet_ntoa(localnet4_addr.sin_addr);
std::cerr << std::endl;
std::cerr << std::endl;
@ -137,13 +137,13 @@ bool test_local_address_manipulation()
addr2.sin_addr.s_addr = htonl(inet_network(loopback_addrstr));
std::cerr << "Loopback Net(expected): " << addr_ans_str;
std::cerr << " -> " << inet_ntoa(addr_ans.sin_addr);
std::cerr << " Net(1):" << inet_ntoa(addr1.sin_addr);
std::cerr << " Net(2):" << inet_ntoa(addr2.sin_addr);
std::cerr << " -> " << rs_inet_ntoa(addr_ans.sin_addr);
std::cerr << " Net(1):" << rs_inet_ntoa(addr1.sin_addr);
std::cerr << " Net(2):" << rs_inet_ntoa(addr2.sin_addr);
std::cerr << std::endl;
//CHECK( 0 == strcmp(addr_ans_str.c_str(), inet_ntoa(addr1.sin_addr)));
//CHECK( 0 == strcmp(addr_ans_str.c_str(), inet_ntoa(addr2.sin_addr)));
//CHECK( 0 == strcmp(addr_ans_str.c_str(), rs_inet_ntoa(addr1.sin_addr)));
//CHECK( 0 == strcmp(addr_ans_str.c_str(), rs_inet_ntoa(addr2.sin_addr)));
addr_ans_str = "192.168.0.0";
@ -152,13 +152,13 @@ bool test_local_address_manipulation()
addr2.sin_addr.s_addr = htonl(inet_network(localnet1_addrstr));
std::cerr << "Localnet1 Net(expected): " << addr_ans_str;
std::cerr << " -> " << inet_ntoa(addr_ans.sin_addr);
std::cerr << " Net(1):" << inet_ntoa(addr1.sin_addr);
std::cerr << " Net(2):" << inet_ntoa(addr2.sin_addr);
std::cerr << " -> " << rs_inet_ntoa(addr_ans.sin_addr);
std::cerr << " Net(1):" << rs_inet_ntoa(addr1.sin_addr);
std::cerr << " Net(2):" << rs_inet_ntoa(addr2.sin_addr);
std::cerr << std::endl;
//CHECK( 0 == strcmp(addr_ans_str.c_str(), inet_ntoa(addr1.sin_addr)));
//CHECK( 0 == strcmp(addr_ans_str.c_str(), inet_ntoa(addr2.sin_addr)));
//CHECK( 0 == strcmp(addr_ans_str.c_str(), rs_inet_ntoa(addr1.sin_addr)));
//CHECK( 0 == strcmp(addr_ans_str.c_str(), rs_inet_ntoa(addr2.sin_addr)));
addr_ans_str = "10.0.0.0";
inet_aton(addr_ans_str.c_str(), &(addr_ans.sin_addr));
@ -166,14 +166,14 @@ bool test_local_address_manipulation()
addr2.sin_addr.s_addr = htonl(inet_network(localnet2_addrstr));
std::cerr << "Localnet2 Net(expected): " << addr_ans_str;
std::cerr << " -> " << inet_ntoa(addr_ans.sin_addr);
std::cerr << " Net(1):" << inet_ntoa(addr1.sin_addr);
std::cerr << " Net(2):" << inet_ntoa(addr2.sin_addr);
std::cerr << " -> " << rs_inet_ntoa(addr_ans.sin_addr);
std::cerr << " Net(1):" << rs_inet_ntoa(addr1.sin_addr);
std::cerr << " Net(2):" << rs_inet_ntoa(addr2.sin_addr);
std::cerr << std::endl;
//CHECK( 0 == strcmp(addr_ans_str.c_str(), inet_ntoa(addr1.sin_addr)));
//CHECK( 0 == strcmp(addr_ans_str.c_str(), inet_ntoa(addr2.sin_addr)));
//CHECK( 0 == strcmp(addr_ans_str.c_str(), rs_inet_ntoa(addr1.sin_addr)));
//CHECK( 0 == strcmp(addr_ans_str.c_str(), rs_inet_ntoa(addr2.sin_addr)));
addr_ans_str = "10.0.0.0";
@ -182,14 +182,14 @@ bool test_local_address_manipulation()
addr2.sin_addr.s_addr = htonl(inet_network(localnet3_addrstr));
std::cerr << "Localnet3 Net(expected): " << addr_ans_str;
std::cerr << " -> " << inet_ntoa(addr_ans.sin_addr);
std::cerr << " Net(1):" << inet_ntoa(addr1.sin_addr);
std::cerr << " Net(2):" << inet_ntoa(addr2.sin_addr);
std::cerr << " -> " << rs_inet_ntoa(addr_ans.sin_addr);
std::cerr << " Net(1):" << rs_inet_ntoa(addr1.sin_addr);
std::cerr << " Net(2):" << rs_inet_ntoa(addr2.sin_addr);
std::cerr << std::endl;
//CHECK( 0 == strcmp(addr_ans_str.c_str(), inet_ntoa(addr1.sin_addr)));
//CHECK( 0 == strcmp(addr_ans_str.c_str(), inet_ntoa(addr2.sin_addr)));
//CHECK( 0 == strcmp(addr_ans_str.c_str(), rs_inet_ntoa(addr1.sin_addr)));
//CHECK( 0 == strcmp(addr_ans_str.c_str(), rs_inet_ntoa(addr2.sin_addr)));
addr_ans_str = "192.168.0.0";
@ -198,14 +198,14 @@ bool test_local_address_manipulation()
addr2.sin_addr.s_addr = htonl(inet_network(localnet4_addrstr));
std::cerr << "Localnet4 Net(expected): " << addr_ans_str;
std::cerr << " -> " << inet_ntoa(addr_ans.sin_addr);
std::cerr << " Net(1):" << inet_ntoa(addr1.sin_addr);
std::cerr << " Net(2):" << inet_ntoa(addr2.sin_addr);
std::cerr << " -> " << rs_inet_ntoa(addr_ans.sin_addr);
std::cerr << " Net(1):" << rs_inet_ntoa(addr1.sin_addr);
std::cerr << " Net(2):" << rs_inet_ntoa(addr2.sin_addr);
std::cerr << std::endl;
//CHECK( 0 == strcmp(addr_ans_str.c_str(), inet_ntoa(addr1.sin_addr)));
//CHECK( 0 == strcmp(addr_ans_str.c_str(), inet_ntoa(addr2.sin_addr)));
//CHECK( 0 == strcmp(addr_ans_str.c_str(), rs_inet_ntoa(addr1.sin_addr)));
//CHECK( 0 == strcmp(addr_ans_str.c_str(), rs_inet_ntoa(addr2.sin_addr)));
REPORT("Test Local Address Manipulation");
return true;
@ -264,12 +264,12 @@ bool test_address_listen()
sockaddr_clear(&addr2);
addr2.sin_family = AF_INET;
addr2.sin_addr = getPreferredInterface(); // returns best addr.
getPreferredInterface(addr2.sin_addr); // returns best addr.
addr2.sin_port = htons(13245);
sockaddr_clear(&addr3);
addr3.sin_family = AF_INET;
addr3.sin_addr = getPreferredInterface(); // returns best addr.
getPreferredInterface(addr3.sin_addr); // returns best addr.
addr3.sin_port = htons(23451);
/* test bind to loopback, and preferred interfaces */
@ -293,7 +293,7 @@ bool test_bind_addr(struct sockaddr_in addr)
std::cerr << "\tAddress Family: " << (int) addr.sin_family;
std::cerr << std::endl;
std::cerr << "\tAddress: " << inet_ntoa(addr.sin_addr);
std::cerr << "\tAddress: " << rs_inet_ntoa(addr.sin_addr);
std::cerr << std::endl;
std::cerr << "\tPort: " << ntohs(addr.sin_port);
std::cerr << std::endl;

View file

@ -203,7 +203,7 @@ int test_isValidNet()
CHECK(isValidNet(&localnet1_addr)==true);
CHECK(inet_aton(invalid_addrstr, &invalid_addr)==0);
std::cerr << inet_ntoa(invalid_addr) << std::endl;
std::cerr << rs_inet_ntoa(invalid_addr) << std::endl;
//CHECK(isValidNet(&invalid_addr)==false);
REPORT("isValidNet()");

View file

@ -36,28 +36,87 @@
bool test_iface();
bool test_iface_loop();
int main(int argc, char **argv)
{
bool repeat = false;
if (argc > 1)
{
repeat = true;
}
test_iface();
if (repeat)
{
test_iface_loop();
}
return 1;
}
/* test 1: byte manipulation */
/* test 1: single check if interfaces */
bool test_iface()
{
struct in_addr pref_iface = getPreferredInterface();
std::list<std::string> ifaces = getLocalInterfaces();
std::list<std::string>::iterator it;
struct in_addr pref_iface;
std::list<struct in_addr> ifaces;
std::list<struct in_addr>::iterator it;
getPreferredInterface(pref_iface);
getLocalInterfaces(ifaces);
std::cerr << "test_iface()" << std::endl;
for(it = ifaces.begin(); it != ifaces.end(); it++)
{
std::cerr << "available iface: " << *it << std::endl;
std::cerr << "available iface: " << rs_inet_ntoa(*it) << std::endl;
}
std::cerr << "preferred " << inet_ntoa(pref_iface) << std::endl;
std::cerr << "preferred " << rs_inet_ntoa(pref_iface) << std::endl;
return true;
}
/* test 2: catch changing interfaces */
bool test_iface_loop()
{
std::cerr << "test_iface_loop()" << std::endl;
struct in_addr curr_pref_iface;
getPreferredInterface(curr_pref_iface);
time_t start = time(NULL);
while(1)
{
struct in_addr pref_iface;
std::list<struct in_addr> ifaces;
std::list<struct in_addr>::iterator it;
getPreferredInterface(pref_iface);
getLocalInterfaces(ifaces);
std::cerr << "T(" << time(NULL) - start << ") ";
for(it = ifaces.begin(); it != ifaces.end(); it++)
{
std::cerr << " I: " << rs_inet_ntoa(*it);
}
std::cerr << " P: " << rs_inet_ntoa(pref_iface) << std::endl;
if (curr_pref_iface.s_addr !=
pref_iface.s_addr)
{
std::cerr << "+++++++++++++ Address CHANGED ++++++++++";
std::cerr << std::endl;
std::cerr << "+++++++++++++ Address CHANGED ++++++++++";
std::cerr << std::endl;
std::cerr << "+++++++++++++ Address CHANGED ++++++++++";
std::cerr << std::endl;
curr_pref_iface = pref_iface;
}
sleep(1);
}
return true;
}

View file

@ -19,25 +19,16 @@ endif
# MAC_I386_BUILD = 1
# MAC_PPC_BUILD = 1
#MAC_I386_BUILD = 1
MAC_I386_BUILD = 1
#MAC_PPC_BUILD = 1
ifndef MAC_I386_BUILD
MAC_PPC_BUILD = 1
endif
# flags for components....
#PQI_USE_SSLONLY = 1
#PQI_USE_XPGP = 1
UPNPC_DIR=../../../../../../src/miniupnpc-1.0
#PQI_USE_PROXY = 1
#PQI_USE_CHANNELS = 1
#USE_FILELOOK = 1
SSL_DIR=../../../../../src/openssl-0.9.7g-xpgp-0.1c
UPNPC_DIR=../../../../../src/miniupnpc-1.0
include $(RS_TOP_DIR)/scripts/checks.mk
include $(RS_TOP_DIR)/tests/scripts/checks.mk
############ ENFORCE DIRECTORY NAMING ########################
@ -73,29 +64,7 @@ CFLAGS += $(INCLUDE)
# This Line is for Universal BUILD for 10.4 + 10.5
# (but unlikely to work unless Qt Libraries are build properly)
# CFLAGS += -isysroot /Developer/SDKs/MacOSX10.4u.sdk
ifdef PQI_USE_XPGP
INCLUDE += -I $(SSL_DIR)/include
CFLAGS += -DPQI_USE_XPGP
endif
ifdef PQI_USE_SSLONLY
CFLAGS += -DPQI_USE_SSLONLY
endif
ifdef PQI_USE_PROXY
CFLAGS += -DPQI_USE_PROXY
endif
ifdef PQI_USE_CHANNELS
CFLAGS += -DPQI_USE_CHANNELS
endif
ifdef USE_FILELOOK
CFLAGS += -DUSE_FILELOOK
endif
#CFLAGS += -isysroot /Developer/SDKs/MacOSX10.5.sdk
# RSCFLAGS = -Wall -O3 $(INCLUDE)
@ -103,30 +72,6 @@ endif
# OS Compile Options
#########################################################################
# For the SSL BIO compilation. (Copied from OpenSSL compilation flags)
BIOCC = gcc
# Flags for architecture builds.
ifdef MAC_I386_BUILD
BIOCFLAGS = -arch i386 -I $(SSL_DIR)/include -DOPENSSL_SYSNAME_MACOSX -DOPENSSL_THREADS -D_REENTRANT -DOPENSSL_NO_KRB5 -O3 -fomit-frame-pointer -fno-common
endif
ifdef MAC_PPC_BUILD
BIOCFLAGS = -arch ppc -I $(SSL_DIR)/include -DOPENSSL_SYSNAME_MACOSX -DOPENSSL_THREADS -D_REENTRANT -DOPENSSL_NO_KRB5 -O3 -fomit-frame-pointer -fno-common -DB_ENDIAN
endif
# MacOSX flags
# BIOCFLAGS = -I $(SSL_DIR)/include -DOPENSSL_SYSNAME_MACOSX -DOPENSSL_THREADS -D_REENTRANT -DOPENSSL_NO_KRB5 -O3 -fomit-frame-pointer -fno-common -DB_ENDIAN
# This is for the Universal Build...
# but is unlikely to work... as options are PPC specific....
#
# BIOCFLAGS = -arch ppc -arch i386 -I $(SSL_DIR)/include -DOPENSSL_SYSNAME_MACOSX -DOPENSSL_THREADS -D_REENTRANT -DOPENSSL_NO_KRB5 -O3 -fomit-frame-pointer -fno-common -DB_ENDIAN
#########################################################################
# OS specific Linking.
#########################################################################
@ -135,7 +80,7 @@ LIBS = -Wl,-search_paths_first
# for Univeral BUILD
# LIBS += -arch ppc -arch i386
# LIBS += -Wl,-syslibroot,/Developer/SDKs/MacOSX10.4u.sdk -arch ppc -arch i386
#LIBS += -Wl,-syslibroot,/Developer/SDKs/MacOSX10.5u.sdk
LIBS += -L$(LIBDIR) -lretroshare
ifdef PQI_USE_XPGP