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

ProtocolStack/RateManager.cs

00001 using System;
00002 using System.Threading;
00003 
00004 namespace ProtocolStack
00005 {
00009         public class RateManager
00010         {
00012                 int BDP; // bandwith delay product
00014                 private StackInterface thisStack;
00015                 private uint bytesSinceSegmentSent;
00016                 private uint bytesSinceAckableSent;
00020                 private Object counterSyncRoot; 
00021                 private Object creditSyncRoot;
00022                 int sendCredit; 
00023                 int creditAtLastACKableRx;
00024                                 
00025 
00027                 public RateManager(RemoteHostComms remoteHost) {
00028                         thisStack = remoteHost.thisStack;
00029                         counterSyncRoot = new Object();
00030                         creditSyncRoot = new Object();
00031                         Init();
00032                 }
00033 
00037                 public void ResetConnection() {
00038                         Console.WriteLine("Rate Manager Reset Started ...");
00039                         Init();
00040                         Console.WriteLine("... Rate Manager Reset Completed");
00041                 }
00042 
00046                 private void Init() {
00047                         BDP = thisStack.settings.DefaultBandwidthDelayProdut; // 8kb Bandwidth Delay product (default in settings)
00048                         bytesSinceSegmentSent = 0;
00049                         bytesSinceAckableSent = 0;
00050                         sendCredit = BDP;
00051                         creditAtLastACKableRx = sendCredit;
00052                 }
00053 
00055                 public RateInfo GetRateInfoForTx(bool IsAckable) {
00056                         uint bytesReceived = 0;
00057                         if (!IsAckable) { // regular segment
00058                                 lock (counterSyncRoot) {
00059                                         // get and clear 'bytesSinceLastRegularSegment'
00060                                         bytesReceived = bytesSinceSegmentSent;
00061                                         bytesSinceSegmentSent = 0;
00062                                 }
00063                         } else { // ackable segment
00064                                 lock (counterSyncRoot) {
00065                                         // get and clear 'bytesSinceLastAckableSegment'
00066                                         bytesReceived = bytesSinceAckableSent;
00067                                         bytesSinceAckableSent = 0;
00068                                         bytesSinceSegmentSent = 0;
00069                                 }
00070                         }
00071                         return new RateInfo(bytesReceived);
00072                 }
00073 
00079                 public void ProcessReceivedSegmentHeaders(ref SegmentHeaders headers, uint dataLength) {
00080                         // add to bytes received
00081                         lock (counterSyncRoot) {
00082                                 bytesSinceAckableSent += dataLength;
00083                                 bytesSinceSegmentSent += dataLength;
00084                         }
00085                         // add credit information
00086                         if (!headers.IsResynch) {
00087                                 lock (creditSyncRoot) {
00088                                         if (headers.IsAckable) {
00089                                                 int temp = sendCredit;
00090                                                 sendCredit = (int)(creditAtLastACKableRx + headers.SynchOrRate);
00091         //                                      Console.WriteLine("Forcing Send Credit from {0} to {1} ({2} + {3})", temp, sendCredit, creditAtLastACKableRx, headers.SynchOrRate);
00092                                                 creditAtLastACKableRx = sendCredit;
00093                                         } else { // non-ackable segment
00094                                                 sendCredit += (int)headers.SynchOrRate;
00095 //                                              Console.WriteLine("[+] New Send Credit = {0} bytes", sendCredit);
00096                                         }
00097                                 Monitor.PulseAll(creditSyncRoot);
00098                                 }
00099                         } else {
00100                                 // TODO: What happens when we have resynch segments?
00101                                 // no change to send credit
00102                         }
00103                 }
00104 
00109                 public void DecreaseSendCredit(int amount) {
00110                         lock (creditSyncRoot) {
00111                                 sendCredit -= amount;
00112                                 creditAtLastACKableRx -= amount;
00113                                 if (sendCredit < 0) { sendCredit = 0; }
00114 //                              Console.WriteLine("[-] New Send Credit = {0} bytes", sendCredit);
00115                                 Monitor.PulseAll(creditSyncRoot);
00116                         }
00117 
00118                 }
00119 
00125                 public bool WaitForSend(uint datagramSize, int secondsToWait) {
00126                         bool result = true;
00127                         lock(creditSyncRoot) {
00128                                 while (sendCredit <= datagramSize) {
00129                                         Console.WriteLine("Waiting for {0} bytes of credit", datagramSize);
00130                                         if (!Monitor.Wait(creditSyncRoot, secondsToWait * 1000)) { // if lock was not re-aquired before timeout
00131                                                 result = false;
00132                                                 break;
00133                                         }
00134                                 }
00135                                 return result; 
00136                         }
00137                 }
00138 
00144                 public bool CanSend(uint datagramSize) {
00145                         return (sendCredit > datagramSize);
00146                 }
00147         }
00148 
00149         public class RateInfo { 
00150                 /* not entirely sure how this one works, but it is what is sent along to tell
00151                  * the other host how fast to communicate.
00152                  * */
00153                 public uint data;
00154                 public RateInfo(uint bytesReceived) {
00155                         data = bytesReceived;                   
00156                 }
00157         }
00158 }

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