Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions src/retroshare/rsconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,48 @@ struct RSTrafficClue : RsSerializable
}
};

/*!
* \brief Cumulative traffic statistics for tracking all-time data transfer
* Used to persist and display per-peer and per-service data usage
*/
struct RsCumulativeTrafficStats : RsSerializable
{
uint64_t bytesIn; //< Total bytes received
uint64_t bytesOut; //< Total bytes sent
uint32_t countIn; //< Number of incoming packets
uint32_t countOut; //< Number of outgoing packets
rstime_t firstSeen; //< Timestamp of first recorded traffic
rstime_t lastSeen; //< Timestamp of most recent traffic

RsCumulativeTrafficStats() :
bytesIn(0), bytesOut(0), countIn(0), countOut(0),
firstSeen(0), lastSeen(0) {}

RsCumulativeTrafficStats& operator+=(const RsCumulativeTrafficStats& other) {
bytesIn += other.bytesIn;
bytesOut += other.bytesOut;
countIn += other.countIn;
countOut += other.countOut;
if (firstSeen == 0 || (other.firstSeen != 0 && other.firstSeen < firstSeen))
firstSeen = other.firstSeen;
if (other.lastSeen > lastSeen)
lastSeen = other.lastSeen;
return *this;
}

void clear() { bytesIn = bytesOut = countIn = countOut = 0; firstSeen = lastSeen = 0; }

// RsSerializable interface
void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext &ctx) {
RS_SERIAL_PROCESS(bytesIn);
RS_SERIAL_PROCESS(bytesOut);
RS_SERIAL_PROCESS(countIn);
RS_SERIAL_PROCESS(countOut);
RS_SERIAL_PROCESS(firstSeen);
RS_SERIAL_PROCESS(lastSeen);
}
};

struct RsConfigNetStatus : RsSerializable
{
RsConfigNetStatus() : netLocalOk(true)
Expand Down Expand Up @@ -338,6 +380,39 @@ class RsServerConfig
*/
virtual int getTrafficInfo(std::list<RSTrafficClue>& out_lst,std::list<RSTrafficClue>& in_lst) = 0 ;

/**
* @brief getCumulativeTrafficByPeer returns cumulative traffic stats grouped by peer
* @jsonapi{development}
* @param[out] stats map of peer ID to cumulative traffic stats
* @return returns true on success
*/
virtual bool getCumulativeTrafficByPeer(std::map<RsPeerId, RsCumulativeTrafficStats>& stats) = 0;

/**
* @brief getCumulativeTrafficByService returns cumulative traffic stats grouped by service
* @jsonapi{development}
* @param[out] stats map of service ID to cumulative traffic stats
* @return returns true on success
*/
virtual bool getCumulativeTrafficByService(std::map<uint16_t, RsCumulativeTrafficStats>& stats) = 0;

/**
* @brief clearCumulativeTraffic clears all cumulative traffic statistics
* @jsonapi{development}
* @param[in] clearPeerStats if true, clears per-peer stats
* @param[in] clearServiceStats if true, clears per-service stats
* @return returns true on success
*/
virtual bool clearCumulativeTraffic(bool clearPeerStats = true, bool clearServiceStats = true) = 0;

/**
* @brief getTotalCumulativeTraffic returns the total cumulative traffic across all peers/services
* @jsonapi{development}
* @param[out] stats total cumulative traffic stats
* @return returns true on success
*/
virtual bool getTotalCumulativeTraffic(RsCumulativeTrafficStats& stats) = 0;

/* From RsInit */

// NOT IMPLEMENTED YET!
Expand Down
85 changes: 85 additions & 0 deletions src/rsitems/rstrafficstatsitems.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*******************************************************************************
* libretroshare/src/rsitems: rstrafficstatsitems.h *
* *
* libretroshare: retroshare core library *
* *
* Copyright (C) 2024 *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
* *
*******************************************************************************/
#ifndef RS_TRAFFIC_STATS_ITEMS_H
#define RS_TRAFFIC_STATS_ITEMS_H

#include <map>

#include "rsitems/rsitem.h"
#include "rsitems/rsserviceids.h"
#include "retroshare/rsconfig.h"
#include "serialiser/rsserializer.h"
#include "serialiser/rstypeserializer.h"

// Use BANDWIDTH_CONTROL service type for config items
const uint8_t RS_PKT_SUBTYPE_TRAFFIC_STATS_ITEM = 0x10;

/**************************************************************************/

class RsTrafficStatsConfigItem : public RsItem
{
public:
RsTrafficStatsConfigItem() : RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_BWCTRL, RS_PKT_SUBTYPE_TRAFFIC_STATS_ITEM)
{}

virtual ~RsTrafficStatsConfigItem() {}

virtual void clear()
{
peerStats.clear();
serviceStats.clear();
}

void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx)
{
RsTypeSerializer::serial_process(j, ctx, peerStats, "peerStats");
RsTypeSerializer::serial_process(j, ctx, serviceStats, "serviceStats");
}

std::map<RsPeerId, RsCumulativeTrafficStats> peerStats;
std::map<uint16_t, RsCumulativeTrafficStats> serviceStats;
};

