hmbdc
simplify-high-performance-messaging-programming
Misc.hpp
1 #include "hmbdc/Copyright.hpp"
2 #pragma once
3 
4 #include "hmbdc/Exception.hpp"
5 
6 #include <string>
7 #include <stdexcept>
8 
9 #include <netdb.h>
10 #include <netinet/in.h>
11 #include <arpa/inet.h>
12 
13 
14 #include <sys/types.h>
15 #include <sys/socket.h>
16 #include <ifaddrs.h>
17 #include <stdlib.h>
18 #include <sys/ioctl.h>
19 #include <net/if.h>
20 #include <string.h>
21 
22 struct msghdr;
23 namespace hmbdc { namespace comm { namespace inet {
24 /**
25  * @brief resolve a local ip interface using a mask
26  *
27  * @param mask in this format: "192.168.0.1/24" or "192.168.0.101" which is the same as "192.168.0.101/32"
28  * when using 192.168.0.1/0
29  * @param includeLoopback if it is false, the loopback address is excluded from the result
30  * @return a local ip matches the mask if no exception is thrown
31  */
32 std::string getLocalIpMatchMask(std::string const& mask);
33 std::string getLocalIpThruName(std::string const& name);
34 std::pair<std::string, uint16_t> getPeerIpPort(int fd);
35 void extractRelicTo(msghdr& to, msghdr const& from, int sent);
36 
37 inline
38 std::string
39 getLocalIpMatchMask(std::string const& mask) {
40  using namespace std;
41  bool includeLoopback = mask != "0.0.0.0/0";
42  auto offset = mask.find('/');
43  auto ip_part = mask;
44  uint32_t maskLen = 32;
45 
46  if (offset != string::npos) {
47  ip_part = mask.substr(0, offset);
48  auto bit_part = mask.substr(offset + 1u);
49  maskLen = atoi(bit_part.c_str());
50  }
51  uint32_t targetIp = inet_addr(ip_part.c_str());
52  struct ifaddrs *ifaddr, *ifa;
53  int family, s;
54  char host[NI_MAXHOST];
55 
56  if (getifaddrs(&ifaddr) == -1) {
57  HMBDC_THROW(runtime_error, " getifaddrs failed ");
58  }
59 
60  for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
61  if (ifa->ifa_addr == NULL)
62  continue;
63 
64  family = ifa->ifa_addr->sa_family;
65 
66  if (family == AF_INET) {
67  s = getnameinfo(ifa->ifa_addr,
68  sizeof(struct sockaddr_in),
69  host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
70  if (s != 0) {
71  HMBDC_THROW(runtime_error, " getnameinfo failed ");
72  }
73  struct in_addr addr;
74  if (inet_aton(host, &addr)
75  && (maskLen == 0
76  || (targetIp << (32u - maskLen)) == (addr.s_addr << (32u - maskLen)))
77  && (includeLoopback || !(ifa->ifa_flags & IFF_LOOPBACK))) {
78  freeifaddrs(ifaddr);
79  return string(host);
80  }
81  }
82  }
83  freeifaddrs(ifaddr);
84  HMBDC_THROW(runtime_error, mask << " does not resolve locally");
85 }
86 
87 inline
88 std::string
89 getLocalIpThruName(std::string const& name) {
90  using namespace std;
91  struct ifaddrs *ifaddr, *ifa;
92  int family, s;
93  char host[NI_MAXHOST];
94 
95  if (getifaddrs(&ifaddr) == -1) {
96  HMBDC_THROW(runtime_error, " getifaddrs failed ");
97  }
98 
99  for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
100  if (ifa->ifa_addr == NULL)
101  continue;
102 
103  family = ifa->ifa_addr->sa_family;
104 
105  if (family == AF_INET
106  && strcmp(name.c_str(), ifa->ifa_name) == 0) {
107  s = getnameinfo(ifa->ifa_addr,
108  sizeof(struct sockaddr_in),
109  host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
110  if (s != 0) {
111  HMBDC_THROW(runtime_error, " getnameinfo failed ");
112  }
113  return string(host);
114  }
115  }
116  HMBDC_THROW(runtime_error, name << " does not resolve locally");
117 }
118 
119 inline
120 std::pair<std::string, uint16_t>
121 getPeerIpPort(int fd) {
122  sockaddr addr = {0};
123  auto addrlen = sizeof(addr);
124  if (getpeername(fd, &addr, (socklen_t*)&addrlen) == -1) {
125  HMBDC_THROW(std::runtime_error, "invalid socket errno=" << errno);
126  }
127  sockaddr_in* p = (sockaddr_in *)&addr;
128  char ipaddr[INET_ADDRSTRLEN];
129  if (inet_ntop(AF_INET, &(p->sin_addr), ipaddr, INET_ADDRSTRLEN)) {
130  } else {
131  HMBDC_THROW(std::runtime_error, "no ip addr errno=" << errno);
132  }
133  return make_pair(std::string(ipaddr), p->sin_port);
134 }
135 
136 inline
137 void
138 extractRelicTo(msghdr& to, msghdr const& from, int sent) {
139  auto l = size_t(sent);
140  auto i = 0;
141  for (; l > 0 && i < (int)from.msg_iovlen; ++i) {
142  auto& msg = from.msg_iov[i];
143  if (msg.iov_len <= l) {
144  l -= msg.iov_len;
145  } else {
146  break;
147  }
148  }
149 
150  auto& msg = from.msg_iov[i];
151  to.msg_iov[0].iov_base = (char*)msg.iov_base + l;
152  to.msg_iov[0].iov_len = msg.iov_len - l;
153  auto to_msg_iovlen = from.msg_iovlen - i;
154 
155  memmove(to.msg_iov + 1
156  , from.msg_iov + i + 1
157  , (to_msg_iovlen - 1) * sizeof(iovec)
158  );
159  to.msg_iovlen = to_msg_iovlen;
160 }
161 }}}
Definition: TypedString.hpp:84
Definition: Base.hpp:12