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
24using Poco::Channel;
25using Poco::Message;
26using Poco::InvalidArgumentException;
27using Poco::NotImplementedException;
28using Poco::TimeoutException;
29using Poco::Exception;
30
31
32namespace Poco {
33namespace Net {
34
35
36ICMPClient::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
45ICMPClient::~ICMPClient()
46{
47}
48
49
50int 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
59int 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
114int 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
124int 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