www.pudn.com > udt.rar > packet.cpp


/*****************************************************************************
This file contains the implementation of UDT packet handling modules.

A UDT packet is a 2-dimension vector of packet header and data.
*****************************************************************************/

//////////////////////////////////////////////////////////////////////////////
//    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                     |
//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//   |                          Time Stamp                           |
//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//
//   bit 0:
//      0: Data Packet
//      1: Control Packet
//
//    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       |           ACK Seq. No.        |
//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//   |                          Time Stamp                           |
//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//
//   bit 1-3:
//      000: Protocol Connection Handshake
//              bits 16-31:   Undefined
//              Control Info: Handshake information (see CHandShake)
//      001: Keep-alive
//              bits 16-31:   Undefined
//              Control Info: None
//      010: Acknowledgement (ACK)
//              bits 16-31:   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
//                            advertised flow window size (number of packets)
//                            estimated bandwidth (number of packets per second)
//      011: Negative Acknowledgement (NAK)
//              bits 16-31:   Undefined
//              Control Info: Loss list (see loss list coding below)
//      100: Congestion Warning
//              bits 16-31:   Undefined
//              Control Info: None
//      101: Shutdown
//              bits 16-31:   Undefined
//              Control Info: None
//      110: Acknowledgement of Acknowledement (ACK-square)
//              bits 16-31:   The ACK sequence number
//              Control Info: None
//      111: Explained by bits 4 - 15
//              
//   bit 4 - 15:
//      This space is used for future expansion or user defined control packets. 
//      Although a user defined packets can use this space freely, it is highly
//      recommended that lower bit is chosen first, i.e., starting from 0xFFF
//      for bits 4 - 15. For example, if a customized protocol need to add two 
//      new types of packets, 0xFFF and 0xFFE is recommended.
//
//    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 consectutive 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 consectutive loss less than 2 packets, use
//      the original sequence numbers in the field.

#include "udt.h"
__int32 CPacket::m_iPktHdrSize = 8;
// Set up the aliases in the constructure
CPacket::CPacket():
m_iSeqNo((__int32&)(m_nHeader[0])),
m_iTimeStamp((__int32&)(m_nHeader[1])),
m_pcData((char*&)(m_PacketVector[1].iov_base))
{
   m_PacketVector[0].iov_base = (char *)m_nHeader;
   m_PacketVector[0].iov_len = CPacket::m_iPktHdrSize;
}

CPacket::~CPacket()
{
}

__int32 CPacket::getLength() const
{
   return m_PacketVector[1].iov_len;
}

void CPacket::setLength(const __int32& len)
{
   m_PacketVector[1].iov_len = len;
}

void CPacket::pack(const __int32& pkttype, void* lparam, void* rparam, const __int32& size)
{
   // Set (bit-0 = 1) and (bit-1~3 = type)
   m_nHeader[0] = 0x80000000 | (pkttype << 28);

   // Set bit-16~31 and control information field
   switch (pkttype)
   {
   case 2: //010 - Acknowledgement (ACK)
      // ACK packet seq. no.
      if (NULL != lparam)
         m_nHeader[0] |= *(__int32 *)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[1].iov_base = (char *)rparam;
      m_PacketVector[1].iov_len = size;

      break;

   case 6: //110 - Acknowledgement of Acknowledgement (ACK-2)
      // ACK packet seq. no.
      m_nHeader[0] |= *(__int32 *)lparam;

      // control info field should be none
      // but "writev" does not allow this
      m_PacketVector[1].iov_base = (char *)&__pad; //NULL;
      m_PacketVector[1].iov_len = sizeof(__int32); //0;

      break;

   case 3: //011 - Loss Report (NAK)
      // loss list
      m_PacketVector[1].iov_base = (char *)rparam;
      m_PacketVector[1].iov_len = size;

      break;

   case 4: //100 - Congestion Warning
      // control info field should be none
      // but "writev" does not allow this
      m_PacketVector[1].iov_base = (char *)&__pad; //NULL;
      m_PacketVector[1].iov_len = sizeof(__int32); //0
  
      break;

   case 1: //001 - Keep-alive
      // control info field should be none
      // but "writev" does not allow this
      m_PacketVector[1].iov_base = (char *)&__pad; //NULL;
      m_PacketVector[1].iov_len = sizeof(__int32); //0

      break;

   case 0: //000 - Handshake
      // control info filed is handshake info
      m_PacketVector[1].iov_base = (char *)rparam;
      m_PacketVector[1].iov_len = size; //sizeof(CHandShake);

      break;

   case 5: //101 - Shutdown
      // control info field should be none
      // but "writev" does not allow this
      m_PacketVector[1].iov_base = (char *)&__pad; //NULL;
      m_PacketVector[1].iov_len = sizeof(__int32); //0

      break;

   case 7: //111 - Reserved for user defined control packets
      // for extended control packet
      // "lparam" contains the extneded type information for bit 4 - 15
      // "rparam" is the control information
      m_nHeader[0] |= (*(__int32 *)lparam) << 16;

      if (NULL != rparam)
      {
         m_PacketVector[1].iov_base = (char *)rparam;
         m_PacketVector[1].iov_len = size;
      }
      else
      {
         m_PacketVector[1].iov_base = (char *)&__pad;
         m_PacketVector[1].iov_len = sizeof(__int32);
      }

      break;

   default:
      break;
   }
}

iovec* CPacket::getPacketVector()
{
   return m_PacketVector;
}

__int32 CPacket::getFlag() const
{
   // read bit 0
   return m_nHeader[0] >> 31;
}

__int32 CPacket::getType() const
{
   // read bit 1~3
   return (m_nHeader[0] >> 28) & 0x00000007;
}

__int32 CPacket::getExtendedType() const
{
   // read bit 4~16
   return (m_nHeader[0] >> 16) & 0x00000FFF;
}

__int32 CPacket::getAckSeqNo() const
{
   // read bit 16~31
   return m_nHeader[0] & 0x0000FFFF;
}