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 }