Skip to content

Commit efc741f

Browse files
authored
Merge pull request #258 from ayushsingh658/feature/cumulative-traffic-stats
Feature/cumulative traffic stats
2 parents e62f153 + 0bcc4f1 commit efc741f

4 files changed

Lines changed: 275 additions & 0 deletions

File tree

src/retroshare/rsconfig.h

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,48 @@ struct RSTrafficClue : RsSerializable
222222
}
223223
};
224224

225+
/*!
226+
* \brief Cumulative traffic statistics for tracking all-time data transfer
227+
* Used to persist and display per-peer and per-service data usage
228+
*/
229+
struct RsCumulativeTrafficStats : RsSerializable
230+
{
231+
uint64_t bytesIn; //< Total bytes received
232+
uint64_t bytesOut; //< Total bytes sent
233+
uint32_t countIn; //< Number of incoming packets
234+
uint32_t countOut; //< Number of outgoing packets
235+
rstime_t firstSeen; //< Timestamp of first recorded traffic
236+
rstime_t lastSeen; //< Timestamp of most recent traffic
237+
238+
RsCumulativeTrafficStats() :
239+
bytesIn(0), bytesOut(0), countIn(0), countOut(0),
240+
firstSeen(0), lastSeen(0) {}
241+
242+
RsCumulativeTrafficStats& operator+=(const RsCumulativeTrafficStats& other) {
243+
bytesIn += other.bytesIn;
244+
bytesOut += other.bytesOut;
245+
countIn += other.countIn;
246+
countOut += other.countOut;
247+
if (firstSeen == 0 || (other.firstSeen != 0 && other.firstSeen < firstSeen))
248+
firstSeen = other.firstSeen;
249+
if (other.lastSeen > lastSeen)
250+
lastSeen = other.lastSeen;
251+
return *this;
252+
}
253+
254+
void clear() { bytesIn = bytesOut = countIn = countOut = 0; firstSeen = lastSeen = 0; }
255+
256+
// RsSerializable interface
257+
void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext &ctx) {
258+
RS_SERIAL_PROCESS(bytesIn);
259+
RS_SERIAL_PROCESS(bytesOut);
260+
RS_SERIAL_PROCESS(countIn);
261+
RS_SERIAL_PROCESS(countOut);
262+
RS_SERIAL_PROCESS(firstSeen);
263+
RS_SERIAL_PROCESS(lastSeen);
264+
}
265+
};
266+
225267
struct RsConfigNetStatus : RsSerializable
226268
{
227269
RsConfigNetStatus() : netLocalOk(true)
@@ -348,6 +390,39 @@ class RsServerConfig
348390
*/
349391
virtual int getTrafficInfo(std::list<RSTrafficClue>& out_lst,std::list<RSTrafficClue>& in_lst) = 0 ;
350392

393+
/**
394+
* @brief getCumulativeTrafficByPeer returns cumulative traffic stats grouped by peer
395+
* @jsonapi{development}
396+
* @param[out] stats map of peer ID to cumulative traffic stats
397+
* @return returns true on success
398+
*/
399+
virtual bool getCumulativeTrafficByPeer(std::map<RsPeerId, RsCumulativeTrafficStats>& stats) = 0;
400+
401+
/**
402+
* @brief getCumulativeTrafficByService returns cumulative traffic stats grouped by service
403+
* @jsonapi{development}
404+
* @param[out] stats map of service ID to cumulative traffic stats
405+
* @return returns true on success
406+
*/
407+
virtual bool getCumulativeTrafficByService(std::map<uint16_t, RsCumulativeTrafficStats>& stats) = 0;
408+
409+
/**
410+
* @brief clearCumulativeTraffic clears all cumulative traffic statistics
411+
* @jsonapi{development}
412+
* @param[in] clearPeerStats if true, clears per-peer stats
413+
* @param[in] clearServiceStats if true, clears per-service stats
414+
* @return returns true on success
415+
*/
416+
virtual bool clearCumulativeTraffic(bool clearPeerStats = true, bool clearServiceStats = true) = 0;
417+
418+
/**
419+
* @brief getTotalCumulativeTraffic returns the total cumulative traffic across all peers/services
420+
* @jsonapi{development}
421+
* @param[out] stats total cumulative traffic stats
422+
* @return returns true on success
423+
*/
424+
virtual bool getTotalCumulativeTraffic(RsCumulativeTrafficStats& stats) = 0;
425+
351426
/* From RsInit */
352427

353428
// NOT IMPLEMENTED YET!

src/rsitems/rstrafficstatsitems.h

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/*******************************************************************************
2+
* libretroshare/src/rsitems: rstrafficstatsitems.h *
3+
* *
4+
* libretroshare: retroshare core library *
5+
* *
6+
* Copyright (C) 2024 *
7+
* *
8+
* This program is free software: you can redistribute it and/or modify *
9+
* it under the terms of the GNU Lesser General Public License as *
10+
* published by the Free Software Foundation, either version 3 of the *
11+
* License, or (at your option) any later version. *
12+
* *
13+
* This program is distributed in the hope that it will be useful, *
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
15+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16+
* GNU Lesser General Public License for more details. *
17+
* *
18+
* You should have received a copy of the GNU Lesser General Public License *
19+
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
20+
* *
21+
*******************************************************************************/
22+
#ifndef RS_TRAFFIC_STATS_ITEMS_H
23+
#define RS_TRAFFIC_STATS_ITEMS_H
24+
25+
#include <map>
26+
27+
#include "rsitems/rsitem.h"
28+
#include "rsitems/rsserviceids.h"
29+
#include "retroshare/rsconfig.h"
30+
#include "serialiser/rsserializer.h"
31+
#include "serialiser/rstypeserializer.h"
32+
33+
// Use BANDWIDTH_CONTROL service type for config items
34+
const uint8_t RS_PKT_SUBTYPE_TRAFFIC_STATS_ITEM = 0x10;
35+
36+
/**************************************************************************/
37+
38+
class RsTrafficStatsConfigItem : public RsItem
39+
{
40+
public:
41+
RsTrafficStatsConfigItem() : RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_BWCTRL, RS_PKT_SUBTYPE_TRAFFIC_STATS_ITEM)
42+
{}
43+
44+
virtual ~RsTrafficStatsConfigItem() {}
45+
46+
virtual void clear()
47+
{
48+
peerStats.clear();
49+
serviceStats.clear();
50+
}
51+
52+
void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx)
53+
{
54+
RsTypeSerializer::serial_process(j, ctx, peerStats, "peerStats");
55+
RsTypeSerializer::serial_process(j, ctx, serviceStats, "serviceStats");
56+
}
57+
58+
std::map<RsPeerId, RsCumulativeTrafficStats> peerStats;
59+
std::map<uint16_t, RsCumulativeTrafficStats> serviceStats;
60+
};
61+
62+
class RsTrafficStatsSerialiser : public RsServiceSerializer
63+
{
64+
public:
65+
RsTrafficStatsSerialiser() : RsServiceSerializer(RS_SERVICE_TYPE_BWCTRL) {}
66+
virtual ~RsTrafficStatsSerialiser() {}
67+
68+
RsItem *create_item(uint16_t service, uint8_t item_sub_id) const
69+
{
70+
if (service != RS_SERVICE_TYPE_BWCTRL)
71+
return nullptr;
72+
73+
switch (item_sub_id)
74+
{
75+
case RS_PKT_SUBTYPE_TRAFFIC_STATS_ITEM:
76+
return new RsTrafficStatsConfigItem();
77+
default:
78+
return nullptr;
79+
}
80+
}
81+
};
82+
83+
/**************************************************************************/
84+
85+
#endif /* RS_TRAFFIC_STATS_ITEMS_H */

