mirror of
				https://github.com/ossrs/srs.git
				synced 2025-03-09 15:49:59 +00:00 
			
		
		
		
	fix https://github.com/ossrs/srs/issues/3155 Build srt-1-fit fails with `standard attributes in middle of decl-specifiers` on GCC 12,Arch Linux. See https://github.com/Haivision/srt/releases/tag/v1.5.3
		
			
				
	
	
		
			657 lines
		
	
	
	
		
			21 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			657 lines
		
	
	
	
		
			21 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/*
 | 
						|
 * 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 - 2011, 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 02/12/2011
 | 
						|
modified by
 | 
						|
   Haivision Systems Inc.
 | 
						|
*****************************************************************************/
 | 
						|
 | 
						|
//////////////////////////////////////////////////////////////////////////////
 | 
						|
//    0                   1                   2                   3
 | 
						|
//    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
						|
//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
//   |                        Packet Header                          |
 | 
						|
//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
//   |                                                               |
 | 
						|
//   ~              Data / Control Information Field                 ~
 | 
						|
//   |                                                               |
 | 
						|
//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
//
 | 
						|
//    0                   1                   2                   3
 | 
						|
//    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
						|
//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
//   |0|                        Sequence Number                      |
 | 
						|
//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
//   |ff |o|kf |r|               Message Number                      |
 | 
						|
//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
//   |                          Time Stamp                           |
 | 
						|
//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
//   |                     Destination Socket ID                     |
 | 
						|
//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
//
 | 
						|
//   bit 0:
 | 
						|
//      0: Data Packet
 | 
						|
//      1: Control Packet
 | 
						|
//   bit ff:
 | 
						|
//      11: solo message packet
 | 
						|
//      10: first packet of a message
 | 
						|
//      01: last packet of a message
 | 
						|
//   bit o:
 | 
						|
//      0: in order delivery not required
 | 
						|
//      1: in order delivery required
 | 
						|
//   bit kf: HaiCrypt Key Flags
 | 
						|
//      00: not encrypted
 | 
						|
//      01: encrypted with even key
 | 
						|
//      10: encrypted with odd key
 | 
						|
//   bit r: retransmission flag (set to 1 if this packet was sent again)
 | 
						|
//
 | 
						|
//    0                   1                   2                   3
 | 
						|
//    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
						|
//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
//   |1|            Type             |             Reserved          |
 | 
						|
//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
//   |                       Additional Info                         |
 | 
						|
//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
//   |                          Time Stamp                           |
 | 
						|
//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
//   |                     Destination Socket ID                     |
 | 
						|
//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
//
 | 
						|
//   bit 1-15: Message type -- see @a UDTMessageType
 | 
						|
//      0: Protocol Connection Handshake (UMSG_HANDSHAKE}
 | 
						|
//              Add. Info:    Undefined
 | 
						|
//              Control Info: Handshake information (see @a CHandShake)
 | 
						|
//      1: Keep-alive (UMSG_KEEPALIVE)
 | 
						|
//              Add. Info:    Undefined
 | 
						|
//              Control Info: None
 | 
						|
//      2: Acknowledgement (UMSG_ACK)
 | 
						|
//              Add. Info:    The ACK sequence number
 | 
						|
//              Control Info: The sequence number to which (but not include) all the previous packets have beed received
 | 
						|
//              Optional:     RTT
 | 
						|
//                            RTT Variance
 | 
						|
//                            available receiver buffer size (in bytes)
 | 
						|
//                            advertised flow window size (number of packets)
 | 
						|
//                            estimated bandwidth (number of packets per second)
 | 
						|
//      3: Negative Acknowledgement (UMSG_LOSSREPORT)
 | 
						|
//              Add. Info:    Undefined
 | 
						|
//              Control Info: Loss list (see loss list coding below)
 | 
						|
//      4: Congestion/Delay Warning (UMSG_CGWARNING)
 | 
						|
//              Add. Info:    Undefined
 | 
						|
//              Control Info: None
 | 
						|
//      5: Shutdown (UMSG_SHUTDOWN)
 | 
						|
//              Add. Info:    Undefined
 | 
						|
