Line data Source code
1 : // DUNE DAQ modification notice:
2 : // This file has been modified from the original ATLAS system source for the DUNE DAQ project.
3 : // Fork baseline commit: system-00-00-20 (2020-09-25).
4 : // Renamed since fork: yes (from src/Host.cxx to src/Host.cpp).
5 :
6 : /*
7 : * Host.cxx
8 : * OksSystem
9 : *
10 : * Created by Matthias Wiesmann on 03.02.05.
11 : * Copyright 2005 CERN. All rights reserved.
12 : *
13 : */
14 :
15 : #include <netdb.h>
16 : #include <sys/socket.h>
17 : #include <sys/types.h>
18 : #include <sys/utsname.h>
19 :
20 : #include <unistd.h>
21 :
22 : #include <iostream>
23 : #include <sstream>
24 : #include <strings.h>
25 :
26 : #include "okssystem/Host.hpp"
27 :
28 : #define BUFFER_SIZE 256
29 :
30 : /** Translates an hostname into an ip address
31 : * \param name hostname to translate
32 : * \return the ip addrress, 0.0.0.0 if name not found.
33 : * \note only returns the first ip address associated with name
34 : */
35 :
36 : struct sockaddr_in
37 19 : OksSystem::Host::resolve(const std::string& name) throw()
38 : {
39 19 : struct addrinfo* info_ptr;
40 19 : const char* str = name.c_str();
41 19 : const int status = getaddrinfo(str, 0, 0, &info_ptr);
42 19 : struct sockaddr_in address;
43 19 : bzero(&address, sizeof(address));
44 19 : address.sin_family = AF_INET;
45 19 : address.sin_addr.s_addr = 0;
46 19 : if (status == 0) {
47 19 : struct sockaddr_in* ptr = (sockaddr_in*)info_ptr->ai_addr;
48 19 : address = *ptr;
49 19 : freeaddrinfo(info_ptr);
50 : } // if
51 19 : return address;
52 : } // resolve
53 :
54 : /** Translates an ip address into an hostname
55 : * \param address the address to translate
56 : * \return the hostname an empty string if the hostname could not be resolved
57 : */
58 :
59 : std::string
60 19 : OksSystem::Host::resolve(struct sockaddr_in address) throw()
61 : {
62 19 : char buffer[NI_MAXHOST];
63 19 : const struct sockaddr* ptr = (const struct sockaddr*)&address;
64 19 : const int status = getnameinfo(ptr, sizeof(address), buffer, sizeof(buffer), 0, 0, 0);
65 19 : if (status != 0)
66 0 : return to_string(address);
67 19 : return std::string(buffer);
68 : } // resolve
69 :
70 : /** Tries to build a fully qualified name.
71 : * This is done first by converting the name to ip then the ip to a name.
72 : * If this fails (basically, we cannot do DNS resolves)
73 : * the non fully qualified name is returned
74 : * \param name the (partial) name
75 : * \return fullname
76 : */
77 :
78 : std::string
79 19 : OksSystem::Host::expand(const std::string& name) throw()
80 : {
81 19 : const struct sockaddr_in address = resolve(name);
82 19 : if (address.sin_addr.s_addr != 0)
83 19 : return resolve(address);
84 0 : return std::string(name);
85 : } // expand
86 :
87 : /** Transliterate an ip address into the canonical dotted text version (w.x.y.z).
88 : * \param ip_addr the address to translate
89 : * \return string containing the text version
90 : * \note Should use addr2ascii
91 : */
92 :
93 : std::string
94 0 : OksSystem::Host::to_string(struct sockaddr_in ip_addr)
95 : {
96 0 : const char* s = inet_ntoa(ip_addr.sin_addr);
97 0 : return std::string(s);
98 : } // to_string
99 :
100 : // Constructors, destructors
101 : // --------------------------
102 :
103 : /** Constructors for the local host
104 : */
105 :
106 19 : OksSystem::Host::Host() throw() {} // Host
107 :
108 0 : OksSystem::Host::Host(const OksSystem::Host& other)
109 : {
110 0 : m_name = other.m_name;
111 0 : if (!other.m_full_name.empty()) {
112 0 : m_full_name = other.m_full_name;
113 : } // if
114 0 : } // Host
115 :
116 : /** Constructor for host by name
117 : * \param name name of the host
118 : */
119 :
120 0 : OksSystem::Host::Host(const std::string& s_name)
121 : {
122 0 : m_name = s_name;
123 0 : } // Host
124 :
125 0 : OksSystem::Host::Host(struct sockaddr_in ip_addr)
126 : {
127 0 : m_name = resolve(ip_addr);
128 0 : m_full_name = m_name;
129 0 : } // Host
130 :
131 0 : OksSystem::Host::~Host() throw() {} // OksSystem
132 :
133 : // Operator
134 : // --------------------------
135 :
136 : /** Cast conversion into ip address
137 : * \return ip address
138 : */
139 :
140 0 : OksSystem::Host::operator struct sockaddr_in() const throw()
141 : {
142 0 : return ip();
143 : } // struct sockaddr_in
144 :
145 : /** Comparison method
146 : * We try to expand both name and compare those
147 : * \param other the host to compare to
148 : * \return \c true if both have the same fully qualified name
149 : */
150 :
151 : bool
152 0 : OksSystem::Host::equals(const Host& other) const throw()
153 : {
154 0 : return full_name() == other.full_name();
155 : } // equals
156 :
157 : // Methods
158 : // --------------------------
159 :
160 : /** Name (this might be non fully qualified name)
161 : * \return name of the host
162 : */
163 :
164 : const std::string&
165 0 : OksSystem::Host::name() const throw()
166 : {
167 0 : return m_name;
168 : }
169 :
170 : /** IP address of the host
171 : * \return IP address of the host, or 0.0.0.0 if it cannot be resolved
172 : */
173 :
174 : struct sockaddr_in
175 0 : OksSystem::Host::ip() const throw()
176 : {
177 0 : return resolve(m_name);
178 : }
179 :
180 : /** Fully qualified name of the host
181 : * \return Fully qualified name of the host, or the string \"0.0.0.0\"
182 : */
183 :
184 : const std::string&
185 19 : OksSystem::Host::full_name() const throw()
186 : {
187 19 : if (m_full_name.empty()) {
188 19 : m_full_name = expand(m_name);
189 : } // if
190 19 : return m_full_name;
191 : } // full_name
192 :
193 : /** The IP Address of the host, as a string
194 : * \return a string containing the IP address of the host in w.x.y.z format
195 : */
196 :
197 : std::string
198 0 : OksSystem::Host::ip_string() const throw()
199 : {
200 0 : const struct sockaddr_in address = ip();
201 0 : return to_string(address);
202 : } // ip_string
203 :
204 : bool
205 0 : OksSystem::operator==(const Host& a, const Host& b) throw()
206 : {
207 0 : return a.equals(b);
208 : } // operator ==
209 :
210 : bool
211 0 : OksSystem::operator!=(const Host& a, const Host& b) throw()
212 : {
213 0 : return !a.equals(b);
214 : } // operator ≠
215 :
216 : // Local Host
217 : // --------------------------
218 :
219 : /** Instance of local host
220 : * \brief LocalHost singleton
221 : */
222 :
223 : OksSystem::LocalHost* OksSystem::LocalHost::s_instance = 0;
224 :
225 : /** Short-cut method - gives the local hostname
226 : * This name is not guaranteed to be a fully qualified name.
227 : * \return hostname
228 : * \see OksSystem::LocalHost::name()
229 : */
230 :
231 : const std::string&
232 0 : OksSystem::LocalHost::local_name() throw()
233 : {
234 0 : return instance()->name();
235 : } // localhostname
236 :
237 : /** Short-cut method - gives the fully qualified local hostname
238 : * \return fully qualified hostname
239 : * \see OksSystem::LocalHost::full_name()
240 : */
241 :
242 : const std::string&
243 19 : OksSystem::LocalHost::full_local_name() throw()
244 : {
245 19 : return instance()->full_name();
246 : } // fulllocalhostname
247 :
248 : /** This method returns a pointer to the singleton instance.
249 : * There is no need to ever create any instance of LocalHost
250 : * \return pointer to singleton instance
251 : * \note utility methods like \c full_local_name use this instance class
252 : */
253 :
254 : const OksSystem::LocalHost*
255 38 : OksSystem::LocalHost::instance() throw()
256 : {
257 38 : if (0 == s_instance) {
258 19 : s_instance = new LocalHost();
259 : } //
260 38 : return s_instance;
261 : } // instance
262 :
263 : /** Constructor
264 : * You should \b not construct new instances, use \c instance to get the
265 : * singleton instance.
266 : */
267 :
268 19 : OksSystem::LocalHost::LocalHost() throw()
269 19 : : Host()
270 : {
271 19 : struct utsname u_name_data;
272 19 : const int status = ::uname(&u_name_data);
273 19 : if (status == 0) {
274 19 : m_name = u_name_data.nodename;
275 19 : m_os_name = u_name_data.sysname;
276 19 : m_release = u_name_data.release;
277 19 : m_version = u_name_data.version;
278 19 : m_machine = u_name_data.machine;
279 : } else {
280 0 : char buffer[NI_MAXHOST];
281 0 : const int host_status = gethostname(buffer, sizeof(buffer));
282 0 : if (host_status == 0) {
283 0 : m_name = buffer;
284 : } else { // both uname and gethostname screwed
285 0 : m_name.clear();
286 : } // check for host_name
287 : } // uname failed.
288 19 : } // LocalHost
289 :
290 0 : OksSystem::LocalHost::~LocalHost() throw()
291 : {
292 : // delete s_instance;
293 0 : }
294 :
295 : /** \return Operating OksSystem name */
296 :
297 : const std::string&
298 0 : OksSystem::LocalHost::os_name() const throw()
299 : {
300 0 : return m_os_name;
301 : } // os_name
302 :
303 : /** \return Operating OksSystem release */
304 :
305 : const std::string&
306 0 : OksSystem::LocalHost::os_release() const throw()
307 : {
308 0 : return m_release;
309 : } // os_release
310 :
311 : /** \return Operating OksSystem version */
312 :
313 : const std::string&
314 0 : OksSystem::LocalHost::os_version() const throw()
315 : {
316 0 : return m_version;
317 : } // os_version
318 :
319 : /** \return machine name */
320 :
321 : const std::string&
322 0 : OksSystem::LocalHost::machine() const throw()
323 : {
324 0 : return m_machine;
325 : } // machine
326 :
327 : /** This method builds a description of the localhost
328 : * This contains all the of the information handled by this class.
329 : * \return description text
330 : */
331 :
332 : const std::string&
333 0 : OksSystem::LocalHost::description() const throw()
334 : {
335 0 : if (m_description.empty()) {
336 0 : std::ostringstream stream;
337 0 : stream << m_os_name << " " << m_release << "/" << m_machine;
338 0 : m_description = stream.str();
339 0 : }
340 0 : return m_description;
341 : } // description
342 :
343 : /** Convenience method, finds the fully qualified host name for this node
344 : * \return c-string with fully qualified hostname
345 : * \note the string is owned by the singleton object it should not be deleted
346 : * \note if resolve fails (typically because there is no network) this method might return
347 : * the short (unqualified) host name.
348 : */
349 :
350 : const char*
351 0 : OksSystem::getfullhost() throw()
352 : {
353 0 : const std::string& str = OksSystem::LocalHost::full_local_name();
354 0 : return str.c_str();
355 : } // full_host_name
356 :
357 : /** Comparison operator
358 : * Simple optimisation - if we compare two localhost instances, they are always equal
359 : * \param a first instance
360 : * \param b second instance
361 : */
362 :
363 : bool
364 0 : OksSystem::operator==(const LocalHost&, const LocalHost&) throw()
365 : {
366 0 : return true;
367 : }
368 :
369 : /** Comparison operator
370 : * Simple optimisation - if we compare two localhost instances, they are always equal
371 : * \param a first instance
372 : * \param b second instance
373 : */
374 :
375 : bool
376 0 : OksSystem::operator!=(const LocalHost&, const LocalHost&) throw()
377 : {
378 0 : return false;
379 : }
380 :
381 : std::ostream&
382 0 : operator<<(std::ostream& stream, const OksSystem::Host& host)
383 : {
384 0 : stream << host.full_name();
385 0 : return stream;
386 : } // operator<<
|