00001 using System;
00002 using System.Threading;
00003
00004 namespace ProtocolStack
00005 {
00009 public class RateManager
00010 {
00012 int BDP;
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;
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) {
00058 lock (counterSyncRoot) {
00059
00060 bytesReceived = bytesSinceSegmentSent;
00061 bytesSinceSegmentSent = 0;
00062 }
00063 } else {
00064 lock (counterSyncRoot) {
00065
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
00081 lock (counterSyncRoot) {
00082 bytesSinceAckableSent += dataLength;
00083 bytesSinceSegmentSent += dataLength;
00084 }
00085
00086 if (!headers.IsResynch) {
00087 lock (creditSyncRoot) {
00088 if (headers.IsAckable) {
00089 int temp = sendCredit;
00090 sendCredit = (int)(creditAtLastACKableRx + headers.SynchOrRate);
00091
00092 creditAtLastACKableRx = sendCredit;
00093 } else {
00094 sendCredit += (int)headers.SynchOrRate;
00095
00096 }
00097 Monitor.PulseAll(creditSyncRoot);
00098 }
00099 } else {
00100
00101
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
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)) {
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
00151
00152
00153 public uint data;
00154 public RateInfo(uint bytesReceived) {
00155 data = bytesReceived;
00156 }
00157 }
00158 }