monotone

monotone Mtn Source Tree

Root/netxx/resolve_getaddrinfo.cxx

1/*
2 * Copyright (C) 2001-2004 Peter J Jones (pjones@pmade.org)
3 * All Rights Reserved
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in
13 * the documentation and/or other materials provided with the
14 * distribution.
15 * 3. Neither the name of the Author nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
23 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
26 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
29 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33/** @file
34 * This file contains the implementation of the resolve_hostname function
35 * using the getaddrinfo system call.
36**/
37
38// common header
39#include "common.h"
40
41// Netxx includes
42#include "resolve.h"
43#include "netxx/types.h"
44#include "sockaddr.h"
45
46// standard includes
47#include <cstring>
48
49#ifndef AF_UNSPEC
50# define AF_UNSPEC PF_UNSPEC
51#endif
52
53//####################################################################
54namespace
55{
56 struct auto_addrinfo
57 {
58explicit auto_addrinfo (addrinfo *in) : ai(in) { }
59~auto_addrinfo (void) { freeaddrinfo(ai); }
60addrinfo *ai;
61 }; // end auto_addrinfo
62}
63//####################################################################
64void Netxx::resolve_hostname (const char *hostname, port_type port, bool use_ipv6, std::vector<Peer> &addrs)
65{
66 addrinfo flags;
67 addrinfo *info;
68
69 std::memset(&flags, 0, sizeof(flags));
70
71 if (use_ipv6) flags.ai_family = AF_UNSPEC;
72 else flags.ai_family = AF_INET;
73 flags.ai_flags = AI_CANONNAME;
74#ifdef AI_ADDRCONFIG
75 flags.ai_flags |= AI_ADDRCONFIG;
76#endif
77
78 // FIXME: this is a local monotone hack; it appears that getaddrinfo
79 // will return datagram and stream addresses here, and we want to avoid
80 // that because we only use stream addresses. I wonder if the netxx
81 // maintainer knows this. hmm.
82 flags.ai_socktype = SOCK_STREAM;
83
84 int gai_error = getaddrinfo(hostname, 0, &flags, &info);
85
86 // Because we might compile on a computer that has AI_ADDRCONFIG and
87 // run on one that doesn't, we need to check for EAI_BADFLAGS, and
88 // try again without AI_ADDRCONFIG in that case.
89#ifdef AI_ADDRCONFIG
90 if (gai_error == EAI_BADFLAGS) {
91flags.ai_flags &= ~AI_ADDRCONFIG;
92gai_error = getaddrinfo(hostname, 0, &flags, &info);
93 }
94#endif
95
96 if (gai_error != 0) {
97std::string error("name resolution failure for "); error += hostname;
98error += ": "; error += gai_strerror(gai_error);
99throw NetworkException(error);
100 }
101
102 // auto clean up
103 auto_addrinfo ai(info);
104
105 const char *canonname;
106
107 for (; info != 0; info = info->ai_next) {
108canonname = info->ai_canonname ? info->ai_canonname : hostname;
109
110switch (info->ai_family) {
111 case AF_INET:
112 {
113SockAddr saddr(AF_INET, port);
114sockaddr_in *sai = reinterpret_cast<sockaddr_in*>(saddr.get_sa());
115std::memcpy(&(sai->sin_addr), &(reinterpret_cast<sockaddr_in*>(info->ai_addr)->sin_addr), sizeof(sai->sin_addr));
116addrs.push_back(Peer(canonname, port, sai, saddr.get_sa_size()));
117 }
118 break;
119
120# ifndef NETXX_NO_INET6
121 case AF_INET6:
122 {
123SockAddr saddr(AF_INET6, port);
124sockaddr_in6 *sai6 = reinterpret_cast<sockaddr_in6*>(saddr.get_sa());
125std::memcpy(&(sai6->sin6_addr), &(reinterpret_cast<sockaddr_in6*>(info->ai_addr)->sin6_addr), sizeof(sai6->sin6_addr));
126addrs.push_back(Peer(canonname, port, sai6, saddr.get_sa_size()));
127 }
128 break;
129# endif
130}
131 }
132}
133//####################################################################
134Netxx::port_type Netxx::resolve_service (const char *service)
135{
136 addrinfo flags;
137 addrinfo *info;
138
139 std::memset(&flags, 0, sizeof(flags));
140 flags.ai_family = AF_INET;
141
142 if (getaddrinfo(0, service, &flags, &info) != 0) {
143std::string error("service name resolution failed for: "); error += service;
144throw NetworkException(error);
145 }
146
147 auto_addrinfo ai(info);
148 return ntohs(reinterpret_cast<sockaddr_in*>(info->ai_addr)->sin_port);
149}
150//####################################################################

Archive Download this file

Branches

Tags

Quick Links:     www.monotone.ca    -     Downloads    -     Documentation    -     Wiki    -     Code Forge    -     Build Status