list.cpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949
  1. /*
  2. * SRT - Secure, Reliable, Transport
  3. * Copyright (c) 2018 Haivision Systems Inc.
  4. *
  5. * This Source Code Form is subject to the terms of the Mozilla Public
  6. * License, v. 2.0. If a copy of the MPL was not distributed with this
  7. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  8. *
  9. */
  10. /*****************************************************************************
  11. Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois.
  12. All rights reserved.
  13. Redistribution and use in source and binary forms, with or without
  14. modification, are permitted provided that the following conditions are
  15. met:
  16. * Redistributions of source code must retain the above
  17. copyright notice, this list of conditions and the
  18. following disclaimer.
  19. * Redistributions in binary form must reproduce the
  20. above copyright notice, this list of conditions
  21. and the following disclaimer in the documentation
  22. and/or other materials provided with the distribution.
  23. * Neither the name of the University of Illinois
  24. nor the names of its contributors may be used to
  25. endorse or promote products derived from this
  26. software without specific prior written permission.
  27. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  28. IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  29. THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  30. PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  31. CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  32. EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  33. PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  34. PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  35. LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  36. NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  37. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  38. *****************************************************************************/
  39. /*****************************************************************************
  40. written by
  41. Yunhong Gu, last updated 01/22/2011
  42. modified by
  43. Haivision Systems Inc.
  44. *****************************************************************************/
  45. #include "platform_sys.h"
  46. #include "list.h"
  47. #include "packet.h"
  48. #include "logging.h"
  49. // Use "inline namespace" in C++11
  50. namespace srt_logging
  51. {
  52. extern Logger qrlog;
  53. extern Logger qslog;
  54. extern Logger tslog;
  55. }
  56. using srt_logging::qrlog;
  57. using srt_logging::qslog;
  58. using srt_logging::tslog;
  59. using namespace srt::sync;
  60. srt::CSndLossList::CSndLossList(int size)
  61. : m_caSeq()
  62. , m_iHead(-1)
  63. , m_iLength(0)
  64. , m_iSize(size)
  65. , m_iLastInsertPos(-1)
  66. , m_ListLock()
  67. {
  68. m_caSeq = new Seq[size];
  69. // -1 means there is no data in the node
  70. for (int i = 0; i < size; ++i)
  71. {
  72. m_caSeq[i].seqstart = SRT_SEQNO_NONE;
  73. m_caSeq[i].seqend = SRT_SEQNO_NONE;
  74. }
  75. // sender list needs mutex protection
  76. setupMutex(m_ListLock, "LossList");
  77. }
  78. srt::CSndLossList::~CSndLossList()
  79. {
  80. delete[] m_caSeq;
  81. releaseMutex(m_ListLock);
  82. }
  83. void srt::CSndLossList::traceState() const
  84. {
  85. int pos = m_iHead;
  86. while (pos != SRT_SEQNO_NONE)
  87. {
  88. std::cout << pos << ":[" << m_caSeq[pos].seqstart;
  89. if (m_caSeq[pos].seqend != SRT_SEQNO_NONE)
  90. std::cout << ", " << m_caSeq[pos].seqend;
  91. std::cout << "], ";
  92. pos = m_caSeq[pos].inext;
  93. }
  94. std::cout << "\n";
  95. }
  96. int srt::CSndLossList::insert(int32_t seqno1, int32_t seqno2)
  97. {
  98. if (seqno1 < 0 || seqno2 < 0 ) {
  99. LOGC(qslog.Error, log << "IPE: Tried to insert negative seqno " << seqno1 << ":" << seqno2
  100. << " into sender's loss list. Ignoring.");
  101. return 0;
  102. }
  103. const int inserted_range = CSeqNo::seqlen(seqno1, seqno2);
  104. if (inserted_range <= 0 || inserted_range >= m_iSize) {
  105. LOGC(qslog.Error, log << "IPE: Tried to insert too big range of seqno: " << inserted_range << ". Ignoring. "
  106. << "seqno " << seqno1 << ":" << seqno2);
  107. return 0;
  108. }
  109. ScopedLock listguard(m_ListLock);
  110. if (m_iLength == 0)
  111. {
  112. insertHead(0, seqno1, seqno2);
  113. return m_iLength;
  114. }
  115. // Find the insert position in the non-empty list
  116. const int origlen = m_iLength;
  117. const int offset = CSeqNo::seqoff(m_caSeq[m_iHead].seqstart, seqno1);
  118. if (offset >= m_iSize)
  119. {
  120. LOGC(qslog.Error, log << "IPE: New loss record is too far from the first record. Ignoring. "
  121. << "First loss seqno " << m_caSeq[m_iHead].seqstart
  122. << ", insert seqno " << seqno1 << ":" << seqno2);
  123. return 0;
  124. }
  125. int loc = (m_iHead + offset + m_iSize) % m_iSize;
  126. if (loc < 0)
  127. {
  128. const int offset_seqno2 = CSeqNo::seqoff(m_caSeq[m_iHead].seqstart, seqno2);
  129. const int loc_seqno2 = (m_iHead + offset_seqno2 + m_iSize) % m_iSize;
  130. if (loc_seqno2 < 0)
  131. {
  132. // The size of the CSndLossList should be at least the size of the flow window.
  133. // It means that all the packets sender has sent should fit within m_iSize.
  134. // If the new loss does not fit, there is some error.
  135. LOGC(qslog.Error, log << "IPE: New loss record is too old. Ignoring. "
  136. << "First loss seqno " << m_caSeq[m_iHead].seqstart
  137. << ", insert seqno " << seqno1 << ":" << seqno2);
  138. return 0;
  139. }
  140. loc = loc_seqno2;
  141. }
  142. if (offset < 0)
  143. {
  144. insertHead(loc, seqno1, seqno2);
  145. }
  146. else if (offset > 0)
  147. {
  148. if (seqno1 == m_caSeq[loc].seqstart)
  149. {
  150. const bool updated = updateElement(loc, seqno1, seqno2);
  151. if (!updated)
  152. return 0;
  153. }
  154. else
  155. {
  156. // Find the prior node.
  157. // It should be the highest sequence number less than seqno1.
  158. // 1. Start the search either from m_iHead, or from m_iLastInsertPos
  159. int i = m_iHead;
  160. if ((m_iLastInsertPos != -1) && (CSeqNo::seqcmp(m_caSeq[m_iLastInsertPos].seqstart, seqno1) < 0))
  161. i = m_iLastInsertPos;
  162. // 2. Find the highest sequence number less than seqno1.
  163. while (m_caSeq[i].inext != -1 && CSeqNo::seqcmp(m_caSeq[m_caSeq[i].inext].seqstart, seqno1) < 0)
  164. i = m_caSeq[i].inext;
  165. // 3. Check if seqno1 overlaps with (seqbegin, seqend)
  166. const int seqend = m_caSeq[i].seqend == SRT_SEQNO_NONE ? m_caSeq[i].seqstart : m_caSeq[i].seqend;
  167. if (CSeqNo::seqcmp(seqend, seqno1) < 0 && CSeqNo::incseq(seqend) != seqno1)
  168. {
  169. // No overlap
  170. // TODO: Here we should actually insert right after i, not at loc.
  171. insertAfter(loc, i, seqno1, seqno2);
  172. }
  173. else
  174. {
  175. // TODO: Replace with updateElement(i, seqno1, seqno2).
  176. // Some changes to updateElement(..) are required.
  177. m_iLastInsertPos = i;
  178. if (CSeqNo::seqcmp(seqend, seqno2) >= 0)
  179. return 0;
  180. // overlap, coalesce with prior node, insert(3, 7) to [2, 5], ... becomes [2, 7]
  181. m_iLength += CSeqNo::seqlen(seqend, seqno2) - 1;
  182. m_caSeq[i].seqend = seqno2;
  183. loc = i;
  184. }
  185. }
  186. }
  187. else // offset == 0, loc == m_iHead
  188. {
  189. const bool updated = updateElement(m_iHead, seqno1, seqno2);
  190. if (!updated)
  191. return 0;
  192. }
  193. coalesce(loc);
  194. return m_iLength - origlen;
  195. }
  196. void srt::CSndLossList::removeUpTo(int32_t seqno)
  197. {
  198. ScopedLock listguard(m_ListLock);
  199. if (0 == m_iLength)
  200. return;
  201. // Remove all from the head pointer to a node with a larger seq. no. or the list is empty
  202. int offset = CSeqNo::seqoff(m_caSeq[m_iHead].seqstart, seqno);
  203. int loc = (m_iHead + offset + m_iSize) % m_iSize;
  204. if (0 == offset)
  205. {
  206. // It is the head. Remove the head and point to the next node
  207. loc = (loc + 1) % m_iSize;
  208. if (SRT_SEQNO_NONE == m_caSeq[m_iHead].seqend)
  209. loc = m_caSeq[m_iHead].inext;
  210. else
  211. {
  212. m_caSeq[loc].seqstart = CSeqNo::incseq(seqno);
  213. if (CSeqNo::seqcmp(m_caSeq[m_iHead].seqend, CSeqNo::incseq(seqno)) > 0)
  214. m_caSeq[loc].seqend = m_caSeq[m_iHead].seqend;
  215. m_caSeq[m_iHead].seqend = SRT_SEQNO_NONE;
  216. m_caSeq[loc].inext = m_caSeq[m_iHead].inext;
  217. }
  218. m_caSeq[m_iHead].seqstart = SRT_SEQNO_NONE;
  219. if (m_iLastInsertPos == m_iHead)
  220. m_iLastInsertPos = -1;
  221. m_iHead = loc;
  222. m_iLength--;
  223. }
  224. else if (offset > 0)
  225. {
  226. int h = m_iHead;
  227. if (seqno == m_caSeq[loc].seqstart)
  228. {
  229. // target node is not empty, remove part/all of the seqno in the node.
  230. int temp = loc;
  231. loc = (loc + 1) % m_iSize;
  232. if (SRT_SEQNO_NONE == m_caSeq[temp].seqend)
  233. m_iHead = m_caSeq[temp].inext;
  234. else
  235. {
  236. // remove part, e.g., [3, 7] becomes [], [4, 7] after remove(3)
  237. m_caSeq[loc].seqstart = CSeqNo::incseq(seqno);
  238. if (CSeqNo::seqcmp(m_caSeq[temp].seqend, m_caSeq[loc].seqstart) > 0)
  239. m_caSeq[loc].seqend = m_caSeq[temp].seqend;
  240. m_iHead = loc;
  241. m_caSeq[loc].inext = m_caSeq[temp].inext;
  242. m_caSeq[temp].inext = loc;
  243. m_caSeq[temp].seqend = SRT_SEQNO_NONE;
  244. }
  245. }
  246. else
  247. {
  248. // target node is empty, check prior node
  249. int i = m_iHead;
  250. while ((-1 != m_caSeq[i].inext) && (CSeqNo::seqcmp(m_caSeq[m_caSeq[i].inext].seqstart, seqno) < 0))
  251. i = m_caSeq[i].inext;
  252. loc = (loc + 1) % m_iSize;
  253. if (SRT_SEQNO_NONE == m_caSeq[i].seqend)
  254. m_iHead = m_caSeq[i].inext;
  255. else if (CSeqNo::seqcmp(m_caSeq[i].seqend, seqno) > 0)
  256. {
  257. // remove part/all seqno in the prior node
  258. m_caSeq[loc].seqstart = CSeqNo::incseq(seqno);
  259. if (CSeqNo::seqcmp(m_caSeq[i].seqend, m_caSeq[loc].seqstart) > 0)
  260. m_caSeq[loc].seqend = m_caSeq[i].seqend;
  261. m_caSeq[i].seqend = seqno;
  262. m_caSeq[loc].inext = m_caSeq[i].inext;
  263. m_caSeq[i].inext = loc;
  264. m_iHead = loc;
  265. }
  266. else
  267. m_iHead = m_caSeq[i].inext;
  268. }
  269. // Remove all nodes prior to the new head
  270. while (h != m_iHead)
  271. {
  272. if (m_caSeq[h].seqend != SRT_SEQNO_NONE)
  273. {
  274. m_iLength -= CSeqNo::seqlen(m_caSeq[h].seqstart, m_caSeq[h].seqend);
  275. m_caSeq[h].seqend = SRT_SEQNO_NONE;
  276. }
  277. else
  278. m_iLength--;
  279. m_caSeq[h].seqstart = SRT_SEQNO_NONE;
  280. if (m_iLastInsertPos == h)
  281. m_iLastInsertPos = -1;
  282. h = m_caSeq[h].inext;
  283. }
  284. }
  285. }
  286. int srt::CSndLossList::getLossLength() const
  287. {
  288. ScopedLock listguard(m_ListLock);
  289. return m_iLength;
  290. }
  291. int32_t srt::CSndLossList::popLostSeq()
  292. {
  293. ScopedLock listguard(m_ListLock);
  294. if (0 == m_iLength)
  295. {
  296. SRT_ASSERT(m_iHead == -1);
  297. return SRT_SEQNO_NONE;
  298. }
  299. if (m_iLastInsertPos == m_iHead)
  300. m_iLastInsertPos = -1;
  301. // return the first loss seq. no.
  302. const int32_t seqno = m_caSeq[m_iHead].seqstart;
  303. // head moves to the next node
  304. if (SRT_SEQNO_NONE == m_caSeq[m_iHead].seqend)
  305. {
  306. //[3, SRT_SEQNO_NONE] becomes [], and head moves to next node in the list
  307. m_caSeq[m_iHead].seqstart = SRT_SEQNO_NONE;
  308. m_iHead = m_caSeq[m_iHead].inext;
  309. }
  310. else
  311. {
  312. // shift to next node, e.g., [3, 7] becomes [], [4, 7]
  313. int loc = (m_iHead + 1) % m_iSize;
  314. m_caSeq[loc].seqstart = CSeqNo::incseq(seqno);
  315. if (CSeqNo::seqcmp(m_caSeq[m_iHead].seqend, m_caSeq[loc].seqstart) > 0)
  316. m_caSeq[loc].seqend = m_caSeq[m_iHead].seqend;
  317. m_caSeq[m_iHead].seqstart = SRT_SEQNO_NONE;
  318. m_caSeq[m_iHead].seqend = SRT_SEQNO_NONE;
  319. m_caSeq[loc].inext = m_caSeq[m_iHead].inext;
  320. m_iHead = loc;
  321. }
  322. m_iLength--;
  323. return seqno;
  324. }
  325. void srt::CSndLossList::insertHead(int pos, int32_t seqno1, int32_t seqno2)
  326. {
  327. SRT_ASSERT(pos >= 0);
  328. m_caSeq[pos].seqstart = seqno1;
  329. SRT_ASSERT(m_caSeq[pos].seqend == SRT_SEQNO_NONE);
  330. if (seqno2 != seqno1)
  331. m_caSeq[pos].seqend = seqno2;
  332. // new node becomes head
  333. m_caSeq[pos].inext = m_iHead;
  334. m_iHead = pos;
  335. m_iLastInsertPos = pos;
  336. m_iLength += CSeqNo::seqlen(seqno1, seqno2);
  337. }
  338. void srt::CSndLossList::insertAfter(int pos, int pos_after, int32_t seqno1, int32_t seqno2)
  339. {
  340. m_caSeq[pos].seqstart = seqno1;
  341. SRT_ASSERT(m_caSeq[pos].seqend == SRT_SEQNO_NONE);
  342. if (seqno2 != seqno1)
  343. m_caSeq[pos].seqend = seqno2;
  344. m_caSeq[pos].inext = m_caSeq[pos_after].inext;
  345. m_caSeq[pos_after].inext = pos;
  346. m_iLastInsertPos = pos;
  347. m_iLength += CSeqNo::seqlen(seqno1, seqno2);
  348. }
  349. void srt::CSndLossList::coalesce(int loc)
  350. {
  351. // coalesce with next node. E.g., [3, 7], ..., [6, 9] becomes [3, 9]
  352. while ((m_caSeq[loc].inext != -1) && (m_caSeq[loc].seqend != SRT_SEQNO_NONE))
  353. {
  354. const int i = m_caSeq[loc].inext;
  355. if (CSeqNo::seqcmp(m_caSeq[i].seqstart, CSeqNo::incseq(m_caSeq[loc].seqend)) > 0)
  356. break;
  357. // coalesce if there is overlap
  358. if (m_caSeq[i].seqend != SRT_SEQNO_NONE)
  359. {
  360. if (CSeqNo::seqcmp(m_caSeq[i].seqend, m_caSeq[loc].seqend) > 0)
  361. {
  362. if (CSeqNo::seqcmp(m_caSeq[loc].seqend, m_caSeq[i].seqstart) >= 0)
  363. m_iLength -= CSeqNo::seqlen(m_caSeq[i].seqstart, m_caSeq[loc].seqend);
  364. m_caSeq[loc].seqend = m_caSeq[i].seqend;
  365. }
  366. else
  367. m_iLength -= CSeqNo::seqlen(m_caSeq[i].seqstart, m_caSeq[i].seqend);
  368. }
  369. else
  370. {
  371. if (m_caSeq[i].seqstart == CSeqNo::incseq(m_caSeq[loc].seqend))
  372. m_caSeq[loc].seqend = m_caSeq[i].seqstart;
  373. else
  374. m_iLength--;
  375. }
  376. m_caSeq[i].seqstart = SRT_SEQNO_NONE;
  377. m_caSeq[i].seqend = SRT_SEQNO_NONE;
  378. m_caSeq[loc].inext = m_caSeq[i].inext;
  379. }
  380. }
  381. bool srt::CSndLossList::updateElement(int pos, int32_t seqno1, int32_t seqno2)
  382. {
  383. m_iLastInsertPos = pos;
  384. if (seqno2 == SRT_SEQNO_NONE || seqno2 == seqno1)
  385. return false;
  386. if (m_caSeq[pos].seqend == SRT_SEQNO_NONE)
  387. {
  388. m_iLength += CSeqNo::seqlen(seqno1, seqno2) - 1;
  389. m_caSeq[pos].seqend = seqno2;
  390. return true;
  391. }
  392. // seqno2 <= m_caSeq[pos].seqend
  393. if (CSeqNo::seqcmp(seqno2, m_caSeq[pos].seqend) <= 0)
  394. return false;
  395. // seqno2 > m_caSeq[pos].seqend
  396. m_iLength += CSeqNo::seqlen(m_caSeq[pos].seqend, seqno2) - 1;
  397. m_caSeq[pos].seqend = seqno2;
  398. return true;
  399. }
  400. ////////////////////////////////////////////////////////////////////////////////
  401. srt::CRcvLossList::CRcvLossList(int size)
  402. : m_caSeq()
  403. , m_iHead(-1)
  404. , m_iTail(-1)
  405. , m_iLength(0)
  406. , m_iSize(size)
  407. , m_iLargestSeq(SRT_SEQNO_NONE)
  408. {
  409. m_caSeq = new Seq[m_iSize];
  410. // -1 means there is no data in the node
  411. for (int i = 0; i < size; ++i)
  412. {
  413. m_caSeq[i].seqstart = SRT_SEQNO_NONE;
  414. m_caSeq[i].seqend = SRT_SEQNO_NONE;
  415. }
  416. }
  417. srt::CRcvLossList::~CRcvLossList()
  418. {
  419. delete[] m_caSeq;
  420. }
  421. int srt::CRcvLossList::insert(int32_t seqno1, int32_t seqno2)
  422. {
  423. // Data to be inserted must be larger than all those in the list
  424. if (m_iLargestSeq != SRT_SEQNO_NONE && CSeqNo::seqcmp(seqno1, m_iLargestSeq) <= 0)
  425. {
  426. if (CSeqNo::seqcmp(seqno2, m_iLargestSeq) > 0)
  427. {
  428. LOGC(qrlog.Warn,
  429. log << "RCV-LOSS/insert: seqno1=" << seqno1 << " too small, adjust to "
  430. << CSeqNo::incseq(m_iLargestSeq));
  431. seqno1 = CSeqNo::incseq(m_iLargestSeq);
  432. }
  433. else
  434. {
  435. LOGC(qrlog.Warn,
  436. log << "RCV-LOSS/insert: (" << seqno1 << "," << seqno2
  437. << ") to be inserted is too small: m_iLargestSeq=" << m_iLargestSeq << ", m_iLength=" << m_iLength
  438. << ", m_iHead=" << m_iHead << ", m_iTail=" << m_iTail << " -- REJECTING");
  439. return 0;
  440. }
  441. }
  442. m_iLargestSeq = seqno2;
  443. if (0 == m_iLength)
  444. {
  445. // insert data into an empty list
  446. m_iHead = 0;
  447. m_iTail = 0;
  448. m_caSeq[m_iHead].seqstart = seqno1;
  449. if (seqno2 != seqno1)
  450. m_caSeq[m_iHead].seqend = seqno2;
  451. m_caSeq[m_iHead].inext = -1;
  452. m_caSeq[m_iHead].iprior = -1;
  453. const int n = CSeqNo::seqlen(seqno1, seqno2);
  454. m_iLength += n;
  455. return n;
  456. }
  457. // otherwise searching for the position where the node should be
  458. const int offset = CSeqNo::seqoff(m_caSeq[m_iHead].seqstart, seqno1);
  459. if (offset < 0)
  460. {
  461. LOGC(qrlog.Error,
  462. log << "RCV-LOSS/insert: IPE: new LOSS %(" << seqno1 << "-" << seqno2 << ") PREDATES HEAD %"
  463. << m_caSeq[m_iHead].seqstart << " -- REJECTING");
  464. return -1;
  465. }
  466. int loc = (m_iHead + offset) % m_iSize;
  467. if ((SRT_SEQNO_NONE != m_caSeq[m_iTail].seqend) && (CSeqNo::incseq(m_caSeq[m_iTail].seqend) == seqno1))
  468. {
  469. // coalesce with prior node, e.g., [2, 5], [6, 7] becomes [2, 7]
  470. loc = m_iTail;
  471. m_caSeq[loc].seqend = seqno2;
  472. }
  473. else
  474. {
  475. // create new node
  476. m_caSeq[loc].seqstart = seqno1;
  477. if (seqno2 != seqno1)
  478. m_caSeq[loc].seqend = seqno2;
  479. m_caSeq[m_iTail].inext = loc;
  480. m_caSeq[loc].iprior = m_iTail;
  481. m_caSeq[loc].inext = -1;
  482. m_iTail = loc;
  483. }
  484. const int n = CSeqNo::seqlen(seqno1, seqno2);
  485. m_iLength += n;
  486. return n;
  487. }
  488. bool srt::CRcvLossList::remove(int32_t seqno)
  489. {
  490. if (m_iLargestSeq == SRT_SEQNO_NONE || CSeqNo::seqcmp(seqno, m_iLargestSeq) > 0)
  491. m_iLargestSeq = seqno;
  492. if (0 == m_iLength)
  493. return false;
  494. // locate the position of "seqno" in the list
  495. int offset = CSeqNo::seqoff(m_caSeq[m_iHead].seqstart, seqno);
  496. if (offset < 0)
  497. return false;
  498. int loc = (m_iHead + offset) % m_iSize;
  499. if (seqno == m_caSeq[loc].seqstart)
  500. {
  501. // This is a seq. no. that starts the loss sequence
  502. if (SRT_SEQNO_NONE == m_caSeq[loc].seqend)
  503. {
  504. // there is only 1 loss in the sequence, delete it from the node
  505. if (m_iHead == loc)
  506. {
  507. m_iHead = m_caSeq[m_iHead].inext;
  508. if (-1 != m_iHead)
  509. m_caSeq[m_iHead].iprior = -1;
  510. else
  511. m_iTail = -1;
  512. }
  513. else
  514. {
  515. m_caSeq[m_caSeq[loc].iprior].inext = m_caSeq[loc].inext;
  516. if (-1 != m_caSeq[loc].inext)
  517. m_caSeq[m_caSeq[loc].inext].iprior = m_caSeq[loc].iprior;
  518. else
  519. m_iTail = m_caSeq[loc].iprior;
  520. }
  521. m_caSeq[loc].seqstart = SRT_SEQNO_NONE;
  522. }
  523. else
  524. {
  525. // there are more than 1 loss in the sequence
  526. // move the node to the next and update the starter as the next loss inSeqNo(seqno)
  527. // find next node
  528. int i = (loc + 1) % m_iSize;
  529. // remove the "seqno" and change the starter as next seq. no.
  530. m_caSeq[i].seqstart = CSeqNo::incseq(m_caSeq[loc].seqstart);
  531. // process the sequence end
  532. if (CSeqNo::seqcmp(m_caSeq[loc].seqend, CSeqNo::incseq(m_caSeq[loc].seqstart)) > 0)
  533. m_caSeq[i].seqend = m_caSeq[loc].seqend;
  534. // remove the current node
  535. m_caSeq[loc].seqstart = SRT_SEQNO_NONE;
  536. m_caSeq[loc].seqend = SRT_SEQNO_NONE;
  537. // update list pointer
  538. m_caSeq[i].inext = m_caSeq[loc].inext;
  539. m_caSeq[i].iprior = m_caSeq[loc].iprior;
  540. if (m_iHead == loc)
  541. m_iHead = i;
  542. else
  543. m_caSeq[m_caSeq[i].iprior].inext = i;
  544. if (m_iTail == loc)
  545. m_iTail = i;
  546. else
  547. m_caSeq[m_caSeq[i].inext].iprior = i;
  548. }
  549. m_iLength--;
  550. return true;
  551. }
  552. // There is no loss sequence in the current position
  553. // the "seqno" may be contained in a previous node
  554. // searching previous node
  555. int i = (loc - 1 + m_iSize) % m_iSize;
  556. while (SRT_SEQNO_NONE == m_caSeq[i].seqstart)
  557. i = (i - 1 + m_iSize) % m_iSize;
  558. // not contained in this node, return
  559. if ((SRT_SEQNO_NONE == m_caSeq[i].seqend) || (CSeqNo::seqcmp(seqno, m_caSeq[i].seqend) > 0))
  560. return false;
  561. if (seqno == m_caSeq[i].seqend)
  562. {
  563. // it is the sequence end
  564. if (seqno == CSeqNo::incseq(m_caSeq[i].seqstart))
  565. m_caSeq[i].seqend = SRT_SEQNO_NONE;
  566. else
  567. m_caSeq[i].seqend = CSeqNo::decseq(seqno);
  568. }
  569. else
  570. {
  571. // split the sequence
  572. // construct the second sequence from CSeqNo::incseq(seqno) to the original sequence end
  573. // located at "loc + 1"
  574. loc = (loc + 1) % m_iSize;
  575. m_caSeq[loc].seqstart = CSeqNo::incseq(seqno);
  576. if (CSeqNo::seqcmp(m_caSeq[i].seqend, m_caSeq[loc].seqstart) > 0)
  577. m_caSeq[loc].seqend = m_caSeq[i].seqend;
  578. // the first (original) sequence is between the original sequence start to CSeqNo::decseq(seqno)
  579. if (seqno == CSeqNo::incseq(m_caSeq[i].seqstart))
  580. m_caSeq[i].seqend = SRT_SEQNO_NONE;
  581. else
  582. m_caSeq[i].seqend = CSeqNo::decseq(seqno);
  583. // update the list pointer
  584. m_caSeq[loc].inext = m_caSeq[i].inext;
  585. m_caSeq[i].inext = loc;
  586. m_caSeq[loc].iprior = i;
  587. if (m_iTail == i)
  588. m_iTail = loc;
  589. else
  590. m_caSeq[m_caSeq[loc].inext].iprior = loc;
  591. }
  592. m_iLength--;
  593. return true;
  594. }
  595. bool srt::CRcvLossList::remove(int32_t seqno1, int32_t seqno2)
  596. {
  597. if (CSeqNo::seqcmp(seqno1, seqno2) > 0)
  598. {
  599. return false;
  600. }
  601. for (int32_t i = seqno1; CSeqNo::seqcmp(i, seqno2) <= 0; i = CSeqNo::incseq(i))
  602. {
  603. remove(i);
  604. }
  605. return true;
  606. }
  607. int32_t srt::CRcvLossList::removeUpTo(int32_t seqno_last)
  608. {
  609. int32_t first = getFirstLostSeq();
  610. if (first == SRT_SEQNO_NONE)
  611. {
  612. //HLOGC(tslog.Debug, log << "rcv-loss: DROP to %" << seqno_last << " - empty list");
  613. return first; // empty, so nothing to remove
  614. }
  615. if (CSeqNo::seqcmp(seqno_last, first) < 0)
  616. {
  617. //HLOGC(tslog.Debug, log << "rcv-loss: DROP to %" << seqno_last << " - first %" << first << " is newer, exitting");
  618. return first; // seqno_last older than first - nothing to remove
  619. }
  620. HLOGC(tslog.Debug, log << "rcv-loss: DROP to %" << seqno_last << " ...");
  621. // NOTE: seqno_last is past-the-end here. Removed are only seqs
  622. // that are earlier than this.
  623. for (int32_t i = first; CSeqNo::seqcmp(i, seqno_last) <= 0; i = CSeqNo::incseq(i))
  624. {
  625. //HLOGC(tslog.Debug, log << "... removing %" << i);
  626. remove(i);
  627. }
  628. return first;
  629. }
  630. bool srt::CRcvLossList::find(int32_t seqno1, int32_t seqno2) const
  631. {
  632. if (0 == m_iLength)
  633. return false;
  634. int p = m_iHead;
  635. while (-1 != p)
  636. {
  637. if ((CSeqNo::seqcmp(m_caSeq[p].seqstart, seqno1) == 0) ||
  638. ((CSeqNo::seqcmp(m_caSeq[p].seqstart, seqno1) > 0) && (CSeqNo::seqcmp(m_caSeq[p].seqstart, seqno2) <= 0)) ||
  639. ((CSeqNo::seqcmp(m_caSeq[p].seqstart, seqno1) < 0) && (m_caSeq[p].seqend != SRT_SEQNO_NONE) &&
  640. CSeqNo::seqcmp(m_caSeq[p].seqend, seqno1) >= 0))
  641. return true;
  642. p = m_caSeq[p].inext;
  643. }
  644. return false;
  645. }
  646. int srt::CRcvLossList::getLossLength() const
  647. {
  648. return m_iLength;
  649. }
  650. int32_t srt::CRcvLossList::getFirstLostSeq() const
  651. {
  652. if (0 == m_iLength)
  653. return SRT_SEQNO_NONE;
  654. return m_caSeq[m_iHead].seqstart;
  655. }
  656. void srt::CRcvLossList::getLossArray(int32_t* array, int& len, int limit)
  657. {
  658. len = 0;
  659. int i = m_iHead;
  660. while ((len < limit - 1) && (-1 != i))
  661. {
  662. array[len] = m_caSeq[i].seqstart;
  663. if (SRT_SEQNO_NONE != m_caSeq[i].seqend)
  664. {
  665. // there are more than 1 loss in the sequence
  666. array[len] |= LOSSDATA_SEQNO_RANGE_FIRST;
  667. ++len;
  668. array[len] = m_caSeq[i].seqend;
  669. }
  670. ++len;
  671. i = m_caSeq[i].inext;
  672. }
  673. }
  674. srt::CRcvFreshLoss::CRcvFreshLoss(int32_t seqlo, int32_t seqhi, int initial_age)
  675. : ttl(initial_age)
  676. , timestamp(steady_clock::now())
  677. {
  678. seq[0] = seqlo;
  679. seq[1] = seqhi;
  680. }
  681. srt::CRcvFreshLoss::Emod srt::CRcvFreshLoss::revoke(int32_t sequence)
  682. {
  683. int32_t diffbegin = CSeqNo::seqcmp(sequence, seq[0]);
  684. int32_t diffend = CSeqNo::seqcmp(sequence, seq[1]);
  685. if (diffbegin < 0 || diffend > 0)
  686. {
  687. return NONE; // not within the range at all.
  688. }
  689. if (diffbegin == 0)
  690. {
  691. if (diffend == 0) // exactly at begin and end
  692. {
  693. return DELETE;
  694. }
  695. // only exactly at begin. Shrink the range
  696. seq[0] = CSeqNo::incseq(seq[0]);
  697. return STRIPPED;
  698. }
  699. if (diffend == 0) // exactly at end
  700. {
  701. seq[1] = CSeqNo::decseq(seq[1]);
  702. return STRIPPED;
  703. }
  704. return SPLIT;
  705. }
  706. srt::CRcvFreshLoss::Emod srt::CRcvFreshLoss::revoke(int32_t lo, int32_t hi)
  707. {
  708. // This should only if the range lo-hi is anyhow covered by seq[0]-seq[1].
  709. // Note: if the checked item contains sequences that are OLDER
  710. // than the oldest sequence in this range, they should be deleted,
  711. // even though this wasn't explicitly requested.
  712. // LOHI: <lo, hi>
  713. // ITEM: <lo, hi> <--- delete
  714. // If the sequence range is older than the range to be revoked,
  715. // delete it anyway.
  716. if (lo != SRT_SEQNO_NONE && CSeqNo::seqcmp(lo, seq[1]) > 0)
  717. return DELETE;
  718. // IF <lo> is NONE, then rely simply on that item.hi <% arg.hi,
  719. // which is a condition at the end.
  720. // LOHI: <lo, hi>
  721. // ITEM: <lo, hi> <-- NOTFOUND
  722. // This element is newer than the given sequence, so match failed.
  723. if (CSeqNo::seqcmp(hi, seq[0]) < 0)
  724. return NONE;
  725. // LOHI: <lo, hi>
  726. // ITEM: <lo, ! hi>
  727. // RESULT: <lo, hi>
  728. // 2. If the 'hi' is in the middle (less than seq[1]), delete partially.
  729. // That is, take care of this range for itself and return STRIPPED.
  730. if (CSeqNo::seqcmp(hi, seq[1]) < 0)
  731. {
  732. seq[0] = CSeqNo::incseq(hi);
  733. return STRIPPED;
  734. }
  735. // LOHI: <lo, hi>
  736. // ITEM: <lo, ! hi>
  737. // RESULT: DELETE.
  738. // 3. Otherwise delete the record, even if this was covering only part of this range.
  739. // This is not possible that the sequences OLDER THAN THIS are not required to be
  740. // revoken together with this one.
  741. return DELETE;
  742. }
  743. bool srt::CRcvFreshLoss::removeOne(std::deque<CRcvFreshLoss>& w_container, int32_t sequence, int* pw_had_ttl)
  744. {
  745. for (size_t i = 0; i < w_container.size(); ++i)
  746. {
  747. const int had_ttl = w_container[i].ttl;
  748. Emod wh = w_container[i].revoke(sequence);
  749. if (wh == NONE)
  750. continue; // Not found. Search again.
  751. if (wh == DELETE) // ... oo ... x ... o ... => ... oo ... o ...
  752. {
  753. // Removed the only element in the record - remove the record.
  754. w_container.erase(w_container.begin() + i);
  755. }
  756. else if (wh == SPLIT) // ... ooxooo ... => ... oo ... ooo ...
  757. {
  758. // Create a new element that will hold the upper part of the range,
  759. // and the found one modify to be the lower part of the range.
  760. // Keep the current end-of-sequence value for the second element
  761. int32_t next_end = w_container[i].seq[1];
  762. // seq-1 set to the end of this element
  763. w_container[i].seq[1] = CSeqNo::decseq(sequence);
  764. // seq+1 set to the begin of the next element
  765. int32_t next_begin = CSeqNo::incseq(sequence);
  766. // Use position of the NEXT element because insertion happens BEFORE pointed element.
  767. // Use the same TTL (will stay the same in the other one).
  768. w_container.insert(w_container.begin() + i + 1,
  769. CRcvFreshLoss(next_begin, next_end, w_container[i].ttl));
  770. }
  771. // For STRIPPED: ... xooo ... => ... ooo ...
  772. // i.e. there's nothing to do.
  773. // Every loss is unique. We're done here.
  774. if (pw_had_ttl)
  775. *pw_had_ttl = had_ttl;
  776. return true;
  777. }
  778. if (pw_had_ttl)
  779. *pw_had_ttl = 0;
  780. return false;
  781. }