blob: 95da5cdd9175a020fa166aec4dfacc16aace3f3b [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>
22#include <pj/string.h>
23#include <pj/unicode.h>
24
25#include "os_symbian.h"
26
27
28// PJLIB API: resolve hostname
29PJ_DEF(pj_status_t) pj_gethostbyname(const pj_str_t *name, pj_hostent *he)
30{
31 PJ_ASSERT_RETURN(name && he, PJ_EINVAL);
32
33 RHostResolver &resv = PjSymbianOS::Instance()->GetResolver();
34
35 // Convert name to Unicode
36 wchar_t name16[PJ_MAX_HOSTNAME];
37 pj_ansi_to_unicode(name->ptr, name->slen, name16, PJ_ARRAY_SIZE(name16));
Benny Prijonoa0c8b5c2007-05-12 15:03:23 +000038 TPtrC16 data((const TUint16*)name16);
Benny Prijonof260e462007-04-30 21:03:32 +000039
40 // Resolve!
41 TNameEntry nameEntry;
42 TRequestStatus reqStatus;
43
44 resv.GetByName(data, nameEntry, reqStatus);
45 User::WaitForRequest(reqStatus);
46
47 if (reqStatus != KErrNone)
48 return PJ_RETURN_OS_ERROR(reqStatus.Int());
49
50 // Get the resolved TInetAddr
51 // This doesn't work, see Martin email on 28/3/2007:
52 // const TNameRecord &rec = (const TNameRecord&) nameEntry;
53 // TInetAddr inetAddr(rec.iAddr);
54 TInetAddr inetAddr(nameEntry().iAddr);
55
56 //
57 // This where we keep static variables.
58 // These should be kept in TLS probably, to allow multiple threads
59 // to call pj_gethostbyname() without interfering each other.
60 // But again, we don't support threads in Symbian!
61 //
62 static char resolved_name[PJ_MAX_HOSTNAME];
63 static char *no_aliases[1];
64 static pj_in_addr *addr_list[2];
65 static pj_sockaddr_in resolved_addr;
66
67 // Convert the official address to ANSI.
Benny Prijonoa0c8b5c2007-05-12 15:03:23 +000068 pj_unicode_to_ansi((const wchar_t*)nameEntry().iName.Ptr(), nameEntry().iName.Length(),
Benny Prijonof260e462007-04-30 21:03:32 +000069 resolved_name, sizeof(resolved_name));
70
71 // Convert IP address
72
73 PjSymbianOS::Addr2pj(inetAddr, resolved_addr);
74 addr_list[0] = &resolved_addr.sin_addr;
75
76 // Return hostent
77 he->h_name = resolved_name;
78 he->h_aliases = no_aliases;
79 he->h_addrtype = PJ_AF_INET;
80 he->h_length = 4;
81 he->h_addr_list = (char**) addr_list;
82
83 return PJ_SUCCESS;
84}
85
86
87/* Resolve the IP address of local machine */
88pj_status_t pj_gethostip(pj_in_addr *addr)
89{
90 const pj_str_t *hostname = pj_gethostname();
91 struct pj_hostent he;
92 pj_str_t cp;
93 pj_in_addr loopip;
94 pj_status_t status;
95
96 cp = pj_str("127.0.0.1");
97 loopip = pj_inet_addr(&cp);
98
99 /* Try with resolving local hostname first */
100 status = pj_gethostbyname(hostname, &he);
101 if (status == PJ_SUCCESS) {
102 *addr = *(pj_in_addr*)he.h_addr;
103 }
104
105
106 /* If we end up with 127.0.0.1 or 0.0.0.0, resolve the IP by getting
107 * the default interface to connect to some public host.
108 */
109 if (status!=PJ_SUCCESS || addr->s_addr == loopip.s_addr || !addr->s_addr) {
110 pj_sock_t fd;
111 pj_sockaddr_in a;
112 int len;
113
114 status = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &fd);
115 if (status != PJ_SUCCESS) {
116 return status;
117 }
118
119 cp = pj_str("1.1.1.1");
120 pj_sockaddr_in_init(&a, &cp, 53);
121
122 status = pj_sock_connect(fd, &a, sizeof(a));
123 if (status != PJ_SUCCESS) {
124 pj_sock_close(fd);
125 return status;
126 }
127
128 len = sizeof(a);
129 status = pj_sock_getsockname(fd, &a, &len);
130 if (status != PJ_SUCCESS) {
131 pj_sock_close(fd);
132 return status;
133 }
134
135 pj_sock_close(fd);
136
137 *addr = a.sin_addr;
138
139 if (a.sin_addr.s_addr == 0)
140 return PJ_ENOTFOUND;
141 }
142
143 return status;
144}
145
146
147