| 776 | } |
| 777 | |
| 778 | Result GetHostByName(const char* name, Address* address, bool ipv4, bool ipv6) |
| 779 | { |
| 780 | Result result = RESULT_HOST_NOT_FOUND; |
| 781 | |
| 782 | memset(address, 0x0, sizeof(Address)); |
| 783 | struct addrinfo hints; |
| 784 | struct addrinfo* res; |
| 785 | |
| 786 | memset(&hints, 0x0, sizeof(hints)); |
| 787 | if (ipv4 == ipv6) |
| 788 | hints.ai_family = AF_UNSPEC; |
| 789 | else if (ipv4) |
| 790 | hints.ai_family = AF_INET; |
| 791 | else if (ipv6) |
| 792 | hints.ai_family = AF_INET6; |
| 793 | |
| 794 | hints.ai_socktype = SOCK_STREAM; |
| 795 | |
| 796 | // getaddrinfo_a is an asynchronous alternative, but it is specific to glibc. |
| 797 | if (getaddrinfo(name, NULL, &hints, &res) == 0) |
| 798 | { |
| 799 | struct addrinfo* iterator = res; |
| 800 | while (iterator && result == RESULT_HOST_NOT_FOUND) |
| 801 | { |
| 802 | // There could be (and probably are) multiple results for the same |
| 803 | // address. The correct way to handle this would be to return a |
| 804 | // list of addresses and then try each of them until one succeeds. |
| 805 | if (ipv4 && iterator->ai_family == AF_INET) |
| 806 | { |
| 807 | sockaddr_in* saddr = (struct sockaddr_in*)iterator->ai_addr; |
| 808 | address->m_family = dmSocket::DOMAIN_IPV4; |
| 809 | *IPv4(address) = saddr->sin_addr.s_addr; |
| 810 | result = RESULT_OK; |
| 811 | } |
| 812 | #if !defined(DM_IPV6_UNSUPPORTED) |
| 813 | else if (ipv6 && iterator->ai_family == AF_INET6) |
| 814 | { |
| 815 | sockaddr_in6* saddr = (struct sockaddr_in6*)iterator->ai_addr; |
| 816 | address->m_family = dmSocket::DOMAIN_IPV6; |
| 817 | memcpy(IPv6(address), &saddr->sin6_addr, sizeof(struct in6_addr)); |
| 818 | result = RESULT_OK; |
| 819 | } |
| 820 | #endif // no ipv6 |
| 821 | |
| 822 | iterator = iterator->ai_next; |
| 823 | } |
| 824 | |
| 825 | freeaddrinfo(res); // Free the head of the linked list |
| 826 | } |
| 827 | |
| 828 | return result; |
| 829 | } |
| 830 | } // namespace dmSocket |