Skip to content

Commit 6ae42c6

Browse files
authored
[core] Drop msg by TTL even if hasn't ever been sent (#2068)
1 parent b99e41c commit 6ae42c6

File tree

4 files changed

+83
-67
lines changed

4 files changed

+83
-67
lines changed

docs/API/API-functions.md

+2-5
Original file line numberDiff line numberDiff line change
@@ -1703,11 +1703,8 @@ called function should work.
17031703
- `msgttl`: [IN]. In **message** and **live mode** only, specifies the TTL for
17041704
sending messages (in `[ms]`). Not used for receiving messages. If this value
17051705
is not negative, it defines the maximum time up to which this message should
1706-
stay scheduled for sending for the sake of later retransmission. A message
1707-
is always sent for the first time, but the UDP packet carrying it may be
1708-
(also partially) lost, and if so, lacking packets will be retransmitted. If
1709-
the message is not successfully resent before TTL expires, further retransmission
1710-
is given up and the message is discarded.
1706+
stay scheduled for sending. If TTL has expired, the message sending and further retransmissions are discarded, even
1707+
if it has never been sent so far.
17111708

17121709
- `inorder`: [IN]. In **message mode** only, specifies that sent messages should
17131710
be extracted by the receiver in the order of sending. This can be meaningful if

srtcore/buffer.cpp

+60-47
Original file line numberDiff line numberDiff line change
@@ -397,57 +397,70 @@ int CSndBuffer::addBufferFromFile(fstream& ifs, int len)
397397
return total;
398398
}
399399

