1 #ifndef DOZERG_SOCKET_ADDR_H_20080229 2 #define DOZERG_SOCKET_ADDR_H_20080229 10 #include <sys/socket.h> 11 #include <arpa/inet.h> 12 #include <sys/ioctl.h> 20 #include "to_string.hh" 26 typedef struct sockaddr_storage __SS;
27 typedef struct sockaddr __SA;
28 typedef struct sockaddr_in __SA4;
29 typedef struct sockaddr_in6 __SA6;
33 static std::string IPv4String(uint32_t ipv4,
bool hostOrder =
true){
35 in.s_addr = (hostOrder ? htonl(ipv4) : ipv4);
42 static bool IPv6String(
const struct in6_addr & ipv6, std::string * result){
45 std::string ret = ipv6Str(ipv6);
53 static uint32_t IPv4FromStr(
const std::string & ipv4,
bool hostOrder =
true){
55 if(ipv4.empty() || 0 >= inet_pton(AF_INET, strPtr(ipv4), &in))
57 return (hostOrder ? ntohl(in.s_addr) : in.s_addr);
63 static bool IPv6FromStr(
const std::string & ipv6,
struct in6_addr * addr){
64 return (NULL != addr && !ipv6.empty() && inet_pton(AF_INET6, strPtr(ipv6), addr) > 0);
68 static uint32_t IPv4FromIf(
const std::string & eth,
bool hostOrder =
true){
70 const socklen_t len = tryIfr(strPtr(eth), &addr);
71 if(
sizeof(__SA4) != len)
73 uint32_t ret =
reinterpret_cast<const __SA4 *
>(&addr)->sin_addr.s_addr;
74 return (hostOrder ? ntohl(ret) : ret);
87 CSockAddr(
const std::string & host,
const std::string & serv){
89 socklen_t len = tryGai(strPtr(host), strPtr(serv), &addr);
93 if(!host.empty() && !setIpAux(host))
95 if(!serv.empty() && !setPort(serv))
98 explicit CSockAddr(
const std::string & host, uint16_t port = 0,
bool hostOrder =
true){
102 }
else if(!setPort(
"0"))
106 setPortAux(port, hostOrder);
108 CSockAddr(
const __SS & addr, socklen_t len){setAddr(addr, len);}
109 CSockAddr(
const __SA & addr, socklen_t len){setAddr(addr, len);}
110 explicit CSockAddr(
const __SA4 & addr){setAddr(addr);}
111 explicit CSockAddr(
const __SA6 & addr){setAddr(addr);}
112 bool setIp(
const std::string & host){
113 const uint16_t port = getPort(
false);
118 setPortAux(port,
false);
121 bool setIp(uint32_t ipv4,
bool hostOrder =
true){
122 if(setIpv4Aux(ipv4, hostOrder))
124 assert(!valid() || isIpv6());
125 const uint16_t port = getPort(
false);
126 if(!setIpAux(
"0.0.0.0"))
130 setIpv4Aux(ipv4, hostOrder);
132 setPortAux(port,
false);
135 bool setIp(
const in6_addr & ipv6){
139 sa<__SA6>()->sin6_addr = ipv6;
142 bool setPort(
const std::string & serv){
143 char buf[
sizeof(__SS)];
144 __SS *
const addr =
reinterpret_cast<__SS *
>(buf);
145 socklen_t len = tryGai(NULL, strPtr(serv), addr);
147 return setSs(*addr, len);
150 if(
sizeof(__SA4) == len){
151 const __SA4 *
const a4 =
reinterpret_cast<const __SA4 *
>(buf);
153 }
else if(
sizeof(__SA6) == len){
154 const __SA6 *
const a6 =
reinterpret_cast<const __SA6 *
>(buf);
155 port = a6->sin6_port;
158 return setPortAux(port,
false);
160 bool setPort(uint16_t port,
bool hostOrder =
true){
161 if(setPortAux(port, hostOrder))
165 const socklen_t len = tryGai(NULL,
"0", &addr);
166 if(!setSs(addr, len))
170 setPortAux(port, hostOrder);
173 bool setAddr(
const __SS & addr, socklen_t len){
return setSs(addr, len);}
174 bool setAddr(
const __SA & addr, socklen_t len){
175 return setAddr(reinterpret_cast<const __SS &>(addr), len);
177 bool setAddr(
const __SA4 & addr){
178 return setAddr(reinterpret_cast<const __SS &>(addr),
sizeof(__SA4));
180 bool setAddr(
const __SA6 & addr){
181 return setAddr(reinterpret_cast<const __SS &>(addr),
sizeof(__SA6));
185 uint32_t getIpv4(
bool hostOrder =
true)
const{
186 const uint32_t ret = (isIpv4() ? sa<__SA4>()->sin_addr.s_addr : 0);
187 return (hostOrder ? htonl(ret) : ret);
190 bool getIpv6(
struct in6_addr & ipv6)
const{
193 ipv6 = sa<__SA6>()->sin6_addr;
198 uint16_t getPort(
bool hostOrder =
true)
const{
199 const uint16_t ret = (isIpv4() ? sa<__SA4>()->sin_port
200 : (isIpv6() ? sa<__SA6>()->sin6_port
202 return (hostOrder ? htons(ret) : ret);
205 void clear(){sa_.clear();}
207 bool valid()
const{
return (isIpv4() || isIpv6());}
209 std::string toString()
const{
210 std::string ret = addr4Str();
226 const __SA * sockaddr()
const{
227 return (sa_.empty() ? NULL :
reinterpret_cast<const __SA *
>(&sa_[0]));
230 socklen_t socklen()
const{
return sa_.size();}
233 return (NULL != sa<__SA4>() && AF_INET == sa<__SA4>()->sin_family);
236 return (NULL != sa<__SA6>() && AF_INET6 == sa<__SA6>()->sin6_family);
240 const T * sa()
const{
241 if(sa_.size() !=
sizeof(T))
243 return reinterpret_cast<const T *
>(&sa_[0]);
247 if(sa_.size() !=
sizeof(T))
249 return reinterpret_cast<T *
>(&sa_[0]);
252 static std::string ipv4Str(
const struct in_addr & addr){
253 std::string buf(16, 0);
254 if(NULL == inet_ntop(AF_INET, &addr, &buf[0], buf.size()))
255 return std::string();
256 buf.resize(std::char_traits<char>::length(buf.c_str()));
260 static std::string ipv6Str(
const struct in6_addr & addr){
261 std::string buf(128, 0);
262 if(NULL == inet_ntop(AF_INET6, &addr, &buf[0], buf.size()))
263 return std::string();
264 buf.resize(std::char_traits<char>::length(buf.c_str()));
268 std::string addr4Str()
const{
270 return std::string();
271 const __SA4 *
const s = sa<__SA4>();
273 oss<<ipv4Str(s->sin_addr)<<
":"<<ntohs(s->sin_port);
276 std::string addr6Str()
const{
278 return std::string();
279 const __SA6 *
const s = sa<__SA6>();
281 oss<<
'['<<ipv6Str(s->sin6_addr)<<
"]:"<<ntohs(s->sin6_port);
285 static const char * strPtr(
const std::string & str){
286 return (str.empty() ? NULL : str.c_str());
292 static socklen_t tryGai(
const char * node,
const char * service, __SS * addr){
294 if(NULL == node && NULL == service)
296 struct addrinfo hints;
297 ::memset(&hints, 0,
sizeof hints);
298 hints.ai_family = AF_UNSPEC;
299 hints.ai_socktype = SOCK_STREAM;
300 struct addrinfo * ai = NULL;
301 if(0 != getaddrinfo(node, service, &hints, &ai) || NULL == ai)
303 socklen_t len = ai->ai_addrlen;
304 ::memcpy(addr, ai->ai_addr, len);
312 static socklen_t tryIfr(
const char * node, __SS * addr){
317 ::memset(&ifr, 0,
sizeof ifr);
318 strncpy(ifr.ifr_name, node, IFNAMSIZ);
319 const int fd = socket(AF_INET, SOCK_STREAM, 0);
322 int ret = ioctl(fd, SIOCGIFADDR, &ifr);
326 ::memset(addr, 0,
sizeof(__SS));
327 ret = ifr.ifr_addr.sa_family;
328 socklen_t len = (AF_INET == ret ?
sizeof(__SA4)
329 : (AF_INET6 == ret ?
sizeof(__SA6) : 0));
330 if(len >
sizeof ifr.ifr_addr)
331 len =
sizeof ifr.ifr_addr;
332 ::memcpy(addr, &ifr.ifr_addr, len);
336 bool setIpAux(
const std::string & host){
338 socklen_t len = tryGai(strPtr(host), NULL, &addr);
340 len = tryIfr(strPtr(host), &addr);
341 return setSs(addr, len);
344 bool setIpv4Aux(uint32_t ipv4,
bool hostOrder){
347 if(hostOrder && ipv4)
349 sa<__SA4>()->sin_addr.s_addr = ipv4;
353 bool setPortAux(uint16_t port,
bool hostOrder){
354 if(hostOrder && port)
357 sa<__SA4>()->sin_port = port;
359 sa<__SA6>()->sin6_port = port;
365 bool setSs(
const __SS & addr, socklen_t len){
366 if(
sizeof(__SA4) != len &&
sizeof(__SA6) != len)
369 ::memcpy(&sa_[0], &addr, sa_.size());
Definition: to_string.hh:43
Definition: sock_addr.hh:24