Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added UDT::devel_setfakeloss testing utility #966

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
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
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,9 @@ if (ENABLE_MONOTONIC_CLOCK AND LINUX)
set (WITH_EXTRALIBS "${WITH_EXTRALIBS} ${NEED_CLOCK_GETTIME}")
endif()

if (ENABLE_DEVEL_API)
add_definitions(-DENABLE_DEVEL_API=1)
endif()

# This options is necessary on some systems; on a cross-ARM compiler it
# has been detected, for example, that -lrt is necessary for some applications
Expand Down
24 changes: 24 additions & 0 deletions srtcore/api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2826,6 +2826,23 @@ SRT_SOCKSTATUS CUDT::getsockstate(SRTSOCKET u)
}
}

#if ENABLE_DEVEL_API
void CUDT::setfakeloss(SRTSOCKET s, const std::string& conf)
{
CUDTSocket* us = s_UDTUnited.locate(s);
if (!us)
return;

CUDT* u = us->m_pUDT;
if (!u)
return;

if (u->m_pSndQueue)
u->m_pSndQueue->setfakeloss(conf);
}

#endif


////////////////////////////////////////////////////////////////////////////////

Expand Down Expand Up @@ -3257,4 +3274,11 @@ SRT_REJECT_REASON getrejectreason(SRTSOCKET u)
return CUDT::rejectReason(u);
}

#if ENABLE_DEVEL_API
void devel_setfakeloss(UDTSOCKET u, const std::string& config)
{
CUDT::setfakeloss(u, config);
}
#endif

} // namespace UDT
3 changes: 2 additions & 1 deletion srtcore/buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -946,7 +946,8 @@ bool CRcvBuffer::getRcvFirstMsg(ref_t<uint64_t> r_tsbpdtime, ref_t<bool> r_passa
}
else if (*r_tsbpdtime != 0)
{
HLOGC(dlog.Debug, log << "getRcvFirstMsg: no packets found");
HLOGC(dlog.Debug, log << "getRcvFirstMsg: no READY packets found (first playtime:"
<< FormatTime(*r_tsbpdtime) << ")");
return false;
}

Expand Down
119 changes: 65 additions & 54 deletions srtcore/channel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,67 @@ void CChannel::getPeerAddr(sockaddr* addr) const
::getpeername(m_iSocket, addr, &namelen);
}

#if ENABLE_DEVEL_API
CChannel::FakeLossConfig::FakeLossConfig(const std::string& f)
: dcounter(0)
, flwcounter(0)
{
vector<string> out;
Split(f, '+', back_inserter(out));

config_length = atoi(out[0].c_str());
config_interval = out.size() > 1 ? atoi(out[1].c_str()) : 8;
}

void CChannel::setfakeloss(const std::string& conf)
{
if (conf == "")
m_fakeloss.reset();
else
m_fakeloss.reset(new FakeLossConfig(conf));
}

// [[requires: (m_fakeloss != nullptr)]]
bool CChannel::checkFakeLoss(int32_t seq SRT_ATR_UNUSED) const
{
if (m_fakeloss->dcounter == 0)
{
timeval tv;
gettimeofday(&tv, 0);
srand(tv.tv_usec & 0xFFFF);
}
++m_fakeloss->dcounter;

if (m_fakeloss->flwcounter)
{
// This is a counter of how many packets in a row shall be lost
--m_fakeloss->flwcounter;
HLOGC(mglog.Debug, log << "CChannel: TEST: FAKE LOSS OF %" << seq << " (" << m_fakeloss->flwcounter << " more to drop)");
return true; // fake successful sending
}

if (m_fakeloss->dcounter > 8)
{
// Make a random number in the range between 8 and 24
int rnd = rand() % 16 + m_fakeloss->config_length + m_fakeloss->config_interval;

if (m_fakeloss->dcounter > rnd)
{
m_fakeloss->dcounter = 1;
HLOGC(mglog.Debug, log << "CChannel: TEST: FAKE LOSS OF %" << seq << " (will drop " << m_fakeloss->config_length << " more)");
m_fakeloss->flwcounter = m_fakeloss->config_length;
return true; // fake successful sending
}
}

int fcval = (m_fakeloss->config_length + m_fakeloss->config_interval);
HLOGC(mglog.Debug, log << "CChannel: NO FAKE LOSS yet. dc=" << m_fakeloss->dcounter << " (upto "
<< fcval << " - " << (fcval + 16) << ") flw=" << m_fakeloss->flwcounter);

return false;
}
#endif


int CChannel::sendto(const sockaddr* addr, CPacket& packet) const
{
Expand Down Expand Up @@ -443,64 +504,14 @@ int CChannel::sendto(const sockaddr* addr, CPacket& packet) const
<< spec.str());
#endif

#ifdef SRT_TEST_FAKE_LOSS

