IdIOHandlerThrottle.pas 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. { $HDR$}
  2. {**********************************************************************}
  3. { Unit archived using Team Coherence }
  4. { Team Coherence is Copyright 2002 by Quality Software Components }
  5. { }
  6. { For further information / comments, visit our WEB site at }
  7. { http://www.TeamCoherence.com }
  8. {**********************************************************************}
  9. {}
  10. { $Log: 10217: IdIOHandlerThrottle.pas
  11. {
  12. { Rev 1.1 14.8.2003 ã. 13:00:46 DBondzhev
  13. { we should not sleep when result is <= 0
  14. }
  15. {
  16. { Rev 1.0 2002.11.12 10:42:54 PM czhower
  17. }
  18. unit IdIOHandlerThrottle;
  19. interface
  20. uses
  21. Classes,
  22. IdComponent, IdGlobal, IdIOHandler;
  23. type
  24. TIdIOHandlerThrottle = class(TIdIOHandler)
  25. protected
  26. FChainedHandler : TIdIOHandler;
  27. FBytesPerSec : Cardinal;
  28. function GetBitsPerSec : Cardinal;
  29. procedure SetBitsPerSec(AValue : Cardinal);
  30. procedure SetChainedHandler(AValue: TIdIOHandler);
  31. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  32. public
  33. procedure Close; override;
  34. procedure ConnectClient(const AHost: string; const APort: Integer; const ABoundIP: string;
  35. const ABoundPort: Integer; const ABoundPortMin: Integer; const ABoundPortMax: Integer;
  36. const ATimeout: Integer = IdTimeoutDefault); override;
  37. function Connected: Boolean; override;
  38. constructor Create(AOwner: TComponent); override;
  39. destructor Destroy; override;
  40. procedure Open; override;
  41. function Readable(AMSec: integer = IdTimeoutDefault): boolean; override;
  42. function Recv(var ABuf; ALen: integer): integer; override;
  43. function Send(var ABuf; ALen: integer): integer; override;
  44. published
  45. property BytesPerSec : Cardinal read FBytesPerSec write FBytesPerSec;
  46. property BitsPerSec : Cardinal read GetBitsPerSec write SetBitsPerSec;
  47. property ChainedHandler : TIdIOHandler read FChainedHandler write SetChainedHandler;
  48. end;
  49. implementation
  50. uses
  51. IdException, IdResourceStrings, SysUtils;
  52. type
  53. EIdThrottleNoChainedIOHandler = class(EIdException);
  54. { TIdIOHandlerThrottle }
  55. procedure TIdIOHandlerThrottle.Close;
  56. begin
  57. inherited Close;
  58. if Assigned(FChainedHandler) then begin
  59. FChainedHandler.Close;
  60. end;
  61. end;
  62. procedure TIdIOHandlerThrottle.ConnectClient(const AHost: string;
  63. const APort: Integer; const ABoundIP: string; const ABoundPort,
  64. ABoundPortMin, ABoundPortMax, ATimeout: Integer);
  65. begin
  66. inherited ConnectClient(AHost, APort, ABoundIP, ABoundPort, ABoundPortMin, ABoundPortMax, ATimeout);
  67. if Assigned(FChainedHandler) then begin
  68. FChainedHandler.ConnectClient(AHost, APort, ABoundIP, ABoundPort, ABoundPortMin, ABoundPortMax, ATimeout);
  69. end else begin
  70. raise EIdThrottleNoChainedIOHandler.Create(RSIHTChainedNotAssigned);
  71. end;
  72. end;
  73. function TIdIOHandlerThrottle.Connected: Boolean;
  74. begin
  75. if Assigned(FChainedHandler) then begin
  76. Result := FChainedHandler.Connected;
  77. end else begin
  78. Result := False;
  79. end;
  80. end;
  81. constructor TIdIOHandlerThrottle.Create(AOwner: TComponent);
  82. begin
  83. inherited Create(AOwner);
  84. end;
  85. destructor TIdIOHandlerThrottle.Destroy;
  86. begin
  87. inherited Destroy;
  88. end;
  89. function TIdIOHandlerThrottle.GetBitsPerSec: Cardinal;
  90. begin
  91. Result := FBytesPerSec * 8;
  92. end;
  93. procedure TIdIOHandlerThrottle.Notification(AComponent: TComponent; Operation: TOperation);
  94. begin
  95. if (Operation = opRemove) and (AComponent = FChainedHandler) then begin
  96. FChainedHandler := nil;
  97. end;
  98. inherited Notification(AComponent, Operation);
  99. end;
  100. procedure TIdIOHandlerThrottle.Open;
  101. begin
  102. inherited Open;
  103. if Assigned(FChainedHandler) then begin
  104. FChainedHandler.Open;
  105. end else begin
  106. raise EIdThrottleNoChainedIOHandler.Create(RSIHTChainedNotAssigned);
  107. end;
  108. end;
  109. function TIdIOHandlerThrottle.Readable(AMSec: Integer): Boolean;
  110. begin
  111. if Assigned(FChainedHandler) then begin
  112. Result := FChainedHandler.Readable(AMSec);
  113. end else begin
  114. Result := False;
  115. end;
  116. end;
  117. function TIdIOHandlerThrottle.Recv(var ABuf; ALen: Integer): Integer;
  118. var
  119. LWaitTime, LRecVTime : Cardinal;
  120. begin
  121. if Assigned(FChainedHandler) then begin
  122. if FBytesPerSec > 0 then begin
  123. LRecvTime := IdGlobal.GetTickCount;
  124. Result := FChainedHandler.Recv(ABuf, ALen);
  125. if Result > 0 then begin
  126. LRecvTime := GetTickDiff(LRecvTime, IdGlobal.GetTickCount);
  127. LWaitTime := Cardinal(Result * 1000) div FBytesPerSec;
  128. if LWaitTime > LRecVTime then begin
  129. IdGlobal.Sleep(LWaitTime - LRecvTime);
  130. end;
  131. end;
  132. end else begin
  133. Result := FChainedHandler.Recv(ABuf, ALen);
  134. end;
  135. end else begin
  136. Result := 0;
  137. end;
  138. end;
  139. function TIdIOHandlerThrottle.Send(var ABuf; ALen: Integer): Integer;
  140. var
  141. WaitTime, SendTime : Cardinal;
  142. begin
  143. if Assigned(FChainedHandler) then begin
  144. if FBytesPerSec > 0 then begin
  145. WaitTime := Cardinal(ALen * 1000) div FBytesPerSec;
  146. SendTime := IdGlobal.GetTickCount;
  147. Result := FChainedHandler.Send(ABuf,ALen);
  148. SendTime := GetTickDiff(SendTime,IdGlobal.GetTickCount);
  149. if WaitTime > SendTime then begin
  150. IdGlobal.Sleep(WaitTime - SendTime);
  151. end;
  152. end else begin
  153. Result := FChainedHandler.Send(ABuf, ALen);
  154. end;
  155. end else begin
  156. Result := 0;
  157. end;
  158. end;
  159. procedure TIdIOHandlerThrottle.SetBitsPerSec(AValue: Cardinal);
  160. begin
  161. FBytesPerSec := AValue div 8;
  162. end;
  163. procedure TIdIOHandlerThrottle.SetChainedHandler(AValue: TIdIOHandler);
  164. begin
  165. if AValue <> FChainedHandler then begin
  166. FChainedHandler := AValue;
  167. if FChainedHandler <> nil then begin
  168. FChainedHandler.FreeNotification(Self);
  169. end;
  170. end;
  171. end;
  172. end.