summaryrefslogtreecommitdiff
path: root/protocols/Tox/libtox/src/toxcore/net_profile.c
blob: 1d700bdb85b17c6d532637c829827ef1687c680d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/* SPDX-License-Identifier: GPL-3.0-or-later
 * Copyright © 2023-2025 The TokTok team.
 */

/**
 * Functions for the network profile.
 */

#include "net_profile.h"

#include <stdint.h>

#include "attributes.h"
#include "logger.h"
#include "mem.h"

#include "ccompat.h"

#define NETPROF_TCP_DATA_PACKET_ID 0x10

typedef struct Net_Profile {
    uint64_t packets_recv[NET_PROF_MAX_PACKET_IDS];
    uint64_t packets_sent[NET_PROF_MAX_PACKET_IDS];

    uint64_t total_packets_recv;
    uint64_t total_packets_sent;

    uint64_t bytes_recv[NET_PROF_MAX_PACKET_IDS];
    uint64_t bytes_sent[NET_PROF_MAX_PACKET_IDS];

    uint64_t total_bytes_recv;
    uint64_t total_bytes_sent;
} Net_Profile;

/** Returns the number of sent or received packets for all ID's between `start_id` and `end_id`. */
nullable(1)
static uint64_t netprof_get_packet_count_id_range(const Net_Profile *profile, uint8_t start_id, uint8_t end_id,
        Packet_Direction dir)
{
    if (profile == nullptr) {
        return 0;
    }

    const uint64_t *arr = dir == PACKET_DIRECTION_SEND ? profile->packets_sent : profile->packets_recv;
    uint64_t count = 0;

    for (size_t i = start_id; i <= end_id; ++i) {
        count += arr[i];
    }

    return count;
}

/** Returns the number of sent or received bytes for all ID's between `start_id` and `end_id`. */
nullable(1)
static uint64_t netprof_get_bytes_id_range(const Net_Profile *profile, uint8_t start_id, uint8_t end_id,
        Packet_Direction dir)
{
    if (profile == nullptr) {
        return 0;
    }

    const uint64_t *arr = dir == PACKET_DIRECTION_SEND ? profile->bytes_sent : profile->bytes_recv;
    uint64_t bytes = 0;

    for (size_t i = start_id; i <= end_id; ++i) {
        bytes += arr[i];
    }

    return bytes;
}

void netprof_record_packet(Net_Profile *profile, uint8_t id, size_t length, Packet_Direction dir)
{
    if (profile == nullptr) {
        return;
    }

    if (dir == PACKET_DIRECTION_SEND) {
        ++profile->total_packets_sent;
        ++profile->packets_sent[id];

        profile->total_bytes_sent += length;
        profile->bytes_sent[id] += length;
    } else {
        ++profile->total_packets_recv;
        ++profile->packets_recv[id];

        profile->total_bytes_recv += length;
        profile->bytes_recv[id] += length;
    }
}

uint64_t netprof_get_packet_count_id(const Net_Profile *profile, uint8_t id, Packet_Direction dir)
{
    if (profile == nullptr) {
        return 0;
    }

    // Special case - TCP data packets can have any ID between 0x10 and 0xff
    if (id == NETPROF_TCP_DATA_PACKET_ID) {
        return netprof_get_packet_count_id_range(profile, id, UINT8_MAX, dir);
    }

    return dir == PACKET_DIRECTION_SEND ? profile->packets_sent[id] : profile->packets_recv[id];
}

uint64_t netprof_get_packet_count_total(const Net_Profile *profile, Packet_Direction dir)
{
    if (profile == nullptr) {
        return 0;
    }

    return dir == PACKET_DIRECTION_SEND ? profile->total_packets_sent : profile->total_packets_recv;
}

uint64_t netprof_get_bytes_id(const Net_Profile *profile, uint8_t id, Packet_Direction dir)
{
    if (profile == nullptr) {
        return 0;
    }

    // Special case - TCP data packets can have any ID between 0x10 and 0xff
    if (id == NETPROF_TCP_DATA_PACKET_ID) {
        return netprof_get_bytes_id_range(profile, id, 0xff, dir);
    }

    return dir == PACKET_DIRECTION_SEND ? profile->bytes_sent[id] : profile->bytes_recv[id];
}

uint64_t netprof_get_bytes_total(const Net_Profile *profile, Packet_Direction dir)
{
    if (profile == nullptr) {
        return 0;
    }

    return dir == PACKET_DIRECTION_SEND ? profile->total_bytes_sent : profile->total_bytes_recv;
}

Net_Profile *netprof_new(const Logger *log, const Memory *mem)
{
    Net_Profile *np = (Net_Profile *)mem_alloc(mem, sizeof(Net_Profile));

    if (np == nullptr) {
        LOGGER_ERROR(log, "failed to allocate memory for net profiler");
        return nullptr;
    }

    return np;
}

void netprof_kill(const Memory *mem, Net_Profile *net_profile)
{
    if (net_profile != nullptr) {
        mem_delete(mem, net_profile);
    }
}