#define FAKELOSS_STRING_0(x) #x
#define FAKELOSS_STRING(x) FAKELOSS_STRING_0(x)
const char* fakeloss_text = FAKELOSS_STRING(SRT_TEST_FAKE_LOSS);
#undef FAKELOSS_STRING
#undef FAKELOSS_WRAP

static int dcounter = 0;
static int flwcounter = 0;

struct FakelossConfig
{
pair<int,int> config;
FakelossConfig(const char* f)
{
vector<string> out;
Split(f, '+', back_inserter(out));

config.first = atoi(out[0].c_str());
config.second = out.size() > 1 ? atoi(out[1].c_str()) : 8;
}
};
static FakelossConfig fakeloss = fakeloss_text;

if (!packet.isControl())
#if ENABLE_DEVEL_API
if (m_fakeloss && !packet.isControl())
{
if (dcounter == 0)
{
timeval tv;
gettimeofday(&tv, 0);
srand(tv.tv_usec & 0xFFFF);
}
++dcounter;

if (flwcounter)
if (checkFakeLoss(packet.getSeqNo()))
{
// This is a counter of how many packets in a row shall be lost
--flwcounter;
HLOGC(mglog.Debug, log << "CChannel: TEST: FAKE LOSS OF %" << packet.getSeqNo() << " (" << flwcounter << " more to drop)");
return packet.getLength(); // fake successful sendinf
}

if (dcounter > 8)
{
// Make a random number in the range between 8 and 24
int rnd = rand() % 16 + SRT_TEST_FAKE_LOSS;

if (dcounter > rnd)
{
dcounter = 1;
HLOGC(mglog.Debug, log << "CChannel: TEST: FAKE LOSS OF %" << packet.getSeqNo() << " (will drop " << fakeloss.config.first << " more)");
flwcounter = fakeloss.config.first;
return packet.getLength(); // fake successful sendinf
}
return packet.getLength();
}
}

#endif

// convert control information into network order
Expand Down
20 changes: 20 additions & 0 deletions srtcore/channel.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,26 @@ class CChannel
const sockaddr* bindAddress() { return &m_BindAddr; }
const sockaddr_any& bindAddressAny() { return m_BindAddr; }

#if ENABLE_DEVEL_API
void setfakeloss(const std::string& conf);
bool checkFakeLoss(int32_t seq) const;

struct FakeLossConfig
{
int config_length;
int config_interval;
FakeLossConfig(const std::string& f);

// Fakeloss state
int dcounter;
int flwcounter;
};

private:
mutable UniquePtr<FakeLossConfig> m_fakeloss;

#endif

private:
void setUDPSockOpt();

Expand Down
20 changes: 14 additions & 6 deletions srtcore/core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4809,14 +4809,14 @@ void *CUDT::tsbpd(void *param)
#if ENABLE_LOGGING
int64_t timediff = 0;
if (tsbpdtime)
timediff = int64_t(tsbpdtime) - int64_t(CTimer::getTime());
timediff = int64_t(CTimer::getTime()) - int64_t(tsbpdtime);
#if ENABLE_HEAVY_LOGGING
HLOGC(tslog.Debug,
log << self->CONID() << "tsbpd: DROPSEQ: up to seq=" << CSeqNo::decseq(skiptoseqno) << " ("
<< seqlen << " packets) playable at " << FormatTime(tsbpdtime) << " delayed "
<< (timediff / 1000) << "." << (timediff % 1000) << " ms");
<< (timediff / 1000.0) << " ms");
#endif
LOGC(dlog.Debug, log << "RCV-DROPPED packet delay=" << (timediff / 1000) << "ms");
LOGC(dlog.Debug, log << "RCV-DROPPED packet delay=" << (timediff / 1000.0) << "ms");
#endif

