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  bool includeLoopback = mask != "0.0.0.0/0";
41  auto offset = mask.find('/');
42  auto ip_part = mask;
43  uint32_t maskLen = 32;
44 
45  if (offset != std::string::npos) {
46  ip_part = mask.substr(0, offset);
47  auto bit_part = mask.substr(offset + 1u);
48  maskLen = atoi(bit_part.c_str());
49  }
50  uint32_t targetIp = inet_addr(ip_part.c_str());
51  struct ifaddrs *ifaddr, *ifa;
52  int family, s;
53  char host[NI_MAXHOST];
54 
55  if (getifaddrs(&ifaddr) == -1) {
56  HMBDC_THROW(std::runtime_error, " getifaddrs failed ");
57  }
58 
59  for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
60  if (ifa->ifa_addr == NULL)
61  continue;
62 
63  family = ifa->ifa_addr->sa_family;
64 
65  if (family == AF_INET) {
66  s = getnameinfo(ifa->ifa_addr,
67  sizeof(struct sockaddr_in),
68  host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
69  if (s != 0) {
70  HMBDC_THROW(std::runtime_error, " getnameinfo failed ");
71  }
72  struct in_addr addr;
73  if (inet_aton(host, &addr)
74  && (maskLen == 0
75  || (targetIp << (32u - maskLen)) == (addr.s_addr << (32u - maskLen)))
76  && (includeLoopback || !(ifa->ifa_flags & IFF_LOOPBACK))) {
77  freeifaddrs(ifaddr);
78  return std::string(host);
79  }
80  }
81  }
82  freeifaddrs(ifaddr);
83  HMBDC_THROW(std::runtime_error, mask << " does not resolve locally");
84 }
85 
86 inline
87 std::string
88 getLocalIpThruName(std::string const& name) {
89  struct ifaddrs *ifaddr, *ifa;
90  int family, s;
91  char host[NI_MAXHOST];
92 
93  if (getifaddrs(&ifaddr) == -1) {
94  HMBDC_THROW(std::runtime_error, " getifaddrs failed ");
95  }
96 
97  for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
98  if (ifa->ifa_addr == NULL)
99  continue;
100 
101  family = ifa->ifa_addr->sa_family;
102 
103  if (family == AF_INET
104  && strcmp(name.c_str(), ifa->ifa_name) == 0) {
105  s = getnameinfo(ifa->ifa_addr,
106  sizeof(struct sockaddr_in),
107  host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
108  if (s != 0) {
109  HMBDC_THROW(std::runtime_error, " getnameinfo failed ");
110  }
111  return std::string(host);
112  }
113  }
114  HMBDC_THROW(std::runtime_error, name << " does not resolve locally");
115 }
116 
117 inline
118 std::pair<std::string, uint16_t>
119 getPeerIpPort(int fd) {
120  sockaddr addr = {0};
121  auto addrlen = sizeof(addr);
122  if (getpeername(fd, &addr, (socklen_t*)&addrlen) == -1) {
123  HMBDC_THROW(std::runtime_error, "invalid socket errno=" << errno);
124  }
125  sockaddr_in* p = (sockaddr_in *)&addr;
126  char ipaddr[INET_ADDRSTRLEN];
127  if (inet_ntop(AF_INET, &(p->sin_addr), ipaddr, INET_ADDRSTRLEN)) {
128  } else {
129  HMBDC_THROW(std::runtime_error, "no ip addr errno=" << errno);
130  }
131  return make_pair(std::string(ipaddr), p->sin_port);
132 }
133 
134 inline
135 void
136 extractRelicTo(msghdr& to, msghdr const& from, int sent) {
137  auto l = size_t(sent);
138  auto i = 0;
139  for (; l > 0 && i < (int)from.msg_iovlen; ++i) {
140  auto& msg = from.msg_iov[i];
141  if (msg.iov_len <= l) {
142  l -= msg.iov_len;
143  } else {
144  break;
145  }
146  }
147 
148  auto& msg = from.msg_iov[i];
149  to.msg_iov[0].iov_base = (char*)msg.iov_base + l;
150  to.msg_iov[0].iov_len = msg.iov_len - l;
151  auto to_msg_iovlen = from.msg_iovlen - i;
152 
153  memmove(to.msg_iov + 1
154  , from.msg_iov + i + 1
155  , (to_msg_iovlen - 1) * sizeof(iovec)
156  );
157  to.msg_iovlen = to_msg_iovlen;
158 }
159 }}}
Definition: Base.hpp:12