00001 using System;
00002 using Common;
00003
00004 namespace ProtocolStack
00005 {
00010 public class Segment {
00011
00012 private SegmentHeaders headers;
00013 private SegmentData data;
00014
00015 public SegmentHeaders Headers {
00016 get { return headers; }
00017 set { headers = value; }
00018 }
00019
00020 public SegmentData Data {
00021 get { return data; }
00022 set { data = value; }
00023 }
00024
00029 public bool IsRetransmission {
00030 get { return headers.IsRetransmission; }
00031 set { headers.IsRetransmission = value; }
00032 }
00033
00034 public Segment() {}
00035
00036 public Segment(byte[] data) : base() {
00037 this.FromByteArray(data);
00038 }
00039
00040 public Segment(SegmentHeaders headers, SegmentData data) {
00041 this.headers = headers;
00042 this.data = data;
00043
00044 }
00045
00046 public byte[] ToByteArray(){
00047 byte[] result = new byte[headers.Length + data.Length];
00048 headers.ToByteArray().CopyTo(result, 0);
00049 data.ToByteArray().CopyTo(result, headers.Length);
00050 return result;
00051 }
00052
00053 public void FromByteArray(byte[] src) {
00054 int index = 0;
00055 headers = new SegmentHeaders();
00056 data = new SegmentData();
00057
00058 headers.FromByteArray(ref src, ref index);
00059 data.FromByteArray(ref src, ref index);
00060 }
00061
00062 }
00063
00064 public class SegmentDataTooBig : Exception {}
00065
00069 public class SegmentData {
00070 private byte[] data;
00071 public static readonly int MAX_DATA_SIZE = 471;
00072
00073
00074
00075 public SegmentData() {}
00076
00077 public SegmentData(byte[] data) {
00078 Data = data;
00079 }
00080
00081 public byte[] Data {
00082 get { return data; }
00083 set { if (value.Length <= MAX_DATA_SIZE) {
00084 data = value; }
00085 else {
00086 throw new SegmentDataTooBig();
00087 }
00088 }
00089 }
00090
00094 public ushort DataLength {
00095 get { if (data != null) {
00096 return (ushort)data.Length;
00097 } else {
00098 return 0;
00099 }
00100 }
00101 }
00102
00106 public ushort Length {
00107 get { return (ushort)(DataLength + 2); }
00108 }
00109
00110 public byte[] ToByteArray() {
00111 byte[] result = new byte[Length];
00112 BitConverter.GetBytes(DataLength).CopyTo(result, 0);
00113 Data.CopyTo(result, 2);
00114 return result;
00115 }
00116
00122 public void FromByteArray(ref byte[] src, ref int currentPos) {
00123 int tempLength;
00124 tempLength = BitConverter.ToUInt16(src, currentPos);
00125 currentPos += 2;
00126 Data = new byte[tempLength];
00127 for (int i = 0; i < tempLength; i++, currentPos++) {
00128 Data[i] = src[currentPos];
00129 }
00130 }
00131
00132 public void Test() {
00133 Data = new byte[] {1,2,3,4,5,6,7,8,9,10};
00134 }
00135
00141 public static SegmentData[] FromMessage(Message msg) {
00142 return FromMessage(msg, MAX_DATA_SIZE);
00143 }
00144
00145 public static SegmentData[] FromMessage(Message msg, int maxDataSize) {
00146 SegmentData[] result;
00147 int segmentCount = 0;
00148 long copyLength = 0;
00149 uint currentPos = 0;
00150 byte[] segmentDataBuffer = msg.ToByteArray();
00151
00152 segmentCount = (int)(Math.Ceiling((double)segmentDataBuffer.Length / maxDataSize));
00153 result = new SegmentData[segmentCount];
00154 for (int i = 0; i < segmentCount; i++) {
00155 result[i] = new SegmentData();
00156
00157 if ((segmentDataBuffer.Length - currentPos) > maxDataSize) {
00158 copyLength = maxDataSize; }
00159 else {
00160 copyLength = segmentDataBuffer.Length - currentPos;
00161 }
00162 result[i].Data = new byte[copyLength];
00163 Array.Copy(segmentDataBuffer, (int)currentPos, result[i].Data, 0, (int)copyLength);
00164 currentPos += (uint)copyLength;
00165 }
00166 return result;
00167 }
00173 public static byte[] ArrayToByteArray(SegmentData[] src) {
00174
00175 int numSegments = src.Length;
00176 int byteCount = 0;
00177 int bufferPtr = 0;
00178 byte[] buffer;
00179
00180 for (int i = 0; i < numSegments; i++) {
00181 byteCount += src[i].DataLength;
00182 }
00183 buffer = new byte[byteCount - 1];
00184
00185
00186 for (int i = 0; i < numSegments; i++) {
00187
00188 Array.Copy(src[i].Data, (i == 0) ? 1 : 0, buffer, bufferPtr, (i == 0) ? src[i].DataLength - 1 : src[i].DataLength);
00189 bufferPtr += src[i].DataLength - ((i == 0) ? 1 : 0);
00190 }
00191 return buffer;
00192 }
00193 }
00194
00195 public class SegmentHeaders {
00196 SegmentFlags flags;
00197
00198 uint synchOrRate;
00199 ushort srcDeviceID;
00200 bool isRetransmission;
00201
00202 uint sequenceNumber;
00203 DateTime sent;
00204 DateTime received;
00205
00206 uint ACK_SequenceNumberACKd;
00207
00208 uint NACK_SequenceNumberNACKd;
00209 uint NACK_Range;
00210
00211 public SegmentHeaders() {
00212 flags = new SegmentFlags();
00213 }
00214
00219 public bool IsRetransmission {
00220 get { return isRetransmission; }
00221 set { isRetransmission = value; }
00222 }
00223
00224 public DateTime TimeSent {
00225 get { return sent; }
00226 set { sent = value; }
00227 }
00228
00229 public DateTime TimeReceived {
00230 get { return received; }
00231 set { received = value; }
00232
00233 }
00234
00238 public int Length {
00239 get {
00240 int runningTotal = 0;
00241 runningTotal += flags.Length;
00242
00243 runningTotal += BitConverter.GetBytes(synchOrRate).Length;
00244
00245 runningTotal += BitConverter.GetBytes(srcDeviceID).Length;
00246
00247 runningTotal += BitConverter.GetBytes(sequenceNumber).Length;
00248
00249 runningTotal += BitConverter.GetBytes(sent.Ticks).Length;
00250
00251
00252 if (flags.isACK) {
00253 runningTotal += BitConverter.GetBytes(ACK_SequenceNumberACKd).Length;
00254 }
00255 if (flags.isNACK) {
00256 runningTotal += BitConverter.GetBytes(NACK_SequenceNumberNACKd).Length;
00257 if (flags.isRangedNACK) {
00258 runningTotal += BitConverter.GetBytes(NACK_Range).Length;
00259 }
00260 }
00261 return runningTotal;
00262 }
00263 }
00264
00269 public byte[] ToByteArray() {
00270 byte[] result = new byte[Length];
00271 byte[] buffer;
00272 int currentPos = 0;
00273 buffer = flags.ToByteArray();
00274 buffer.CopyTo(result, currentPos);
00275 currentPos += buffer.Length;
00276
00277 buffer = BitConverter.GetBytes(synchOrRate);
00278 buffer.CopyTo(result, currentPos);
00279 currentPos += buffer.Length;
00280
00281 buffer = BitConverter.GetBytes(srcDeviceID);
00282 buffer.CopyTo(result, currentPos);
00283 currentPos += buffer.Length;
00284
00285 buffer = BitConverter.GetBytes(sequenceNumber);
00286 buffer.CopyTo(result, currentPos);
00287 currentPos += buffer.Length;
00288
00289 buffer = BitConverter.GetBytes(sent.Ticks);
00290 buffer.CopyTo(result, currentPos);
00291 currentPos += buffer.Length;
00292
00293 if (flags.isACK) {
00294 buffer = BitConverter.GetBytes(ACK_SequenceNumberACKd);
00295 buffer.CopyTo(result, currentPos);
00296 currentPos += buffer.Length;
00297 }
00298
00299 if (flags.isNACK) {
00300 buffer = BitConverter.GetBytes(NACK_SequenceNumberNACKd);
00301 buffer.CopyTo(result, currentPos);
00302 currentPos += buffer.Length;
00303 if (flags.isRangedNACK) {
00304 buffer = BitConverter.GetBytes(NACK_Range);
00305 buffer.CopyTo(result, currentPos);
00306 currentPos += buffer.Length;
00307 }
00308 }
00309 return result;
00310 }
00311
00319 public void FromByteArray(ref byte[] src, ref int currentPos) {
00320 flags = new SegmentFlags();
00321 flags.FromByte(src[currentPos]);
00322 currentPos += 1;
00323
00324 synchOrRate = BitConverter.ToUInt32(src, currentPos);
00325 currentPos += 4;
00326
00327 srcDeviceID = BitConverter.ToUInt16(src, currentPos);
00328 currentPos += 2;
00329
00330 sequenceNumber = BitConverter.ToUInt32(src, currentPos);
00331 currentPos += 4;
00332
00333 sent = new DateTime(BitConverter.ToInt64(src, currentPos));
00334 currentPos += 8;
00335
00336 if (flags.isACK) {
00337 ACK_SequenceNumberACKd = BitConverter.ToUInt32(src, currentPos);
00338 currentPos += 4;
00339 }
00340
00341 if (flags.isNACK) {
00342 NACK_SequenceNumberNACKd = BitConverter.ToUInt32(src, currentPos);
00343 currentPos += 4;
00344 if (flags.isRangedNACK) {
00345 NACK_Range = BitConverter.ToUInt32(src, currentPos);
00346 currentPos += 4;
00347 }
00348 }
00349 }
00350
00351
00352 public void SetNACKStatus(NackInfo nackInfo) {
00353 flags.isNACK = true;
00354 NACK_SequenceNumberNACKd = nackInfo.SequenceNumber;
00355 flags.isRangedNACK = nackInfo.IsRanged;
00356 NACK_Range = (nackInfo.IsRanged ? nackInfo.Range : 0);
00357 }
00358
00359 public void ClearNACKStatus() {
00360 flags.isNACK = false;
00361 NACK_SequenceNumberNACKd = 0;
00362 flags.isRangedNACK = false;
00363 NACK_Range = 0;
00364 }
00365
00366 public void SetAck(AckInfo ackInfo) {
00367 flags.isACK = true;
00368 ACK_SequenceNumberACKd = ackInfo.SequenceNumber;
00369 }
00370
00371 public void ClearAck() {
00372 flags.isACK = false;
00373 ACK_SequenceNumberACKd = 0;
00374 }
00375
00376 public bool IsAckable {
00377 get { return flags.isACKable; }
00378 set { flags.isACKable = value; }
00379 }
00380
00384 public bool IsAck {
00385 get { return flags.isACK; }
00386 }
00387
00391 public uint ACKdSequenceNumber {
00392
00393 get { return ACK_SequenceNumberACKd; }
00394 }
00395
00396 public bool IsResynch {
00397 get { return flags.isSynchedPacket; }
00398 set { flags.isSynchedPacket = value; }
00399 }
00400
00401 public bool IsFirstInMessage {
00402 get { return flags.isFirstMessageSegment; }
00403 set { flags.isFirstMessageSegment= value; }
00404 }
00405 public bool IsLastInMessage {
00406 get { return flags.isLastMessageSegment; }
00407 set { flags.isLastMessageSegment = value; }
00408 }
00409
00410 public ushort SourceDeviceID {
00411 get { return srcDeviceID; }
00412 set { srcDeviceID = value; }
00413 }
00414
00415 public uint SequenceNumber {
00416 get {return sequenceNumber; }
00417 set {sequenceNumber = value; }
00418 }
00419
00420 public uint SynchOrRate {
00421 get { return synchOrRate; }
00422 set { synchOrRate = value; }
00423
00424 }
00425
00426 public bool IsNACK {
00427 get { return flags.isNACK; }
00428
00429 }
00430
00431 public bool IsRangedNACK {
00432 get { return flags.isRangedNACK; }
00433 }
00434
00435 public NackInfo NackInfo {
00436 get { return new NackInfo(NACK_SequenceNumberNACKd, NACK_Range); }
00437 }
00438
00439 public void Test() {
00440 flags = new SegmentFlags();
00441 flags.Test();
00442 srcDeviceID = 1234;
00443 sequenceNumber = 2;
00444 NACK_Range = 42;
00445 NACK_SequenceNumberNACKd = 314159;
00446 ACK_SequenceNumberACKd = 76;
00447 sent = DateTime.Now;
00448 }
00449
00450
00451 }
00452
00456 public class SegmentFlags {
00460 public int Length {
00461 get { return 1; }
00462 }
00463
00464
00465 public bool isACK;
00466 public bool isACKable;
00467 public bool isNACK;
00468 public bool isRangedNACK;
00469 public bool isSynchedPacket;
00470
00471
00472
00473
00474 public bool isFirstMessageSegment;
00475 public bool isLastMessageSegment;
00476
00477
00478 public byte[] ToByteArray() {
00479 byte temp = 0;
00480 temp += (byte)(isACK ? 1 : 0);
00481 temp += (byte)(isACKable ? 1 << 1 : 0);
00482 temp += (byte)(isNACK ? 1 << 2 : 0);
00483 temp += (byte)(isRangedNACK ? 1 << 3: 0);
00484 temp += (byte)(isSynchedPacket ? 1 << 4: 0);
00485 temp += (byte)(isFirstMessageSegment ? 1 << 5: 0);
00486 temp += (byte)(isLastMessageSegment ? 1 << 6: 0);
00487 temp += (byte)(false ? 1 << 7: 0);
00488 return new byte[] {temp};
00489 }
00490
00495 public void FromByteArray(byte[] src) {
00496 this.FromByte(src[0]);
00497 }
00498
00503 public void FromByte(byte src) {
00504 isACK = ((src & (1 << 0)) != 0);
00505 isACKable = ((src & (1 << 1)) != 0);
00506 isNACK = ((src & (1 << 2)) != 0);
00507 isRangedNACK = ((src & (1 << 3)) != 0);
00508 isSynchedPacket = ((src & (1 << 4)) != 0);
00509 isFirstMessageSegment = ((src & (1 << 5)) != 0);
00510 isLastMessageSegment = ((src & (1 << 6)) != 0);
00511 }
00512
00513 public void Test() {
00514 isACK = true;
00515 isACKable = true;
00516 isNACK = true;
00517 isRangedNACK = true;
00518 isSynchedPacket = false;
00519 isFirstMessageSegment = false;
00520 isLastMessageSegment = false;
00521 }
00522 }
00523
00524
00525 }