From ced28dc7f5a454707095326b230d6ca0915e5edc Mon Sep 17 00:00:00 2001 From: Guilherme Maciel Ferreira Date: Wed, 16 Feb 2011 15:03:14 +0100 Subject: [PATCH] Working version with better class distribution --- .gitignore | 3 + CMakeLists.txt | 6 +- src/CMakeLists.txt | 38 ++++++--- src/config/configuration.cpp | 9 ++ src/config/configuration.h | 27 ++++++ src/config/configurationcommandline.cpp | 14 +++ src/config/configurationcommandline.h | 16 ++++ src/config/configurationfile.cpp | 14 +++ src/config/configurationfile.h | 15 +++ src/config/configurationreader.cpp | 31 +++++++ src/config/configurationreader.h | 19 ++++ src/icmp_header.cpp | 77 ----------------- src/icmp_header.hpp | 91 -------------------- src/ipv4_header.cpp | 99 --------------------- src/ipv4_header.hpp | 68 --------------- src/main.cpp | 26 ++++-- src/ping/boostpinger.cpp | 143 +++++++++++++++++++++++++++++++ src/ping/boostpinger.h | 46 ++++++++++ src/ping/host.cpp | 58 +++++++++++++ src/ping/host.h | 39 +++++++++ src/ping/icmp_header.cpp | 77 +++++++++++++++++ src/ping/icmp_header.h | 91 ++++++++++++++++++++ src/ping/ipv4_header.cpp | 99 +++++++++++++++++++++ src/ping/ipv4_header.h | 68 +++++++++++++++ src/ping/pingcheck.cpp | 44 ++++++++++ src/ping/pingcheck.h | 24 +++++ src/ping/pinger.cpp | 9 ++ src/ping/pinger.h | 18 ++++ src/ping/pingmanager.cpp | 14 +++ src/ping/pingmanager.h | 22 +++++ src/pinger.cpp | 133 ---------------------------- src/pinger.hpp | 41 --------- uml/libpingcheck.vpp | Bin 134301 -> 136962 bytes 33 files changed, 946 insertions(+), 533 deletions(-) create mode 100644 src/config/configuration.cpp create mode 100644 src/config/configuration.h create mode 100644 src/config/configurationcommandline.cpp create mode 100644 src/config/configurationcommandline.h create mode 100644 src/config/configurationfile.cpp create mode 100644 src/config/configurationfile.h create mode 100644 src/config/configurationreader.cpp create mode 100644 src/config/configurationreader.h delete mode 100644 src/icmp_header.cpp delete mode 100644 src/icmp_header.hpp delete mode 100644 src/ipv4_header.cpp delete mode 100644 src/ipv4_header.hpp create mode 100644 src/ping/boostpinger.cpp create mode 100644 src/ping/boostpinger.h create mode 100644 src/ping/host.cpp create mode 100644 src/ping/host.h create mode 100644 src/ping/icmp_header.cpp create mode 100644 src/ping/icmp_header.h create mode 100644 src/ping/ipv4_header.cpp create mode 100644 src/ping/ipv4_header.h create mode 100644 src/ping/pingcheck.cpp create mode 100644 src/ping/pingcheck.h create mode 100644 src/ping/pinger.cpp create mode 100644 src/ping/pinger.h create mode 100644 src/ping/pingmanager.cpp create mode 100644 src/ping/pingmanager.h delete mode 100644 src/pinger.cpp delete mode 100644 src/pinger.hpp diff --git a/.gitignore b/.gitignore index 1f2ed52..f04e513 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,6 @@ Debug .cproject .project .directory + +# uml cache files +*.vpp~* diff --git a/CMakeLists.txt b/CMakeLists.txt index e08a828..7abe55e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,11 +1,13 @@ +# project definitions +project( libpingcheck CXX ) +set( VERSION 0.0.1 ) cmake_minimum_required( VERSION 2.6 ) -project( pinger CXX ) - # set the directory where the executable will be placed set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) # set the directory where the make install places the executable #set( CMAKE_INSTALL_PREFIX ${CMAKE_CURRENT_BINARY_DIR} ) +# more build in the source folder add_subdirectory( src ) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9298f6b..534b156 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,22 +1,36 @@ -set( SOURCES - icmp_header.cpp - ipv4_header.cpp - pinger.cpp - main.cpp -) - -set( TARGET pinger ) +# binary name +set( TARGET pingcheck ) +# required boost libraries set( Boost_USE_STATIC_LIBS ON ) set( Boost_USE_MULTITHREADED ON ) set( Boost_USE_STATIC_RUNTIME OFF ) find_package( Boost 1.36.0 REQUIRED COMPONENTS filesystem ) +include_directories( config ) +include_directories( ping ) include_directories( ${Boost_INCLUDE_DIRS} ) + +set( SOURCES + config/configuration.cpp + config/configurationcommandline.cpp + config/configurationfile.cpp + config/configurationreader.cpp + ping/boostpinger.cpp + ping/host.cpp + ping/icmp_header.cpp + ping/ipv4_header.cpp + ping/pingcheck.cpp + ping/pinger.cpp + ping/pingmanager.cpp + main.cpp +) + +# creates the binary add_executable( ${TARGET} ${SOURCES} ) + +# link the program against the libraries target_link_libraries( ${TARGET} ${Boost_LIBRARIES} ) -install( - TARGETS ${TARGET} - DESTINATION . -) \ No newline at end of file +# creates the install rule for the binary +install( TARGETS ${TARGET} DESTINATION . ) diff --git a/src/config/configuration.cpp b/src/config/configuration.cpp new file mode 100644 index 0000000..ce1bab4 --- /dev/null +++ b/src/config/configuration.cpp @@ -0,0 +1,9 @@ +#include "configuration.h" + +Configuration::Configuration() +{ +} + +Configuration::~Configuration() +{ +} diff --git a/src/config/configuration.h b/src/config/configuration.h new file mode 100644 index 0000000..af72f76 --- /dev/null +++ b/src/config/configuration.h @@ -0,0 +1,27 @@ +#ifndef CONFIGURATION_H_ +#define CONFIGURATION_H_ + +#include +#include +#include + +#include "host.h" + +class Configuration +{ +public: + Configuration(); + virtual ~Configuration(); + + virtual void read() = 0; + +private: + std::string call_fail_command; + std::string logfile; + bool daemonize; + uint32_t limit_down_hosts_to_notify; + std::vector hosts; + +}; + +#endif /* CONFIGURATION_H_ */ diff --git a/src/config/configurationcommandline.cpp b/src/config/configurationcommandline.cpp new file mode 100644 index 0000000..c54f5d5 --- /dev/null +++ b/src/config/configurationcommandline.cpp @@ -0,0 +1,14 @@ +#include "configurationcommandline.h" + +ConfigurationCommandLine::ConfigurationCommandLine() +{ +} + +ConfigurationCommandLine::~ConfigurationCommandLine() +{ +} + +void ConfigurationCommandLine::read() +{ + +} diff --git a/src/config/configurationcommandline.h b/src/config/configurationcommandline.h new file mode 100644 index 0000000..09c51df --- /dev/null +++ b/src/config/configurationcommandline.h @@ -0,0 +1,16 @@ +#ifndef CONFIGURATIONCOMMANDLINE_H_ +#define CONFIGURATIONCOMMANDLINE_H_ + +#include "configuration.h" + +class ConfigurationCommandLine : public Configuration +{ +public: + ConfigurationCommandLine(); + virtual ~ConfigurationCommandLine(); + + void read(); + +}; + +#endif /* CONFIGURATIONCOMMANDLINE_H_ */ diff --git a/src/config/configurationfile.cpp b/src/config/configurationfile.cpp new file mode 100644 index 0000000..f1a5831 --- /dev/null +++ b/src/config/configurationfile.cpp @@ -0,0 +1,14 @@ +#include "configurationfile.h" + +ConfigurationFile::ConfigurationFile() +{ +} + +ConfigurationFile::~ConfigurationFile() +{ +} + +void ConfigurationFile::read() +{ + +} diff --git a/src/config/configurationfile.h b/src/config/configurationfile.h new file mode 100644 index 0000000..8225b45 --- /dev/null +++ b/src/config/configurationfile.h @@ -0,0 +1,15 @@ +#ifndef CONFIGURATIONFILE_H_ +#define CONFIGURATIONFILE_H_ + +#include "configuration.h" + +class ConfigurationFile : public Configuration +{ +public: + ConfigurationFile(); + virtual ~ConfigurationFile(); + + void read(); +}; + +#endif /* CONFIGURATIONFILE_H_ */ diff --git a/src/config/configurationreader.cpp b/src/config/configurationreader.cpp new file mode 100644 index 0000000..c213753 --- /dev/null +++ b/src/config/configurationreader.cpp @@ -0,0 +1,31 @@ +#include "configurationreader.h" + +ConfigurationReader::ConfigurationReader() +{ + // TODO how to select the source? Shall the main pass the command line? +} + +ConfigurationReader::~ConfigurationReader() +{ +} + +void ConfigurationReader::read() +{ + // if user provides parameters to command line + // parse and use the parameters + // configuration = new ConfigurationCommandLine + // if user provides a file path to command line + // read the given configuration file + // configuration = new ConfigurationFile( file from command line ) + // if user doesn't provide any file or parameters + // read the default file at the default location + // configuration = new ConfigurationFile( default file ) + // + // configuration->read(); +} + +Configuration *ConfigurationReader::getConfiguration() const +{ + return configuration; +} + diff --git a/src/config/configurationreader.h b/src/config/configurationreader.h new file mode 100644 index 0000000..11a9767 --- /dev/null +++ b/src/config/configurationreader.h @@ -0,0 +1,19 @@ +#ifndef CONFIGURATIONREADER_H_ +#define CONFIGURATIONREADER_H_ + +#include "configuration.h" + +class ConfigurationReader +{ +public: + ConfigurationReader(); + virtual ~ConfigurationReader(); + + void read(); + Configuration *getConfiguration() const; + +private: + Configuration *configuration; +}; + +#endif /* CONFIGURATIONREADER_H_ */ diff --git a/src/icmp_header.cpp b/src/icmp_header.cpp deleted file mode 100644 index 4908ba7..0000000 --- a/src/icmp_header.cpp +++ /dev/null @@ -1,77 +0,0 @@ -#include "icmp_header.hpp" - -IcmpHeader::IcmpHeader() -{ - std::fill( m_rep, m_rep + sizeof(m_rep), 0 ); -} - -unsigned char IcmpHeader::type() const -{ - return m_rep[ 0 ]; -} - -unsigned char IcmpHeader::code() const -{ - return m_rep[ 1 ]; -} - -unsigned short IcmpHeader::checksum() const -{ - return decode( 2, 3 ); -} - -unsigned short IcmpHeader::identifier() const -{ - return decode( 4, 5 ); -} - -unsigned short IcmpHeader::sequence_number() const -{ - return decode( 6, 7 ); -} - -void IcmpHeader::type( unsigned char n ) -{ - m_rep[ 0 ] = n; -} - -void IcmpHeader::code( unsigned char n ) -{ - m_rep[ 1 ] = n; -} - -void IcmpHeader::checksum( unsigned short n ) -{ - encode( 2, 3, n ); -} - -void IcmpHeader::identifier( unsigned short n ) -{ - encode( 4, 5, n ); -} - -void IcmpHeader::sequence_number( unsigned short n ) -{ - encode( 6, 7, n ); -} - -std::istream& operator>>( std::istream& is, IcmpHeader& header ) -{ - return is.read( reinterpret_cast ( header.m_rep ), 8 ); -} - -std::ostream& operator<<( std::ostream& os, const IcmpHeader& header ) -{ - return os.write( reinterpret_cast ( header.m_rep ), 8 ); -} - -unsigned short IcmpHeader::decode( int a, int b ) const -{ - return (m_rep[ a ] << 8) + m_rep[ b ]; -} - -void IcmpHeader::encode( int a, int b, unsigned short n ) -{ - m_rep[ a ] = static_cast ( n >> 8 ); - m_rep[ b ] = static_cast ( n & 0xFF ); -} diff --git a/src/icmp_header.hpp b/src/icmp_header.hpp deleted file mode 100644 index 06adc4a..0000000 --- a/src/icmp_header.hpp +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef ICMP_HEADER_HPP -#define ICMP_HEADER_HPP - -#include -#include -#include - -// ICMP header format: -// -// 0 8 16 31 -// +---------------+---------------+------------------------------+ --- -// | | | | ^ -// | type | code | checksum | | -// | | | | | -// +---------------+---------------+------------------------------+ 8 bytes -// | | | | -// | identifier | sequence number | | -// | | | v -// +-------------------------------+------------------------------+ --- - -class IcmpHeader -{ -public: - enum IcmpType - { - EchoReply = 0, - DestinationUnreachable = 3, - SourceQuench = 4, - Redirect = 5, - EchoRequest = 8, - TimeExceeded = 11, - ParameterProblem = 12, - TimestampRequest = 13, - TimestampReply = 14, - InfoRequest = 15, - InfoReply = 16, - AddressRequest = 17, - AddressReply = 18 - }; - - IcmpHeader(); - - unsigned char type() const; - unsigned char code() const; - unsigned short checksum() const; - unsigned short identifier() const; - unsigned short sequence_number() const; - - void type( const unsigned char n ); - void code( const unsigned char n ); - void checksum( const unsigned short n ); - void identifier( const unsigned short n ); - void sequence_number( const unsigned short n ); - - friend std::istream& operator>>( - std::istream& is, - IcmpHeader& header ); - friend std::ostream& operator<<( - std::ostream& os, - const IcmpHeader& header ); - -private: - unsigned short decode( int a, int b ) const; - void encode( int a, int b, unsigned short n ); - - unsigned char m_rep[ 8 ]; -}; - -template - void compute_checksum( - IcmpHeader& header, - Iterator body_begin, - Iterator body_end ) - { - unsigned int sum = (header.type() << 8) + header.code() - + header.identifier() + header.sequence_number(); - - Iterator body_iter = body_begin; - while ( body_iter != body_end ) - { - sum += (static_cast ( *body_iter++ ) << 8); - if (body_iter != body_end) - sum += static_cast ( *body_iter++ ); - } - - sum = (sum >> 16) + (sum & 0xFFFF); - sum += (sum >> 16); - header.checksum( static_cast ( ~sum ) ); - } - -#endif // ICMP_HEADER_HPP diff --git a/src/ipv4_header.cpp b/src/ipv4_header.cpp deleted file mode 100644 index c426505..0000000 --- a/src/ipv4_header.cpp +++ /dev/null @@ -1,99 +0,0 @@ -#include "ipv4_header.hpp" - -Ipv4Header::Ipv4Header() -{ - std::fill( m_rep, m_rep + sizeof(m_rep), 0 ); -} - -unsigned char Ipv4Header::version() const -{ - return (m_rep[ 0 ] >> 4) & 0xF; -} - -unsigned short Ipv4Header::header_length() const -{ - return (m_rep[ 0 ] & 0xF) * 4; -} - -unsigned char Ipv4Header::type_of_service() const -{ - return m_rep[ 1 ]; -} - -unsigned short Ipv4Header::total_length() const -{ - return decode( 2, 3 ); -} - -unsigned short Ipv4Header::identification() const -{ - return decode( 4, 5 ); -} - -bool Ipv4Header::dont_fragment() const -{ - return (m_rep[ 6 ] & 0x40) != 0; -} - -bool Ipv4Header::more_fragments() const -{ - return (m_rep[ 6 ] & 0x20) != 0; -} - -unsigned short Ipv4Header::fragment_offset() const -{ - return decode( 6, 7 ) & 0x1FFF; -} - -unsigned int Ipv4Header::time_to_live() const -{ - return m_rep[ 8 ]; -} - -unsigned char Ipv4Header::protocol() const -{ - return m_rep[ 9 ]; -} - -unsigned short Ipv4Header::header_checksum() const -{ - return decode( 10, 11 ); -} - -boost::asio::ip::address_v4 Ipv4Header::source_address() const -{ - boost::asio::ip::address_v4::bytes_type bytes = { { - m_rep[ 12 ], - m_rep[ 13 ], - m_rep[ 14 ], - m_rep[ 15 ] } }; - return boost::asio::ip::address_v4( bytes ); -} - -boost::asio::ip::address_v4 Ipv4Header::destination_address() const -{ - boost::asio::ip::address_v4::bytes_type bytes = { { - m_rep[ 16 ], - m_rep[ 17 ], - m_rep[ 18 ], - m_rep[ 19 ] } }; - return boost::asio::ip::address_v4( bytes ); -} - -std::istream& operator>>( std::istream& is, Ipv4Header& header ) -{ - is.read( reinterpret_cast ( header.m_rep ), 20 ); - if (header.version() != 4) - is.setstate( std::ios::failbit ); - std::streamsize options_length = header.header_length() - 20; - if (options_length < 0 || options_length > 40) - is.setstate( std::ios::failbit ); - else - is.read( reinterpret_cast ( header.m_rep ) + 20, options_length ); - return is; -} - -unsigned short Ipv4Header::decode( int a, int b ) const -{ - return (m_rep[ a ] << 8) + m_rep[ b ]; -} diff --git a/src/ipv4_header.hpp b/src/ipv4_header.hpp deleted file mode 100644 index dd9fc6d..0000000 --- a/src/ipv4_header.hpp +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef IPV4_HEADER_HPP -#define IPV4_HEADER_HPP - -#include -#include - -// IPv4 header format: -// -// 0 8 16 31 -// +-------+-------+---------------+------------------------------+ --- -// | | | | | ^ -// |version|header | type of | total length in bytes | | -// | (4) | length| service | | | -// +-------+-------+---------------+-+-+-+------------------------+ | -// | | | | | | | -// | identification |0|D|M| fragment offset | | -// | | |F|F| | | -// +---------------+---------------+-+-+-+------------------------+ | -// | | | | | -// | time to live | protocol | header checksum | 20 bytes -// | | | | | -// +---------------+---------------+------------------------------+ | -// | | | -// | source IPv4 address | | -// | | | -// +--------------------------------------------------------------+ | -// | | | -// | destination IPv4 address | | -// | | v -// +--------------------------------------------------------------+ --- -// | | ^ -// | | | -// / options (if any) / 0 - 40 -// / / bytes -// | | | -// | | v -// +--------------------------------------------------------------+ --- - -class Ipv4Header -{ -public: - Ipv4Header(); - - unsigned char version() const; - unsigned short header_length() const; - unsigned char type_of_service() const; - unsigned short total_length() const; - unsigned short identification() const; - - bool dont_fragment() const; - bool more_fragments() const; - unsigned short fragment_offset() const; - unsigned int time_to_live() const; - unsigned char protocol() const; - unsigned short header_checksum() const; - - boost::asio::ip::address_v4 source_address() const; - boost::asio::ip::address_v4 destination_address() const; - - friend std::istream& operator>>( std::istream& is, Ipv4Header& header ); - -private: - unsigned short decode( int a, int b ) const; - - unsigned char m_rep[ 60 ]; -}; - -#endif // IPV4_HEADER_HPP diff --git a/src/main.cpp b/src/main.cpp index a5bbcd0..2aff178 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,21 +1,27 @@ +#include +#include +#include #include +#include -#include "pinger.hpp" +#include "host.h" +#include "boostpinger.h" int main( int argc, char* argv[] ) { - try + if (argc != 2) { - if (argc != 2) - { - std::cerr << "Usage: ping " << std::endl; - std::cerr << "(You may need to run this program as root.)" - << std::endl; - return 1; - } + std::cerr << "Usage: ping " << std::endl; + std::cerr << "(You may need to run this program as root.)" << std::endl; + return 1; + } + try + { boost::asio::io_service io_service; - Pinger p( io_service, argv[ 1 ] ); + BoostPinger p( io_service ); + Host host( argv[ 1 ] ); + p.ping( host ); io_service.run(); } catch (std::exception& e) diff --git a/src/ping/boostpinger.cpp b/src/ping/boostpinger.cpp new file mode 100644 index 0000000..9119a89 --- /dev/null +++ b/src/ping/boostpinger.cpp @@ -0,0 +1,143 @@ +#include +#include +#include +#include + +#include +#include +#include + +#include "icmp_header.h" +#include "ipv4_header.h" +#include "boostpinger.h" + +//----------------------------------------------------------------------------- +// BoostPinger +//----------------------------------------------------------------------------- + +BoostPinger::BoostPinger( + boost::asio::io_service& io_service +) : + resolver( io_service ), timer( io_service ), sequence_number( 0 ), + num_replies( 0 ), socket( io_service, icmp::v4() ) +{ +#if 0 + try + { + std::string ip = "172.16.1.149"; + uint32_t port = 21; + icmp::endpoint ep( address::from_string( ip ), port ); + socket.bind( ep ); + } + catch (boost::system::system_error &e) + { + std::cerr << "exception" << std::endl; + } +#endif +} + +BoostPinger::~BoostPinger() +{ +} + +void BoostPinger::ping( const Host &host ) +{ + std::string destination = host.getIp(); + // TODO what if it is an DNS? + + icmp::resolver::query query( icmp::v4(), destination, "" ); + destination_endpoint = *resolver.resolve( query ); + + start_send(); + start_receive(); +} + +void BoostPinger::start_send() +{ + std::string body( "ping message" ); + + // Create an ICMP header for an echo request. + IcmpHeader echo_request; + echo_request.type( IcmpHeader::EchoRequest ); + echo_request.code( 0 ); + echo_request.identifier( get_identifier() ); + sequence_number++; + echo_request.sequence_number( sequence_number ); + compute_checksum( echo_request, body.begin(), body.end() ); + + // Encode the request packet. + boost::asio::streambuf request_buffer; + std::ostream os( &request_buffer ); + os << echo_request << body; + + // Send the request. + time_sent = posix_time::microsec_clock::universal_time(); + socket.send_to( request_buffer.data(), destination_endpoint ); + + // Wait up to five seconds for a reply. + num_replies = 0; + timer.expires_at( time_sent + posix_time::seconds( 5 ) ); + timer.async_wait( boost::bind( &BoostPinger::handle_timeout, this ) ); +} + +void BoostPinger::handle_timeout() +{ + if (num_replies == 0) + std::cout << "Request timed out" << std::endl; + + // Requests must be sent no less than one second apart. + timer.expires_at( time_sent + posix_time::seconds( 1 ) ); + timer.async_wait( boost::bind( &BoostPinger::start_send, this ) ); +} + +void BoostPinger::start_receive() +{ + // Discard any data already in the buffer. + reply_buffer.consume( reply_buffer.size() ); + + // Wait for a reply. We prepare the buffer to receive up to 64KB. + socket.async_receive( + reply_buffer.prepare( 65536 ), + boost::bind( &BoostPinger::handle_receive, this, _2 ) ); +} + +void BoostPinger::handle_receive( std::size_t length ) +{ + // The actual number of bytes received is committed to the buffer so that we + // can extract it using a std::istream object. + reply_buffer.commit( length ); + + // Decode the reply packet. + std::istream is( &reply_buffer ); + Ipv4Header ipv4_hdr; + IcmpHeader icmp_hdr; + is >> ipv4_hdr >> icmp_hdr; + + // We can receive all ICMP packets received by the host, so we need to + // filter out only the echo replies that match the our identifier and + // expected sequence number. + if (is && icmp_hdr.type() == IcmpHeader::EchoReply + && icmp_hdr.identifier() == get_identifier() + && icmp_hdr.sequence_number() == sequence_number) + { + // If this is the first reply, interrupt the five second timeout. + if (num_replies++ == 0) + timer.cancel(); + + // Print out some information about the reply packet. + posix_time::ptime now = posix_time::microsec_clock::universal_time(); + std::cout << length - ipv4_hdr.header_length() << " bytes from " + << ipv4_hdr.source_address() << ": icmp_seq=" + << icmp_hdr.sequence_number() << ", ttl=" + << ipv4_hdr.time_to_live() << ", time=" + << (now - time_sent).total_milliseconds() << " ms" + << std::endl; + } + + start_receive(); +} + +uint16_t BoostPinger::get_identifier() +{ + return static_cast ( ::getpid() ); +} diff --git a/src/ping/boostpinger.h b/src/ping/boostpinger.h new file mode 100644 index 0000000..a7c9f3f --- /dev/null +++ b/src/ping/boostpinger.h @@ -0,0 +1,46 @@ +#ifndef PINGER_HPP +#define PINGER_HPP + +#include + +#include "pinger.h" + +using boost::asio::ip::address; +using boost::asio::ip::icmp; +using boost::asio::deadline_timer; + +namespace posix_time = boost::posix_time; + +//----------------------------------------------------------------------------- +// BoostPinger +//----------------------------------------------------------------------------- + +class BoostPinger : public Pinger +{ +public: + BoostPinger( boost::asio::io_service& io_service ); + virtual ~BoostPinger(); + + void ping( const Host &host ); + +private: + void start_send(); + + void handle_timeout(); + void start_receive(); + void handle_receive( std::size_t length ); + + static uint16_t get_identifier(); + + icmp::resolver resolver; + icmp::endpoint destination_endpoint; + icmp::socket socket; + deadline_timer timer; + uint16_t sequence_number; + posix_time::ptime time_sent; + boost::asio::streambuf reply_buffer; + std::size_t num_replies; + +}; + +#endif /* PINGER_HPP */ diff --git a/src/ping/host.cpp b/src/ping/host.cpp new file mode 100644 index 0000000..4ee1c19 --- /dev/null +++ b/src/ping/host.cpp @@ -0,0 +1,58 @@ +#include "host.h" + +Host::Host( std::string address ) +{ +} + +Host::~Host() +{ +} + +std::string Host::getDns() const +{ + return dns; +} + +void Host::setDns( std::string dns ) +{ + this->dns = dns; +} + +uint32_t Host::getInterval() const +{ + return interval; +} + +void Host::setInterval( uint32_t interval ) +{ + this->interval = interval; +} + +std::string Host::getIp() const +{ + return ip; +} + +void Host::setIp( std::string ip ) +{ + this->ip = ip; +} +std::vector Host::getOptions() const +{ + return options; +} + +void Host::setOptions( std::vector options ) +{ + this->options = options; +} + +uint16_t Host::getPort() const +{ + return port; +} + +void Host::setPort( uint16_t port ) +{ + this->port = port; +} diff --git a/src/ping/host.h b/src/ping/host.h new file mode 100644 index 0000000..36b8772 --- /dev/null +++ b/src/ping/host.h @@ -0,0 +1,39 @@ +#ifndef HOST_H_ +#define HOST_H_ + +#include +#include + +#include + +class Host +{ +public: + Host( std::string address ); + virtual ~Host(); + + std::string getDns() const; + void setDns( std::string dns ); + + uint32_t getInterval() const; + void setInterval( uint32_t interval ); + + std::string getIp() const; + void setIp( std::string ip ); + + std::vector getOptions() const; + void setOptions( std::vector options ); + + uint16_t getPort() const; + void setPort( uint16_t port ); + +private: + std::string ip; + std::string dns; + uint16_t port; + uint32_t interval; + std::vector options; + +}; + +#endif /* HOST_H_ */ diff --git a/src/ping/icmp_header.cpp b/src/ping/icmp_header.cpp new file mode 100644 index 0000000..c3b4e91 --- /dev/null +++ b/src/ping/icmp_header.cpp @@ -0,0 +1,77 @@ +#include "icmp_header.h" + +IcmpHeader::IcmpHeader() +{ + std::fill( rep, rep + sizeof(rep), 0 ); +} + +unsigned char IcmpHeader::type() const +{ + return rep[ 0 ]; +} + +unsigned char IcmpHeader::code() const +{ + return rep[ 1 ]; +} + +unsigned short IcmpHeader::checksum() const +{ + return decode( 2, 3 ); +} + +unsigned short IcmpHeader::identifier() const +{ + return decode( 4, 5 ); +} + +unsigned short IcmpHeader::sequence_number() const +{ + return decode( 6, 7 ); +} + +void IcmpHeader::type( unsigned char n ) +{ + rep[ 0 ] = n; +} + +void IcmpHeader::code( unsigned char n ) +{ + rep[ 1 ] = n; +} + +void IcmpHeader::checksum( unsigned short n ) +{ + encode( 2, 3, n ); +} + +void IcmpHeader::identifier( unsigned short n ) +{ + encode( 4, 5, n ); +} + +void IcmpHeader::sequence_number( unsigned short n ) +{ + encode( 6, 7, n ); +} + +std::istream& operator>>( std::istream& is, IcmpHeader& header ) +{ + return is.read( reinterpret_cast ( header.rep ), 8 ); +} + +std::ostream& operator<<( std::ostream& os, const IcmpHeader& header ) +{ + return os.write( reinterpret_cast ( header.rep ), 8 ); +} + +unsigned short IcmpHeader::decode( int a, int b ) const +{ + return (rep[ a ] << 8) + rep[ b ]; +} + +void IcmpHeader::encode( int a, int b, unsigned short n ) +{ + rep[ a ] = static_cast ( n >> 8 ); + rep[ b ] = static_cast ( n & 0xFF ); +} diff --git a/src/ping/icmp_header.h b/src/ping/icmp_header.h new file mode 100644 index 0000000..6b459f4 --- /dev/null +++ b/src/ping/icmp_header.h @@ -0,0 +1,91 @@ +#ifndef ICMP_HEADER_HPP +#define ICMP_HEADER_HPP + +#include +#include +#include + +// ICMP header format: +// +// 0 8 16 31 +// +---------------+---------------+------------------------------+ --- +// | | | | ^ +// | type | code | checksum | | +// | | | | | +// +---------------+---------------+------------------------------+ 8 bytes +// | | | | +// | identifier | sequence number | | +// | | | v +// +-------------------------------+------------------------------+ --- + +class IcmpHeader +{ +public: + enum IcmpType + { + EchoReply = 0, + DestinationUnreachable = 3, + SourceQuench = 4, + Redirect = 5, + EchoRequest = 8, + TimeExceeded = 11, + ParameterProblem = 12, + TimestampRequest = 13, + TimestampReply = 14, + InfoRequest = 15, + InfoReply = 16, + AddressRequest = 17, + AddressReply = 18 + }; + + IcmpHeader(); + + unsigned char type() const; + unsigned char code() const; + unsigned short checksum() const; + unsigned short identifier() const; + unsigned short sequence_number() const; + + void type( const unsigned char n ); + void code( const unsigned char n ); + void checksum( const unsigned short n ); + void identifier( const unsigned short n ); + void sequence_number( const unsigned short n ); + + friend std::istream& operator>>( + std::istream& is, + IcmpHeader& header ); + friend std::ostream& operator<<( + std::ostream& os, + const IcmpHeader& header ); + +private: + unsigned short decode( int a, int b ) const; + void encode( int a, int b, unsigned short n ); + + unsigned char rep[ 8 ]; +}; + +template + void compute_checksum( + IcmpHeader& header, + Iterator body_begin, + Iterator body_end ) + { + unsigned int sum = (header.type() << 8) + header.code() + + header.identifier() + header.sequence_number(); + + Iterator body_iter = body_begin; + while ( body_iter != body_end ) + { + sum += (static_cast ( *body_iter++ ) << 8); + if (body_iter != body_end) + sum += static_cast ( *body_iter++ ); + } + + sum = (sum >> 16) + (sum & 0xFFFF); + sum += (sum >> 16); + header.checksum( static_cast ( ~sum ) ); + } + +#endif // ICMP_HEADER_HPP diff --git a/src/ping/ipv4_header.cpp b/src/ping/ipv4_header.cpp new file mode 100644 index 0000000..f563534 --- /dev/null +++ b/src/ping/ipv4_header.cpp @@ -0,0 +1,99 @@ +#include "ipv4_header.h" + +Ipv4Header::Ipv4Header() +{ + std::fill( rep, rep + sizeof(rep), 0 ); +} + +unsigned char Ipv4Header::version() const +{ + return (rep[ 0 ] >> 4) & 0xF; +} + +unsigned short Ipv4Header::header_length() const +{ + return (rep[ 0 ] & 0xF) * 4; +} + +unsigned char Ipv4Header::type_of_service() const +{ + return rep[ 1 ]; +} + +unsigned short Ipv4Header::total_length() const +{ + return decode( 2, 3 ); +} + +unsigned short Ipv4Header::identification() const +{ + return decode( 4, 5 ); +} + +bool Ipv4Header::dont_fragment() const +{ + return (rep[ 6 ] & 0x40) != 0; +} + +bool Ipv4Header::more_fragments() const +{ + return (rep[ 6 ] & 0x20) != 0; +} + +unsigned short Ipv4Header::fragment_offset() const +{ + return decode( 6, 7 ) & 0x1FFF; +} + +unsigned int Ipv4Header::time_to_live() const +{ + return rep[ 8 ]; +} + +unsigned char Ipv4Header::protocol() const +{ + return rep[ 9 ]; +} + +unsigned short Ipv4Header::header_checksum() const +{ + return decode( 10, 11 ); +} + +boost::asio::ip::address_v4 Ipv4Header::source_address() const +{ + boost::asio::ip::address_v4::bytes_type bytes = { { + rep[ 12 ], + rep[ 13 ], + rep[ 14 ], + rep[ 15 ] } }; + return boost::asio::ip::address_v4( bytes ); +} + +boost::asio::ip::address_v4 Ipv4Header::destination_address() const +{ + boost::asio::ip::address_v4::bytes_type bytes = { { + rep[ 16 ], + rep[ 17 ], + rep[ 18 ], + rep[ 19 ] } }; + return boost::asio::ip::address_v4( bytes ); +} + +std::istream& operator>>( std::istream& is, Ipv4Header& header ) +{ + is.read( reinterpret_cast ( header.rep ), 20 ); + if (header.version() != 4) + is.setstate( std::ios::failbit ); + std::streamsize options_length = header.header_length() - 20; + if (options_length < 0 || options_length > 40) + is.setstate( std::ios::failbit ); + else + is.read( reinterpret_cast ( header.rep ) + 20, options_length ); + return is; +} + +unsigned short Ipv4Header::decode( int a, int b ) const +{ + return (rep[ a ] << 8) + rep[ b ]; +} diff --git a/src/ping/ipv4_header.h b/src/ping/ipv4_header.h new file mode 100644 index 0000000..3dd4806 --- /dev/null +++ b/src/ping/ipv4_header.h @@ -0,0 +1,68 @@ +#ifndef IPV4_HEADER_HPP +#define IPV4_HEADER_HPP + +#include +#include + +// IPv4 header format: +// +// 0 8 16 31 +// +-------+-------+---------------+------------------------------+ --- +// | | | | | ^ +// |version|header | type of | total length in bytes | | +// | (4) | length| service | | | +// +-------+-------+---------------+-+-+-+------------------------+ | +// | | | | | | | +// | identification |0|D|M| fragment offset | | +// | | |F|F| | | +// +---------------+---------------+-+-+-+------------------------+ | +// | | | | | +// | time to live | protocol | header checksum | 20 bytes +// | | | | | +// +---------------+---------------+------------------------------+ | +// | | | +// | source IPv4 address | | +// | | | +// +--------------------------------------------------------------+ | +// | | | +// | destination IPv4 address | | +// | | v +// +--------------------------------------------------------------+ --- +// | | ^ +// | | | +// / options (if any) / 0 - 40 +// / / bytes +// | | | +// | | v +// +--------------------------------------------------------------+ --- + +class Ipv4Header +{ +public: + Ipv4Header(); + + unsigned char version() const; + unsigned short header_length() const; + unsigned char type_of_service() const; + unsigned short total_length() const; + unsigned short identification() const; + + bool dont_fragment() const; + bool more_fragments() const; + unsigned short fragment_offset() const; + unsigned int time_to_live() const; + unsigned char protocol() const; + unsigned short header_checksum() const; + + boost::asio::ip::address_v4 source_address() const; + boost::asio::ip::address_v4 destination_address() const; + + friend std::istream& operator>>( std::istream& is, Ipv4Header& header ); + +private: + unsigned short decode( int a, int b ) const; + + unsigned char rep[ 60 ]; +}; + +#endif // IPV4_HEADER_HPP diff --git a/src/ping/pingcheck.cpp b/src/ping/pingcheck.cpp new file mode 100644 index 0000000..262b3f8 --- /dev/null +++ b/src/ping/pingcheck.cpp @@ -0,0 +1,44 @@ +#include "configurationreader.h" + +#include "pingcheck.h" + +PingCheck::PingCheck() : + configuration( NULL ) +{ + +} + +PingCheck::~PingCheck() +{ +} + +void PingCheck::read_configuration() +{ + // sends the program command line to be parsed by the configuration reader + // check if it reads correctly + + // + // + // + // + // + // + // + // + // + // + // +} + +void PingCheck::init_ping_managers() +{ + // starts N ping managers with a host and an interval, this was read in configuration + // for each host in configuration + // + // + // + // + // + // + // +} diff --git a/src/ping/pingcheck.h b/src/ping/pingcheck.h new file mode 100644 index 0000000..fafb59f --- /dev/null +++ b/src/ping/pingcheck.h @@ -0,0 +1,24 @@ +#ifndef PINGCHECK_H_ +#define PINGCHECK_H_ + +#include + +#include "configuration.h" +#include "pingmanager.h" + +class PingCheck +{ +public: + PingCheck(); + virtual ~PingCheck(); + + void read_configuration(); + void init_ping_managers(); + +private: + Configuration *configuration; + std::multimap ping_managers; + +}; + +#endif /* PINGCHECK_H_ */ diff --git a/src/ping/pinger.cpp b/src/ping/pinger.cpp new file mode 100644 index 0000000..ba01a64 --- /dev/null +++ b/src/ping/pinger.cpp @@ -0,0 +1,9 @@ +#include "pinger.h" + +Pinger::Pinger() +{ +} + +Pinger::~Pinger() +{ +} diff --git a/src/ping/pinger.h b/src/ping/pinger.h new file mode 100644 index 0000000..9cf469c --- /dev/null +++ b/src/ping/pinger.h @@ -0,0 +1,18 @@ +#ifndef PINGER_H_ +#define PINGER_H_ + +#include + +#include "host.h" + +class Pinger +{ +public: + Pinger(); + virtual ~Pinger(); + + virtual void ping( const Host &host ) = 0; + +}; + +#endif /* PINGER_H_ */ diff --git a/src/ping/pingmanager.cpp b/src/ping/pingmanager.cpp new file mode 100644 index 0000000..9ceee4e --- /dev/null +++ b/src/ping/pingmanager.cpp @@ -0,0 +1,14 @@ +#include "pingmanager.h" + +PingManager::PingManager() +{ + +} + +PingManager::~PingManager() +{ +} + +void PingManager::ping() +{ +} diff --git a/src/ping/pingmanager.h b/src/ping/pingmanager.h new file mode 100644 index 0000000..de79ce2 --- /dev/null +++ b/src/ping/pingmanager.h @@ -0,0 +1,22 @@ +#ifndef PINGMANAGER_H_ +#define PINGMANAGER_H_ + +#include "pinger.h" +#include "host.h" + +class PingManager +{ +public: + PingManager(); + virtual ~PingManager(); + + void ping(); + +private: + Pinger *pinger; + uint32_t interval; + Host *host; + +}; + +#endif /* PINGMANAGER_H_ */ diff --git a/src/pinger.cpp b/src/pinger.cpp deleted file mode 100644 index 242cbd7..0000000 --- a/src/pinger.cpp +++ /dev/null @@ -1,133 +0,0 @@ -#include -#include -#include -#include - -#include -#include -#include - -#include "icmp_header.hpp" -#include "ipv4_header.hpp" -#include "pinger.hpp" - -//----------------------------------------------------------------------------- -// Pinger -//----------------------------------------------------------------------------- - -Pinger::Pinger( boost::asio::io_service& io_service, const char* destination ) : - m_resolver( io_service ), m_timer( io_service ), m_sequence_number( 0 ), - m_num_replies( 0 ), m_socket( io_service, icmp::v4() ) -{ - try - { - std::string ip = "172.16.1.149"; - uint32_t port = 21; - icmp::endpoint ep( address::from_string( ip ), port ); - m_socket.bind( ep ); - } - catch (boost::system::system_error &e) - { - std::cerr << "exception" << std::endl; - } - - icmp::resolver::query query( icmp::v4(), destination, "" ); - m_destination = *m_resolver.resolve( query ); - - start_send(); - start_receive(); -} - -Pinger::~Pinger() -{ -} - -void Pinger::start_send() -{ - std::string body( "ping message" ); - - // Create an ICMP header for an echo request. - IcmpHeader echo_request; - echo_request.type( IcmpHeader::EchoRequest ); - echo_request.code( 0 ); - echo_request.identifier( get_identifier() ); - m_sequence_number++; - echo_request.sequence_number( m_sequence_number ); - compute_checksum( echo_request, body.begin(), body.end() ); - - // Encode the request packet. - boost::asio::streambuf request_buffer; - std::ostream os( &request_buffer ); - os << echo_request << body; - - // Send the request. - m_time_sent = posix_time::microsec_clock::universal_time(); - m_socket.send_to( request_buffer.data(), m_destination ); - - // Wait up to five seconds for a reply. - m_num_replies = 0; - m_timer.expires_at( m_time_sent + posix_time::seconds( 5 ) ); - m_timer.async_wait( boost::bind( &Pinger::handle_timeout, this ) ); -} - -void Pinger::handle_timeout() -{ - if (m_num_replies == 0) - std::cout << "Request timed out" << std::endl; - - // Requests must be sent no less than one second apart. - m_timer.expires_at( m_time_sent + posix_time::seconds( 1 ) ); - m_timer.async_wait( boost::bind( &Pinger::start_send, this ) ); -} - -void Pinger::start_receive() -{ - // Discard any data already in the buffer. - m_reply_buffer.consume( m_reply_buffer.size() ); - - // Wait for a reply. We prepare the buffer to receive up to 64KB. - m_socket.async_receive( - m_reply_buffer.prepare( 65536 ), - boost::bind( &Pinger::handle_receive, this, _2 ) ); -} - -void Pinger::handle_receive( std::size_t length ) -{ - // The actual number of bytes received is committed to the buffer so that we - // can extract it using a std::istream object. - m_reply_buffer.commit( length ); - - // Decode the reply packet. - std::istream is( &m_reply_buffer ); - Ipv4Header ipv4_hdr; - IcmpHeader icmp_hdr; - is >> ipv4_hdr >> icmp_hdr; - - // We can receive all ICMP packets received by the host, so we need to - // filter out only the echo replies that match the our identifier and - // expected sequence number. - if (is && icmp_hdr.type() == IcmpHeader::EchoReply - && icmp_hdr.identifier() == get_identifier() - && icmp_hdr.sequence_number() == m_sequence_number) - { - // If this is the first reply, interrupt the five second timeout. - if (m_num_replies++ == 0) - m_timer.cancel(); - - // Print out some information about the reply packet. - posix_time::ptime now = posix_time::microsec_clock::universal_time(); - std::cout << length - ipv4_hdr.header_length() << " bytes from " - << ipv4_hdr.source_address() << ": icmp_seq=" - << icmp_hdr.sequence_number() << ", ttl=" - << ipv4_hdr.time_to_live() << ", time=" - << (now - m_time_sent).total_milliseconds() << " ms" - << std::endl; - } - - start_receive(); -} - -uint16_t Pinger::get_identifier() -{ - return static_cast ( ::getpid() ); -} diff --git a/src/pinger.hpp b/src/pinger.hpp deleted file mode 100644 index bf1d8a4..0000000 --- a/src/pinger.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef PINGER_HPP -#define PINGER_HPP - -#include - -using boost::asio::ip::address; -using boost::asio::ip::icmp; -using boost::asio::deadline_timer; - -namespace posix_time = boost::posix_time; - -//----------------------------------------------------------------------------- -// Pinger -//----------------------------------------------------------------------------- - -class Pinger -{ -public: - Pinger( boost::asio::io_service& io_service, const char* destination ); - virtual ~Pinger(); - -private: - void start_send(); - - void handle_timeout(); - void start_receive(); - void handle_receive( std::size_t length ); - - static uint16_t get_identifier(); - - icmp::resolver m_resolver; - icmp::endpoint m_destination; - icmp::socket m_socket; - deadline_timer m_timer; - uint16_t m_sequence_number; - posix_time::ptime m_time_sent; - boost::asio::streambuf m_reply_buffer; - std::size_t m_num_replies; -}; - -#endif /* PINGER_HPP */ diff --git a/uml/libpingcheck.vpp b/uml/libpingcheck.vpp index 1cb081dc116686e66dbee1761fd16519eae8ab02..afb4256c56dc973dca622ae6563eda09fdb4e88b 100644 GIT binary patch delta 36198 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 delta 33534 zcmYhhV{}}7xIP@)wr$%RE&` z>}BVzKm2=8ux9TY(g zVH(it_T_Gmsx)tyW|Vs3X!t7iZ#h)^{zP3{C!+72ya+%~q)6Q51J3j%6>7010e1YC zKBA*59Z-`99#Le$fj_U%6q=PpIdeqif8*k0Y$MhOR#T`+vt=WspFkn@Cq~>r4)TrT+fLO*BE_VlzTxIk9E?dabj4 zah05}=q%n9$xb_UfQ-JQC3j1q#b}cM#^0fidwu2|H1BSH5m5BI<*Ydyv1s>9PJ<;l zHW(pl2oX1g=vU~LlUhfOw?$pWgWaJ5973r7rrgoc@;YC;xRl&;LD+U0x85{|P4tXf zHh%x~Ipc869zUG8BQmpcqgw7pa@=)?WgmaC4qkWrWL7~s?(}+2=AFw_&k9B!e!w!^ znkc(n9`Mzbo9wIl-i?;NMh^J4YOC3Y7h{!SFQ~E{G|Ww+`wl7?2#7ueP=G@@H5U{b zAmKkJtuZ`M_7ZGo~u_S61suqgmMGIVJr~^eH0Oj%ATe}(Am!r8RzjjuJ z!~ahrZ;*r<&GCYZOzn|*_t!~?Ke7xsfYFLxvVJfx7@hXS@95WIq6i(Wa1s zr=EI5sOKCY0`juKzt8^EjS3f7s4#QZQ=w)g1x6w+(z!TI_qkft7`uW*%zJ<3>9F;L_6_^&V%NF>2XV*y^{n|p0N{6u7-~ctj>hhD*SO+kPGHYN ze~8y*%Y`@nV_|p+e$ZmKqc$P?Ovsdv-WB4jyWt-MHCmC$Z`t@;?$4qx-w;#c3dfcK zsbDd&gr#WCL&ee9Mx}m93-i`PvHr#of`f!?fnxc%Sr#l(tc7&TJe*7_)mD4(SYBbU zsU_aByunFVq~Z8To>Z>%RLYS>Qrr!{Ow+TsJtY+0 zvMdGX05~w#k{n4+C8WGyn`Tc}6pwOhq@c1ZrgTq!7~E%?6!JEDRxQbqKG~>tJ*?-W zyS;hLc6$-8WxMy)tBk*wRD*7Q0~!fpLzwRiECYQ7Dd8rNqjE6+Z|GWaAwVNRfzli( zpMN_!ux=b0u;#MLg5n=uJ9hbNsyNnf7tee^B)eE-H7Y2TS`r7712vUA3Z-=(P|MU} zn|@!yY+(IxYV&Z4>pQPhTZ^pH)`gF70E9de{6P)e6oJ7)r+}4X3Rtw=!X4F{MjD3- z_`YPbeY|se0wvn*v7#kCeQzkuHmQn0=x$gNOQG5a2w#HKasYV_IQVu)FpCUkix0=( zaf%}|#R{Y|?8~^8(M)!A9f}oXkItJV!tWE^#*Oiy85Ym}ZnpcYO}V)+5uR);Q<;n% zJ(^cC=?Ya;FaEyN#Z)>GrTr5NKTXp!FMR|gCY?oR^YQOD&qJKYm!%0D?9h!9RjtWG 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∾h8>x(uona<|gqnn!r* zA15QPMLxGjqQw!5c9r?Ei4_bt9`jtDx)xAMuCC888J5bI_;e3N8e0W_5~eE+qMybL z4dxpx91psgD*n{m+_Hiu{m8nJmD=A|Sh^+x#YqK9>~B^soeX?^7eaffv_xJRQPQ4w z0NEHPB?nylpBjRLwFAY>;4UZ5L*i5EJ=O*Eq-jQ>ouz8&f!ZPfk}8Mk1eDu^nw1fsy=+2EDMHcg_A1Cd9yDpJt{6q7|n z12GnN(BDCB?4Y9kIwahwVXs00m=hg8p{v)-IstH12!xx3Lnv z0CRw`^xFWgp!iE%FJ_yWuEF>g-_H?OJ&rt+;#V1n#M4zIz@jz!k;%Dz)J#X$H^*f7 zr*Z|8@g9FX=M+rQl~PHQ>=@0I^e)-cH@e^axGPn0Cm5Av8}Y*^Z4CY`M#l~X60>GQ zXHKggwG2-ySYFSI;iqT2n|TIK*zFT$oH77mdNgcFM@CNu#uTXbI_kni_k&b5*QrcK zOkS?GNI0w+kJ|xR;|PR(DWq)S0nt>J6E~(q?$M__dNh|Ae&Y{irD(A`rcxz2!Hk}E z0td@(C;?>Y#*F)v(2Lx+?-Dy-%zn&2 z8{?UuTxH?`;LdpT6nRMw4pNL>`Lby4(IuiLcP<}>|=1racu%1MA zP|YA3awN6r8e}h9p#_tPfb{G#6{EBzqFWT8*r!PxiLkR&@lVF)B28A&+h?Aekzndd zoJeegxKN(GPw6mZJ8S?Z;7UMY+aX5>!kbdOanpEJa4o&!E9JlG1;i;0iQ@pC{KKVr zmgvlE5UXlRBo-kCKiW!9wmB`;*f$jtqD74m7y$4*u*_HEqC0_R*pBME|)5T9Y` zqh6H1IfXs#&N3b5%@df;V=1WMpDqlh?;yM_<@@Rt^Gqxhb2nUK?Vt%LlLwlmMXEcm ze?@*VRK3T1PH(yp!+jL_!j#X%f@GIp1=&GlT2NV144~`Cjw`U`?iOzSz!B#mnaI zgt}Wjov;YeCfjj5AjA&dIK_s{%F$I?bCE@T7Giqaes=uW*2ns;wI0Jq-+;XF8P|V? zlX=j1dZ2m`HL&J=DPc>u`6VH*t zV>U;?I=$^P|0T&7P|`}}kDd!Q7~)HJT{oCav8EL$>s8L~@ax2h5LY0utT0&L$zD^Z zOOshJBV1lv$oqS}S#xo^%-87ncYH=kZ%({xvJ0osR`l`B z`Q#{h$chV)qIY`mIlFowtwTb$*=w3qotS9SvI>kI&iZ(M-_Tro+TquM5VsYw8n;EX zK26E}pZno^l#{aPE!%wP_7%83Mo2i;o-c$u=`!+)S?kgzc4F7Z{9tUUf(J@*j7;b$ zcQ|KwPATAA0JMX~lN)rQgsXP_r+`KMcAg{U1P_XLYlB?2b>ZVg-vvsGu9TCt3XC^! z(*FB^OaV0pA(an1(&8QHTNJ}BA^1DXEs#j43V~V(YY#t~#c|VE)b@m>&asjndwW87 zPNZlc)3X#`;(muVv7cB&{Ed~H5FNpY*iNM6!mG?EU@sR(G|AvxqI^+4I=HoPh{MQn z@6^f0K1YNOqJBc{Z1Vt44ZUmpBJ$oqp{3e^b@^%v=GGrnDPA23_C<_n2;~oDCrdAh zV<|wX9vd76+n>?dQ6?XgKS4||Jy^Pcha{(`9Y1AhxzAi-HuUDud775&`h!bSRXmDe z6YDJuz-X=g;!+aOtIPb#=m2A<#Og5RVkKYp!jYAbXH>`=(wN||&M2pi#wDG44E>UI zlG!4spg0xkS5c7fLxBE7a~74RFJS{Q{GN%KM)bCx?Ro+}t4up*b>w>(yVps}_mcEJ zJo9IHQfg`sDlbS7VK5`pEa#pl!t*%oqH9PLAnvwF)T_7&PBNWoYd#qj-2?98thLs> z9#m^wk^Pw4j~Q%Nu+~=NWJPLXQx;H04VMyj7R#u5HJ|`4d$rPiLxozoD{3Kca-bC zoN^c3Lhy;MJXPnmWeOX9Qy3<-uQE!PMdi*Q(2mtpiOoVTX)^q&c?{L}z4cW@l?Ogr z5*@j-xWl4L{+iz`hndzL7`v2u!$}&^>+KO+FVP){8m| zuQz!#kts=qabb^8lp1!eT&;jF3*c8TYwhM3SHiMIju7%2N1Sa;w`L=eMt%MD&_L<9W5>`ytFuJQ6-0uFHQRue=9`aVDn+INtwAQ;g2P z(rMS!I!iZs!Ej#Dud!c>{77G_w|1!?cC8%;j+D226#Wbunei78yE>aDe+5{mt)=-i zjv(Xy+RsCK!b?~bNNcs0@5ipSACn1_?NRK&_CM9ksh(wO9NP^(VCP^&a?K$XAibYj0QA~S1F{GKACCGPdmS#8vZ4GP__M%3ZLsVC$> z)Gdv zObPkSlDkV=$^yfqaV=a;a9lbdIELr$7LwDnBf_2bFvhIW;JtDc#S7rLeEPH-OKxg& zf8ogxl6$^(Jr1ZL@ZSE?wr(aZZ-zjKR-A<~oW@tcg4g9sLpd{_j&)zz#D-8HLFh5@ z*2IUvdbosJ#IQ8|p0XFK_Bweel`;^G)+=(a^(2G0+PmeXYOd^M?|x$M_P}t6!~wIW zNsEYVwVNbr1&Se@Ck`mXTI7yd=VDR7aYU>dCMHEFiI*eqWci(=ElSRo*r-Q|ok_hl ztR9md1J?$XJybb)Y_Kd(%gR@UqwA-iA`TU9=yf;JRu+`NY7b z$2XG30&nfdsNVJY_Up*Q<%XwwEllB;F~=DO;G~qhw_B3~KUI)m4qfLA`&P^S`AC~t zgQBc&V$>V51qHXHl2%40eU?LK#mB4IkEAbQ6zj zqE*o-LwxM3<1vvhbYy&`3lY{E_W>e_G?itE~JNjk(pV`**(PgyRKX#T#_kKN(Q^P@H?QW%}IE!Nykf)eoNE zSrS}#;r&*s&c&?{xF5C}bMEU3lL^rnctqYGUr`qnBM81%DomB6zx^7=Y1N`c$*;wY0+K zOUAdRb)UXat5tr<#Kui)xF|?Iiqv5?tkIkZ%}eeh9!{hwI2TcSm z$w)e!Fm@wT)_gkDg&a+auEdjgGn zrObG?N0rx7Gd5!to98fjEW>I#LC2>8H0or{L$hRy!*4AA+D>{|!x&bb`{vSIY5ABe zPeHa6eaw*9F6-*N{qk(s_Zjbyaofz(QKx1145{{ws+w=7i?t``t%iC9zwk%NNx ziM_(Txn~)f1_2vVgcVnthjY|c6!53$Gk;w>9ZH8nC4m3`0#cxU9}?g$CC}p{!fhLT zDa?RXPD1?f%}?Ounogk?ZUN}*t3hmdX)f6HW5SM?Jcqq{z&UxQ($G$KIOK14mPN58k%1_O>>7()S36xr*Pm~f|pR*UsA7oZWyJ&nO zedo8D^3J?ATZKU)n{2Fa;(X(}PWLxO%+1B1jq&B%@zs4(t&vWXN~cOKoD|2LMkMre zqdY3?FQgsY+vE=aTGLu3`(%KNrI*kpJLGnO{3Wl(nVyQlSf@zO$M8KHwF!RRgjr4f z5Pp?hrR#xf?CooPh1M1ehkcH|PKKCycSjzt#dhb6n1`r#Sdp4;+V18LwNSBu>lj2b zYmurVx+2du-|&7k<1FegDeSv2Ql#)cuzlUyLcwAn`l`8iJGGUCL~X9)35WNk@YDPA zKRY9FOM@@VzAco4Gc4%e+i02ClrTALXv0g~u@vT}H@JN)%mCQOGH*-Cs!cn>p<_Q0ka&mdJFg|V%Rsxx>05Elt{tNhJvTqD(1+ykRDT|f zU^is*s`~Eu@!7|WBEb``Eu80zgoU)5PACj`VN|87lTa6%pFeo9@~%E?>!AyzTe;b9 zFo|~T-oLT(rmp<`-iAcim&|Kq!70jB`HJg(KJFJ{m%}CY@ zTmpNab<#?=Hz#h#oF=gU{)Tr#6012kDzGAv8J2%d4n5EK%0k)exX`yjyUypSbhCU$ z^+6c_?agGe@lR5RLa&P5d^2%N=$-rC`hQTAW?^zkk&9tfck8TZUkyP zd|n$C4G;J3a@iT@H+<(vx=eF5Mexxjd9uw!4A+$Ph#=olzuifN6DjvJr=doF(1-NNFrM3_;6*~8tGcee9v&#tFg`7Oud4`7yrKjenMp3tMx z^!+15f6a$z0ir4YOaxgIBCv9BJgSR`Kr2!gCZvU$5lceO>k4D8oC{QBv|{fcFJ+)} z5NTl^)Vy}@gltk&iIz*lPuZ}$S5Ao%3z9hq#mnC|?mN13v^-xfNx<6a0;?12*|8q~ z)SZ!?<73=YPd1*cR8Q@8EWVox>9h^9)>ZNF_F!gaR(TQQ0zbOKUn=0cA89#vlv~ur zVZyjbR_W<7{*hzTJts51}jzkAm1ln|i{u}>=p-^IHf zVesNHe#*xy>r$)EmnCUZEM(p1Mx^XKtUcH*AG+V$-cQsPNQ%9Ox%X7R;AKHhz!meC zVoDzjvW>N8YEw|*{GB5PbW>cTyeV+ zdvB0pICYpuQfz@hd;7Zelppz?jqLM?XX@%^^{4ij&KnwjUoaS7F0XKW?$YQ(uaum8 zu55YJ-{$foZ}uS)k_pVmZW$3q8Tsa0Qv}2Ir#S@QD%OY>-j$VUpKi!cP#}Mm+JDW1 zhC4f0;(_P0?wsvcoXI~O4P8XkxgJ>cSy|=DUiF=NykOL|(OaGLGgUJ#M}VQwpmQqx zx_RDK!29(Sx~#q@l|YHRJG4Kb!YHd%$?NP zYs(qOD>^*Vuc^`K#~X}b?B{L`8yz^1F*t?#c?1{0>qv4gcQq~fm zE(gBw$&z#CCGP~L5{YzlkLXO3@|3hb^y2S+a&?W1OIS|Uc3>+fQDUs0{ZN2XkZfy* zv0K-`M^>^v`@YSxsvQmDz&uu0jWF(>p%XLh`+=?j4>#l)OkB7-cQLp7pPce&d~;F# zzB+k7K@NfE$a+GSVoYn+_NKulE?K62YLrfzP1^VV``0fwznZDP$;`*4c0M_6^Grja z7JrTBVTr)F>E;*h1qEDmHu8aD<2Ji> zZ!bo`^j~GTMLkDPL5v5OxSg5pZTlp{dfqLeT?E-fbu-qS!$Kj zfzIO}gBr(gvW3)cnUkANZe{=QY%hFV9H8j&S^4v1tnc;a@({-0%-o)V9UWdy0)vS$ z^P}G$=?1~INth8G&fAg1^35!c`(r0YtJ!Zjqvo8o#33d|7W>1`na1yW51ebG8?WN635$v<${Mzj z;~HvO`}L%>M(9|fi+T8Wk7jU_Cv zG#BV;-6Yp99E!THoA2e*$Axwb4z_9(K5u#W7>n*Xb@!Bwb?OkkYOBea6 ztf)Gb#ivjV7K@jft;Qwi9VT?#zRM_m2y#0k`QqJ-LrLxRf;+EH+9rvKv>{$XUI`>o`<`l&yrd{)!5nlrA>Op)cIRF zLEKYShxl)OC#zsQ!yIq;MKkiMmj}0(X8qb)wY6hba`_fT$td=A@6h)RPbWR*pZaX4 zJf)0M-Q3Te(8Xv3oD~lddr%-0z>a0YG#l3M3fBI(c*wnN#m1Yc?Jn_ zOW&RkgnQ0$7?qB`kCN@hEGYaaZtxE6@*&JBm;OR?>-#CiV%Z~8x?8Q4&ZH~5QL0B- zrB|Fj9#?&=kd~yim*uPpD=x(PKb(IMPs}{HdgLLcztgu(p&x}r!3#+_xhl`5(Kk6~ zqcoYxEgQ{CESq|pBs5~ZQi&#ag0?UVy#eHg?^I+hYB`GTmKXTuT1#7_mkHRCC^o~7UQIh>>hu7*?#u42#V{(qiyGG zA}G30Q^Dt|vrBW7zMG;cCfDU&erK8I8mInhqP+AdL7RD%@A;QxWqyJxB7R&~gyfu5 z6R$(t--^tfx~zKIUx&}8UYitvvTuse1YY1%W=@Qgo;Q`sO%u8;6ci=8@5ukjp*|== zp?=HM(1_uwQox~GR5vs&-fT-7&fj)qHvbqRw|!yHzW#LJ_|w+L`8CXgxlq4HTiTpN zM(>F?s|l!WPQJ_?RcZ=-D)3~g`)bCkn@>B)vyV_d{C4~SPn(yCk!I0*6)~SvmnziA zT9ud&s;Wqgd#}bfXQ?V49{P4JIXO4VB8a79D6seRglMA(_LxbOfDG#Ki&Gngx7#!6 zhrCzNiRHyoR*nVI?$QNUQ!zn5Pb~{xDL%`KYVla#_CWV70LF88*&8P)lVDx4a){;O`;wL{lgXa}0#gh*$S^ znj6-Cgt?@gN>e%eQz6#aQlhZWM`EjFDa0a#!kKiwyk2&GVy3}tuYFyijJTtDo31jg`t3+l|V`eQ7dOhj{yn7+0SP2N*dp(?Z-6>3?#2iL6A z$Q3uzeW+wD8y6)@3o%JzamTf8%)2oc(>@_5ka-|#G7*MJyGgOuRum&Wx8K?!-R{*n zd_wau)^0n$Qsd%F0VnmI)`kyv13l;LV{IKirJpk~NmwuU9OJus>(&puY1brOM%SW>Gv&-l@&7+dzsRJmT&Tcsd^Ia{ReK$C)d&wx29M z+wB%+yee!|Y@{p(0=Z#q{*t>TB2u)2-cipgevaLGbAt7T&_GxBV7~rOo0zkgDC6^v zyjf`{D7+oE7X@#&)W)Bp~5N)}mCUl4xH&?%-2Qg#xJ%^D|_k*7m zthFz%H}0(mlv;70W9M|}Fkr%JSe@FA%G7zG8kamMsCI9hChc;TKuwIH>pM!L@4G`c z^>_nwZ?;{LFgtbg2-ykm3iF}-Sq$R^7rN%Ysx+a)8_^P{=DfsWBAC^dCS2#25?zR} ziQJdEmc3Xd=k>EbHPo0mZ7ECcc2wm&K1*r%!JqX^{)_aIM0QOI{rbGT%~p0180`w9 zEzJ#xk6o!4JVTJ2MXl^|tWNLLp04@{+EKHg^F!9~UDwHwn_cynoQR|;XGt;luVq_$ zDi6|T+!K8uRB@3->Li6%cxKt2qOS;XPQbZsncA@M%$i?|sn>fsPn_C2?f!8`ox@N) zNX(wnrAMvyHg}7-^~c*SH?=AhyntI5TWR@X#^Wz*eziX*q#>Wd!T)R1Qx$gJ2UGG7 z$0oO1KamigkgM6h#ZAJ-+gv^@k9nFu)W5KyGVzS<5tSZk``c4vRujEuib^Y;6rMLM z3|=S>=`Yg{dW7{~E+9`b+5a&9$VMpk%W8K`cinRP>zDn9r@d}}ic2(&*z>qLymF9N z$mDr@kCR<|ug%SqHPw zWqOI;Jz24?G!3eJBsj!yU0yN&aAFoXR$j0WtX2jt0&fo~OmU?KaeRVjHY|fzeAzS~ zzqRy{k0Qim3?dPgxNS7R;qvttV`twejxdd{_d7$Osxup-KQEBWE;Ux%pr@A=T|Z7W zx)yX|aSvlTrTp&Q{6>c`wRn%!rv*Fpum>jK+IhsRo%;p|rzAFc`$2SGAYVXHil0SJ zP*>1kf=r}1Uo-WQCTmLH(Vm7Q-w0pS)CwTsl-LDXldNxsR=K^Fla{~btG#NKPxyUk z{~R&@*vCz_%@kMWfjbf!$aw&|_f^W=Q5L(SKd-)W`yW~kDiSm|D!ND1KHNfRd*T8!j<TOZDsk(o=&|6w}6LvLA zA-c(4^MQa$3X`@m;NtlMtNUcGqIU@&zqy)md28ryCa0cwO6!a6oy@E=(fSc)zi$Dv zqwaJr*JK2QZu?n~mdP0k`?C^ymW>WnNk(dY#ua@efwEeg>u}r!I{Cs`i(g9aZKG`jlI!=fyxz zt~VTc+vZ)*?Lm6_=&z!ho#$;SrX%;sD)Pv>OFDyz(_^@0990tBFXm;)3+l_%VcOEM zMpAbV7ikwQrU%@q7+fz}wBo*eYpEosb*Cs5+*a};Y@>cIlOoLM&4Ui3uWa(S(VH02 z>f4NFH-Biq->-jgTw60r_TBK8gtp+1v2@R-DRvqH?v&-QPDb#_C$@>|HsvzRUHi0{ ztyvix*L$n@Y*$Tg`O0d4O;t~7j^Au9=-Iym5v{KoPpo`{peJrEb>B#;0_46~| z>!KM7Zw=g-l_A7L+z%pLPi{XkT`9w-_rp^n}{oUsn0NtNy;3}$#3 zHX_Ba%S$Oz2R;7&GKGpl_^wCLu*vk+W>`g-KjF5bA9{m&%MC+Eqs5wc?)c*VX#JZM zp&#O5js*>4!piD2=`@9ucFOvdTe#7+(9yHP3E1LilK(8_6C!K*QgCKp5l!gqY>TsJlD( z`kt4@M`E%?*6>3-Fhnh%c?#?`k6noTt-h#;SIwFj=pC@1(M0D z^TnfXt=w2#(EP!ZDP4y-5avyfb8KIkR)62WqRQo0J>fO5$eHrij{l{gem~o_DxW+t z&Dr=$rWq@6XXl=x!|RMo$z)uIJC#Lx4o|;!uX#9mOS=S3^^5Ie;^HL+D=#Eq-37$M zDhm>UfORQVGuImBfQM~bHIV=wmg_}kP5k|3d2;uh1 zJKuVrXgKX6SDD)#OwDd;2NG|X!en2G(&-xB#@H2z*)}?w;Um_)(K*_BDU{-Dgs5H} zbzU3;k4PhBKzi%N@dI1wOpdad56^VdG;%Y?dnAtb9yeqD@r}V*f>}>n{5z3P!r6K3 zbTVtf%O{vaY*K0SH}hk6T|VbdFh6pm8{pCmc{{jIIMM7u66W3DFc(HGO57LmgY-DZ zwyp3x^NnMJb(d0v3|<||yQst3do^s7GsP!Q)IphhU%-8#BU>P7RL&=?{0`N8Uq{*E z+81}1|3s{l`PF5q$2h7Y6MJams8YH^9mY(2JEDT!~U|StTkJjC7AUI2Pchz($<~1%JW6_;0kjP zE#0*_aD~~ew0>joK&nG0gZ^-RDVC9L7eB_Q@xJOWWMo9nArzDzCdj8t{n{nYASa_*uz zv=`I#i@!|I=s0uJ_yb&q#)PE@NquYE$BvUk{?%- zn4i}N7AQt7fVX60e>CEDgL{e zG1MhChtivT_+Gme&L1wlsL<(Jfs6k%oko5PealDhW}zROpB3hio=BwZm!mU`(_+1$ zo|pZ%{BkAQ`W0F%M38W`${<|rfbb_GBwX#{5j(X($eZp}o_=t8L%T zUhv-lBfMP4W$q_&j`j;6Ty03qZWCGKY(b`NPF8EvowDcAlA@WFIbCl*I)O{{?u#E& zZ(kYN61>w-qFJzXuK1Si@Zfrgg`QA^l9wF|`D&Qp{Y(Y|8W66wMOmO>`Ri!InH(1H z-sl@VKch_*3d~B@*svo;MJ!I%!j3RqnOOa0kmih6)cFF5%WX>&eVc@8 zUoQuj*;a2ZbbuHifnR1)CbbIY98TWBrms=+@XZg&9mswvsPpgMmg+Fc;5%GDbS9eg z_Z@nU;8!0^fdPI)_PNT1f+0@`w>9uE1X9Dq>mxy+B087E*$k2cPIjTMK90NM#&4P# ze9_QFJo9e&^DnlS?k>N#W_#Yv5P7T(8z_qntQWJ0Tv4#wa8Bnf_a1JHSRg_&;Zph(WVmIr##ZpLx zNg|3Ox6-4K@b$^KJoI4m?fd1rgRs7tk90GQ{h**?qI4p*|2u^u0XQ21+2pCEMb_ts6z!M*kn%bDw@_ZgpQ4?tgPl$=BBqW_C|lnr0&< z9I1#ao3J}V95dcyaYyj;nf+~Sc(LGPyHu9NpRQH=1+OSjJZ{{FZAZS)20R&TwdcInH_j=^_c9_ zAejO)C`!m?3Zk@&3>AKVBi_A7q8jVuo2X5BYt37N{B0q`f z?s)4T4X~EGwI3y9C6@i--T8I*#;ckm-^j#eQI$RE>F8#z%vizgFm|UT#<}37d7f#k4k#6%z$c|=zYLhp1F?NNW_h-BOqhHkb z4mnb?maq;d)2(Xt%%_OuCKC*#MsPW0a4GNAM{uyxd?z@5wO;VryQa7FJ_CE$Mg-3+>65XFhzwer)cp)c8U}UPRr>S?}J`%5q-xVMF%4;j7im z*0rNbsr<2oM;~AEH^FZ1l-k+`SZ|RBod2R3{yE3vY3*Q+M^bH|%@^)d;iZiD)QnybFZoU zIe2M)K@O+ug4dR@L?{Ed?OyJX3|SN4cG@4MLaAiPyEN{5F>rS&!~~(RaYejXX&++P zc^;zW`0vL|6T={w`GWMm_)eGU*Kq%EU1BD~J-7u7e2S ztMf>3IAWv_{Ba(l!$FB~UpIiI1|cT&c~V@d!e(OFeeicFB3$HpeEtNu+Fry1OMHju z@f4{_07W}097XFAJVh?F91Q}1_!OC~_1^;4kywiG&W2V}~!kfDYlvasD@K zGwVO7c?>AH2|^3u@HqYk*hQh_{=w^JMo414oT%W!Qiv6g{x`rW3MKLn`W=AL32`F0 zBuUh0yi^>2V_yFM9Q$(M6hKz>TLBz@;})V&qW_St<-&1dT0@I#9L~Qn{7@*ae=xmx zQE=KmB#u{UWdTrW6(2TKlN&zY1ku2Rh2UHTuKl=sK^C(B!U8t69B&@*^>qL=7sByX zw*H5&zoFVtD20D&dnSV8%gc!iZ(e^RY@tvfJjj23F5YW5HlRt4{@QnB;lfd zNExI99=wzTQvfP);t!Mt=9`8%VAXU04OfAU-$MM@ zI3glAVjQA{e;`mJRjlziA1sgoy2s57&<(K&lwA#b@(@4#DIH>j`!fJwObu(y#Sb%Q zLQL>&1WyjYT+J15FAm{%laeGO9cE$2Tq>?{LTR|?#zdM7Q~Kzstbo?LDKNq zY=ClD52qhEAsb>!LI68@*a=2qn5h8J&PD+B`Z$h%WCOA8831NQVAULm5=YM<2hg)M z#L}_wAof8EKh6OqjEn#lA3T@?N-!FOOa_=U7g9jy8e>BP_^~(Hh~OK!kQn;1382ge zx8*|8=)-5hvj{Ad2jGw?4(^u+;Ps|(aV-#`DGv~PY6dinL!yPl5cBmr2dBP(j=)|+ zz~8FmL#*gfbL7J>?2+G69c^CK~U@V=Yl z)JKc=5nyfhD0puZ`p1yN?BKXU$OLU`kCTtM2vFyBfE9`$E%Yk~9GjU4EZh+>9zpDT zX>vGn8MFgKF%V?N2{a5ZY*Y-iQg#7H;TiHA;*2+u;y+FAg$w{1E;x*W5M2B?O)kL`uK>rqmvQ;#uK{ckJTvmaFJ1#` zmF_regcn~!$I%v7aLsO51~NE2urlf*a84Oe^Dhsi+2IWY-s*{CMYkM0Kl8$AF0~w@ z<7tl8Rry~8B%nOSe-!8L4Z5}x-on@_0KZN?2tU|DEn?WN0#qU4i?@>e3P2a~!!dhM z@yGH04GDunar{HL(GQk+18Jkx1K^-HkSM(H1`uZs#3?|m68P6=2w)))c4z>7&dz`w z{_+O2hgv0oHeAPvf~f>mJ`BR~vuH#N4^#pK`L_VUE*LQ{MR*#)<_|$=9D>~M8;|Wn7W1Z z4A`U^2=gKgadKEAYa%$W8kC@V4-mX=<0KrjA%^?X0k9G&bvzsZ`Qfc<;4mE!EaC_p zT@csi_ptrHkRzZo2>zq`)(G4HAo&4!>eonF%pJJYO<6C>`57FI@poC!F| z13v;)%+&$FH~@g|DpC(rffETvpm|uF#`*w79@a+^5hOsslbSBzvYbHz?nWR^ z4}moZ2wKu(95+nO zzgrr{Ah>o<5<&#w56z%U`li71&5$12CmmPZwgoie@eEvx6tw^iUv35X)R{OX<+K8s z4k3VP002XR83L$p0f1M};E5LKC|r%?`aQ=Fb9=3Tm|+&M2w@2$T?oyH!hKB;S@2c4 z^8D30qS1%{N27GvNI%j+S7gKOZIC89E(dfKFzB`e3rubYjNCTZ-fZe$-0KWsV zICz%s=&Jk;F#tY_@|OsBQY=KKz(?RVqMjD2@5H%)md^m7iU6Q4 zWNrbD-&4cEpMkl`^#I_*E}V^d_W&+DyK!99^#Cr8eZuCKvBEUHf7*tw4`5S%#>!MN zud0F4~Rm3un~6ayEJgBopzz#zjk3=mC6VVPkt{L~JC1lJhi zN|S~GZ9gRaa}16ff@EPgfC+`c6BEGUOLr5)`NNnS=CqMd3GA~AWm3%43a^I&fx3= zD?LOAM~?ww+Os%EGdKniY3C3Lu}h}+5|;1;EWQG>#l8Jq`3mS>S%&X?g%r`Rm$4_m z3d6GqYUnRS-&m<{#IVXYkVdWIE&lE|K)YuZXUJp7^P@GK*s_yAY`1mXa|H5ybOR^$ z@Z=v?bm}{(igFWJ5f>c%9h4;A18?*S_yKGc$?V+6_x6Qla`^BMP-)Hqj$Y6Yh#ogv zkNW|!6L_K^xZnqL20DO^=YYYmO#x;0La;Fbnh*Az0#!dm!|5v!FI+qIXXsLy2ISod z@HoNK0OvFzg2M-QO+%7sN+Ns#-WiZHNCb!e1hW;RZJb*G6ZIL0ji7=Ug41RoL7dvo z-Aj}j)dqgW2>ijJnE(9ll0Ya=pDSJt9?p^hSKR;W+`*}ImH!=M2VIc;KgCceDpCmM zo&^nN4pw#$?xSWQX#x%k2!1;Y=@67sKo2+}F2qsM!bj(TINFr(#0HSSZw~145EUFs zj^>A(ki;+*yfp`%Lg!QCfuQr_2kQ}GwRd%()(kK~{nsVlpn+HCflG{~h2!VJ+Qm3A z@M*YtlFtIDE0qqX6L^XQqJj$+K-1iy$Lnu*0aU2UfY+?yPlz7pd#{)u2sVO>CjU=G z6pRQZ9W)o1;~-N0{0UUP&V-cbht(GWu|{Tm4kr~v0zX*BZ=&qxz2=mpJXH*z z-TDhyrH?qg{|nMbKa%`yohtytMGC>dFK=*?o_bKT0+b{PHh#tbu?I0}2n&U9!3?XQ zXI_)V6Ic?3h~cZNpi&JvL<7cXrX%>A`{E#nV-4gC|At&z1C?dUjP-TvcrNOnL04Rt(N za|aZlJB`&{av$w9P^T+2=u1{@a?B+6bFGaL*o)pUD8vkM#a;H_Y+h<50B! zn8Abr?641U;mrAeCsu&-koX5{-w49iyb*@EjerQO2SBKzvv_V@4}e~xO!2Mu_5e77 zs9U-!|2=Q;uNyKpgXa$*QC?&wI+{oCj(9m2@c(xe4}_zJmoh>3xnT|*0@uF9wFKYO?ClJAw;X8-(A3CLPQ|*t}{Mi ziX`k@@WpbFgp4abG42Me7g4*UnYp(ENVzd%k`6BE_j8;ceyW!Egh(Vd&-w6Q{ zka&6tPuiaZ{d-8hO9C`$cNyvZEHI%5AlXfV28$4v@g%rOL8)@EY(WaRbiM*(Nzn#q z$OBKM&-Tw>7|%gco8{?C>TT z`Utw;2k(N7$k9^h6kntRnxHTG;p^BS2P_@Eicc*10~5rJ91avf6O7mJoTX6wSqT5% zt}L+Pf8VIbufbguXk&uNKnNBM2Cokmlt7Y`*YSk2DADvh$Qb&+olD?pB>!QVI0zX4 z#Np@2Y9k93sNOahU%eR>S_Z8cf=}d9p&9TKQf6v^LvaHSK1&V6=)ZxlEgMPXV&Fk) z(0su+@ffN!K>CxR_=IF65EP~X9J1fSk4E2->`9P7j8=gbEe++tGSpyJ5={$g_q&ZB zSh{G@Z1~C7Pw+%w7LIsEZdi;C6z++{*B(L#YKNoniEboea|cgWfF2~IqwxuU`rk_B z`nxTJLNWZK6LbuOf=3vEyX~L{!cNB`MEPN`Z$t!>5CM0~#{j^^_hA(Vv?+mA90W@x zfwzDH1|XPJJYKL}2Ef}|Jieq6=l^yhDF*F4h z&+Tz0!1@FhFH{^8AX%IU*D#^aptT?1F%B~Wd2nwESA(sl6aC PsOl;T)sh6pOVs}Z){uQ# -- 1.7.1