glib_compat.h: remove obsolete header
[ncmpc.git] / src / resolver.c
blob6363bc8ea15b0b31500cd9c7004a8e591e68f2cf
1 /* libmpdclient
2 (c) 2008 Max Kellermann <max@duempel.org>
3 This project's homepage is: http://www.musicpd.org
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
9 - Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
12 - Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
16 - Neither the name of the Music Player Daemon nor the names of its
17 contributors may be used to endorse or promote products derived from
18 this software without specific prior written permission.
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
24 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #include "config.h"
34 #include "resolver.h"
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
40 #ifdef WIN32
41 # include <ws2tcpip.h>
42 # include <winsock.h>
43 #else
44 # include <netdb.h>
45 # include <netinet/in.h>
46 # include <arpa/inet.h>
47 # include <sys/socket.h>
48 # include <sys/un.h>
49 # include <netdb.h>
50 #endif
52 #ifndef MPD_NO_GAI
53 # ifdef AI_ADDRCONFIG
54 # define MPD_HAVE_GAI
55 # endif
56 #endif
58 struct resolver {
59 enum {
60 TYPE_ZERO, TYPE_ONE, TYPE_ANY
61 } type;
63 #ifdef MPD_HAVE_GAI
64 struct addrinfo *ai;
65 const struct addrinfo *next;
66 #else
67 struct sockaddr_in sin;
68 #endif
70 struct resolver_address current;
72 #ifndef WIN32
73 struct sockaddr_un saun;
74 #endif
77 struct resolver *
78 resolver_new(const char *host, int port)
80 struct resolver *resolver;
82 resolver = malloc(sizeof(*resolver));
83 if (resolver == NULL)
84 return NULL;
86 #ifndef WIN32
87 if (host[0] == '/') {
88 size_t path_length = strlen(host);
89 if (path_length >= sizeof(resolver->saun.sun_path)) {
90 free(resolver);
91 return NULL;
94 resolver->saun.sun_family = AF_UNIX;
95 memcpy(resolver->saun.sun_path, host, path_length + 1);
97 resolver->current.family = PF_UNIX;
98 resolver->current.protocol = 0;
99 resolver->current.addrlen = sizeof(resolver->saun);
100 resolver->current.addr = (const struct sockaddr *)&resolver->saun;
101 resolver->type = TYPE_ONE;
102 } else {
103 #endif
104 #ifdef MPD_HAVE_GAI
105 struct addrinfo hints;
106 char service[20];
107 int ret;
109 memset(&hints, 0, sizeof(hints));
110 hints.ai_flags = AI_ADDRCONFIG;
111 hints.ai_family = PF_UNSPEC;
112 hints.ai_socktype = SOCK_STREAM;
113 hints.ai_protocol = IPPROTO_TCP;
115 snprintf(service, sizeof(service), "%d", port);
117 ret = getaddrinfo(host, service, &hints, &resolver->ai);
118 if (ret != 0) {
119 free(resolver);
120 return NULL;
123 resolver->next = resolver->ai;
124 resolver->type = TYPE_ANY;
125 #else
126 const struct hostent *he;
128 he = gethostbyname(host);
129 if (he == NULL) {
130 free(resolver);
131 return NULL;
134 if (he->h_addrtype != AF_INET) {
135 free(resolver);
136 return NULL;
140 memset(&resolver->sin, 0, sizeof(resolver->sin));
141 resolver->sin.sin_family = AF_INET;
142 resolver->sin.sin_port = htons(port);
143 memcpy((char *)&resolver->sin.sin_addr.s_addr,
144 (char *)he->h_addr, he->h_length);
146 resolver->current.family = PF_INET;
147 resolver->current.protocol = 0;
148 resolver->current.addrlen = sizeof(resolver->sin);
149 resolver->current.addr = (const struct sockaddr *)&resolver->sin;
151 resolver->type = TYPE_ONE;
152 #endif
153 #ifndef WIN32
155 #endif
157 return resolver;
160 void
161 resolver_free(struct resolver *resolver)
163 #ifdef MPD_HAVE_GAI
164 if (resolver->type == TYPE_ANY)
165 freeaddrinfo(resolver->ai);
166 #endif
167 free(resolver);
170 const struct resolver_address *
171 resolver_next(struct resolver *resolver)
173 if (resolver->type == TYPE_ZERO)
174 return NULL;
176 if (resolver->type == TYPE_ONE) {
177 resolver->type = TYPE_ZERO;
178 return &resolver->current;
181 #ifdef MPD_HAVE_GAI
182 if (resolver->next == NULL)
183 return NULL;
185 resolver->current.family = resolver->next->ai_family;
186 resolver->current.protocol = resolver->next->ai_protocol;
187 resolver->current.addrlen = resolver->next->ai_addrlen;
188 resolver->current.addr = resolver->next->ai_addr;
190 resolver->next = resolver->next->ai_next;
192 return &resolver->current;
193 #else
194 return NULL;
195 #endif