Skip to content

Commit 6fdd000

Browse files
committed
Added check_ping command and CheckNet module
1 parent 49c94e4 commit 6fdd000

File tree

6 files changed

+337
-7
lines changed

6 files changed

+337
-7
lines changed

ext/docs

include/net/icmp_header.hpp

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
//
2+
// icmp_header.hpp
3+
// ~~~~~~~~~~~~~~~
4+
//
5+
// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6+
//
7+
// Distributed under the Boost Software License, Version 1.0. (See accompanying
8+
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9+
//
10+
11+
#ifndef ICMP_HEADER_HPP
12+
#define ICMP_HEADER_HPP
13+
14+
#include <istream>
15+
#include <ostream>
16+
#include <algorithm>
17+
18+
// ICMP header for both IPv4 and IPv6.
19+
//
20+
// The wire format of an ICMP header is:
21+
//
22+
// 0 8 16 31
23+
// +---------------+---------------+------------------------------+ ---
24+
// | | | | ^
25+
// | type | code | checksum | |
26+
// | | | | |
27+
// +---------------+---------------+------------------------------+ 8 bytes
28+
// | | | |
29+
// | identifier | sequence number | |
30+
// | | | v
31+
// +-------------------------------+------------------------------+ ---
32+
33+
class icmp_header
34+
{
35+
public:
36+
enum { echo_reply = 0, destination_unreachable = 3, source_quench = 4,
37+
redirect = 5, echo_request = 8, time_exceeded = 11, parameter_problem = 12,
38+
timestamp_request = 13, timestamp_reply = 14, info_request = 15,
39+
info_reply = 16, address_request = 17, address_reply = 18 };
40+
41+
icmp_header() { std::fill(rep_, rep_ + sizeof(rep_), 0); }
42+
43+
unsigned char type() const { return rep_[0]; }
44+
unsigned char code() const { return rep_[1]; }
45+
unsigned short checksum() const { return decode(2, 3); }
46+
unsigned short identifier() const { return decode(4, 5); }
47+
unsigned short sequence_number() const { return decode(6, 7); }
48+
49+
void type(unsigned char n) { rep_[0] = n; }
50+
void code(unsigned char n) { rep_[1] = n; }
51+
void checksum(unsigned short n) { encode(2, 3, n); }
52+
void identifier(unsigned short n) { encode(4, 5, n); }
53+
void sequence_number(unsigned short n) { encode(6, 7, n); }
54+
55+
friend std::istream& operator>>(std::istream& is, icmp_header& header)
56+
{ return is.read(reinterpret_cast<char*>(header.rep_), 8); }
57+
58+
friend std::ostream& operator<<(std::ostream& os, const icmp_header& header)
59+
{ return os.write(reinterpret_cast<const char*>(header.rep_), 8); }
60+
61+
private:
62+
unsigned short decode(int a, int b) const
63+
{ return (rep_[a] << 8) + rep_[b]; }
64+
65+
void encode(int a, int b, unsigned short n)
66+
{
67+
rep_[a] = static_cast<unsigned char>(n >> 8);
68+
rep_[b] = static_cast<unsigned char>(n & 0xFF);
69+
}
70+
71+
unsigned char rep_[8];
72+
};
73+
74+
template <typename Iterator>
75+
void compute_checksum(icmp_header& header,
76+
Iterator body_begin, Iterator body_end)
77+
{
78+
unsigned int sum = (header.type() << 8) + header.code()
79+
+ header.identifier() + header.sequence_number();
80+
81+
Iterator body_iter = body_begin;
82+
while (body_iter != body_end)
83+
{
84+
sum += (static_cast<unsigned char>(*body_iter++) << 8);
85+
if (body_iter != body_end)
86+
sum += static_cast<unsigned char>(*body_iter++);
87+
}
88+
89+
sum = (sum >> 16) + (sum & 0xFFFF);
90+
sum += (sum >> 16);
91+
header.checksum(static_cast<unsigned short>(~sum));
92+
}
93+
94+
#endif // ICMP_HEADER_HPP