400-
int CSndBuffer::readData(CPacket& w_packet, steady_clock::time_point& w_srctime, int kflgs)
400+
int CSndBuffer::readData(CPacket& w_packet, steady_clock::time_point& w_srctime, int kflgs, int& w_seqnoinc)
401401
{
402-
// No data to read
403-
if (m_pCurrBlock == m_pLastBlock)
404-
return 0;
402+
int readlen = 0;
403+
w_seqnoinc = 0;
404+
405+
while (m_pCurrBlock != m_pLastBlock)
406+
{
407+
// Make the packet REFLECT the data stored in the buffer.
408+
w_packet.m_pcData = m_pCurrBlock->m_pcData;
409+
readlen = m_pCurrBlock->m_iLength;
410+
w_packet.setLength(readlen);
411+
w_packet.m_iSeqNo = m_pCurrBlock->m_iSeqNo;
412+
413+
// XXX This is probably done because the encryption should happen
414+
// just once, and so this sets the encryption flags to both msgno bitset
415+
// IN THE PACKET and IN THE BLOCK. This is probably to make the encryption
416+
// happen at the time when scheduling a new packet to send, but the packet
417+
// must remain in the send buffer until it's ACKed. For the case of rexmit
418+
// the packet will be taken "as is" (that is, already encrypted).
419+
//
420+
// The problem is in the order of things:
421+
// 0. When the application stores the data, some of the flags for PH_MSGNO are set.
422+
// 1. The readData() is called to get the original data sent by the application.
423+
// 2. The data are original and must be encrypted. They WILL BE encrypted, later.
424+
// 3. So far we are in readData() so the encryption flags must be updated NOW because
425+
// later we won't have access to the block's data.
426+
// 4. After exiting from readData(), the packet is being encrypted. It's immediately
427+
// sent, however the data must remain in the sending buffer until they are ACKed.
428+
// 5. In case when rexmission is needed, the second overloaded version of readData
429+
// is being called, and the buffer + PH_MSGNO value is extracted. All interesting
430+
// flags must be present and correct at that time.
431+
//
432+
// The only sensible way to fix this problem is to encrypt the packet not after
433+
// extracting from here, but when the packet is stored into CSndBuffer. The appropriate
434+
// flags for PH_MSGNO will be applied directly there. Then here the value for setting
435+
// PH_MSGNO will be set as is.
436+
437+
if (kflgs == -1)
438+
{
439+
HLOGC(bslog.Debug, log << CONID() << " CSndBuffer: ERROR: encryption required and not possible. NOT SENDING.");
440+
readlen = 0;
441+
}
442+
else
443+
{
444+
m_pCurrBlock->m_iMsgNoBitset |= MSGNO_ENCKEYSPEC::wrap(kflgs);
445+
}
405446

406-
// Make the packet REFLECT the data stored in the buffer.
407-
w_packet.m_pcData = m_pCurrBlock->m_pcData;
408-
int readlen = m_pCurrBlock->m_iLength;
409-
w_packet.setLength(readlen);
410-
w_packet.m_iSeqNo = m_pCurrBlock->m_iSeqNo;
411-
412-
// XXX This is probably done because the encryption should happen
413-
// just once, and so this sets the encryption flags to both msgno bitset
414-
// IN THE PACKET and IN THE BLOCK. This is probably to make the encryption
415-
// happen at the time when scheduling a new packet to send, but the packet
416-
// must remain in the send buffer until it's ACKed. For the case of rexmit
417-
// the packet will be taken "as is" (that is, already encrypted).
418-
//
419-
// The problem is in the order of things:
420-
// 0. When the application stores the data, some of the flags for PH_MSGNO are set.
421-
// 1. The readData() is called to get the original data sent by the application.
422-
// 2. The data are original and must be encrypted. They WILL BE encrypted, later.
423-
// 3. So far we are in readData() so the encryption flags must be updated NOW because
424-
// later we won't have access to the block's data.
425-
// 4. After exiting from readData(), the packet is being encrypted. It's immediately
426-
// sent, however the data must remain in the sending buffer until they are ACKed.
427-
// 5. In case when rexmission is needed, the second overloaded version of readData
428-
// is being called, and the buffer + PH_MSGNO value is extracted. All interesting
429-
// flags must be present and correct at that time.
430-
//
431-
// The only sensible way to fix this problem is to encrypt the packet not after
432-
// extracting from here, but when the packet is stored into CSndBuffer. The appropriate
433-
// flags for PH_MSGNO will be applied directly there. Then here the value for setting
434-
// PH_MSGNO will be set as is.
447+
Block* p = m_pCurrBlock;
448+
w_packet.m_iMsgNo = m_pCurrBlock->m_iMsgNoBitset;
449+
w_srctime = m_pCurrBlock->m_tsOriginTime;
450+
m_pCurrBlock = m_pCurrBlock->m_pNext;
435451

436-
if (kflgs == -1)
437-
{
438-
HLOGC(bslog.Debug, log << CONID() << " CSndBuffer: ERROR: encryption required and not possible. NOT SENDING.");
439-
readlen = 0;
440-
}
441-
else
442-
{
443-
m_pCurrBlock->m_iMsgNoBitset |= MSGNO_ENCKEYSPEC::wrap(kflgs);
444-
}
445-
446-
w_packet.m_iMsgNo = m_pCurrBlock->m_iMsgNoBitset;
447-
w_srctime = m_pCurrBlock->m_tsOriginTime;
448-
m_pCurrBlock = m_pCurrBlock->m_pNext;
452+
if ((p->m_iTTL >= 0) && (count_milliseconds(steady_clock::now() - w_srctime) > p->m_iTTL))
453+
{
454+
LOGC(bslog.Warn, log << CONID() << "CSndBuffer: skipping packet %" << p->m_iSeqNo << " #" << p->getMsgSeq() << " with TTL=" << p->m_iTTL);
455+
// Skip this packet due to TTL expiry.
456+
readlen = 0;
457+
++w_seqnoinc;
458+
continue;
459+
}
449460

450-
HLOGC(bslog.Debug, log << CONID() << "CSndBuffer: extracting packet size=" << readlen << " to send");
461+
HLOGC(bslog.Debug, log << CONID() << "CSndBuffer: extracting packet size=" << readlen << " to send");
462+
break;
463+
}
451464

452465
return readlen;
453466
}

srtcore/buffer.h

+8-7
Original file line numberDiff line numberDiff line change
@@ -142,17 +142,18 @@ class CSndBuffer
142142
int addBufferFromFile(std::fstream& ifs, int len);
143143

