Coverage Report

Created: 2026-10-24 08:16

/work/testing/support/doubles/fake_sockets.cc
Line
Count
Source (jump to first uncovered line)
1
#include "fake_sockets.hh"
2
3
#include <algorithm>
4
#include <cerrno>
5
#include <cstddef>
6
#include <cstring>
7
#include <deque>
8
#include <functional>
9
#include <iostream>
10
#include <mutex>
11
#include <vector>
12
13
#include "network_universe.hh"
14
15
namespace tox::test {
16
17
// --- FakeSocket ---
18
19
FakeSocket::FakeSocket(NetworkUniverse &universe, int type)
20
    : universe_(universe)
21
    , type_(type)
22
8.96k
{
23
8.96k
    ip_init(&ip_, false);
24
8.96k
    ip_.ip.v4.uint32 = net_htonl(0x7F000001);
25
8.96k
}
26
27
8.96k
FakeSocket::~FakeSocket() = default;
28
29
int FakeSocket::close()
30
0
{
31
    // Override in subclasses to unbind
32
0
    return 0;
33
0
}
34
35
int FakeSocket::getsockopt(
36
    int level, int optname, void *_Nonnull optval, std::size_t *_Nonnull optlen)
37
1.44k
{
38
1.44k
    return 0;
39
1.44k
}
40
int FakeSocket::setsockopt(int level, int optname, const void *_Nonnull optval, std::size_t optlen)
41
6.10k
{
42
6.10k
    return 0;
43
6.10k
}
44
int FakeSocket::socket_nonblock(bool nonblock)
45
1.59k
{
46
1.59k
    nonblocking_ = nonblock;
47
1.59k
    return 0;
48
1.59k
}
49
50
// --- FakeUdpSocket ---
51
52
FakeUdpSocket::FakeUdpSocket(NetworkUniverse &universe)
53
    : FakeSocket(universe, SOCK_DGRAM)
54
8.84k
{
55
8.84k
}
56
57
8.84k
FakeUdpSocket::~FakeUdpSocket() { close_impl(); }
58
59
int FakeUdpSocket::close()
60
1.54k
{
61
1.54k
    std::lock_guard<std::mutex> lock(mutex_);
62
1.54k
    close_impl();
63
1.54k
    return 0;
64
1.54k
}
65
66
void FakeUdpSocket::close_impl()
67
10.3k
{
68
10.3k
    if (local_port_ != 0) {
69
8.82k
        universe_.unbind_udp(ip_, local_port_);
70
8.82k
        local_port_ = 0;
71
8.82k
    }
72
10.3k
}
73
74
int FakeUdpSocket::bind(const IP_Port *_Nonnull addr)
75
10.2k
{
76
10.2k
    std::lock_guard<std::mutex> lock(mutex_);
77
10.2k
    if (local_port_ != 0)
78
0
        return -1;  // Already bound
79
80
10.2k
    uint16_t port = addr->port;
81
10.2k
    if (port == 0) {
82
0
        port = universe_.find_free_port(ip_);
83
10.2k
    } else {
84
10.2k
        port = net_ntohs(port);
85
10.2k
    }
86
87
10.2k
    if (universe_.bind_udp(ip_, port, this)) {
88
8.81k
        local_port_ = port;
89
8.81k
        return 0;
90
8.81k
    }
91
1.46k
    errno = EADDRINUSE;
92
1.46k
    return -1;
93
10.2k
}
94
95
int FakeUdpSocket::connect(const IP_Port *_Nonnull addr)
96
0
{
97
    // UDP connect just sets default dest.
98
    // Not strictly needed for toxcore UDP but good for completeness.
99
0
    return 0;
100
0
}
101
102
int FakeUdpSocket::listen(int backlog)
103
0
{
104
0
    errno = EOPNOTSUPP;
105
0
    return -1;
106
0
}
107
std::unique_ptr<FakeSocket> FakeUdpSocket::accept(IP_Port *_Nullable addr)
108
0
{
109
0
    errno = EOPNOTSUPP;
110
0
    return nullptr;
111
0
}
112
int FakeUdpSocket::send(const uint8_t *_Nonnull buf, std::size_t len)
113
0
{
114
0
    errno = EDESTADDRREQ;
115
0
    return -1;
116
0
}
117
int FakeUdpSocket::recv(uint8_t *_Nonnull buf, std::size_t len)
118
0
{
119
0
    errno = EOPNOTSUPP;
120
0
    return -1;
121
0
}
122
123
std::size_t FakeUdpSocket::recv_buffer_size()
124
3
{
125
3
    std::lock_guard<std::mutex> lock(mutex_);
126
3
    return recv_queue_.size();
127
3
}
128
129
int FakeUdpSocket::sendto(
130
    const uint8_t *_Nonnull buf, std::size_t len, const IP_Port *_Nonnull addr)
131
41.0k
{
132
41.0k
    std::lock_guard<std::mutex> lock(mutex_);
133
41.0k
    if (local_port_ == 0) {
134
        // Implicit bind
135
6
        uint16_t p = universe_.find_free_port(ip_);
136
6
        if (universe_.bind_udp(ip_, p, this)) {
137
6
            local_port_ = p;
138
6
        } else {
139
0
            errno = EADDRINUSE;
140
0
            return -1;
141
0
        }
142
6
    }
143
144
41.0k
    Packet p{};
145
    // Source
146
41.0k
    p.from.ip = ip_;
147
41.0k
    p.from.port = net_htons(local_port_);
148
41.0k
    p.to = *addr;
149
41.0k
    p.data.assign(buf, buf + len);
150
41.0k
    p.is_tcp = false;
151
152
41.0k
    universe_.send_packet(p);
153
41.0k
    if (universe_.is_verbose()) {
154
0
        Ip_Ntoa ip_str;
155
0
        net_ip_ntoa(&addr->ip, &ip_str);
156
0
        std::cerr << "[FakeUdpSocket] sent " << len << " bytes from port " << local_port_ << " to "
157
0
                  << ip_str.buf << ":" << net_ntohs(addr->port) << std::endl;
158
0
    }
159
41.0k
    return len;
160
41.0k
}
161
162
int FakeUdpSocket::recvfrom(uint8_t *_Nonnull buf, std::size_t len, IP_Port *_Nonnull addr)
163
48.5k
{
164
48.5k
    RecvObserver observer_copy;
165
48.5k
    std::vector<uint8_t> data_copy;
166
48.5k
    IP_Port from_copy;
167
48.5k
    std::size_t copy_len = 0;
168
169
48.5k
    {
170
48.5k
        std::lock_guard<std::mutex> lock(mutex_);
171
172
48.5k
        if (recv_queue_.empty() && packet_source_) {
173
            // NOTE: We call packet_source_ with lock held.
174
            // Be careful not to call back into socket methods from packet_source_.
175
0
            std::vector<uint8_t> data;
176
0
            IP_Port from;
177
0
            if (packet_source_(data, from)) {
178
0
                recv_queue_.push_back({std::move(data), from});
179
0
            }
180
0
        }
181
182
48.5k
        if (recv_queue_.empty()) {
183
8.38k
            errno = EWOULDBLOCK;
184
8.38k
            return -1;
185
8.38k
        }
186
187
40.2k
        auto &p = recv_queue_.front();
188
40.2k
        copy_len = std::min(len, p.data.size());
189
40.2k
        if (copy_len > 0) {
190
40.2k
            std::memcpy(buf, p.data.data(), copy_len);
191
40.2k
        }
192
40.2k
        *addr = p.from;
193
194
40.2k
        if (recv_observer_) {
195
16.7k
            observer_copy = recv_observer_;
196
16.7k
            data_copy = p.data;
197
16.7k
            from_copy = p.from;
198
16.7k
        }
199
200
40.2k
        recv_queue_.pop_front();
201
40.2k
    }
202
203
40.2k
    if (observer_copy) {
204
16.7k
        observer_copy(data_copy, from_copy);
205
16.7k
    }
206
207
40.2k
    if (universe_.is_verbose()) {
208
0
        std::cerr << "[FakeUdpSocket] recv " << copy_len << " bytes at port " << local_port_
209
0
                  << " from port " << net_ntohs(addr->port) << std::endl;
210
0
    }
211
212
40.2k
    return copy_len;
213
48.5k
}
214
215
void FakeUdpSocket::push_packet(std::vector<uint8_t> data, IP_Port from)
216
40.2k
{
217
40.2k
    std::lock_guard<std::mutex> lock(mutex_);
218
40.2k
    if (recv_queue_.size() >= kMaxQueueSize) {
219
1
        if (universe_.is_verbose()) {
220
0
            std::cerr << "[FakeUdpSocket] queue full, dropping packet" << std::endl;
221
0
        }
222
1
        return;
223
1
    }
224
40.2k
    if (universe_.is_verbose()) {
225
0
        Ip_Ntoa local_ip_str, from_ip_str;
226
0
        net_ip_ntoa(&ip_, &local_ip_str);
227
0
        net_ip_ntoa(&from.ip, &from_ip_str);
228
229
0
        std::cerr << "[FakeUdpSocket] push " << data.size() << " bytes into queue for "
230
0
                  << local_ip_str.buf << ":" << local_port_ << " from " << from_ip_str.buf << ":"
231
0
                  << net_ntohs(from.port) << std::endl;
232
0
    }
233
40.2k
    recv_queue_.push_back({std::move(data), from});
234
40.2k
}
235
236
void FakeUdpSocket::set_packet_source(PacketSource source)
237
104
{
238
104
    std::lock_guard<std::mutex> lock(mutex_);
239
104
    packet_source_ = std::move(source);
240
104
}
241
242
void FakeUdpSocket::set_recv_observer(RecvObserver observer)
243
25
{
244
25
    std::lock_guard<std::mutex> lock(mutex_);
245
25
    recv_observer_ = std::move(observer);
246
25
}
247
248
// --- FakeTcpSocket ---
249
250
FakeTcpSocket::FakeTcpSocket(NetworkUniverse &universe)
251
    : FakeSocket(universe, SOCK_STREAM)
252
123
{
253
123
    ipport_reset(&remote_addr_);
254
123
}
255
256
123
FakeTcpSocket::~FakeTcpSocket() { close_impl(); }
257
258
int FakeTcpSocket::close()
259
57
{
260
57
    std::lock_guard<std::mutex> lock(mutex_);
261
57
    if (state_ == ESTABLISHED || state_ == SYN_SENT || state_ == SYN_RECEIVED
262
57
        || state_ == CLOSE_WAIT) {
263
        // Send RST to peer
264
5
        Packet p{};
265
5
        p.from.ip = ip_;
266
5
        p.from.port = net_htons(local_port_);
267
5
        p.to = remote_addr_;
268
5
        p.is_tcp = true;
269
5
        p.tcp_flags = 0x04;  // RST
270
5
        universe_.send_packet(p);
271
5
    }
272
57
    close_impl();
273
57
    return 0;
274
57
}
275
276
void FakeTcpSocket::close_impl()
277
181
{
278
181
    if (local_port_ != 0) {
279
72
        universe_.unbind_tcp(ip_, local_port_, this);
280
72
        local_port_ = 0;
281
72
    }
282
181
    state_ = CLOSED;
283
181
}
284
285
int FakeTcpSocket::bind(const IP_Port *_Nonnull addr)
286
37
{
287
37
    std::lock_guard<std::mutex> lock(mutex_);
288
37
    if (local_port_ != 0)
289
0
        return -1;
290
291
37
    uint16_t port = addr->port;
292
37
    if (port == 0) {
293
0
        port = universe_.find_free_port(ip_);
294
37
    } else {
295
37
        port = net_ntohs(port);
296
37
    }
297
298
37
    if (universe_.bind_tcp(ip_, port, this)) {
299
37
        local_port_ = port;
300
37
        return 0;
301
37
    }
302
0
    errno = EADDRINUSE;
303
0
    return -1;
304
37
}
305
306
int FakeTcpSocket::listen(int backlog)
307
35
{
308
35
    std::lock_guard<std::mutex> lock(mutex_);
309
35
    state_ = LISTEN;
310
35
    backlog_ = backlog;
311
35
    return 0;
312
35
}
313
314
int FakeTcpSocket::connect(const IP_Port *_Nonnull addr)
315
21
{
316
21
    std::lock_guard<std::mutex> lock(mutex_);
317
21
    if (universe_.is_verbose()) {
318
12
        Ip_Ntoa ip_str, dest_str;
319
12
        net_ip_ntoa(&ip_, &ip_str);
320
12
        net_ip_ntoa(&addr->ip, &dest_str);
321
12
        std::cerr << "[FakeTcpSocket] connect from " << ip_str.buf << " to " << dest_str.buf << ":"
322
12
                  << net_ntohs(addr->port) << std::endl;
323
12
    }
324
325
21
    if (local_port_ == 0) {
326
        // Implicit bind
327
15
        uint16_t p = universe_.find_free_port(ip_);
328
15
        if (universe_.bind_tcp(ip_, p, this)) {
329
15
            local_port_ = p;
330
15
            if (universe_.is_verbose()) {
331
6
                std::cerr << "[FakeTcpSocket] implicit bind to port " << local_port_ << std::endl;
332
6
            }
333
15
        } else {
334
0
            errno = EADDRINUSE;
335
0
            return -1;
336
0
        }
337
15
    }
338
339
21
    remote_addr_ = *addr;
340
21
    state_ = SYN_SENT;
341
342
21
    Packet p{};
343
21
    p.from.ip = ip_;
344
21
    p.from.port = net_htons(local_port_);
345
21
    p.to = *addr;
346
21
    p.is_tcp = true;
347
21
    p.tcp_flags = 0x02;  // SYN
348
21
    p.seq = next_seq_;
349
350
21
    universe_.send_packet(p);
351
    // Non-blocking connect not fully simulated.
352
    // Real connect() blocks or returns EINPROGRESS.
353
    // For simplicity, we assume the test will pump events until connected.
354
21
    errno = EINPROGRESS;
355
21
    return -1;
356
21
}
357
358
std::unique_ptr<FakeSocket> FakeTcpSocket::accept(IP_Port *_Nullable addr)
359
19
{
360
19
    std::lock_guard<std::mutex> lock(mutex_);
361
19
    if (state_ != LISTEN) {
362
0
        errno = EINVAL;
363
0
        return nullptr;
364
0
    }
365
366
19
    auto it = std::find_if(pending_connections_.begin(), pending_connections_.end(),
367
19
        [](const std::unique_ptr<FakeTcpSocket> &s) { return s->state() == ESTABLISHED; });
368
369
19
    if (it == pending_connections_.end()) {
370
3
        errno = EWOULDBLOCK;
371
3
        return nullptr;
372
3
    }
373
374
16
    auto client = std::move(*it);
375
16
    pending_connections_.erase(it);
376
377
16
    if (addr) {
378
3
        *addr = client->remote_addr();
379
3
    }
380
16
    return client;
381
19
}
382
383
int FakeTcpSocket::send(const uint8_t *_Nonnull buf, std::size_t len)
384
22
{
385
22
    std::lock_guard<std::mutex> lock(mutex_);
386
22
    if (state_ != ESTABLISHED) {
387
5
        if (universe_.is_verbose()) {
388
0
            std::cerr << "[FakeTcpSocket] send failed: state " << state_ << " port " << local_port_
389
0
                      << std::endl;
390
0
        }
391
5
        if (state_ == SYN_SENT || state_ == SYN_RECEIVED) {
392
0
            errno = EWOULDBLOCK;
393
5
        } else {
394
5
            errno = ENOTCONN;
395
5
        }
396
5
        return -1;
397
5
    }
398
399
    // Wrap as TCP packet
400
17
    Packet p{};
401
    // Source
402
17
    p.from.ip = ip_;
403
17
    p.from.port = net_htons(local_port_);
404
17
    p.to = remote_addr_;
405
17
    p.data.assign(buf, buf + len);
406
17
    p.is_tcp = true;
407
17
    p.tcp_flags = 0x10;  // ACK (Data packets usually have ACK)
408
17
    p.seq = next_seq_;
409
17
    p.ack = last_ack_;
410
411
17
    next_seq_ += len;
412
17
    universe_.send_packet(p);
413
17
    return len;
414
22
}
415
416
int FakeTcpSocket::recv(uint8_t *_Nonnull buf, std::size_t len)
417
18
{
418
18
    std::lock_guard<std::mutex> lock(mutex_);
419
18
    if (recv_buffer_.empty()) {
420
4
        if (state_ == CLOSED || state_ == CLOSE_WAIT)
421
0
            return 0;  // EOF
422
4
        errno = EWOULDBLOCK;
423
4
        return -1;
424
4
    }
425
426
14
    std::size_t actual = std::min(len, recv_buffer_.size());
427
14
    if (universe_.is_verbose() && actual > 0) {
428
3
        char remote_ip_str[TOX_INET_ADDRSTRLEN];
429
3
        ip_parse_addr(&remote_addr_.ip, remote_ip_str, sizeof(remote_ip_str));
430
3
        std::cerr << "[FakeTcpSocket] Port " << local_port_ << " (Peer: " << remote_ip_str << ":"
431
3
                  << net_ntohs(remote_addr_.port) << ") recv requested " << len << " got " << actual
432
3
                  << " (remaining " << recv_buffer_.size() - actual << ")" << std::endl;
433
3
    }
434
575
    for (std::size_t i = 0; i < actual; ++i) {
435
561
        buf[i] = recv_buffer_.front();
436
561
        recv_buffer_.pop_front();
437
561
    }
438
14
    return actual;
439
18
}
440
441
std::size_t FakeTcpSocket::recv_buffer_size()
442
44
{
443
44
    std::lock_guard<std::mutex> lock(mutex_);
444
44
    return recv_buffer_.size();
445
44
}
446
447
bool FakeTcpSocket::is_readable()
448
1
{
449
1
    std::lock_guard<std::mutex> lock(mutex_);
450
1
    if (state_ == LISTEN) {
451
1
        return std::any_of(pending_connections_.begin(), pending_connections_.end(),
452
1
            [](const std::unique_ptr<FakeTcpSocket> &s) { return s->state() == ESTABLISHED; });
453
1
    }
454
0
    return !recv_buffer_.empty() || state_ == CLOSED || state_ == CLOSE_WAIT;
455
1
}
456
457
bool FakeTcpSocket::is_writable()
458
0
{
459
0
    std::lock_guard<std::mutex> lock(mutex_);
460
0
    return state_ == ESTABLISHED;
461
0
}
462
463
int FakeTcpSocket::sendto(
464
    const uint8_t *_Nonnull buf, std::size_t len, const IP_Port *_Nonnull addr)
465
0
{
466
0
    errno = EOPNOTSUPP;
467
0
    return -1;
468
0
}
469
int FakeTcpSocket::recvfrom(uint8_t *_Nonnull buf, std::size_t len, IP_Port *_Nonnull addr)
470
0
{
471
0
    errno = EOPNOTSUPP;
472
0
    return -1;
473
0
}
474
475
int FakeTcpSocket::getsockopt(
476
    int level, int optname, void *_Nonnull optval, std::size_t *_Nonnull optlen)
477
15
{
478
15
    if (universe_.is_verbose()) {
479
0
        std::cerr << "[FakeTcpSocket] getsockopt level=" << level << " optname=" << optname
480
0
                  << " state=" << state_ << std::endl;
481
0
    }
482
15
    if (level == SOL_SOCKET && optname == SO_ERROR) {
483
0
        int error = 0;
484
0
        if (state_ == SYN_SENT || state_ == SYN_RECEIVED) {
485
0
            error = EINPROGRESS;
486
0
        } else if (state_ == CLOSED) {
487
0
            error = ECONNREFUSED;
488
0
        }
489
490
0
        if (*optlen >= sizeof(int)) {
491
0
            *static_cast<int *>(optval) = error;
492
0
            *optlen = sizeof(int);
493
0
        }
494
0
        if (universe_.is_verbose()) {
495
0
            std::cerr << "[FakeTcpSocket] getsockopt SO_ERROR returning error=" << error
496
0
                      << std::endl;
497
0
        }
498
0
        return 0;
499
0
    }
500
15
    return 0;
501
15
}
502
503
bool FakeTcpSocket::handle_packet(const Packet &p)
504
82
{
505
82
    std::lock_guard<std::mutex> lock(mutex_);
506
82
    if (universe_.is_verbose()) {
507
44
        char remote_ip_str[TOX_INET_ADDRSTRLEN];
508
44
        ip_parse_addr(&remote_addr_.ip, remote_ip_str, sizeof(remote_ip_str));
509
44
        std::cerr << "Handle Packet: Port " << local_port_ << " (Peer: " << remote_ip_str << ":"
510
44
                  << net_ntohs(remote_addr_.port) << ") Flags " << TcpFlags{p.tcp_flags}
511
44
                  << " State " << state_ << " From " << net_ntohs(p.from.port) << std::endl;
512
44
    }
513
514
82
    if (state_ != LISTEN) {
515
        // Filter packets not from our peer
516
63
        bool port_match = net_ntohs(p.from.port) == net_ntohs(remote_addr_.port);
517
63
        bool ip_match = ip_equal(&p.from.ip, &remote_addr_.ip)
518
63
            || (is_loopback(p.from.ip) && ip_equal(&remote_addr_.ip, &ip_))
519
63
            || (is_loopback(remote_addr_.ip) && ip_equal(&p.from.ip, &ip_));
520
521
63
        if (!port_match || !ip_match) {
522
0
            return false;
523
0
        }
524
525
63
        if (p.tcp_flags & 0x04) {  // RST
526
1
            close_impl();
527
1
            return true;
528
1
        }
529
63
    }
530
531
81
    switch (state_) {
532
19
    case LISTEN:
533
19
        if (p.tcp_flags & 0x02) {  // SYN
534
            // Check backlog
535
19
            std::size_t effective_backlog
536
19
                = std::clamp(static_cast<std::size_t>(backlog_), std::size_t{1}, kMaxBacklog);
537
19
            if (pending_connections_.size() >= effective_backlog) {
538
1
                return false;  // Drop packet
539
1
            }
540
541
            // Check for duplicate SYN from same peer
542
18
            for (const auto &pending : pending_connections_) {
543
3
                if (ipport_equal(&p.from, &pending->remote_addr_)) {
544
1
                    return true;
545
1
                }
546
3
            }
547
548
            // Create new socket for connection
549
17
            auto new_sock = std::make_unique<FakeTcpSocket>(universe_);
550
551
17
            new_sock->state_ = SYN_RECEIVED;
552
17
            new_sock->remote_addr_ = p.from;
553
17
            new_sock->local_port_ = local_port_;
554
17
            new_sock->set_ip(ip_);  // Inherit IP from listening socket
555
17
            new_sock->last_ack_ = p.seq + 1;
556
17
            new_sock->next_seq_ = 1000;  // Random ISN
557
558
17
            universe_.bind_tcp(ip_, local_port_, new_sock.get());
559
560
            // Send SYN-ACK
561
17
            Packet resp{};
562
17
            resp.from = p.to;
563
17
            resp.to = p.from;
564
17
            resp.is_tcp = true;
565
17
            resp.tcp_flags = 0x12;  // SYN | ACK
566
17
            resp.seq = new_sock->next_seq_++;
567
17
            resp.ack = new_sock->last_ack_;
568
569
17
            universe_.send_packet(resp);
570
571
            // Add to pending, but it's still SYN_RECEIVED
572
17
            pending_connections_.push_back(std::move(new_sock));
573
17
            return true;
574
18
        }
575
0
        return false;
576
577
19
    case SYN_SENT:
578
19
        if ((p.tcp_flags & 0x12) == 0x12) {  // SYN | ACK
579
15
            state_ = ESTABLISHED;
580
15
            last_ack_ = p.seq + 1;
581
15
            next_seq_++;  // Consumer SYN
582
583
            // Send ACK
584
15
            Packet ack{};
585
15
            ack.from = p.to;
586
15
            ack.to = p.from;
587
15
            ack.is_tcp = true;
588
15
            ack.tcp_flags = 0x10;  // ACK
589
15
            ack.seq = next_seq_;
590
15
            ack.ack = last_ack_;
591
15
            universe_.send_packet(ack);
592
            // Fall through to handle data if any
593
15
        } else if (p.tcp_flags & 0x02) {  // SYN (Simultaneous Open)
594
4
            state_ = SYN_RECEIVED;
595
4
            last_ack_ = p.seq + 1;
596
597
            // Send SYN-ACK
598
4
            Packet resp{};
599
4
            resp.from = p.to;
600
4
            resp.to = p.from;
601
4
            resp.is_tcp = true;
602
4
            resp.tcp_flags = 0x12;  // SYN | ACK
603
4
            resp.seq = next_seq_++;
604
4
            resp.ack = last_ack_;
605
4
            universe_.send_packet(resp);
606
4
            return true;
607
4
        } else {
608
0
            return false;
609
0
        }
610
15
        break;
611
612
22
    case SYN_RECEIVED:
613
22
        if (p.tcp_flags & 0x10) {  // ACK
614
21
            state_ = ESTABLISHED;
615
            // Fall through to handle data if any
616
21
        } else {
617
1
            return false;
618
1
        }
619
21
        break;
620
621
21
    case ESTABLISHED:
622
21
        break;
623
624
0
    case CLOSED:
625
0
    case CLOSE_WAIT:
626
0
    default:
627
0
        return false;
628
81
    }
629
630
57
    if (state_ == ESTABLISHED) {
631
57
        if (p.tcp_flags & 0x01) {  // FIN
632
0
            state_ = CLOSE_WAIT;
633
            // Send ACK
634
0
            Packet ack{};
635
0
            ack.from = p.to;
636
0
            ack.to = p.from;
637
0
            ack.is_tcp = true;
638
0
            ack.tcp_flags = 0x10;  // ACK
639
0
            ack.seq = next_seq_;
640
0
            ack.ack = p.seq + 1;  // Consume FIN
641
0
            universe_.send_packet(ack);
642
0
            return true;
643
57
        } else {
644
57
            if (!p.data.empty()) {
645
21
                if (recv_buffer_.size() + p.data.size() <= kMaxBufferSize) {
646
20
                    if (universe_.is_verbose()) {
647
8
                        char remote_ip_str[TOX_INET_ADDRSTRLEN];
648
8
                        ip_parse_addr(&remote_addr_.ip, remote_ip_str, sizeof(remote_ip_str));
649
8
                        std::cerr << "[FakeTcpSocket] Port " << local_port_
650
8
                                  << " (Peer: " << remote_ip_str << ":"
651
8
                                  << net_ntohs(remote_addr_.port) << ") adding " << p.data.size()
652
8
                                  << " bytes to buffer (currently " << recv_buffer_.size() << ")"
653
8
                                  << std::endl;
654
8
                    }
655
20
                    recv_buffer_.insert(recv_buffer_.end(), p.data.begin(), p.data.end());
656
20
                    last_ack_ += p.data.size();
657
20
                } else {
658
1
                    if (universe_.is_verbose()) {
659
0
                        std::cerr << "[FakeTcpSocket] Port " << local_port_
660
0
                                  << " Buffer full, dropping " << p.data.size() << " bytes"
661
0
                                  << std::endl;
662
0
                    }
663
1
                }
664
21
            }
665
57
            return true;
666
57
        }
667
57
    }
668
0
    return false;
669
57
}
670
671
std::unique_ptr<FakeTcpSocket> FakeTcpSocket::create_connected(
672
    NetworkUniverse &universe, const IP_Port &remote, uint16_t local_port)
673
3
{
674
3
    auto s = std::make_unique<FakeTcpSocket>(universe);
675
3
    s->state_ = ESTABLISHED;
676
3
    s->remote_addr_ = remote;
677
3
    s->local_port_ = local_port;
678
3
    return s;
679
3
}
680
681
std::ostream &operator<<(std::ostream &os, FakeTcpSocket::State state)
682
44
{
683
44
    switch (state) {
684
0
    case FakeTcpSocket::CLOSED:
685
0
        return os << "CLOSED";
686
10
    case FakeTcpSocket::LISTEN:
687
10
        return os << "LISTEN";
688
11
    case FakeTcpSocket::SYN_SENT:
689
11
        return os << "SYN_SENT";
690
14
    case FakeTcpSocket::SYN_RECEIVED:
691
14
        return os << "SYN_RECEIVED";
692
9
    case FakeTcpSocket::ESTABLISHED:
693
9
        return os << "ESTABLISHED";
694
0
    case FakeTcpSocket::CLOSE_WAIT:
695
0
        return os << "CLOSE_WAIT";
696
44
    }
697
0
    return os << "UNKNOWN(" << static_cast<int>(state) << ")";
698
44
}
699
700
}  // namespace tox::test