From 963e77aecb6441f396c1614302e0593aa6006dbe Mon Sep 17 00:00:00 2001 From: Jelani Brandon Date: Fri, 19 Jul 2024 07:50:37 -0700 Subject: [PATCH 01/12] adding code to get local address information --- .../devdoc/socket_transport_requirements.md | 15 ++ interfaces/inc/c_pal/socket_transport.h | 17 ++ .../socket_transport_int.c | 35 +++ linux/src/socket_transport_linux.c | 93 ++++++++ .../socket_transport_win32_requirements.md | 35 +++ win32/src/socket_transport_win32.c | 122 +++++++++++ win32/tests/CMakeLists.txt | 1 + .../socket_transport_win32_ut.c | 202 ++++++++++++++++++ .../winsock_mocked.h | 4 + 9 files changed, 524 insertions(+) diff --git a/interfaces/devdoc/socket_transport_requirements.md b/interfaces/devdoc/socket_transport_requirements.md index ab419455..92fd75c6 100644 --- a/interfaces/devdoc/socket_transport_requirements.md +++ b/interfaces/devdoc/socket_transport_requirements.md @@ -51,6 +51,12 @@ typedef struct SOCKET_BUFFER_TAG void* buffer; } SOCKET_BUFFER; +typedef struct LOCAL_ADDRESS_TAG +{ + ADDRESS_TYPE address_type; + char address[MAX_LOCAL_ADDRESS_LEN]; +} LOCAL_ADDRESS; + MOCKABLE_FUNCTION(, SOCKET_TRANSPORT_HANDLE, socket_transport_create_client); MOCKABLE_FUNCTION(, SOCKET_TRANSPORT_HANDLE, socket_transport_create_server); MOCKABLE_FUNCTION(, void, socket_transport_destroy, SOCKET_TRANSPORT_HANDLE, socket_transport); @@ -65,6 +71,7 @@ MOCKABLE_FUNCTION(, SOCKET_SEND_RESULT, socket_transport_send, SOCKET_TRANSPORT_ MOCKABLE_FUNCTION(, SOCKET_RECEIVE_RESULT, socket_transport_receive, SOCKET_TRANSPORT_HANDLE, socket_transport, SOCKET_BUFFER*, payload, uint32_t, buffer_count, uint32_t*, bytes_recv, uint32_t, flags, void*, data); MOCKABLE_FUNCTION(, SOCKET_HANDLE, socket_transport_get_underlying_socket, SOCKET_TRANSPORT_HANDLE, socket_transport); +MOCKABLE_FUNCTION(, 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); ``` ### socket_transport_create_client @@ -147,3 +154,11 @@ MOCKABLE_FUNCTION(, SOCKET_HANDLE, socket_transport_get_underlying_socket, SOCKE ``` `socket_transport_get_underlying_socket` returns the underlying socket. + +### socket_transport_get_local_address + +```c +MOCKABLE_FUNCTION(, 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); +``` + +`socket_transport_get_local_address` shall return the hostname and IP address of the machine. \ No newline at end of file diff --git a/interfaces/inc/c_pal/socket_transport.h b/interfaces/inc/c_pal/socket_transport.h index bf016b8e..fbbdb299 100644 --- a/interfaces/inc/c_pal/socket_transport.h +++ b/interfaces/inc/c_pal/socket_transport.h @@ -16,6 +16,9 @@ extern "C" { #include #endif +#define MAX_GET_HOST_NAME_LEN 256 +#define MAX_LOCAL_ADDRESS_LEN 22 + typedef struct SOCKET_TRANSPORT_TAG* SOCKET_TRANSPORT_HANDLE; #define SOCKET_SEND_RESULT_VALUES \ @@ -42,12 +45,25 @@ MU_DEFINE_ENUM(SOCKET_RECEIVE_RESULT, SOCKET_RECEIVE_RESULT_VALUES) MU_DEFINE_ENUM(SOCKET_TYPE, SOCKET_TYPE_VALUES) +#define ADDRESS_TYPE_VALUES \ + ADDRESS_INET, \ + ADDRESS_INET_6, \ + ADDRESS_NETBIOS + +MU_DEFINE_ENUM(ADDRESS_TYPE, ADDRESS_TYPE_VALUES) + typedef struct SOCKET_BUFFER_TAG { uint32_t length; unsigned char* buffer; } SOCKET_BUFFER; +typedef struct LOCAL_ADDRESS_TAG +{ + ADDRESS_TYPE address_type; + char address[MAX_LOCAL_ADDRESS_LEN]; +} LOCAL_ADDRESS; + MOCKABLE_FUNCTION(, SOCKET_TRANSPORT_HANDLE, socket_transport_create_client); MOCKABLE_FUNCTION(, SOCKET_TRANSPORT_HANDLE, socket_transport_create_server); MOCKABLE_FUNCTION(, void, socket_transport_destroy, SOCKET_TRANSPORT_HANDLE, socket_transport); @@ -62,6 +78,7 @@ MOCKABLE_FUNCTION(, SOCKET_SEND_RESULT, socket_transport_send, SOCKET_TRANSPORT_ MOCKABLE_FUNCTION(, SOCKET_RECEIVE_RESULT, socket_transport_receive, SOCKET_TRANSPORT_HANDLE, socket_transport, SOCKET_BUFFER*, payload, uint32_t, buffer_count, uint32_t*, bytes_recv, uint32_t, flags, void*, data); MOCKABLE_FUNCTION(, SOCKET_HANDLE, socket_transport_get_underlying_socket, SOCKET_TRANSPORT_HANDLE, socket_transport); +MOCKABLE_FUNCTION(, 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); #ifdef __cplusplus } diff --git a/interfaces/tests/socket_transport_int/socket_transport_int.c b/interfaces/tests/socket_transport_int/socket_transport_int.c index bef2cf77..b505556d 100644 --- a/interfaces/tests/socket_transport_int/socket_transport_int.c +++ b/interfaces/tests/socket_transport_int/socket_transport_int.c @@ -359,4 +359,39 @@ TEST_FUNCTION(socket_transport_chaos_knight_test) } +TEST_FUNCTION(get_local_socket_address_test) +{ + // assert + SOCKET_TRANSPORT_HANDLE listen_socket = socket_transport_create_server(); + ASSERT_IS_NOT_NULL(listen_socket); + + ASSERT_ARE_EQUAL(int, 0, socket_transport_listen(listen_socket, g_port_num)); + + // create the async socket object + SOCKET_TRANSPORT_HANDLE client_socket = socket_transport_create_client(); + ASSERT_IS_NOT_NULL(client_socket); + + char client_hostname[MAX_GET_HOST_NAME_LEN] = { 0 }; + char server_hostname[MAX_GET_HOST_NAME_LEN] = { 0 }; + + LOCAL_ADDRESS* server_local_address_list; + LOCAL_ADDRESS* client_local_address_list; + uint32_t server_list_count; + uint32_t client_list_count; + ASSERT_ARE_EQUAL(int, 0, socket_transport_get_local_address(listen_socket, server_hostname, &server_local_address_list, &server_list_count)); + ASSERT_ARE_EQUAL(int, 0, socket_transport_get_local_address(client_socket, client_hostname, &client_local_address_list, &client_list_count)); + + ASSERT_ARE_EQUAL(char_ptr, server_hostname, client_hostname); + ASSERT_ARE_EQUAL(uint32_t, server_list_count, client_list_count); + + socket_transport_disconnect(client_socket); + socket_transport_destroy(client_socket); + + socket_transport_disconnect(listen_socket); + socket_transport_destroy(listen_socket); + + free(server_local_address_list); + free(client_local_address_list); +} + END_TEST_SUITE(TEST_SUITE_NAME_FROM_CMAKE) diff --git a/linux/src/socket_transport_linux.c b/linux/src/socket_transport_linux.c index cfee98b2..509fd039 100644 --- a/linux/src/socket_transport_linux.c +++ b/linux/src/socket_transport_linux.c @@ -713,4 +713,97 @@ SOCKET_HANDLE socket_transport_get_underlying_socket(SOCKET_TRANSPORT_HANDLE soc } } return result; +} + +int socket_transport_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; + if (socket_transport == NULL || + hostname == NULL || + (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 + { + if (gethostname(hostname, MAX_GET_HOST_NAME_LEN) == SOCKET_ERROR) + { + LogLastError("Unable to get hostname"); + result = MU_FAILURE; + } + else + { + if (local_address_list != NULL) + { + struct hostent* host_info = gethostbyname(hostname); + if (host_info == NULL) + { + 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 + LOCAL_ADDRESS* temp_list = malloc_2(sizeof(LOCAL_ADDRESS), total_count); + if (temp_list == NULL) + { + LogError("failure in malloc_2(total_count: %" PRIu32 ", MAX_LOCAL_ADDRESS_LEN: %d)", total_count, MAX_LOCAL_ADDRESS_LEN); + result = MU_FAILURE; + } + else + { + 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]; + inet_ntop(AF_INET, &(addr.s_addr), temp_list[address_index].address, MAX_LOCAL_ADDRESS_LEN); + + LogInfo("IPv4 Address #: %s", temp_list[address_index].address); + address_index++; + } + *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 + { + LogError("Unknown address type h_addrtype: %d", host_info->h_addrtype); + result = MU_FAILURE; + } + } + } + else + { + result = 0; + } + } + } + return result; } \ No newline at end of file diff --git a/win32/devdoc/socket_transport_win32_requirements.md b/win32/devdoc/socket_transport_win32_requirements.md index 8efe237c..485f76d6 100644 --- a/win32/devdoc/socket_transport_win32_requirements.md +++ b/win32/devdoc/socket_transport_win32_requirements.md @@ -42,6 +42,12 @@ typedef struct SOCKET_BUFFER_TAG void* buffer; } SOCKET_BUFFER; +typedef struct LOCAL_ADDRESS_TAG +{ + ADDRESS_TYPE address_type; + char address[MAX_LOCAL_ADDRESS_LEN]; +} LOCAL_ADDRESS; + MOCKABLE_FUNCTION(, SOCKET_TRANSPORT_HANDLE, socket_transport_create_client); MOCKABLE_FUNCTION(, SOCKET_TRANSPORT_HANDLE, socket_transport_create_server); MOCKABLE_FUNCTION(, void, socket_transport_destroy, SOCKET_TRANSPORT_HANDLE, socket_transport); @@ -56,6 +62,7 @@ MOCKABLE_FUNCTION(, SOCKET_SEND_RESULT, socket_transport_send, SOCKET_TRANSPORT_ MOCKABLE_FUNCTION(, SOCKET_RECEIVE_RESULT, socket_transport_receive, SOCKET_TRANSPORT_HANDLE, socket_transport, SOCKET_BUFFER*, payload, uint32_t, buffer_count, uint32_t*, bytes_recv, uint32_t, flags, void*, data); MOCKABLE_FUNCTION(, SOCKET_HANDLE, socket_transport_get_underlying_socket, SOCKET_TRANSPORT_HANDLE, socket_transport); +MOCKABLE_FUNCTION(, 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); ``` ### socket_transport_create_client @@ -320,3 +327,31 @@ MOCKABLE_FUNCTION(, SOCKET_HANDLE, socket_transport_get_underlying_socket, SOCKE **SOCKET_TRANSPORT_WIN32_09_081: [** `socket_transport_get_underlying_socket` shall return the SOCKET_TRANSPORT socket value. **]** **SOCKET_TRANSPORT_WIN32_09_082: [** `socket_transport_get_underlying_socket` shall call `sm_exec_end`. **]** + +### socket_transport_get_local_address + +```c +MOCKABLE_FUNCTION(, 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); +``` + +**SOCKET_TRANSPORT_WIN32_11_001: [** If `socket_transport` is `NULL`, `socket_transport_get_local_address` shall fail and return a non-zero value. **]** + +**SOCKET_TRANSPORT_WIN32_11_002: [** If `hostname` is `NULL`, `socket_transport_get_local_address` shall fail and return a non-zero value. **]** + +**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. **]** + +**SOCKET_TRANSPORT_WIN32_11_004: [** `socket_transport_get_local_address` shall call `sm_exec_begin` **]** + +**SOCKET_TRANSPORT_WIN32_11_005: [** `socket_transport_get_local_address` shall call get the `hostname` by calling `gethostname`. **]** + +**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. **]** + +**SOCKET_TRANSPORT_WIN32_11_007: [** `socket_transport_get_local_address` shall allocate the `LOCAL_ADDRESS` array. **]** + +**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`. **]** + +**SOCKET_TRANSPORT_WIN32_11_009: [** `socket_transport_get_local_address` shall call `sm_exec_end`. **]** + +**SOCKET_TRANSPORT_WIN32_11_010: [** On success `socket_transport_get_local_address` shall return 0. **]** + +**SOCKET_TRANSPORT_WIN32_11_011: [** If any failure is encountered, `socket_transport_get_local_address` shall fail and return a non-zero value. **]** diff --git a/win32/src/socket_transport_win32.c b/win32/src/socket_transport_win32.c index 42ad27c1..ff2586d5 100644 --- a/win32/src/socket_transport_win32.c +++ b/win32/src/socket_transport_win32.c @@ -751,3 +751,125 @@ SOCKET_HANDLE socket_transport_get_underlying_socket(SOCKET_TRANSPORT_HANDLE soc } return result; } + +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 || + (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 + { + SM_RESULT sm_result = sm_exec_begin(socket_transport->sm); + if (sm_result != SM_EXEC_GRANTED) + { + LogError("sm_exec_begin failed : %" PRI_MU_ENUM, MU_ENUM_VALUE(SM_RESULT, sm_result)); + result = MU_FAILURE; + } + else + { + if (gethostname(hostname, MAX_GET_HOST_NAME_LEN) == SOCKET_ERROR) + { + LogLastError("Unable to get hostname"); + result = MU_FAILURE; + } + else + { + if (local_address_list != NULL) + { + struct hostent* host_info = gethostbyname(hostname); + if (host_info == NULL) + { + 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 + LOCAL_ADDRESS* temp_list = malloc_2(sizeof(LOCAL_ADDRESS), total_count); + if (temp_list == NULL) + { + LogError("failure in malloc_2(total_count: %" PRIu32 ", MAX_LOCAL_ADDRESS_LEN: %d)", total_count, MAX_LOCAL_ADDRESS_LEN); + result = MU_FAILURE; + } + else + { + bool failure = false; + 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) + { + 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 + { + LogError("Unknown address type h_addrtype: %d", host_info->h_addrtype); + result = MU_FAILURE; + } + } + } + else + { + result = 0; + } + } + sm_exec_end(socket_transport->sm); + } + } + return result; +} diff --git a/win32/tests/CMakeLists.txt b/win32/tests/CMakeLists.txt index a474ceed..c839446f 100644 --- a/win32/tests/CMakeLists.txt +++ b/win32/tests/CMakeLists.txt @@ -36,6 +36,7 @@ if(${run_unittests}) endif() if(${run_int_tests}) + build_test_folder(async_socket_win32_int) build_test_folder(malloc_multi_flex_int) build_test_folder(threadpool_win32_int) build_test_folder(string_utils_int) diff --git a/win32/tests/socket_transport_win32_ut/socket_transport_win32_ut.c b/win32/tests/socket_transport_win32_ut/socket_transport_win32_ut.c index d5dbcac1..48a822f7 100644 --- a/win32/tests/socket_transport_win32_ut/socket_transport_win32_ut.c +++ b/win32/tests/socket_transport_win32_ut/socket_transport_win32_ut.c @@ -119,6 +119,13 @@ static int my_shutdown(SOCKET s, int how) return 0; } +static int my_gethostname(char* name, int namelen) +{ + (void)namelen; + strcpy(name, TEST_INCOMING_HOSTNAME); + return 0; +} + BEGIN_TEST_SUITE(TEST_SUITE_NAME_FROM_CMAKE) TEST_SUITE_INITIALIZE(suite_init) @@ -131,7 +138,9 @@ TEST_SUITE_INITIALIZE(suite_init) REGISTER_SM_GLOBAL_MOCK_HOOK(); REGISTER_GLOBAL_MOCK_HOOK(malloc, real_gballoc_ll_malloc); + REGISTER_GLOBAL_MOCK_HOOK(malloc_2, real_gballoc_ll_malloc_2); REGISTER_GLOBAL_MOCK_FAIL_RETURN(malloc, NULL); + REGISTER_GLOBAL_MOCK_FAIL_RETURN(malloc_2, NULL); REGISTER_GLOBAL_MOCK_HOOK(free, real_gballoc_ll_free); REGISTER_UMOCK_ALIAS_TYPE(WORD, uint16_t); @@ -158,6 +167,10 @@ TEST_SUITE_INITIALIZE(suite_init) REGISTER_GLOBAL_MOCK_FAIL_RETURN(shutdown, 1); REGISTER_GLOBAL_MOCK_HOOK(inet_ntop, my_inet_ntop); + REGISTER_GLOBAL_MOCK_FAIL_RETURN(inet_ntop, NULL); + REGISTER_GLOBAL_MOCK_HOOK(gethostname, my_gethostname); + REGISTER_GLOBAL_MOCK_FAIL_RETURN(gethostname, SOCKET_ERROR); + REGISTER_GLOBAL_MOCK_FAIL_RETURN(gethostbyname, NULL); REGISTER_GLOBAL_MOCK_FAIL_RETURN(select, SOCKET_ERROR); REGISTER_GLOBAL_MOCK_RETURNS(WSAGetLastError, WSAEALREADY, WSAEFAULT); @@ -1796,4 +1809,193 @@ TEST_FUNCTION(socket_transport_get_underlying_socket_NULL_input_fail) //cleanup } +// socket_transport_get_local_address + +TEST_FUNCTION(socket_transport_get_local_address_handle_NULL_fail) +{ + //arrange + char hostname[MAX_GET_HOST_NAME_LEN]; + LOCAL_ADDRESS* local_address_list; + uint32_t address_count; + + //act + int result = socket_transport_get_local_address(NULL, hostname, &local_address_list, &address_count); + + //assert + ASSERT_ARE_NOT_EQUAL(int, 0, result); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + + // Cleanup +} + +TEST_FUNCTION(socket_transport_get_local_address_hostname_NULL_fail) +{ + //arrange + SOCKET_TRANSPORT_HANDLE socket_handle = socket_transport_create_client(); + ASSERT_IS_NOT_NULL(socket_handle); + ASSERT_ARE_EQUAL(int, 0, socket_transport_connect(socket_handle, TEST_HOSTNAME, TEST_PORT, TEST_CONNECTION_TIMEOUT)); + umock_c_reset_all_calls(); + + LOCAL_ADDRESS* local_address_list; + uint32_t address_count; + + //act + int result = socket_transport_get_local_address(socket_handle, NULL, &local_address_list, &address_count); + + //assert + ASSERT_ARE_NOT_EQUAL(int, 0, result); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + + // Cleanup + socket_transport_disconnect(socket_handle); + socket_transport_destroy(socket_handle); +} + +TEST_FUNCTION(socket_transport_get_local_address_address_count_NULL_fail) +{ + //arrange + SOCKET_TRANSPORT_HANDLE socket_handle = socket_transport_create_client(); + ASSERT_IS_NOT_NULL(socket_handle); + ASSERT_ARE_EQUAL(int, 0, socket_transport_connect(socket_handle, TEST_HOSTNAME, TEST_PORT, TEST_CONNECTION_TIMEOUT)); + umock_c_reset_all_calls(); + + char hostname[MAX_GET_HOST_NAME_LEN]; + LOCAL_ADDRESS* local_address_list; + + //act + int result = socket_transport_get_local_address(socket_handle, hostname, &local_address_list, NULL); + + //assert + ASSERT_ARE_NOT_EQUAL(int, 0, result); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + + // Cleanup + socket_transport_disconnect(socket_handle); + socket_transport_destroy(socket_handle); +} + +TEST_FUNCTION(socket_transport_get_local_address_success) +{ + //arrange + SOCKET_TRANSPORT_HANDLE socket_handle = socket_transport_create_client(); + ASSERT_IS_NOT_NULL(socket_handle); + ASSERT_ARE_EQUAL(int, 0, socket_transport_connect(socket_handle, TEST_HOSTNAME, TEST_PORT, TEST_CONNECTION_TIMEOUT)); + umock_c_reset_all_calls(); + + char hostname[MAX_GET_HOST_NAME_LEN]; + LOCAL_ADDRESS* local_address_list; + uint32_t address_count; + + uint32_t NUM_OF_ADDRESSES = 2; + const char* ip_address_list[] = { + "10.0.0.1", + "10.0.0.50", + NULL + }; + + struct hostent test_host_info = {0}; + test_host_info.h_addrtype = AF_INET; + test_host_info.h_addr_list = ip_address_list; + + STRICT_EXPECTED_CALL(sm_exec_begin(IGNORED_ARG)); + STRICT_EXPECTED_CALL(gethostname(IGNORED_ARG, MAX_GET_HOST_NAME_LEN)); + STRICT_EXPECTED_CALL(gethostbyname(IGNORED_ARG)) + .SetReturn(&test_host_info); + STRICT_EXPECTED_CALL(malloc_2(IGNORED_ARG, 2)); + STRICT_EXPECTED_CALL(inet_ntop(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG)); + STRICT_EXPECTED_CALL(inet_ntop(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG)); + STRICT_EXPECTED_CALL(sm_exec_end(IGNORED_ARG)); + + //act + int result = socket_transport_get_local_address(socket_handle, hostname, &local_address_list, &address_count); + + //assert + ASSERT_ARE_EQUAL(int, 0, result); + ASSERT_ARE_EQUAL(int, NUM_OF_ADDRESSES, address_count); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + + // Cleanup + socket_transport_disconnect(socket_handle); + socket_transport_destroy(socket_handle); + free(local_address_list); +} + +TEST_FUNCTION(socket_transport_get_local_address_no_address_list_success) +{ + //arrange + SOCKET_TRANSPORT_HANDLE socket_handle = socket_transport_create_client(); + ASSERT_IS_NOT_NULL(socket_handle); + ASSERT_ARE_EQUAL(int, 0, socket_transport_connect(socket_handle, TEST_HOSTNAME, TEST_PORT, TEST_CONNECTION_TIMEOUT)); + umock_c_reset_all_calls(); + + char hostname[MAX_GET_HOST_NAME_LEN]; + + STRICT_EXPECTED_CALL(sm_exec_begin(IGNORED_ARG)); + STRICT_EXPECTED_CALL(gethostname(IGNORED_ARG, MAX_GET_HOST_NAME_LEN)); + STRICT_EXPECTED_CALL(sm_exec_end(IGNORED_ARG)); + + //act + int result = socket_transport_get_local_address(socket_handle, hostname, NULL, NULL); + + //assert + ASSERT_ARE_EQUAL(int, 0, result); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + + // Cleanup + socket_transport_disconnect(socket_handle); + socket_transport_destroy(socket_handle); +} + +TEST_FUNCTION(socket_transport_get_local_address_fail) +{ + //arrange + SOCKET_TRANSPORT_HANDLE socket_handle = socket_transport_create_client(); + ASSERT_IS_NOT_NULL(socket_handle); + ASSERT_ARE_EQUAL(int, 0, socket_transport_connect(socket_handle, TEST_HOSTNAME, TEST_PORT, TEST_CONNECTION_TIMEOUT)); + umock_c_reset_all_calls(); + + char hostname[MAX_GET_HOST_NAME_LEN]; + LOCAL_ADDRESS* local_address_list; + uint32_t address_count; + + const char* ip_address_list[] = { + "10.0.0.1", + "10.0.0.50", + NULL + }; + + struct hostent test_host_info = { 0 }; + test_host_info.h_addrtype = AF_INET; + test_host_info.h_addr_list = ip_address_list; + + STRICT_EXPECTED_CALL(sm_exec_begin(IGNORED_ARG)); + STRICT_EXPECTED_CALL(gethostname(IGNORED_ARG, MAX_GET_HOST_NAME_LEN)); + STRICT_EXPECTED_CALL(gethostbyname(IGNORED_ARG)) + .SetReturn(&test_host_info); + STRICT_EXPECTED_CALL(malloc_2(IGNORED_ARG, 2)); + STRICT_EXPECTED_CALL(inet_ntop(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG)); + STRICT_EXPECTED_CALL(inet_ntop(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG)); + STRICT_EXPECTED_CALL(sm_exec_end(IGNORED_ARG)); + umock_c_negative_tests_snapshot(); + + for (size_t index = 0; index < umock_c_negative_tests_call_count(); index++) + { + if (umock_c_negative_tests_can_call_fail(index)) + { + umock_c_negative_tests_reset(); + umock_c_negative_tests_fail_call(index); + + //act + int result = socket_transport_get_local_address(socket_handle, hostname, &local_address_list, &address_count); + + //assert + ASSERT_ARE_NOT_EQUAL(int, 0, result); + } + } + + // Cleanup + socket_transport_disconnect(socket_handle); + socket_transport_destroy(socket_handle); +} + END_TEST_SUITE(TEST_SUITE_NAME_FROM_CMAKE) diff --git a/win32/tests/socket_transport_win32_ut/winsock_mocked.h b/win32/tests/socket_transport_win32_ut/winsock_mocked.h index 6b9037bc..f6360bd4 100644 --- a/win32/tests/socket_transport_win32_ut/winsock_mocked.h +++ b/win32/tests/socket_transport_win32_ut/winsock_mocked.h @@ -27,6 +27,8 @@ #define __WSAFDIsSet mocked___WSAFDIsSet #define ioctlsocket mocked_ioctlsocket #define shutdown mocked_shutdown +#define gethostname mocked_gethostname +#define gethostbyname mocked_gethostbyname MOCKABLE_FUNCTION(, int, mocked_getaddrinfo, const char*, pNodeName, const char*, pServiceName, const ADDRINFOA*, pHints, PADDRINFOA*, ppResult); MOCKABLE_FUNCTION(, int, mocked_connect, SOCKET, s, const struct sockaddr*, name, int, namelen); @@ -46,5 +48,7 @@ MOCKABLE_FUNCTION(, int, mocked_WSARecv, SOCKET, s, LPWSABUF, lpBuffers, DWORD, MOCKABLE_FUNCTION(, int, mocked_WSASend, SOCKET, s, LPWSABUF, lpBuffers, DWORD, dwBufferCount, LPDWORD, lpNumberOfBytesSent, DWORD, dwFlags, LPWSAOVERLAPPED, lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE, lpCompletionRoutine); MOCKABLE_FUNCTION(, int, mocked___WSAFDIsSet, SOCKET, fd, fd_set*, p); MOCKABLE_FUNCTION(, int, mocked_shutdown, SOCKET, __fd, int, __how); +MOCKABLE_FUNCTION(, int, mocked_gethostname, char*, name, int, namelen); +MOCKABLE_FUNCTION(, struct hostent*, mocked_gethostbyname, const char*, name); #endif // WINSOCK_MOCKED_H From 9a45603efe9525479e8b22c42a01a0d2f2eba811 Mon Sep 17 00:00:00 2001 From: Jelani Brandon Date: Fri, 9 Aug 2024 14:43:02 -0700 Subject: [PATCH 02/12] add spec to UT --- .../tests/socket_transport_win32_ut/socket_transport_win32_ut.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/win32/tests/socket_transport_win32_ut/socket_transport_win32_ut.c b/win32/tests/socket_transport_win32_ut/socket_transport_win32_ut.c index 48a822f7..de43e232 100644 --- a/win32/tests/socket_transport_win32_ut/socket_transport_win32_ut.c +++ b/win32/tests/socket_transport_win32_ut/socket_transport_win32_ut.c @@ -1811,6 +1811,7 @@ TEST_FUNCTION(socket_transport_get_underlying_socket_NULL_input_fail) // socket_transport_get_local_address +// Tests_SOCKET_TRANSPORT_WIN32_11_001: [ If socket_transport is NULL, socket_transport_get_local_address shall fail and return a non-zero value. ] TEST_FUNCTION(socket_transport_get_local_address_handle_NULL_fail) { //arrange @@ -1828,6 +1829,7 @@ TEST_FUNCTION(socket_transport_get_local_address_handle_NULL_fail) // Cleanup } +// Tests_SOCKET_TRANSPORT_WIN32_11_002: [ If hostname is NULL, socket_transport_get_local_address shall fail and return a non-zero value. ] TEST_FUNCTION(socket_transport_get_local_address_hostname_NULL_fail) { //arrange From 720c2e498ae4a468e9135aeca5f79e8704bc5025 Mon Sep 17 00:00:00 2001 From: Jelani Brandon Date: Tue, 22 Oct 2024 11:02:00 -0700 Subject: [PATCH 03/12] merge with master --- common/reals/real_socket_transport.h | 4 +- common/reals/real_socket_transport_renames.h | 1 + .../socket_transport_int.c | 23 +++- linux/src/socket_transport_linux.c | 107 ++++++++++-------- win32/src/socket_transport_win32.c | 14 +++ win32/tests/CMakeLists.txt | 1 - .../socket_transport_win32_ut.c | 49 ++++++++ 7 files changed, 148 insertions(+), 51 deletions(-) diff --git a/common/reals/real_socket_transport.h b/common/reals/real_socket_transport.h index 7d61ce7f..29e4f174 100644 --- a/common/reals/real_socket_transport.h +++ b/common/reals/real_socket_transport.h @@ -23,7 +23,8 @@ socket_transport_send, \ socket_transport_receive, \ socket_transport_get_underlying_socket, \ - socket_transport_is_valid_socket \ + socket_transport_is_valid_socket, \ + socket_transport_get_local_address \ ) #ifdef __cplusplus @@ -42,6 +43,7 @@ SOCKET_SEND_RESULT real_socket_transport_send(SOCKET_TRANSPORT_HANDLE socket_tra SOCKET_RECEIVE_RESULT real_socket_transport_receive(SOCKET_TRANSPORT_HANDLE socket_transport, SOCKET_BUFFER* payload, uint32_t buffer_count, uint32_t* bytes_recv, uint32_t flags, void* data); SOCKET_HANDLE real_socket_transport_get_underlying_socket(SOCKET_TRANSPORT_HANDLE socket_transport); bool real_socket_transport_is_valid_socket(SOCKET_TRANSPORT_HANDLE socket_transport_handle); +int real_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); #ifdef __cplusplus } diff --git a/common/reals/real_socket_transport_renames.h b/common/reals/real_socket_transport_renames.h index 3a8e10fa..78db8806 100644 --- a/common/reals/real_socket_transport_renames.h +++ b/common/reals/real_socket_transport_renames.h @@ -12,6 +12,7 @@ #define socket_transport_receive real_socket_transport_receive #define socket_transport_get_underlying_socket real_socket_transport_get_underlying_socket #define socket_transport_is_valid_socket real_socket_transport_is_valid_socket +#define socket_transport_get_local_address real_socket_transport_get_local_address #define SOCKET_SEND_RESULT real_SOCKET_SEND_RESULT #define SOCKET_RECEIVE_RESULT real_SOCKET_RECEIVE_RESULT diff --git a/interfaces/tests/socket_transport_int/socket_transport_int.c b/interfaces/tests/socket_transport_int/socket_transport_int.c index 2e039b89..03368455 100644 --- a/interfaces/tests/socket_transport_int/socket_transport_int.c +++ b/interfaces/tests/socket_transport_int/socket_transport_int.c @@ -66,6 +66,7 @@ TEST_SUITE_CLEANUP(suite_cleanup) TEST_FUNCTION_INITIALIZE(method_init) { + g_port_num++; } TEST_FUNCTION_CLEANUP(method_cleanup) @@ -428,6 +429,12 @@ TEST_FUNCTION(get_local_socket_address_test) SOCKET_TRANSPORT_HANDLE client_socket = socket_transport_create_client(); ASSERT_IS_NOT_NULL(client_socket); + ASSERT_ARE_EQUAL(int, 0, socket_transport_connect(client_socket, "localhost", g_port_num, TEST_CONN_TIMEOUT)); + + SOCKET_TRANSPORT_HANDLE incoming_socket; + ASSERT_ARE_EQUAL(SOCKET_ACCEPT_RESULT, SOCKET_ACCEPT_OK, socket_transport_accept(listen_socket, &incoming_socket, TEST_CONN_TIMEOUT)); + ASSERT_IS_NOT_NULL(incoming_socket); + char client_hostname[MAX_GET_HOST_NAME_LEN] = { 0 }; char server_hostname[MAX_GET_HOST_NAME_LEN] = { 0 }; @@ -435,15 +442,29 @@ TEST_FUNCTION(get_local_socket_address_test) LOCAL_ADDRESS* client_local_address_list; uint32_t server_list_count; uint32_t client_list_count; - ASSERT_ARE_EQUAL(int, 0, socket_transport_get_local_address(listen_socket, server_hostname, &server_local_address_list, &server_list_count)); + ASSERT_ARE_EQUAL(int, 0, socket_transport_get_local_address(incoming_socket, server_hostname, &server_local_address_list, &server_list_count)); ASSERT_ARE_EQUAL(int, 0, socket_transport_get_local_address(client_socket, client_hostname, &client_local_address_list, &client_list_count)); + LogVerbose("Client Address:"); + for (uint32_t index = 0; index < client_list_count; index++) + { + LogVerbose("\tType: %" PRI_MU_ENUM ", Address: %s", MU_ENUM_VALUE(ADDRESS_TYPE, client_local_address_list[0].address_type), client_local_address_list[0].address); + } + LogVerbose("Incoming Address:"); + for (uint32_t index = 0; index < server_list_count; index++) + { + LogVerbose("\tType: %" PRI_MU_ENUM ", Address: %s", MU_ENUM_VALUE(ADDRESS_TYPE, server_local_address_list[0].address_type), server_local_address_list[0].address); + } + ASSERT_ARE_EQUAL(char_ptr, server_hostname, client_hostname); ASSERT_ARE_EQUAL(uint32_t, server_list_count, client_list_count); socket_transport_disconnect(client_socket); socket_transport_destroy(client_socket); + socket_transport_disconnect(incoming_socket); + socket_transport_destroy(incoming_socket); + socket_transport_disconnect(listen_socket); socket_transport_destroy(listen_socket); diff --git a/linux/src/socket_transport_linux.c b/linux/src/socket_transport_linux.c index 08a9d7d0..89c7d60e 100644 --- a/linux/src/socket_transport_linux.c +++ b/linux/src/socket_transport_linux.c @@ -807,7 +807,7 @@ bool socket_transport_is_valid_socket(SOCKET_TRANSPORT_HANDLE socket_transport_h } -int socket_transport_local_address(SOCKET_TRANSPORT_HANDLE socket_transport, char hostname[MAX_GET_HOST_NAME_LEN], LOCAL_ADDRESS** local_address_list, uint32_t* address_count) +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; if (socket_transport == NULL || @@ -821,81 +821,92 @@ int socket_transport_local_address(SOCKET_TRANSPORT_HANDLE socket_transport, cha } else { - if (gethostname(hostname, MAX_GET_HOST_NAME_LEN) == SOCKET_ERROR) + SM_RESULT sm_result = sm_exec_begin(socket_transport->sm); + if (sm_result != SM_EXEC_GRANTED) { - LogLastError("Unable to get hostname"); + // 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 { - if (local_address_list != NULL) + if (gethostname(hostname, MAX_GET_HOST_NAME_LEN) == INVALID_SOCKET) { - struct hostent* host_info = gethostbyname(hostname); - if (host_info == NULL) - { - LogLastError("Failure in call to gethostbyname %s", hostname); - result = MU_FAILURE; - } - else + LogErrorNo("Unable to get hostname"); + result = MU_FAILURE; + } + else + { + if (local_address_list != NULL) { - if (host_info->h_addrtype == AF_INET) + struct ifaddrs *ifaddr, *ifa; + if (getifaddrs(&ifaddr) == -1) + { + LogErrorNo("Failure getting interface addresses"); + result = MU_FAILURE; + } + else { 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) + for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { total_count++; } - // Allocate the array LOCAL_ADDRESS* temp_list = malloc_2(sizeof(LOCAL_ADDRESS), total_count); 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 ", MAX_LOCAL_ADDRESS_LEN: %d)", total_count, MAX_LOCAL_ADDRESS_LEN); result = MU_FAILURE; } else { - while (host_info->h_addr_list[address_index] != 0) - { - temp_list[address_index].address_type = ADDRESS_INET; + bool failure = false; + uint32_t address_index = 0; - addr.s_addr = *(u_long*)host_info->h_addr_list[address_index]; - inet_ntop(AF_INET, &(addr.s_addr), temp_list[address_index].address, MAX_LOCAL_ADDRESS_LEN); + for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) + { + if (ifa->ifa_addr != NULL) + { + int family = ifa->ifa_addr->sa_family; + + temp_list[address_index].address_type = ADDRESS_INET; + + if (getnameinfo( ifa->ifa_addr, (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6), temp_list[address_index].address, MAX_LOCAL_ADDRESS_LEN, NULL, 0, NI_NUMERICHOST) != 0) + { + //LogLastError("failure in retreiving network name"); + failure = true; + break; + } + else + { + printf("flag: %u\n", ifa->ifa_flags); + printf("type: %s\n", ifa->ifa_name); + printf("Name: %s\n", temp_list[address_index].address); + address_index++; + } + } + } - 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; } - *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 - { - LogError("Unknown address type h_addrtype: %d", host_info->h_addrtype); - result = MU_FAILURE; - } } } - else - { - result = 0; - } + sm_exec_end(socket_transport->sm); } } return result; -} \ No newline at end of file +} diff --git a/win32/src/socket_transport_win32.c b/win32/src/socket_transport_win32.c index dd6b5902..4bd669b0 100644 --- a/win32/src/socket_transport_win32.c +++ b/win32/src/socket_transport_win32.c @@ -870,6 +870,7 @@ int socket_transport_get_local_address(SOCKET_TRANSPORT_HANDLE socket_transport, 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) ) { @@ -879,16 +880,20 @@ int socket_transport_get_local_address(SOCKET_TRANSPORT_HANDLE socket_transport, } 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 call 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; } @@ -896,9 +901,11 @@ int socket_transport_get_local_address(SOCKET_TRANSPORT_HANDLE socket_transport, { 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; } @@ -917,15 +924,18 @@ int socket_transport_get_local_address(SOCKET_TRANSPORT_HANDLE socket_transport, } // Allocate the array + // Codes_SOCKET_TRANSPORT_WIN32_11_007: [ socket_transport_get_local_address shall allocate the LOCAL_ADDRESS array. ] LOCAL_ADDRESS* temp_list = malloc_2(sizeof(LOCAL_ADDRESS), total_count); 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 ", MAX_LOCAL_ADDRESS_LEN: %d)", total_count, MAX_LOCAL_ADDRESS_LEN); 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; @@ -946,6 +956,7 @@ int socket_transport_get_local_address(SOCKET_TRANSPORT_HANDLE socket_transport, 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; } @@ -969,6 +980,7 @@ int socket_transport_get_local_address(SOCKET_TRANSPORT_HANDLE socket_transport, } 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; } @@ -976,9 +988,11 @@ int socket_transport_get_local_address(SOCKET_TRANSPORT_HANDLE socket_transport, } 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); } } diff --git a/win32/tests/CMakeLists.txt b/win32/tests/CMakeLists.txt index c839446f..a474ceed 100644 --- a/win32/tests/CMakeLists.txt +++ b/win32/tests/CMakeLists.txt @@ -36,7 +36,6 @@ if(${run_unittests}) endif() if(${run_int_tests}) - build_test_folder(async_socket_win32_int) build_test_folder(malloc_multi_flex_int) build_test_folder(threadpool_win32_int) build_test_folder(string_utils_int) diff --git a/win32/tests/socket_transport_win32_ut/socket_transport_win32_ut.c b/win32/tests/socket_transport_win32_ut/socket_transport_win32_ut.c index 2778e52b..2ab541f4 100644 --- a/win32/tests/socket_transport_win32_ut/socket_transport_win32_ut.c +++ b/win32/tests/socket_transport_win32_ut/socket_transport_win32_ut.c @@ -2113,6 +2113,7 @@ TEST_FUNCTION(socket_transport_get_local_address_hostname_NULL_fail) socket_transport_destroy(socket_handle); } +// Test_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. ] TEST_FUNCTION(socket_transport_get_local_address_address_count_NULL_fail) { //arrange @@ -2136,6 +2137,13 @@ TEST_FUNCTION(socket_transport_get_local_address_address_count_NULL_fail) socket_transport_destroy(socket_handle); } +// Tests_SOCKET_TRANSPORT_WIN32_11_004: [ socket_transport_get_local_address shall call sm_exec_begin ] +// Tests_SOCKET_TRANSPORT_WIN32_11_005: [ socket_transport_get_local_address shall call get the hostname by calling gethostname. ] +// Tests_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. ] +// Tests_SOCKET_TRANSPORT_WIN32_11_007: [ socket_transport_get_local_address shall allocate the LOCAL_ADDRESS array. ] +// Tests_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. ] +// Tests_SOCKET_TRANSPORT_WIN32_11_009: [ socket_transport_get_local_address shall call sm_exec_end. ] +// Tests_SOCKET_TRANSPORT_WIN32_11_010: [ On success socket_transport_get_local_address shall return 0. ] TEST_FUNCTION(socket_transport_get_local_address_success) { //arrange @@ -2182,6 +2190,46 @@ TEST_FUNCTION(socket_transport_get_local_address_success) free(local_address_list); } +// Tests_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. ] +TEST_FUNCTION(socket_transport_get_local_address_invalid_address_list_success) +{ + //arrange + SOCKET_TRANSPORT_HANDLE socket_handle = socket_transport_create_client(); + ASSERT_IS_NOT_NULL(socket_handle); + ASSERT_ARE_EQUAL(int, 0, socket_transport_connect(socket_handle, TEST_HOSTNAME, TEST_PORT, TEST_CONNECTION_TIMEOUT)); + umock_c_reset_all_calls(); + + char hostname[MAX_GET_HOST_NAME_LEN]; + const char* ip_address_list[] = { + "10.0.0.1", + NULL + }; + + struct hostent test_host_info = { 0 }; + test_host_info.h_addrtype = 1; + test_host_info.h_addr_list = ip_address_list; + LOCAL_ADDRESS* local_address_list; + uint32_t address_count; + + STRICT_EXPECTED_CALL(sm_exec_begin(IGNORED_ARG)); + STRICT_EXPECTED_CALL(gethostname(IGNORED_ARG, MAX_GET_HOST_NAME_LEN)); + STRICT_EXPECTED_CALL(gethostbyname(IGNORED_ARG)) + .SetReturn(&test_host_info); + STRICT_EXPECTED_CALL(sm_exec_end(IGNORED_ARG)); + + //act + int result = socket_transport_get_local_address(socket_handle, hostname, &local_address_list, &address_count); + + //assert + ASSERT_ARE_NOT_EQUAL(int, 0, result); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + + // Cleanup + socket_transport_disconnect(socket_handle); + socket_transport_destroy(socket_handle); +} + +// Tests_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. ] TEST_FUNCTION(socket_transport_get_local_address_no_address_list_success) { //arrange @@ -2208,6 +2256,7 @@ TEST_FUNCTION(socket_transport_get_local_address_no_address_list_success) socket_transport_destroy(socket_handle); } +// Tests_SOCKET_TRANSPORT_WIN32_11_010: [ On success socket_transport_get_local_address shall return 0. ] TEST_FUNCTION(socket_transport_get_local_address_fail) { //arrange From dd1ad9dc516a6dcd5e3fc505c97cfd563ca85b16 Mon Sep 17 00:00:00 2001 From: Jelani Brandon Date: Thu, 24 Oct 2024 09:24:48 -0700 Subject: [PATCH 04/12] adding socket address to linux --- .../socket_transport_linux_requirements.md | 33 ++- linux/src/socket_transport_linux.c | 74 +++-- .../socket_transport_linux_ut/socket_mocked.h | 11 + .../socket_transport_linux_ut.c | 277 ++++++++++++++++++ .../socket_transport_win32_requirements.md | 6 +- win32/src/socket_transport_win32.c | 1 + 6 files changed, 378 insertions(+), 24 deletions(-) diff --git a/linux/devdoc/socket_transport_linux_requirements.md b/linux/devdoc/socket_transport_linux_requirements.md index df8ba297..b20dd409 100644 --- a/linux/devdoc/socket_transport_linux_requirements.md +++ b/linux/devdoc/socket_transport_linux_requirements.md @@ -66,6 +66,7 @@ MOCKABLE_FUNCTION(, SOCKET_RECEIVE_RESULT, socket_transport_receive, SOCKET_TRAN MOCKABLE_FUNCTION(, SOCKET_HANDLE, socket_transport_get_underlying_socket, SOCKET_TRANSPORT_HANDLE, socket_transport); MOCKABLE_FUNCTION(, bool, socket_transport_is_valid_socket, SOCKET_TRANSPORT_HANDLE, socket_transport_handle); +MOCKABLE_FUNCTION(, 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); ``` ### socket_transport_create_client @@ -344,4 +345,34 @@ MOCKABLE_FUNCTION(, bool, socket_transport_is_valid_socket, SOCKET_TRANSPORT_HAN **SOCKET_TRANSPORT_LINUX_11_094: [** If the socket inside `socket_transport_handle` is an `INVALID_SOCKET`, `socket_transport_is_valid_socket` shall fail and return `false`. **]** -**SOCKET_TRANSPORT_LINUX_11_095: [** On success, `socket_transport_is_valid_socket` shall return `true`. **]** \ No newline at end of file +**SOCKET_TRANSPORT_LINUX_11_095: [** On success, `socket_transport_is_valid_socket` shall return `true`. **]** + +### socket_transport_get_local_address + +```c +MOCKABLE_FUNCTION(, 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); +``` + +`socket_transport_get_local_address` gets the interface addresses and hostname of the current machine. + +**SOCKET_TRANSPORT_LINUX_11_098: [** If `socket_transport` is `NULL`, `socket_transport_get_local_address` shall fail and return a non-zero value. **]** + +**SOCKET_TRANSPORT_LINUX_11_099: [** If `hostname` is `NULL`, `socket_transport_get_local_address` shall fail and return a non-zero value. **]** + +**SOCKET_TRANSPORT_LINUX_11_100: [** 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. **]** + +**SOCKET_TRANSPORT_LINUX_11_101: [** `socket_transport_get_local_address` shall call `sm_exec_begin`. **]** + +**SOCKET_TRANSPORT_LINUX_11_102: [** `socket_transport_get_local_address` shall call get the `hostname` by calling `gethostname`. **]** + +**SOCKET_TRANSPORT_LINUX_11_103: [** If `local_address_list` is not `NULL`, `socket_transport_get_local_address` shall call `getifaddrs` to get the link list of ifaddrs. **]** + +**SOCKET_TRANSPORT_LINUX_11_104: [** `socket_transport_get_local_address` shall allocate the `LOCAL_ADDRESS` array for each ifaddrs with a `sa_family` of `AF_INET` and the interface is up and running. **]** + +**SOCKET_TRANSPORT_LINUX_11_105: [** For each IP in the `ifaddr` object if the `sa_family` is `AF_INET` and the interface is up and running and it's not a loopback, `socket_transport_get_local_address` shall retrieve the name of the address by calling `getnameinfo`. **]** + +**SOCKET_TRANSPORT_LINUX_11_106: [** `socket_transport_get_local_address` shall call `sm_exec_end`. **]** + +**SOCKET_TRANSPORT_LINUX_11_107: [** On success `socket_transport_get_local_address` shall return 0. **]** + +**SOCKET_TRANSPORT_LINUX_11_108: [** If any failure is encountered, `socket_transport_get_local_address` shall fail and return a non-zero value. **]** diff --git a/linux/src/socket_transport_linux.c b/linux/src/socket_transport_linux.c index 89c7d60e..aa19a3d3 100644 --- a/linux/src/socket_transport_linux.c +++ b/linux/src/socket_transport_linux.c @@ -12,6 +12,10 @@ #include #include #include +#include +#include +#include +#include #include "macro_utils/macro_utils.h" // IWYU pragma: keep @@ -36,7 +40,11 @@ MU_DEFINE_ENUM(SOCKET_IO_TYPE, SOCKET_IO_TYPE_VALUES) MU_DEFINE_ENUM_STRINGS(SOCKET_IO_TYPE, SOCKET_IO_TYPE_VALUES) +MU_DEFINE_ENUM_STRINGS(SOCKET_SEND_RESULT, SOCKET_SEND_RESULT_VALUES) +MU_DEFINE_ENUM_STRINGS(SOCKET_RECEIVE_RESULT, SOCKET_RECEIVE_RESULT_VALUES) +MU_DEFINE_ENUM_STRINGS(SOCKET_ACCEPT_RESULT, SOCKET_ACCEPT_RESULT_VALUES) MU_DEFINE_ENUM_STRINGS(SOCKET_TYPE, SOCKET_TYPE_VALUES) +MU_DEFINE_ENUM_STRINGS(ADDRESS_TYPE, ADDRESS_TYPE_VALUES) typedef struct SOCKET_TRANSPORT_TAG { @@ -806,12 +814,14 @@ bool socket_transport_is_valid_socket(SOCKET_TRANSPORT_HANDLE socket_transport_h return result; } - 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_LINUX_11_098: [ 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_LINUX_11_099: [ If hostname is NULL, socket_transport_get_local_address shall fail and return a non-zero value. ] hostname == NULL || + // Codes_SOCKET_TRANSPORT_LINUX_11_100: [ 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) ) { @@ -821,17 +831,20 @@ int socket_transport_get_local_address(SOCKET_TRANSPORT_HANDLE socket_transport, } else { + // Codes_SOCKET_TRANSPORT_LINUX_11_101: [ 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. ] + // Codes_SOCKET_TRANSPORT_LINUX_11_108: [ 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_LINUX_11_102: [ socket_transport_get_local_address shall call get the hostname by calling gethostname. ] if (gethostname(hostname, MAX_GET_HOST_NAME_LEN) == INVALID_SOCKET) { + // Codes_SOCKET_TRANSPORT_LINUX_11_108: [ If any failure is encountered, socket_transport_get_local_address shall fail and return a non-zero value. ] LogErrorNo("Unable to get hostname"); result = MU_FAILURE; } @@ -840,8 +853,10 @@ int socket_transport_get_local_address(SOCKET_TRANSPORT_HANDLE socket_transport, if (local_address_list != NULL) { struct ifaddrs *ifaddr, *ifa; + // Codes_SOCKET_TRANSPORT_LINUX_11_103: [ If local_address_list is not NULL, socket_transport_get_local_address shall call getifaddrs to get the link list of ifaddrs. ] if (getifaddrs(&ifaddr) == -1) { + // Codes_SOCKET_TRANSPORT_LINUX_11_108: [ If any failure is encountered, socket_transport_get_local_address shall fail and return a non-zero value. ] LogErrorNo("Failure getting interface addresses"); result = MU_FAILURE; } @@ -850,13 +865,20 @@ int socket_transport_get_local_address(SOCKET_TRANSPORT_HANDLE socket_transport, uint32_t total_count = 0; for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { - total_count++; + if (ifa->ifa_addr->sa_family == AF_INET) + { + if (ifa->ifa_flags & IFF_UP && ifa->ifa_flags & IFF_RUNNING && !(ifa->ifa_flags & IFF_LOOPBACK)) + { + total_count++; + } + } } + // Codes_SOCKET_TRANSPORT_LINUX_11_104: [ socket_transport_get_local_address shall allocate the LOCAL_ADDRESS array for each ifaddrs with a sa_family of AF_INET and the interface is up and running. ] LOCAL_ADDRESS* temp_list = malloc_2(sizeof(LOCAL_ADDRESS), total_count); 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. ] + // Codes_SOCKET_TRANSPORT_LINUX_11_108: [ 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 ", MAX_LOCAL_ADDRESS_LEN: %d)", total_count, MAX_LOCAL_ADDRESS_LEN); result = MU_FAILURE; } @@ -865,46 +887,56 @@ int socket_transport_get_local_address(SOCKET_TRANSPORT_HANDLE socket_transport, bool failure = false; uint32_t address_index = 0; + // Codes_SOCKET_TRANSPORT_LINUX_11_105: [ For each IP in the ifaddr object if the sa_family is AF_INET and the interface is up and running and it's not a loopback, socket_transport_get_local_address shall retrieve the name of the address by calling getnameinfo. ] for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { if (ifa->ifa_addr != NULL) { - int family = ifa->ifa_addr->sa_family; - - temp_list[address_index].address_type = ADDRESS_INET; - - if (getnameinfo( ifa->ifa_addr, (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6), temp_list[address_index].address, MAX_LOCAL_ADDRESS_LEN, NULL, 0, NI_NUMERICHOST) != 0) - { - //LogLastError("failure in retreiving network name"); - failure = true; - break; - } - else + if (ifa->ifa_addr->sa_family == AF_INET) { - printf("flag: %u\n", ifa->ifa_flags); - printf("type: %s\n", ifa->ifa_name); - printf("Name: %s\n", temp_list[address_index].address); - address_index++; + char temp_address[MAX_LOCAL_ADDRESS_LEN]; + int err_result = getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in), temp_address, MAX_LOCAL_ADDRESS_LEN, NULL, 0, NI_NUMERICHOST); + if (err_result != 0) + { + if (err_result != EAI_FAMILY) + { + LogError("failure in retreiving network name error: %d", err_result); + failure = true; + break; + } + } + else + { + if (ifa->ifa_flags & IFF_UP && ifa->ifa_flags & IFF_RUNNING && !(ifa->ifa_flags & IFF_LOOPBACK)) + { + temp_list[address_index].address_type = ADDRESS_INET; + memcpy(temp_list[address_index].address, temp_address, MAX_LOCAL_ADDRESS_LEN); + 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. ] + // Codes_SOCKET_TRANSPORT_LINUX_11_108: [ 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; + *address_count = address_index; *local_address_list = temp_list; + // Codes_SOCKET_TRANSPORT_LINUX_11_107: [ On success socket_transport_get_local_address shall return 0. ] result = 0; } } + freeifaddrs(ifaddr); } } } + // Codes_SOCKET_TRANSPORT_LINUX_11_106: [ socket_transport_get_local_address shall call sm_exec_end. ] sm_exec_end(socket_transport->sm); } } diff --git a/linux/tests/socket_transport_linux_ut/socket_mocked.h b/linux/tests/socket_transport_linux_ut/socket_mocked.h index 33893ac9..d4c65adb 100644 --- a/linux/tests/socket_transport_linux_ut/socket_mocked.h +++ b/linux/tests/socket_transport_linux_ut/socket_mocked.h @@ -7,6 +7,9 @@ #include #include +#include +#include +#include #include "umock_c/umock_c_prod.h" @@ -29,6 +32,10 @@ struct addrinfo; #define accept mocked_accept #define close mocked_close #define shutdown mocked_shutdown +#define gethostname mocked_gethostname +#define getifaddrs mocked_getifaddrs +#define freeifaddrs mocked_freeifaddrs +#define getnameinfo mocked_getnameinfo #define fcntl mocked_fcntl MOCKABLE_FUNCTION(, const char*, mocked_inet_ntop, int, af, const void*, cp, char*, buf, socklen_t, len); @@ -46,6 +53,10 @@ MOCKABLE_FUNCTION(, ssize_t, mocked_recv, SOCKET_HANDLE, sockfd, void*, buf, siz MOCKABLE_FUNCTION(, SOCKET_HANDLE, mocked_accept, SOCKET_HANDLE, s, struct sockaddr*, addr, socklen_t*, addrlen); MOCKABLE_FUNCTION(, int, mocked_close, SOCKET_HANDLE, s); MOCKABLE_FUNCTION(, int, mocked_shutdown, SOCKET_HANDLE, __fd, int, __how); +MOCKABLE_FUNCTION(, int, mocked_gethostname, char*, name, size_t, namelen); +MOCKABLE_FUNCTION(, int, mocked_getifaddrs, struct ifaddrs**, ifap); +MOCKABLE_FUNCTION(, void, mocked_freeifaddrs, struct ifaddrs*, ifap); +MOCKABLE_FUNCTION(, int, mocked_getnameinfo, const struct sockaddr*, addr, socklen_t, addrlen, char*, host, socklen_t, hostlen, char*, serv, socklen_t, servlen, int, flags); extern int mocked_fcntl(int __fd, int __cmd, ...); #endif // SOCKET_MOCKED_H diff --git a/linux/tests/socket_transport_linux_ut/socket_transport_linux_ut.c b/linux/tests/socket_transport_linux_ut/socket_transport_linux_ut.c index 6b9e0c7d..b210c3e9 100644 --- a/linux/tests/socket_transport_linux_ut/socket_transport_linux_ut.c +++ b/linux/tests/socket_transport_linux_ut/socket_transport_linux_ut.c @@ -10,6 +10,9 @@ #include #include #include +#include +#include +#include #include "macro_utils/macro_utils.h" // IWYU pragma: keep @@ -139,6 +142,13 @@ static ssize_t my_recv(SOCKET_HANDLE sockfd, void* buf, size_t len, int flags) return TEST_BYTES_RECV; } +static int my_gethostname(char* name, size_t namelen) +{ + (void)namelen; + strcpy(name, TEST_INCOMING_HOSTNAME); + return 0; +} + BEGIN_TEST_SUITE(TEST_SUITE_NAME_FROM_CMAKE) TEST_SUITE_INITIALIZE(suite_init) @@ -150,7 +160,9 @@ TEST_SUITE_INITIALIZE(suite_init) REGISTER_SM_GLOBAL_MOCK_HOOK(); REGISTER_GLOBAL_MOCK_HOOK(malloc, real_gballoc_ll_malloc); + REGISTER_GLOBAL_MOCK_HOOK(malloc_2, real_gballoc_ll_malloc_2); REGISTER_GLOBAL_MOCK_FAIL_RETURN(malloc, NULL); + REGISTER_GLOBAL_MOCK_FAIL_RETURN(malloc_2, NULL); REGISTER_GLOBAL_MOCK_HOOK(free, real_gballoc_ll_free); REGISTER_GLOBAL_MOCK_HOOK(socket, my_socket); @@ -170,6 +182,10 @@ TEST_SUITE_INITIALIZE(suite_init) REGISTER_GLOBAL_MOCK_FAIL_RETURN(send, INVALID_SOCKET); REGISTER_GLOBAL_MOCK_HOOK(recv, my_recv); REGISTER_GLOBAL_MOCK_FAIL_RETURN(recv, INVALID_SOCKET); + REGISTER_GLOBAL_MOCK_HOOK(gethostname, my_gethostname); + REGISTER_GLOBAL_MOCK_FAIL_RETURN(gethostname, -1); + REGISTER_GLOBAL_MOCK_FAIL_RETURN(getnameinfo, EAI_SYSTEM); + REGISTER_GLOBAL_MOCK_FAIL_RETURN(getifaddrs, -1); REGISTER_TYPE(SM_RESULT, SM_RESULT); @@ -1708,4 +1724,265 @@ TEST_FUNCTION(socket_transport_is_valid_socket_INVALID_SOCKET) socket_transport_destroy(test_socket_transport); } +// socket_transport_get_local_address + +// Tests_SOCKET_TRANSPORT_LINUX_11_098: [ If socket_transport is NULL, socket_transport_get_local_address shall fail and return a non-zero value. ] +TEST_FUNCTION(socket_transport_get_local_address_handle_NULL_fail) +{ + //arrange + char hostname[MAX_GET_HOST_NAME_LEN]; + LOCAL_ADDRESS* local_address_list; + uint32_t address_count; + + //act + int result = socket_transport_get_local_address(NULL, hostname, &local_address_list, &address_count); + + //assert + ASSERT_ARE_NOT_EQUAL(int, 0, result); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + + // Cleanup +} + +// Tests_SOCKET_TRANSPORT_LINUX_11_099: [ If hostname is NULL, socket_transport_get_local_address shall fail and return a non-zero value. ] +TEST_FUNCTION(socket_transport_get_local_address_hostname_NULL_fail) +{ + //arrange + SOCKET_TRANSPORT_HANDLE socket_handle = socket_transport_create_client(); + ASSERT_IS_NOT_NULL(socket_handle); + ASSERT_ARE_EQUAL(int, 0, socket_transport_connect(socket_handle, TEST_HOSTNAME, TEST_PORT, TEST_CONNECTION_TIMEOUT)); + umock_c_reset_all_calls(); + + LOCAL_ADDRESS* local_address_list; + uint32_t address_count; + + //act + int result = socket_transport_get_local_address(socket_handle, NULL, &local_address_list, &address_count); + + //assert + ASSERT_ARE_NOT_EQUAL(int, 0, result); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + + // Cleanup + socket_transport_disconnect(socket_handle); + socket_transport_destroy(socket_handle); +} + +// Tests_SOCKET_TRANSPORT_LINUX_11_100: [ 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. ] +TEST_FUNCTION(socket_transport_get_local_address_address_count_NULL_fail) +{ + //arrange + SOCKET_TRANSPORT_HANDLE socket_handle = socket_transport_create_client(); + ASSERT_IS_NOT_NULL(socket_handle); + ASSERT_ARE_EQUAL(int, 0, socket_transport_connect(socket_handle, TEST_HOSTNAME, TEST_PORT, TEST_CONNECTION_TIMEOUT)); + umock_c_reset_all_calls(); + + char hostname[MAX_GET_HOST_NAME_LEN]; + LOCAL_ADDRESS* local_address_list; + + //act + int result = socket_transport_get_local_address(socket_handle, hostname, &local_address_list, NULL); + + //assert + ASSERT_ARE_NOT_EQUAL(int, 0, result); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + + // Cleanup + socket_transport_disconnect(socket_handle); + socket_transport_destroy(socket_handle); +} + +// Tests_SOCKET_TRANSPORT_LINUX_11_101: [ socket_transport_get_local_address shall call sm_exec_begin. ] +// Tests_SOCKET_TRANSPORT_LINUX_11_102: [ socket_transport_get_local_address shall call get the hostname by calling gethostname. ] +// Tests_SOCKET_TRANSPORT_LINUX_11_103: [ If local_address_list is not NULL, socket_transport_get_local_address shall call getifaddrs to get the link list of ifaddrs. ] +// Tests_SOCKET_TRANSPORT_LINUX_11_104: [ socket_transport_get_local_address shall allocate the LOCAL_ADDRESS array for each ifaddrs with a sa_family of AF_INET and the interface is up and running. ] +// Tests_SOCKET_TRANSPORT_LINUX_11_105: [ For each IP in the ifaddr object if the sa_family is AF_INET and the interface is up and running and it's not a loopback, socket_transport_get_local_address shall retrieve the name of the address by calling getnameinfo. ] +// Tests_SOCKET_TRANSPORT_LINUX_11_106: [ socket_transport_get_local_address shall call sm_exec_end. ] +// Tests_SOCKET_TRANSPORT_LINUX_11_107: [ On success socket_transport_get_local_address shall return 0. ] +TEST_FUNCTION(socket_transport_get_local_address_success) +{ + //arrange + SOCKET_TRANSPORT_HANDLE socket_handle = socket_transport_create_client(); + ASSERT_IS_NOT_NULL(socket_handle); + ASSERT_ARE_EQUAL(int, 0, socket_transport_connect(socket_handle, TEST_HOSTNAME, TEST_PORT, TEST_CONNECTION_TIMEOUT)); + umock_c_reset_all_calls(); + + char hostname[MAX_GET_HOST_NAME_LEN]; + LOCAL_ADDRESS* local_address_list; + uint32_t address_count; + + struct ifaddrs address_info_1 = {0}; + struct sockaddr ifa_addr_1 = {0}; + struct ifaddrs address_info_2; + + ifa_addr_1.sa_family = AF_INET; + + address_info_1.ifa_next = &address_info_2; + address_info_1.ifa_name = "lo"; + address_info_1.ifa_flags = IFF_LOOPBACK | IFF_UP | IFF_RUNNING | IFF_POINTOPOINT; + address_info_1.ifa_addr = &ifa_addr_1; + + address_info_2.ifa_next = NULL; + address_info_2.ifa_name = "enp0s31f6"; + address_info_2.ifa_flags = IFF_UP | IFF_RUNNING | IFF_POINTOPOINT; + address_info_2.ifa_addr = &ifa_addr_1; + const char* actual_address = "192.168.1.21"; + + STRICT_EXPECTED_CALL(sm_exec_begin(IGNORED_ARG)); + STRICT_EXPECTED_CALL(gethostname(IGNORED_ARG, MAX_GET_HOST_NAME_LEN)); + STRICT_EXPECTED_CALL(getifaddrs(IGNORED_ARG)) + .CopyOutArgumentBuffer_ifap(&address_info_1, sizeof(struct ifaddrs)); + STRICT_EXPECTED_CALL(malloc_2(IGNORED_ARG, IGNORED_ARG)); + + STRICT_EXPECTED_CALL(getnameinfo(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, NULL, 0, IGNORED_ARG)) + .CopyOutArgumentBuffer_host(actual_address, sizeof(actual_address)); + + STRICT_EXPECTED_CALL(freeifaddrs(IGNORED_ARG)); + STRICT_EXPECTED_CALL(sm_exec_end(IGNORED_ARG)); + + //act + int result = socket_transport_get_local_address(socket_handle, hostname, &local_address_list, &address_count); + + //assert + ASSERT_ARE_EQUAL(int, 0, result); + ASSERT_ARE_EQUAL(int, 1, address_count); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + + // Cleanup + socket_transport_disconnect(socket_handle); + socket_transport_destroy(socket_handle); + free(local_address_list); +} + +// Tests_SOCKET_TRANSPORT_LINUX_11_108: [ If any failure is encountered, socket_transport_get_local_address shall fail and return a non-zero value. ] +TEST_FUNCTION(socket_transport_get_local_address_invalid_address_list_fail) +{ + //arrange + SOCKET_TRANSPORT_HANDLE socket_handle = socket_transport_create_client(); + ASSERT_IS_NOT_NULL(socket_handle); + ASSERT_ARE_EQUAL(int, 0, socket_transport_connect(socket_handle, TEST_HOSTNAME, TEST_PORT, TEST_CONNECTION_TIMEOUT)); + umock_c_reset_all_calls(); + + char hostname[MAX_GET_HOST_NAME_LEN]; + const char* ip_address_list[] = { + "10.0.0.1", + NULL + }; + (void)ip_address_list; + + LOCAL_ADDRESS* local_address_list; + uint32_t address_count; + + STRICT_EXPECTED_CALL(sm_exec_begin(IGNORED_ARG)); + STRICT_EXPECTED_CALL(gethostname(IGNORED_ARG, MAX_GET_HOST_NAME_LEN)); + STRICT_EXPECTED_CALL(getifaddrs(IGNORED_ARG)) + .SetReturn(-1); + STRICT_EXPECTED_CALL(sm_exec_end(IGNORED_ARG)); + + //act + int result = socket_transport_get_local_address(socket_handle, hostname, &local_address_list, &address_count); + + //assert + ASSERT_ARE_NOT_EQUAL(int, 0, result); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + + // Cleanup + socket_transport_disconnect(socket_handle); + socket_transport_destroy(socket_handle); +} + +// Tests_SOCKET_TRANSPORT_LINUX_11_101: [ socket_transport_get_local_address shall call sm_exec_begin. ] +// Tests_SOCKET_TRANSPORT_LINUX_11_102: [ socket_transport_get_local_address shall call get the hostname by calling gethostname. ] +// Tests_SOCKET_TRANSPORT_LINUX_11_106: [ socket_transport_get_local_address shall call sm_exec_end. ] +// Tests_SOCKET_TRANSPORT_LINUX_11_107: [ On success socket_transport_get_local_address shall return 0. ] +TEST_FUNCTION(socket_transport_get_local_address_no_address_list_success) +{ + //arrange + SOCKET_TRANSPORT_HANDLE socket_handle = socket_transport_create_client(); + ASSERT_IS_NOT_NULL(socket_handle); + ASSERT_ARE_EQUAL(int, 0, socket_transport_connect(socket_handle, TEST_HOSTNAME, TEST_PORT, TEST_CONNECTION_TIMEOUT)); + umock_c_reset_all_calls(); + + char hostname[MAX_GET_HOST_NAME_LEN]; + + STRICT_EXPECTED_CALL(sm_exec_begin(IGNORED_ARG)); + STRICT_EXPECTED_CALL(gethostname(IGNORED_ARG, MAX_GET_HOST_NAME_LEN)); + STRICT_EXPECTED_CALL(sm_exec_end(IGNORED_ARG)); + + //act + int result = socket_transport_get_local_address(socket_handle, hostname, NULL, NULL); + + //assert + ASSERT_ARE_EQUAL(int, 0, result); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + + // Cleanup + socket_transport_disconnect(socket_handle); + socket_transport_destroy(socket_handle); +} + +// Tests_SOCKET_TRANSPORT_LINUX_11_108: [ If any failure is encountered, socket_transport_get_local_address shall fail and return a non-zero value. ] +TEST_FUNCTION(socket_transport_get_local_address_fail) +{ + //arrange + SOCKET_TRANSPORT_HANDLE socket_handle = socket_transport_create_client(); + ASSERT_IS_NOT_NULL(socket_handle); + ASSERT_ARE_EQUAL(int, 0, socket_transport_connect(socket_handle, TEST_HOSTNAME, TEST_PORT, TEST_CONNECTION_TIMEOUT)); + umock_c_reset_all_calls(); + + char hostname[MAX_GET_HOST_NAME_LEN]; + LOCAL_ADDRESS* local_address_list; + uint32_t address_count; + + struct ifaddrs address_info_1 = {0}; + struct sockaddr ifa_addr_1 = {0}; + struct ifaddrs address_info_2; + + ifa_addr_1.sa_family = AF_INET; + + address_info_1.ifa_next = &address_info_2; + address_info_1.ifa_name = "lo"; + address_info_1.ifa_flags = IFF_LOOPBACK | IFF_UP | IFF_RUNNING | IFF_POINTOPOINT; + address_info_1.ifa_addr = &ifa_addr_1; + + address_info_2.ifa_next = NULL; + address_info_2.ifa_name = "enp0s31f6"; + address_info_2.ifa_flags = IFF_UP | IFF_RUNNING | IFF_POINTOPOINT; + address_info_2.ifa_addr = &ifa_addr_1; + const char* actual_address = "192.168.1.21"; + + STRICT_EXPECTED_CALL(sm_exec_begin(IGNORED_ARG)); + STRICT_EXPECTED_CALL(gethostname(IGNORED_ARG, MAX_GET_HOST_NAME_LEN)); + STRICT_EXPECTED_CALL(getifaddrs(IGNORED_ARG)) + .CopyOutArgumentBuffer_ifap(&address_info_1, sizeof(struct ifaddrs)); + STRICT_EXPECTED_CALL(malloc_2(IGNORED_ARG, IGNORED_ARG)); + + STRICT_EXPECTED_CALL(getnameinfo(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, NULL, 0, IGNORED_ARG)) + .CopyOutArgumentBuffer_host(actual_address, sizeof(actual_address)); + + STRICT_EXPECTED_CALL(freeifaddrs(IGNORED_ARG)); + STRICT_EXPECTED_CALL(sm_exec_end(IGNORED_ARG)); + + umock_c_negative_tests_snapshot(); + + for (size_t index = 0; index < umock_c_negative_tests_call_count(); index++) + { + if (umock_c_negative_tests_can_call_fail(index)) + { + umock_c_negative_tests_reset(); + umock_c_negative_tests_fail_call(index); + + //act + int result = socket_transport_get_local_address(socket_handle, hostname, &local_address_list, &address_count); + + //assert + ASSERT_ARE_NOT_EQUAL(int, 0, result, "On failed call %zu", index); + } + } + + // Cleanup + socket_transport_disconnect(socket_handle); + socket_transport_destroy(socket_handle); +} + END_TEST_SUITE(TEST_SUITE_NAME_FROM_CMAKE) diff --git a/win32/devdoc/socket_transport_win32_requirements.md b/win32/devdoc/socket_transport_win32_requirements.md index 0428efc4..5011fa15 100644 --- a/win32/devdoc/socket_transport_win32_requirements.md +++ b/win32/devdoc/socket_transport_win32_requirements.md @@ -389,13 +389,15 @@ MOCKABLE_FUNCTION(, bool, socket_transport_is_valid_socket, SOCKET_TRANSPORT_HAN MOCKABLE_FUNCTION(, 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); ``` +`socket_transport_get_local_address` gets the interface addresses and hostname of the current machine. + **SOCKET_TRANSPORT_WIN32_11_001: [** If `socket_transport` is `NULL`, `socket_transport_get_local_address` shall fail and return a non-zero value. **]** **SOCKET_TRANSPORT_WIN32_11_002: [** If `hostname` is `NULL`, `socket_transport_get_local_address` shall fail and return a non-zero value. **]** **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. **]** -**SOCKET_TRANSPORT_WIN32_11_004: [** `socket_transport_get_local_address` shall call `sm_exec_begin` **]** +**SOCKET_TRANSPORT_WIN32_11_004: [** `socket_transport_get_local_address` shall call `sm_exec_begin`. **]** **SOCKET_TRANSPORT_WIN32_11_005: [** `socket_transport_get_local_address` shall call get the `hostname` by calling `gethostname`. **]** @@ -403,7 +405,7 @@ MOCKABLE_FUNCTION(, int, socket_transport_get_local_address, SOCKET_TRANSPORT_HA **SOCKET_TRANSPORT_WIN32_11_007: [** `socket_transport_get_local_address` shall allocate the `LOCAL_ADDRESS` array. **]** -**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`. **]** +**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`. **]** **SOCKET_TRANSPORT_WIN32_11_009: [** `socket_transport_get_local_address` shall call `sm_exec_end`. **]** diff --git a/win32/src/socket_transport_win32.c b/win32/src/socket_transport_win32.c index 4bd669b0..9b695dea 100644 --- a/win32/src/socket_transport_win32.c +++ b/win32/src/socket_transport_win32.c @@ -40,6 +40,7 @@ MU_DEFINE_ENUM_STRINGS(SOCKET_SEND_RESULT, SOCKET_SEND_RESULT_VALUES) MU_DEFINE_ENUM_STRINGS(SOCKET_RECEIVE_RESULT, SOCKET_RECEIVE_RESULT_VALUES) MU_DEFINE_ENUM_STRINGS(SOCKET_ACCEPT_RESULT, SOCKET_ACCEPT_RESULT_VALUES) MU_DEFINE_ENUM_STRINGS(SOCKET_TYPE, SOCKET_TYPE_VALUES) +MU_DEFINE_ENUM_STRINGS(ADDRESS_TYPE, ADDRESS_TYPE_VALUES) typedef struct SOCKET_TRANSPORT_TAG { From cf384a10d39c74e79ca2510863a6f27587558354 Mon Sep 17 00:00:00 2001 From: Jelani Brandon Date: Fri, 25 Oct 2024 07:03:56 -0700 Subject: [PATCH 05/12] fix struct in int test --- common/reals/real_socket_transport_renames.h | 3 ++- interfaces/tests/socket_transport_int/socket_transport_int.c | 2 ++ linux/tests/socket_transport_linux_ut/socket_mocked.c | 2 ++ linux/tests/socket_transport_linux_ut/socket_mocked.h | 1 + 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/common/reals/real_socket_transport_renames.h b/common/reals/real_socket_transport_renames.h index 78db8806..92392d5e 100644 --- a/common/reals/real_socket_transport_renames.h +++ b/common/reals/real_socket_transport_renames.h @@ -18,4 +18,5 @@ #define SOCKET_RECEIVE_RESULT real_SOCKET_RECEIVE_RESULT #define SOCKET_ACCEPT_RESULT real_SOCKET_ACCEPT_RESULT #define SOCKET_TYPE real_SOCKET_TYPE -#define SOCKET_IO_TYPE real_SOCKET_IO_TYPE \ No newline at end of file +#define SOCKET_IO_TYPE real_SOCKET_IO_TYPE +#define ADDRESS_TYPE real_ADDRESS_TYPE \ No newline at end of file diff --git a/interfaces/tests/socket_transport_int/socket_transport_int.c b/interfaces/tests/socket_transport_int/socket_transport_int.c index 03368455..d65572b8 100644 --- a/interfaces/tests/socket_transport_int/socket_transport_int.c +++ b/interfaces/tests/socket_transport_int/socket_transport_int.c @@ -48,6 +48,8 @@ TEST_DEFINE_ENUM_TYPE(SOCKET_SEND_RESULT, SOCKET_SEND_RESULT_VALUES); TEST_DEFINE_ENUM_TYPE(SOCKET_RECEIVE_RESULT, SOCKET_RECEIVE_RESULT_VALUES); TEST_DEFINE_ENUM_TYPE(SOCKET_ACCEPT_RESULT, SOCKET_ACCEPT_RESULT_VALUES); TEST_DEFINE_ENUM_TYPE(THREADAPI_RESULT, THREADAPI_RESULT_VALUES); +TEST_DEFINE_ENUM_TYPE(SOCKET_TYPE, SOCKET_TYPE_VALUES); +TEST_DEFINE_ENUM_TYPE(ADDRESS_TYPE, ADDRESS_TYPE_VALUES); BEGIN_TEST_SUITE(TEST_SUITE_NAME_FROM_CMAKE) diff --git a/linux/tests/socket_transport_linux_ut/socket_mocked.c b/linux/tests/socket_transport_linux_ut/socket_mocked.c index ac471ac7..25c95247 100644 --- a/linux/tests/socket_transport_linux_ut/socket_mocked.c +++ b/linux/tests/socket_transport_linux_ut/socket_mocked.c @@ -1,5 +1,7 @@ // Copyright (C) Microsoft Corporation. All rights reserved. +#include +#include #include // IWYU pragma: keep #include "socket_mocked.h" diff --git a/linux/tests/socket_transport_linux_ut/socket_mocked.h b/linux/tests/socket_transport_linux_ut/socket_mocked.h index d4c65adb..d49bfe92 100644 --- a/linux/tests/socket_transport_linux_ut/socket_mocked.h +++ b/linux/tests/socket_transport_linux_ut/socket_mocked.h @@ -7,6 +7,7 @@ #include #include +#include #include #include #include From 3b6e0883aed3e6c1c38d59398131a279c3ec6f63 Mon Sep 17 00:00:00 2001 From: Jelani Brandon Date: Fri, 25 Oct 2024 12:20:07 -0700 Subject: [PATCH 06/12] fixing linux code --- linux/src/socket_transport_linux.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/linux/src/socket_transport_linux.c b/linux/src/socket_transport_linux.c index aa19a3d3..db215130 100644 --- a/linux/src/socket_transport_linux.c +++ b/linux/src/socket_transport_linux.c @@ -935,6 +935,11 @@ int socket_transport_get_local_address(SOCKET_TRANSPORT_HANDLE socket_transport, freeifaddrs(ifaddr); } } + else + { + // Codes_SOCKET_TRANSPORT_LINUX_11_107: [ On success socket_transport_get_local_address shall return 0. ] + result = 0; + } } // Codes_SOCKET_TRANSPORT_LINUX_11_106: [ socket_transport_get_local_address shall call sm_exec_end. ] sm_exec_end(socket_transport->sm); From 6b295076ddf8d10019328756cd971c5cec5adad0 Mon Sep 17 00:00:00 2001 From: Jelani Brandon Date: Fri, 22 Nov 2024 09:34:39 -0800 Subject: [PATCH 07/12] fix includes --- interfaces/tests/socket_transport_int/socket_transport_int.c | 3 +++ win32/src/socket_transport_win32.c | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/interfaces/tests/socket_transport_int/socket_transport_int.c b/interfaces/tests/socket_transport_int/socket_transport_int.c index d65572b8..22063bdf 100644 --- a/interfaces/tests/socket_transport_int/socket_transport_int.c +++ b/interfaces/tests/socket_transport_int/socket_transport_int.c @@ -12,6 +12,9 @@ #include "c_logging/logger.h" // IWYU pragma: keep +#include "c_pal/gballoc_hl.h" +#include "c_pal/gballoc_hl_redirect.h" + #include "c_pal/platform.h" // IWYU pragma: keep #include "c_pal/gballoc_hl.h" #include "c_pal/socket_transport.h" diff --git a/win32/src/socket_transport_win32.c b/win32/src/socket_transport_win32.c index 9b695dea..56f3578a 100644 --- a/win32/src/socket_transport_win32.c +++ b/win32/src/socket_transport_win32.c @@ -926,11 +926,11 @@ int socket_transport_get_local_address(SOCKET_TRANSPORT_HANDLE socket_transport, // Allocate the array // Codes_SOCKET_TRANSPORT_WIN32_11_007: [ socket_transport_get_local_address shall allocate the LOCAL_ADDRESS array. ] - LOCAL_ADDRESS* temp_list = malloc_2(sizeof(LOCAL_ADDRESS), total_count); + 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 ", MAX_LOCAL_ADDRESS_LEN: %d)", total_count, MAX_LOCAL_ADDRESS_LEN); + LogError("failure in malloc_2(total_count: %" PRIu32 ", sizeof(LOCAL_ADDRESS): %zu)", total_count, sizeof(LOCAL_ADDRESS)); result = MU_FAILURE; } else From 621e9799d57cf9b754aed7d175fdbb23a8926188 Mon Sep 17 00:00:00 2001 From: Jelani Brandon Date: Fri, 22 Nov 2024 09:51:00 -0800 Subject: [PATCH 08/12] update includes --- .../tests/socket_transport_int/socket_transport_int.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/interfaces/tests/socket_transport_int/socket_transport_int.c b/interfaces/tests/socket_transport_int/socket_transport_int.c index 22063bdf..89267774 100644 --- a/interfaces/tests/socket_transport_int/socket_transport_int.c +++ b/interfaces/tests/socket_transport_int/socket_transport_int.c @@ -5,18 +5,16 @@ #include #include "testrunnerswitcher.h" -#include "c_pal/threadapi.h" -#include "c_pal/interlocked.h" #include "macro_utils/macro_utils.h" // IWYU pragma: keep #include "c_logging/logger.h" // IWYU pragma: keep #include "c_pal/gballoc_hl.h" -#include "c_pal/gballoc_hl_redirect.h" - +#include "c_pal/gballoc_hl_redirect.h" // IWYU pragma: keep #include "c_pal/platform.h" // IWYU pragma: keep -#include "c_pal/gballoc_hl.h" +#include "c_pal/threadapi.h" +#include "c_pal/interlocked.h" #include "c_pal/socket_transport.h" #include "c_pal/timer.h" // IWYU pragma: keep From e1f98bae742830def3d186707053c206cafc66f6 Mon Sep 17 00:00:00 2001 From: Jelani Brandon Date: Mon, 25 Nov 2024 13:11:20 -0800 Subject: [PATCH 09/12] update unittest for code changes --- .../socket_transport_win32_ut/socket_transport_win32_ut.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/win32/tests/socket_transport_win32_ut/socket_transport_win32_ut.c b/win32/tests/socket_transport_win32_ut/socket_transport_win32_ut.c index 2ab541f4..8c2b4227 100644 --- a/win32/tests/socket_transport_win32_ut/socket_transport_win32_ut.c +++ b/win32/tests/socket_transport_win32_ut/socket_transport_win32_ut.c @@ -2171,7 +2171,7 @@ TEST_FUNCTION(socket_transport_get_local_address_success) STRICT_EXPECTED_CALL(gethostname(IGNORED_ARG, MAX_GET_HOST_NAME_LEN)); STRICT_EXPECTED_CALL(gethostbyname(IGNORED_ARG)) .SetReturn(&test_host_info); - STRICT_EXPECTED_CALL(malloc_2(IGNORED_ARG, 2)); + STRICT_EXPECTED_CALL(malloc_2(IGNORED_ARG, IGNORED_ARG)); STRICT_EXPECTED_CALL(inet_ntop(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG)); STRICT_EXPECTED_CALL(inet_ntop(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG)); STRICT_EXPECTED_CALL(sm_exec_end(IGNORED_ARG)); @@ -2283,7 +2283,7 @@ TEST_FUNCTION(socket_transport_get_local_address_fail) STRICT_EXPECTED_CALL(gethostname(IGNORED_ARG, MAX_GET_HOST_NAME_LEN)); STRICT_EXPECTED_CALL(gethostbyname(IGNORED_ARG)) .SetReturn(&test_host_info); - STRICT_EXPECTED_CALL(malloc_2(IGNORED_ARG, 2)); + STRICT_EXPECTED_CALL(malloc_2(IGNORED_ARG, IGNORED_ARG)); STRICT_EXPECTED_CALL(inet_ntop(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG)); STRICT_EXPECTED_CALL(inet_ntop(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG)); STRICT_EXPECTED_CALL(sm_exec_end(IGNORED_ARG)); @@ -2300,7 +2300,7 @@ TEST_FUNCTION(socket_transport_get_local_address_fail) int result = socket_transport_get_local_address(socket_handle, hostname, &local_address_list, &address_count); //assert - ASSERT_ARE_NOT_EQUAL(int, 0, result); + ASSERT_ARE_NOT_EQUAL(int, 0, result, "On failed call %zu", index); } } From c45965806c268b33acc7395972fb911d98f8a75f Mon Sep 17 00:00:00 2001 From: Jelani Brandon Date: Mon, 25 Nov 2024 15:09:02 -0800 Subject: [PATCH 10/12] update specs for wording --- linux/devdoc/socket_transport_linux_requirements.md | 2 +- linux/src/socket_transport_linux.c | 6 +++--- .../socket_transport_linux_ut/socket_transport_linux_ut.c | 4 ++-- win32/devdoc/socket_transport_win32_requirements.md | 6 +++--- win32/src/socket_transport_win32.c | 4 ++-- .../socket_transport_win32_ut/socket_transport_win32_ut.c | 4 ++-- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/linux/devdoc/socket_transport_linux_requirements.md b/linux/devdoc/socket_transport_linux_requirements.md index b20dd409..38e29024 100644 --- a/linux/devdoc/socket_transport_linux_requirements.md +++ b/linux/devdoc/socket_transport_linux_requirements.md @@ -363,7 +363,7 @@ MOCKABLE_FUNCTION(, int, socket_transport_get_local_address, SOCKET_TRANSPORT_HA **SOCKET_TRANSPORT_LINUX_11_101: [** `socket_transport_get_local_address` shall call `sm_exec_begin`. **]** -**SOCKET_TRANSPORT_LINUX_11_102: [** `socket_transport_get_local_address` shall call get the `hostname` by calling `gethostname`. **]** +**SOCKET_TRANSPORT_LINUX_11_102: [** `socket_transport_get_local_address` shall get the `hostname` by calling `gethostname`. **]** **SOCKET_TRANSPORT_LINUX_11_103: [** If `local_address_list` is not `NULL`, `socket_transport_get_local_address` shall call `getifaddrs` to get the link list of ifaddrs. **]** diff --git a/linux/src/socket_transport_linux.c b/linux/src/socket_transport_linux.c index db215130..6c333e01 100644 --- a/linux/src/socket_transport_linux.c +++ b/linux/src/socket_transport_linux.c @@ -159,11 +159,11 @@ SOCKET_TRANSPORT_HANDLE socket_transport_create_client(void) goto all_ok; } free(result); - // Codes_SOCKET_TRANSPORT_WIN32_11_004: [ On any failure socket_transport_create_client shall return NULL. ] + // Codes_SOCKET_TRANSPORT_LINUX_11_004: [ On any failure socket_transport_create_client shall return NULL. ] result = NULL; } all_ok: - // Codes_SOCKET_TRANSPORT_WIN32_11_005: [ On success socket_transport_create_client shall return SOCKET_TRANSPORT_HANDLE. ] + // Codes_SOCKET_TRANSPORT_LINUX_11_005: [ On success socket_transport_create_client shall return SOCKET_TRANSPORT_HANDLE. ] return result; } @@ -841,7 +841,7 @@ int socket_transport_get_local_address(SOCKET_TRANSPORT_HANDLE socket_transport, } else { - // Codes_SOCKET_TRANSPORT_LINUX_11_102: [ socket_transport_get_local_address shall call get the hostname by calling gethostname. ] + // Codes_SOCKET_TRANSPORT_LINUX_11_102: [ socket_transport_get_local_address shall get the hostname by calling gethostname. ] if (gethostname(hostname, MAX_GET_HOST_NAME_LEN) == INVALID_SOCKET) { // Codes_SOCKET_TRANSPORT_LINUX_11_108: [ If any failure is encountered, socket_transport_get_local_address shall fail and return a non-zero value. ] diff --git a/linux/tests/socket_transport_linux_ut/socket_transport_linux_ut.c b/linux/tests/socket_transport_linux_ut/socket_transport_linux_ut.c index b210c3e9..2c557745 100644 --- a/linux/tests/socket_transport_linux_ut/socket_transport_linux_ut.c +++ b/linux/tests/socket_transport_linux_ut/socket_transport_linux_ut.c @@ -1793,7 +1793,7 @@ TEST_FUNCTION(socket_transport_get_local_address_address_count_NULL_fail) } // Tests_SOCKET_TRANSPORT_LINUX_11_101: [ socket_transport_get_local_address shall call sm_exec_begin. ] -// Tests_SOCKET_TRANSPORT_LINUX_11_102: [ socket_transport_get_local_address shall call get the hostname by calling gethostname. ] +// Tests_SOCKET_TRANSPORT_LINUX_11_102: [ socket_transport_get_local_address shall get the hostname by calling gethostname. ] // Tests_SOCKET_TRANSPORT_LINUX_11_103: [ If local_address_list is not NULL, socket_transport_get_local_address shall call getifaddrs to get the link list of ifaddrs. ] // Tests_SOCKET_TRANSPORT_LINUX_11_104: [ socket_transport_get_local_address shall allocate the LOCAL_ADDRESS array for each ifaddrs with a sa_family of AF_INET and the interface is up and running. ] // Tests_SOCKET_TRANSPORT_LINUX_11_105: [ For each IP in the ifaddr object if the sa_family is AF_INET and the interface is up and running and it's not a loopback, socket_transport_get_local_address shall retrieve the name of the address by calling getnameinfo. ] @@ -1892,7 +1892,7 @@ TEST_FUNCTION(socket_transport_get_local_address_invalid_address_list_fail) } // Tests_SOCKET_TRANSPORT_LINUX_11_101: [ socket_transport_get_local_address shall call sm_exec_begin. ] -// Tests_SOCKET_TRANSPORT_LINUX_11_102: [ socket_transport_get_local_address shall call get the hostname by calling gethostname. ] +// Tests_SOCKET_TRANSPORT_LINUX_11_102: [ socket_transport_get_local_address shall get the hostname by calling gethostname. ] // Tests_SOCKET_TRANSPORT_LINUX_11_106: [ socket_transport_get_local_address shall call sm_exec_end. ] // Tests_SOCKET_TRANSPORT_LINUX_11_107: [ On success socket_transport_get_local_address shall return 0. ] TEST_FUNCTION(socket_transport_get_local_address_no_address_list_success) diff --git a/win32/devdoc/socket_transport_win32_requirements.md b/win32/devdoc/socket_transport_win32_requirements.md index 5011fa15..075207ce 100644 --- a/win32/devdoc/socket_transport_win32_requirements.md +++ b/win32/devdoc/socket_transport_win32_requirements.md @@ -399,11 +399,11 @@ MOCKABLE_FUNCTION(, int, socket_transport_get_local_address, SOCKET_TRANSPORT_HA **SOCKET_TRANSPORT_WIN32_11_004: [** `socket_transport_get_local_address` shall call `sm_exec_begin`. **]** -**SOCKET_TRANSPORT_WIN32_11_005: [** `socket_transport_get_local_address` shall call get the `hostname` by calling `gethostname`. **]** +**SOCKET_TRANSPORT_WIN32_11_005: [** `socket_transport_get_local_address` shall get the `hostname` by calling `gethostname`. **]** -**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. **]** +**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. **]** -**SOCKET_TRANSPORT_WIN32_11_007: [** `socket_transport_get_local_address` shall allocate the `LOCAL_ADDRESS` array. **]** +**SOCKET_TRANSPORT_WIN32_11_007: [** `socket_transport_get_local_address` shall allocate a `LOCAL_ADDRESS` array. **]** **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`. **]** diff --git a/win32/src/socket_transport_win32.c b/win32/src/socket_transport_win32.c index 56f3578a..e29a06ea 100644 --- a/win32/src/socket_transport_win32.c +++ b/win32/src/socket_transport_win32.c @@ -891,7 +891,7 @@ int socket_transport_get_local_address(SOCKET_TRANSPORT_HANDLE socket_transport, } else { - // Codes_SOCKET_TRANSPORT_WIN32_11_005: [ socket_transport_get_local_address shall call get the hostname by calling gethostname. ] + // 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. ] @@ -925,7 +925,7 @@ int socket_transport_get_local_address(SOCKET_TRANSPORT_HANDLE socket_transport, } // Allocate the array - // Codes_SOCKET_TRANSPORT_WIN32_11_007: [ socket_transport_get_local_address shall allocate the LOCAL_ADDRESS 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) { diff --git a/win32/tests/socket_transport_win32_ut/socket_transport_win32_ut.c b/win32/tests/socket_transport_win32_ut/socket_transport_win32_ut.c index 8c2b4227..364d2f6c 100644 --- a/win32/tests/socket_transport_win32_ut/socket_transport_win32_ut.c +++ b/win32/tests/socket_transport_win32_ut/socket_transport_win32_ut.c @@ -2138,9 +2138,9 @@ TEST_FUNCTION(socket_transport_get_local_address_address_count_NULL_fail) } // Tests_SOCKET_TRANSPORT_WIN32_11_004: [ socket_transport_get_local_address shall call sm_exec_begin ] -// Tests_SOCKET_TRANSPORT_WIN32_11_005: [ socket_transport_get_local_address shall call get the hostname by calling gethostname. ] +// Tests_SOCKET_TRANSPORT_WIN32_11_005: [ socket_transport_get_local_address shall get the hostname by calling gethostname. ] // Tests_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. ] -// Tests_SOCKET_TRANSPORT_WIN32_11_007: [ socket_transport_get_local_address shall allocate the LOCAL_ADDRESS array. ] +// Tests_SOCKET_TRANSPORT_WIN32_11_007: [ socket_transport_get_local_address shall allocate a LOCAL_ADDRESS array. ] // Tests_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. ] // Tests_SOCKET_TRANSPORT_WIN32_11_009: [ socket_transport_get_local_address shall call sm_exec_end. ] // Tests_SOCKET_TRANSPORT_WIN32_11_010: [ On success socket_transport_get_local_address shall return 0. ] From f8503a5ee34c3f6d591b43ed6a4cfcc11d8c99fa Mon Sep 17 00:00:00 2001 From: Jelani Brandon Date: Mon, 2 Dec 2024 15:12:29 -0800 Subject: [PATCH 11/12] fixed values from PR --- interfaces/devdoc/socket_transport_requirements.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interfaces/devdoc/socket_transport_requirements.md b/interfaces/devdoc/socket_transport_requirements.md index cdf0fa7e..bf2e04a0 100644 --- a/interfaces/devdoc/socket_transport_requirements.md +++ b/interfaces/devdoc/socket_transport_requirements.md @@ -186,4 +186,4 @@ MOCKABLE_FUNCTION(, bool, socket_transport_is_valid_socket, SOCKET_TRANSPORT_HAN MOCKABLE_FUNCTION(, 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); ``` -`socket_transport_get_local_address` shall return the hostname and IP address of the machine. \ No newline at end of file +`socket_transport_get_local_address` shall return the hostname and IP address of the local machine. From 2025fe882d37888f9a2f29313a76fed92ff93538 Mon Sep 17 00:00:00 2001 From: Jelani Brandon Date: Mon, 2 Dec 2024 15:12:50 -0800 Subject: [PATCH 12/12] another fix --- interfaces/devdoc/socket_transport_requirements.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interfaces/devdoc/socket_transport_requirements.md b/interfaces/devdoc/socket_transport_requirements.md index bf2e04a0..4763bc94 100644 --- a/interfaces/devdoc/socket_transport_requirements.md +++ b/interfaces/devdoc/socket_transport_requirements.md @@ -186,4 +186,4 @@ MOCKABLE_FUNCTION(, bool, socket_transport_is_valid_socket, SOCKET_TRANSPORT_HAN MOCKABLE_FUNCTION(, 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); ``` -`socket_transport_get_local_address` shall return the hostname and IP address of the local machine. +`socket_transport_get_local_address` shall return the hostname and IP addresses of the local machine.