IdIntercept.pas 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. {
  2. $Project$
  3. $Workfile$
  4. $Revision$
  5. $DateUTC$
  6. $Id$
  7. This file is part of the Indy (Internet Direct) project, and is offered
  8. under the dual-licensing agreement described on the Indy website.
  9. (http://www.indyproject.org/)
  10. Copyright:
  11. (c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
  12. }
  13. {
  14. $Log$
  15. }
  16. {
  17. Rev 1.10 3/10/2005 12:00:46 AM JPMugaas
  18. Minor problem Craig Peterson had noted in an E-Mail to me.
  19. Rev 1.9 11/30/04 6:19:12 PM RLebeau
  20. Promoted the TIdConnectionIntercept.Intercept property from protected to
  21. published
  22. Rev 1.8 2004.02.03 4:16:44 PM czhower
  23. For unit name changes.
  24. Rev 1.7 2004.01.20 10:03:24 PM czhower
  25. InitComponent
  26. Rev 1.6 5/12/2003 12:33:32 AM GGrieve
  27. add Data from BlockCipher descendent
  28. Rev 1.5 2003.10.14 1:26:48 PM czhower
  29. Uupdates + Intercept support
  30. Rev 1.4 2003.10.11 5:48:16 PM czhower
  31. -VCL fixes for servers
  32. -Chain suport for servers (Super core)
  33. -Scheduler upgrades
  34. -Full yarn support
  35. Rev 1.3 10/5/2003 3:20:46 PM BGooijen
  36. .net
  37. Rev 1.2 2003.10.01 1:12:34 AM czhower
  38. .Net
  39. Rev 1.1 3/5/2003 10:59:48 PM BGooijen
  40. Fixed (i know, the SendBuffer looks bad)
  41. Rev 1.0 11/13/2002 08:44:42 AM JPMugaas
  42. 2002-03-01 - Andrew P.Rybin
  43. - Nested Intercept support (ex: ->logging->compression->encryption)
  44. 2002-04-09 - Chuck Smith
  45. - set ABuffer.Position := 0; in OnSend/OnReceive for Nested Stream send/receive
  46. }
  47. unit IdIntercept;
  48. interface
  49. {$I IdCompilerDefines.inc}
  50. //here only to put FPC in Delphi mode
  51. uses
  52. Classes,
  53. IdGlobal, IdBaseComponent, IdException;
  54. type
  55. EIdInterceptCircularLink = class(EIdException);
  56. TIdConnectionIntercept = class;
  57. TIdInterceptNotifyEvent = procedure(ASender: TIdConnectionIntercept) of object;
  58. TIdInterceptStreamEvent = procedure(ASender: TIdConnectionIntercept; var ABuffer: TIdBytes) of object;
  59. TIdConnectionIntercept = class(TIdBaseComponent)
  60. protected
  61. FConnection: TComponent;
  62. {$IFDEF USE_OBJECT_ARC}[Weak]{$ENDIF} FIntercept: TIdConnectionIntercept;
  63. FIsClient: Boolean;
  64. {$IFDEF USE_OBJECT_ARC}
  65. // When ARC is enabled, object references MUST be valid objects.
  66. // It is common for users to store non-object values, though, so
  67. // we will provide separate properties for those purposes
  68. //
  69. // TODO; use TValue instead of separating them
  70. //
  71. FDataObject: TObject;
  72. FDataValue: PtrInt;
  73. {$ELSE}
  74. FData: TObject;
  75. {$ENDIF}
  76. FOnConnect: TIdInterceptNotifyEvent;
  77. FOnDisconnect: TIdInterceptNotifyEvent;
  78. FOnReceive: TIdInterceptStreamEvent;
  79. FOnSend: TIdInterceptStreamEvent;
  80. //
  81. procedure InitComponent; override;
  82. {$IFNDEF USE_OBJECT_ARC}
  83. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  84. {$ENDIF}
  85. procedure SetIntercept(AValue: TIdConnectionIntercept);
  86. //
  87. public
  88. procedure Connect(AConnection: TComponent); virtual;
  89. procedure Disconnect; virtual;
  90. procedure Receive(var VBuffer: TIdBytes); virtual;
  91. procedure Send(var VBuffer: TIdBytes); virtual;
  92. //
  93. property Connection: TComponent read FConnection;
  94. property IsClient: Boolean read FIsClient;
  95. // user can use this to keep context
  96. {$IFDEF USE_OBJECT_ARC}
  97. property DataObject: TObject read FDataObject write FDataObject;
  98. property DataValue: PtrInt read FDataValue write FDataValue;
  99. {$ELSE}
  100. property Data: TObject read FData write FData;
  101. {$ENDIF}
  102. published
  103. property Intercept: TIdConnectionIntercept read FIntercept write SetIntercept;
  104. property OnConnect: TIdInterceptNotifyEvent read FOnConnect write FOnConnect;
  105. property OnDisconnect: TIdInterceptNotifyEvent read FOnDisconnect write FOnDisconnect;
  106. property OnReceive: TIdInterceptStreamEvent read FOnReceive write FOnReceive;
  107. property OnSend: TIdInterceptStreamEvent read FOnSend write FOnSend;
  108. end;
  109. TIdServerIntercept = class(TIdBaseComponent)
  110. public
  111. procedure Init; virtual; abstract;
  112. function Accept(AConnection: TComponent): TIdConnectionIntercept; virtual; abstract;
  113. end;
  114. implementation
  115. uses
  116. IdResourceStringsCore;
  117. { TIdIntercept }
  118. procedure TIdConnectionIntercept.Disconnect;
  119. var
  120. // under ARC, convert a weak reference to a strong reference before working with it
  121. LIntercept: TIdConnectionIntercept;
  122. begin
  123. LIntercept := Intercept;
  124. if LIntercept <> nil then begin
  125. LIntercept.Disconnect;
  126. end;
  127. if Assigned(OnDisconnect) then begin
  128. OnDisconnect(Self);
  129. end;
  130. FConnection := nil;
  131. end;
  132. procedure TIdConnectionIntercept.Connect(AConnection: TComponent);
  133. var
  134. // under ARC, convert a weak reference to a strong reference before working with it
  135. LIntercept: TIdConnectionIntercept;
  136. begin
  137. FConnection := AConnection;
  138. if Assigned(OnConnect) then begin
  139. OnConnect(Self);
  140. end;
  141. LIntercept := Intercept;
  142. if LIntercept <> nil then begin
  143. LIntercept.Connect(AConnection);
  144. end;
  145. end;
  146. procedure TIdConnectionIntercept.Receive(var VBuffer: TIdBytes);
  147. var
  148. // under ARC, convert a weak reference to a strong reference before working with it
  149. LIntercept: TIdConnectionIntercept;
  150. begin
  151. LIntercept := Intercept;
  152. if LIntercept <> nil then begin
  153. LIntercept.Receive(VBuffer);
  154. end;
  155. if Assigned(OnReceive) then begin
  156. OnReceive(Self, VBuffer);
  157. end;
  158. end;
  159. procedure TIdConnectionIntercept.Send(var VBuffer: TIdBytes);
  160. var
  161. // under ARC, convert a weak reference to a strong reference before working with it
  162. LIntercept: TIdConnectionIntercept;
  163. begin
  164. if Assigned(OnSend) then begin
  165. OnSend(Self, VBuffer);
  166. end;
  167. LIntercept := Intercept;
  168. if LIntercept <> nil then begin
  169. LIntercept.Send(VBuffer);
  170. end;
  171. end;
  172. procedure TIdConnectionIntercept.SetIntercept(AValue: TIdConnectionIntercept);
  173. var
  174. // under ARC, convert a weak reference to a strong reference before working with it
  175. LIntercept: TIdConnectionIntercept;
  176. LNextValue: TIdConnectionIntercept;
  177. begin
  178. LIntercept := FIntercept;
  179. if LIntercept <> AValue then
  180. begin
  181. LNextValue := AValue;
  182. while Assigned(LNextValue) do begin
  183. if LNextValue = Self then begin //recursion
  184. raise EIdInterceptCircularLink.CreateFmt(RSInterceptCircularLink, [ClassName]);
  185. end;
  186. LNextValue := LNextValue.Intercept;
  187. end;
  188. // under ARC, all weak references to a freed object get nil'ed automatically
  189. {$IFNDEF USE_OBJECT_ARC}
  190. // remove self from the Intercept's free notification list {Do not Localize}
  191. if Assigned(LIntercept) then begin
  192. LIntercept.RemoveFreeNotification(Self);
  193. end;
  194. {$ENDIF}
  195. FIntercept := AValue;
  196. {$IFNDEF USE_OBJECT_ARC}
  197. // add self to the Intercept's free notification list {Do not Localize}
  198. if Assigned(AValue) then begin
  199. AValue.FreeNotification(Self);
  200. end;
  201. {$ENDIF}
  202. end;
  203. end;
  204. // under ARC, all weak references to a freed object get nil'ed automatically
  205. {$IFNDEF USE_OBJECT_ARC}
  206. procedure TIdConnectionIntercept.Notification(AComponent: TComponent; Operation: TOperation);
  207. begin
  208. if (Operation = opRemove) and (AComponent = Intercept) then begin
  209. FIntercept := nil;
  210. end;
  211. inherited Notification(AComponent, OPeration);
  212. end;
  213. {$ENDIF}
  214. procedure TIdConnectionIntercept.InitComponent;
  215. begin
  216. inherited InitComponent;
  217. FIsClient := True;
  218. end;
  219. end.