blob: 055ad414ccba1d9aa6798f1ccd4e62f6fbffedb9 [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
Nanang Izzuddin1ff605d2009-08-17 11:29:39 +000074#if !defined(PJ_HAS_IPV6) || !PJ_HAS_IPV6
75 if (af == PJ_AF_INET6)
76 return PJ_EIPV6NOTSUP;
77#endif
78
Nanang Izzuddin90b83202009-03-02 15:48:45 +000079 // Return failure if access point is marked as down by app.
80 PJ_SYMBIAN_CHECK_CONNECTION();
Nanang Izzuddin1ff605d2009-08-17 11:29:39 +000081
Benny Prijono62b86eb2007-12-01 08:52:57 +000082 // Get resolver for the specified address family
83 RHostResolver &resv = PjSymbianOS::Instance()->GetResolver(af);
Benny Prijonof260e462007-04-30 21:03:32 +000084
85 // Convert name to Unicode
86 wchar_t name16[PJ_MAX_HOSTNAME];
87 pj_ansi_to_unicode(name->ptr, name->slen, name16, PJ_ARRAY_SIZE(name16));
Benny Prijonoa0c8b5c2007-05-12 15:03:23 +000088 TPtrC16 data((const TUint16*)name16);
Benny Prijonof260e462007-04-30 21:03:32 +000089
90 // Resolve!
91 TNameEntry nameEntry;
92 TRequestStatus reqStatus;
93
94 resv.GetByName(data, nameEntry, reqStatus);
95 User::WaitForRequest(reqStatus);
96
Benny Prijono62b86eb2007-12-01 08:52:57 +000097 // Iterate each result
98 i = 0;
99 while (reqStatus == KErrNone && i < *count) {
100
Benny Prijono9db4bd62007-12-31 11:26:21 +0000101 // Get the resolved TInetAddr
102 TInetAddr inetAddr(nameEntry().iAddr);
103 int addrlen;
Benny Prijonof260e462007-04-30 21:03:32 +0000104
Benny Prijono9db4bd62007-12-31 11:26:21 +0000105#if TRACE_ME
106 if (1) {
107 pj_sockaddr a;
108 char ipaddr[PJ_INET6_ADDRSTRLEN+2];
109 int namelen;
110
111 namelen = sizeof(pj_sockaddr);
112 if (PjSymbianOS::Addr2pj(inetAddr, a, &namelen,
113 PJ_FALSE) == PJ_SUCCESS)
114 {
115 PJ_LOG(5,(THIS_FILE, "resolve %.*s: %s",
116 (int)name->slen, name->ptr,
117 pj_sockaddr_print(&a, ipaddr, sizeof(ipaddr), 2)));
118 }
119 }
120#endif
121
122 // Ignore if this is not the same address family
123 // Not a good idea, as Symbian mapps IPv4 to IPv6.
124 //fam = inetAddr.Family();
125 //if (fam != af) {
126 // resv.Next(nameEntry, reqStatus);
127 // User::WaitForRequest(reqStatus);
128 // continue;
129 //}
130
131 // Convert IP address first to get IPv4 mapped address
132 addrlen = sizeof(ai[i].ai_addr);
133 status = PjSymbianOS::Addr2pj(inetAddr, ai[i].ai_addr,
134 &addrlen, PJ_TRUE);
135 if (status != PJ_SUCCESS)
136 return status;
137
138 // Ignore if address family doesn't match
139 if (ai[i].ai_addr.addr.sa_family != af) {
140 resv.Next(nameEntry, reqStatus);
141 User::WaitForRequest(reqStatus);
142 continue;
143 }
Benny Prijono62b86eb2007-12-01 08:52:57 +0000144
Benny Prijono9db4bd62007-12-31 11:26:21 +0000145 // Convert the official address to ANSI.
146 pj_unicode_to_ansi((const wchar_t*)nameEntry().iName.Ptr(),
147 nameEntry().iName.Length(),
148 ai[i].ai_canonname, sizeof(ai[i].ai_canonname));
Benny Prijono62b86eb2007-12-01 08:52:57 +0000149
Benny Prijono9db4bd62007-12-31 11:26:21 +0000150 // Next
151 ++i;
152 resv.Next(nameEntry, reqStatus);
153 User::WaitForRequest(reqStatus);
Benny Prijonof260e462007-04-30 21:03:32 +0000154 }
155
Benny Prijono62b86eb2007-12-01 08:52:57 +0000156 *count = i;
157 return PJ_SUCCESS;
Benny Prijonof260e462007-04-30 21:03:32 +0000158}
159
Benny Prijono62b86eb2007-12-01 08:52:57 +0000160/* Resolve IPv4/IPv6 address */
161PJ_DEF(pj_status_t) pj_getaddrinfo(int af, const pj_str_t *nodename,
162 unsigned *count, pj_addrinfo ai[])
163{
164 unsigned start;
Benny Prijonoe11dbee2009-06-17 12:18:42 +0000165 pj_status_t status = PJ_EAFNOTSUP;
Benny Prijono62b86eb2007-12-01 08:52:57 +0000166
167 PJ_ASSERT_RETURN(af==PJ_AF_INET || af==PJ_AF_INET6 || af==PJ_AF_UNSPEC,
168 PJ_EAFNOTSUP);
169 PJ_ASSERT_RETURN(nodename && count && *count && ai, PJ_EINVAL);
170
171 start = 0;
172
173 if (af==PJ_AF_INET6 || af==PJ_AF_UNSPEC) {
174 unsigned max = *count;
175 status = getaddrinfo_by_af(PJ_AF_INET6, nodename,
176 &max, &ai[start]);
177 if (status == PJ_SUCCESS) {
178 (*count) -= max;
179 start += max;
180 }
181 }
182
183 if (af==PJ_AF_INET || af==PJ_AF_UNSPEC) {
184 unsigned max = *count;
185 status = getaddrinfo_by_af(PJ_AF_INET, nodename,
186 &max, &ai[start]);
187 if (status == PJ_SUCCESS) {
188 (*count) -= max;
189 start += max;
190 }
191 }
192
193 *count = start;
194
195 if (*count) {
196 return PJ_SUCCESS;
197 } else {
198 return status!=PJ_SUCCESS ? status : PJ_ENOTFOUND;
199 }
200}
Benny Prijonof260e462007-04-30 21:03:32 +0000201