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