Code

po: updated Russian translation
[ncmpc.git] / src / resolver.c
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.
31 */
33 #include "resolver.h"
35 #include <netdb.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 <netinet/in.h>
45 #  include <arpa/inet.h>
46 #  include <sys/socket.h>
47 #  include <sys/un.h>
48 #  include <netdb.h>
49 #endif
51 #ifndef MPD_NO_GAI
52 #  ifdef AI_ADDRCONFIG
53 #    define MPD_HAVE_GAI
54 #  endif
55 #endif
57 struct resolver {
58         enum {
59                 TYPE_ZERO, TYPE_ONE, TYPE_ANY
60         } type;
62 #ifdef MPD_HAVE_GAI
63         struct addrinfo *ai;
64         const struct addrinfo *next;
65 #else
66         struct sockaddr_in sin;
67 #endif
69         struct resolver_address current;
71 #ifndef WIN32
72         struct sockaddr_un saun;
73 #endif
74 };
76 struct resolver *
77 resolver_new(const char *host, int port)
78 {
79         struct resolver *resolver;
81         resolver = malloc(sizeof(*resolver));
82         if (resolver == NULL)
83                 return NULL;
85 #ifndef WIN32
86         if (host[0] == '/') {
87                 size_t path_length = strlen(host);
88                 if (path_length >= sizeof(resolver->saun.sun_path)) {
89                         free(resolver);
90                         return NULL;
91                 }
93                 resolver->saun.sun_family = AF_UNIX;
94                 memcpy(resolver->saun.sun_path, host, path_length + 1);
96                 resolver->current.family = PF_UNIX;
97                 resolver->current.protocol = 0;
98                 resolver->current.addrlen = sizeof(resolver->saun);
99                 resolver->current.addr = (const struct sockaddr *)&resolver->saun;
100                 resolver->type = TYPE_ONE;
101         } else {
102 #endif
103 #ifdef MPD_HAVE_GAI
104                 struct addrinfo hints;
105                 char service[20];
106                 int ret;
108                 memset(&hints, 0, sizeof(hints));
109                 hints.ai_flags = AI_ADDRCONFIG;
110                 hints.ai_family = PF_UNSPEC;
111                 hints.ai_socktype = SOCK_STREAM;
112                 hints.ai_protocol = IPPROTO_TCP;
114                 snprintf(service, sizeof(service), "%d", port);
116                 ret = getaddrinfo(host, service, &hints, &resolver->ai);
117                 if (ret != 0) {
118                         free(resolver);
119                         return NULL;
120                 }
122                 resolver->next = resolver->ai;
123                 resolver->type = TYPE_ANY;
124 #else
125                 const struct hostent *he;
127                 he = gethostbyname(host);
128                 if (he == NULL) {
129                         free(resolver);
130                         return NULL;
131                 }
133                 if (he->h_addrtype != AF_INET) {
134                         free(resolver);
135                         return NULL;
136                 }
139                 memset(&resolver->sin, 0, sizeof(resolver->sin));
140                 resolver->sin.sin_family = AF_INET;
141                 resolver->sin.sin_port = htons(port);
142                 memcpy((char *)&resolver->sin.sin_addr.s_addr,
143                        (char *)he->h_addr, he->h_length);
145                 resolver->current.family = PF_INET;
146                 resolver->current.protocol = 0;
147                 resolver->current.addrlen = sizeof(resolver->sin);
148                 resolver->current.addr = (const struct sockaddr *)&resolver->sin;
150                 resolver->type = TYPE_ONE;
151 #endif
152 #ifndef WIN32
153         }
154 #endif
156         return resolver;
159 void
160 resolver_free(struct resolver *resolver)
162 #ifdef MPD_HAVE_GAI
163         if (resolver->type == TYPE_ANY)
164                 freeaddrinfo(resolver->ai);
165 #endif
166         free(resolver);
169 const struct resolver_address *
170 resolver_next(struct resolver *resolver)
172         if (resolver->type == TYPE_ZERO)
173                 return NULL;
175         if (resolver->type == TYPE_ONE) {
176                 resolver->type = TYPE_ZERO;
177                 return &resolver->current;
178         }
180 #ifdef MPD_HAVE_GAI
181         if (resolver->next == NULL)
182                 return NULL;
184         resolver->current.family = resolver->next->ai_family;
185         resolver->current.protocol = resolver->next->ai_protocol;
186         resolver->current.addrlen = resolver->next->ai_addrlen;
187         resolver->current.addr = resolver->next->ai_addr;
189         resolver->next = resolver->next->ai_next;
191         return &resolver->current;
192 #else
193         return NULL;
194 #endif