CPN
Computational Process Networks
SocketAddress.cc
Go to the documentation of this file.
1 //=============================================================================
2 // Computational Process Networks class library
3 // Copyright (C) 1997-2006 Gregory E. Allen and The University of Texas
4 //
5 // This library is free software; you can redistribute it and/or modify it
6 // under the terms of the GNU Library General Public License as published
7 // by the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Library General Public License for more details.
14 //
15 // The GNU Public License is available in the file LICENSE, or you
16 // can write to the Free Software Foundation, Inc., 59 Temple Place -
17 // Suite 330, Boston, MA 02111-1307, USA, or you can find it on the
18 // World Wide Web at http://www.fsf.org.
19 //=============================================================================
23 #include "common_priv.h"
24 #include <cpn/io/SocketAddress.h>
27 #include <string.h>
28 #include <netdb.h>
29 #include <sstream>
30 #include <err.h>
31 #include <errno.h>
32 
34  : length(0)
35 {
36  memset(&address, 0, sizeof(address));
37 }
38 
39 SockAddrList SocketAddress::Lookup(const char* const hostname, const char* const port,
40  int family, unsigned portnum) {
41  addrinfo hints = {0};
42  // Get only supported types.
43  hints.ai_flags = AI_ADDRCONFIG;
44  hints.ai_family = family;
45  hints.ai_socktype = SOCK_STREAM;
46  if (0 == hostname || *hostname == '\0') {
47  hints.ai_flags |= AI_PASSIVE;
48  }
49  addrinfo *res = 0;
50  int lookupstatus = 0;
51  do {
52  lookupstatus = getaddrinfo(hostname, port, &hints, &res);
53  switch (lookupstatus) {
54  case EAI_AGAIN:
55  // try again
56  case EAI_MEMORY:
57  // our of memory, try again?
58  case 0:
59  // Success.
60  break;
61  case EAI_ADDRFAMILY:
62  case EAI_BADFLAGS:
63  case EAI_FAIL:
64  case EAI_FAMILY:
65  case EAI_NODATA:
66  case EAI_NONAME:
67  case EAI_SERVICE:
68  case EAI_SOCKTYPE:
69  case EAI_SYSTEM:
70  default:
71  throw ErrnoException(gai_strerror(lookupstatus), lookupstatus);
72  }
73  } while (lookupstatus != 0);
74 
75  SockAddrList results;
76  for (addrinfo *rp = res; rp != 0; rp = rp->ai_next) {
77  if (port) {
78  results.push_back(SocketAddress(rp));
79  } else {
80  results.push_back(SocketAddress(rp, portnum));
81  }
82  }
83  freeaddrinfo(res);
84  return results;
85 }
86 
88  return Lookup(0, servname, AF_UNSPEC, 0);
89 }
90 
91 SockAddrList SocketAddress::CreateIPFromServ(const std::string &servname) {
92  return Lookup(0, servname.c_str(), AF_UNSPEC, 0);
93 }
94 
96  return Lookup(hostname, 0, AF_UNSPEC, 0);
97 }
98 
99 SockAddrList SocketAddress::CreateIPFromHost(const std::string &hostname) {
100  return Lookup(hostname.c_str(), 0, AF_UNSPEC, 0);
101 }
102 
104  SocketAddress addr;
105  addr.Family() = AF_INET;
106  addr.address.in.sin_port = htons(serv);
107  addr.address.in.sin_addr.s_addr = INADDR_ANY;
108  addr.length = sizeof(sockaddr_in);
109  SockAddrList list;
110  list.push_back(addr);
111  return list;
112 }
113 
114 SockAddrList SocketAddress::CreateIP(const char* hostname, const char* servname) {
115  return Lookup(hostname, servname, AF_UNSPEC, 0);
116 }
117 
118 SockAddrList SocketAddress::CreateIP(const std::string &hostname, const std::string &servname) {
119  return Lookup(hostname.c_str(), servname.c_str(), AF_UNSPEC, 0);
120 }
121 
122 SockAddrList SocketAddress::CreateIP(const char *hostname, unsigned serv) {
123  return Lookup(hostname, 0, AF_UNSPEC, serv);
124 }
125 
126 SockAddrList SocketAddress::CreateIP(const std::string &hostname, unsigned serv) {
127  return Lookup(hostname.c_str(), 0, AF_UNSPEC, serv);
128 }
129 
130 SockAddrList SocketAddress::CreateIP(const std::string &hostname) {
131  std::string host;
132  std::string port;
133  std::string::const_iterator it, e;
134  e = hostname.end();
135  it = hostname.begin();
136  bool in_address = false;
137  bool at_port = false;
138  while (it != e) {
139  if (in_address) {
140  if (*it == ']') {
141  in_address = false;
142  } else {
143  host.push_back(*it);
144  }
145  }
146  if (at_port) {
147  port.push_back(*it);
148  } else {
149  switch (*it) {
150  case '[':
151  in_address = true;
152  break;
153  case ':':
154  at_port = true;
155  break;
156  default:
157  host.push_back(*it);
158  break;
159  }
160  }
161  ++it;
162  }
163  const char *h = 0;
164  const char *p = 0;
165  if (!host.empty()) {
166  h = host.c_str();
167  }
168  if (!port.empty()) {
169  p = port.c_str();
170  }
171  return Lookup(h, p, AF_UNSPEC, 0);
172 }
173 
175  length = info->ai_addrlen;
176  memcpy(&address, info->ai_addr, length);
177 }
178 
179 SocketAddress::SocketAddress(addrinfo *info, unsigned portnum) {
180  length = info->ai_addrlen;
181  memcpy(&address, info->ai_addr, length);
182  uint16_t port = (uint16_t)portnum;
183  port = htons(port);
184  switch (Family()) {
185  case AF_INET:
186  address.in.sin_port = port;
187  break;
188  case AF_INET6:
189  address.in6.sin6_port = port;
190  break;
191  default:
192  break;
193  }
194 }
195 
196 SocketAddress::SocketAddress(sockaddr *addr, socklen_t len) {
197  memcpy(&address, addr, len);
198  length = len;
199 }
200 
201 std::string SocketAddress::GetHostName(bool numerichost) const {
202  std::vector<char> hostname(NI_MAXHOST, '\0');
203  bool loop = true;
204  std::ostringstream oss;
205  while (loop) {
206  int flags = NI_NUMERICSERV;
207  if (numerichost) { flags |= NI_NUMERICHOST; }
208  int lookupstatus = getnameinfo(&address.addr, length,
209  &hostname[0], hostname.size(),
210  0, 0,
211  flags);
212  switch (lookupstatus) {
213  case 0:
214  oss << &hostname[0];
215  loop = false;
216  break;
217  case EAI_AGAIN:
218  break;
219 #if !defined(__APPLE__)
220  case EAI_OVERFLOW:
221  hostname.resize(hostname.size()*2, '\0');
222  break;
223 #endif
224  case EAI_BADFLAGS:
225  case EAI_FAIL:
226  case EAI_FAMILY:
227  case EAI_MEMORY:
228  case EAI_NONAME:
229  case EAI_SYSTEM:
230  default:
231  throw ErrnoException(gai_strerror(lookupstatus), lookupstatus);
232  }
233  }
234  return oss.str();
235 }
236 
237 std::string SocketAddress::GetServName() const {
238  std::vector<char> servname(NI_MAXSERV, '\0');
239  bool loop = true;
240  std::ostringstream oss;
241  while (loop) {
242  int lookupstatus = getnameinfo(&address.addr, length,
243  0, 0,
244  &servname[0], servname.size(),
245  NI_NUMERICSERV);
246  switch (lookupstatus) {
247  case 0:
248  oss << &servname[0];
249  loop = false;
250  break;
251  case EAI_AGAIN:
252  break;
253 #if !defined(__APPLE__)
254  case EAI_OVERFLOW:
255  servname.resize(servname.size()*2, '\0');
256  break;
257 #endif
258  case EAI_BADFLAGS:
259  case EAI_FAIL:
260  case EAI_FAMILY:
261  case EAI_MEMORY:
262  case EAI_NONAME:
263  case EAI_SYSTEM:
264  default:
265  throw ErrnoException(gai_strerror(lookupstatus), lookupstatus);
266  }
267  }
268  return oss.str();
269 }
270 
271 unsigned SocketAddress::GetServ() const {
272  uint16_t retval = 0;
273  switch (Family()) {
274  case AF_INET:
275  retval = address.in.sin_port;
276  break;
277  case AF_INET6:
278  retval = address.in6.sin6_port;
279  break;
280  default:
281  break;
282  }
283  return (unsigned)ntohs(retval);
284 }
285 
287  Type_t type;
288  switch (Family()) {
289  case AF_INET:
290  type = IPV4;
291  break;
292  case AF_INET6:
293  type = IPV6;
294  break;
295  case AF_UNIX:
296  type = LOCAL;
297  break;
298  default:
299  ASSERT(false, "Unknown address type.");
300  }
301  return type;
302 }
303 
305  GetLen() = sizeof(sockaddr_storage);
306  if (getsockname(fd, GetAddr(), &GetLen()) != 0) {
307  throw ErrnoException();
308  }
309 }
310 
312  GetLen() = sizeof(sockaddr_storage);
313  if (getpeername(fd, GetAddr(), &GetLen()) != 0) {
314  throw ErrnoException();
315  }
316 }
317 
318 
static SockAddrList Lookup(const char *const hostname, const char *const port, int family, unsigned portnum)
An abstraction of a socket address with convenience methods.
Definition: SocketAddress.h:42
socklen_t & GetLen()
unsigned GetServ() const
std::string GetHostName(bool numerichost=true) const
void SetFromPeerName(int fd)
Fill this SocketAddress with data from the other side of the connection represented by fd...
Type_t GetType() const
socklen_t length
static SockAddrList CreateIPFromServ(const char *servname)
Return a list of valid socket addresses for the given service name All CreateIP functions create IP a...
sa_family_t & Family()
sockaddr * GetAddr()
void SetFromSockName(int fd)
Fill this SocketAddress with data from this side of the connection represented by fd...
std::string GetServName() const
static SockAddrList CreateIPFromHost(const char *hostname)
static SockAddrList CreateIP(unsigned serv)
Return a list of valid socket address for the given service number or port number.
std::vector< SocketAddress > SockAddrList
Definition: SocketAddress.h:35
union SocketAddress::address_ address
#define ASSERT(exp,...)