//              Control Info: None
 | 
						|
//      6: Acknowledgement of Acknowledement (UMSG_ACKACK)
 | 
						|
//              Add. Info:    The ACK sequence number
 | 
						|
//              Control Info: None
 | 
						|
//      7: Message Drop Request (UMSG_DROPREQ)
 | 
						|
//              Add. Info:    Message ID
 | 
						|
//              Control Info: first sequence number of the message
 | 
						|
//                            last seqeunce number of the message
 | 
						|
//      8: Error Signal from the Peer Side (UMSG_PEERERROR)
 | 
						|
//              Add. Info:    Error code
 | 
						|
//              Control Info: None
 | 
						|
//      0x7FFF: Explained by bits 16 - 31 (UMSG_EXT)
 | 
						|
//
 | 
						|
//   bit 16 - 31:
 | 
						|
//      This space is used for future expansion or user defined control packets.
 | 
						|
//
 | 
						|
//    0                   1                   2                   3
 | 
						|
//    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
						|
//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
//   |1|                 Sequence Number a (first)                   |
 | 
						|
//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
//   |0|                 Sequence Number b (last)                    |
 | 
						|
//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
//   |0|                 Sequence Number (single)                    |
 | 
						|
//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
						|
//
 | 
						|
//   Loss List Field Coding:
 | 
						|
//      For any consecutive lost seqeunce numbers that the differnece between
 | 
						|
//      the last and first is more than 1, only record the first (a) and the
 | 
						|
//      the last (b) sequence numbers in the loss list field, and modify the
 | 
						|
//      the first bit of a to 1.
 | 
						|
//      For any single loss or consecutive loss less than 2 packets, use
 | 
						|
//      the original sequence numbers in the field.
 | 
						|
 | 
						|
#include "platform_sys.h"
 | 
						|
 | 
						|
#include <cstring>
 | 
						|
#include "packet.h"
 | 
						|
#include "handshake.h"
 | 
						|
#include "logging.h"
 | 
						|
#include "handshake.h"
 | 
						|
 | 
						|
namespace srt_logging
 | 
						|
{
 | 
						|
extern Logger inlog;
 | 
						|
}
 | 
						|
using namespace srt_logging;
 | 
						|
 | 
						|