src/rsserver/p3serverconfig.cc

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <retroshare/rsturtle.h>
2323
#include "rsserver/p3serverconfig.h"
2424
#include "services/p3bwctrl.h"
25+
#include "rsitems/rstrafficstatsitems.h"
2526

2627
#include "pqi/authgpg.h"
2728
#include "pqi/authssl.h"
@@ -184,6 +185,108 @@ int p3ServerConfig::getTrafficInfo(std::list<RSTrafficClue>& out_lst,std::list<R
184185
return 0 ;
185186
}
186187

188+
bool p3ServerConfig::getCumulativeTrafficByPeer(std::map<RsPeerId, RsCumulativeTrafficStats>& stats)
189+
{
190+
RsStackMutex stack(configMtx);
191+
192+
// First, update cumulative stats from current traffic clues
193+
std::list<RSTrafficClue> out_lst, in_lst;
194+
if (rsBandwidthControl)
195+
{
196+
rsBandwidthControl->ExtractTrafficInfo(out_lst, in_lst);
197+
198+
rstime_t now = time(nullptr);
199+
200+
// Accumulate outgoing traffic
201+
for (const auto& clue : out_lst)
202+
{
203+
auto& peerStats = mCumulativeTrafficByPeer[clue.peer_id];
204+
peerStats.bytesOut += clue.size;
205+
peerStats.countOut += clue.count;
206+
if (peerStats.firstSeen == 0) peerStats.firstSeen = now;
207+
peerStats.lastSeen = now;
208+
}
209+
210+
// Accumulate incoming traffic
211+
for (const auto& clue : in_lst)
212+
{
213+
auto& peerStats = mCumulativeTrafficByPeer[clue.peer_id];
214+
peerStats.bytesIn += clue.size;
215+
peerStats.countIn += clue.count;
216+
if (peerStats.firstSeen == 0) peerStats.firstSeen = now;
217+
peerStats.lastSeen = now;
218+
}
219+
}
220+
221+
stats = mCumulativeTrafficByPeer;
222+
return true;
223+
}
224+
225+
bool p3ServerConfig::getCumulativeTrafficByService(std::map<uint16_t, RsCumulativeTrafficStats>& stats)
226+
{
227+
RsStackMutex stack(configMtx);
228+
229+
// First, update cumulative stats from current traffic clues
230+
std::list<RSTrafficClue> out_lst, in_lst;
231+
if (rsBandwidthControl)
232+
{
233+
rsBandwidthControl->ExtractTrafficInfo(out_lst, in_lst);
234+
235+
rstime_t now = time(nullptr);
236+
237+
// Accumulate outgoing traffic by service
238+
for (const auto& clue : out_lst)
239+
{
240+
auto& serviceStats = mCumulativeTrafficByService[clue.service_id];
241+
serviceStats.bytesOut += clue.size;
242+
serviceStats.countOut += clue.count;
243+
if (serviceStats.firstSeen == 0) serviceStats.firstSeen = now;
244+
serviceStats.lastSeen = now;
245+
}
246+
247+
// Accumulate incoming traffic by service
248+
for (const auto& clue : in_lst)
249+
{
250+
auto& serviceStats = mCumulativeTrafficByService[clue.service_id];
251+
serviceStats.bytesIn += clue.size;
252+
serviceStats.countIn += clue.count;
253+
if (serviceStats.firstSeen == 0) serviceStats.firstSeen = now;
254+
serviceStats.lastSeen = now;
255+
}
256+
}
257+
258+
stats = mCumulativeTrafficByService;
259+
return true;
260+
}
261+
262+
bool p3ServerConfig::clearCumulativeTraffic(bool clearPeerStats, bool clearServiceStats)
263+
{
264+
RsStackMutex stack(configMtx);
265+
266+
if (clearPeerStats)
267+
mCumulativeTrafficByPeer.clear();
268+
269+
if (clearServiceStats)
270+
mCumulativeTrafficByService.clear();
271+
272+
return true;
273+
}
274+
275+
bool p3ServerConfig::getTotalCumulativeTraffic(RsCumulativeTrafficStats& stats)
276+
{
277+
RsStackMutex stack(configMtx);
278+
279+
stats.clear();
280+
281+
// Sum up all peer stats
282+
for (const auto& pair : mCumulativeTrafficByPeer)
283+
{
284+
stats += pair.second;
285+
}
286+
287+
return true;
288+
}
289+
187290
int p3ServerConfig::getTotalBandwidthRates(RsConfigDataRates &rates)
188291
{
189292
if (rsBandwidthControl)

src/rsserver/p3serverconfig.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ class p3ServerConfig: public RsServerConfig
3838

3939
void load_config();
4040

41+
public:
42+
4143
/* From RsIface::RsConfig */
4244

4345
virtual int getConfigNetStatus(RsConfigNetStatus &status) override;
@@ -50,6 +52,12 @@ class p3ServerConfig: public RsServerConfig
5052
virtual int getAllBandwidthRates(std::map<RsPeerId, RsConfigDataRates> &ratemap) override;
5153
virtual int getTrafficInfo(std::list<RSTrafficClue>& out_lst, std::list<RSTrafficClue> &in_lst) override;
5254

55+
// Cumulative traffic statistics
56+
virtual bool getCumulativeTrafficByPeer(std::map<RsPeerId, RsCumulativeTrafficStats>& stats) override;
57+
virtual bool getCumulativeTrafficByService(std::map<uint16_t, RsCumulativeTrafficStats>& stats) override;
58+
virtual bool clearCumulativeTraffic(bool clearPeerStats, bool clearServiceStats) override;
59+
virtual bool getTotalCumulativeTraffic(RsCumulativeTrafficStats& stats) override;
60+
5361
/* From RsInit */
5462

5563
virtual std::string RsConfigDirectory();
@@ -115,6 +123,10 @@ class p3ServerConfig: public RsServerConfig
115123
bool mIsIdle;
116124

117125
RsOpMode mOpMode;
126+
127+
// Cumulative traffic statistics storage
128+
std::map<RsPeerId, RsCumulativeTrafficStats> mCumulativeTrafficByPeer;
129+
std::map<uint16_t, RsCumulativeTrafficStats> mCumulativeTrafficByService;
118130
};
119131

120132
#endif

0 commit comments

Comments
 (0)