/work/toxcore/net_profile.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* SPDX-License-Identifier: GPL-3.0-or-later |
2 | | * Copyright © 2023-2025 The TokTok team. |
3 | | */ |
4 | | |
5 | | /** |
6 | | * Functions for the network profile. |
7 | | */ |
8 | | |
9 | | #include "net_profile.h" |
10 | | |
11 | | #include <stdint.h> |
12 | | |
13 | | #include "attributes.h" |
14 | | #include "logger.h" |
15 | | #include "mem.h" |
16 | | |
17 | | #include "ccompat.h" |
18 | | |
19 | 1.02k | #define NETPROF_TCP_DATA_PACKET_ID 0x10 |
20 | | |
21 | | typedef struct Net_Profile { |
22 | | uint64_t packets_recv[NET_PROF_MAX_PACKET_IDS]; |
23 | | uint64_t packets_sent[NET_PROF_MAX_PACKET_IDS]; |
24 | | |
25 | | uint64_t total_packets_recv; |
26 | | uint64_t total_packets_sent; |
27 | | |
28 | | uint64_t bytes_recv[NET_PROF_MAX_PACKET_IDS]; |
29 | | uint64_t bytes_sent[NET_PROF_MAX_PACKET_IDS]; |
30 | | |
31 | | uint64_t total_bytes_recv; |
32 | | uint64_t total_bytes_sent; |
33 | | } Net_Profile; |
34 | | |
35 | | /** Returns the number of sent or received packets for all ID's between `start_id` and `end_id`. */ |
36 | | static uint64_t netprof_get_packet_count_id_range(const Net_Profile *_Nullable profile, uint8_t start_id, uint8_t end_id, |
37 | | Packet_Direction dir) |
38 | 1 | { |
39 | 1 | if (profile == nullptr) { |
40 | 0 | return 0; |
41 | 0 | } |
42 | | |
43 | 1 | const uint64_t *arr = dir == PACKET_DIRECTION_SEND ? profile->packets_sent : profile->packets_recv; |
44 | 1 | uint64_t count = 0; |
45 | | |
46 | 241 | for (size_t i = start_id; i <= end_id; ++i) { |
47 | 240 | count += arr[i]; |
48 | 240 | } |
49 | | |
50 | 1 | return count; |
51 | 1 | } |
52 | | |
53 | | /** Returns the number of sent or received bytes for all ID's between `start_id` and `end_id`. */ |
54 | | static uint64_t netprof_get_bytes_id_range(const Net_Profile *_Nullable profile, uint8_t start_id, uint8_t end_id, |
55 | | Packet_Direction dir) |
56 | 3 | { |
57 | 3 | if (profile == nullptr) { |
58 | 0 | return 0; |
59 | 0 | } |
60 | | |
61 | 3 | const uint64_t *arr = dir == PACKET_DIRECTION_SEND ? profile->bytes_sent : profile->bytes_recv; |
62 | 3 | uint64_t bytes = 0; |
63 | | |
64 | 723 | for (size_t i = start_id; i <= end_id; ++i) { |
65 | 720 | bytes += arr[i]; |
66 | 720 | } |
67 | | |
68 | 3 | return bytes; |
69 | 3 | } |
70 | | |
71 | | void netprof_record_packet(Net_Profile *profile, uint8_t id, size_t length, Packet_Direction dir) |
72 | 2.05M | { |
73 | 2.05M | if (profile == nullptr) { |
74 | 118 | return; |
75 | 118 | } |
76 | | |
77 | 2.05M | if (dir == PACKET_DIRECTION_SEND) { |
78 | 1.08M | ++profile->total_packets_sent; |
79 | 1.08M | ++profile->packets_sent[id]; |
80 | | |
81 | 1.08M | profile->total_bytes_sent += length; |
82 | 1.08M | profile->bytes_sent[id] += length; |
83 | 1.08M | } else { |
84 | 961k | ++profile->total_packets_recv; |
85 | 961k | ++profile->packets_recv[id]; |
86 | | |
87 | 961k | profile->total_bytes_recv += length; |
88 | 961k | profile->bytes_recv[id] += length; |
89 | 961k | } |
90 | 2.05M | } |
91 | | |
92 | | uint64_t netprof_get_packet_count_id(const Net_Profile *profile, uint8_t id, Packet_Direction dir) |
93 | 511 | { |
94 | 511 | if (profile == nullptr) { |
95 | 0 | return 0; |
96 | 0 | } |
97 | | |
98 | | // Special case - TCP data packets can have any ID between 0x10 and 0xff |
99 | 511 | if (id == NETPROF_TCP_DATA_PACKET_ID) { |
100 | 1 | return netprof_get_packet_count_id_range(profile, id, UINT8_MAX, dir); |
101 | 1 | } |
102 | | |
103 | 510 | return dir == PACKET_DIRECTION_SEND ? profile->packets_sent[id] : profile->packets_recv[id]; |
104 | 511 | } |
105 | | |
106 | | uint64_t netprof_get_packet_count_total(const Net_Profile *profile, Packet_Direction dir) |
107 | 6 | { |
108 | 6 | if (profile == nullptr) { |
109 | 2 | return 0; |
110 | 2 | } |
111 | | |
112 | 4 | return dir == PACKET_DIRECTION_SEND ? profile->total_packets_sent : profile->total_packets_recv; |
113 | 6 | } |
114 | | |
115 | | uint64_t netprof_get_bytes_id(const Net_Profile *profile, uint8_t id, Packet_Direction dir) |
116 | 513 | { |
117 | 513 | if (profile == nullptr) { |
118 | 0 | return 0; |
119 | 0 | } |
120 | | |
121 | | // Special case - TCP data packets can have any ID between 0x10 and 0xff |
122 | 513 | if (id == NETPROF_TCP_DATA_PACKET_ID) { |
123 | 3 | return netprof_get_bytes_id_range(profile, id, 0xff, dir); |
124 | 3 | } |
125 | | |
126 | 510 | return dir == PACKET_DIRECTION_SEND ? profile->bytes_sent[id] : profile->bytes_recv[id]; |
127 | 513 | } |
128 | | |
129 | | uint64_t netprof_get_bytes_total(const Net_Profile *profile, Packet_Direction dir) |
130 | 6 | { |
131 | 6 | if (profile == nullptr) { |
132 | 2 | return 0; |
133 | 2 | } |
134 | | |
135 | 4 | return dir == PACKET_DIRECTION_SEND ? profile->total_bytes_sent : profile->total_bytes_recv; |
136 | 6 | } |
137 | | |
138 | | Net_Profile *netprof_new(const Logger *log, const Memory *mem) |
139 | 6.18k | { |
140 | 6.18k | Net_Profile *np = (Net_Profile *)mem_alloc(mem, sizeof(Net_Profile)); |
141 | | |
142 | 6.18k | if (np == nullptr) { |
143 | 29 | LOGGER_ERROR(log, "failed to allocate memory for net profiler"); |
144 | 29 | return nullptr; |
145 | 29 | } |
146 | | |
147 | 6.15k | return np; |
148 | 6.18k | } |
149 | | |
150 | | void netprof_kill(const Memory *mem, Net_Profile *net_profile) |
151 | 4.46k | { |
152 | 4.46k | if (net_profile != nullptr) { |
153 | 4.40k | mem_delete(mem, net_profile); |
154 | 4.40k | } |
155 | 4.46k | } |