144144
/// Find data position to pack a DATA packet from the furthest reading point.
145-
/// @param [out] w_packet data packet buffer to fill.
146-
/// @param [out] w_origintime origin time stamp of the message.
147-
/// @param [in] kflags Odd|Even crypto key flag.
145+
/// @param [out] packet the packet to read.
146+
/// @param [out] origintime origin time stamp of the message
147+
/// @param [in] kflags Odd|Even crypto key flag
148+
/// @param [out] seqnoinc the number of packets skipped due to TTL, so that seqno should be incremented.
148149
/// @return Actual length of data read.
149-
int readData(CPacket& w_packet, time_point& w_origintime, int kflgs);
150+
int readData(CPacket& w_packet, time_point& w_origintime, int kflgs, int& w_seqnoinc);
150151

151152
/// Find data position to pack a DATA packet for a retransmission.
152153
/// @param [in] offset offset from the last ACK point (backward sequence number difference)
153-
/// @param [out] w_packet data packet buffer to fill.
154-
/// @param [out] w_origintime origin time stamp of the message
155-
/// @param [out] w_msglen length of the message
154+
/// @param [out] packet the packet to read.
155+
/// @param [out] origintime origin time stamp of the message
156+
/// @param [out] msglen length of the message
156157
/// @return Actual length of data read (return 0 if offset too large, -1 if TTL exceeded).
157158
int readData(const int offset, CPacket& w_packet, time_point& w_origintime, int& w_msglen);
158159

srtcore/core.cpp

+13-8
Original file line numberDiff line numberDiff line change
@@ -9219,17 +9219,15 @@ int srt::CUDT::packLostData(CPacket& w_packet, steady_clock::time_point& w_origi
92199219
SRT_ASSERT(msglen >= 1);
92209220
seqpair[1] = CSeqNo::incseq(seqpair[0], msglen - 1);
92219221

9222-
HLOGC(qrlog.Debug, log << "IPE: loss-reported packets not found in SndBuf - requesting DROP: "
9223-
<< "msg=" << MSGNO_SEQ::unwrap(w_packet.m_iMsgNo) << " msglen=" << msglen << " SEQ:"
9224-
<< seqpair[0] << " - " << seqpair[1] << "(" << (-offset) << " packets)");
9222+
HLOGC(qrlog.Debug,
9223+
log << "loss-reported packets expired in SndBuf - requesting DROP: "
9224+
<< "msgno=" << MSGNO_SEQ::unwrap(w_packet.m_iMsgNo) << " msglen=" << msglen
9225+
<< " SEQ:" << seqpair[0] << " - " << seqpair[1]);
92259226
sendCtrl(UMSG_DROPREQ, &w_packet.m_iMsgNo, seqpair, sizeof(seqpair));
92269227

9227-
// only one msg drop request is necessary
9228-
m_pSndLossList->removeUpTo(seqpair[1]);
9229-
92309228
// skip all dropped packets
9229+
m_pSndLossList->removeUpTo(seqpair[1]);
92319230
m_iSndCurrSeqNo = CSeqNo::maxseq(m_iSndCurrSeqNo, seqpair[1]);
9232-
92339231
continue;
92349232
}
92359233
else if (payload == 0)
@@ -9327,7 +9325,14 @@ std::pair<int, steady_clock::time_point> srt::CUDT::packData(CPacket& w_packet)
93279325
// It would be nice to research as to whether CSndBuffer::Block::m_iMsgNoBitset field
93289326
// isn't a useless redundant state copy. If it is, then taking the flags here can be removed.
93299327
kflg = m_pCryptoControl->getSndCryptoFlags();
9330-
payload = m_pSndBuffer->readData((w_packet), (origintime), kflg);
9328+
int pktskipseqno = 0;
9329+
payload = m_pSndBuffer->readData((w_packet), (origintime), kflg, (pktskipseqno));
9330+
if (pktskipseqno)
9331+
{
9332+
// Some packets were skipped due to TTL expiry.
9333+
m_iSndCurrSeqNo = CSeqNo::incseq(m_iSndCurrSeqNo, pktskipseqno);
9334+
}
9335+
93319336
if (payload)
93329337
{
93339338
// A CHANGE. The sequence number is currently added to the packet

0 commit comments

Comments
 (0)