1 | // |
2 | // Ping.cpp |
3 | // |
4 | // This sample demonstrates the Application class. |
5 | // |
6 | // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. |
7 | // and Contributors. |
8 | // |
9 | // SPDX-License-Identifier: BSL-1.0 |
10 | // |
11 | |
12 | |
13 | #include "Poco/Util/Application.h" |
14 | #include "Poco/Util/Option.h" |
15 | #include "Poco/Util/OptionSet.h" |
16 | #include "Poco/Util/HelpFormatter.h" |
17 | #include "Poco/Util/AbstractConfiguration.h" |
18 | #include "Poco/Net/ICMPSocket.h" |
19 | #include "Poco/Net/ICMPClient.h" |
20 | #include "Poco/Net/IPAddress.h" |
21 | #include "Poco/Net/ICMPEventArgs.h" |
22 | #include "Poco/AutoPtr.h" |
23 | #include "Poco/NumberParser.h" |
24 | #include "Poco/Delegate.h" |
25 | #include <iostream> |
26 | #include <sstream> |
27 | |
28 | |
29 | using Poco::Util::Application; |
30 | using Poco::Util::Option; |
31 | using Poco::Util::OptionSet; |
32 | using Poco::Util::HelpFormatter; |
33 | using Poco::Util::AbstractConfiguration; |
34 | using Poco::Net::ICMPSocket; |
35 | using Poco::Net::ICMPClient; |
36 | using Poco::Net::IPAddress; |
37 | using Poco::Net::ICMPEventArgs; |
38 | using Poco::AutoPtr; |
39 | using Poco::NumberParser; |
40 | using Poco::Delegate; |
41 | |
42 | |
43 | class Ping: public Application |
44 | /// This sample demonstrates the Poco::Net::ICMPClient in conjunction with |
45 | /// Poco Foundation C#-like events functionality. |
46 | /// |
47 | /// Try Ping --help (on Unix platforms) or Ping /help (elsewhere) for |
48 | /// more information. |
49 | { |
50 | public: |
51 | Ping(): |
52 | _helpRequested(false), |
53 | _icmpClient(IPAddress::IPv4), |
54 | _repetitions(4), |
55 | _target("localhost" ) |
56 | { |
57 | } |
58 | |
59 | protected: |
60 | void initialize(Application& self) |
61 | { |
62 | loadConfiguration(); // load default configuration files, if present |
63 | Application::initialize(self); |
64 | |
65 | _icmpClient.pingBegin += delegate(this, &Ping::onBegin); |
66 | _icmpClient.pingReply += delegate(this, &Ping::onReply); |
67 | _icmpClient.pingError += delegate(this, &Ping::onError); |
68 | _icmpClient.pingEnd += delegate(this, &Ping::onEnd); |
69 | } |
70 | |
71 | void uninitialize() |
72 | { |
73 | _icmpClient.pingBegin -= delegate(this, &Ping::onBegin); |
74 | _icmpClient.pingReply -= delegate(this, &Ping::onReply); |
75 | _icmpClient.pingError -= delegate(this, &Ping::onError); |
76 | _icmpClient.pingEnd -= delegate(this, &Ping::onEnd); |
77 | |
78 | Application::uninitialize(); |
79 | } |
80 | |
81 | void defineOptions(OptionSet& options) |
82 | { |
83 | Application::defineOptions(options); |
84 | |
85 | options.addOption( |
86 | Option("help" , "h" , "display help information on command line arguments" ) |
87 | .required(false) |
88 | .repeatable(false)); |
89 | |
90 | options.addOption( |
91 | Option("repetitions" , "r" , "define the number of repetitions" ) |
92 | .required(false) |
93 | .repeatable(false) |
94 | .argument("repetitions" )); |
95 | |
96 | options.addOption( |
97 | Option("target" , "t" , "define the target address" ) |
98 | .required(false) |
99 | .repeatable(false) |
100 | .argument("target" )); |
101 | } |
102 | |
103 | void handleOption(const std::string& name, const std::string& value) |
104 | { |
105 | Application::handleOption(name, value); |
106 | |
107 | if (name == "help" ) |
108 | _helpRequested = true; |
109 | else if (name == "repetitions" ) |
110 | _repetitions = NumberParser::parse(value); |
111 | else if (name == "target" ) |
112 | _target = value; |
113 | } |
114 | |
115 | void displayHelp() |
116 | { |
117 | HelpFormatter helpFormatter(options()); |
118 | helpFormatter.setCommand(commandName()); |
119 | helpFormatter.setUsage("OPTIONS" ); |
120 | helpFormatter.setHeader( |
121 | "A sample application that demonstrates the functionality of the " |
122 | "Poco::Net::ICMPClient class in conjunction with Poco::Events package functionality." ); |
123 | helpFormatter.format(std::cout); |
124 | } |
125 | |
126 | |
127 | int main(const std::vector<std::string>& args) |
128 | { |
129 | if (_helpRequested) |
130 | displayHelp(); |
131 | else |
132 | _icmpClient.ping(_target, _repetitions); |
133 | |
134 | return Application::EXIT_OK; |
135 | } |
136 | |
137 | |
138 | void onBegin(const void* pSender, ICMPEventArgs& args) |
139 | { |
140 | std::ostringstream os; |
141 | os << "Pinging " << args.hostName() << " [" << args.hostAddress() << "] with " << args.dataSize() << " bytes of data:" |
142 | << std::endl << "---------------------------------------------" << std::endl; |
143 | logger().information(os.str()); |
144 | } |
145 | |
146 | void onReply(const void* pSender, ICMPEventArgs& args) |
147 | { |
148 | std::ostringstream os; |
149 | os << "Reply from " << args.hostAddress() |
150 | << " bytes=" << args.dataSize() |
151 | << " time=" << args.replyTime() << "ms" |
152 | << " TTL=" << args.ttl(); |
153 | logger().information(os.str()); |
154 | } |
155 | |
156 | void onError(const void* pSender, ICMPEventArgs& args) |
157 | { |
158 | std::ostringstream os; |
159 | os << args.error(); |
160 | logger().information(os.str()); |
161 | } |
162 | |
163 | void onEnd(const void* pSender, ICMPEventArgs& args) |
164 | { |
165 | std::ostringstream os; |
166 | os << std::endl << "--- Ping statistics for " << args.hostName() << " ---" |
167 | << std::endl << "Packets: Sent=" << args.sent() << ", Received=" << args.received() |
168 | << " Lost=" << args.repetitions() - args.received() << " (" << 100.0 - args.percent() << "% loss)," |
169 | << std::endl << "Approximate round trip times in milliseconds: " << std::endl |
170 | << "Minimum=" << args.minRTT() << "ms, Maximum=" << args.maxRTT() |
171 | << "ms, Average=" << args.avgRTT() << "ms" |
172 | << std::endl << "------------------------------------------" ; |
173 | logger().information(os.str()); |
174 | } |
175 | |
176 | private: |
177 | bool _helpRequested; |
178 | ICMPClient _icmpClient; |
179 | int _repetitions; |
180 | std::string _target; |
181 | }; |
182 | |
183 | |
184 | int main(int argc, char** argv) |
185 | { |
186 | AutoPtr<Ping> pApp = new Ping; |
187 | try |
188 | { |
189 | pApp->init(argc, argv); |
190 | } |
191 | catch (Poco::Exception& exc) |
192 | { |
193 | pApp->logger().log(exc); |
194 | return Application::EXIT_CONFIG; |
195 | } |
196 | return pApp->run(); |
197 | } |
198 | |