1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227: 228: 229:
| unit IdIOHandlerThrottle;
interface uses Classes, IdComponent, IdGlobal, IdIOHandler;
type TIdIOHandlerThrottle = class(TIdIOHandler) protected FChainedHandler : TIdIOHandler; FBytesPerSec : Cardinal; FRate: double; FRealRate: double; FLastTime: cardinal; FLastRateTime: cardinal; FTotalBytes: integer; FActivated: boolean; function GetBitsPerSec : Cardinal; procedure SetBitsPerSec(AValue : Cardinal); procedure Notification(AComponent: TComponent; Operation: TOperation); override; public procedure Close; override; procedure ConnectClient(const AHost: string; const APort: Integer; const ABoundIP: string; const ABoundPort: Integer; const ABoundPortMin: Integer; const ABoundPortMax: Integer; const ATimeout: Integer = IdTimeoutDefault); override; function Connected: Boolean; override; constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure Open; override; function Readable(AMSec: integer = IdTimeoutDefault): boolean; override; function Recv(var ABuf; ALen: integer): integer; override; function Send(var ABuf; ALen: integer): integer; override; published property BytesPerSec : Cardinal read FBytesPerSec write FBytesPerSec; property BitsPerSec : Cardinal read GetBitsPerSec write SetBitsPerSec; property ChainedHandler : TIdIOHandler read FChainedHandler write FChainedHandler; property CurrentRate: double read FRate; property Activated: boolean read FActivated write FActivated; end;
implementation uses IdException, IdResourceStrings, SysUtils;
type EIdThrottleNoChainedIOHandler = class(EIdException);
procedure TIdIOHandlerThrottle.Close; begin inherited; if Assigned(FChainedHandler) then begin FChainedHandler.Close; end; end;
procedure TIdIOHandlerThrottle.ConnectClient(const AHost: string; const APort: Integer; const ABoundIP: string; const ABoundPort, ABoundPortMin, ABoundPortMax, ATimeout: Integer); begin inherited; if Assigned(FChainedHandler) then begin FChainedHandler.ConnectClient(AHost,APort,ABoundIP,ABoundPort,ABoundPortMin,ABoundPortMax,ATimeout); end else begin raise EIdThrottleNoChainedIOHandler.Create(RSIHTChainedNotAssigned); end; end;
function TIdIOHandlerThrottle.Connected: Boolean; begin if Assigned(FChainedHandler) then begin Result := FChainedHandler.Connected; end else begin Result := False; end; end;
constructor TIdIOHandlerThrottle.Create(AOwner: TComponent); begin inherited Create(AOwner); end;
destructor TIdIOHandlerThrottle.Destroy; begin Close; ChainedHandler.Free; ChainedHandler := nil; inherited Destroy; end;
function TIdIOHandlerThrottle.GetBitsPerSec: Cardinal; begin Result := FBytesPerSec * 8; end;
procedure TIdIOHandlerThrottle.Notification(AComponent: TComponent; Operation: TOperation); begin if (Operation = opRemove) then begin if (AComponent = FChainedHandler) then begin FChainedHandler := nil; end; end; inherited; end;
procedure TIdIOHandlerThrottle.Open; begin inherited Open; if Assigned(FChainedHandler) then begin FChainedHandler.Open; end else begin raise EIdThrottleNoChainedIOHandler.Create(RSIHTChainedNotAssigned); end; end;
function TIdIOHandlerThrottle.Readable(AMSec: integer): boolean; begin if Assigned(FChainedHandler) then begin Result := FChainedHandler.Readable(AMSec); end else begin Result := False; end; end;
function TIdIOHandlerThrottle.Recv(var ABuf; ALen: integer): integer; var LWaitTime : Cardinal; LRecVTime : Cardinal; begin if Assigned(FChainedHandler) then begin if FBytesPerSec > 0 then begin LRecvTime := IdGlobal.GetTickCount; Result := FChainedHandler.Recv(ABuf, ALen); LRecvTime := GetTickDiff(LRecvTime, IdGlobal.GetTickCount); LWaitTime := Cardinal(Result * 1000) div FBytesPerSec; if LWaitTime > LRecVTime then begin IdGlobal.Sleep(LWaitTime - LRecvTime); end; end else begin Result := FChainedHandler.Recv(ABuf, ALen); end; end else begin Result := 0; end; end;
function TIdIOHandlerThrottle.Send(var ABuf; ALen: integer): integer; var WaitTime : Cardinal; SendTime : Cardinal; NewRate: double; begin if Assigned(FChainedHandler) then begin if FBytesPerSec > 0 then begin WaitTime := Cardinal(ALen * 1000) div FBytesPerSec; SendTime := IdGlobal.GetTickCount; Result := FChainedHandler.Send(ABuf,ALen); SendTime := GetTickDiff(SendTime,IdGlobal.GetTickCount); if WaitTime = 0 then FRate := 0 else FRate := ALen / WaitTime; if WaitTime > SendTime then IdGlobal.Sleep(WaitTime - SendTime); end else begin SendTime := IdGlobal.GetTickCount; if FLastTime = 0 then begin FLastTime := SendTime; FTotalBytes := ALen; FRate := 0; end else begin if SendTime - FLastTime > 1000 then begin NewRate := FTotalBytes / (SendTime - FLastTime); FTotalBytes := ALen; FLastTime := SendTime; if FRealRate = 0 then begin FRealRate := NewRate; FRate := NewRate; end else begin FRate := (FRealRate + NewRate) / (SendTime - FLastRateTime) * 1000 / 2; FRealRate := NewRate; end; FLastRateTime := SendTime; end else FTotalBytes := FTotalBytes + ALen; end; Result := FChainedHandler.Send(ABuf,ALen); end; end else begin Result := 0; end; end;
procedure TIdIOHandlerThrottle.SetBitsPerSec(AValue: Cardinal); begin FBytesPerSec := AValue div 8; end;
end. |