class RsTrafficStatsSerialiser : public RsServiceSerializer
{
public:
RsTrafficStatsSerialiser() : RsServiceSerializer(RS_SERVICE_TYPE_BWCTRL) {}
virtual ~RsTrafficStatsSerialiser() {}

RsItem *create_item(uint16_t service, uint8_t item_sub_id) const
{
if (service != RS_SERVICE_TYPE_BWCTRL)
return nullptr;

switch (item_sub_id)
{
case RS_PKT_SUBTYPE_TRAFFIC_STATS_ITEM:
return new RsTrafficStatsConfigItem();
default:
return nullptr;
}
}
};

/**************************************************************************/

#endif /* RS_TRAFFIC_STATS_ITEMS_H */
103 changes: 103 additions & 0 deletions src/rsserver/p3serverconfig.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <retroshare/rsturtle.h>
#include "rsserver/p3serverconfig.h"
#include "services/p3bwctrl.h"
#include "rsitems/rstrafficstatsitems.h"

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

bool p3ServerConfig::getCumulativeTrafficByPeer(std::map<RsPeerId, RsCumulativeTrafficStats>& stats)
{
RsStackMutex stack(configMtx);

// First, update cumulative stats from current traffic clues
std::list<RSTrafficClue> out_lst, in_lst;
if (rsBandwidthControl)
{
rsBandwidthControl->ExtractTrafficInfo(out_lst, in_lst);

rstime_t now = time(nullptr);

// Accumulate outgoing traffic
for (const auto& clue : out_lst)
{
auto& peerStats = mCumulativeTrafficByPeer[clue.peer_id];
peerStats.bytesOut += clue.size;
peerStats.countOut += clue.count;
if (peerStats.firstSeen == 0) peerStats.firstSeen = now;
peerStats.lastSeen = now;
}

// Accumulate incoming traffic
for (const auto& clue : in_lst)
{
auto& peerStats = mCumulativeTrafficByPeer[clue.peer_id];
peerStats.bytesIn += clue.size;
peerStats.countIn += clue.count;
if (peerStats.firstSeen == 0) peerStats.firstSeen = now;
peerStats.lastSeen = now;
}
}

stats = mCumulativeTrafficByPeer;
return true;
}

bool p3ServerConfig::getCumulativeTrafficByService(std::map<uint16_t, RsCumulativeTrafficStats>& stats)
{
RsStackMutex stack(configMtx);

// First, update cumulative stats from current traffic clues
std::list<RSTrafficClue> out_lst, in_lst;
if (rsBandwidthControl)
{
rsBandwidthControl->ExtractTrafficInfo(out_lst, in_lst);

rstime_t now = time(nullptr);

// Accumulate outgoing traffic by service
for (const auto& clue : out_lst)
{
auto& serviceStats = mCumulativeTrafficByService[clue.service_id];
serviceStats.bytesOut += clue.size;
serviceStats.countOut += clue.count;
if (serviceStats.firstSeen == 0) serviceStats.firstSeen = now;
serviceStats.lastSeen = now;
}

// Accumulate incoming traffic by service
for (const auto& clue : in_lst)
{
auto& serviceStats = mCumulativeTrafficByService[clue.service_id];
serviceStats.bytesIn += clue.size;
serviceStats.countIn += clue.count;
if (serviceStats.firstSeen == 0) serviceStats.firstSeen = now;
serviceStats.lastSeen = now;
}
}

stats = mCumulativeTrafficByService;
return true;
}

bool p3ServerConfig::clearCumulativeTraffic(bool clearPeerStats, bool clearServiceStats)
{
RsStackMutex stack(configMtx);

if (clearPeerStats)
mCumulativeTrafficByPeer.clear();

if (clearServiceStats)
mCumulativeTrafficByService.clear();

return true;
}

bool p3ServerConfig::getTotalCumulativeTraffic(RsCumulativeTrafficStats& stats)
{
RsStackMutex stack(configMtx);

stats.clear();

// Sum up all peer stats
for (const auto& pair : mCumulativeTrafficByPeer)
{
stats += pair.second;
}

return true;
}

int p3ServerConfig::getTotalBandwidthRates(RsConfigDataRates &rates)
{
if (rsBandwidthControl)
Expand Down
12 changes: 12 additions & 0 deletions src/rsserver/p3serverconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ class p3ServerConfig: public RsServerConfig

void load_config();

public:

/* From RsIface::RsConfig */

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

// Cumulative traffic statistics
virtual bool getCumulativeTrafficByPeer(std::map<RsPeerId, RsCumulativeTrafficStats>& stats) override;
virtual bool getCumulativeTrafficByService(std::map<uint16_t, RsCumulativeTrafficStats>& stats) override;
virtual bool clearCumulativeTraffic(bool clearPeerStats, bool clearServiceStats) override;
virtual bool getTotalCumulativeTraffic(RsCumulativeTrafficStats& stats) override;

/* From RsInit */

virtual std::string RsConfigDirectory();
Expand Down Expand Up @@ -115,6 +123,10 @@ class p3ServerConfig: public RsServerConfig
bool mIsIdle;

RsOpMode mOpMode;

// Cumulative traffic statistics storage
std::map<RsPeerId, RsCumulativeTrafficStats> mCumulativeTrafficByPeer;
std::map<uint16_t, RsCumulativeTrafficStats> mCumulativeTrafficByService;
};

#endif