-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathPingWorker.pas
More file actions
186 lines (153 loc) · 4.29 KB
/
Copy pathPingWorker.pas
File metadata and controls
186 lines (153 loc) · 4.29 KB
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
unit PingWorker;
interface
uses
windows,
iphlpapi,
IpExport,
Winapi.WinSock,
classes, sysUtils,
IdBaseComponent, IdComponent, IdRawBase, IdRawClient, IdIcmpClient;
type
T4Bytes = packed record
s_b1, s_b2, s_b3, s_b4: byte;
end;
T2Words = packed record
s_w1, s_w2: word;
end;
TIPAddress = record
case integer of
0:
(asBytes: T4Bytes);
1:
(asWords: T2Words);
2:
(asDWord: longword);
end;
tPingResult = record
Ip: TIPAddress;
NumResponses: dword;
ReceivedFrom: string;
status: dword;
RoundTripTime: dword; // in milliseconds
end;
TPingWorker = class
private
fTimeOut: dword;
public
constructor Create;
destructor destroy; override;
// requires admin rights, so it is not the best option
function PingWithIndy: boolean;
function ping(const IpAddress: TIPAddress; out PingResult: tPingResult): boolean; overload;
function ping(const aHost: Ansistring; out PingResult: tPingResult): boolean; overload;
function ping(const Ip: dword; out PingResult: tPingResult): boolean; overload;
function ping(const aHost: Ansistring): boolean; overload;
function ping(const Ip: TIPAddress): boolean; overload;
function ping(const Ip: dword): boolean; overload;
property TimeOut: dword read fTimeOut write fTimeOut;
end;
function IcmpCreateFile: THandle; stdcall; external 'icmp.dll';
function IcmpCloseHandle(icmpHandle: THandle): boolean; stdcall; external 'icmp.dll'
function IcmpSendEcho
(icmpHandle: THandle;
DestinationAddress: TIPAddress;
RequestData: Pointer; RequestSize: Smallint;
RequestOptions: Pointer;
ReplyBuffer: Pointer;
ReplySize: dword;
TimeOut: dword): dword; stdcall; external 'icmp.dll';
implementation
{ TPingWorker }
function TPingWorker.PingWithIndy: boolean;
var
IdIcmpClient1: TIdIcmpClient;
begin
result := false;
IdIcmpClient1 := TIdIcmpClient.Create(nil);
try
IdIcmpClient1.Host := '8.8.8.8';
IdIcmpClient1.ping();
result := IdIcmpClient1.ReplyStatus.ReplyStatusType = rsEcho;
finally
IdIcmpClient1.free;
end;
end;
constructor TPingWorker.Create;
begin
inherited;
fTimeOut := 1000;
end;
destructor TPingWorker.destroy;
begin
inherited;
end;
function TPingWorker.ping(const Ip: dword; out PingResult: tPingResult): boolean;
var
IpAddress: TIPAddress;
begin
IpAddress.asDWord := Ip;
result := ping(IpAddress, PingResult);
end;
function TPingWorker.ping(const aHost: Ansistring): boolean;
var
PingResult: tPingResult;
begin
result := ping(aHost, PingResult);
end;
function TPingWorker.ping(const aHost: Ansistring; out PingResult: tPingResult): boolean;
var
IpAddress: TIPAddress;
begin
IpAddress.asDWord := inet_addr(pAnsiChar(aHost));
result := ping(IpAddress, PingResult);
end;
function TPingWorker.ping(const IpAddress: TIPAddress; out PingResult: tPingResult): boolean;
// Something like this crude translation from:
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa366050(v=vs.85).aspx
// Should do the trick.
var
ICMPFile: THandle;
SendData: array [0 .. 31] of AnsiChar;
ReplyBuffer: PICMP_ECHO_REPLY;
ReplySize: dword;
begin
result := false;
PingResult := default (tPingResult);
PingResult.Ip := IpAddress;
SendData := 'Data Buffer';
ICMPFile := IcmpCreateFile;
if ICMPFile <> INVALID_HANDLE_VALUE then
try
ReplySize := SizeOf(ICMP_ECHO_REPLY) + SizeOf(SendData);
GetMem(ReplyBuffer, ReplySize);
try
PingResult.NumResponses := IcmpSendEcho(ICMPFile, IpAddress, @SendData, SizeOf(SendData),
nil, ReplyBuffer, ReplySize, fTimeOut);
if (PingResult.NumResponses <> 0) then
begin
result := true;
PingResult.ReceivedFrom := inet_ntoa(in_addr(ReplyBuffer.Address));
// PAnsiChar(ReplyBuffer.Data)
PingResult.status := ReplyBuffer.status;
PingResult.RoundTripTime := ReplyBuffer.RoundTripTime;
end;
finally
FreeMem(ReplyBuffer);
end;
finally
IcmpCloseHandle(ICMPFile);
end;
end;
function TPingWorker.ping(const Ip: TIPAddress): boolean;
var
PingResult: tPingResult;
begin
result := ping(Ip, PingResult);
end;
function TPingWorker.ping(const Ip: dword): boolean;
var
PingResult: tPingResult;
begin
result := ping(Ip, PingResult);
end;
end.