include/net/ipv4_header.hpp

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
//
2+
// ipv4_header.hpp
3+
// ~~~~~~~~~~~~~~~
4+
//
5+
// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6+
//
7+
// Distributed under the Boost Software License, Version 1.0. (See accompanying
8+
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9+
//
10+
11+
#ifndef IPV4_HEADER_HPP
12+
#define IPV4_HEADER_HPP
13+
14+
#include <algorithm>
15+
#include <boost/asio/ip/address_v4.hpp>
16+
17+
// Packet header for IPv4.
18+
//
19+
// The wire format of an IPv4 header is:
20+
//
21+
// 0 8 16 31
22+
// +-------+-------+---------------+------------------------------+ ---
23+
// | | | | | ^
24+
// |version|header | type of | total length in bytes | |
25+
// | (4) | length| service | | |
26+
// +-------+-------+---------------+-+-+-+------------------------+ |
27+
// | | | | | | |
28+
// | identification |0|D|M| fragment offset | |
29+
// | | |F|F| | |
30+
// +---------------+---------------+-+-+-+------------------------+ |
31+
// | | | | |
32+
// | time to live | protocol | header checksum | 20 bytes
33+
// | | | | |
34+
// +---------------+---------------+------------------------------+ |
35+
// | | |
36+
// | source IPv4 address | |
37+
// | | |
38+
// +--------------------------------------------------------------+ |
39+
// | | |
40+
// | destination IPv4 address | |
41+
// | | v
42+
// +--------------------------------------------------------------+ ---
43+
// | | ^
44+
// | | |
45+
// / options (if any) / 0 - 40
46+
// / / bytes
47+
// | | |
48+
// | | v
49+
// +--------------------------------------------------------------+ ---
50+
51+
class ipv4_header
52+
{
53+
public:
54+
ipv4_header() { std::fill(rep_, rep_ + sizeof(rep_), 0); }
55+
56+
unsigned char version() const { return (rep_[0] >> 4) & 0xF; }
57+
unsigned short header_length() const { return (rep_[0] & 0xF) * 4; }
58+
unsigned char type_of_service() const { return rep_[1]; }
59+
unsigned short total_length() const { return decode(2, 3); }
60+
unsigned short identification() const { return decode(4, 5); }
61+
bool dont_fragment() const { return (rep_[6] & 0x40) != 0; }
62+
bool more_fragments() const { return (rep_[6] & 0x20) != 0; }
63+
unsigned short fragment_offset() const { return decode(6, 7) & 0x1FFF; }
64+
unsigned int time_to_live() const { return rep_[8]; }
65+
unsigned char protocol() const { return rep_[9]; }
66+
unsigned short header_checksum() const { return decode(10, 11); }
67+
68+
boost::asio::ip::address_v4 source_address() const
69+
{
70+
boost::asio::ip::address_v4::bytes_type bytes
71+
= { { rep_[12], rep_[13], rep_[14], rep_[15] } };
72+
return boost::asio::ip::address_v4(bytes);
73+
}
74+
75+
boost::asio::ip::address_v4 destination_address() const
76+
{
77+
boost::asio::ip::address_v4::bytes_type bytes
78+
= { { rep_[16], rep_[17], rep_[18], rep_[19] } };
79+
return boost::asio::ip::address_v4(bytes);
80+
}
81+
82+
friend std::istream& operator>>(std::istream& is, ipv4_header& header)
83+
{
84+
is.read(reinterpret_cast<char*>(header.rep_), 20);
85+
if (header.version() != 4)
86+
is.setstate(std::ios::failbit);
87+
std::streamsize options_length = header.header_length() - 20;
88+
if (options_length < 0 || options_length > 40)
89+
is.setstate(std::ios::failbit);
90+
else
91+
is.read(reinterpret_cast<char*>(header.rep_) + 20, options_length);
92+
return is;
93+
}
94+
95+
private:
96+
unsigned short decode(int a, int b) const
97+
{ return (rep_[a] << 8) + rep_[b]; }
98+
99+
unsigned char rep_[60];
100+
};
101+
102+
#endif // IPV4_HEADER_HPP

