common.h 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427
  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 - 2009, 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 08/01/2009
  42. modified by
  43. Haivision Systems Inc.
  44. *****************************************************************************/
  45. #ifndef INC_SRT_COMMON_H
  46. #define INC_SRT_COMMON_H
  47. #include <memory>
  48. #include <cstdlib>
  49. #include <cstdio>
  50. #ifndef _WIN32
  51. #include <sys/time.h>
  52. #include <sys/uio.h>
  53. #else
  54. // #include <winsock2.h>
  55. //#include <windows.h>
  56. #endif
  57. #include "srt.h"
  58. #include "utilities.h"
  59. #include "sync.h"
  60. #include "netinet_any.h"
  61. #include "packetfilter_api.h"
  62. // System-independent errno
  63. #ifndef _WIN32
  64. #define NET_ERROR errno
  65. #else
  66. #define NET_ERROR WSAGetLastError()
  67. #endif
  68. #ifdef _DEBUG
  69. #include <assert.h>
  70. #define SRT_ASSERT(cond) assert(cond)
  71. #else
  72. #define SRT_ASSERT(cond)
  73. #endif
  74. #if HAVE_FULL_CXX11
  75. #define SRT_STATIC_ASSERT(cond, msg) static_assert(cond, msg)
  76. #else
  77. #define SRT_STATIC_ASSERT(cond, msg)
  78. #endif
  79. #include <exception>
  80. namespace srt_logging
  81. {
  82. std::string SockStatusStr(SRT_SOCKSTATUS s);
  83. #if ENABLE_BONDING
  84. std::string MemberStatusStr(SRT_MEMBERSTATUS s);
  85. #endif
  86. }
  87. namespace srt
  88. {
  89. // Class CUDTException exposed for C++ API.
  90. // This is actually useless, unless you'd use a DIRECT C++ API,
  91. // however there's no such API so far. The current C++ API for UDT/SRT
  92. // is predicted to NEVER LET ANY EXCEPTION out of implementation,
  93. // so it's useless to catch this exception anyway.
  94. class CUDTException: public std::exception
  95. {
  96. public:
  97. CUDTException(CodeMajor major = MJ_SUCCESS, CodeMinor minor = MN_NONE, int err = -1);
  98. virtual ~CUDTException() ATR_NOTHROW {}
  99. /// Get the description of the exception.
  100. /// @return Text message for the exception description.
  101. const char* getErrorMessage() const ATR_NOTHROW;
  102. virtual const char* what() const ATR_NOTHROW ATR_OVERRIDE
  103. {
  104. return getErrorMessage();
  105. }
  106. std::string getErrorString() const;
  107. /// Get the system errno for the exception.
  108. /// @return errno.
  109. int getErrorCode() const;
  110. /// Get the system network errno for the exception.
  111. /// @return errno.
  112. int getErrno() const;
  113. /// Clear the error code.
  114. void clear();
  115. private:
  116. CodeMajor m_iMajor; // major exception categories
  117. CodeMinor m_iMinor; // for specific error reasons
  118. int m_iErrno; // errno returned by the system if there is any
  119. mutable std::string m_strMsg; // text error message (cache)
  120. std::string m_strAPI; // the name of UDT function that returns the error
  121. std::string m_strDebug; // debug information, set to the original place that causes the error
  122. public: // Legacy Error Code
  123. static const int EUNKNOWN = SRT_EUNKNOWN;
  124. static const int SUCCESS = SRT_SUCCESS;
  125. static const int ECONNSETUP = SRT_ECONNSETUP;
  126. static const int ENOSERVER = SRT_ENOSERVER;
  127. static const int ECONNREJ = SRT_ECONNREJ;
  128. static const int ESOCKFAIL = SRT_ESOCKFAIL;
  129. static const int ESECFAIL = SRT_ESECFAIL;
  130. static const int ECONNFAIL = SRT_ECONNFAIL;
  131. static const int ECONNLOST = SRT_ECONNLOST;
  132. static const int ENOCONN = SRT_ENOCONN;
  133. static const int ERESOURCE = SRT_ERESOURCE;
  134. static const int ETHREAD = SRT_ETHREAD;
  135. static const int ENOBUF = SRT_ENOBUF;
  136. static const int EFILE = SRT_EFILE;
  137. static const int EINVRDOFF = SRT_EINVRDOFF;
  138. static const int ERDPERM = SRT_ERDPERM;
  139. static const int EINVWROFF = SRT_EINVWROFF;
  140. static const int EWRPERM = SRT_EWRPERM;
  141. static const int EINVOP = SRT_EINVOP;
  142. static const int EBOUNDSOCK = SRT_EBOUNDSOCK;
  143. static const int ECONNSOCK = SRT_ECONNSOCK;
  144. static const int EINVPARAM = SRT_EINVPARAM;
  145. static const int EINVSOCK = SRT_EINVSOCK;
  146. static const int EUNBOUNDSOCK = SRT_EUNBOUNDSOCK;
  147. static const int ESTREAMILL = SRT_EINVALMSGAPI;
  148. static const int EDGRAMILL = SRT_EINVALBUFFERAPI;
  149. static const int ENOLISTEN = SRT_ENOLISTEN;
  150. static const int ERDVNOSERV = SRT_ERDVNOSERV;
  151. static const int ERDVUNBOUND = SRT_ERDVUNBOUND;
  152. static const int EINVALMSGAPI = SRT_EINVALMSGAPI;
  153. static const int EINVALBUFFERAPI = SRT_EINVALBUFFERAPI;
  154. static const int EDUPLISTEN = SRT_EDUPLISTEN;
  155. static const int ELARGEMSG = SRT_ELARGEMSG;
  156. static const int EINVPOLLID = SRT_EINVPOLLID;
  157. static const int EASYNCFAIL = SRT_EASYNCFAIL;
  158. static const int EASYNCSND = SRT_EASYNCSND;
  159. static const int EASYNCRCV = SRT_EASYNCRCV;
  160. static const int ETIMEOUT = SRT_ETIMEOUT;
  161. static const int ECONGEST = SRT_ECONGEST;
  162. static const int EPEERERR = SRT_EPEERERR;
  163. };
  164. enum UDTSockType
  165. {
  166. UDT_UNDEFINED = 0, // initial trap representation
  167. UDT_STREAM = 1,
  168. UDT_DGRAM
  169. };
  170. /// The message types used by UDT protocol. This is a part of UDT
  171. /// protocol and should never be changed.
  172. enum UDTMessageType
  173. {
  174. UMSG_HANDSHAKE = 0, //< Connection Handshake. Control: see @a CHandShake.
  175. UMSG_KEEPALIVE = 1, //< Keep-alive.
  176. UMSG_ACK = 2, //< Acknowledgement. Control: past-the-end sequence number up to which packets have been received.
  177. UMSG_LOSSREPORT = 3, //< Negative Acknowledgement (NAK). Control: Loss list.
  178. UMSG_CGWARNING = 4, //< Congestion warning.
  179. UMSG_SHUTDOWN = 5, //< Shutdown.
  180. UMSG_ACKACK = 6, //< Acknowledgement of Acknowledgement. Add info: The ACK sequence number
  181. UMSG_DROPREQ = 7, //< Message Drop Request. Add info: Message ID. Control Info: (first, last) number of the message.
  182. UMSG_PEERERROR = 8, //< Signal from the Peer side. Add info: Error code.
  183. // ... add extra code types here
  184. UMSG_END_OF_TYPES,
  185. UMSG_EXT = 0x7FFF //< For the use of user-defined control packets.
  186. };
  187. // This side's role is: INITIATOR prepares the environment first, and sends
  188. // appropriate information to the peer. The peer must be RESPONDER and be ready
  189. // to receive it. It's important for the encryption: the INITIATOR side generates
  190. // the KM, and sends it to RESPONDER. RESPONDER awaits KM received from the
  191. // INITIATOR. Note that in bidirectional mode - that is always with HSv5 - the
  192. // INITIATOR creates both sending and receiving contexts, then sends the key to
  193. // RESPONDER, which creates both sending and receiving contexts, using the same
  194. // key received from INITIATOR.
  195. //
  196. // The method of selection:
  197. //
  198. // In HSv4, it's always data sender (the party that sets SRTO_SENDER flag on the
  199. // socket) INITIATOR, and receiver - RESPONDER. The HSREQ and KMREQ are done
  200. // AFTER the UDT connection is done using UMSG_EXT extension messages. As this
  201. // is unidirectional, the INITIATOR prepares the sending context only, the
  202. // RESPONDER - receiving context only.
  203. //
  204. // In HSv5, for caller-listener configuration, it's simple: caller is INITIATOR,
  205. // listener is RESPONDER. In case of rendezvous the parties are equivalent,
  206. // so the role is resolved by "cookie contest". Rendezvous sockets both know
  207. // each other's cookie generated during the URQ_WAVEAHAND handshake phase.
  208. // The cookies are simply compared as integer numbers; the party which's cookie
  209. // is a greater number becomes an INITIATOR, and the other party becomes a
  210. // RESPONDER.
  211. //
  212. // The case of a draw - that both occasionally have baked identical cookies -
  213. // is treated as an extremely rare and virtually impossible case, so this
  214. // results in connection rejected.
  215. enum HandshakeSide
  216. {
  217. HSD_DRAW,
  218. HSD_INITIATOR, //< Side that initiates HSREQ/KMREQ. HSv4: data sender, HSv5: connecting socket or winner rendezvous socket
  219. HSD_RESPONDER //< Side that expects HSREQ/KMREQ from the peer. HSv4: data receiver, HSv5: accepted socket or loser rendezvous socket
  220. };
  221. // For debug
  222. std::string MessageTypeStr(UDTMessageType mt, uint32_t extt = 0);
  223. ////////////////////////////////////////////////////////////////////////////////
  224. // Commonly used by various reading facilities
  225. enum EReadStatus
  226. {
  227. RST_OK = 0, //< A new portion of data has been received
  228. RST_AGAIN, //< Nothing has been received, try again
  229. RST_ERROR = -1 //< Irrecoverable error, please close descriptor and stop reading.
  230. };
  231. enum EConnectStatus
  232. {
  233. CONN_ACCEPT = 0, //< Received final handshake that confirms connection established
  234. CONN_REJECT = -1, //< Error during processing handshake.
  235. CONN_CONTINUE = 1, //< induction->conclusion phase
  236. CONN_RENDEZVOUS = 2, //< pass to a separate rendezvous processing (HSv5 only)
  237. CONN_CONFUSED = 3, //< listener thinks it's connected, but caller missed conclusion
  238. CONN_RUNNING = 10, //< no connection in progress, already connected
  239. CONN_AGAIN = -2 //< No data was read, don't change any state.
  240. };
  241. enum EConnectMethod
  242. {
  243. COM_ASYNCHRO,
  244. COM_SYNCHRO
  245. };
  246. std::string ConnectStatusStr(EConnectStatus est);
  247. const int64_t BW_INFINITE = 1000000000/8; //Infinite=> 1 Gbps
  248. enum ETransmissionEvent
  249. {
  250. TEV_INIT, // --> After creation, and after any parameters were updated.
  251. TEV_ACK, // --> When handling UMSG_ACK - older CCC:onAck()
  252. TEV_ACKACK, // --> UDT does only RTT sync, can be read from CUDT::SRTT().
  253. TEV_LOSSREPORT, // --> When handling UMSG_LOSSREPORT - older CCC::onLoss()
  254. TEV_CHECKTIMER, // --> See TEV_CHT_REXMIT
  255. TEV_SEND, // --> When the packet is scheduled for sending - older CCC::onPktSent
  256. TEV_RECEIVE, // --> When a data packet was received - older CCC::onPktReceived
  257. TEV_CUSTOM, // --> probably dead call - older CCC::processCustomMsg
  258. TEV_SYNC, // --> Backup group. When rate estimation is derived from an active member, and update is needed.
  259. TEV_E_SIZE
  260. };
  261. std::string TransmissionEventStr(ETransmissionEvent ev);
  262. // Special parameter for TEV_CHECKTIMER
  263. enum ECheckTimerStage
  264. {
  265. TEV_CHT_INIT, // --> UDT: just update parameters, don't call any CCC::*
  266. TEV_CHT_FASTREXMIT, // --> not available on UDT
  267. TEV_CHT_REXMIT // --> CCC::onTimeout() in UDT
  268. };
  269. enum EInitEvent
  270. {
  271. TEV_INIT_RESET = 0,
  272. TEV_INIT_INPUTBW,
  273. TEV_INIT_OHEADBW
  274. };
  275. class CPacket;
  276. // XXX Use some more standard less hand-crafted solution, if possible
  277. // XXX Consider creating a mapping between TEV_* values and associated types,
  278. // so that the type is compiler-enforced when calling updateCC() and when
  279. // connecting signals to slots.
  280. struct EventVariant
  281. {
  282. enum Type {UNDEFINED, PACKET, ARRAY, ACK, STAGE, INIT} type;
  283. union U
  284. {
  285. const srt::CPacket* packet;
  286. int32_t ack;
  287. struct
  288. {
  289. const int32_t* ptr;
  290. size_t len;
  291. } array;
  292. ECheckTimerStage stage;
  293. EInitEvent init;
  294. } u;
  295. template<Type t>
  296. struct VariantFor;
  297. // Note: UNDEFINED and ARRAY don't have assignment operator.
  298. // For ARRAY you'll use 'set' function. For UNDEFINED there's nothing.
  299. explicit EventVariant(const srt::CPacket* arg)
  300. {
  301. type = PACKET;
  302. u.packet = arg;
  303. }
  304. explicit EventVariant(int32_t arg)
  305. {
  306. type = ACK;
  307. u.ack = arg;
  308. }
  309. explicit EventVariant(ECheckTimerStage arg)
  310. {
  311. type = STAGE;
  312. u.stage = arg;
  313. }
  314. explicit EventVariant(EInitEvent arg)
  315. {
  316. type = INIT;
  317. u.init = arg;
  318. }
  319. const int32_t* get_ptr() const
  320. {
  321. return u.array.ptr;
  322. }
  323. size_t get_len() const
  324. {
  325. return u.array.len;
  326. }
  327. void set(const int32_t* ptr, size_t len)
  328. {
  329. type = ARRAY;
  330. u.array.ptr = ptr;
  331. u.array.len = len;
  332. }
  333. EventVariant(const int32_t* ptr, size_t len)
  334. {
  335. set(ptr, len);
  336. }
  337. template<Type T>
  338. typename VariantFor<T>::type get() const
  339. {
  340. return u.*(VariantFor<T>::field());
  341. }
  342. };
  343. /*
  344. Maybe later.
  345. This had to be a solution for automatic extraction of the
  346. type hidden in particular EventArg for particular event so
  347. that it's not runtime-mistaken.
  348. In order that this make sense there would be required an array
  349. indexed by event id (just like a slot array m_Slots in CUDT),
  350. where the "type distiller" function would be extracted and then
  351. combined with the user-connected slot function this would call
  352. it already with correct type. Note that also the ConnectSignal
  353. function would have to get the signal id by template parameter,
  354. not function parameter. For example:
  355. m_parent->ConnectSignal<TEV_ACK>(SSLOT(updateOnSent));
  356. in which updateOnSent would have to receive an appropriate type.
  357. This has a disadvantage that you can't connect multiple signals
  358. with different argument types to the same slot, you'd have to
  359. make slot wrappers to translate arguments.
  360. It seems that a better idea would be to create binders that would
  361. translate the argument from EventArg to the correct type according
  362. to the rules imposed by particular event id. But I'd not make it
  363. until there's a green light on C++11 for SRT, so maybe in a far future.
  364. template <ETransmissionEvent type>
  365. class EventArgType;
  366. #define MAP_EVENT_TYPE(tev, tp) template<> class EventArgType<tev> { typedef tp type; }
  367. */
  368. // The 'type' field wouldn't be even necessary if we
  369. // use a full-templated version. TBD.
  370. template<> struct EventVariant::VariantFor<EventVariant::PACKET>
  371. {
  372. typedef const srt::CPacket* type;
  373. static type U::*field() {return &U::packet;}
  374. };
  375. template<> struct EventVariant::VariantFor<EventVariant::ACK>
  376. {
  377. typedef int32_t type;
  378. static type U::*field() { return &U::ack; }
  379. };
  380. template<> struct EventVariant::VariantFor<EventVariant::STAGE>
  381. {
  382. typedef ECheckTimerStage type;
  383. static type U::*field() { return &U::stage; }
  384. };
  385. template<> struct EventVariant::VariantFor<EventVariant::INIT>
  386. {
  387. typedef EInitEvent type;
  388. static type U::*field() { return &U::init; }
  389. };
  390. // Using a hand-crafted solution because there's a non-backward-compatible
  391. // change between C++03 and others on the way up to C++17 (and we want this
  392. // code to be compliant with all C++ standards):
  393. //
  394. // - there's std::mem_fun in C++03 - deprecated in C++11, removed in C++17
  395. // - std::function in C++11 would be perfect, but not in C++03
  396. // This can be changed in future to use C++11 way, but only after C++03
  397. // compatibility is finally abaondoned. Until then, this stays with a custom
  398. // class.
  399. class EventSlotBase
  400. {
  401. public:
  402. virtual void emit(ETransmissionEvent tev, EventVariant var) = 0;
  403. typedef void dispatcher_t(void* opaque, ETransmissionEvent tev, EventVariant var);
  404. virtual ~EventSlotBase() {}
  405. };
  406. class SimpleEventSlot: public EventSlotBase
  407. {
  408. public:
  409. void* opaque;
  410. dispatcher_t* dispatcher;
  411. SimpleEventSlot(void* op, dispatcher_t* disp): opaque(op), dispatcher(disp) {}
  412. void emit(ETransmissionEvent tev, EventVariant var) ATR_OVERRIDE
  413. {
  414. (*dispatcher)(opaque, tev, var);
  415. }
  416. };
  417. template <class Class>
  418. class ObjectEventSlot: public EventSlotBase
  419. {
  420. public:
  421. typedef void (Class::*method_ptr_t)(ETransmissionEvent tev, EventVariant var);
  422. method_ptr_t pm;
  423. Class* po;
  424. ObjectEventSlot(Class* o, method_ptr_t m): pm(m), po(o) {}
  425. void emit(ETransmissionEvent tev, EventVariant var) ATR_OVERRIDE
  426. {
  427. (po->*pm)(tev, var);
  428. }
  429. };
  430. struct EventSlot
  431. {
  432. mutable EventSlotBase* slot;
  433. // Create empty slot. Calls are ignored.
  434. EventSlot(): slot(0) {}
  435. // "Stealing" copy constructor, following the auto_ptr method.
  436. // This isn't very nice, but no other way to do it in C++03
  437. // without rvalue-reference and move.
  438. void moveFrom(const EventSlot& victim)
  439. {
  440. slot = victim.slot; // Should MOVE.
  441. victim.slot = 0;
  442. }
  443. EventSlot(const EventSlot& victim) { moveFrom(victim); }
  444. EventSlot& operator=(const EventSlot& victim) { moveFrom(victim); return *this; }
  445. EventSlot(void* op, EventSlotBase::dispatcher_t* disp)
  446. {
  447. slot = new SimpleEventSlot(op, disp);
  448. }
  449. template <class ObjectClass>
  450. EventSlot(ObjectClass* obj, typename ObjectEventSlot<ObjectClass>::method_ptr_t method)
  451. {
  452. slot = new ObjectEventSlot<ObjectClass>(obj, method);
  453. }
  454. void emit(ETransmissionEvent tev, EventVariant var)
  455. {
  456. if (!slot)
  457. return;
  458. slot->emit(tev, var);
  459. }
  460. ~EventSlot()
  461. {
  462. delete slot;
  463. }
  464. };
  465. // UDT Sequence Number 0 - (2^31 - 1)
  466. // seqcmp: compare two seq#, considering the wraping
  467. // seqlen: length from the 1st to the 2nd seq#, including both
  468. // seqoff: offset from the 2nd to the 1st seq#
  469. // incseq: increase the seq# by 1
  470. // decseq: decrease the seq# by 1
  471. // incseq: increase the seq# by a given offset
  472. class CSeqNo
  473. {
  474. int32_t value;
  475. public:
  476. explicit CSeqNo(int32_t v): value(v) {}
  477. // Comparison
  478. bool operator == (const CSeqNo& other) const { return other.value == value; }
  479. bool operator < (const CSeqNo& other) const
  480. {
  481. return seqcmp(value, other.value) < 0;
  482. }
  483. // The std::rel_ops namespace cannot be "imported"
  484. // as a whole into the class - it can only be used
  485. // in the application code.
  486. bool operator != (const CSeqNo& other) const { return other.value != value; }
  487. bool operator > (const CSeqNo& other) const { return other < *this; }
  488. bool operator >= (const CSeqNo& other) const
  489. {
  490. return seqcmp(value, other.value) >= 0;
  491. }
  492. bool operator <=(const CSeqNo& other) const
  493. {
  494. return seqcmp(value, other.value) <= 0;
  495. }
  496. // circular arithmetics
  497. friend int operator-(const CSeqNo& c1, const CSeqNo& c2)
  498. {
  499. return seqoff(c2.value, c1.value);
  500. }
  501. friend CSeqNo operator-(const CSeqNo& c1, int off)
  502. {
  503. return CSeqNo(decseq(c1.value, off));
  504. }
  505. friend CSeqNo operator+(const CSeqNo& c1, int off)
  506. {
  507. return CSeqNo(incseq(c1.value, off));
  508. }
  509. friend CSeqNo operator+(int off, const CSeqNo& c1)
  510. {
  511. return CSeqNo(incseq(c1.value, off));
  512. }
  513. CSeqNo& operator++()
  514. {
  515. value = incseq(value);
  516. return *this;
  517. }
  518. /// This behaves like seq1 - seq2, in comparison to numbers,
  519. /// and with the statement that only the sign of the result matters.
  520. /// Returns a negative value if seq1 < seq2,
  521. /// positive if seq1 > seq2, and zero if they are equal.
  522. /// The only correct application of this function is when you
  523. /// compare two values and it works faster than seqoff. However
  524. /// the result's meaning is only in its sign. DO NOT USE THE
  525. /// VALUE for any other purpose. It is not meant to be the
  526. /// distance between two sequence numbers.
  527. ///
  528. /// Example: to check if (seq1 %> seq2): seqcmp(seq1, seq2) > 0.
  529. /// Note: %> stands for "later than".
  530. inline static int seqcmp(int32_t seq1, int32_t seq2)
  531. {return (abs(seq1 - seq2) < m_iSeqNoTH) ? (seq1 - seq2) : (seq2 - seq1);}
  532. /// This function measures a length of the range from seq1 to seq2,
  533. /// including endpoints (seqlen(a, a) = 1; seqlen(a, a + 1) = 2),
  534. /// WITH A PRECONDITION that certainly @a seq1 is earlier than @a seq2.
  535. /// This can also include an enormously large distance between them,
  536. /// that is, exceeding the m_iSeqNoTH value (can be also used to test
  537. /// if this distance is larger).
  538. /// Prior to calling this function the caller must be certain that
  539. /// @a seq2 is a sequence coming from a later time than @a seq1,
  540. /// and that the distance does not exceed m_iMaxSeqNo.
  541. inline static int seqlen(int32_t seq1, int32_t seq2)
  542. {
  543. SRT_ASSERT(seq1 >= 0 && seq1 <= m_iMaxSeqNo);
  544. SRT_ASSERT(seq2 >= 0 && seq2 <= m_iMaxSeqNo);
  545. return (seq1 <= seq2) ? (seq2 - seq1 + 1) : (seq2 - seq1 + m_iMaxSeqNo + 2);
  546. }
  547. /// This behaves like seq2 - seq1, with the precondition that the true
  548. /// distance between two sequence numbers never exceeds m_iSeqNoTH.
  549. /// That is, if the difference in numeric values of these two arguments
  550. /// exceeds m_iSeqNoTH, it is treated as if the later of these two
  551. /// sequence numbers has overflown and actually a segment of the
  552. /// MAX+1 value should be added to it to get the proper result.
  553. ///
  554. /// Note: this function does more calculations than seqcmp, so it should
  555. /// be used if you need the exact distance between two sequences. If
  556. /// you are only interested with their relationship, use seqcmp.
  557. inline static int seqoff(int32_t seq1, int32_t seq2)
  558. {
  559. if (abs(seq1 - seq2) < m_iSeqNoTH)
  560. return seq2 - seq1;
  561. if (seq1 < seq2)
  562. return seq2 - seq1 - m_iMaxSeqNo - 1;
  563. return seq2 - seq1 + m_iMaxSeqNo + 1;
  564. }
  565. inline static int32_t incseq(int32_t seq)
  566. {return (seq == m_iMaxSeqNo) ? 0 : seq + 1;}
  567. inline static int32_t decseq(int32_t seq)
  568. {return (seq == 0) ? m_iMaxSeqNo : seq - 1;}
  569. inline static int32_t incseq(int32_t seq, int32_t inc)
  570. {return (m_iMaxSeqNo - seq >= inc) ? seq + inc : seq - m_iMaxSeqNo + inc - 1;}
  571. // m_iMaxSeqNo >= inc + sec --- inc + sec <= m_iMaxSeqNo
  572. // if inc + sec > m_iMaxSeqNo then return seq + inc - (m_iMaxSeqNo+1)
  573. inline static int32_t decseq(int32_t seq, int32_t dec)
  574. {
  575. // Check if seq - dec < 0, but before it would have happened
  576. if ( seq < dec )
  577. {
  578. int32_t left = dec - seq; // This is so many that is left after dragging dec to 0
  579. // So now decrement the (m_iMaxSeqNo+1) by "left"
  580. return m_iMaxSeqNo - left + 1;
  581. }
  582. return seq - dec;
  583. }
  584. static int32_t maxseq(int32_t seq1, int32_t seq2)
  585. {
  586. if (seqcmp(seq1, seq2) < 0)
  587. return seq2;
  588. return seq1;
  589. }
  590. public:
  591. static const int32_t m_iSeqNoTH = 0x3FFFFFFF; // threshold for comparing seq. no.
  592. static const int32_t m_iMaxSeqNo = 0x7FFFFFFF; // maximum sequence number used in UDT
  593. };
  594. ////////////////////////////////////////////////////////////////////////////////
  595. // UDT ACK Sub-sequence Number: 0 - (2^31 - 1)
  596. class CAckNo
  597. {
  598. public:
  599. inline static int32_t incack(int32_t ackno)
  600. {return (ackno == m_iMaxAckSeqNo) ? 0 : ackno + 1;}
  601. public:
  602. static const int32_t m_iMaxAckSeqNo = 0x7FFFFFFF; // maximum ACK sub-sequence number used in UDT
  603. };
  604. template <size_t BITS, uint32_t MIN = 0>
  605. class RollNumber
  606. {
  607. typedef RollNumber<BITS, MIN> this_t;
  608. typedef Bits<BITS, 0> number_t;
  609. uint32_t number;
  610. public:
  611. static const size_t OVER = number_t::mask+1;
  612. static const size_t HALF = (OVER-MIN)/2;
  613. private:
  614. static int Diff(uint32_t left, uint32_t right)
  615. {
  616. // UNExpected order, diff is negative
  617. if ( left < right )
  618. {
  619. int32_t diff = right - left;
  620. if ( diff >= int32_t(HALF) ) // over barrier
  621. {
  622. // It means that left is less than right because it was overflown
  623. // For example: left = 0x0005, right = 0xFFF0; diff = 0xFFEB > HALF
  624. left += OVER - MIN; // left was really 0x00010005, just narrowed.
  625. // Now the difference is 0x0015, not 0xFFFF0015
  626. }
  627. }
  628. else
  629. {
  630. int32_t diff = left - right;
  631. if ( diff >= int32_t(HALF) )
  632. {
  633. right += OVER - MIN;
  634. }
  635. }
  636. return left - right;
  637. }
  638. public:
  639. explicit RollNumber(uint32_t val): number(val)
  640. {
  641. }
  642. bool operator<(const this_t& right) const
  643. {
  644. int32_t ndiff = number - right.number;
  645. if (ndiff < -int32_t(HALF))
  646. {
  647. // it' like ndiff > 0
  648. return false;
  649. }
  650. if (ndiff > int32_t(HALF))
  651. {
  652. // it's like ndiff < 0
  653. return true;
  654. }
  655. return ndiff < 0;
  656. }
  657. bool operator>(const this_t& right) const
  658. {
  659. return right < *this;
  660. }
  661. bool operator==(const this_t& right) const
  662. {
  663. return number == right.number;
  664. }
  665. bool operator<=(const this_t& right) const
  666. {
  667. return !(*this > right);
  668. }
  669. bool operator>=(const this_t& right) const
  670. {
  671. return !(*this < right);
  672. }
  673. void operator++(int)
  674. {
  675. ++number;
  676. if (number > number_t::mask)
  677. number = MIN;
  678. }
  679. this_t& operator++() { (*this)++; return *this; }
  680. void operator--(int)
  681. {
  682. if (number == MIN)
  683. number = number_t::mask;
  684. else
  685. --number;
  686. }
  687. this_t& operator--() { (*this)--; return *this; }
  688. int32_t operator-(this_t right)
  689. {
  690. return Diff(this->number, right.number);
  691. }
  692. void operator+=(int32_t delta)
  693. {
  694. // NOTE: this condition in practice tests if delta is negative.
  695. // That's because `number` is always positive, so negated delta
  696. // can't be ever greater than this, unless it's negative.
  697. if (-delta > int64_t(number))
  698. {
  699. number = OVER - MIN + number + delta; // NOTE: delta is negative
  700. }
  701. else
  702. {
  703. number += delta;
  704. if (number >= OVER)
  705. number -= OVER - MIN;
  706. }
  707. }
  708. operator uint32_t() const { return number; }
  709. };
  710. ////////////////////////////////////////////////////////////////////////////////
  711. struct CIPAddress
  712. {
  713. static bool ipcmp(const struct sockaddr* addr1, const struct sockaddr* addr2, int ver = AF_INET);
  714. static void ntop(const struct sockaddr_any& addr, uint32_t ip[4]);
  715. static void pton(sockaddr_any& addr, const uint32_t ip[4], const sockaddr_any& peer);
  716. static std::string show(const struct sockaddr* adr);
  717. };
  718. ////////////////////////////////////////////////////////////////////////////////
  719. struct CMD5
  720. {
  721. static void compute(const char* input, unsigned char result[16]);
  722. };
  723. // Debug stats
  724. template <size_t SIZE>
  725. class StatsLossRecords
  726. {
  727. int32_t initseq;
  728. std::bitset<SIZE> array;
  729. public:
  730. StatsLossRecords(): initseq(SRT_SEQNO_NONE) {}
  731. // To check if this structure still keeps record of that sequence.
  732. // This is to check if the information about this not being found
  733. // is still reliable.
  734. bool exists(int32_t seq)
  735. {
  736. return initseq != SRT_SEQNO_NONE && CSeqNo::seqcmp(seq, initseq) >= 0;
  737. }
  738. int32_t base() { return initseq; }
  739. void clear()
  740. {
  741. initseq = SRT_SEQNO_NONE;
  742. array.reset();
  743. }
  744. void add(int32_t lo, int32_t hi)
  745. {
  746. int32_t end = CSeqNo::incseq(hi);
  747. for (int32_t i = lo; i != end; i = CSeqNo::incseq(i))
  748. add(i);
  749. }
  750. void add(int32_t seq)
  751. {
  752. if ( array.none() )
  753. {
  754. // May happen it wasn't initialized. Set it as initial loss sequence.
  755. initseq = seq;
  756. array[0] = true;
  757. return;
  758. }
  759. // Calculate the distance between this seq and the oldest one.
  760. int seqdiff = CSeqNo::seqoff(initseq, seq);
  761. if ( seqdiff > int(SIZE) )
  762. {
  763. // Size exceeded. Drop the oldest sequences.
  764. // First calculate how many must be removed.
  765. size_t toremove = seqdiff - SIZE;
  766. // Now, since that position, find the nearest 1
  767. while ( !array[toremove] && toremove <= SIZE )
  768. ++toremove;
  769. // All have to be dropped, so simply reset the array
  770. if ( toremove == SIZE )
  771. {
  772. initseq = seq;
  773. array[0] = true;
  774. return;
  775. }
  776. // Now do the shift of the first found 1 to position 0
  777. // and its index add to initseq
  778. initseq += toremove;
  779. seqdiff -= toremove;
  780. array >>= toremove;
  781. }
  782. // Now set appropriate bit that represents this seq
  783. array[seqdiff] = true;
  784. }
  785. StatsLossRecords& operator << (int32_t seq)
  786. {
  787. add(seq);
  788. return *this;
  789. }
  790. void remove(int32_t seq)
  791. {
  792. // Check if is in range. If not, ignore.
  793. int seqdiff = CSeqNo::seqoff(initseq, seq);
  794. if ( seqdiff < 0 )
  795. return; // already out of array
  796. if ( seqdiff > SIZE )
  797. return; // never was added!
  798. array[seqdiff] = true;
  799. }
  800. bool find(int32_t seq) const
  801. {
  802. int seqdiff = CSeqNo::seqoff(initseq, seq);
  803. if ( seqdiff < 0 )
  804. return false; // already out of array
  805. if ( size_t(seqdiff) > SIZE )
  806. return false; // never was added!
  807. return array[seqdiff];
  808. }
  809. #if HAVE_CXX11
  810. std::string to_string() const
  811. {
  812. std::string out;
  813. for (size_t i = 0; i < SIZE; ++i)
  814. {
  815. if ( array[i] )
  816. out += std::to_string(initseq+i) + " ";
  817. }
  818. return out;
  819. }
  820. #endif
  821. };
  822. // There are some better or worse things you can find outside,
  823. // there's also boost::circular_buffer, but it's too overspoken
  824. // to be included here. We also can't rely on boost. Maybe in future
  825. // when it's added to the standard and SRT can heighten C++ standard
  826. // requirements; until then it needs this replacement.
  827. template <class Value>
  828. class CircularBuffer
  829. {
  830. #ifdef SRT_TEST_CIRCULAR_BUFFER
  831. public:
  832. #endif
  833. int m_iSize;
  834. Value* m_aStorage;
  835. int m_xBegin;
  836. int m_xEnd;
  837. static void destr(Value& v)
  838. {
  839. v.~Value();
  840. }
  841. static void constr(Value& v)
  842. {
  843. new ((void*)&v) Value();
  844. }
  845. template <class V>
  846. static void constr(Value& v, const V& source)
  847. {
  848. new ((void*)&v) Value(source);
  849. }
  850. // Wipe the copy constructor
  851. CircularBuffer(const CircularBuffer&);
  852. public:
  853. typedef Value value_type;
  854. CircularBuffer(int size)
  855. :m_iSize(size+1),
  856. m_xBegin(0),
  857. m_xEnd(0)
  858. {
  859. // We reserve one spare element just for a case.
  860. if (size == 0)
  861. m_aStorage = 0;
  862. else
  863. m_aStorage = (Value*)::operator new (sizeof(Value) * m_iSize);
  864. }
  865. void set_capacity(int size)
  866. {
  867. reset();
  868. // This isn't called resize (the size is 0 after the operation)
  869. // nor reserve (the existing elements are removed).
  870. if (size != m_iSize)
  871. {
  872. if (m_aStorage)
  873. ::operator delete (m_aStorage);
  874. m_iSize = size+1;
  875. m_aStorage = (Value*)::operator new (sizeof(Value) * m_iSize);
  876. }
  877. }
  878. void reset()
  879. {
  880. if (m_xEnd < m_xBegin)
  881. {
  882. for (int i = m_xBegin; i < m_iSize; ++i)
  883. destr(m_aStorage[i]);
  884. for (int i = 0; i < m_xEnd; ++i)
  885. destr(m_aStorage[i]);
  886. }
  887. else
  888. {
  889. for (int i = m_xBegin; i < m_xEnd; ++i)
  890. destr(m_aStorage[i]);
  891. }
  892. m_xBegin = 0;
  893. m_xEnd = 0;
  894. }
  895. ~CircularBuffer()
  896. {
  897. reset();
  898. ::operator delete (m_aStorage);
  899. }
  900. // In the beginning, m_xBegin == m_xEnd, which
  901. // means that the container is empty. Adding can
  902. // be done exactly at the place pointed to by m_xEnd,
  903. // and m_xEnd must be then shifted to the next unused one.
  904. // When (m_xEnd + 1) % m_zSize == m_xBegin, the container
  905. // is considered full and the element adding is rejected.
  906. //
  907. // This container is not designed to be STL-compatible
  908. // because it doesn't make much sense. It's not a typical
  909. // container, even treated as random-access container.
  910. int shift(int basepos, int shift) const
  911. {
  912. return (basepos + shift) % m_iSize;
  913. }
  914. // Simplified versions with ++ and --; avoid using division instruction
  915. int shift_forward(int basepos) const
  916. {
  917. if (++basepos == m_iSize)
  918. return 0;
  919. return basepos;
  920. }
  921. int shift_backward(int basepos) const
  922. {
  923. if (basepos == 0)
  924. return m_iSize-1;
  925. return --basepos;
  926. }
  927. int size() const
  928. {
  929. // Count the distance between begin and end
  930. if (m_xEnd < m_xBegin)
  931. {
  932. // Use "merge two slices" method.
  933. // (BEGIN - END) is the distance of the unused
  934. // space in the middle. Used space is left to END
  935. // and right to BEGIN, the sum of the left and right
  936. // slice and the free space is the size.
  937. // This includes also a case when begin and end
  938. // are equal, which means that it's empty, so
  939. // spaceleft() should simply return m_iSize.
  940. return m_iSize - (m_xBegin - m_xEnd);
  941. }
  942. return m_xEnd - m_xBegin;
  943. }
  944. bool empty() const { return m_xEnd == m_xBegin; }
  945. size_t capacity() const { return m_iSize-1; }
  946. int spaceleft() const
  947. {
  948. // It's kinda tautology, but this will be more efficient.
  949. if (m_xEnd < m_xBegin)
  950. {
  951. return m_xBegin - m_xEnd;
  952. }
  953. return m_iSize - (m_xEnd - m_xBegin);
  954. }
  955. // This is rather written for testing and rather won't
  956. // be used in the real code.
  957. template <class V>
  958. int push(const V& v)
  959. {
  960. // Check if you can add
  961. int nend = shift_forward(m_xEnd);
  962. if ( nend == m_xBegin)
  963. return -1;
  964. constr(m_aStorage[m_xEnd], v);
  965. m_xEnd = nend;
  966. return size() - 1;
  967. }
  968. Value* push()
  969. {
  970. int nend = shift_forward(m_xEnd);
  971. if ( nend == m_xBegin)
  972. return NULL;
  973. Value* pos = &m_aStorage[m_xEnd];
  974. constr(*pos);
  975. m_xEnd = nend;
  976. return pos;
  977. }
  978. bool access(int position, Value*& w_v)
  979. {
  980. // This version doesn't require the boolean value to report
  981. // whether the element is newly added because it never adds
  982. // a new element.
  983. int ipos, vend;
  984. if (!INT_checkAccess(position, ipos, vend))
  985. return false;
  986. if (ipos >= vend) // exceeds
  987. return false;
  988. INT_access(ipos, false, (w_v)); // never exceeds
  989. return true;
  990. }
  991. // Ok, now it's the real deal.
  992. bool access(int position, Value*& w_v, bool& w_isnew)
  993. {
  994. int ipos, vend;
  995. if (!INT_checkAccess(position, ipos, vend))
  996. return false;
  997. bool exceeds = (ipos >= vend);
  998. w_isnew = exceeds;
  999. INT_access(ipos, exceeds, (w_v));
  1000. return true;
  1001. }
  1002. private:
  1003. bool INT_checkAccess(int position, int& ipos, int& vend)
  1004. {
  1005. // Reject if no space left.
  1006. // Also INVAL if negative position.
  1007. if (position >= (m_iSize-1) || position < 0)
  1008. return false; // That's way to far, we can't even calculate
  1009. ipos = m_xBegin + position;
  1010. vend = m_xEnd;
  1011. if (m_xEnd < m_xBegin)
  1012. vend += m_iSize;
  1013. return true;
  1014. }
  1015. void INT_access(int ipos, bool exceeds, Value*& w_v)
  1016. {
  1017. if (ipos >= m_iSize)
  1018. ipos -= m_iSize; // wrap around
  1019. // Update the end position.
  1020. if (exceeds)
  1021. {
  1022. int nend = ipos+1;
  1023. if (m_xEnd > nend)
  1024. {
  1025. // Here we know that the current index exceeds the size.
  1026. // So, if this happens, it's m_xEnd wrapped around.
  1027. // Clear out elements in two slices:
  1028. // - from m_xEnd to m_iSize-1
  1029. // - from 0 to nend
  1030. for (int i = m_xEnd; i < m_iSize; ++i)
  1031. constr(m_aStorage[i]);
  1032. for (int i = 0; i < nend; ++i)
  1033. constr(m_aStorage[i]);
  1034. }
  1035. else
  1036. {
  1037. for (int i = m_xEnd; i < nend; ++i)
  1038. constr(m_aStorage[i]);
  1039. }
  1040. if (nend == m_iSize)
  1041. nend = 0;
  1042. m_xEnd = nend;
  1043. }
  1044. w_v = &m_aStorage[ipos];
  1045. }
  1046. public:
  1047. bool set(int position, const Value& newval, bool overwrite = true)
  1048. {
  1049. Value* pval = 0;
  1050. bool isnew = false;
  1051. if (!access(position, (pval), (isnew)))
  1052. return false;
  1053. if (isnew || overwrite)
  1054. *pval = newval;
  1055. return true;
  1056. }
  1057. template<class Updater>
  1058. bool update(int position, Updater updater)
  1059. {
  1060. Value* pval = 0;
  1061. bool isnew = false;
  1062. if (!access(position, (pval), (isnew)))
  1063. return false;
  1064. updater(*pval, isnew);
  1065. return true;
  1066. }
  1067. int getIndexFor(int position) const
  1068. {
  1069. int ipos = m_xBegin + position;
  1070. int vend = m_xEnd;
  1071. if (vend < m_xBegin)
  1072. vend += m_iSize;
  1073. if (ipos >= vend)
  1074. return -1;
  1075. if (ipos >= m_iSize)
  1076. ipos -= m_iSize;
  1077. return ipos;
  1078. }
  1079. bool get(int position, Value& w_out) const
  1080. {
  1081. // Check if that position is occupied
  1082. if (position > m_iSize || position < 0)
  1083. return false;
  1084. int ipos = getIndexFor(position);
  1085. if (ipos == -1)
  1086. return false;
  1087. w_out = m_aStorage[ipos];
  1088. return true;
  1089. }
  1090. bool drop(int position)
  1091. {
  1092. // This function "deletes" items by shifting the
  1093. // given position to position 0. That is,
  1094. // elements from the beginning are being deleted
  1095. // up to (including) the given position.
  1096. if (position > m_iSize || position < 1)
  1097. return false;
  1098. int ipos = m_xBegin + position;
  1099. int vend = m_xEnd;
  1100. if (vend < m_xBegin)
  1101. vend += m_iSize;
  1102. // Destroy the elements in the removed range
  1103. if (ipos >= vend)
  1104. {
  1105. // There was a request to drop; the position
  1106. // is higher than the number of items. Allow this
  1107. // and simply make the container empty.
  1108. reset();
  1109. return true;
  1110. }
  1111. // Otherwise we have a new beginning.
  1112. int nbegin = ipos;
  1113. // Destroy the old elements
  1114. if (nbegin >= m_iSize)
  1115. {
  1116. nbegin -= m_iSize;
  1117. for (int i = m_xBegin; i < m_iSize; ++i)
  1118. destr(m_aStorage[i]);
  1119. for (int i = 0; i < nbegin; ++i)
  1120. destr(m_aStorage[i]);
  1121. }
  1122. else
  1123. {
  1124. for (int i = m_xBegin; i < nbegin; ++i)
  1125. destr(m_aStorage[i]);
  1126. }
  1127. m_xBegin = nbegin;
  1128. return true;
  1129. }
  1130. // This function searches for an element that satisfies
  1131. // the given predicate. If none found, returns -1.
  1132. template <class Predicate>
  1133. int find_if(Predicate pred)
  1134. {
  1135. if (m_xEnd < m_xBegin)
  1136. {
  1137. // Loop in two slices
  1138. for (int i = m_xBegin; i < m_iSize; ++i)
  1139. if (pred(m_aStorage[i]))
  1140. return i - m_xBegin;
  1141. for (int i = 0; i < m_xEnd; ++i)
  1142. if (pred(m_aStorage[i]))
  1143. return i + m_iSize - m_xBegin;
  1144. }
  1145. else
  1146. {
  1147. for (int i = m_xBegin; i < m_xEnd; ++i)
  1148. if (pred(m_aStorage[i]))
  1149. return i - m_xBegin;
  1150. }
  1151. return -1;
  1152. }
  1153. };
  1154. // Version parsing
  1155. inline ATR_CONSTEXPR uint32_t SrtVersion(int major, int minor, int patch)
  1156. {
  1157. return patch + minor*0x100 + major*0x10000;
  1158. }
  1159. inline int32_t SrtParseVersion(const char* v)
  1160. {
  1161. int major, minor, patch;
  1162. #if defined(_MSC_VER)
  1163. int result = sscanf_s(v, "%d.%d.%d", &major, &minor, &patch);
  1164. #else
  1165. int result = sscanf(v, "%d.%d.%d", &major, &minor, &patch);
  1166. #endif
  1167. if (result != 3)
  1168. {
  1169. return 0;
  1170. }
  1171. return SrtVersion(major, minor, patch);
  1172. }
  1173. inline std::string SrtVersionString(int version)
  1174. {
  1175. int patch = version % 0x100;
  1176. int minor = (version/0x100)%0x100;
  1177. int major = version/0x10000;
  1178. char buf[22];
  1179. #if defined(_MSC_VER) && _MSC_VER < 1900
  1180. _snprintf(buf, sizeof(buf) - 1, "%d.%d.%d", major, minor, patch);
  1181. #else
  1182. snprintf(buf, sizeof(buf), "%d.%d.%d", major, minor, patch);
  1183. #endif
  1184. return buf;
  1185. }
  1186. bool SrtParseConfig(const std::string& s, SrtConfig& w_config);
  1187. } // namespace srt
  1188. #endif