1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "nacl_io/host_resolver.h"
10 #include "nacl_io/kernel_proxy.h"
11 #include "nacl_io/ossocket.h"
12 #include "nacl_io/pepper_interface.h"
14 #ifdef PROVIDES_SOCKET_API
18 HostResolver::HostResolver() : hostent_(), ppapi_(NULL) {
21 HostResolver::~HostResolver() {
25 void HostResolver::Init(PepperInterface* ppapi) {
29 struct hostent* HostResolver::gethostbyname(const char* name) {
30 h_errno = NETDB_INTERNAL;
35 HostResolverInterface* resolver_interface =
36 ppapi_->GetHostResolverInterface();
37 ScopedResource resolver(ppapi_,
38 resolver_interface->Create(ppapi_->GetInstance()));
40 struct PP_CompletionCallback callback;
42 struct PP_HostResolver_Hint hint;
43 hint.family = PP_NETADDRESS_FAMILY_IPV4;
44 hint.flags = PP_HOSTRESOLVER_FLAG_CANONNAME;
46 int err = resolver_interface->Resolve(resolver.pp_resource(),
47 name, 0, &hint, callback);
50 case PP_ERROR_NOACCESS:
51 h_errno = NO_RECOVERY;
53 case PP_ERROR_NAME_NOT_RESOLVED:
54 h_errno = HOST_NOT_FOUND;
57 h_errno = NETDB_INTERNAL;
63 // We use a single hostent struct for all calls to to gethostbyname
64 // (as explicitly permitted by the spec - gethostbyname is NOT supposed to
65 // be threadsafe!), so the first thing we do is free all the malloced data
66 // left over from the last call.
70 resolver_interface->GetCanonicalName(resolver.pp_resource());
71 if (PP_VARTYPE_STRING != name_var.type)
75 const char* name_ptr = ppapi_->GetVarInterface()->VarToUtf8(name_var, &len);
79 // Sometimes GetCanonicalName gives up more easily than gethostbyname should
80 // (for example, it returns "" when asked to resolve "localhost"), so if we
81 // get an empty string we copy over the input string instead.
85 hostent_.h_name = static_cast<char*>(malloc(len + 1));
86 if (NULL == hostent_.h_name)
88 memcpy(hostent_.h_name, name_ptr, len);
89 hostent_.h_name[len] = '\0';
91 // Aliases aren't supported at the moment, so we just make an empty list.
92 hostent_.h_aliases = static_cast<char**>(malloc(sizeof(char*)));
93 if (NULL == hostent_.h_aliases)
95 hostent_.h_aliases[0] = NULL;
97 NetAddressInterface* netaddr_interface = ppapi_->GetNetAddressInterface();
99 resolver_interface->GetNetAddress(resolver.pp_resource(), 0);
100 if (!PP_ToBool(netaddr_interface->IsNetAddress(addr)))
103 switch (netaddr_interface->GetFamily(addr)) {
104 case PP_NETADDRESS_FAMILY_IPV4:
105 hostent_.h_addrtype = AF_INET;
106 hostent_.h_length = 4;
108 case PP_NETADDRESS_FAMILY_IPV6:
109 hostent_.h_addrtype = AF_INET6;
110 hostent_.h_length = 16;
116 const uint32_t num_addresses =
117 resolver_interface->GetNetAddressCount(resolver.pp_resource());
118 if (0 == num_addresses)
120 hostent_.h_addr_list =
121 static_cast<char**>(calloc(num_addresses + 1, sizeof(char*)));
122 if (NULL == hostent_.h_addr_list)
125 for (uint32_t i = 0; i < num_addresses; i++) {
127 resolver_interface->GetNetAddress(resolver.pp_resource(), i);
128 if (!PP_ToBool(netaddr_interface->IsNetAddress(addr)))
130 if (AF_INET == hostent_.h_addrtype) {
131 struct PP_NetAddress_IPv4 addr_struct;
132 if (!netaddr_interface->DescribeAsIPv4Address(addr, &addr_struct)) {
135 hostent_.h_addr_list[i] = static_cast<char*>(malloc(hostent_.h_length));
136 if (NULL == hostent_.h_addr_list[i])
138 memcpy(hostent_.h_addr_list[i], addr_struct.addr, hostent_.h_length);
140 struct PP_NetAddress_IPv6 addr_struct;
141 if (!netaddr_interface->DescribeAsIPv6Address(addr, &addr_struct))
143 hostent_.h_addr_list[i] = static_cast<char*>(malloc(hostent_.h_length));
144 if (NULL == hostent_.h_addr_list[i])
146 memcpy(hostent_.h_addr_list[i], addr_struct.addr, hostent_.h_length);
152 // Frees all of the deep pointers in a hostent struct. Called between uses of
153 // gethostbyname, and when the kernel_proxy object is destroyed.
154 void HostResolver::hostent_cleanup() {
155 if (NULL != hostent_.h_name) {
156 free(hostent_.h_name);
158 if (NULL != hostent_.h_aliases) {
159 for (int i = 0; NULL != hostent_.h_aliases[i]; i++) {
160 free(hostent_.h_aliases[i]);
162 free(hostent_.h_aliases);
164 if (NULL != hostent_.h_addr_list) {
165 for (int i = 0; NULL != hostent_.h_addr_list[i]; i++) {
166 free(hostent_.h_addr_list[i]);
168 free(hostent_.h_addr_list);
170 hostent_.h_name = NULL;
171 hostent_.h_aliases = NULL;
172 hostent_.h_addr_list = NULL;
175 } // namespace nacl_io
177 #endif // PROVIDES_SOCKET_API