blob: fbca108553cbd0cbfe9999c469e611c0c3f8e8cd [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 Izzuddin90b83202009-03-02 15:48:45 +000074 // Return failure if access point is marked as down by app.
75 PJ_SYMBIAN_CHECK_CONNECTION();
76
Benny Prijono62b86eb2007-12-01 08:52:57 +000077 // Get resolver for the specified address family
78 RHostResolver &resv = PjSymbianOS::Instance()->GetResolver(af);
Benny Prijonof260e462007-04-30 21:03:32 +000079
80 // Convert name to Unicode
81 wchar_t name16[PJ_MAX_HOSTNAME];
82 pj_ansi_to_unicode(name->ptr, name->slen, name16, PJ_ARRAY_SIZE(name16));
Benny Prijonoa0c8b5c2007-05-12 15:03:23 +000083 TPtrC16 data((const TUint16*)name16);
Benny Prijonof260e462007-04-30 21:03:32 +000084
85 // Resolve!
86 TNameEntry nameEntry;
87 TRequestStatus reqStatus;
88
89 resv.GetByName(data, nameEntry, reqStatus);
90 User::WaitForRequest(reqStatus);
91
Benny Prijono62b86eb2007-12-01 08:52:57 +000092 // Iterate each result
93 i = 0;
94 while (reqStatus == KErrNone && i < *count) {
95
Benny Prijono9db4bd62007-12-31 11:26:21 +000096 // Get the resolved TInetAddr
97 TInetAddr inetAddr(nameEntry().iAddr);
98 int addrlen;
Benny Prijonof260e462007-04-30 21:03:32 +000099
Benny Prijono9db4bd62007-12-31 11:26:21 +0000100#if TRACE_ME
101 if (1) {
102 pj_sockaddr a;
103 char ipaddr[PJ_INET6_ADDRSTRLEN+2];
104 int namelen;
105
106 namelen = sizeof(pj_sockaddr);
107 if (PjSymbianOS::Addr2pj(inetAddr, a, &namelen,
108 PJ_FALSE) == PJ_SUCCESS)
109 {
110 PJ_LOG(5,(THIS_FILE, "resolve %.*s: %s",
111 (int)name->slen, name->ptr,
112 pj_sockaddr_print(&a, ipaddr, sizeof(ipaddr), 2)));
113 }
114 }
115#endif
116
117 // Ignore if this is not the same address family
118 // Not a good idea, as Symbian mapps IPv4 to IPv6.
119 //fam = inetAddr.Family();
120 //if (fam != af) {
121 // resv.Next(nameEntry, reqStatus);
122 // User::WaitForRequest(reqStatus);
123 // continue;
124 //}
125
126 // Convert IP address first to get IPv4 mapped address
127 addrlen = sizeof(ai[i].ai_addr);
128 status = PjSymbianOS::Addr2pj(inetAddr, ai[i].ai_addr,
129 &addrlen, PJ_TRUE);
130 if (status != PJ_SUCCESS)
131 return status;
132
133 // Ignore if address family doesn't match
134 if (ai[i].ai_addr.addr.sa_family != af) {
135 resv.Next(nameEntry, reqStatus);
136 User::WaitForRequest(reqStatus);
137 continue;
138 }
Benny Prijono62b86eb2007-12-01 08:52:57 +0000139
Benny Prijono9db4bd62007-12-31 11:26:21 +0000140 // Convert the official address to ANSI.
141 pj_unicode_to_ansi((const wchar_t*)nameEntry().iName.Ptr(),
142 nameEntry().iName.Length(),
143 ai[i].ai_canonname, sizeof(ai[i].ai_canonname));
Benny Prijono62b86eb2007-12-01 08:52:57 +0000144
Benny Prijono9db4bd62007-12-31 11:26:21 +0000145 // Next
146 ++i;
147 resv.Next(nameEntry, reqStatus);
148 User::WaitForRequest(reqStatus);
Benny Prijonof260e462007-04-30 21:03:32 +0000149 }
150
Benny Prijono62b86eb2007-12-01 08:52:57 +0000151 *count = i;
152 return PJ_SUCCESS;
Benny Prijonof260e462007-04-30 21:03:32 +0000153}
154
Benny Prijono62b86eb2007-12-01 08:52:57 +0000155/* Resolve IPv4/IPv6 address */
156PJ_DEF(pj_status_t) pj_getaddrinfo(int af, const pj_str_t *nodename,
157 unsigned *count, pj_addrinfo ai[])
158{
159 unsigned start;
160 pj_status_t status;
161
162 PJ_ASSERT_RETURN(af==PJ_AF_INET || af==PJ_AF_INET6 || af==PJ_AF_UNSPEC,
163 PJ_EAFNOTSUP);
164 PJ_ASSERT_RETURN(nodename && count && *count && ai, PJ_EINVAL);
165
166 start = 0;
167
168 if (af==PJ_AF_INET6 || af==PJ_AF_UNSPEC) {
169 unsigned max = *count;
170 status = getaddrinfo_by_af(PJ_AF_INET6, nodename,
171 &max, &ai[start]);
172 if (status == PJ_SUCCESS) {
173 (*count) -= max;
174 start += max;
175 }
176 }
177
178 if (af==PJ_AF_INET || af==PJ_AF_UNSPEC) {
179 unsigned max = *count;
180 status = getaddrinfo_by_af(PJ_AF_INET, nodename,
181 &max, &ai[start]);
182 if (status == PJ_SUCCESS) {
183 (*count) -= max;
184 start += max;
185 }
186 }
187
188 *count = start;
189
190 if (*count) {
191 return PJ_SUCCESS;
192 } else {
193 return status!=PJ_SUCCESS ? status : PJ_ENOTFOUND;
194 }
195}
Benny Prijonof260e462007-04-30 21:03:32 +0000196