+ return EAI_FAMILY;
+ }
+
+ struct sockaddr_in addr_in;
+ memset(&addr_in, 0, sizeof(addr_in));
+ addr_in.sin_family = AF_INET;
+ addr_in.sin_port = port;
+
+ struct sockaddr_in6 addr_in6;
+ memset(&addr_in6, 0, sizeof(addr_in6));
+ addr_in6.sin6_family = AF_INET6;
+ addr_in6.sin6_port = port;
+
+ if (node) {
+ // Handle numeric node name.
+ if (hints->ai_family == AF_INET || hints->ai_family == AF_UNSPEC) {
+ in_addr in;
+ if (inet_pton(AF_INET, node, &in)) {
+ addr_in.sin_addr = in;
+ CreateAddrInfo(hints, (sockaddr*)&addr_in, node, result, &end);
+ return 0;
+ }
+ }
+
+ if (hints->ai_family == AF_INET6 || hints->ai_family == AF_UNSPEC) {
+ in6_addr in6;
+ if (inet_pton(AF_INET6, node, &in6)) {
+ addr_in6.sin6_addr = in6;
+ CreateAddrInfo(hints, (sockaddr*)&addr_in6, node, result, &end);
+ return 0;
+ }
+ }
+ }
+
+ // Handle AI_PASSIVE (used for listening sockets, e.g. INADDR_ANY)
+ if (node == NULL && (hints->ai_flags & AI_PASSIVE)) {
+ if (hints->ai_family == AF_INET6 || hints->ai_family == AF_UNSPEC) {
+ const in6_addr in6addr_any = IN6ADDR_ANY_INIT;
+ memcpy(&addr_in6.sin6_addr.s6_addr, &in6addr_any, sizeof(in6addr_any));
+ CreateAddrInfo(hints, (sockaddr*)&addr_in6, NULL, result, &end);
+ }
+
+ if (hints->ai_family == AF_INET || hints->ai_family == AF_UNSPEC) {
+ addr_in.sin_addr.s_addr = INADDR_ANY;
+ CreateAddrInfo(hints, (sockaddr*)&addr_in, NULL, result, &end);
+ }
+ return 0;
+ }
+
+ if (NULL == ppapi_)
+ return EAI_SYSTEM;
+
+ // Use PPAPI interface to resolve nodename
+ HostResolverInterface* resolver_iface = ppapi_->GetHostResolverInterface();
+ VarInterface* var_interface = ppapi_->GetVarInterface();
+ NetAddressInterface* netaddr_iface = ppapi_->GetNetAddressInterface();
+
+ if (NULL == resolver_iface || NULL == var_interface || NULL == netaddr_iface)
+ return EAI_SYSTEM;
+
+ ScopedResource scoped_resolver(ppapi_,
+ resolver_iface->Create(ppapi_->GetInstance()));
+ PP_Resource resolver = scoped_resolver.pp_resource();
+
+ struct PP_HostResolver_Hint pp_hints;
+ HintsToPPHints(hints, &pp_hints);
+
+ int err = resolver_iface->Resolve(resolver,
+ node,
+ 0,
+ &pp_hints,
+ PP_BlockUntilComplete());
+ if (err) {
+ switch (err) {
+ case PP_ERROR_NOACCESS:
+ return EAI_SYSTEM;
+ case PP_ERROR_NAME_NOT_RESOLVED:
+ return EAI_NONAME;
+ default:
+ return EAI_SYSTEM;
+ }
+ }
+
+ char* canon_name = NULL;
+ if (hints->ai_flags & AI_CANONNAME) {
+ PP_Var name_var = resolver_iface->GetCanonicalName(resolver);
+ if (PP_VARTYPE_STRING == name_var.type) {
+ uint32_t len = 0;
+ const char* tmp = var_interface->VarToUtf8(name_var, &len);
+ // For some reason GetCanonicalName alway returns an empty
+ // string so this condition is never true.
+ // TODO(sbc): investigate this issue with PPAPI team.
+ if (len > 0) {
+ // Copy and NULL-terminate the UTF8 string var.
+ canon_name = static_cast<char*>(malloc(len+1));
+ strncpy(canon_name, tmp, len);
+ canon_name[len] = '\0';
+ }
+ }
+ if (!canon_name)
+ canon_name = strdup(node);
+ var_interface->Release(name_var);