IdIPWatch.pas 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  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: 10225: IdIPWatch.pas
  11. {
  12. { Rev 1.1 12-15-2002 13:18:24 BGooijen
  13. { Fixed SetWatchInterval (bug # 650083)
  14. }
  15. {
  16. { Rev 1.0 2002.11.12 10:43:26 PM czhower
  17. }
  18. unit IdIPWatch;
  19. {
  20. Simple component determines Online status,
  21. returns current IP address, and (optionally) keeps history on
  22. IP's issued.
  23. 2000-Dec-22 Kudzu
  24. -Changed from a TTimer to a sleeping thread to eliminate the reference to ExtCtrls. This was the
  25. only unit in all of Indy that used this unit and caused the pkg to rely on extra pkgs.
  26. -Changed Enabled to Active to be more consistent
  27. -Active now also defaults to false to be more consistent
  28. 2000-MAY-10 Hadi Hariri
  29. -Added new feature to Force Check of status
  30. 2000-Apr-23 Hadi Hariri
  31. -Converted to Indy
  32. 2000-Mar-01 Johannes Berg <[email protected]>
  33. - new property HistoryFilename
  34. - new property MaxHistoryEntries
  35. - new property HistoryEnabled
  36. 2000-Jan-13 MTL
  37. -Moved to new Palette Scheme (Winshoes Misc)
  38. Original Author: Dave Nosker - AfterWave Technologies ([email protected])
  39. }
  40. //TODO: We are feature frozen now, but this should probably be moved to the GUI pkg in the future
  41. // (GUI Pkg will be a new pkg in 8.100 that links to forms etc and deals with things other than
  42. // just communications).
  43. interface
  44. uses
  45. Classes,
  46. IdComponent, IdThread;
  47. const
  48. IP_WATCH_HIST_MAX = 25;
  49. IP_WATCH_HIST_FILENAME = 'iphist.dat'; {Do not Localize}
  50. IP_WATCH_INTERVAL = 1000;
  51. type
  52. TIdIPWatchThread = class(TIdThread)
  53. protected
  54. FInterval: Integer;
  55. FSender: TObject;
  56. FTimerEvent: TNotifyEvent;
  57. //
  58. procedure Run; override;
  59. procedure TimerEvent;
  60. end;
  61. TIdIPWatch = class(TIdComponent)
  62. protected
  63. FActive: Boolean;
  64. FCurrentIP: string;
  65. FHistoryEnabled: Boolean;
  66. FHistoryFilename: string;
  67. FIPHistoryList: TStringList;
  68. FIsOnline: Boolean;
  69. FLocalIPHuntBusy: Boolean;
  70. FMaxHistoryEntries: Integer;
  71. FOnLineCount: Integer;
  72. FOnStatusChanged: TNotifyEvent;
  73. FPreviousIP: string;
  74. FThread: TIdIPWatchThread;
  75. FWatchInterval: Cardinal;
  76. //
  77. procedure AddToIPHistoryList(Value: string);
  78. procedure CheckStatus(Sender: TObject);
  79. procedure SetActive(Value: Boolean);
  80. procedure SetMaxHistoryEntries(Value: Integer);
  81. procedure SetWatchInterval(Value: Cardinal);
  82. public
  83. constructor Create(AOwner: TComponent); override;
  84. destructor Destroy; override;
  85. function ForceCheck: Boolean;
  86. procedure LoadHistory;
  87. function LocalIP: string;
  88. procedure SaveHistory;
  89. //
  90. property CurrentIP: string read FCurrentIP;
  91. property IPHistoryList: TStringList read FIPHistoryList;
  92. property IsOnline: Boolean read FIsOnline;
  93. property PreviousIP: string read FPreviousIP;
  94. published
  95. property Active: Boolean read FActive write SetActive;
  96. property HistoryEnabled: Boolean read FHistoryEnabled write FHistoryEnabled default True;
  97. property HistoryFilename: string read FHistoryFilename write FHistoryFilename;
  98. property MaxHistoryEntries: Integer read FMaxHistoryEntries write SetMaxHistoryEntries
  99. default IP_WATCH_HIST_MAX;
  100. property OnStatusChanged: TNotifyEvent read FOnStatusChanged write FOnStatusChanged;
  101. property WatchInterval: Cardinal read FWatchInterval write SetWatchInterval
  102. default IP_WATCH_INTERVAL;
  103. end;
  104. implementation
  105. uses
  106. IdGlobal, IdStack,
  107. SysUtils;
  108. { TIdIPWatch }
  109. procedure TIdIPWatch.AddToIPHistoryList(Value: string);
  110. begin
  111. if (Value = '') or (Value = '127.0.0.1') then {Do not Localize}
  112. begin
  113. Exit;
  114. end;
  115. // Make sure the last entry does not allready contain the new one...
  116. if FIPHistoryList.Count > 0 then
  117. begin
  118. if FIPHistoryList[FIPHistoryList.Count-1] = Value then
  119. begin
  120. Exit;
  121. end;
  122. end;
  123. FIPHistoryList.Add(Value);
  124. if FIPHistoryList.Count > MaxHistoryEntries then
  125. begin
  126. FIPHistoryList.Delete(0);
  127. end;
  128. end;
  129. procedure TIdIPWatch.CheckStatus(Sender: TObject);
  130. var
  131. WasOnLine: Boolean;
  132. OldIP: string;
  133. begin
  134. try
  135. if FLocalIPHuntBusy then
  136. begin
  137. Exit;
  138. end;
  139. WasOnLine := FIsOnline;
  140. OldIP := FCurrentIP;
  141. FCurrentIP := LocalIP;
  142. FIsOnline := (FCurrentIP <> '127.0.0.1') and (FCurrentIP <> ''); {Do not Localize}
  143. if (WasOnline) and (not FIsOnline) then
  144. begin
  145. if (OldIP <> '127.0.0.1') and (OldIP <> '') then {Do not Localize}
  146. begin
  147. FPreviousIP := OldIP;
  148. end;
  149. AddToIPHistoryList(FPreviousIP);
  150. end;
  151. if (not WasOnline) and (FIsOnline) then
  152. begin
  153. if FOnlineCount = 0 then
  154. begin
  155. FOnlineCount := 1;
  156. end;
  157. if FOnlineCount = 1 then
  158. begin
  159. if FPreviousIP = FCurrentIP then
  160. begin
  161. // Del last history item...
  162. if FIPHistoryList.Count > 0 then
  163. begin
  164. FIPHistoryList.Delete(FIPHistoryList.Count-1);
  165. end;
  166. // Change the Previous IP# to the remaining last item on the list
  167. // OR to blank if none on list.
  168. if FIPHistoryList.Count > 0 then
  169. begin
  170. FPreviousIP := FIPHistoryList[FIPHistoryList.Count-1];
  171. end
  172. else
  173. begin
  174. FPreviousIP := ''; {Do not Localize}
  175. end;
  176. end;
  177. end;
  178. FOnlineCount := 2;
  179. end;
  180. if ((WasOnline) and (not FIsOnline)) or ((not WasOnline) and (FIsOnline)) then
  181. begin
  182. if (not (csDesigning in ComponentState)) and Assigned(FOnStatusChanged) then
  183. begin
  184. FOnStatusChanged(Self);
  185. end;
  186. end;
  187. except
  188. end;
  189. end;
  190. constructor TIdIPWatch.Create(AOwner: TComponent);
  191. begin
  192. inherited;
  193. FIPHistoryList := TStringList.Create;
  194. FIsOnLine := False;
  195. FOnLineCount := 0;
  196. FWatchInterval := IP_WATCH_INTERVAL;
  197. FActive := False;
  198. FPreviousIP := ''; {Do not Localize}
  199. FLocalIPHuntBusy := False;
  200. FHistoryEnabled:= True;
  201. FHistoryFilename:= IP_WATCH_HIST_FILENAME;
  202. FMaxHistoryEntries:= IP_WATCH_HIST_MAX;
  203. end;
  204. destructor TIdIPWatch.Destroy;
  205. begin
  206. if FIsOnLine then begin
  207. AddToIPHistoryList(FCurrentIP);
  208. end;
  209. Active := False;
  210. SaveHistory;
  211. FIPHistoryList.Free;
  212. inherited;
  213. end;
  214. function TIdIPWatch.ForceCheck: Boolean;
  215. begin
  216. // Forces a check and doesn't wait for the timer to fire. {Do not Localize}
  217. // It will return true if online.
  218. CheckStatus(nil);
  219. Result := FIsOnline;
  220. end;
  221. procedure TIdIPWatch.LoadHistory;
  222. begin
  223. if not (csDesigning in ComponentState) then begin
  224. FIPHistoryList.Clear;
  225. if (FileExists(FHistoryFilename)) and (FHistoryEnabled) then
  226. begin
  227. FIPHistoryList.LoadFromFile(FHistoryFileName);
  228. if FIPHistoryList.Count > 0 then
  229. begin
  230. FPreviousIP := FIPHistoryList[FIPHistoryList.Count-1];
  231. end;
  232. end;
  233. end;
  234. end;
  235. function TIdIPWatch.LocalIP: string;
  236. begin
  237. FLocalIpHuntBusy := True;
  238. try
  239. Result := GStack.LocalAddress;
  240. finally
  241. FLocalIPHuntBusy := False;
  242. end;
  243. end;
  244. procedure TIdIPWatch.SaveHistory;
  245. begin
  246. if (not (csDesigning in ComponentState)) and FHistoryEnabled then begin
  247. FIPHistoryList.SaveToFile(FHistoryFilename);
  248. end;
  249. end;
  250. procedure TIdIPWatch.SetActive(Value: Boolean);
  251. begin
  252. if Value <> FActive then begin
  253. FActive := Value;
  254. if not (csDesigning in ComponentState) then begin
  255. if FActive then begin
  256. FThread := TIdIPWatchThread.Create;
  257. with FThread do begin
  258. FSender := Self;
  259. FTimerEvent := CheckStatus;
  260. FInterval := FWatchInterval;
  261. Start;
  262. end;
  263. end else begin
  264. FThread.TerminateAndWaitFor;
  265. FreeAndNil(FThread);
  266. end;
  267. end;
  268. end;
  269. end;
  270. procedure TIdIPWatch.SetMaxHistoryEntries(Value: Integer);
  271. begin
  272. FMaxHistoryEntries:= Value;
  273. while FIPHistoryList.Count > MaxHistoryEntries do // delete the oldest...
  274. FIPHistoryList.Delete(0);
  275. end;
  276. procedure TIdIPWatch.SetWatchInterval(Value: Cardinal);
  277. begin
  278. if Value <> FWatchInterval then begin
  279. FWatchInterval := Value;
  280. end;
  281. // might be necessary even if its the same, for example
  282. // when loading (not 100% sure though)
  283. if Assigned(FThread) then begin
  284. FThread.FInterval := FWatchInterval;
  285. end;
  286. end;
  287. { TIdIPWatchThread }
  288. procedure TIdIPWatchThread.Run;
  289. var
  290. LInterval: Integer;
  291. begin
  292. LInterval := FInterval;
  293. while LInterval > 0 do begin
  294. if LInterval > 500 then begin
  295. Sleep(500);
  296. LInterval := LInterval - 500;
  297. end else begin
  298. Sleep(LInterval);
  299. LInterval := 0;
  300. end;
  301. if Terminated then begin
  302. exit;
  303. end;
  304. Synchronize(TimerEvent);
  305. end;
  306. end;
  307. procedure TIdIPWatchThread.TimerEvent;
  308. begin
  309. FTimerEvent(FSender);
  310. end;
  311. end.