blob: cfd8aa5d34e1252f29e546a92e82763f2834b61b [file] [log] [blame]
Benny Prijonof260e462007-04-30 21:03:32 +00001/* $Id$ */
2/*
Benny Prijono844653c2008-12-23 17:27:53 +00003 * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
Benny Prijonof260e462007-04-30 21:03:32 +00005 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20#include <pj/addr_resolv.h>
21#include <pj/assert.h>
22#include <pj/errno.h>
Benny Prijono4c8fb532007-11-26 05:36:18 +000023#include <pj/ip_helper.h>
Benny Prijono9db4bd62007-12-31 11:26:21 +000024#include <pj/log.h>
Benny Prijono4c8fb532007-11-26 05:36:18 +000025#include <pj/sock.h>
Benny Prijonof260e462007-04-30 21:03:32 +000026#include <pj/string.h>
27#include <pj/unicode.h>
28
29#include "os_symbian.h"
30
Benny Prijono9db4bd62007-12-31 11:26:21 +000031#define THIS_FILE "addr_resolv_symbian.cpp"
32#define TRACE_ME 0
Benny Prijonof260e462007-04-30 21:03:32 +000033
Benny Prijono62b86eb2007-12-01 08:52:57 +000034
Benny Prijonof260e462007-04-30 21:03:32 +000035// PJLIB API: resolve hostname
36PJ_DEF(pj_status_t) pj_gethostbyname(const pj_str_t *name, pj_hostent *he)
37{
Benny Prijono62b86eb2007-12-01 08:52:57 +000038 static pj_addrinfo ai;
39 static char *aliases[2];
40 static char *addrlist[2];
41 unsigned count = 1;
42 pj_status_t status;
43
44 status = pj_getaddrinfo(PJ_AF_INET, name, &count, &ai);
45 if (status != PJ_SUCCESS)
46 return status;
47
48 aliases[0] = ai.ai_canonname;
49 aliases[1] = NULL;
50
51 addrlist[0] = (char*) &ai.ai_addr.ipv4.sin_addr;
52 addrlist[1] = NULL;
53
54 pj_bzero(he, sizeof(*he));
55 he->h_name = aliases[0];
56 he->h_aliases = aliases;
57 he->h_addrtype = PJ_AF_INET;
58 he->h_length = 4;
59 he->h_addr_list = addrlist;
60
61 return PJ_SUCCESS;
62}
Benny Prijonof260e462007-04-30 21:03:32 +000063
Benny Prijono62b86eb2007-12-01 08:52:57 +000064
65// Resolve for specific address family
66static pj_status_t getaddrinfo_by_af(int af, const pj_str_t *name,
67 unsigned *count, pj_addrinfo ai[])
68{
69 unsigned i;
70 pj_status_t status;
71
72 PJ_ASSERT_RETURN(name && count && ai, PJ_EINVAL);
73
74 // Get resolver for the specified address family
75 RHostResolver &resv = PjSymbianOS::Instance()->GetResolver(af);
Benny Prijonof260e462007-04-30 21:03:32 +000076
77 // Convert name to Unicode
78 wchar_t name16[PJ_MAX_HOSTNAME];
79 pj_ansi_to_unicode(name->ptr, name->slen, name16, PJ_ARRAY_SIZE(name16));
Benny Prijonoa0c8b5c2007-05-12 15:03:23 +000080 TPtrC16 data((const TUint16*)name16);
Benny Prijonof260e462007-04-30 21:03:32 +000081
82 // Resolve!
83 TNameEntry nameEntry;
84 TRequestStatus reqStatus;
85
86 resv.GetByName(data, nameEntry, reqStatus);
87 User::WaitForRequest(reqStatus);
88
Benny Prijono62b86eb2007-12-01 08:52:57 +000089 // Iterate each result
90 i = 0;
91 while (reqStatus == KErrNone && i < *count) {
92
Benny Prijono9db4bd62007-12-31 11:26:21 +000093 // Get the resolved TInetAddr
94 TInetAddr inetAddr(nameEntry().iAddr);
95 int addrlen;
Benny Prijonof260e462007-04-30 21:03:32 +000096
Benny Prijono9db4bd62007-12-31 11:26:21 +000097#if TRACE_ME
98 if (1) {
99 pj_sockaddr a;
100 char ipaddr[PJ_INET6_ADDRSTRLEN+2];
101 int namelen;
102
103 namelen = sizeof(pj_sockaddr);
104 if (PjSymbianOS::Addr2pj(inetAddr, a, &namelen,
105 PJ_FALSE) == PJ_SUCCESS)
106 {
107 PJ_LOG(5,(THIS_FILE, "resolve %.*s: %s",
108 (int)name->slen, name->ptr,
109 pj_sockaddr_print(&a, ipaddr, sizeof(ipaddr), 2)));
110 }
111 }
112#endif
113
114 // Ignore if this is not the same address family
115 // Not a good idea, as Symbian mapps IPv4 to IPv6.
116 //fam = inetAddr.Family();
117 //if (fam != af) {
118 // resv.Next(nameEntry, reqStatus);
119 // User::WaitForRequest(reqStatus);
120 // continue;
121 //}
122
123 // Convert IP address first to get IPv4 mapped address
124 addrlen = sizeof(ai[i].ai_addr);
125 status = PjSymbianOS::Addr2pj(inetAddr, ai[i].ai_addr,
126 &addrlen, PJ_TRUE);
127 if (status != PJ_SUCCESS)
128 return status;
129
130 // Ignore if address family doesn't match
131 if (ai[i].ai_addr.addr.sa_family != af) {
132 resv.Next(nameEntry, reqStatus);
133 User::WaitForRequest(reqStatus);
134 continue;
135 }
Benny Prijono62b86eb2007-12-01 08:52:57 +0000136
Benny Prijono9db4bd62007-12-31 11:26:21 +0000137 // Convert the official address to ANSI.
138 pj_unicode_to_ansi((const wchar_t*)nameEntry().iName.Ptr(),
139 nameEntry().iName.Length(),
140 ai[i].ai_canonname, sizeof(ai[i].ai_canonname));
Benny Prijono62b86eb2007-12-01 08:52:57 +0000141
Benny Prijono9db4bd62007-12-31 11:26:21 +0000142 // Next
143 ++i;
144 resv.Next(nameEntry, reqStatus);
145 User::WaitForRequest(reqStatus);
Benny Prijonof260e462007-04-30 21:03:32 +0000146 }
147
Benny Prijono62b86eb2007-12-01 08:52:57 +0000148 *count = i;
149 return PJ_SUCCESS;
Benny Prijonof260e462007-04-30 21:03:32 +0000150}
151
Benny Prijono62b86eb2007-12-01 08:52:57 +0000152/* Resolve IPv4/IPv6 address */
153PJ_DEF(pj_status_t) pj_getaddrinfo(int af, const pj_str_t *nodename,
154 unsigned *count, pj_addrinfo ai[])
155{
156 unsigned start;
157 pj_status_t status;
158
159 PJ_ASSERT_RETURN(af==PJ_AF_INET || af==PJ_AF_INET6 || af==PJ_AF_UNSPEC,
160 PJ_EAFNOTSUP);
161 PJ_ASSERT_RETURN(nodename && count && *count && ai, PJ_EINVAL);
162
163 start = 0;
164
165 if (af==PJ_AF_INET6 || af==PJ_AF_UNSPEC) {
166 unsigned max = *count;
167 status = getaddrinfo_by_af(PJ_AF_INET6, nodename,
168 &max, &ai[start]);
169 if (status == PJ_SUCCESS) {
170 (*count) -= max;
171 start += max;
172 }
173 }
174
175 if (af==PJ_AF_INET || af==PJ_AF_UNSPEC) {
176 unsigned max = *count;
177 status = getaddrinfo_by_af(PJ_AF_INET, nodename,
178 &max, &ai[start]);
179 if (status == PJ_SUCCESS) {
180 (*count) -= max;
181 start += max;
182 }
183 }
184
185 *count = start;
186
187 if (*count) {
188 return PJ_SUCCESS;
189 } else {
190 return status!=PJ_SUCCESS ? status : PJ_ENOTFOUND;
191 }
192}
Benny Prijonof260e462007-04-30 21:03:32 +0000193