namespace srt {
 | 
						|
 | 
						|
// Set up the aliases in the constructure
 | 
						|
CPacket::CPacket()
 | 
						|
    : m_nHeader() // Silences GCC 12 warning "used uninitialized".
 | 
						|
    , m_extra_pad()
 | 
						|
    , m_data_owned(false)
 | 
						|
    , m_iSeqNo((int32_t&)(m_nHeader[SRT_PH_SEQNO]))
 | 
						|
    , m_iMsgNo((int32_t&)(m_nHeader[SRT_PH_MSGNO]))
 | 
						|
    , m_iTimeStamp((int32_t&)(m_nHeader[SRT_PH_TIMESTAMP]))
 | 
						|
    , m_iID((int32_t&)(m_nHeader[SRT_PH_ID]))
 | 
						|
    , m_pcData((char*&)(m_PacketVector[PV_DATA].dataRef()))
 | 
						|
{
 | 
						|
    m_nHeader.clear();
 | 
						|
 | 
						|
    // The part at PV_HEADER will be always set to a builtin buffer
 | 
						|
    // containing SRT header.
 | 
						|
    m_PacketVector[PV_HEADER].set(m_nHeader.raw(), HDR_SIZE);
 | 
						|
 | 
						|
    // The part at PV_DATA is zero-initialized. It should be
 | 
						|
    // set (through m_pcData and setLength()) to some externally
 | 
						|
    // provided buffer before calling CChannel::sendto().
 | 
						|
    m_PacketVector[PV_DATA].set(NULL, 0);
 | 
						|
}
 | 
						|
 | 
						|
char* CPacket::getData()
 | 
						|
{
 | 
						|
    return (char*)m_PacketVector[PV_DATA].dataRef();
 | 
						|
}
 | 
						|
 | 
						|
void CPacket::allocate(size_t alloc_buffer_size)
 | 
						|
{
 | 
						|
    if (m_data_owned)
 | 
						|
    {
 | 
						|
        if (getLength() == alloc_buffer_size)
 | 
						|
            return; // already allocated
 | 
						|
 | 
						|
        // Would be nice to reallocate; for now just allocate again.
 | 
						|
        delete[] m_pcData;
 | 
						|
    }
 | 
						|
    m_PacketVector[PV_DATA].set(new char[alloc_buffer_size], alloc_buffer_size);
 | 
						|
    m_data_owned = true;
 | 
						|
}
 | 
						|
 | 
						|
void CPacket::deallocate()
 | 
						|
{
 | 
						|
    if (m_data_owned)
 | 
						|
        delete[](char*) m_PacketVector[PV_DATA].data();
 | 
						|
    m_PacketVector[PV_DATA].set(NULL, 0);
 | 
						|
    m_data_owned = false;
 | 
						|
}
 | 
						|
 | 
						|
char* CPacket::release()
 | 
						|
{
 | 
						|
    // When not owned, release returns NULL.
 | 
						|
    char* buffer = NULL;
 | 
						|
    if (m_data_owned)
 | 
						|
    {
 | 
						|
        buffer       = getData();
 | 
						|
        m_data_owned = false;
 | 
						|
    }
 | 
						|
 | 
						|
    deallocate(); // won't delete because m_data_owned == false
 | 
						|
    return buffer;
 | 
						|
}
 | 
						|
 | 
						|
CPacket::~CPacket()
 | 
						|
{
 | 
						|
    // PV_HEADER is always owned, PV_DATA may use a "borrowed" buffer.
 | 
						|
    // Delete the internal buffer only if it was declared as owned.
 | 
						|
    deallocate();
 | 
						|
}
 | 
						|
 | 
						|
size_t CPacket::getLength() const
 | 
						|
{
 | 
						|
    return m_PacketVector[PV_DATA].size();
 | 
						|
}
 | 
						|
 | 
						|
void CPacket::setLength(size_t len)
 | 
						|
{
 | 
						|
    m_PacketVector[PV_DATA].setLength(len);
 | 
						|
}
 | 
						|
 | 
						|
void CPacket::setLength(size_t len, size_t cap)
 | 
						|
{
 | 
						|
   SRT_ASSERT(len <= cap);
 | 
						|
   setLength(len);
 | 
						|
   m_zCapacity = cap;
 | 
						|
}
 | 
						|
 | 
						|
#if ENABLE_HEAVY_LOGGING
 | 
						|
// Debug only
 | 
						|
static std::string FormatNumbers(UDTMessageType pkttype, const int32_t* lparam, void* rparam, const size_t size)
 | 
						|
{
 | 
						|
    // This may be changed over time, so use special interpretation
 | 
						|
    // only for certain types, and still display all data, no matter
 | 
						|
    // if it is expected to provide anything or not.
 | 
						|
    std::ostringstream out;
 | 
						|
 | 
						|
    out << "ARG=";
 | 
						|
    if (lparam)
 | 
						|
        out << *lparam;
 | 
						|
    else
 | 
						|
        out << "none";
 | 
						|
 | 
						|
    if (size == 0)
 | 
						|
    {
 | 
						|
        out << " [no data]";
 | 
						|
        return out.str();
 | 
						|
    }
 | 
						|
    else if (!rparam)
 | 
						|
    {
 | 
						|
        out << " [ {" << size << "} ]";
 | 
						|
        return out.str();
 | 
						|
    }
 | 
						|
 | 
						|
    bool interp_as_seq = (pkttype == UMSG_LOSSREPORT || pkttype == UMSG_DROPREQ);
 | 
						|
    bool display_dec = (pkttype == UMSG_ACK || pkttype == UMSG_ACKACK || pkttype == UMSG_DROPREQ);
 | 
						|
 | 
						|
    out << " [ ";
 | 
						|
 | 
						|
    // Will be effective only for hex/oct.
 | 
						|
    out << std::showbase;
 | 
						|
 | 
						|
    const size_t size32 = size/4;
 | 
						|
    for (size_t i = 0; i < size32; ++i)
 | 
						|
    {
 | 
						|
        int32_t val = ((int32_t*)rparam)[i];
 | 
						|
        if (interp_as_seq)
 | 
						|
        {
 | 
						|
            if (val & LOSSDATA_SEQNO_RANGE_FIRST)
 | 
						|
                out << "<" << (val & (~LOSSDATA_SEQNO_RANGE_FIRST)) << ">";
 | 
						|
            else
 | 
						|
                out << val;
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            if (!display_dec)
 | 
						|
            {
 | 
						|
                out << std::hex;
 | 
						|
                out << val << "/";
 | 
						|
                out << std::dec;
 | 
						|
            }
 | 
						|
            out << val;
 | 
						|
 | 
						|
        }
 | 
						|
        out << " ";
 | 
						|
    }
 | 
						|
 | 
						|
    out << "]";
 | 
						|
    return out.str();
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
void CPacket::pack(UDTMessageType pkttype, const int32_t* lparam, void* rparam, size_t size)
 | 
						|
{
 | 
						|
    // Set (bit-0 = 1) and (bit-1~15 = type)
 | 
						|
    setControl(pkttype);
 | 
						|
    HLOGC(inlog.Debug, log << "pack: type=" << MessageTypeStr(pkttype) << " " << FormatNumbers(pkttype, lparam, rparam, size));
 | 
						|
 | 
						|
    // Set additional information and control information field
 | 
						|
    switch (pkttype)
 | 
						|
    {
 | 
						|
    case UMSG_ACK: // 0010 - Acknowledgement (ACK)
 | 
						|
        // ACK packet seq. no.
 | 
						|
        if (NULL != lparam)
 | 
						|
            m_nHeader[SRT_PH_MSGNO] = *lparam;
 | 
						|
 | 
						|
        // data ACK seq. no.
 | 
						|
        // optional: RTT (microsends), RTT variance (microseconds) advertised flow window size (packets), and estimated
 | 
						|
        // link capacity (packets per second)
 | 
						|
        m_PacketVector[PV_DATA].set(rparam, size);
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
    case UMSG_ACKACK: // 0110 - Acknowledgement of Acknowledgement (ACK-2)
 | 
						|
        // ACK packet seq. no.
 | 
						|
        m_nHeader[SRT_PH_MSGNO] = *lparam;
 | 
						|
 | 
						|
        // control info field should be none
 | 
						|
        // but "writev" does not allow this
 | 
						|
        m_PacketVector[PV_DATA].set((void*)&m_extra_pad, 4);
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
    case UMSG_LOSSREPORT: // 0011 - Loss Report (NAK)
 | 
						|
        // loss list
 | 
						|
        m_PacketVector[PV_DATA].set(rparam, size);
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
    case UMSG_CGWARNING: // 0100 - Congestion Warning
 | 
						|
        // control info field should be none
 | 
						|
        // but "writev" does not allow this
 | 
						|
        m_PacketVector[PV_DATA].set((void*)&m_extra_pad, 4);
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
    case UMSG_KEEPALIVE: // 0001 - Keep-alive
 | 
						|
        if (lparam)
 | 
						|
        {
 | 
						|
            // XXX EXPERIMENTAL. Pass the 32-bit integer here.
 | 
						|
            m_nHeader[SRT_PH_MSGNO] = *lparam;
 | 
						|
        }
 | 
						|
        // control info field should be none
 | 
						|
        // but "writev" does not allow this
 | 
						|
        m_PacketVector[PV_DATA].set((void*)&m_extra_pad, 4);
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
    case UMSG_HANDSHAKE: // 0000 - Handshake
 | 
						|
        // control info filed is handshake info
 | 
						|
        m_PacketVector[PV_DATA].set(rparam, size);
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
    case UMSG_SHUTDOWN: // 0101 - Shutdown
 | 
						|
        // control info field should be none
 | 
						|
        // but "writev" does not allow this
 | 
						|
        m_PacketVector[PV_DATA].set((void*)&m_extra_pad, 4);
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
    case UMSG_DROPREQ: // 0111 - Message Drop Request
 | 
						|
        // msg id
 | 
						|
        m_nHeader[SRT_PH_MSGNO] = *lparam;
 | 
						|
 | 
						|
        // first seq no, last seq no
 | 
						|
        m_PacketVector[PV_DATA].set(rparam, size);
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
    case UMSG_PEERERROR: // 1000 - Error Signal from the Peer Side
 | 
						|
        // Error type
 | 
						|
        m_nHeader[SRT_PH_MSGNO] = *lparam;
 | 
						|
 | 
						|
        // control info field should be none
 | 
						|
        // but "writev" does not allow this
 | 
						|
        m_PacketVector[PV_DATA].set((void*)&m_extra_pad, 4);
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
    case UMSG_EXT: // 0x7FFF - Reserved for user defined control packets
 | 
						|
        // for extended control packet
 | 
						|
        // "lparam" contains the extended type information for bit 16 - 31
 | 
						|
        // "rparam" is the control information
 | 
						|
        m_nHeader[SRT_PH_SEQNO] |= *lparam;
 | 
						|
 | 
						|
        if (NULL != rparam)
 | 
						|
        {
 | 
						|
            m_PacketVector[PV_DATA].set(rparam, size);
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            m_PacketVector[PV_DATA].set((void*)&m_extra_pad, 4);
 | 
						|
        }
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void CPacket::toNL()
 | 
						|
{
 | 
						|
    // XXX USE HtoNLA!
 | 
						|
    if (isControl())
 | 
						|
    {
 | 
						|
        for (ptrdiff_t i = 0, n = getLength() / 4; i < n; ++i)
 | 
						|
            *((uint32_t*)m_pcData + i) = htonl(*((uint32_t*)m_pcData + i));
 | 
						|
    }
 | 
						|
 | 
						|
    // convert packet header into network order
 | 
						|
    uint32_t* p = m_nHeader;
 | 
						|
    for (int j = 0; j < 4; ++j)
 | 
						|
    {
 | 
						|
        *p = htonl(*p);
 | 
						|
        ++p;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void CPacket::toHL()
 | 
						|
{
 | 
						|
    // convert back into local host order
 | 
						|
    uint32_t* p = m_nHeader;
 | 
						|
    for (int k = 0; k < 4; ++k)
 | 
						|
    {
 | 
						|
        *p = ntohl(*p);
 | 
						|
        ++p;
 | 
						|
    }
 | 
						|
 | 
						|
    if (isControl())
 | 
						|
    {
 | 
						|
        for (ptrdiff_t l = 0, n = getLength() / 4; l < n; ++l)
 | 
						|
            *((uint32_t*)m_pcData + l) = ntohl(*((uint32_t*)m_pcData + l));
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
IOVector* CPacket::getPacketVector()
 | 
						|
{
 | 
						|
    return m_PacketVector;
 | 
						|
}
 | 
						|
 | 
						|
UDTMessageType CPacket::getType() const
 | 
						|
{
 | 
						|
    return UDTMessageType(SEQNO_MSGTYPE::unwrap(m_nHeader[SRT_PH_SEQNO]));
 | 
						|
}
 | 
						|
 | 
						|
int CPacket::getExtendedType() const
 | 
						|
{
 | 
						|
    return SEQNO_EXTTYPE::unwrap(m_nHeader[SRT_PH_SEQNO]);
 | 
						|
}
 | 
						|
 | 
						|
int32_t CPacket::getAckSeqNo() const
 | 
						|
{
 | 
						|
    // read additional information field
 | 
						|
    // This field is used only in UMSG_ACK and UMSG_ACKACK,
 | 
						|
    // so 'getAckSeqNo' symbolically defines the only use of it
 | 
						|
    // in case of CONTROL PACKET.
 | 
						|
    return m_nHeader[SRT_PH_MSGNO];
 | 
						|
}
 | 
						|
 | 
						|
uint16_t CPacket::getControlFlags() const
 | 
						|
{
 | 
						|
    // This returns exactly the "extended type" value,
 | 
						|
    // which is not used at all in case when the standard
 | 
						|
    // type message is interpreted. This can be used to pass
 | 
						|
    // additional special flags.
 | 
						|
    return SEQNO_EXTTYPE::unwrap(m_nHeader[SRT_PH_SEQNO]);
 | 
						|
}
 | 
						|
 | 
						|
PacketBoundary CPacket::getMsgBoundary() const
 | 
						|
{
 | 
						|
    return PacketBoundary(MSGNO_PACKET_BOUNDARY::unwrap(m_nHeader[SRT_PH_MSGNO]));
 | 
						|
}
 | 
						|
 | 
						|
bool CPacket::getMsgOrderFlag() const
 | 
						|
{
 | 
						|
    return 0 != MSGNO_PACKET_INORDER::unwrap(m_nHeader[SRT_PH_MSGNO]);
 | 
						|
}
 | 
						|
 | 
						|
int32_t CPacket::getMsgSeq(bool has_rexmit) const
 | 
						|
{
 | 
						|
    if (has_rexmit)
 | 
						|
    {
 | 
						|
        return MSGNO_SEQ::unwrap(m_nHeader[SRT_PH_MSGNO]);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        return MSGNO_SEQ_OLD::unwrap(m_nHeader[SRT_PH_MSGNO]);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
bool CPacket::getRexmitFlag() const
 | 
						|
{
 | 
						|
    return 0 != MSGNO_REXMIT::unwrap(m_nHeader[SRT_PH_MSGNO]);
 | 
						|
}
 | 
						|
 | 
						|
void CPacket::setRexmitFlag(bool bRexmit)
 | 
						|
{
 | 
						|
    const int32_t clr_msgno = m_nHeader[SRT_PH_MSGNO] & ~MSGNO_REXMIT::mask;
 | 
						|
    m_nHeader[SRT_PH_MSGNO] = clr_msgno | MSGNO_REXMIT::wrap(bRexmit? 1 : 0);
 | 
						|
}
 | 
						|
 | 
						|
EncryptionKeySpec CPacket::getMsgCryptoFlags() const
 | 
						|
{
 | 
						|
    return EncryptionKeySpec(MSGNO_ENCKEYSPEC::unwrap(m_nHeader[SRT_PH_MSGNO]));
 | 
						|
}
 | 
						|
 | 
						|
// This is required as the encryption/decryption happens in place.
 | 
						|
// This is required to clear off the flags after decryption or set
 | 
						|
// crypto flags after encrypting a packet.
 | 
						|
void CPacket::setMsgCryptoFlags(EncryptionKeySpec spec)
 | 
						|
{
 | 
						|
    int32_t clr_msgno       = m_nHeader[SRT_PH_MSGNO] & ~MSGNO_ENCKEYSPEC::mask;
 | 
						|
    m_nHeader[SRT_PH_MSGNO] = clr_msgno | EncryptionKeyBits(spec);
 | 
						|
}
 | 
						|
 | 
						|
uint32_t CPacket::getMsgTimeStamp() const
 | 
						|
{
 | 
						|
    // SRT_DEBUG_TSBPD_WRAP used to enable smaller timestamps for faster testing of how wraparounds are handled
 | 
						|
    return (uint32_t)m_nHeader[SRT_PH_TIMESTAMP] & TIMESTAMP_MASK;
 | 
						|
}
 | 
						|
 | 
						|
CPacket* CPacket::clone() const
 | 
						|
{
 | 
						|
    CPacket* pkt = new CPacket;
 | 
						|
    memcpy((pkt->m_nHeader), m_nHeader, HDR_SIZE);
 | 
						|
    pkt->allocate(this->getLength());
 | 
						|
    SRT_ASSERT(this->getLength() == pkt->getLength());
 | 
						|
    memcpy((pkt->m_pcData), m_pcData, this->getLength());
 | 
						|
    pkt->m_DestAddr = m_DestAddr;
 | 
						|
 | 
						|
    return pkt;
 | 
						|
}
 | 
						|
 | 
						|
// Useful for debugging
 | 
						|
std::string PacketMessageFlagStr(uint32_t msgno_field)
 | 
						|
{
 | 
						|
    using namespace std;
 | 
						|
 | 
						|
    stringstream out;
 | 
						|
 | 
						|
    static const char* const boundary[] = {"PB_SUBSEQUENT", "PB_LAST", "PB_FIRST", "PB_SOLO"};
 | 
						|
    static const char* const order[]    = {"ORD_RELAXED", "ORD_REQUIRED"};
 | 
						|
    static const char* const crypto[]   = {"EK_NOENC", "EK_EVEN", "EK_ODD", "EK*ERROR"};
 | 
						|
    static const char* const rexmit[]   = {"SN_ORIGINAL", "SN_REXMIT"};
 | 
						|
 | 
						|
    out << boundary[MSGNO_PACKET_BOUNDARY::unwrap(msgno_field)] << " ";
 | 
						|
    out << order[MSGNO_PACKET_INORDER::unwrap(msgno_field)] << " ";
 | 
						|
    out << crypto[MSGNO_ENCKEYSPEC::unwrap(msgno_field)] << " ";
 | 
						|
    out << rexmit[MSGNO_REXMIT::unwrap(msgno_field)];
 | 
						|
 | 
						|
    return out.str();
 | 
						|
}
 | 
						|
 | 
						|
inline void SprintSpecialWord(std::ostream& os, int32_t val)
 | 
						|
{
 | 
						|
    if (val & LOSSDATA_SEQNO_RANGE_FIRST)
 | 
						|
        os << "<" << (val & (~LOSSDATA_SEQNO_RANGE_FIRST)) << ">";
 | 
						|
    else
 | 
						|
        os << val;
 | 
						|
}
 | 
						|
 | 
						|
#if ENABLE_LOGGING
 | 
						|
std::string CPacket::Info()
 | 
						|
{
 | 
						|
    std::ostringstream os;
 | 
						|
    os << "TARGET=@" << m_iID << " ";
 | 
						|
 | 
						|
    if (isControl())
 | 
						|
    {
 | 
						|
        os << "CONTROL: size=" << getLength() << " type=" << MessageTypeStr(getType(), getExtendedType());
 | 
						|
 | 
						|
        if (getType() == UMSG_HANDSHAKE)
 | 
						|
        {
 | 
						|
            os << " HS: ";
 | 
						|
            // For handshake we already have a parsing method
 | 
						|
            CHandShake hs;
 | 
						|
            hs.load_from(m_pcData, getLength());
 | 
						|
            os << hs.show();
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            // This is a value that some messages use for some purposes.
 | 
						|
            // The "ack seq no" is one of the purposes, used by UMSG_ACK and UMSG_ACKACK.
 | 
						|
            // This is simply the SRT_PH_MSGNO field used as a message number in data packets.
 | 
						|
            os << " ARG: 0x";
 | 
						|
            os << std::hex << getAckSeqNo() << " ";
 | 
						|
            os << std::dec << getAckSeqNo();
 | 
						|
 | 
						|
            // It would be nice to see the extended packet data, but this
 | 
						|
            // requires strictly a message-dependent interpreter. So let's simply
 | 
						|
            // display all numbers in the array with the following restrictions:
 | 
						|
            // - all data contained in the buffer are considered 32-bit integer
 | 
						|
            // - sign flag will be cleared before displaying, with additional mark
 | 
						|
            size_t   wordlen = getLength() / 4; // drop any remainder if present
 | 
						|
            int32_t* array   = (int32_t*)m_pcData;
 | 
						|
            os << " [ ";
 | 
						|
            for (size_t i = 0; i < wordlen; ++i)
 | 
						|
            {
 | 
						|
                SprintSpecialWord(os, array[i]);
 | 
						|
                os << " ";
 | 
						|
            }
 | 
						|
            os << "]";
 | 
						|
        }
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        // It's hard to extract the information about peer's supported rexmit flag.
 | 
						|
        // This is only a log, nothing crucial, so we can risk displaying incorrect message number.
 | 
						|
        // Declaring that the peer supports rexmit flag cuts off the highest bit from
 | 
						|
        // the displayed number.
 | 
						|
        os << "DATA: size=" << getLength() << " " << BufferStamp(m_pcData, getLength()) << " #" << getMsgSeq(true)
 | 
						|
           << " %" << getSeqNo() << " " << MessageFlagStr();
 | 
						|
    }
 | 
						|
 | 
						|
    return os.str();
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
} // end namespace srt
 |