congctl.h 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  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. #ifndef INC_SRT_CONGCTL_H
  11. #define INC_SRT_CONGCTL_H
  12. #include <algorithm>
  13. #include <map>
  14. #include <string>
  15. #include <utility>
  16. namespace srt {
  17. class CUDT;
  18. class SrtCongestionControlBase;
  19. typedef SrtCongestionControlBase* srtcc_create_t(srt::CUDT* parent);
  20. class SrtCongestion
  21. {
  22. // Temporarily changed to linear searching, until this is exposed
  23. // for a user-defined controller.
  24. // Note that this is a pointer to function :)
  25. static const size_t N_CONTROLLERS = 2;
  26. // The first/second is to mimic the map.
  27. typedef struct { const char* first; srtcc_create_t* second; } NamePtr;
  28. static NamePtr congctls[N_CONTROLLERS];
  29. // This is a congctl container.
  30. SrtCongestionControlBase* congctl;
  31. size_t selector;
  32. void Check();
  33. public:
  34. // If you predict to allow something to be done on controller also
  35. // before it is configured, call this first. If you need it configured,
  36. // you can rely on Check().
  37. bool ready() { return congctl; }
  38. SrtCongestionControlBase* operator->() { Check(); return congctl; }
  39. // In the beginning it's uninitialized
  40. SrtCongestion(): congctl(), selector(N_CONTROLLERS) {}
  41. struct IsName
  42. {
  43. const std::string n;
  44. IsName(const std::string& nn): n(nn) {}
  45. bool operator()(NamePtr np) { return n == np.first; }
  46. };
  47. static NamePtr* find(const std::string& name)
  48. {
  49. NamePtr* end = congctls+N_CONTROLLERS;
  50. NamePtr* try_selector = std::find_if(congctls, end, IsName(name));
  51. return try_selector != end ? try_selector : NULL;
  52. }
  53. static bool exists(const std::string& name)
  54. {
  55. return find(name);
  56. }
  57. // You can call select() multiple times, until finally
  58. // the 'configure' method is called.
  59. bool select(const std::string& name)
  60. {
  61. NamePtr* try_selector = find(name);
  62. if (!try_selector)
  63. return false;
  64. selector = try_selector - congctls;
  65. return true;
  66. }
  67. std::string selected_name()
  68. {
  69. if (selector == N_CONTROLLERS)
  70. return "";
  71. return congctls[selector].first;
  72. }
  73. // Copy constructor - important when listener-spawning
  74. // Things being done:
  75. // 1. The congctl is individual, so don't copy it. Set NULL.
  76. // 2. The selected name is copied so that it's configured correctly.
  77. SrtCongestion(const SrtCongestion& source): congctl(), selector(source.selector) {}
  78. void operator=(const SrtCongestion& source) { congctl = 0; selector = source.selector; }
  79. // This function will be called by the parent CUDT
  80. // in appropriate time. It should select appropriate
  81. // congctl basing on the value in selector, then
  82. // pin oneself in into CUDT for receiving event signals.
  83. bool configure(srt::CUDT* parent);
  84. // This function will intentionally delete the contained object.
  85. // This makes future calls to ready() return false. Calling
  86. // configure on it again will create it again.
  87. void dispose();
  88. // Will delete the pinned in congctl object.
  89. // This must be defined in *.cpp file due to virtual
  90. // destruction.
  91. ~SrtCongestion();
  92. enum RexmitMethod
  93. {
  94. SRM_LATEREXMIT,
  95. SRM_FASTREXMIT
  96. };
  97. enum TransAPI
  98. {
  99. STA_MESSAGE = 0x1, // sendmsg/recvmsg functions
  100. STA_BUFFER = 0x2, // send/recv functions
  101. STA_FILE = 0x3, // sendfile/recvfile functions
  102. };
  103. enum TransDir
  104. {
  105. STAD_RECV = 0,
  106. STAD_SEND = 1
  107. };
  108. };
  109. class CPacket;
  110. class SrtCongestionControlBase
  111. {
  112. protected:
  113. // Here can be some common fields
  114. srt::CUDT* m_parent;
  115. double m_dPktSndPeriod;
  116. double m_dCWndSize;
  117. //int m_iBandwidth; // NOT REQUIRED. Use m_parent->bandwidth() instead.
  118. double m_dMaxCWndSize;
  119. //int m_iMSS; // NOT REQUIRED. Use m_parent->MSS() instead.
  120. //int32_t m_iSndCurrSeqNo; // NOT REQUIRED. Use m_parent->sndSeqNo().
  121. //int m_iRcvRate; // NOT REQUIRED. Use m_parent->deliveryRate() instead.
  122. //int m_RTT; // NOT REQUIRED. Use m_parent->SRTT() instead.
  123. //char* m_pcParam; // Used to access m_llMaxBw. Use m_parent->maxBandwidth() instead.
  124. // Constructor in protected section so that this class is semi-abstract.
  125. SrtCongestionControlBase(srt::CUDT* parent);
  126. public:
  127. // This could be also made abstract, but this causes a linkage
  128. // problem in C++: this would constitute the first virtual method,
  129. // and C++ compiler uses the location of the first virtual method as the
  130. // file to which it also emits the virtual call table. When this is
  131. // abstract, there would have to be simultaneously either defined
  132. // an empty method in congctl.cpp file (obviously never called),
  133. // or simply left empty body here.
  134. virtual ~SrtCongestionControlBase() { }
  135. // All these functions that return values interesting for processing
  136. // by CUDT can be overridden. Normally they should refer to the fields
  137. // and these fields should keep the values as a state.
  138. virtual double pktSndPeriod_us() { return m_dPktSndPeriod; }
  139. virtual double cgWindowSize() { return m_dCWndSize; }
  140. virtual double cgWindowMaxSize() { return m_dMaxCWndSize; }
  141. virtual int64_t sndBandwidth() { return 0; }
  142. // If user-defined, will return nonzero value.
  143. // If not, it will be internally calculated.
  144. virtual int RTO() { return 0; }
  145. // Maximum number of packets to trigger ACK sending.
  146. // Specifies the number of packets to receive before sending the ACK.
  147. // Used by CUDT together with ACKTimeout_us() to trigger ACK packet sending.
  148. virtual int ACKMaxPackets() const { return 0; }
  149. // Periodical interval to send an ACK, in microseconds.
  150. // If user-defined, this value will be used to calculate
  151. // the next ACK time every time ACK is considered to be sent (see CUDT::checkTimers).
  152. // Otherwise this will be calculated internally in CUDT, normally taken
  153. // from CUDT::COMM_SYN_INTERVAL_US.
  154. virtual int ACKTimeout_us() const { return 0; }
  155. // Called when the settings concerning m_llMaxBW were changed.
  156. // Arg 1: value of CUDT's m_config.m_llMaxBW
  157. // Arg 2: value calculated out of CUDT's m_config.llInputBW and m_config.iOverheadBW.
  158. virtual void updateBandwidth(int64_t, int64_t) {}
  159. virtual bool needsQuickACK(const srt::CPacket&)
  160. {
  161. return false;
  162. }
  163. // Particular controller is allowed to agree or disagree on the use of particular API.
  164. virtual bool checkTransArgs(SrtCongestion::TransAPI , SrtCongestion::TransDir , const char* /*buffer*/, size_t /*size*/, int /*ttl*/, bool /*inorder*/)
  165. {
  166. return true;
  167. }
  168. virtual SrtCongestion::RexmitMethod rexmitMethod() = 0; // Implementation enforced.
  169. virtual int64_t updateNAKInterval(int64_t nakint_us, int rcv_speed, size_t loss_length)
  170. {
  171. if (rcv_speed > 0)
  172. nakint_us += (loss_length * int64_t(1000000) / rcv_speed);
  173. return nakint_us;
  174. }
  175. virtual int64_t minNAKInterval()
  176. {
  177. return 0; // Leave default
  178. }
  179. };
  180. } // namespace srt
  181. #endif