blob: 496c1f8bec70f903b76bbaf0fd4faeffc173e38f [file] [log] [blame]
Benny Prijonof260e462007-04-30 21:03:32 +00001/* $Id$ */
2/*
3 * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19#include <pj/addr_resolv.h>
20#include <pj/assert.h>
21#include <pj/errno.h>
Benny Prijono4c8fb532007-11-26 05:36:18 +000022#include <pj/ip_helper.h>
23#include <pj/sock.h>
Benny Prijonof260e462007-04-30 21:03:32 +000024#include <pj/string.h>
25#include <pj/unicode.h>
26
27#include "os_symbian.h"
28
29
30// PJLIB API: resolve hostname
31PJ_DEF(pj_status_t) pj_gethostbyname(const pj_str_t *name, pj_hostent *he)
32{
33 PJ_ASSERT_RETURN(name && he, PJ_EINVAL);
34
35 RHostResolver &resv = PjSymbianOS::Instance()->GetResolver();
36
37 // Convert name to Unicode
38 wchar_t name16[PJ_MAX_HOSTNAME];
39 pj_ansi_to_unicode(name->ptr, name->slen, name16, PJ_ARRAY_SIZE(name16));
Benny Prijonoa0c8b5c2007-05-12 15:03:23 +000040 TPtrC16 data((const TUint16*)name16);
Benny Prijonof260e462007-04-30 21:03:32 +000041
42 // Resolve!
43 TNameEntry nameEntry;
44 TRequestStatus reqStatus;
45
46 resv.GetByName(data, nameEntry, reqStatus);
47 User::WaitForRequest(reqStatus);
48
49 if (reqStatus != KErrNone)
50 return PJ_RETURN_OS_ERROR(reqStatus.Int());
51
52 // Get the resolved TInetAddr
53 // This doesn't work, see Martin email on 28/3/2007:
54 // const TNameRecord &rec = (const TNameRecord&) nameEntry;
55 // TInetAddr inetAddr(rec.iAddr);
56 TInetAddr inetAddr(nameEntry().iAddr);
57
58 //
59 // This where we keep static variables.
60 // These should be kept in TLS probably, to allow multiple threads
61 // to call pj_gethostbyname() without interfering each other.
62 // But again, we don't support threads in Symbian!
63 //
64 static char resolved_name[PJ_MAX_HOSTNAME];
65 static char *no_aliases[1];
66 static pj_in_addr *addr_list[2];
67 static pj_sockaddr_in resolved_addr;
68
69 // Convert the official address to ANSI.
Benny Prijonoa0c8b5c2007-05-12 15:03:23 +000070 pj_unicode_to_ansi((const wchar_t*)nameEntry().iName.Ptr(), nameEntry().iName.Length(),
Benny Prijonof260e462007-04-30 21:03:32 +000071 resolved_name, sizeof(resolved_name));
72
73 // Convert IP address
74
75 PjSymbianOS::Addr2pj(inetAddr, resolved_addr);
76 addr_list[0] = &resolved_addr.sin_addr;
77
78 // Return hostent
79 he->h_name = resolved_name;
80 he->h_aliases = no_aliases;
Benny Prijono8ab968f2007-07-20 08:08:30 +000081 he->h_addrtype = pj_AF_INET();
Benny Prijonof260e462007-04-30 21:03:32 +000082 he->h_length = 4;
83 he->h_addr_list = (char**) addr_list;
84
85 return PJ_SUCCESS;
86}
87
88
Benny Prijono4c8fb532007-11-26 05:36:18 +000089/* Get the default IP interface */
90PJ_DEF(pj_status_t) pj_getdefaultipinterface(pj_in_addr *addr)
91{
92 pj_sock_t fd;
93 pj_str_t cp;
94 pj_sockaddr_in a;
95 int len;
96 pj_status_t status;
97
98 status = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &fd);
99 if (status != PJ_SUCCESS) {
100 return status;
101 }
102
103 cp = pj_str("1.1.1.1");
104 pj_sockaddr_in_init(&a, &cp, 53);
105
106 status = pj_sock_connect(fd, &a, sizeof(a));
107 if (status != PJ_SUCCESS) {
108 pj_sock_close(fd);
109 return status;
110 }
111
112 len = sizeof(a);
113 status = pj_sock_getsockname(fd, &a, &len);
114 if (status != PJ_SUCCESS) {
115 pj_sock_close(fd);
116 return status;
117 }
118
119 pj_sock_close(fd);
120
121 *addr = a.sin_addr;
122
123 /* Success */
124 return PJ_SUCCESS;
125}
126
127
Benny Prijonof260e462007-04-30 21:03:32 +0000128/* Resolve the IP address of local machine */
Benny Prijono8ab968f2007-07-20 08:08:30 +0000129PJ_DEF(pj_status_t) pj_gethostip(pj_in_addr *addr)
Benny Prijonof260e462007-04-30 21:03:32 +0000130{
131 const pj_str_t *hostname = pj_gethostname();
132 struct pj_hostent he;
Benny Prijonof260e462007-04-30 21:03:32 +0000133 pj_status_t status;
134
Benny Prijonof260e462007-04-30 21:03:32 +0000135
136 /* Try with resolving local hostname first */
137 status = pj_gethostbyname(hostname, &he);
138 if (status == PJ_SUCCESS) {
139 *addr = *(pj_in_addr*)he.h_addr;
140 }
141
142
Benny Prijono4c8fb532007-11-26 05:36:18 +0000143 /* If we end up with 127.x.x.x, resolve the IP by getting the default
144 * interface to connect to some public host.
Benny Prijonof260e462007-04-30 21:03:32 +0000145 */
Benny Prijono4c8fb532007-11-26 05:36:18 +0000146 if (status != PJ_SUCCESS || (pj_ntohl(addr->s_addr) >> 24)==127 ||
147 addr->s_addr == 0)
148 {
149 status = pj_getdefaultipinterface(addr);
150 }
Benny Prijonof260e462007-04-30 21:03:32 +0000151
Benny Prijono4c8fb532007-11-26 05:36:18 +0000152 /* As the last resort, get the first available interface */
153 if (status != PJ_SUCCESS) {
154 pj_in_addr addrs[2];
155 unsigned count = PJ_ARRAY_SIZE(addrs);
156
157 status = pj_enum_ip_interface(&count, addrs);
158 if (status == PJ_SUCCESS) {
159 if (count != 0) {
160 *addr = addrs[0];
161 } else {
162 /* Just return 127.0.0.1 */
163 addr->s_addr = pj_htonl(0x7f000001);
164 }
Benny Prijonof260e462007-04-30 21:03:32 +0000165 }
Benny Prijonof260e462007-04-30 21:03:32 +0000166 }
167
168 return status;
169}
170
171