/work/testing/support/doubles/network_universe.hh
Line | Count | Source (jump to first uncovered line) |
1 | | #ifndef C_TOXCORE_TESTING_SUPPORT_DOUBLES_NETWORK_UNIVERSE_H |
2 | | #define C_TOXCORE_TESTING_SUPPORT_DOUBLES_NETWORK_UNIVERSE_H |
3 | | |
4 | | #include <cstdint> |
5 | | #include <functional> |
6 | | #include <map> |
7 | | #include <memory> |
8 | | #include <mutex> |
9 | | #include <queue> |
10 | | #include <vector> |
11 | | |
12 | | #include "../../../toxcore/attributes.h" |
13 | | #include "../../../toxcore/network.h" |
14 | | |
15 | | namespace tox::test { |
16 | | |
17 | | class FakeUdpSocket; |
18 | | class FakeTcpSocket; |
19 | | |
20 | | struct TcpFlags { |
21 | | uint8_t value; |
22 | | }; |
23 | | std::ostream &operator<<(std::ostream &os, TcpFlags flags); |
24 | | |
25 | | struct Packet { |
26 | | IP_Port from; |
27 | | IP_Port to; |
28 | | std::vector<uint8_t> data; |
29 | | uint64_t delivery_time; |
30 | | uint64_t sequence_number = 0; |
31 | | bool is_tcp = false; |
32 | | |
33 | | // TCP Simulation Fields |
34 | | uint8_t tcp_flags = 0; // 0x01=FIN, 0x02=SYN, 0x10=ACK |
35 | | uint32_t seq = 0; |
36 | | uint32_t ack = 0; |
37 | | |
38 | | bool operator>(const Packet &other) const |
39 | 336k | { |
40 | 336k | if (delivery_time != other.delivery_time) { |
41 | 0 | return delivery_time > other.delivery_time; |
42 | 0 | } |
43 | 336k | return sequence_number > other.sequence_number; |
44 | 336k | } |
45 | | }; |
46 | | |
47 | | bool is_loopback(const IP &ip); |
48 | | |
49 | | /** |
50 | | * @brief The God Object for the network simulation. |
51 | | * Manages routing, latency, and connectivity. |
52 | | */ |
53 | | class NetworkUniverse { |
54 | | public: |
55 | | using PacketFilter = std::function<bool(Packet &)>; |
56 | | using PacketSink = std::function<void(const Packet &)>; |
57 | | |
58 | | NetworkUniverse(); |
59 | | ~NetworkUniverse(); |
60 | | |
61 | | // Registration |
62 | | // Returns true if binding succeeded |
63 | | bool bind_udp(IP ip, uint16_t port, FakeUdpSocket *_Nonnull socket); |
64 | | void unbind_udp(IP ip, uint16_t port); |
65 | | |
66 | | bool bind_tcp(IP ip, uint16_t port, FakeTcpSocket *_Nonnull socket); |
67 | | void unbind_tcp(IP ip, uint16_t port, FakeTcpSocket *_Nonnull socket); |
68 | | |
69 | | // Routing |
70 | | void send_packet(Packet p); |
71 | | |
72 | | // Simulation |
73 | | void process_events(uint64_t current_time_ms); |
74 | | void set_latency(uint64_t ms); |
75 | | void set_verbose(bool verbose); |
76 | | bool is_verbose() const; |
77 | | void add_filter(PacketFilter filter); |
78 | | void add_observer(PacketSink sink); |
79 | | |
80 | | // Helpers |
81 | | // Finds a free port starting from 'start' |
82 | | uint16_t find_free_port(IP ip, uint16_t start = 33445); |
83 | | |
84 | | struct IP_Port_Key { |
85 | | IP ip; |
86 | | uint16_t port; |
87 | | bool operator<(const IP_Port_Key &other) const; |
88 | | }; |
89 | | |
90 | | private: |
91 | | std::map<IP_Port_Key, FakeUdpSocket *> udp_bindings_; |
92 | | std::multimap<IP_Port_Key, FakeTcpSocket *> tcp_bindings_; |
93 | | |
94 | | std::priority_queue<Packet, std::vector<Packet>, std::greater<Packet>> event_queue_; |
95 | | std::vector<PacketFilter> filters_; |
96 | | std::vector<PacketSink> observers_; |
97 | | |
98 | | uint64_t global_latency_ms_ = 0; |
99 | | uint64_t next_packet_id_ = 0; |
100 | | bool verbose_ = false; |
101 | | std::recursive_mutex mutex_; |
102 | | }; |
103 | | |
104 | | } // namespace tox::test |
105 | | |
106 | | #endif // C_TOXCORE_TESTING_SUPPORT_DOUBLES_NETWORK_UNIVERSE_H |