OLD | NEW |
| (Empty) |
1 /***************************************************************************** | |
2 Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. | |
3 All rights reserved. | |
4 | |
5 Redistribution and use in source and binary forms, with or without | |
6 modification, are permitted provided that the following conditions are | |
7 met: | |
8 | |
9 * Redistributions of source code must retain the above | |
10 copyright notice, this list of conditions and the | |
11 following disclaimer. | |
12 | |
13 * Redistributions in binary form must reproduce the | |
14 above copyright notice, this list of conditions | |
15 and the following disclaimer in the documentation | |
16 and/or other materials provided with the distribution. | |
17 | |
18 * Neither the name of the University of Illinois | |
19 nor the names of its contributors may be used to | |
20 endorse or promote products derived from this | |
21 software without specific prior written permission. | |
22 | |
23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | |
24 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | |
25 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
26 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | |
27 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
28 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
29 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
30 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
31 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
32 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
33 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
34 *****************************************************************************/ | |
35 | |
36 /***************************************************************************** | |
37 written by | |
38 Yunhong Gu, last updated 02/12/2011 | |
39 *****************************************************************************/ | |
40 | |
41 | |
42 ////////////////////////////////////////////////////////////////////////////// | |
43 // 0 1 2 3 | |
44 // 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 | |
45 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
46 // | Packet Header | | |
47 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
48 // | | | |
49 // ~ Data / Control Information Field ~ | |
50 // | | | |
51 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
52 // | |
53 // 0 1 2 3 | |
54 // 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 | |
55 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
56 // |0| Sequence Number | | |
57 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
58 // |ff |o| Message Number | | |
59 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
60 // | Time Stamp | | |
61 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
62 // | Destination Socket ID | | |
63 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
64 // | |
65 // bit 0: | |
66 // 0: Data Packet | |
67 // 1: Control Packet | |
68 // bit ff: | |
69 // 11: solo message packet | |
70 // 10: first packet of a message | |
71 // 01: last packet of a message | |
72 // bit o: | |
73 // 0: in order delivery not required | |
74 // 1: in order delivery required | |
75 // | |
76 // 0 1 2 3 | |
77 // 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 | |
78 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
79 // |1| Type | Reserved | | |
80 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
81 // | Additional Info | | |
82 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
83 // | Time Stamp | | |
84 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
85 // | Destination Socket ID | | |
86 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
87 // | |
88 // bit 1-15: | |
89 // 0: Protocol Connection Handshake | |
90 // Add. Info: Undefined | |
91 // Control Info: Handshake information (see CHandShake) | |
92 // 1: Keep-alive | |
93 // Add. Info: Undefined | |
94 // Control Info: None | |
95 // 2: Acknowledgement (ACK) | |
96 // Add. Info: The ACK sequence number | |
97 // Control Info: The sequence number to which (but not include) all
the previous packets have beed received | |
98 // Optional: RTT | |
99 // RTT Variance | |
100 // available receiver buffer size (in bytes) | |
101 // advertised flow window size (number of packets) | |
102 // estimated bandwidth (number of packets per second) | |
103 // 3: Negative Acknowledgement (NAK) | |
104 // Add. Info: Undefined | |
105 // Control Info: Loss list (see loss list coding below) | |
106 // 4: Congestion/Delay Warning | |
107 // Add. Info: Undefined | |
108 // Control Info: None | |
109 // 5: Shutdown | |
110 // Add. Info: Undefined | |
111 // Control Info: None | |
112 // 6: Acknowledgement of Acknowledement (ACK-square) | |
113 // Add. Info: The ACK sequence number | |
114 // Control Info: None | |
115 // 7: Message Drop Request | |
116 // Add. Info: Message ID | |
117 // Control Info: first sequence number of the message | |
118 // last seqeunce number of the message | |
119 // 8: Error Signal from the Peer Side | |
120 // Add. Info: Error code | |
121 // Control Info: None | |
122 // 0x7FFF: Explained by bits 16 - 31 | |
123 // | |
124 // bit 16 - 31: | |
125 // This space is used for future expansion or user defined control packets.
| |
126 // | |
127 // 0 1 2 3 | |
128 // 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 | |
129 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
130 // |1| Sequence Number a (first) | | |
131 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
132 // |0| Sequence Number b (last) | | |
133 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
134 // |0| Sequence Number (single) | | |
135 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
136 // | |
137 // Loss List Field Coding: | |
138 // For any consectutive lost seqeunce numbers that the differnece between | |
139 // the last and first is more than 1, only record the first (a) and the | |
140 // the last (b) sequence numbers in the loss list field, and modify the | |
141 // the first bit of a to 1. | |
142 // For any single loss or consectutive loss less than 2 packets, use | |
143 // the original sequence numbers in the field. | |
144 | |
145 | |
146 #include <cstring> | |
147 #include "packet.h" | |
148 | |
149 | |
150 const int CPacket::m_iPktHdrSize = 16; | |
151 const int CHandShake::m_iContentSize = 48; | |
152 | |
153 | |
154 // Set up the aliases in the constructure | |
155 CPacket::CPacket(): | |
156 m_iSeqNo((int32_t&)(m_nHeader[0])), | |
157 m_iMsgNo((int32_t&)(m_nHeader[1])), | |
158 m_iTimeStamp((int32_t&)(m_nHeader[2])), | |
159 m_iID((int32_t&)(m_nHeader[3])), | |
160 m_pcData((char*&)(m_PacketVector[1].iov_base)), | |
161 __pad() | |
162 { | |
163 for (int i = 0; i < 4; ++ i) | |
164 m_nHeader[i] = 0; | |
165 m_PacketVector[0].iov_base = (char *)m_nHeader; | |
166 m_PacketVector[0].iov_len = CPacket::m_iPktHdrSize; | |
167 m_PacketVector[1].iov_base = NULL; | |
168 m_PacketVector[1].iov_len = 0; | |
169 } | |
170 | |
171 CPacket::~CPacket() | |
172 { | |
173 } | |
174 | |
175 int CPacket::getLength() const | |
176 { | |
177 return m_PacketVector[1].iov_len; | |
178 } | |
179 | |
180 void CPacket::setLength(const int& len) | |
181 { | |
182 m_PacketVector[1].iov_len = len; | |
183 } | |
184 | |
185 void CPacket::pack(const int& pkttype, void* lparam, void* rparam, const int& si
ze) | |
186 { | |
187 // Set (bit-0 = 1) and (bit-1~15 = type) | |
188 m_nHeader[0] = 0x80000000 | (pkttype << 16); | |
189 | |
190 // Set additional information and control information field | |
191 switch (pkttype) | |
192 { | |
193 case 2: //0010 - Acknowledgement (ACK) | |
194 // ACK packet seq. no. | |
195 if (NULL != lparam) | |
196 m_nHeader[1] = *(int32_t *)lparam; | |
197 | |
198 // data ACK seq. no. | |
199 // optional: RTT (microsends), RTT variance (microseconds) advertised flow
window size (packets), and estimated link capacity (packets per second) | |
200 m_PacketVector[1].iov_base = (char *)rparam; | |
201 m_PacketVector[1].iov_len = size; | |
202 | |
203 break; | |
204 | |
205 case 6: //0110 - Acknowledgement of Acknowledgement (ACK-2) | |
206 // ACK packet seq. no. | |
207 m_nHeader[1] = *(int32_t *)lparam; | |
208 | |
209 // control info field should be none | |
210 // but "writev" does not allow this | |
211 m_PacketVector[1].iov_base = (char *)&__pad; //NULL; | |
212 m_PacketVector[1].iov_len = 4; //0; | |
213 | |
214 break; | |
215 | |
216 case 3: //0011 - Loss Report (NAK) | |
217 // loss list | |
218 m_PacketVector[1].iov_base = (char *)rparam; | |
219 m_PacketVector[1].iov_len = size; | |
220 | |
221 break; | |
222 | |
223 case 4: //0100 - Congestion Warning | |
224 // control info field should be none | |
225 // but "writev" does not allow this | |
226 m_PacketVector[1].iov_base = (char *)&__pad; //NULL; | |
227 m_PacketVector[1].iov_len = 4; //0; | |
228 | |
229 break; | |
230 | |
231 case 1: //0001 - Keep-alive | |
232 // control info field should be none | |
233 // but "writev" does not allow this | |
234 m_PacketVector[1].iov_base = (char *)&__pad; //NULL; | |
235 m_PacketVector[1].iov_len = 4; //0; | |
236 | |
237 break; | |
238 | |
239 case 0: //0000 - Handshake | |
240 // control info filed is handshake info | |
241 m_PacketVector[1].iov_base = (char *)rparam; | |
242 m_PacketVector[1].iov_len = size; //sizeof(CHandShake); | |
243 | |
244 break; | |
245 | |
246 case 5: //0101 - Shutdown | |
247 // control info field should be none | |
248 // but "writev" does not allow this | |
249 m_PacketVector[1].iov_base = (char *)&__pad; //NULL; | |
250 m_PacketVector[1].iov_len = 4; //0; | |
251 | |
252 break; | |
253 | |
254 case 7: //0111 - Message Drop Request | |
255 // msg id | |
256 m_nHeader[1] = *(int32_t *)lparam; | |
257 | |
258 //first seq no, last seq no | |
259 m_PacketVector[1].iov_base = (char *)rparam; | |
260 m_PacketVector[1].iov_len = size; | |
261 | |
262 break; | |
263 | |
264 case 8: //1000 - Error Signal from the Peer Side | |
265 // Error type | |
266 m_nHeader[1] = *(int32_t *)lparam; | |
267 | |
268 // control info field should be none | |
269 // but "writev" does not allow this | |
270 m_PacketVector[1].iov_base = (char *)&__pad; //NULL; | |
271 m_PacketVector[1].iov_len = 4; //0; | |
272 | |
273 break; | |
274 | |
275 case 32767: //0x7FFF - Reserved for user defined control packets | |
276 // for extended control packet | |
277 // "lparam" contains the extended type information for bit 16 - 31 | |
278 // "rparam" is the control information | |
279 m_nHeader[0] |= *(int32_t *)lparam; | |
280 | |
281 if (NULL != rparam) | |
282 { | |
283 m_PacketVector[1].iov_base = (char *)rparam; | |
284 m_PacketVector[1].iov_len = size; | |
285 } | |
286 else | |
287 { | |
288 m_PacketVector[1].iov_base = (char *)&__pad; | |
289 m_PacketVector[1].iov_len = 4; | |
290 } | |
291 | |
292 break; | |
293 | |
294 default: | |
295 break; | |
296 } | |
297 } | |
298 | |
299 iovec* CPacket::getPacketVector() | |
300 { | |
301 return m_PacketVector; | |
302 } | |
303 | |
304 int CPacket::getFlag() const | |
305 { | |
306 // read bit 0 | |
307 return m_nHeader[0] >> 31; | |
308 } | |
309 | |
310 int CPacket::getType() const | |
311 { | |
312 // read bit 1~15 | |
313 return (m_nHeader[0] >> 16) & 0x00007FFF; | |
314 } | |
315 | |
316 int CPacket::getExtendedType() const | |
317 { | |
318 // read bit 16~31 | |
319 return m_nHeader[0] & 0x0000FFFF; | |
320 } | |
321 | |
322 int32_t CPacket::getAckSeqNo() const | |
323 { | |
324 // read additional information field | |
325 return m_nHeader[1]; | |
326 } | |
327 | |
328 int CPacket::getMsgBoundary() const | |
329 { | |
330 // read [1] bit 0~1 | |
331 return m_nHeader[1] >> 30; | |
332 } | |
333 | |
334 bool CPacket::getMsgOrderFlag() const | |
335 { | |
336 // read [1] bit 2 | |
337 return (1 == ((m_nHeader[1] >> 29) & 1)); | |
338 } | |
339 | |
340 int32_t CPacket::getMsgSeq() const | |
341 { | |
342 // read [1] bit 3~31 | |
343 return m_nHeader[1] & 0x1FFFFFFF; | |
344 } | |
345 | |
346 CPacket* CPacket::clone() const | |
347 { | |
348 CPacket* pkt = new CPacket; | |
349 memcpy(pkt->m_nHeader, m_nHeader, m_iPktHdrSize); | |
350 pkt->m_pcData = new char[m_PacketVector[1].iov_len]; | |
351 memcpy(pkt->m_pcData, m_pcData, m_PacketVector[1].iov_len); | |
352 pkt->m_PacketVector[1].iov_len = m_PacketVector[1].iov_len; | |
353 | |
354 return pkt; | |
355 } | |
356 | |
357 CHandShake::CHandShake(): | |
358 m_iVersion(0), | |
359 m_iType(0), | |
360 m_iISN(0), | |
361 m_iMSS(0), | |
362 m_iFlightFlagSize(0), | |
363 m_iReqType(0), | |
364 m_iID(0), | |
365 m_iCookie(0), | |
366 m_piPeerIP() | |
367 { | |
368 } | |
369 | |
370 int CHandShake::serialize(char* buf, int& size) | |
371 { | |
372 if (size < m_iContentSize) | |
373 return -1; | |
374 | |
375 int32_t* p = (int32_t*)buf; | |
376 *p++ = m_iVersion; | |
377 *p++ = m_iType; | |
378 *p++ = m_iISN; | |
379 *p++ = m_iMSS; | |
380 *p++ = m_iFlightFlagSize; | |
381 *p++ = m_iReqType; | |
382 *p++ = m_iID; | |
383 *p++ = m_iCookie; | |
384 for (int i = 0; i < 4; ++ i) | |
385 *p++ = m_piPeerIP[i]; | |
386 | |
387 size = m_iContentSize; | |
388 | |
389 return 0; | |
390 } | |
391 | |
392 int CHandShake::deserialize(const char* buf, const int& size) | |
393 { | |
394 if (size < m_iContentSize) | |
395 return -1; | |
396 | |
397 int32_t* p = (int32_t*)buf; | |
398 m_iVersion = *p++; | |
399 m_iType = *p++; | |
400 m_iISN = *p++; | |
401 m_iMSS = *p++; | |
402 m_iFlightFlagSize = *p++; | |
403 m_iReqType = *p++; | |
404 m_iID = *p++; | |
405 m_iCookie = *p++; | |
406 for (int i = 0; i < 4; ++ i) | |
407 m_piPeerIP[i] = *p++; | |
408 | |
409 return 0; | |
410 } | |
OLD | NEW |