packet.cpp

00001 /*****************************************************************************
00002 Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois.
00003 All rights reserved.
00004 
00005 Redistribution and use in source and binary forms, with or without
00006 modification, are permitted provided that the following conditions are
00007 met:
00008 
00009 * Redistributions of source code must retain the above
00010   copyright notice, this list of conditions and the
00011   following disclaimer.
00012 
00013 * Redistributions in binary form must reproduce the
00014   above copyright notice, this list of conditions
00015   and the following disclaimer in the documentation
00016   and/or other materials provided with the distribution.
00017 
00018 * Neither the name of the University of Illinois
00019   nor the names of its contributors may be used to
00020   endorse or promote products derived from this
00021   software without specific prior written permission.
00022 
00023 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
00024 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
00025 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00026 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
00027 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00028 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00029 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00030 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00031 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00032 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00033 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00034 *****************************************************************************/
00035 
00036 /*****************************************************************************
00037 written by
00038    Yunhong Gu, last updated 02/12/2011
00039 *****************************************************************************/
00040 
00041 
00043 //    0                   1                   2                   3
00044 //    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
00045 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00046 //   |                        Packet Header                          |
00047 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00048 //   |                                                               |
00049 //   ~              Data / Control Information Field                 ~
00050 //   |                                                               |
00051 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00052 //
00053 //    0                   1                   2                   3
00054 //    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
00055 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00056 //   |0|                        Sequence Number                      |
00057 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00058 //   |ff |o|                     Message Number                      |
00059 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00060 //   |                          Time Stamp                           |
00061 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00062 //   |                     Destination Socket ID                     |
00063 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00064 //
00065 //   bit 0:
00066 //      0: Data Packet
00067 //      1: Control Packet
00068 //   bit ff:
00069 //      11: solo message packet
00070 //      10: first packet of a message
00071 //      01: last packet of a message
00072 //   bit o:
00073 //      0: in order delivery not required
00074 //      1: in order delivery required
00075 //
00076 //    0                   1                   2                   3
00077 //    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
00078 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00079 //   |1|            Type             |             Reserved          |
00080 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00081 //   |                       Additional Info                         |
00082 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00083 //   |                          Time Stamp                           |
00084 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00085 //   |                     Destination Socket ID                     |
00086 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00087 //
00088 //   bit 1-15:
00089 //      0: Protocol Connection Handshake
00090 //              Add. Info:    Undefined
00091 //              Control Info: Handshake information (see CHandShake)
00092 //      1: Keep-alive
00093 //              Add. Info:    Undefined
00094 //              Control Info: None
00095 //      2: Acknowledgement (ACK)
00096 //              Add. Info:    The ACK sequence number
00097 //              Control Info: The sequence number to which (but not include) all the previous packets have beed received
00098 //              Optional:     RTT
00099 //                            RTT Variance
00100 //                            available receiver buffer size (in bytes)
00101 //                            advertised flow window size (number of packets)
00102 //                            estimated bandwidth (number of packets per second)
00103 //      3: Negative Acknowledgement (NAK)
00104 //              Add. Info:    Undefined
00105 //              Control Info: Loss list (see loss list coding below)
00106 //      4: Congestion/Delay Warning
00107 //              Add. Info:    Undefined
00108 //              Control Info: None
00109 //      5: Shutdown
00110 //              Add. Info:    Undefined
00111 //              Control Info: None
00112 //      6: Acknowledgement of Acknowledement (ACK-square)
00113 //              Add. Info:    The ACK sequence number
00114 //              Control Info: None
00115 //      7: Message Drop Request
00116 //              Add. Info:    Message ID
00117 //              Control Info: first sequence number of the message
00118 //                            last seqeunce number of the message
00119 //      8: Error Signal from the Peer Side
00120 //              Add. Info:    Error code
00121 //              Control Info: None
00122 //      0x7FFF: Explained by bits 16 - 31
00123 //              
00124 //   bit 16 - 31:
00125 //      This space is used for future expansion or user defined control packets. 
00126 //
00127 //    0                   1                   2                   3
00128 //    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
00129 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00130 //   |1|                 Sequence Number a (first)                   |
00131 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00132 //   |0|                 Sequence Number b (last)                    |
00133 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00134 //   |0|                 Sequence Number (single)                    |
00135 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00136 //
00137 //   Loss List Field Coding:
00138 //      For any consectutive lost seqeunce numbers that the differnece between
00139 //      the last and first is more than 1, only record the first (a) and the
00140 //      the last (b) sequence numbers in the loss list field, and modify the
00141 //      the first bit of a to 1.
00142 //      For any single loss or consectutive loss less than 2 packets, use
00143 //      the original sequence numbers in the field.
00144 
00145 
00146 #include <cstring>
00147 #include "packet.h"
00148 
00149 
00150 const int CPacket::m_iPktHdrSize = 16;
00151 const int CHandShake::m_iContentSize = 48;
00152 
00153 
00154 // Set up the aliases in the constructure
00155 CPacket::CPacket():
00156 m_iSeqNo((int32_t&)(m_nHeader[0])),
00157 m_iMsgNo((int32_t&)(m_nHeader[1])),
00158 m_iTimeStamp((int32_t&)(m_nHeader[2])),
00159 m_iID((int32_t&)(m_nHeader[3])),
00160 m_pcData((char*&)(m_PacketVector[1].iov_base)),
00161 __pad()
00162 {
00163    for (int i = 0; i < 4; ++ i)
00164       m_nHeader[i] = 0;
00165    m_PacketVector[0].iov_base = (char *)m_nHeader;
00166    m_PacketVector[0].iov_len = CPacket::m_iPktHdrSize;
00167    m_PacketVector[1].iov_base = NULL;
00168    m_PacketVector[1].iov_len = 0;
00169 }
00170 
00171 CPacket::~CPacket()
00172 {
00173 }
00174 
00175 int CPacket::getLength() const
00176 {
00177    return m_PacketVector[1].iov_len;
00178 }
00179 
00180 void CPacket::setLength(int len)
00181 {
00182    m_PacketVector[1].iov_len = len;
00183 }
00184 
00185 void CPacket::pack(int pkttype, void* lparam, void* rparam, int size)
00186 {
00187    // Set (bit-0 = 1) and (bit-1~15 = type)
00188    m_nHeader[0] = 0x80000000 | (pkttype << 16);
00189 
00190    // Set additional information and control information field
00191    switch (pkttype)
00192    {
00193    case 2: //0010 - Acknowledgement (ACK)
00194       // ACK packet seq. no.
00195       if (NULL != lparam)
00196          m_nHeader[1] = *(int32_t *)lparam;
00197 
00198       // data ACK seq. no. 
00199       // optional: RTT (microsends), RTT variance (microseconds) advertised flow window size (packets), and estimated link capacity (packets per second)
00200       m_PacketVector[1].iov_base = (char *)rparam;
00201       m_PacketVector[1].iov_len = size;
00202 
00203       break;
00204 
00205    case 6: //0110 - Acknowledgement of Acknowledgement (ACK-2)
00206       // ACK packet seq. no.
00207       m_nHeader[1] = *(int32_t *)lparam;
00208 
00209       // control info field should be none
00210       // but "writev" does not allow this
00211       m_PacketVector[1].iov_base = (char *)&__pad; //NULL;
00212       m_PacketVector[1].iov_len = 4; //0;
00213 
00214       break;
00215 
00216    case 3: //0011 - Loss Report (NAK)
00217       // loss list
00218       m_PacketVector[1].iov_base = (char *)rparam;
00219       m_PacketVector[1].iov_len = size;
00220 
00221       break;
00222 
00223    case 4: //0100 - Congestion Warning
00224       // control info field should be none
00225       // but "writev" does not allow this
00226       m_PacketVector[1].iov_base = (char *)&__pad; //NULL;
00227       m_PacketVector[1].iov_len = 4; //0;
00228   
00229       break;
00230 
00231    case 1: //0001 - Keep-alive
00232       // control info field should be none
00233       // but "writev" does not allow this
00234       m_PacketVector[1].iov_base = (char *)&__pad; //NULL;
00235       m_PacketVector[1].iov_len = 4; //0;
00236 
00237       break;
00238 
00239    case 0: //0000 - Handshake
00240       // control info filed is handshake info
00241       m_PacketVector[1].iov_base = (char *)rparam;
00242       m_PacketVector[1].iov_len = size; //sizeof(CHandShake);
00243 
00244       break;
00245 
00246    case 5: //0101 - Shutdown
00247       // control info field should be none
00248       // but "writev" does not allow this
00249       m_PacketVector[1].iov_base = (char *)&__pad; //NULL;
00250       m_PacketVector[1].iov_len = 4; //0;
00251 
00252       break;
00253 
00254    case 7: //0111 - Message Drop Request
00255       // msg id 
00256       m_nHeader[1] = *(int32_t *)lparam;
00257 
00258       //first seq no, last seq no
00259       m_PacketVector[1].iov_base = (char *)rparam;
00260       m_PacketVector[1].iov_len = size;
00261 
00262       break;
00263 
00264    case 8: //1000 - Error Signal from the Peer Side
00265       // Error type
00266       m_nHeader[1] = *(int32_t *)lparam;
00267 
00268       // control info field should be none
00269       // but "writev" does not allow this
00270       m_PacketVector[1].iov_base = (char *)&__pad; //NULL;
00271       m_PacketVector[1].iov_len = 4; //0;
00272 
00273       break;
00274 
00275    case 32767: //0x7FFF - Reserved for user defined control packets
00276       // for extended control packet
00277       // "lparam" contains the extended type information for bit 16 - 31
00278       // "rparam" is the control information
00279       m_nHeader[0] |= *(int32_t *)lparam;
00280 
00281       if (NULL != rparam)
00282       {
00283          m_PacketVector[1].iov_base = (char *)rparam;
00284          m_PacketVector[1].iov_len = size;
00285       }
00286       else
00287       {
00288          m_PacketVector[1].iov_base = (char *)&__pad;
00289          m_PacketVector[1].iov_len = 4;
00290       }
00291 
00292       break;
00293 
00294    default:
00295       break;
00296    }
00297 }
00298 
00299 iovec* CPacket::getPacketVector()
00300 {
00301    return m_PacketVector;
00302 }
00303 
00304 int CPacket::getFlag() const
00305 {
00306    // read bit 0
00307    return m_nHeader[0] >> 31;
00308 }
00309 
00310 int CPacket::getType() const
00311 {
00312    // read bit 1~15
00313    return (m_nHeader[0] >> 16) & 0x00007FFF;
00314 }
00315 
00316 int CPacket::getExtendedType() const
00317 {
00318    // read bit 16~31
00319    return m_nHeader[0] & 0x0000FFFF;
00320 }
00321 
00322 int32_t CPacket::getAckSeqNo() const
00323 {
00324    // read additional information field
00325    return m_nHeader[1];
00326 }
00327 
00328 int CPacket::getMsgBoundary() const
00329 {
00330    // read [1] bit 0~1
00331    return m_nHeader[1] >> 30;
00332 }
00333 
00334 bool CPacket::getMsgOrderFlag() const
00335 {
00336    // read [1] bit 2
00337    return (1 == ((m_nHeader[1] >> 29) & 1));
00338 }
00339 
00340 int32_t CPacket::getMsgSeq() const
00341 {
00342    // read [1] bit 3~31
00343    return m_nHeader[1] & 0x1FFFFFFF;
00344 }
00345 
00346 CPacket* CPacket::clone() const
00347 {
00348    CPacket* pkt = new CPacket;
00349    memcpy(pkt->m_nHeader, m_nHeader, m_iPktHdrSize);
00350    pkt->m_pcData = new char[m_PacketVector[1].iov_len];
00351    memcpy(pkt->m_pcData, m_pcData, m_PacketVector[1].iov_len);
00352    pkt->m_PacketVector[1].iov_len = m_PacketVector[1].iov_len;
00353 
00354    return pkt;
00355 }
00356 
00357 CHandShake::CHandShake():
00358 m_iVersion(0),
00359 m_iType(0),
00360 m_iISN(0),
00361 m_iMSS(0),
00362 m_iFlightFlagSize(0),
00363 m_iReqType(0),
00364 m_iID(0),
00365 m_iCookie(0)
00366 {
00367    for (int i = 0; i < 4; ++ i)
00368       m_piPeerIP[i] = 0;
00369 }
00370 
00371 int CHandShake::serialize(char* buf, int& size)
00372 {
00373    if (size < m_iContentSize)
00374       return -1;
00375 
00376    int32_t* p = (int32_t*)buf;
00377    *p++ = m_iVersion;
00378    *p++ = m_iType;
00379    *p++ = m_iISN;
00380    *p++ = m_iMSS;
00381    *p++ = m_iFlightFlagSize;
00382    *p++ = m_iReqType;
00383    *p++ = m_iID;
00384    *p++ = m_iCookie;
00385    for (int i = 0; i < 4; ++ i)
00386       *p++ = m_piPeerIP[i];
00387 
00388    size = m_iContentSize;
00389 
00390    return 0;
00391 }
00392 
00393 int CHandShake::deserialize(const char* buf, int size)
00394 {
00395    if (size < m_iContentSize)
00396       return -1;
00397 
00398    int32_t* p = (int32_t*)buf;
00399    m_iVersion = *p++;
00400    m_iType = *p++;
00401    m_iISN = *p++;
00402    m_iMSS = *p++;
00403    m_iFlightFlagSize = *p++;
00404    m_iReqType = *p++;
00405    m_iID = *p++;
00406    m_iCookie = *p++;
00407    for (int i = 0; i < 4; ++ i)
00408       m_piPeerIP[i] = *p++;
00409 
00410    return 0;
00411 }

Generated on 9 Feb 2013 for barchart-udt-core-2.2.2 by  doxygen 1.6.1