include/net/pinger.hpp

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
#pragma once
2+
3+
#include <boost/asio.hpp>
4+
#include <boost/bind.hpp>
5+
#include <istream>
6+
#include <iostream>
7+
#include <ostream>
8+
9+
#include <net/icmp_header.hpp>
10+
#include <net/ipv4_header.hpp>
11+
12+
using boost::asio::ip::icmp;
13+
using boost::asio::deadline_timer;
14+
namespace posix_time = boost::posix_time;
15+
16+
struct result_container {
17+
result_container() : num_send_(0), num_replies_(0), num_timeouts_(0), length_(0), sequence_number_(0), ttl_(0), time_(0) {}
18+
19+
std::string destination_;
20+
std::string ip_;
21+
std::size_t num_send_;
22+
std::size_t num_replies_;
23+
std::size_t num_timeouts_;
24+
std::size_t length_;
25+
unsigned short sequence_number_;
26+
unsigned short ttl_;
27+
std::size_t time_;
28+
};
29+
class pinger {
30+
public:
31+
pinger(boost::asio::io_service& io_service, result_container &result, const char* destination, int timeout)
32+
: resolver_(io_service)
33+
, socket_(io_service, icmp::v4())
34+
, timer_(io_service)
35+
, sequence_number_(0)
36+
, timeout_(timeout)
37+
, result_(result)
38+
39+
{
40+
icmp::resolver::query query(icmp::v4(), destination, "");
41+
destination_ = *resolver_.resolve(query);
42+
result.destination_ = destination;
43+
result.ip_ = destination_.address().to_string();
44+
}
45+
46+
void ping() {
47+
start_send();
48+
start_receive();
49+
}
50+
51+
private:
52+
void start_send() {
53+
std::string body("Hello from NSClient++.");
54+
55+
icmp_header echo_request;
56+
echo_request.type(icmp_header::echo_request);
57+
echo_request.code(0);
58+
echo_request.identifier(get_identifier());
59+
echo_request.sequence_number(++sequence_number_);
60+
compute_checksum(echo_request, body.begin(), body.end());
61+
62+
boost::asio::streambuf request_buffer;
63+
std::ostream os(&request_buffer);
64+
os << echo_request << body;
65+
66+
result_.num_send_++;
67+
time_sent_ = posix_time::microsec_clock::universal_time();
68+
socket_.send_to(request_buffer.data(), destination_);
69+
70+
timer_.expires_at(time_sent_ + posix_time::millisec(timeout_));
71+
timer_.async_wait(boost::bind(&pinger::handle_timeout, this, boost::asio::placeholders::error));
72+
}
73+
74+
void handle_timeout(const boost::system::error_code ec) {
75+
if (ec != boost::asio::error::operation_aborted) {
76+
result_.num_timeouts_++;
77+
socket_.cancel();
78+
}
79+
}
80+
81+
void start_receive() {
82+
reply_buffer_.consume(reply_buffer_.size());
83+
socket_.async_receive(reply_buffer_.prepare(65536), boost::bind(&pinger::handle_receive, this, _2, boost::asio::placeholders::error));
84+
}
85+
86+
void handle_receive(std::size_t length, const boost::system::error_code ec) {
87+
if (ec == boost::asio::error::operation_aborted) {
88+
return;
89+
}
90+
91+
92+
reply_buffer_.commit(length);
93+
94+
std::istream is(&reply_buffer_);
95+
ipv4_header ipv4_hdr;
96+
icmp_header icmp_hdr;
97+
is >> ipv4_hdr >> icmp_hdr;
98+
99+
if (is
100+
&& icmp_hdr.type() == icmp_header::echo_reply
101+
&& icmp_hdr.identifier() == get_identifier()
102+
&& icmp_hdr.sequence_number() == sequence_number_)
103+
{
104+
timer_.cancel();
105+
result_.num_replies_++;
106+
107+
posix_time::ptime now = posix_time::microsec_clock::universal_time();
108+
result_.length_ = length - ipv4_hdr.header_length();
109+
result_.ttl_ = ipv4_hdr.time_to_live();
110+
result_.time_ = (now - time_sent_).total_milliseconds();
111+
return;
112+
}
113+
//start_receive();
114+
}
115+
116+
117+
static unsigned short get_identifier() {
118+
#if defined(BOOST_WINDOWS)
119+
return static_cast<unsigned short>(::GetCurrentProcessId());
120+
#else
121+
return static_cast<unsigned short>(::getpid());
122+
#endif
123+
}
124+
125+
icmp::resolver resolver_;
126+
icmp::endpoint destination_;
127+
icmp::socket socket_;
128+
deadline_timer timer_;
129+
unsigned short sequence_number_;
130+
posix_time::ptime time_sent_;
131+
boost::asio::streambuf reply_buffer_;
132+
result_container& result_;
133+
int timeout_;
134+
};

