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

SmartDeviceGUIClient/ACKManager.cs

00001 using System;
00002 using System.Threading;
00003 using System.Collections;
00004 using System.Collections.Specialized;
00005 
00006 namespace SmartDeviceGUIClient
00007 {
00008         public class ACKManager{}
00009 
00010 //      public class ACKManager2 {
00011 //              public static int INTER_ACKABLE_TIME;
00012 //              public static int FIRST_ACKABLE_TIME;
00013 //              public static int ACK_ARRIVAL_TIMEOUT;
00014 //
00015 //              private AckQueue ackQueue;
00016 //              private ReplyTracker replyTracker;
00017 //              private AckTimerList ackTimerList;
00018 //              private AckableGenerator ackableGenerator;
00019 //              private RemoteHostComms thisRemoteHost;
00020 //
00021 //              public ACKManager2(RemoteHostComms thisRemoteHost) {                    
00022 //                      this.thisRemoteHost = thisRemoteHost;
00023 //                      Init();
00024 //                      ackQueue = new AckQueue();
00025 //                      replyTracker = new ReplyTracker();
00026 //                      ackTimerList = new AckTimerList(replyTracker, thisRemoteHost.thisStack.connectionReset);
00027 //                      ackableGenerator = new AckableGenerator(thisRemoteHost);
00028 //              }
00029 //
00030 //              public void Init() {
00031 //                      INTER_ACKABLE_TIME = thisRemoteHost.thisStack.settings.InterAckableTime; // seconds
00032 //                      FIRST_ACKABLE_TIME = thisRemoteHost.thisStack.settings.FirstAckableTime; // seconds
00033 //                      ACK_ARRIVAL_TIMEOUT = thisRemoteHost.thisStack.settings.AckArrivalTimeout; // seconds
00034 //              }
00035 //
00036 //              public void ResetConnection() {
00037 //                      StopAckableGenerator();
00038 //            ackQueue.Clear();
00039 //                      ackTimerList.ResetConnection();
00040 //                      replyTracker.ResetConnection();
00041 //                      StartAckableGenerator();
00042 //              }
00043 //
00044 //              /// <summary>
00045 //              /// Determines if the next segment to be sent should be 'ackable'
00046 //              /// </summary>
00047 //              /// <returns></returns>
00048 //              public bool IsAckableWaiting() {
00049 //                      /* if we are due to send an ackable packet, this will return true. Else it will not.
00050 //                       * should maintain a count of ackable packets waiting (semaphore style?) */
00051 //                      return ackableGenerator.IsAckableWaiting;
00052 //              }
00053 //
00054 //              public void StartAckableGenerator() {
00055 //                      ackableGenerator.Start();
00056 //              }
00057 //
00058 //              public void StopAckableGenerator() {
00059 //                      ackableGenerator.Stop();
00060 //              }
00061 //              
00062 //              public AckInfo GetNextAck() {
00063 //                      /* returns details of the next acknowledgement that needs to be sent, 
00064 //                       * or null if no acknowledgement needs sending */
00065 //                      if (ackQueue.IsEmpty) { return null; } 
00066 //                      else return ackQueue.Dequeue(); 
00067 //              }
00068 //
00069 //              /// <summary>
00070 //              /// Sets timer awaiting arrival of the acknowledgemnt for just sent ackable packet.
00071 //              /// </summary>
00072 //              /// <param name="sequenceNumber">sequence number we are expecting an ACK for</param>
00073 //              public void SentAckableSegment(uint sequenceNumber) {
00074 //                      ackableGenerator.DecAckablesWaiting();
00075 //                      if (thisRemoteHost.readyToSendUserData) {
00076 //                              ackTimerList.AddTimer(sequenceNumber);
00077 //                      } else {
00078 //                              Console.WriteLine("    Did not set timer for return of ACK, since not ready to send");
00079 //                      }
00080 //                      //Console.WriteLine("ACK Manager: Ackable Segment #" + sequenceNumber +" just Sent");
00081 //              }
00082 //
00083 //              /// <summary>
00084 //              /// Issues and accepts acknowledgements from a set of Segment Headers
00085 //              /// </summary>
00086 //              /// <param name="headers">Segment Headers to process</param>
00087 //              public void ProcessReceivedSegmentHeaders(ref SegmentHeaders headers) {
00088 //                      /* if segment is an ACK, call SegmentAcknowledged(seqNum) 
00089 //                       * if segment is ACKable, call IssueACK(seqNum) 
00090 //                       * otherwise noop*/
00091 //                      if (headers.IsAck) { this.SegmentAcknowledged(headers.ACKdSequenceNumber); }
00092 //                      if (headers.IsAckable) { this.IssueACK(headers.SequenceNumber); }
00093 //              }
00094 //
00095 //              /// <summary>
00096 //              /// Processes the acknowledgement of a segment.
00097 //              /// </summary>
00098 //              /// <param name="ackdSequenceNumber">The segment number that has been acknowledged</param>
00099 //              private void SegmentAcknowledged(uint ackdSequenceNumber) {
00100 //                      /* If a timer for the segment has not yet expired: 
00101 //                       * - clear the timer
00102 //                       * - reset the 'Number of Acks missed in a row' counter
00103 //                       * else 
00104 //                       * - do nothing */
00105 //                      if (thisRemoteHost.readyToSendUserData) {
00106 //                              if (ackTimerList.Contains(ackdSequenceNumber)) {
00107 //                                      ackTimerList.RemoveTimer(ackdSequenceNumber);
00108 //                                      replyTracker.ACKReceived();
00109 //                                      //Console.WriteLine("ACK Manager: ACK received for segment#" + ackdSequenceNumber);
00110 //                              }
00111 //                      } else {
00112 //                              thisRemoteHost.readyToSendUserData = true;
00113 //                              Console.WriteLine("### First ACK received. Now READY TO SEND USER DATA ###");
00114 //                      }
00115 //                      
00116 //              }
00117 //
00118 //              private void IssueACK(uint sequenceNumberToACK) {
00119 //                      //Console.WriteLine("ACK Manager: Ackable received. Need to ACK #" + sequenceNumberToACK);
00120 //                      lock(thisRemoteHost.TxQueue.SyncRoot) {
00121 //                              if (thisRemoteHost.TxQueue.IsEmpty) {
00122 //                                      /* create no-op message */
00123 //                                      Message noopMsg = new EmptyMessage();
00124 //                                      noopMsg.Destination = thisRemoteHost.RemoteDeviceID;
00125 //                                      /* segmentise */
00126 //                                      TransmissionQueueEntry[] buffer = TransmissionQueueEntry.FromMessage(noopMsg);
00127 //                                      /* place results in segment queue */
00128 //                                      // make sure this all happens in a monitor, so we get them all together
00129 //                                      thisRemoteHost.TxQueue.EnqueueUnprotected(buffer, false);
00130 //                              }
00131 //                              ackQueue.Enqueue(new AckInfo(sequenceNumberToACK));
00132 //                              //Console.WriteLine("ACK Manager: ACK Issued for #" + sequenceNumberToACK);
00133 //                              Monitor.PulseAll(thisRemoteHost.TxQueue.SyncRoot);
00134 //                      }
00135 //                      
00136 //              }
00137 //      }
00138 //
00139 //      public class AckableGenerator {
00140 //              private int ackablesWaitingCount;
00141 //              private Timer ackableGenerateTimer;
00142 //              private RemoteHostComms thisRemoteHost;
00143 //              private TransmissionQueue txQueue;
00144 //              
00145 //              /// <summary>
00146 //              /// Creates a new generator of Ackable segments
00147 //              /// </summary>
00148 //              /// <param name="txQueue">The transmission queue to output carriers on to, if need be</param>
00149 //              public AckableGenerator(RemoteHostComms thisRemoteHost) {
00150 //                      this.thisRemoteHost = thisRemoteHost;
00151 //                      this.txQueue = thisRemoteHost.TxQueue;
00152 //                      ackablesWaitingCount = 0;
00153 //                      ackableGenerateTimer = new Timer(new TimerCallback(this.GeneratorTimerCallback), null, Timeout.Infinite, Timeout.Infinite);
00154 //              }
00155 //
00156 //              public void GeneratorTimerCallback(object o) {
00157 //                      lock(txQueue.SyncRoot) {
00158 //                              if (txQueue.IsEmpty) {
00159 //                                      /* create no-op message */
00160 //                                      Message noopMsg = new EmptyMessage();
00161 //                                      noopMsg.Destination = thisRemoteHost.RemoteDeviceID;
00162 //                                      /* segmentise */
00163 //                                      TransmissionQueueEntry[] buffer = TransmissionQueueEntry.FromMessage(noopMsg);
00164 //                                      /* place results in segment queue */
00165 //                                      // make sure this all happens in a monitor, so we get them all together
00166 //                                      txQueue.EnqueueUnprotected(buffer, false);
00167 //                              }
00168 //                              IncAckablesWaiting();
00169 //                              lock (thisRemoteHost.AckManager) {
00170 //                                      Monitor.PulseAll(thisRemoteHost.AckManager);
00171 //                              }
00172 //                              Monitor.PulseAll(txQueue.SyncRoot);
00173 //                      }
00174 //              }
00175 //
00176 //              public void IncAckablesWaiting() {
00177 //                      lock(this) {
00178 //                              ackablesWaitingCount++;
00179 //                      }
00180 //              }
00181 //              public void DecAckablesWaiting() {
00182 //                      lock(this) {
00183 //                              if (ackablesWaitingCount > 0) { ackablesWaitingCount--; }
00184 //                      }
00185 //              }
00186 //
00187 //              public void ResetConnection() {
00188 //                      lock(this) {
00189 //                              ackablesWaitingCount = 0;
00190 //                      }
00191 //              }
00192 //
00193 //              public void Start() {
00194 //                      ackableGenerateTimer.Change(ACKManager.FIRST_ACKABLE_TIME * 1000, ACKManager.INTER_ACKABLE_TIME * 1000);
00195 //              }
00196 //
00197 //              public void Stop() {
00198 //                      ackableGenerateTimer.Change(Timeout.Infinite, Timeout.Infinite);
00199 //              }
00200 //
00201 //              public bool IsAckableWaiting {
00202 //                      get {
00203 //                              bool result;
00204 //                              lock(this) {
00205 //                                      result = (ackablesWaitingCount != 0);
00206 //                              }
00207 //                              return result;
00208 //                      }
00209 //              }
00210 //
00211 //      }
00212 
00213         public class AckInfo {
00215                 uint sequenceNumber; // seq # of the segment that needs acking
00216 
00218                 public AckInfo(uint sequenceNumber) {
00219                         this.sequenceNumber = sequenceNumber;
00220                 }
00221 
00223                 public uint SequenceNumber { get { return sequenceNumber; } }
00224         }
00225 
00226 //      class AckQueue : Queue {
00227 //              public AckQueue() : base() {}
00228 //
00229 //              public void Enqueue(AckInfo ackInfo) {
00230 //                      lock (this.SyncRoot) {
00231 //                              base.Enqueue(ackInfo);                  
00232 //                              Monitor.PulseAll(this.SyncRoot);
00233 //                      } 
00234 //              }
00235 //
00236 //              public new AckInfo Dequeue() {
00237 //                      AckInfo result;
00238 //                      lock (this.SyncRoot) {
00239 //                              result = (AckInfo)base.Dequeue();
00240 //                      }
00241 //                      return result;
00242 //              }
00243 //
00244 //
00245 //              public bool IsEmpty {
00246 //                      get {
00247 //                              bool result;
00248 //                              lock (this.SyncRoot) {
00249 //                                      result = (this.Count == 0);
00250 //                              }
00251 //                              return result;
00252 //                      }
00253 //              }
00254 //
00255 //      }
00256 //
00257 //      class AckTimer {
00258 //              private Timer t;
00259 //
00260 //              public AckTimer(TimerInfo timerInfo, TimerCallback callback) {
00261 //                      t = new Timer(callback, timerInfo, Timeout.Infinite, Timeout.Infinite);
00262 //              }
00263 //
00264 //              public void StopTheClock() {
00265 //                      t.Change(Timeout.Infinite, Timeout.Infinite);
00266 //                      //t.Dispose();
00267 //                      //t = null; // cause garbage collecter to free some memory.
00268 //                      //Console.WriteLine("Clock Stopped");
00269 //              }
00270 //
00271 //              /// <summary>
00272 //              /// Starts the timer. 'TimerExpired' will execute after the number of milliseconds in the argument
00273 //              /// </summary>
00274 //              /// <param name="countdown">Number of milliseconds before timer expires</param>
00275 //              public void StartTheClock(uint countdown) {
00276 //                      t.Change(countdown, Timeout.Infinite);
00277 //                      //Console.WriteLine("Clock Started");
00278 //              }
00279 //      }
00280 //
00281 //      /// <summary>
00282 //      /// Maintains a list of the number of ACKs that have been missed in succession.
00283 //      /// Must be locked before use.
00284 //      /// </summary>
00285 //      class ReplyTracker {
00286 //              private int noReplyCount;
00287 //              public ReplyTracker() {
00288 //                      Init();
00289 //              }
00290 //
00291 //              private void Init() {
00292 //                      noReplyCount = 0;
00293 //              }
00294 //
00295 //              public void ResetConnection() {
00296 //                      Init();
00297 //              }
00298 //
00299 //              public void ACKMissed() {
00300 //                      noReplyCount++;
00301 //                      if (noReplyCount == 3) {
00302 //                              throw new ConnectionReset();
00303 //                      }
00304 //              }
00305 //
00306 //              public void ACKReceived() {
00307 //                      noReplyCount = 0;
00308 //              }
00309 //      }
00310 //
00311 //      /// <summary>
00312 //      /// List of AckTimers. Also deals with the 'three strikes and you're out' connection reset.
00313 //      /// </summary>
00314 //      class AckTimerList : ListDictionary {
00315 //              private ReplyTracker replyTracker;
00316 //              private ConnectionResetDelegate connectionReset;
00317 //
00318 //              public AckTimerList(ReplyTracker replyTracker, ConnectionResetDelegate connectionReset) : base() {
00319 //                      this.replyTracker = replyTracker;
00320 //                      this.connectionReset = connectionReset;
00321 //              }
00322 //
00323 //              /// <summary>
00324 //              /// Adds a timer to the list for a the ACK of a given sequence number.
00325 //              /// Sets it going on a 10 second fuse
00326 //              /// </summary>
00327 //              /// <param name="sequenceNumber">sequence number we are timing the ACK response for</param>
00328 //              public void AddTimer(uint sequenceNumber) {
00329 //                      TimerInfo info = new TimerInfo(sequenceNumber, replyTracker);
00330 //                      AckTimer timerObj = new AckTimer(info, new TimerCallback(this.TimerExpires));
00331 //                      base.Add(sequenceNumber, timerObj);
00332 //                      timerObj.StartTheClock((uint)ACKManager.ACK_ARRIVAL_TIMEOUT * 1000);
00333 //              }
00334 //
00335 //              /// <summary>
00336 //              /// Called by timer thread when a timer expires.
00337 //              /// </summary>
00338 //              /// <param name="obj">A TimerInfo object telling what segment number we were wating for, and where to record the count</param>
00339 //              public void TimerExpires(object obj){
00340 //                      try {
00341 //                              TimerInfo ti = (TimerInfo)obj;
00342 //                              lock(ti.tracker) {
00343 //                                      ti.tracker.ACKMissed();
00344 //                              }
00345 //                              this.RemoveTimer(ti.segmentNumber); 
00346 //                      } catch (ConnectionReset) {
00347 //                              Console.WriteLine("*** No traffic on connection for last 90 seconds. Connection Reset ***\n*** Calling Connection Reset Handler ***");
00348 //                              connectionReset();
00349 //                      }
00350 //              }
00351 //
00352 //              /// <summary>
00353 //              /// Stops timer for given sequence number, and removes it from the list. 
00354 //              /// </summary>
00355 //              /// <param name="sequenceNumber"></param>
00356 //              public void RemoveTimer(uint sequenceNumber) {
00357 //                      AckTimer workingTimer = (AckTimer)base[sequenceNumber];
00358 //                      if (workingTimer != null) {
00359 //                              workingTimer.StopTheClock();
00360 //                      }
00361 //                      base.Remove(sequenceNumber);
00362 //              }
00363 //
00364 //              /// <summary>
00365 //              /// Stops and removes all timers
00366 //              /// </summary>
00367 //              public void ResetConnection() {
00368 //                      foreach (DictionaryEntry de in this) {
00369 //                              AckTimer timer = (AckTimer)de.Value;
00370 //                              timer.StopTheClock();
00371 //                      }
00372 //                      Clear();
00373 //              }
00374 //      }
00375 //
00376 //      /// <summary>
00377 //      /// An object passed to the timer, which in turn passes it to the timer callback on firing.
00378 //      /// This object specifies where to find the ReplyTracker object, and what segement number we were wating for
00379 //      /// (this allows is to delete the timer)
00380 //      /// </summary>
00381 //      class TimerInfo {
00382 //              public uint segmentNumber;
00383 //              public ReplyTracker tracker;
00384 //
00385 //              public TimerInfo(uint segmentNumber, ReplyTracker tracker) {
00386 //                      this.segmentNumber = segmentNumber;
00387 //                      this.tracker = tracker;
00388 //              }
00389 //      }
00390 }

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