IBR-DTNSuite  0.12
vaddress.cpp
Go to the documentation of this file.
1 /*
2  * vaddress.cpp
3  *
4  * Copyright (C) 2011 IBR, TU Braunschweig
5  *
6  * Written-by: Johannes Morgenroth <morgenroth@ibr.cs.tu-bs.de>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21 
22 #include "ibrcommon/config.h"
23 #include "ibrcommon/net/vaddress.h"
24 #include "ibrcommon/net/socket.h"
25 
26 #ifdef __WIN32__
27 #include <winsock2.h>
28 #else
29 #include <arpa/inet.h>
30 #include <netdb.h>
31 #endif
32 
33 #include <string.h>
34 
35 namespace ibrcommon
36 {
37 #if (defined HAVE_LIBNL3) || (defined HAVE_LIBNL)
38  const std::string vaddress::SCOPE_GLOBAL = "global";
39 #else
40  const std::string vaddress::SCOPE_GLOBAL = "universe";
41 #endif
42  const std::string vaddress::SCOPE_LINKLOCAL = "link";
43 
44  const std::string vaddress::VADDR_LOCALHOST = "localhost";
45  const std::string vaddress::VADDR_ANY = "any";
46 
48  : _address(VADDR_ANY), _service(), _scope(), _family(AF_UNSPEC)
49  {
50  }
51 
52  vaddress::vaddress(const int port, sa_family_t family)
53  : _address(VADDR_ANY), _service(), _scope(), _family(family)
54  {
55  std::stringstream ss;
56  ss << port;
57  _service = ss.str();
58  }
59 
60  vaddress::vaddress(const std::string &address, const int port, sa_family_t family)
61  : _address(address), _service(), _scope(), _family(family)
62  {
63  std::stringstream ss;
64  ss << port;
65  _service = ss.str();
66  }
67 
68  vaddress::vaddress(const std::string &address, const std::string &service, sa_family_t family)
69  : _address(address), _service(service), _scope(), _family(family)
70  {
71  }
72 
73  vaddress::vaddress(const std::string &address, const std::string &service, const std::string &scope, sa_family_t family)
74  : _address(address), _service(service), _scope(scope), _family(family)
75  {
76  }
77 
79  {
80  }
81 
83  {
84  if (_address < dhs._address) return true;
85  if (_scope < dhs._scope) return true;
86  return false;
87  }
88 
89 
90  bool vaddress::operator!=(const vaddress &obj) const
91  {
92  if (_address != obj._address) return true;
93  if (_scope != obj._scope) return true;
94  return false;
95  }
96 
97  bool vaddress::operator==(const vaddress &obj) const
98  {
99  if (_address != obj._address) return false;
100  if (_scope != obj._scope) return false;
101  return true;
102  }
103 
104  bool vaddress::isLocal() const
105  {
106  if (_address == VADDR_LOCALHOST) return true;
107 
108  try {
109  const std::string n = name();
110  if (n == VADDR_LOCALHOST) return true;
111 
112  size_t pos = n.find_last_of(VADDR_LOCALHOST);
113  if (pos == std::string::npos) return false;
114  if ((n.length() - 1) == pos) return true;
115  } catch (const address_exception&) { }
116 
117  return false;
118  }
119 
120  bool vaddress::isAny() const
121  {
122  return (_address == VADDR_ANY);
123  }
124 
125  sa_family_t vaddress::family() const throw (address_exception)
126  {
127  if (_family != AF_UNSPEC)
128  return _family;
129 
130  struct addrinfo hints;
131  memset(&hints, 0, sizeof(struct addrinfo));
132  hints.ai_family = PF_UNSPEC;
133  hints.ai_socktype = SOCK_DGRAM;
134 
135  struct addrinfo *res;
136  int ret = 0;
137 
138  const char *address = NULL;
139  const char *service = NULL;
140 
141  // throw exception if the address is not set.
142  // without an address we can not determine the address family
143  address = this->address().c_str();
144 
145  try {
146  service = this->service().c_str();
147  } catch (const vaddress::service_not_set&) { };
148 
149  if ((ret = ::getaddrinfo(address, service, &hints, &res)) != 0)
150  {
151  throw address_exception("getaddrinfo(): " + std::string(gai_strerror(ret)));
152  }
153 
154  sa_family_t fam = static_cast<sa_family_t>(res->ai_family);
155  freeaddrinfo(res);
156 
157  return fam;
158  }
159 
160  std::string vaddress::scope() const throw (scope_not_set)
161  {
162  if (_scope.length() == 0) throw scope_not_set();
163  return _scope;
164  }
165 
166  const std::string vaddress::address() const throw (address_not_set)
167  {
168  if (_address.length() == 0) throw address_not_set();
169  if (isAny()) throw address_not_set();
170  return _address;
171  }
172 
173  const std::string vaddress::name() const throw (address_exception)
174  {
175  struct addrinfo hints;
176  char addr_str[256];
177  struct addrinfo *res;
178  int ret = 0;
179 
180  memset(&hints, 0, sizeof(struct addrinfo));
181  hints.ai_family = PF_UNSPEC;
182  hints.ai_socktype = SOCK_STREAM;
183 
184  if ((ret = ::getaddrinfo(_address.c_str(), NULL, &hints, &res)) != 0)
185  {
186  throw address_exception("getaddrinfo(): " + std::string(gai_strerror(ret)));
187  }
188 
189  if ((ret = ::getnameinfo(res->ai_addr, res->ai_addrlen, (char*)&addr_str, 256, NULL, 256, NI_NAMEREQD | NI_NOFQDN)) != 0)
190  {
191  freeaddrinfo(res);
192  throw address_exception("getnameinfo(): " + std::string(gai_strerror(ret)));
193  }
194 
195  freeaddrinfo(res);
196 
197  return std::string(addr_str);
198  }
199 
200  const std::string vaddress::service() const throw (service_not_set)
201  {
202  if (_service.length() == 0) throw service_not_set();
203  return _service;
204  }
205 
206  void vaddress::setService(const uint32_t port)
207  {
208  std::stringstream ss;
209  ss << port;
210  _service = ss.str();
211  }
212 
213  void vaddress::setService(const std::string &service)
214  {
215  _service = service;
216  }
217 
218  const std::string vaddress::toString() const
219  {
220  std::stringstream ss;
221 
222  try {
223  try {
224  const std::string service = this->service();
225  const std::string address = this->address();
226  ss << "[" << address << "]:" + service;
227  } catch (const service_not_set&) {
228  ss << this->address();
229  }
230 
231  try {
232  const std::string scope = this->scope();
233  ss << " (" << scope << ")";
234  } catch (const scope_not_set&) { }
235  } catch (const address_not_set&) {
236  ss << "<any>";
237  try {
238  const std::string service = this->service();
239  ss << ":" + service;
240  } catch (const service_not_set&) { }
241  }
242 
243  return ss.str();
244  }
245 }