installers/common/re-generate.bat

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
"C:/Program Files (x86)/WiX Toolset v3.8\bin\heat.exe" dir ..\..\web -cg WEBResources -gg -out web.wxs
2-
"C:/Program Files (x86)/WiX Toolset v3.8\bin\heat.exe" dir ..\..\scripts -cg ScriptResources -gg -out scripts.wxs
3-
"C:/Program Files (x86)/WiX Toolset v3.8\bin\heat.exe" dir "D:\source\build\w32\dist\ext\docs\html" -cg HTMLHelp -gg -out html_help.wxs
1+
"C:/Program Files (x86)/WiX Toolset v3.9\bin\heat.exe" dir ..\..\web -cg WEBResources -gg -out web.wxs
2+
"C:/Program Files (x86)/WiX Toolset v3.9\bin\heat.exe" dir ..\..\scripts -cg ScriptResources -gg -out scripts.wxs
3+
"C:/Program Files (x86)/WiX Toolset v3.9\bin\heat.exe" dir "D:\source\build\x64\dev\ext\docs\html" -cg HTMLHelp -gg -out html_help.wxs

installers/installer-NSCP/CMakeLists.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,17 +42,17 @@ set(HAS_ATL "yes")
4242
if(VSTUDIO_EXPRESS)
4343
set(HAS_ATL "no")
4444
endif()
45-
set(HAS_ATL "110")
45+
set(MSVER "vc110")
4646
if(MSVC13)
47-
set(HAS_ATL "120")
47+
set(MSVER "vc120")
4848
endif()
4949
SET(WIX_CANDLE_FLAGS -dboost=true -darch=${ARCH} -arch ${ARCH}
5050
-dVersion.Major=${VERSION_SERIES} -dVersion.Minor=${VERSION_MAJOR} -dVersion.Revision=${VERSION_MINOR} -dVersion.Build=${VERSION_BUILD}
5151
"-dWebHelpSource=${NSCP_PROJECT_BINARY_DIR_NATIVE}\\ext\\docs\\html"
5252
"-dWebSource=..\\..\\web" "-dScriptSource=..\\..\\scripts"
5353
-dSource=${NSCP_PROJECT_BINARY_DIR}
5454
-dHelpers=${NSCP_PROJECT_BINARY_DIR}/installer-dlls
55-
-dBoostTag=vc120-mt-1_56
55+
-dBoostTag=${MSVER}-mt-1_56
5656
-dHasATL=${HAS_ATL}
5757
-dCRTMergeModule=${CRT_MERGE_MODULE}
5858
-dRuntime=${RUNTIME}

0 commit comments

Comments
 (0)