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