1660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti#include <arpa/inet.h> 2660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti#include <linux/if.h> 3660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti#include <netinet/in.h> 450eedd14706d7a9768e48bb3272bf00451becff4Dan Albert#include <stdlib.h> 550eedd14706d7a9768e48bb3272bf00451becff4Dan Albert#include <sys/ioctl.h> 6660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti#include <sys/socket.h> 750eedd14706d7a9768e48bb3272bf00451becff4Dan Albert#include <unistd.h> 8660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti 9660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti#include <atomic> 10660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti#include <mutex> 11660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti#include <thread> 12660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti 1350eedd14706d7a9768e48bb3272bf00451becff4Dan Albert#include "utils/RWLock.h" 1450eedd14706d7a9768e48bb3272bf00451becff4Dan Albert 15660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti// Defined only in ifc_utils.c, in the kernel, and in the NDK. 16660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti#ifndef SIOCKILLADDR 17660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti#define SIOCKILLADDR 0x8939 18660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti#endif 19660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti 20660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti#ifndef TCP_LINGER2 21660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti#define TCP_LINGER2 8 22660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti#endif 23660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti 24660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti#define KILL_INTERVAL_MS 10 25660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti#define CONNECT_THREADS 1 26660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti 27660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti#define PERROR_EXIT(msg) { do { perror((msg)); exit(1); } while (0); }; 28660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti 29660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti 30660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti// Ensures that sockets don't stay in TIME_WAIT state. 31660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colittivoid setSoLinger(int s) { 32660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti const struct linger l = { 33660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti 0, // off 34660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti 0, // 0 seconds 35660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti }; 36660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti if (setsockopt(s, SOL_SOCKET, SO_LINGER, &l, sizeof(l)) == -1) { 37660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti PERROR_EXIT("SO_LINGER"); 38660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti } 39660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti const int nolinger = -1; 40660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti if (setsockopt(s, SOL_TCP, TCP_LINGER2, &nolinger, sizeof(nolinger)) == -1) { 41660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti PERROR_EXIT("TCP_LINGER2"); 42660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti } 43660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti} 44660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti 45660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti 46660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti// Binds to a random port on a random loopback address. We don't just use 127.0.0.1 because we don't 47660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti// want this test to kill unrelated connections on loopback. 48660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colittiint bindRandomAddr() { 49660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti sockaddr_in sin; 50660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti sin.sin_family = AF_INET; 51660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti sin.sin_port = 0; 52660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 53660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti 54660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti while (sin.sin_addr.s_addr == htonl(INADDR_LOOPBACK)) { 55660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti arc4random_buf( 56660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti ((uint8_t *) &sin.sin_addr.s_addr) + 1, 57660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti sizeof(sin.sin_addr.s_addr) - 1); 58660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti } 59660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti 60660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti int listensock; 61660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti if ((listensock = socket(AF_INET, SOCK_STREAM, 0)) == -1) PERROR_EXIT("listensock"); 62660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti if (bind(listensock, (sockaddr *) &sin, sizeof(sin)) == -1) PERROR_EXIT("bind"); 63660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti if (listen(listensock, 10) == -1) PERROR_EXIT("listen"); 64660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti 65660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti return listensock; 66660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti} 67660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti 68660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti 69660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti// Thread that calls SIOCKILLADDR in a loop. 70660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colittivoid killSockets(sockaddr_in listenaddr, int intervalMs, android::RWLock *lock) { 71660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti ifreq ifr; 72660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti memset(&ifr, 0, sizeof(ifr)); 73660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti listenaddr.sin_port = 0; 74660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti strncpy(ifr.ifr_name, "lo", strlen("lo")); 75660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti memcpy(&ifr.ifr_addr, &listenaddr, sizeof(listenaddr)); 76660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti 77660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti int ioctlsock = socket(AF_INET, SOCK_DGRAM, 0); 78660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti if (ioctlsock == -1) PERROR_EXIT("ioctlsock"); 79660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti while(true) { 80660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti lock->writeLock(); 81660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti if (ioctl(ioctlsock, SIOCKILLADDR, &ifr) != 0) { 82660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti PERROR_EXIT("SIOCKILLADDR failed, did you run 32-bit userspace on a 64-bit kernel?"); 83660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti } 84660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti lock->unlock(); 85660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti std::this_thread::sleep_for(std::chrono::milliseconds(intervalMs)); 86660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti } 87660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti} 88660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti 89660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti 90660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti// Thread that calls connect() in a loop. 91660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colittivoid connectLoop(sockaddr_in listenaddr, int listensock, 92660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti android::RWLock *lock, std::atomic<unsigned int> *attempts) { 93660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti while(true) { 94660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti int s = socket(AF_INET, SOCK_STREAM, 0); 95660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti setSoLinger(s); 96660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti 97660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti // Don't call SIOCKILLADDR while connect() is running, or we'll end up with lots of 98660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti // connections in state FIN_WAITx or TIME_WAIT, which will then slow down future 99660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti // due to SYN retransmits. 100660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti lock->readLock(); 101660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti if (connect(s, (sockaddr *) &listenaddr, sizeof(listenaddr)) == -1) PERROR_EXIT("connect"); 102660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti lock->unlock(); 103660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti 104660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti send(s, "foo", 3, 0); 105660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti int acceptedsock = accept(listensock, NULL, 0); 106660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti if (close(acceptedsock) == -1) PERROR_EXIT("close"); 107660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti if (close(s) == -1) PERROR_EXIT("close"); 108660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti 109660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti attempts->fetch_add(1); 110660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti } 111660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti} 112660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti 113660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti 114660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti// Thread that prints progress every second. 115660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colittivoid progressThread(std::atomic<unsigned int> *attempts) { 116660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti uint32_t elapsed = 0; 117660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti uint32_t total, previous = 0; 118660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti while (true) { 119660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti std::this_thread::sleep_for(std::chrono::seconds(1)); 120660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti elapsed++; 121660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti total = attempts->load(); 122660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti printf("%ds: %u cps, total %u\n", elapsed, total-previous, total); 123660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti fflush(stdout); 124660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti previous = total; 125660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti } 126660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti} 127660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti 128660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti 129660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colittiint main() { 130660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti int listensock = bindRandomAddr(); 131660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti struct sockaddr_in sin; 132660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti socklen_t len = sizeof(sin); 133660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti if (getsockname(listensock, (sockaddr *) &sin, &len) == -1) PERROR_EXIT("getsockname"); 134660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti 135660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti printf("Using address %s:%d\n", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 136660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti 137660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti android::RWLock lock; 138660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti std::atomic<unsigned int> attempts; 139660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti attempts.store(0); 140660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti 141660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti std::thread t0(killSockets, sin, KILL_INTERVAL_MS, &lock); 142660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti std::thread *connectThreads[CONNECT_THREADS]; 143660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti for (size_t i = 0; i < CONNECT_THREADS; i++) { 144660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti connectThreads[i] = new std::thread(connectLoop, sin, listensock, &lock, &attempts); 145660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti } 146660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti std::thread t1(progressThread, &attempts); 147660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti t1.join(); 148660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti 149660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti return 0; 150660bdfdefcd4e8662e47c8ac9236fdb8df18a934Lorenzo Colitti} 151