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