IdIntercept.pas 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  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. {$IF DEFINED(HAS_UNSAFE_OBJECT_REF)}[Unsafe]
  63. {$ELSEIF DEFINED(HAS_WEAK_OBJECT_REF)}[Weak]
  64. {$IFEND} FIntercept: TIdConnectionIntercept;
  65. FIsClient: Boolean;
  66. // When ARC is enabled, object references MUST be valid objects.
  67. // It is common for users to store non-object values, though, so
  68. // we will provide separate properties for those purposes
  69. //
  70. // TODO; use TValue instead of separating them
  71. //
  72. FDataObject: TObject;
  73. FDataValue: PtrInt;
  74. FOnConnect: TIdInterceptNotifyEvent;
  75. FOnDisconnect: TIdInterceptNotifyEvent;
  76. FOnReceive: TIdInterceptStreamEvent;
  77. FOnSend: TIdInterceptStreamEvent;
  78. //
  79. {$IFDEF USE_OBJECT_REF_FREENOTIF}
  80. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  81. {$ENDIF}
  82. procedure SetIntercept(AValue: TIdConnectionIntercept);
  83. //
  84. public
  85. constructor Create(AOwner: TComponent); override;
  86. procedure Connect(AConnection: TComponent); virtual;
  87. procedure Disconnect; virtual;
  88. procedure Receive(var VBuffer: TIdBytes); virtual;
  89. procedure Send(var VBuffer: TIdBytes); virtual;
  90. //
  91. property Connection: TComponent read FConnection;
  92. property IsClient: Boolean read FIsClient;
  93. // user can use these to keep context
  94. property DataObject: TObject read FDataObject write FDataObject;
  95. property DataValue: PtrInt read FDataValue write FDataValue;
  96. {$IFNDEF USE_OBJECT_ARC}
  97. property Data: TObject read FDataObject write FDataObject; // deprecated 'Use DataObject or DataValue property.';
  98. {$ENDIF}
  99. published
  100. property Intercept: TIdConnectionIntercept read FIntercept write SetIntercept;
  101. property OnConnect: TIdInterceptNotifyEvent read FOnConnect write FOnConnect;
  102. property OnDisconnect: TIdInterceptNotifyEvent read FOnDisconnect write FOnDisconnect;
  103. property OnReceive: TIdInterceptStreamEvent read FOnReceive write FOnReceive;
  104. property OnSend: TIdInterceptStreamEvent read FOnSend write FOnSend;
  105. end;
  106. TIdServerIntercept = class(TIdBaseComponent)
  107. public
  108. procedure Init; virtual; abstract;
  109. function Accept(AConnection: TComponent): TIdConnectionIntercept; virtual; abstract;
  110. end;
  111. implementation
  112. uses
  113. IdResourceStringsCore;
  114. { TIdIntercept }
  115. constructor TIdConnectionIntercept.Create(AOwner: TComponent);
  116. begin
  117. inherited Create(AOwner);
  118. FIsClient := True;
  119. end;
  120. procedure TIdConnectionIntercept.Disconnect;
  121. var
  122. // under ARC, convert a weak reference to a strong reference before working with it
  123. LIntercept: TIdConnectionIntercept;
  124. begin
  125. LIntercept := Intercept;
  126. if LIntercept <> nil then begin
  127. LIntercept.Disconnect;
  128. end;
  129. if Assigned(OnDisconnect) then begin
  130. OnDisconnect(Self);
  131. end;
  132. FConnection := nil;
  133. end;
  134. procedure TIdConnectionIntercept.Connect(AConnection: TComponent);
  135. var
  136. // under ARC, convert a weak reference to a strong reference before working with it
  137. LIntercept: TIdConnectionIntercept;
  138. begin
  139. FConnection := AConnection;
  140. if Assigned(OnConnect) then begin
  141. OnConnect(Self);
  142. end;
  143. LIntercept := Intercept;
  144. if LIntercept <> nil then begin
  145. LIntercept.Connect(AConnection);
  146. end;
  147. end;
  148. procedure TIdConnectionIntercept.Receive(var VBuffer: TIdBytes);
  149. var
  150. // under ARC, convert a weak reference to a strong reference before working with it
  151. LIntercept: TIdConnectionIntercept;
  152. begin
  153. LIntercept := Intercept;
  154. if LIntercept <> nil then begin
  155. LIntercept.Receive(VBuffer);
  156. end;
  157. if Assigned(OnReceive) then begin
  158. OnReceive(Self, VBuffer);
  159. end;
  160. end;
  161. procedure TIdConnectionIntercept.Send(var VBuffer: TIdBytes);
  162. var
  163. // under ARC, convert a weak reference to a strong reference before working with it
  164. LIntercept: TIdConnectionIntercept;
  165. begin
  166. if Assigned(OnSend) then begin
  167. OnSend(Self, VBuffer);
  168. end;
  169. LIntercept := Intercept;
  170. if LIntercept <> nil then begin
  171. LIntercept.Send(VBuffer);
  172. end;
  173. end;
  174. procedure TIdConnectionIntercept.SetIntercept(AValue: TIdConnectionIntercept);
  175. var
  176. // under ARC, convert weak references to strong references before working with them
  177. LIntercept: TIdConnectionIntercept;
  178. LNextValue: TIdConnectionIntercept;
  179. begin
  180. LIntercept := FIntercept;
  181. if LIntercept <> AValue then
  182. begin
  183. LNextValue := AValue;
  184. while Assigned(LNextValue) do begin
  185. if LNextValue = Self then begin //recursion
  186. raise EIdInterceptCircularLink.CreateFmt(RSInterceptCircularLink, [ClassName]);
  187. end;
  188. LNextValue := LNextValue.Intercept;
  189. end;
  190. // under ARC, all weak references to a freed object get nil'ed automatically
  191. {$IFDEF USE_OBJECT_REF_FREENOTIF}
  192. // remove self from the Intercept's free notification list
  193. if Assigned(LIntercept) then begin
  194. LIntercept.RemoveFreeNotification(Self);
  195. end;
  196. {$ENDIF}
  197. FIntercept := AValue;
  198. {$IFDEF USE_OBJECT_REF_FREENOTIF}
  199. // add self to the Intercept's free notification list
  200. if Assigned(AValue) then begin
  201. AValue.FreeNotification(Self);
  202. end;
  203. {$ENDIF}
  204. end;
  205. end;
  206. // under ARC, all weak references to a freed object get nil'ed automatically
  207. {$IFDEF USE_OBJECT_REF_FREENOTIF}
  208. procedure TIdConnectionIntercept.Notification(AComponent: TComponent; Operation: TOperation);
  209. begin
  210. if (Operation = opRemove) and (AComponent = FIntercept) then begin
  211. FIntercept := nil;
  212. end;
  213. inherited Notification(AComponent, OPeration);
  214. end;
  215. {$ENDIF}
  216. end.