1 | // |
2 | // ICMPClient.cpp |
3 | // |
4 | // Library: Net |
5 | // Package: ICMP |
6 | // Module: ICMPClient |
7 | // |
8 | // Copyright (c) 2006, Applied Informatics Software Engineering GmbH. |
9 | // and Contributors. |
10 | // |
11 | // SPDX-License-Identifier: BSL-1.0 |
12 | // |
13 | |
14 | |
15 | #include "Poco/Net/SocketAddress.h" |
16 | #include "Poco/Net/ICMPClient.h" |
17 | #include "Poco/Net/NetException.h" |
18 | #include "Poco/Channel.h" |
19 | #include "Poco/Message.h" |
20 | #include "Poco/Format.h" |
21 | #include <sstream> |
22 | |
23 | |
24 | using Poco::Channel; |
25 | using Poco::Message; |
26 | using Poco::InvalidArgumentException; |
27 | using Poco::NotImplementedException; |
28 | using Poco::TimeoutException; |
29 | using Poco::Exception; |
30 | |
31 | |
32 | namespace Poco { |
33 | namespace Net { |
34 | |
35 | |
36 | ICMPClient::ICMPClient(SocketAddress::Family family, int dataSize, int ttl, int timeout): |
37 | _family(family), |
38 | _dataSize(dataSize), |
39 | _ttl(ttl), |
40 | _timeout(timeout) |
41 | { |
42 | } |
43 | |
44 | |
45 | ICMPClient::~ICMPClient() |
46 | { |
47 | } |
48 | |
49 | |
50 | int ICMPClient::ping(const std::string& address, int repeat) const |
51 | { |
52 | if (repeat <= 0) return 0; |
53 | |
54 | SocketAddress addr(address, 0); |
55 | return ping(addr, repeat); |
56 | } |
57 | |
58 | |
59 | int ICMPClient::ping(const SocketAddress& address, int repeat) const |
60 | { |
61 | if (repeat <= 0) return 0; |
62 | |
63 | ICMPSocket icmpSocket(_family, _dataSize, _ttl, _timeout); |
64 | |
65 | ICMPEventArgs eventArgs(address, repeat, icmpSocket.dataSize(), icmpSocket.ttl()); |
66 | pingBegin.notify(this, eventArgs); |
67 | |
68 | for (int i = 0; i < repeat; ++i) |
69 | { |
70 | try |
71 | { |
72 | int sent = icmpSocket.sendTo(address); |
73 | if (icmpSocket.packetSize() == sent) |
74 | { |
75 | SocketAddress responseAddress(address); |
76 | ++eventArgs; |
77 | int t = icmpSocket.receiveFrom(responseAddress); |
78 | poco_assert (address.host() == responseAddress.host()); |
79 | eventArgs.setReplyTime(i, t); |
80 | pingReply.notify(this, eventArgs); |
81 | } |
82 | else |
83 | throw ICMPException(Poco::format("Error sending ICMP packet " |
84 | "(sent=%d, expected=%d)" , sent, icmpSocket.packetSize())); |
85 | } |
86 | catch (TimeoutException&) |
87 | { |
88 | std::ostringstream os; |
89 | os << address.host().toString() << ": Request timed out." ; |
90 | eventArgs.setError(i, os.str()); |
91 | pingError.notify(this, eventArgs); |
92 | continue; |
93 | } |
94 | catch (ICMPException& ex) |
95 | { |
96 | std::ostringstream os; |
97 | os << address.host().toString() << ": " << ex.displayText(); |
98 | eventArgs.setError(i, os.str()); |
99 | pingError.notify(this, eventArgs); |
100 | continue; |
101 | } |
102 | catch (Exception& ex) |
103 | { |
104 | eventArgs.setError(i, ex.displayText()); |
105 | pingError.notify(this, eventArgs); |
106 | continue; |
107 | } |
108 | } |
109 | pingEnd.notify(this, eventArgs); |
110 | return eventArgs.received(); |
111 | } |
112 | |
113 | |
114 | int ICMPClient::pingIPv4(const std::string& address, int repeat, |
115 | int dataSize, int ttl, int timeout) |
116 | { |
117 | if (repeat <= 0) return 0; |
118 | |
119 | SocketAddress a(address, 0); |
120 | return ping(a, IPAddress::IPv4, repeat, dataSize, ttl, timeout); |
121 | } |
122 | |
123 | |
124 | int ICMPClient::ping(const SocketAddress& address, |
125 | IPAddress::Family family, int repeat, |
126 | int dataSize, int ttl, int timeout) |
127 | { |
128 | if (repeat <= 0) return 0; |
129 | |
130 | ICMPSocket icmpSocket(family, dataSize, ttl, timeout); |
131 | int received = 0; |
132 | |
133 | for (int i = 0; i < repeat; ++i) |
134 | { |
135 | try |
136 | { |
137 | if (icmpSocket.sendTo(address) == icmpSocket.packetSize()) |
138 | { |
139 | SocketAddress responseAddress(address); |
140 | icmpSocket.receiveFrom(responseAddress); |
141 | poco_assert (address.host() == responseAddress.host()); |
142 | ++received; |
143 | } |
144 | } |
145 | catch (Exception&) { } |
146 | } |
147 | return received; |
148 | } |
149 | |
150 | |
151 | } } // namespace Poco::Net |
152 | |