00001 using System;
00002 using System.Collections.Specialized;
00003 
00004 namespace GPRSWeb.SmartDeviceClient.SmartProtocolStack.RemoteHost
00005 {
00011         public class SequenceManager
00012         {
00013                 private uint nextInSendSequence; 
00014                 private uint expectedNextInReceiveSequence; 
00015 
00016                 private bool nextInSequenceUnknown; 
00017                 private uint sendSequenceRoot = 0; 
00018                 private uint receiveSequenceRoot = 0; 
00019 
00020                 private DateTime earliestMissing; 
00021                 private DateTime lastSeen; 
00022 
00023                 private int resynchCount = 0; 
00024 
00025                 private MissingList missingList; 
00026                 private NACKManager nackManager; 
00027 
00032                 public SequenceManager(NACKManager nackManager) {
00033                         Console.WriteLine("Creating Sequence Manager...");
00034                         StartResynch(); 
00035                         missingList = new MissingList();
00036                         earliestMissing = DateTime.MinValue; 
00037                         lastSeen = DateTime.MinValue; 
00038                         nextInSequenceUnknown = true;
00039                         this.nackManager = nackManager;
00040                         
00041                         Console.WriteLine("... Sequence Manager Created");
00042                 }
00043                 
00045                 uint LastSeenNumber {
00046                         get {return expectedNextInReceiveSequence - 1 ;}
00047                 }
00048 
00049                 public bool IsSegmentsMissing {
00050                         get { return missingList.AreSegmentsMissing; } 
00051                 }
00052 
00054 
00055 
00056 
00057                 public void ResetConnection() {
00058                         Console.WriteLine("Resetting Sequence Manager...");
00059                         StartResynch(); 
00060                         missingList.Clear();
00061                         earliestMissing = DateTime.MinValue;
00062                         lastSeen = DateTime.MinValue;
00063                         nextInSequenceUnknown = true;
00064                         Console.WriteLine("... Sequence Manager Reset");
00065                 }
00066 
00067                 public uint GetNextSequenceNumber() {
00068                         uint sequenceNumber;
00069                         
00070 
00071                         sequenceNumber = nextInSendSequence;
00072                         nextInSendSequence = (uint)(((long)nextInSendSequence + 1L) % UInt32.MaxValue);
00073                         return sequenceNumber;
00074                 }
00075 
00076                 private void StartResynch() {
00077                         Random r = new Random();
00078                         nextInSendSequence = (uint)r.Next(1000,9999);
00079                         sendSequenceRoot = nextInSendSequence;
00080                         resynchCount = 3;
00081                 }
00082 
00087                 public bool IsResynching {
00088                         get { return (resynchCount != 0); }
00089                 }
00090 
00091                 public uint GetSequenceOffset(uint number) {
00092                         
00093 
00094                         resynchCount--;
00095                         return (uint)(number - sendSequenceRoot); 
00096                 }
00097 
00098                 public void ProcessReceivedSegmentHeaders(ref SegmentHeaders headers) {
00099                         long numberOfMissingSegments = 0;
00100                         
00101 
00102 
00103 
00104 
00105 
00106                         if (nextInSequenceUnknown) {
00107                                 Console.WriteLine("    Next sequence # unknown, adopting #" + headers.SequenceNumber + " as next expected.");
00108                                 receiveSequenceRoot = headers.SequenceNumber;
00109                                 expectedNextInReceiveSequence = headers.SequenceNumber;
00110                                 
00111                                 nextInSequenceUnknown = false;
00112                         } else if (headers.IsResynch && !headers.IsRetransmission) {
00113                                 if (receiveSequenceRoot != headers.SequenceNumber - headers.SynchOrRate) {
00114                                         receiveSequenceRoot = (headers.SequenceNumber - headers.SynchOrRate); 
00115                                         Console.WriteLine("    Resynch Detected. Adopting #" + receiveSequenceRoot + " as root of new sequence");
00116                                         expectedNextInReceiveSequence = headers.SequenceNumber ; 
00117                                         Console.WriteLine("    Checking for missing segments at start of sequence");
00118                                         for (uint i = receiveSequenceRoot; i < headers.SequenceNumber; i++) {
00119                                                 Console.WriteLine("SeqManager: Mismatch between new sequence root and new segment. Issuing NACK");
00120                                                 nackManager.IssueNACK(i);
00121                                                 missingList.Add(i, lastSeen);
00122                                                 earliestMissing = missingList.GetEarliestMissingTime();
00123                                         }
00124                                         Console.WriteLine("    New sequence init complete");
00125                                 }
00126                         }
00127                         
00128                         
00129                         
00130                 
00131                         
00132                         if (missingList.IsMissing(headers.SequenceNumber)) {
00133                                 missingList.Remove(headers.SequenceNumber); 
00134                                 earliestMissing = missingList.GetEarliestMissingTime(); 
00135                                 if (earliestMissing == DateTime.MaxValue) { 
00136                                         earliestMissing = lastSeen; 
00137                                 }
00138                         }   
00139                                 
00140                         else { 
00141                                 if (headers.SequenceNumber != expectedNextInReceiveSequence) { 
00142                                         numberOfMissingSegments = (long)headers.SequenceNumber - (long)expectedNextInReceiveSequence;
00143                                         if (numberOfMissingSegments == 1) {     
00144                                                 nackManager.IssueNACK(expectedNextInReceiveSequence); 
00145                                                 missingList.Add(expectedNextInReceiveSequence, lastSeen);
00146                                         }
00147                                         else { 
00148                                                 nackManager.IssueNACK(expectedNextInReceiveSequence, numberOfMissingSegments); 
00149                                                 for (int i = 0; i < numberOfMissingSegments; i++) {
00150                                                         missingList.Add((uint)(expectedNextInReceiveSequence + i), lastSeen);
00151                                                 }
00152                                         }
00153                                         
00154                                         earliestMissing = missingList.GetEarliestMissingTime(); 
00155                                 } 
00156                                 expectedNextInReceiveSequence = (uint)(((ulong)headers.SequenceNumber + 1L) % UInt32.MaxValue); 
00157                                 
00158                                 lastSeen = headers.TimeSent;
00159                         } 
00160                         
00161                 }
00162 
00163                 public bool IsProcessable(SegmentHeaders headers) {
00164                         bool result = true;
00165                         if (headers.TimeSent < earliestMissing) { 
00166                                 result = false; 
00167                         }
00168                         
00169                         else if (headers.TimeSent == lastSeen) { 
00170                                 if (headers.SequenceNumber == LastSeenNumber) { result = false; } 
00171                                 else if ((headers.SequenceNumber < LastSeenNumber) && (!missingList.IsMissing(headers.SequenceNumber))) { result = false; } 
00172                         }
00173                         
00174                         else if (headers.TimeSent < lastSeen) { 
00175                                 if (!missingList.IsMissing(headers.SequenceNumber)) { result = false; } 
00176                         }
00177                         
00178                         
00179 
00180                         
00181                         if (headers.IsRetransmission)
00182                                 result = true; 
00183                         
00184                         return result;
00185                 }
00186 
00187         }
00188 
00192         class MissingList : HybridDictionary {
00199                 public bool IsMissing(uint target) {
00200                         return Contains(target);
00201                 }
00202 
00207                 public void Remove(uint sequenceNumber) {
00208                         base.Remove(sequenceNumber);
00209                 }
00210 
00216                 public void Add(uint sequenceNumber, DateTime lastSeen) {
00217                         base.Add(sequenceNumber, lastSeen);
00218                 } 
00219 
00225                 public DateTime GetEarliestMissingTime() {
00226                         DateTime result = DateTime.MaxValue; 
00227                         DateTime[] listValues = new DateTime[Values.Count];
00228                         this.Values.CopyTo(listValues, 0);
00229                         foreach (DateTime dt in listValues) {
00230                                 if (dt < result) { result = dt; }
00231                         }
00232                         return result;
00233                 }
00234 
00239                 public bool AreSegmentsMissing {
00240                         get { return (Count != 0); }
00241                 }
00242 
00243         }
00244 }