/src/Fast-DDS/src/cpp/utils/SystemInfo.hpp
Line | Count | Source |
1 | | // Copyright 2020 Proyectos y Sistemas de Mantenimiento SL (eProsima). |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | |
15 | | #ifndef UTILS_SYSTEMINFO_HPP_ |
16 | | #define UTILS_SYSTEMINFO_HPP_ |
17 | | |
18 | | #if defined(_WIN32) |
19 | | #include <process.h> |
20 | | #else |
21 | | #include <unistd.h> |
22 | | #endif // if defined(_WIN32) |
23 | | |
24 | | #include <cstdint> |
25 | | #include <memory> |
26 | | #include <mutex> |
27 | | #include <string> |
28 | | |
29 | | #include <fastdds/rtps/attributes/ThreadSettings.hpp> |
30 | | #include <fastdds/dds/core/ReturnCode.hpp> |
31 | | #include <fastdds/utils/IPFinder.hpp> |
32 | | #include <utils/Host.hpp> |
33 | | |
34 | | #if defined(_WIN32) || defined(__unix__) |
35 | | #include <FileWatch.hpp> |
36 | | #endif // defined(_WIN32) || defined(__unix__) |
37 | | |
38 | | namespace eprosima { |
39 | | |
40 | | using ReturnCode_t = eprosima::fastdds::dds::ReturnCode_t; |
41 | | #if defined(_WIN32) || defined(__unix__) |
42 | | using FileWatchHandle = std::unique_ptr<filewatch::FileWatch<std::string>>; |
43 | | #else |
44 | | using FileWatchHandle = void*; |
45 | | #endif // defined(_WIN32) || defined(__unix__) |
46 | | |
47 | | /** |
48 | | * This singleton serves as a centralized point from where to obtain platform dependent system information. |
49 | | */ |
50 | | class SystemInfo |
51 | | { |
52 | | public: |
53 | | |
54 | | /** |
55 | | * Get the identifier of the current process. |
56 | | * |
57 | | * @return the identifier of the current process. |
58 | | */ |
59 | | inline int process_id() const |
60 | 0 | { |
61 | | #if defined(__cplusplus_winrt) |
62 | | return (int)GetCurrentProcessId(); |
63 | | #elif defined(_WIN32) |
64 | | return (int)_getpid(); |
65 | | #else |
66 | 0 | return (int)getpid(); |
67 | 0 | #endif // platform selection |
68 | 0 | } |
69 | | |
70 | | /** |
71 | | * Get the identifier of the current host. |
72 | | * |
73 | | * @return the identifier of the current host. |
74 | | */ |
75 | | inline uint16_t host_id() const |
76 | 0 | { |
77 | 0 | return Host::instance().id(); |
78 | 0 | } |
79 | | |
80 | | /** |
81 | | * Get the identifier of the current machine. |
82 | | * |
83 | | * @return the identifier of the current host. |
84 | | */ |
85 | | inline fastcdr::string_255 machine_id() const |
86 | 0 | { |
87 | 0 | return Host::instance().machine_id(); |
88 | 0 | } |
89 | | |
90 | | /** |
91 | | * Get a reference to the singleton instance. |
92 | | * |
93 | | * @return reference to the singleton instance. |
94 | | */ |
95 | | static const SystemInfo& instance() |
96 | 0 | { |
97 | 0 | static SystemInfo singleton; |
98 | |
|
99 | 0 | return singleton; |
100 | 0 | } |
101 | | |
102 | | /** |
103 | | * Retrieve the value of a given environment variable if it exists. |
104 | | * The string which is returned in the env_value output parameter is not modified |
105 | | * if the environment variable is not set. |
106 | | * |
107 | | * This function is thread-safe as long as no other function modifies the host environment (in particular, POSIX |
108 | | * functions setenv, unsetenv and putenv would introduce a data race if called without synchronization.) |
109 | | * |
110 | | * \param [in] env_name name of the environment variable. |
111 | | * \param [out] env_value value of the environment variable. |
112 | | * @return RETCODE_OK if the environment variable is set. |
113 | | * RETCODE_NO_DATA if the environment variable is unset. |
114 | | * RETCODE_BAD_PARAMETER if the provided parameters are not valid. |
115 | | */ |
116 | | static ReturnCode_t get_env( |
117 | | const std::string& env_name, |
118 | | std::string& env_value); |
119 | | |
120 | | /** |
121 | | * Read environment variable contained in the environment file. |
122 | | * |
123 | | * @param [in] filename path/name of the environment file. |
124 | | * @param [in] env_name environment variable name to read from the file. |
125 | | * @param [out] env_value environment variable value read from the file. |
126 | | * |
127 | | * @return RETCODE_OK if succesful. |
128 | | * RETCODE_BAD_PARAMETER if the file does not exist. |
129 | | * RETCODE_NO_DATA if the file exists but there is no information about the environment variable. |
130 | | * RETCODE_ERROR if the file is empty or malformed. |
131 | | */ |
132 | | static ReturnCode_t get_env( |
133 | | const std::string& filename, |
134 | | const std::string& env_name, |
135 | | std::string& env_value); |
136 | | |
137 | | /** |
138 | | * Get the effective username of the person that launched the application |
139 | | * This implementation follows the whoami implementation for POSIX |
140 | | * (https://github.com/coreutils/coreutils/blob/master/src/whoami.c) |
141 | | * |
142 | | * geteuid is always successful. |
143 | | * |
144 | | * getpwuid returns a pointer to a struct passwd if a matching entry is found and nullptr otherwise. |
145 | | * This pointer is only valid until the next time getpwuid function is called, because it is a direct |
146 | | * pointer to the static storage. |
147 | | * Modifying the pointer invokes undefined behavior. |
148 | | * |
149 | | * This function is thread-safe as long as no other function modifies the storage areas pointed within the structure |
150 | | * (in particular, POSIX functions getpwent or getpwnam might overwrite some of the storage areas.) |
151 | | * |
152 | | * \param [out] username string with the effective username. |
153 | | * @return RETCODE_OK if successful. |
154 | | * RETCODE_ERROR if the username information cannot be determined. |
155 | | */ |
156 | | static ReturnCode_t get_username( |
157 | | std::string& username); |
158 | | |
159 | | /** |
160 | | * Check if the file with name \c filename exists. |
161 | | * \c filename can also include the path to the file. |
162 | | * |
163 | | * \param [in] filename path/name of the file to check. |
164 | | * @return True if the file exists. False otherwise. |
165 | | */ |
166 | | static bool file_exists( |
167 | | const std::string& filename); |
168 | | |
169 | | /** |
170 | | * Wait for file with name \c filename |
171 | | * until exclusive lock can be taken on it |
172 | | * |
173 | | * \param [in] filename path/name of the file to check. |
174 | | * \param [in] lock wait timeout |
175 | | * @return True if the file could be locked. False otherwise (timeout). |
176 | | */ |
177 | | static bool wait_for_file_closure( |
178 | | const std::string& filename, |
179 | | const std::chrono::seconds timeout); |
180 | | |
181 | | /** |
182 | | * Read FASTDDS_ENVIRONMENT_FILE_ENV_VAR environment value and save its value. |
183 | | * Use get_environment_file to read its value. |
184 | | * |
185 | | * @return RETCODE_OK if the environment variable is set. |
186 | | * RETCODE_NO_DATA if the environment variable is unset. |
187 | | */ |
188 | | static ReturnCode_t set_environment_file(); |
189 | | |
190 | | /** |
191 | | * Getter for the path/filename contained in the FASTDDS_ENVIRONMENT_FILE_ENV_VAR. |
192 | | * The value is set calling set_environment_file(). |
193 | | * |
194 | | * @return Path/filename contained in the environment variable. |
195 | | */ |
196 | | static const std::string& get_environment_file(); |
197 | | |
198 | | /** |
199 | | * Start a thread that watches for changes in the given file and executes a callback when the file changes. |
200 | | * |
201 | | * The method returns a handle to the object that implements the watcher containing the thread. |
202 | | * The scope of the listening thread is the same as the watching object, so when the object |
203 | | * goes out of scope, the thread is terminated. |
204 | | * |
205 | | * The thread can be terminated earlier with stop_watching_file(FileWatchHandle) |
206 | | * |
207 | | * @param [in] filename Path/name of the file to watch. |
208 | | * @param [in] callback Callback to execute when the file changes. |
209 | | * @param [in] watch_thread_config Thread settings for watch thread. |
210 | | * @param [in] callback_thread_config Thread settings for callback thread. |
211 | | * |
212 | | * @return The handle that represents the watcher object. |
213 | | */ |
214 | | static FileWatchHandle watch_file( |
215 | | std::string filename, |
216 | | std::function<void()> callback, |
217 | | const fastdds::rtps::ThreadSettings& watch_thread_config, |
218 | | const fastdds::rtps::ThreadSettings& callback_thread_config); |
219 | | |
220 | | /** |
221 | | * Stop a file watcher. |
222 | | * |
223 | | * This method effectively destroys the file watcher and the thread that were created with watch_file. |
224 | | * Once this method returns, the handle is no longer valid. |
225 | | * |
226 | | * @param [in] handle The watcher handle as returned by watch_file. |
227 | | */ |
228 | | static void stop_watching_file( |
229 | | FileWatchHandle& handle); |
230 | | |
231 | | /** |
232 | | * Get the current time as string, formatting it as specified by argument format. |
233 | | * |
234 | | * The function returns a timestamp of the current time in the following format: YYYY-MM-DD HH:MM:SS.ms |
235 | | * |
236 | | * @param [in] format Format of the date to be printed. |
237 | | * This format is build according to the std::put_time(const struct tm* tmb, const charT* fmt) function. |
238 | | * Default "%F %T". |
239 | | * |
240 | | * @return The current time in string format |
241 | | */ |
242 | | static std::string get_timestamp( |
243 | | const char* format = "%F %T"); |
244 | | |
245 | | /** |
246 | | * Fetch and store/update the information relative to all network interfaces present on the system. |
247 | | * |
248 | | * @return true if successful, false otherwise |
249 | | */ |
250 | | static bool update_interfaces(); |
251 | | |
252 | | /** |
253 | | * Get the information relative to all network interfaces present on the system. |
254 | | * |
255 | | * The loopback interface is only included in the collection if \c return_loopback is true. |
256 | | * If this information is already cached, it is returned without performing any system call, |
257 | | * unless \c force_lookup is true. |
258 | | * |
259 | | * @param [out] vec_name Collection to be populated with the network interfaces information. |
260 | | * @param [in] return_loopback Whether to include the loopback interface in the collection. |
261 | | * @param [in] force_lookup Whether to force a system call even if information is cached. |
262 | | * |
263 | | * @return true if successful, false otherwise |
264 | | */ |
265 | | static bool get_ips( |
266 | | std::vector<fastdds::rtps::IPFinder::info_IP>& vec_name, |
267 | | bool return_loopback, |
268 | | bool force_lookup); |
269 | | |
270 | | private: |
271 | | |
272 | | SystemInfo(); |
273 | | |
274 | | static std::string environment_file_; |
275 | | |
276 | | static bool cached_interfaces_; |
277 | | static std::vector<fastdds::rtps::IPFinder::info_IP> interfaces_; |
278 | | static std::mutex interfaces_mtx_; |
279 | | }; |
280 | | |
281 | | /** |
282 | | * Environment variable to specify the name of a file (including or not the path) where the environment variables |
283 | | * could be defined. |
284 | | * Thus, the user can modify the environment variables' values in runtime. |
285 | | * |
286 | | * TODO(jlbueno) Currently only ROS_DISCOVERY_SERVER environment variable is supported. |
287 | | */ |
288 | | const char* const FASTDDS_ENVIRONMENT_FILE_ENV_VAR = "FASTDDS_ENVIRONMENT_FILE"; |
289 | | |
290 | | } // namespace eprosima |
291 | | |
292 | | #endif // UTILS_SYSTEMINFO_HPP_ |