FairMQ  1.2.1
C++ Message Passing Framework
Network.h
1 /********************************************************************************
2  * Copyright (C) 2017 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
3  * *
4  * This software is distributed under the terms of the *
5  * GNU Lesser General Public Licence (LGPL) version 3, *
6  * copied verbatim in the file "LICENSE" *
7  ********************************************************************************/
8 
9 #ifndef FAIR_MQ_TOOLS_NETWORK_H
10 #define FAIR_MQ_TOOLS_NETWORK_H
11 
12 #ifndef _GNU_SOURCE
13 #define _GNU_SOURCE // To get defns of NI_MAXSERV and NI_MAXHOST
14 #endif
15 
16 #include "FairMQLogger.h"
17 
18 #include <sys/socket.h>
19 #include <sys/types.h>
20 #include <netdb.h>
21 #include <ifaddrs.h>
22 #include <stdio.h>
23 
24 #include <boost/algorithm/string.hpp> // trim
25 #include <boost/asio.hpp>
26 
27 #include <map>
28 #include <string>
29 #include <iostream>
30 #include <array>
31 #include <exception>
32 #include <algorithm>
33 
34 namespace fair
35 {
36 namespace mq
37 {
38 namespace tools
39 {
40 
41 // returns a map with network interface names as keys and their IP addresses as values
42 inline int getHostIPs(std::map<std::string, std::string>& addressMap)
43 {
44  struct ifaddrs *ifaddr, *ifa;
45  int s;
46  char host[NI_MAXHOST];
47 
48  if (getifaddrs(&ifaddr) == -1)
49  {
50  perror("getifaddrs");
51  return -1;
52  }
53 
54  for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
55  {
56  if (ifa->ifa_addr == NULL)
57  {
58  continue;
59  }
60 
61  if (ifa->ifa_addr->sa_family == AF_INET)
62  {
63  s = getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in), host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
64  if (s != 0)
65  {
66  std::cout << "getnameinfo() failed: " << gai_strerror(s) << std::endl;
67  return -1;
68  }
69 
70  addressMap.insert(std::pair<std::string, std::string>(ifa->ifa_name, host));
71  }
72  }
73  freeifaddrs(ifaddr);
74 
75  return 0;
76 }
77 
78 // get IP address of a given interface name
79 inline std::string getInterfaceIP(std::string interface)
80 {
81  std::map<std::string, std::string> IPs;
82  getHostIPs(IPs);
83  if (IPs.count(interface))
84  {
85  return IPs[interface];
86  }
87  else
88  {
89  LOG(error) << "Could not find provided network interface: \"" << interface << "\"!, exiting.";
90  return "";
91  }
92 }
93 
94 // get name of the default route interface
95 inline std::string getDefaultRouteNetworkInterface()
96 {
97  std::array<char, 128> buffer;
98  std::string interfaceName;
99 
100 #ifdef __APPLE__ // MacOS
101  std::unique_ptr<FILE, decltype(pclose) *> file(popen("route -n get default | grep interface | cut -d \":\" -f 2", "r"), pclose);
102 #else // Linux
103  std::unique_ptr<FILE, decltype(pclose) *> file(popen("ip route | grep default | cut -d \" \" -f 5 | head -n 1", "r"), pclose);
104 #endif
105 
106  if (!file)
107  {
108  LOG(error) << "Could not detect default route network interface name - popen() failed!";
109  return "";
110  }
111 
112  while (!feof(file.get()))
113  {
114  if (fgets(buffer.data(), 128, file.get()) != NULL)
115  {
116  interfaceName += buffer.data();
117  }
118  }
119 
120  boost::algorithm::trim(interfaceName);
121 
122  if (interfaceName == "")
123  {
124  LOG(error) << "Could not detect default route network interface name";
125  }
126  else
127  {
128  LOG(debug) << "Detected network interface name for the default route: " << interfaceName;
129  }
130 
131  return interfaceName;
132 }
133 
134 inline std::string getIpFromHostname(const std::string& hostname)
135 {
136  try {
137  namespace bai = boost::asio::ip;
138  boost::asio::io_service ios;
139  bai::tcp::resolver resolver(ios);
140  bai::tcp::resolver::query query(hostname, "");
141  bai::tcp::resolver::iterator end;
142 
143  auto it = std::find_if(static_cast<bai::basic_resolver_iterator<bai::tcp>>(resolver.resolve(query)), end, [](const bai::tcp::endpoint& ep) {
144  return ep.address().is_v4();
145  });
146 
147  if (it != end) {
148  std::stringstream ss;
149  ss << static_cast<bai::tcp::endpoint>(*it).address();
150  return ss.str();
151  }
152 
153  LOG(warn) << "could not find ipv4 address for hostname '" << hostname << "'";
154 
155  return "";
156  } catch (std::exception& e) {
157  LOG(error) << "could not resolve hostname '" << hostname << "', reason: " << e.what();
158  return "";
159  }
160 }
161 
162 inline std::string getIpFromHostname(const std::string& hostname, boost::asio::io_service& ios)
163 {
164  try {
165  namespace bai = boost::asio::ip;
166  bai::tcp::resolver resolver(ios);
167  bai::tcp::resolver::query query(hostname, "");
168  bai::tcp::resolver::iterator end;
169 
170  auto it = std::find_if(static_cast<bai::basic_resolver_iterator<bai::tcp>>(resolver.resolve(query)), end, [](const bai::tcp::endpoint& ep) {
171  return ep.address().is_v4();
172  });
173 
174  if (it != end) {
175  std::stringstream ss;
176  ss << static_cast<bai::tcp::endpoint>(*it).address();
177  return ss.str();
178  }
179 
180  LOG(warn) << "could not find ipv4 address for hostname '" << hostname << "'";
181 
182  return "";
183  } catch (std::exception& e) {
184  LOG(error) << "could not resolve hostname '" << hostname << "', reason: " << e.what();
185  return "";
186  }
187 }
188 
189 } /* namespace tools */
190 } /* namespace mq */
191 } /* namespace fair */
192 
193 #endif /* FAIR_MQ_TOOLS_NETWORK_H */
Definition: DeviceRunner.h:23