tsbpdtime = 0; // Next sent ack will unblock
Expand All @@ -4825,6 +4825,8 @@ void *CUDT::tsbpd(void *param)
else if (passack)
{
/* Packets ready to play but not yet acknowledged (should happen within 10ms) */
HLOGC(tslog.Debug, log << self->CONID() << "tsbpd: No more ready packets, past-ack only, playtime: "
<< FormatTime(tsbpdtime) << " - resetting to wait for ACK");
rxready = false;
tsbpdtime = 0; // Next sent ack will unblock
} /* else packet ready to play */
Expand Down Expand Up @@ -6888,12 +6890,16 @@ void CUDT::sendCtrl(UDTMessageType pkttype, const void *lparam, void *rparam, in
{
int32_t ack;

IF_HEAVY_LOGGING(int32_t floss = -1);
// If there is no loss, the ACK is the current largest sequence number plus 1;
// Otherwise it is the smallest sequence number in the receiver loss list.
if (m_pRcvLossList->getLossLength() == 0)
ack = CSeqNo::incseq(m_iRcvCurrSeqNo);
else
{
ack = m_pRcvLossList->getFirstLostSeq();
IF_HEAVY_LOGGING(floss = ack);
}

if (m_iRcvLastAckAck == ack)
break;
Expand Down Expand Up @@ -6937,7 +6943,9 @@ void CUDT::sendCtrl(UDTMessageType pkttype, const void *lparam, void *rparam, in
// will signal m_RecvDataCond when there's time to play for particular
// data packet.
HLOGC(dlog.Debug,
log << "ACK: clip %" << oldack << "-%" << ack << ", REVOKED " << acksize << " from RCV buffer");
log << "ACK: clip %" << oldack << "-%" << ack << ", REVOKED " << acksize
<< " from RCV buffer, BUFr=" << m_pRcvBuffer->getAvailBufSize()
<< " first loss: " << floss);

if (m_bTsbPd)
{
Expand Down Expand Up @@ -8385,13 +8393,13 @@ int CUDT::processData(CUnit *in_unit)
// Meaning, this packet will be rejected, even if it could potentially be
// one of missing packets in the transmission.
int32_t offset = CSeqNo::seqoff(m_iRcvLastSkipAck, rpkt.m_iSeqNo);
uint64_t tsbpdtime = m_pRcvBuffer->getPktTsbPdTime(rpkt.getMsgTimeStamp());

IF_HEAVY_LOGGING(const char *exc_type = "EXPECTED");

if (offset < 0)
{
IF_HEAVY_LOGGING(exc_type = "BELATED");
uint64_t tsbpdtime = m_pRcvBuffer->getPktTsbPdTime(rpkt.getMsgTimeStamp());
uint64_t bltime =
CountIIR(uint64_t(m_stats.traceBelatedTime) * 1000, CTimer::getTime() - tsbpdtime, 0.2);

Expand Down Expand Up @@ -8483,7 +8491,7 @@ int CUDT::processData(CUnit *in_unit)
log << CONID() << "RECEIVED: seq=" << rpkt.m_iSeqNo << " offset=" << offset
<< " BUFr=" << avail_bufsize
<< " (" << exc_type << "/" << rexmitstat[pktrexmitflag] << rexmit_reason << ") FLAGS: "
<< packet.MessageFlagStr());
<< packet.MessageFlagStr() << " PLAY: " << FormatTime(tsbpdtime));

// Decryption should have made the crypto flags EK_NOENC.
// Otherwise it's an error.
Expand Down
4 changes: 4 additions & 0 deletions srtcore/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,10 @@ class CUDT
return SRT_ERROR;
}

#if ENABLE_DEVEL_API
static void setfakeloss(SRTSOCKET s, const std::string& conf);
#endif

public: // internal API
static const SRTSOCKET INVALID_SOCK = -1; // invalid socket descriptor
static const int ERROR = -1; // socket api error returned value
Expand Down
4 changes: 4 additions & 0 deletions srtcore/queue.h
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,10 @@ friend class CUDTUnited;
m_bClosing = true;
}

#if ENABLE_DEVEL_API
void setfakeloss(const std::string& conf) { m_pChannel->setfakeloss(conf); }
#endif

private:
static void* worker(void* param);
pthread_t m_WorkerThread;
Expand Down
4 changes: 4 additions & 0 deletions srtcore/udt.h
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,10 @@ UDT_API void setlogflags(int flags);
UDT_API bool setstreamid(UDTSOCKET u, const std::string& sid);
UDT_API std::string getstreamid(UDTSOCKET u);

#if ENABLE_DEVEL_API
UDT_API void devel_setfakeloss(UDTSOCKET u, const std::string& config);
#endif

} // namespace UDT

// This is a log configuration used inside SRT.
Expand Down
19 changes: 19 additions & 0 deletions testing/testmedia.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
#include "srt_compat.h"
#include "verbose.hpp"

#include "udt.h"

using namespace std;


Expand Down Expand Up @@ -329,6 +331,13 @@ void SrtCommon::InitParameters(string host, map<string,string> par)
}
}

if (par.count("fakeloss"))
{
m_fakeloss = par["fakeloss"];
par.erase("fakeloss");
Verb() << "Will do FAKE LOSS: " << m_fakeloss;
}

// Assign the others here.
m_options = par;
}
Expand Down Expand Up @@ -519,6 +528,16 @@ int SrtCommon::ConfigurePost(SRTSOCKET sock)

SrtConfigurePost(sock, m_options, &failures);

if (m_fakeloss != "")
{
#if ENABLE_DEVEL_API
UDT::devel_setfakeloss(sock, m_fakeloss);
#else
Verb() << "ERROR: fakeloss not enabled at compile time";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"not" -> "is not"

return -1;
#endif
}


if (!failures.empty())
{
Expand Down
1 change: 1 addition & 0 deletions testing/testmedia.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class SrtCommon
int m_outgoing_port = 0;
string m_mode;
string m_adapter;
string m_fakeloss;
map<string, string> m_options; // All other options, as provided in the URI
SRTSOCKET m_sock = SRT_INVALID_SOCK;
SRTSOCKET m_bindsock = SRT_INVALID_SOCK;
Expand Down