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