diff --git a/CMakeLists.txt b/CMakeLists.txt index abb5162..59e7aeb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,10 +1,11 @@ cmake_minimum_required(VERSION 2.8) project(syslog-bulk-uploader) -set(CMAKE_CXX_FLAGS "-g -Wall") +set(CMAKE_CXX_FLAGS "-g -Wall -Werror") add_definitions(-std=c++11) add_subdirectory(src) add_subdirectory(test) enable_testing() add_test(NAME SyslogBulkUploaderTests COMMAND SyslogBulkUploaderTests) add_test(NAME SyslogMessageTests COMMAND SyslogMessageTests) +add_test(NAME RFC3164FormattedSyslogMessageTests COMMAND RFC3164FormattedSyslogMessageTests) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0e0eb5f..f5ca5ab 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -8,6 +8,8 @@ add_library(slbu-lib Facility.cpp Severity.cpp SyslogMessage.cpp + UDPWriter.cpp + RFC3164FormattedSyslogMessage ) add_executable(syslog-bulk-uploader main.cpp) diff --git a/src/Facility.h b/src/Facility.h index f0e73cb..f2f8d4f 100644 --- a/src/Facility.h +++ b/src/Facility.h @@ -42,6 +42,9 @@ public: Facility(const Facility & orig) : _value(orig._value) { }; + virtual ~Facility() { + }; + bool operator!=(const Facility & right) const { bool result = !(*this == right); // Reuse equals operator return result; @@ -56,8 +59,10 @@ public: return os; } - virtual ~Facility() { - }; + uint8_t as_int() const { + return _value; + } + private: const std::map _values{ diff --git a/src/RFC3164FormattedSyslogMessage.cpp b/src/RFC3164FormattedSyslogMessage.cpp new file mode 100644 index 0000000..a9e6b11 --- /dev/null +++ b/src/RFC3164FormattedSyslogMessage.cpp @@ -0,0 +1,44 @@ +/* + The MIT License (MIT) + +Copyright (c) 2015 Marko Živanović + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ + +#include +#include "RFC3164FormattedSyslogMessage.h" + +using namespace boost::posix_time; +using namespace std; + +static time_facet* f = new time_facet("%b %e %H:%M:%S"); +static stringstream ss; + +std::string RFC3164FormattedSyslogMessage::operator()() { + ss.str(""); + ss.imbue(locale(locale::classic(), f)); + + ss << "<" << to_string(_message.priority()) << ">"; + ss << _message.timestamp() << " "; + ss << _message.source() << " "; + ss << _message.message(); + + return ss.str(); +} diff --git a/src/RFC3164FormattedSyslogMessage.h b/src/RFC3164FormattedSyslogMessage.h new file mode 100644 index 0000000..562fd4a --- /dev/null +++ b/src/RFC3164FormattedSyslogMessage.h @@ -0,0 +1,49 @@ +/* + The MIT License (MIT) + +Copyright (c) 2015 Marko Živanović + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ + +#ifndef RFC3164FORMATTEDSYSLOGMESSAGE_H +#define RFC3164FORMATTEDSYSLOGMESSAGE_H + +#include "SyslogMessage.h" + +class RFC3164FormattedSyslogMessage { +public: + + RFC3164FormattedSyslogMessage(const SyslogMessage& msg) : _message(msg) { + }; + + RFC3164FormattedSyslogMessage(const RFC3164FormattedSyslogMessage& orig) : _message(orig._message) { + }; + + virtual ~RFC3164FormattedSyslogMessage() { + }; + + std::string operator()(); + +private: + const SyslogMessage& _message; +}; + +#endif /* RFC3164FORMATTEDSYSLOGMESSAGE_H */ + diff --git a/src/Severity.h b/src/Severity.h index 1851dad..cdca9dc 100644 --- a/src/Severity.h +++ b/src/Severity.h @@ -40,6 +40,9 @@ public: Severity(const Severity& orig) : _value(orig._value) { }; + virtual ~Severity() { + }; + bool operator!=(const Severity& right) const { bool result = !(*this == right); // Reuse equals operator return result; @@ -49,14 +52,15 @@ public: return _value == right._value; } - virtual ~Severity() { - }; - friend std::ostream& operator<<(std::ostream& os, const Severity& obj) { os << obj._value; return os; } + uint8_t as_int() const { + return _value; + } + private: const std::map _values{ diff --git a/src/SyslogMessage.cpp b/src/SyslogMessage.cpp index 1a1d9e1..396f283 100644 --- a/src/SyslogMessage.cpp +++ b/src/SyslogMessage.cpp @@ -87,3 +87,4 @@ const std::string SyslogMessage::readMessage(std::istream & src) { } return ret; }; + diff --git a/src/SyslogMessage.h b/src/SyslogMessage.h index e27213a..9f08779 100644 --- a/src/SyslogMessage.h +++ b/src/SyslogMessage.h @@ -64,6 +64,10 @@ public: return _timestamp; } + const uint8_t priority() const { + return (_facility.as_int() * 8) +_severity.as_int(); + }; + friend std::ostream& operator<<(std::ostream& os, const SyslogMessage& obj) { os << "SyslogMessage{timestamp:" << obj._timestamp << ", facility:" << obj._facility << ", severity:" << obj._severity << ",source:" << obj._source << ",message:" << obj._message << "}"; diff --git a/src/UDPWriter.cpp b/src/UDPWriter.cpp new file mode 100644 index 0000000..3d6aa9c --- /dev/null +++ b/src/UDPWriter.cpp @@ -0,0 +1,49 @@ +/* + The MIT License (MIT) + +Copyright (c) 2015 Marko Živanović + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ + +#include +#include "UDPWriter.h" +#include "RFC3164FormattedSyslogMessage.h" + +using namespace boost::asio::ip; + +UDPWriter::UDPWriter(const std::string& destination, const int port) : _destination(destination), _port(port) { + udp::resolver resolver(_ios); + udp::resolver::query query(_destination, std::to_string(_port)); + udp::resolver::iterator it = resolver.resolve(query); + if (it != udp::resolver::iterator()) { + auto endpoint = *it; + _socket.connect(endpoint); + } else { + throw "Destination not found: " + destination; + } +}; + +void UDPWriter::sendMessage(std::shared_ptr message) { + if (_socket.is_open()) { + auto formatted = RFC3164FormattedSyslogMessage{*message}; + auto buff = ::boost::asio::buffer(formatted()); + _socket.send(buff); + } +} diff --git a/src/UDPWriter.h b/src/UDPWriter.h new file mode 100644 index 0000000..869a5c7 --- /dev/null +++ b/src/UDPWriter.h @@ -0,0 +1,47 @@ +/* + The MIT License (MIT) + +Copyright (c) 2015 Marko Živanović + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ + +#ifndef UDPWRITER_H +#define UDPWRITER_H + +#include +#include +#include "Writer.h" + +class UDPWriter : public Writer { +public: + + UDPWriter(const std::string&, const int); + + virtual void sendMessage(std::shared_ptr); + +private: + const std::string& _destination; + const int _port; + boost::asio::io_service _ios; + boost::asio::ip::udp::socket _socket{_ios}; +}; + +#endif /* UDPWRITER_H */ + diff --git a/src/Writer.h b/src/Writer.h index 5c4187e..40000ce 100644 --- a/src/Writer.h +++ b/src/Writer.h @@ -26,6 +26,7 @@ SOFTWARE. #ifndef WRITER_H #define WRITER_H +#include #include "SyslogMessage.h" class Writer : private boost::noncopyable { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index a3a394b..cb4be34 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -19,3 +19,10 @@ target_link_libraries(SyslogMessageTests ${Boost_DATE_TIME_LIBRARY} ) +add_executable(RFC3164FormattedSyslogMessageTests RFC3164FormattedSyslogMessageTests.cpp) +target_link_libraries(RFC3164FormattedSyslogMessageTests + slbu-lib + ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} + ${Boost_DATE_TIME_LIBRARY} +) + diff --git a/test/RFC3164FormattedSyslogMessageTests.cpp b/test/RFC3164FormattedSyslogMessageTests.cpp new file mode 100644 index 0000000..8d2677b --- /dev/null +++ b/test/RFC3164FormattedSyslogMessageTests.cpp @@ -0,0 +1,38 @@ +/* + The MIT License (MIT) + +Copyright (c) 2015 Marko Živanović + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ + +#define BOOST_TEST_MODULE RFC3164FormattedSyslogMessageTests +#include +#include "../src/SyslogMessage.h" +#include "../src/RFC3164FormattedSyslogMessage.h" + +using namespace std; + +BOOST_AUTO_TEST_CASE(format) { + stringstream ss("2015-09-02 13:33:11 Local4.Critical 192.168.0.1 test message"); + SyslogMessage m(ss); + RFC3164FormattedSyslogMessage f(m); + string s = f(); + BOOST_CHECK_EQUAL(s, "<162>Sep 2 13:33:11 192.168.0.1 test message"); +} \ No newline at end of file