int socket_transport_get_local_address()

in win32/src/socket_transport_win32.c [867:1001]


int socket_transport_get_local_address(SOCKET_TRANSPORT_HANDLE socket_transport, char hostname[MAX_GET_HOST_NAME_LEN], LOCAL_ADDRESS** local_address_list, uint32_t* address_count)
{
    int result;
    // Codes_SOCKET_TRANSPORT_WIN32_11_001: [ If socket_transport is NULL, socket_transport_get_local_address shall fail and return a non-zero value. ]
    if (socket_transport == NULL ||
        // Codes_SOCKET_TRANSPORT_WIN32_11_002: [ If hostname is NULL, socket_transport_get_local_address shall fail and return a non-zero value. ]
        hostname == NULL ||
        // Codes_SOCKET_TRANSPORT_WIN32_11_003: [ If local_address_list is not NULL and address_count is NULL, socket_transport_get_local_address shall fail and return a non-zero value. ]
        (local_address_list != NULL && address_count == NULL)
    )
    {
        LogError("Invalid arguments: SOCKET_TRANSPORT_HANDLE socket_transport: %p, char* hostname: %p, char* local_address_list[MAX_LOCAL_ADDRESS_LEN]: %p, uint32_t* address_count: %p",
            socket_transport, hostname, local_address_list, address_count);
        result = MU_FAILURE;
    }
    else
    {
        // Codes_SOCKET_TRANSPORT_WIN32_11_004: [ socket_transport_get_local_address shall call sm_exec_begin ]
        SM_RESULT sm_result = sm_exec_begin(socket_transport->sm);
        if (sm_result != SM_EXEC_GRANTED)
        {
            // Codes_SOCKET_TRANSPORT_WIN32_11_011: [ If any failure is encountered, socket_transport_get_local_address shall fail and return a non-zero value. ]
            LogError("sm_exec_begin failed : %" PRI_MU_ENUM, MU_ENUM_VALUE(SM_RESULT, sm_result));
            result = MU_FAILURE;
        }
        else
        {
            // Codes_SOCKET_TRANSPORT_WIN32_11_005: [ socket_transport_get_local_address shall get the hostname by calling gethostname. ]
            if (gethostname(hostname, MAX_GET_HOST_NAME_LEN) == SOCKET_ERROR)
            {
                // Codes_SOCKET_TRANSPORT_WIN32_11_011: [ If any failure is encountered, socket_transport_get_local_address shall fail and return a non-zero value. ]
                LogLastError("Unable to get hostname");
                result = MU_FAILURE;
            }
            else
            {
                if (local_address_list != NULL)
                {
                    // Codes_SOCKET_TRANSPORT_WIN32_11_006: [ If local_address_list is not NULL, socket_transport_get_local_address shall call gethostbyname to get the addresses in a hostent object. ]
                    struct hostent* host_info = gethostbyname(hostname);
                    if (host_info == NULL)
                    {
                        // Codes_SOCKET_TRANSPORT_WIN32_11_011: [ If any failure is encountered, socket_transport_get_local_address shall fail and return a non-zero value. ]
                        LogLastError("Failure in call to gethostbyname %s", hostname);
                        result = MU_FAILURE;
                    }
                    else
                    {
                        if (host_info->h_addrtype == AF_INET)
                        {
                            uint32_t total_count = 0;
                            uint32_t address_index = 0;
                            struct in_addr addr;

                            // Count the address returned
                            while (host_info->h_addr_list[total_count] != 0)
                            {
                                total_count++;
                            }

                            // Allocate the array
                            // Codes_SOCKET_TRANSPORT_WIN32_11_007: [ socket_transport_get_local_address shall allocate a LOCAL_ADDRESS array. ]
                            LOCAL_ADDRESS* temp_list = malloc_2(total_count, sizeof(LOCAL_ADDRESS));
                            if (temp_list == NULL)
                            {
                                // Codes_SOCKET_TRANSPORT_WIN32_11_011: [ If any failure is encountered, socket_transport_get_local_address shall fail and return a non-zero value. ]
                                LogError("failure in malloc_2(total_count: %" PRIu32 ", sizeof(LOCAL_ADDRESS): %zu)", total_count, sizeof(LOCAL_ADDRESS));
                                result = MU_FAILURE;
                            }
                            else
                            {
                                bool failure = false;
                                // Codes_SOCKET_TRANSPORT_WIN32_11_008: [ For each IP in the hostent object, socket_transport_get_local_address shall copy the value into the LOCAL_ADDRESS address by calling inet_ntop. ]
                                while (host_info->h_addr_list[address_index] != 0)
                                {
                                    temp_list[address_index].address_type = ADDRESS_INET;

                                    addr.s_addr = *(u_long*)host_info->h_addr_list[address_index];
                                    if (inet_ntop(AF_INET, &(addr.s_addr), temp_list[address_index].address, MAX_LOCAL_ADDRESS_LEN) == NULL)
                                    {
                                        LogLastError("failure in retreiving network name");
                                        failure = true;
                                        break;
                                    }
                                    else
                                    {
                                        LogInfo("IPv4 Address #: %s", temp_list[address_index].address);
                                        address_index++;
                                    }
                                }

                                if (failure)
                                {
                                    // Codes_SOCKET_TRANSPORT_WIN32_11_011: [ If any failure is encountered, socket_transport_get_local_address shall fail and return a non-zero value. ]
                                    free(temp_list);
                                    result = MU_FAILURE;
                                }
                                else
                                {
                                    *address_count = total_count;
                                    *local_address_list = temp_list;
                                    result = 0;
                                }
                            }
                        }
                        else if (host_info->h_addrtype == AF_INET6)
                        {
                            address_count = 0;
                            result = 0;
                        }
                        else if (host_info->h_addrtype == AF_NETBIOS)
                        {
                            address_count = 0;
                            result = 0;
                        }
                        else
                        {
                            // Codes_SOCKET_TRANSPORT_WIN32_11_011: [ If any failure is encountered, socket_transport_get_local_address shall fail and return a non-zero value. ]
                            LogError("Unknown address type h_addrtype: %d", host_info->h_addrtype);
                            result = MU_FAILURE;
                        }
                    }
                }
                else
                {
                    // Codes_SOCKET_TRANSPORT_WIN32_11_010: [ On success socket_transport_get_local_address shall return 0. ]
                    result = 0;
                }
            }
            // Codes_SOCKET_TRANSPORT_WIN32_11_009: [ socket_transport_get_local_address shall call sm_exec_end. ]
            sm_exec_end(socket_transport->sm);
        }
    }
    return result;
}