Skip to content

Commit

Permalink
Introduced a platform-dependent IOVector class
Browse files Browse the repository at this point in the history
  • Loading branch information
maxsharabayko authored and rndi committed Nov 30, 2018
1 parent 78e063d commit bcbbe0f
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 52 deletions.
63 changes: 24 additions & 39 deletions srtcore/packet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,54 +174,50 @@ m_iSeqNo((int32_t&)(m_nHeader[PH_SEQNO])),
m_iMsgNo((int32_t&)(m_nHeader[PH_MSGNO])),
m_iTimeStamp((int32_t&)(m_nHeader[PH_TIMESTAMP])),
m_iID((int32_t&)(m_nHeader[PH_ID])),
m_pcData((char*&)(m_PacketVector[PV_DATA].iov_base))
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].iov_base = m_nHeader.raw();
m_PacketVector[PV_HEADER].iov_len = HDR_SIZE;
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].iov_base = NULL;
m_PacketVector[PV_DATA].iov_len = 0;
m_PacketVector[PV_DATA].set(NULL, 0);
}

void CPacket::allocate(size_t alloc_buffer_size)
{
m_PacketVector[PV_DATA].iov_base = new char[alloc_buffer_size];
m_PacketVector[PV_DATA].iov_len = alloc_buffer_size;
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].iov_base;
m_PacketVector[PV_DATA].iov_base = 0;
m_PacketVector[PV_DATA].iov_len = 0;
delete [] (char*)m_PacketVector[PV_DATA].data();
m_PacketVector[PV_DATA].set(NULL, 0);
}

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.
if (m_data_owned)
delete [] (char*)m_PacketVector[PV_DATA].iov_base;
delete[](char*)m_PacketVector[PV_DATA].data();
}


size_t CPacket::getLength() const
{
return m_PacketVector[PV_DATA].iov_len;
return m_PacketVector[PV_DATA].size();
}

void CPacket::setLength(size_t len)
{
m_PacketVector[PV_DATA].iov_len = len;
m_PacketVector[PV_DATA].setLength(len);
}

void CPacket::pack(UDTMessageType pkttype, void* lparam, void* rparam, int size)
Expand All @@ -239,8 +235,7 @@ void CPacket::pack(UDTMessageType pkttype, void* lparam, void* rparam, int size)

// 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].iov_base = (char *)rparam;
m_PacketVector[PV_DATA].iov_len = size;
m_PacketVector[PV_DATA].set(rparam, size);

break;

Expand All @@ -250,46 +245,40 @@ void CPacket::pack(UDTMessageType pkttype, void* lparam, void* rparam, int size)

// control info field should be none
// but "writev" does not allow this
m_PacketVector[PV_DATA].iov_base = (char *)&__pad; //NULL;
m_PacketVector[PV_DATA].iov_len = 4; //0;
m_PacketVector[PV_DATA].set((void *)&__pad, 4);

break;

case UMSG_LOSSREPORT: //0011 - Loss Report (NAK)
// loss list
m_PacketVector[PV_DATA].iov_base = (char *)rparam;
m_PacketVector[PV_DATA].iov_len = size;
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].iov_base = (char *)&__pad; //NULL;
m_PacketVector[PV_DATA].iov_len = 4; //0;
m_PacketVector[PV_DATA].set((void *)&__pad, 4);

break;

case UMSG_KEEPALIVE: //0001 - Keep-alive
// control info field should be none
// but "writev" does not allow this
m_PacketVector[PV_DATA].iov_base = (char *)&__pad; //NULL;
m_PacketVector[PV_DATA].iov_len = 4; //0;
m_PacketVector[PV_DATA].set((void *)&__pad, 4);

break;

case UMSG_HANDSHAKE: //0000 - Handshake
// control info filed is handshake info
m_PacketVector[PV_DATA].iov_base = (char *)rparam;
m_PacketVector[PV_DATA].iov_len = size; //sizeof(CHandShake);
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].iov_base = (char *)&__pad; //NULL;
m_PacketVector[PV_DATA].iov_len = 4; //0;
m_PacketVector[PV_DATA].set((void *)&__pad, 4);

break;

Expand All @@ -298,8 +287,7 @@ void CPacket::pack(UDTMessageType pkttype, void* lparam, void* rparam, int size)
m_nHeader[PH_MSGNO] = *(int32_t *)lparam;

//first seq no, last seq no
m_PacketVector[PV_DATA].iov_base = (char *)rparam;
m_PacketVector[PV_DATA].iov_len = size;
m_PacketVector[PV_DATA].set(rparam, size);

break;

Expand All @@ -309,8 +297,7 @@ void CPacket::pack(UDTMessageType pkttype, void* lparam, void* rparam, int size)

