diff --git a/src/connectionstartframe.h b/src/connectionstartframe.h index a203046..27701bf 100644 --- a/src/connectionstartframe.h +++ b/src/connectionstartframe.h @@ -5,9 +5,15 @@ * is opened. It contains the initial connection properties, and the protocol * number. * - * @copyright 2014 - 2022 Copernica BV + * @copyright 2014 - 2023 Copernica BV */ +/** + * Dependencies + */ +#include "programname.h" +#include "platformname.h" + /** * Set up namespace */ @@ -200,11 +206,11 @@ public: capabilities["consumer_cancel_notify"] = true; // fill the peer properties - if (!properties.contains("product")) properties["product"] = "Copernica AMQP library"; + if (!properties.contains("product")) properties["product"] = ProgramName(); if (!properties.contains("version")) properties["version"] = "Unknown"; - if (!properties.contains("platform")) properties["platform"] = "Unknown"; - if (!properties.contains("copyright")) properties["copyright"] = "Copyright 2015 - 2018 Copernica BV"; - if (!properties.contains("information")) properties["information"] = "https://www.copernica.com"; + if (!properties.contains("platform")) properties["platform"] = PlatformName(); + if (!properties.contains("copyright")) properties["copyright"] = "Copernica AMQP-CPP library :: Copyright 2015-2023 Copernica BV"; + if (!properties.contains("information")) properties["information"] = "https://github.com/CopernicaMarketingSoftware/AMQP-CPP"; if (!properties.contains("capabilities")) properties["capabilities"] = capabilities; // send back a connection start ok frame @@ -213,6 +219,7 @@ public: // done return true; } + }; /** diff --git a/src/platformname.h b/src/platformname.h new file mode 100644 index 0000000..af89410 --- /dev/null +++ b/src/platformname.h @@ -0,0 +1,69 @@ +/** + * PlatformName.h + * + * Class to extract the platform name (operating system, etc) + * + * @author Emiel Bruijntjes + * @copyright 2023 Copernica BV + */ + +/** + * Include guard + */ +#pragma once + +/** + * Dependencies + */ +#include + +/** + * Begin of namespace + */ +namespace AMQP { + +/** + * Class definition + */ +class PlatformName +{ +private: + /** + * The string holding all info + * @var std::string + */ + std::string _value; + +public: + /** + * Constructor + */ + PlatformName() + { + // all information + struct utsname sysinfo; + + // retrieve system info + if (uname(&sysinfo) != 0) return; + + // add all info + _value.append(sysinfo.sysname).append(" ").append(sysinfo.version).append(" ").append(sysinfo.release).append(" running on ").append(sysinfo.nodename); + } + + /** + * Destructor + */ + virtual ~PlatformName() = default; + + /** + * Cast to a const char * + * @return const char * + */ + operator const char * () const { return _value.data(); } +}; + +/** + * End of namespace + */ +} + diff --git a/src/programname.h b/src/programname.h new file mode 100644 index 0000000..3fd892d --- /dev/null +++ b/src/programname.h @@ -0,0 +1,75 @@ +/** + * ProgramName.h + * + * Helper class that detects the name of the program + * + * @author Emiel Bruijntjes + * @copyright 2023 Copernica BV + */ + +/** + * Include guard + */ +#pragma once + +/** + * Dependencies + */ +#include +#include + +/** + * Begin of namespace + */ +namespace AMQP { + +/** + * Class definition + */ +class ProgramName +{ +private: + /** + * Path of the program + * @var char[] + */ + char _path[PATH_MAX]; + + /** + * Is the _path valid? + * @var bool + */ + bool _valid; + +public: + /** + * Constructor + */ + ProgramName() : _valid(readlink("/proc/self/exe", _path, PATH_MAX) == 0) {} + + /** + * Destructor + */ + virtual ~ProgramName() = default; + + /** + * Cast to a const char * + * @return const char * + */ + operator const char * () const + { + // empty string when not valid + if (!_valid) return ""; + + // locate the last slash + auto *slash = strrchr(_path, '/'); + + // if not found return entire path, otherwise just the program name + return slash ? slash + 1 : _path; + } +}; + +/** + * End of namespace + */ +}