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