// control info field should be none
// but "writev" does not allow this
m_PacketVector[PV_DATA].iov_base = (char *)&__pad; //NULL;
m_PacketVector[PV_DATA].iov_len = 4; //0;
m_PacketVector[PV_DATA].set((void *)&__pad, 4);

break;

Expand All @@ -322,13 +309,11 @@ void CPacket::pack(UDTMessageType pkttype, void* lparam, void* rparam, int size)

if (NULL != rparam)
{
m_PacketVector[PV_DATA].iov_base = (char *)rparam;
m_PacketVector[PV_DATA].iov_len = size;
m_PacketVector[PV_DATA].set(rparam, size);
}
else
{
m_PacketVector[PV_DATA].iov_base = (char *)&__pad;
m_PacketVector[PV_DATA].iov_len = 4;
m_PacketVector[PV_DATA].set((void *)&__pad, 4);
}

break;
Expand All @@ -338,7 +323,7 @@ void CPacket::pack(UDTMessageType pkttype, void* lparam, void* rparam, int size)
}
}

iovec* CPacket::getPacketVector()
IOVector* CPacket::getPacketVector()
{
return m_PacketVector;
}
Expand Down Expand Up @@ -477,9 +462,9 @@ CPacket* CPacket::clone() const
{
CPacket* pkt = new CPacket;
memcpy(pkt->m_nHeader, m_nHeader, HDR_SIZE);
pkt->m_pcData = new char[m_PacketVector[PV_DATA].iov_len];
memcpy(pkt->m_pcData, m_pcData, m_PacketVector[PV_DATA].iov_len);
pkt->m_PacketVector[PV_DATA].iov_len = m_PacketVector[PV_DATA].iov_len;
pkt->m_pcData = new char[m_PacketVector[PV_DATA].size()];
memcpy(pkt->m_pcData, m_pcData, m_PacketVector[PV_DATA].size());
pkt->m_PacketVector[PV_DATA].setLength(m_PacketVector[PV_DATA].size());

return pkt;
}
Expand Down
71 changes: 58 additions & 13 deletions srtcore/packet.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,23 +58,68 @@ modified by
#include "common.h"
#include "utilities.h"


//////////////////////////////////////////////////////////////////////////////
// The purpose of the IOVector class is to proide a platform-independet interface
// to the WSABUF on Windows and iovec on Linux, that can be easilly converted
// to the native structure for use in WSARecvFrom() and recvmsg(...) functions
class IOVector
#ifdef _WIN32
: public WSABUF
#else
: public iovec
#endif
{
public:

inline void set(void *buffer, size_t length)
{
#ifdef _WIN32
len = (ULONG)length;
buf = (CHAR*)buffer;
#else
iov_base = (void*)buffer;
iov_len = length;
#endif
}

// XXX REFACTOR THIS.
inline char*& dataRef()
{
#ifdef _WIN32
return buf;
#else
return (char*&) iov_base;
#endif
}

// Instead of providing this, the appropriate equivalent system type on Windows
// should be used. Then, instead of `iovec`, some portable definition should
// be used. See the definition of WSARecvMsg for details.
inline char* data()
{
#ifdef _WIN32
return buf;
#else
return (char*)iov_base;
#endif
}

// Note that iovec is part of CPacket definition, so the common type name should
// be used there. Fortunately, the Windows definition differs only by field names.
inline size_t size() const
{
#ifdef _WIN32
return (size_t) len;
#else
return iov_len;
#endif
}

struct iovec
{
int iov_len;
char* iov_base;
};
inline void setLength(size_t length)
{
#ifdef _WIN32
len = length;
#else
iov_len = length;
#endif
}
};


/// To define packets in order in the buffer. This is public due to being used in buffer.
enum PacketBoundary
Expand Down Expand Up @@ -203,7 +248,7 @@ friend class CRcvQueue;
/// Read the packet vector.
/// @return Pointer to the packet vector.

iovec* getPacketVector();
IOVector* getPacketVector();

uint32_t* getHeader() { return m_nHeader; }

Expand Down Expand Up @@ -358,7 +403,7 @@ friend class CRcvQueue;
// For example, something like that:
// class IoVector: public iovec { public: size_t size() { return iov_len; } char* data() { return iov_base; } };
// class IoVector: public WSAMSG { public: size_t size() { return len; } char* data() { return buf; } };
iovec m_PacketVector[PV_SIZE]; //< The 2-demension vector of UDT packet [header, data]
IOVector m_PacketVector[PV_SIZE]; //< The 2-demension vector of UDT packet [header, data]

int32_t __pad;
bool m_data_owned;
Expand Down

0 comments on commit bcbbe0f

Please sign in to comment.