1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
|
/*
* SRT - Secure, Reliable, Transport
* Copyright (c) 2018 Haivision Systems Inc.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
*/
/*****************************************************************************
Copyright (c) 2001 - 2009, The Board of Trustees of the University of Illinois.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the
above copyright notice, this list of conditions
and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the University of Illinois
nor the names of its contributors may be used to
endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
/*****************************************************************************
written by
Yunhong Gu, last updated 05/05/2009
modified by
Haivision Systems Inc.
*****************************************************************************/
#ifndef INC_SRT_BUFFER_SND_H
#define INC_SRT_BUFFER_SND_H
#include "srt.h"
#include "packet.h"
#include "buffer_tools.h"
// The notation used for "circular numbers" in comments:
// The "cicrular numbers" are numbers that when increased up to the
// maximum become zero, and similarly, when the zero value is decreased,
// it turns into the maximum value minus one. This wrapping works the
// same for adding and subtracting. Circular numbers cannot be multiplied.
// Operations done on these numbers are marked with additional % character:
// a %> b : a is later than b
// a ++% (++%a) : shift a by 1 forward
// a +% b : shift a by b
// a == b : equality is same as for just numbers
namespace srt {
class CSndBuffer
{
typedef sync::steady_clock::time_point time_point;
typedef sync::steady_clock::duration duration;
public:
// XXX There's currently no way to access the socket ID set for
// whatever the buffer is currently working for. Required to find
// some way to do this, possibly by having a "reverse pointer".
// Currently just "unimplemented".
std::string CONID() const { return ""; }
/// @brief CSndBuffer constructor.
/// @param size initial number of blocks (each block to store one packet payload).
/// @param maxpld maximum packet payload (including auth tag).
/// @param authtag auth tag length in bytes (16 for GCM, 0 otherwise).
CSndBuffer(int ip_family, int size, int maxpld, int authtag);
~CSndBuffer();
public:
/// Insert a user buffer into the sending list.
/// For @a w_mctrl the following fields are used:
/// INPUT:
/// - msgttl: timeout for retransmitting the message, if lost
/// - inorder: request to deliver the message in order of sending
/// - srctime: local time as a base for packet's timestamp (0 if unused)
/// - pktseq: sequence number to be stamped on the packet (-1 if unused)
/// - msgno: message number to be stamped on the packet (-1 if unused)
/// OUTPUT:
/// - srctime: local time stamped on the packet (same as input, if input wasn't 0)
/// - pktseq: sequence number to be stamped on the next packet
/// - msgno: message number stamped on the packet
/// @param [in] data pointer to the user data block.
/// @param [in] len size of the block.
/// @param [inout] w_mctrl Message control data
SRT_ATTR_EXCLUDES(m_BufLock)
void addBuffer(const char* data, int len, SRT_MSGCTRL& w_mctrl);
/// Read a block of data from file and insert it into the sending list.
/// @param [in] ifs input file stream.
/// @param [in] len size of the block.
/// @return actual size of data added from the file.
SRT_ATTR_EXCLUDES(m_BufLock)
int addBufferFromFile(std::fstream& ifs, int len);
// Special values that can be returned by readData.
static const int READ_NONE = 0;
static const int READ_DROP = -1;
/// Find data position to pack a DATA packet from the furthest reading point.
/// @param [out] packet the packet to read.
/// @param [out] origintime origin time stamp of the message
/// @param [in] kflags Odd|Even crypto key flag
/// @param [out] seqnoinc the number of packets skipped due to TTL, so that seqno should be incremented.
/// @return Actual length of data read.
SRT_ATTR_EXCLUDES(m_BufLock)
int readData(CPacket& w_packet, time_point& w_origintime, int kflgs, int& w_seqnoinc);
/// Peek an information on the next original data packet to send.
/// @return origin time stamp of the next packet; epoch start time otherwise.
SRT_ATTR_EXCLUDES(m_BufLock)
time_point peekNextOriginal() const;
struct DropRange
{
static const size_t BEGIN = 0, END = 1;
int32_t seqno[2];
int32_t msgno;
};
/// Find data position to pack a DATA packet for a retransmission.
/// IMPORTANT: @a packet is [in,out] because it is expected to get set
/// the sequence number of the packet expected to be sent next. The sender
/// buffer normally doesn't handle sequence numbers and the consistency
/// between the sequence number of a packet already sent and kept in the
/// buffer is achieved by having the sequence number recorded in the
/// CUDT::m_iSndLastDataAck field that should represent the oldest packet
/// still in the buffer.
/// @param [in] offset offset from the last ACK point (backward sequence number difference)
/// @param [in,out] w_packet storage for the packet, preinitialized with sequence number
/// @param [out] w_origintime origin time stamp of the message
/// @param [out] w_drop the drop information in case when dropping is to be done instead
/// @retval >0 Length of the data read.
/// @retval READ_NONE No data available or @a offset points out of the buffer occupied space.
/// @retval READ_DROP The call requested data drop due to TTL exceeded, to be handled first.
SRT_ATTR_EXCLUDES(m_BufLock)
int readData(const int offset, CPacket& w_packet, time_point& w_origintime, DropRange& w_drop);
/// Get the time of the last retransmission (if any) of the DATA packet.
/// @param [in] offset offset from the last ACK point (backward sequence number difference)
///
/// @return Last time of the last retransmission event for the corresponding DATA packet.
SRT_ATTR_EXCLUDES(m_BufLock)
time_point getPacketRexmitTime(const int offset);
/// Update the ACK point and may release/unmap/return the user data according to the flag.
/// @param [in] offset number of packets acknowledged.
int32_t getMsgNoAt(const int offset);
void ackData(int offset);
/// Read size of data still in the sending list.
/// @return Current size of the data in the sending list.
int getCurrBufSize() const;
SRT_ATTR_EXCLUDES(m_BufLock)
int dropLateData(int& bytes, int32_t& w_first_msgno, const time_point& too_late_time);
void updAvgBufSize(const time_point& time);
int getAvgBufSize(int& bytes, int& timespan);
int getCurrBufSize(int& bytes, int& timespan) const;
/// Het maximum payload length per packet.
int getMaxPacketLen() const;
/// @brief Count the number of required packets to store the payload (message).
/// @param iPldLen the length of the payload to check.
/// @return the number of required data packets.
int countNumPacketsRequired(int iPldLen) const;
/// @brief Count the number of required packets to store the payload (message).
/// @param iPldLen the length of the payload to check.
/// @param iMaxPktLen the maximum payload length of the packet (the value returned from getMaxPacketLen()).
/// @return the number of required data packets.
int countNumPacketsRequired(int iPldLen, int iMaxPktLen) const;
/// @brief Get the buffering delay of the oldest message in the buffer.
/// @return the delay value.
SRT_ATTR_EXCLUDES(m_BufLock)
duration getBufferingDelay(const time_point& tnow) const;
uint64_t getInRatePeriod() const { return m_rateEstimator.getInRatePeriod(); }
/// Retrieve input bitrate in bytes per second
int getInputRate() const { return m_rateEstimator.getInputRate(); }
void resetInputRateSmpPeriod(bool disable = false) { m_rateEstimator.resetInputRateSmpPeriod(disable); }
const CRateEstimator& getRateEstimator() const { return m_rateEstimator; }
void setRateEstimator(const CRateEstimator& other) { m_rateEstimator = other; }
private:
void increase();
private:
mutable sync::Mutex m_BufLock; // used to synchronize buffer operation
struct Block
{
char* m_pcData; // pointer to the data block
int m_iLength; // payload length of the block (excluding auth tag).
int32_t m_iMsgNoBitset; // message number
int32_t m_iSeqNo; // sequence number for scheduling
time_point m_tsOriginTime; // block origin time (either provided from above or equals the time a message was submitted for sending.
time_point m_tsRexmitTime; // packet retransmission time
int m_iTTL; // time to live (milliseconds)
Block* m_pNext; // next block
int32_t getMsgSeq()
{
// NOTE: this extracts message ID with regard to REXMIT flag.
// This is valid only for message ID that IS GENERATED in this instance,
// not provided by the peer. This can be otherwise sent to the peer - it doesn't matter
// for the peer that it uses LESS bits to represent the message.
return m_iMsgNoBitset & MSGNO_SEQ::mask;
}
} * m_pBlock, *m_pFirstBlock, *m_pCurrBlock, *m_pLastBlock;
// m_pBlock: The head pointer
// m_pFirstBlock: The first block
// m_pCurrBlock: The current block
// m_pLastBlock: The last block (if first == last, buffer is empty)
struct Buffer
{
char* m_pcData; // buffer
int m_iSize; // size
Buffer* m_pNext; // next buffer
} * m_pBuffer; // physical buffer
int32_t m_iNextMsgNo; // next message number
int m_iSize; // buffer size (number of packets)
const int m_iBlockLen; // maximum length of a block holding packet payload and AUTH tag (excluding packet header).
const int m_iAuthTagSize; // Authentication tag size (if GCM is enabled).
// NOTE: This is atomic AND under lock because the function getCurrBufSize()
// is returning it WITHOUT locking. Modification, however, must stay under
// a lock.
sync::atomic<int> m_iCount; // number of used blocks
int m_iBytesCount; // number of payload bytes in queue
time_point m_tsLastOriginTime;
AvgBufSize m_mavg;
CRateEstimator m_rateEstimator;
private:
CSndBuffer(const CSndBuffer&);
CSndBuffer& operator=(const CSndBuffer&);
};
} // namespace srt
#endif
|