Main Page | Class Hierarchy | Class List | File List | Class Members

ProtocolStack/SequenceManager.cs

00001 using System;
00002 using System.Collections.Specialized;
00003 
00004 namespace ProtocolStack
00005 {
00011         public class SequenceManager
00012         {
00013                 private uint nextInSendSequence; // next number to send
00014                 private uint expectedNextInReceiveSequence; // next number to receive
00015 
00016                 private bool nextInSequenceUnknown; // is the next receive number known?
00017                 private uint sendSequenceRoot = 0; // root of the current sent sequequence numbers
00018                 private uint receiveSequenceRoot = 0; // root of the current received sequence numbers
00019 
00020                 private DateTime earliestMissing; // the timestamp of segment we got before we missed one.
00021                 private DateTime lastSeen; // the timestamp of the segment last received
00022 
00023                 private int resynchCount = 0; // number of segments remaining before resynch complete
00024 
00025                 private MissingList missingList; // list of missing segments
00026                 private NACKManager nackManager; // the NACK manager that will issue NACKs
00027 
00032                 public SequenceManager(NACKManager nackManager) {
00033                         Console.WriteLine("Creating Sequence Manager...");
00034                         StartResynch(); // resets resynch counters
00035                         missingList = new MissingList();
00036                         earliestMissing = DateTime.MinValue; // init
00037                         lastSeen = DateTime.MinValue; // init
00038                         nextInSequenceUnknown = true;
00039                         this.nackManager = nackManager;
00040                         //TODO: Set up initial send sequence and do re-synch code if need be
00041                         Console.WriteLine("... Sequence Manager Created");
00042                 }
00043                 
00045                 uint LastSeenNumber {
00046                         get {return expectedNextInReceiveSequence - 1 /* mod stuff, changeover stuff */;}
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(); // reset the connection number
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                         /* Should loop round and round and round. 
00070                          * On new sequence number, should start talking about resynch numbers */
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                         /* returns the number of packets difference between 
00093                          * the sequence number passed to it, and the start of that sequence*/
00094                         resynchCount--;
00095                         return (uint)(number - sendSequenceRoot); // TODO: Correct for rollover
00096                 }
00097 
00098                 public void ProcessReceivedSegmentHeaders(ref SegmentHeaders headers) {
00099                         long numberOfMissingSegments = 0;
00100                         /* Deal with ReSynchronisation issues
00101                          * update expectedNextInReceiveSequence 
00102                          * update list of missing segments (add / remove entries)
00103                          * cutoff timestamps, last seen timestamps, etc?
00104                          * call NACK services if need be?
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                                 // TODO: May need to reset buffers, etc...
00111                                 nextInSequenceUnknown = false;
00112                         } else if (headers.IsResynch && !headers.IsRetransmission) {
00113                                 if (receiveSequenceRoot != headers.SequenceNumber - headers.SynchOrRate) {
00114                                         receiveSequenceRoot = (headers.SequenceNumber - headers.SynchOrRate); // TODO: Correct for wrapround
00115                                         Console.WriteLine("    Resynch Detected. Adopting #" + receiveSequenceRoot + " as root of new sequence");
00116                                         expectedNextInReceiveSequence = headers.SequenceNumber ; // TODO: Figure out how we can generate the right number of NACKs if we need to
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                         // We know that the segment has a timestamp greater than the one last seen, or is definitely on the missing list.
00128                         // What does it mean if the segment has the most recent timestamp, but a smaller sequence number than we've already seen? 
00129                         // Answer - rollover. That's OK.
00130                 
00131                         // first, if the segment that arrived fills a gap?
00132                         if (missingList.IsMissing(headers.SequenceNumber)) {
00133                                 missingList.Remove(headers.SequenceNumber); // remove it 
00134                                 earliestMissing = missingList.GetEarliestMissingTime(); // update the earliest missing thing.
00135                                 if (earliestMissing == DateTime.MaxValue) { // Sentinal Value
00136                                         earliestMissing = lastSeen; // a reasonable value
00137                                 }
00138                         }   // do not update last received timestamp
00139                                 // do not update next expected sequence number
00140                         else { // was not missing. See if it causes missing ones....
00141                                 if (headers.SequenceNumber != expectedNextInReceiveSequence) { // Something's gone missing
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                                         //Console.WriteLine(missingList.AsArray);
00154                                         earliestMissing = missingList.GetEarliestMissingTime(); // update the earliest missing thing.
00155                                 } // in both NACK issuing and non-nack issuing cases, we need to update some variables
00156                                 expectedNextInReceiveSequence = (uint)(((ulong)headers.SequenceNumber + 1L) % UInt32.MaxValue); // longs to prevent overflow
00157                                 // TODO: Fix for overflow?
00158                                 lastSeen = headers.TimeSent;
00159                         } 
00160                         //Console.WriteLine("Seq Manager: Process Received Segment Headers.... Done");
00161                 }
00162 
00163                 public bool IsProcessable(SegmentHeaders headers) {
00164                         bool result = true;
00165                         if (headers.TimeSent < earliestMissing) { 
00166                                 result = false; 
00167                         }
00168                         // all segments now >= earliestMissing
00169                         else if (headers.TimeSent == lastSeen) { // does it have same timestamp as the last seen segment?
00170                                 if (headers.SequenceNumber == LastSeenNumber) { result = false; } // discard - is a duplicate
00171                                 else if ((headers.SequenceNumber < LastSeenNumber) && (!missingList.IsMissing(headers.SequenceNumber))) { result = false; } // is a duplucate
00172                         }
00173                         // all segments now sent != last Seen time
00174                         else if (headers.TimeSent < lastSeen) { // is it now a duplicate, or a late segment?
00175                                 if (!missingList.IsMissing(headers.SequenceNumber)) { result = false; } // not missing => duplicate
00176                         }
00177                         // all segments either now > last seen time, and thus processable, or <= last seen time,
00178                         // > cutoff time, and are on missing list
00179 
00180                         /**** HACK HACK HACK ****/
00181                         if (headers.IsRetransmission)
00182                                 result = true; // always process retransmissions (for now)
00183                         /**** END HACK ****/
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 }

Generated on Mon May 8 22:07:27 2006 by  doxygen 1.3.9.1