adding two functions to socket_transport API (#359)

* adding two functions to socket_transport API

* changing function name

* small fixes
This commit is contained in:
samrach9 2024-08-19 11:30:52 -07:00 коммит произвёл GitHub
Родитель 2ddd023c53
Коммит d79a408f35
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
8 изменённых файлов: 507 добавлений и 5 удалений

Просмотреть файл

@ -60,6 +60,7 @@ typedef struct SOCKET_BUFFER_TAG
MOCKABLE_FUNCTION(, SOCKET_TRANSPORT_HANDLE, socket_transport_create_client);
MOCKABLE_FUNCTION(, SOCKET_TRANSPORT_HANDLE, socket_transport_create_server);
MOCKABLE_FUNCTION(, SOCKET_TRANSPORT_HANDLE, socket_transport_create_from_socket, SOCKET_HANDLE, socket_handle);
MOCKABLE_FUNCTION(, void, socket_transport_destroy, SOCKET_TRANSPORT_HANDLE, socket_transport);
MOCKABLE_FUNCTION(, int, socket_transport_connect, SOCKET_TRANSPORT_HANDLE, socket_transport, const char*, hostname, uint16_t, port, uint32_t, connection_timeout_ms);
@ -72,6 +73,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(, bool, socket_transport_is_valid_socket, SOCKET_TRANSPORT_HANDLE, socket_transport_handle);
```
### socket_transport_create_client
@ -90,6 +92,14 @@ MOCKABLE_FUNCTION(, SOCKET_TRANSPORT_HANDLE, socket_transport_create_server);
`socket_transport_create_server` creates a binding socket transport.
### socket_transport_create_from_socket
```c
MOCKABLE_FUNCTION(, SOCKET_TRANSPORT_HANDLE, socket_transport_create_from_socket, SOCKET_HANDLE, socket_handle);
```
`socket_transport_create_from_socket` creates a client socket transport from a given socket handle.
### socket_transport_destroy
```c
@ -154,3 +164,11 @@ MOCKABLE_FUNCTION(, SOCKET_HANDLE, socket_transport_get_underlying_socket, SOCKE
```
`socket_transport_get_underlying_socket` returns the underlying socket.
### socket_transport_is_valid_socket
```c
MOCKABLE_FUNCTION(, bool, socket_transport_is_valid_socket, SOCKET_TRANSPORT_HANDLE, socket_transport_handle);
```
`socket_transport_check_valid_handle` checks that the internal socket is valid.

Просмотреть файл

@ -13,6 +13,7 @@
#include <cstdint>
extern "C" {
#else
#include <stdbool.h>
#include <stdint.h>
#endif
@ -57,6 +58,7 @@ typedef struct SOCKET_BUFFER_TAG
MOCKABLE_FUNCTION(, SOCKET_TRANSPORT_HANDLE, socket_transport_create_client);
MOCKABLE_FUNCTION(, SOCKET_TRANSPORT_HANDLE, socket_transport_create_server);
MOCKABLE_FUNCTION(, SOCKET_TRANSPORT_HANDLE, socket_transport_create_from_socket, SOCKET_HANDLE, socket_handle);
MOCKABLE_FUNCTION(, void, socket_transport_destroy, SOCKET_TRANSPORT_HANDLE, socket_transport);
MOCKABLE_FUNCTION(, int, socket_transport_connect, SOCKET_TRANSPORT_HANDLE, socket_transport, const char*, hostname, uint16_t, port, uint32_t, connection_timeout_ms);
@ -69,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(, bool, socket_transport_is_valid_socket, SOCKET_TRANSPORT_HANDLE, socket_transport_handle);
#ifdef __cplusplus
}

Просмотреть файл

@ -52,6 +52,7 @@ typedef struct SOCKET_BUFFER_TAG
MOCKABLE_FUNCTION(, SOCKET_TRANSPORT_HANDLE, socket_transport_create_client);
MOCKABLE_FUNCTION(, SOCKET_TRANSPORT_HANDLE, socket_transport_create_server);
MOCKABLE_FUNCTION(, SOCKET_TRANSPORT_HANDLE, socket_transport_create_from_socket, SOCKET_HANDLE, socket_handle);
MOCKABLE_FUNCTION(, void, socket_transport_destroy, SOCKET_TRANSPORT_HANDLE, socket_transport);
MOCKABLE_FUNCTION(, int, socket_transport_connect, SOCKET_TRANSPORT_HANDLE, socket_transport, const char*, hostname, uint16_t, port, uint32_t, connection_timeout_ms);
@ -64,6 +65,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(, bool, socket_transport_is_valid_socket, SOCKET_TRANSPORT_HANDLE, socket_transport_handle);
```
### socket_transport_create_client
@ -98,6 +100,28 @@ MOCKABLE_FUNCTION(, SOCKET_TRANSPORT_HANDLE, socket_transport_create_server);
**SOCKET_TRANSPORT_LINUX_11_082: [** On success `socket_transport_create_server` shall return `SOCKET_TRANSPORT_HANDLE`. **]**
### socket_transport_create_from_socket
```c
MOCKABLE_FUNCTION(, SOCKET_TRANSPORT_HANDLE, socket_transport_create_from_socket, SOCKET_HANDLE, socket_handle);
```
`socket_transport_create_from_socket` creates a client socket transport from a given socket handle.
**SOCKET_TRANSPORT_LINUX_11_086: [** If socket_handle is an INVALID_SOCKET, `socket_transport_create_from_socket` shall fail and return `NULL`. **]**
**SOCKET_TRANSPORT_LINUX_11_087: [** `socket_transport_create_from_socket` shall allocate a new SOCKET_TRANSPORT object. **]**
**SOCKET_TRANSPORT_LINUX_11_088: [** `socket_transport_create_from_socket` shall call sm_create to create a sm_object with the type set to SOCKET_CLIENT. **]**
**SOCKET_TRANSPORT_LINUX_11_097: [** If `sm_open_begin` does not return `SM_EXEC_GRANTED`, `socket_transport_create_from_socket` shall fail and return `NULL`. **]**
**SOCKET_TRANSPORT_LINUX_11_096: [** `socket_transport_create_from_socket` shall assign the socket_handle to the new allocated socket transport. **]**
**SOCKET_TRANSPORT_LINUX_11_090: [** On any failure `socket_transport_create_from_socket` shall return `NULL`. **]**
**SOCKET_TRANSPORT_LINUX_11_091: [** On success `socket_transport_create_from_socket` shall return SOCKET_TRANSPORT_HANDLE. **]**
### socket_transport_destroy
```c
@ -307,3 +331,17 @@ MOCKABLE_FUNCTION(, SOCKET_HANDLE, socket_transport_get_underlying_socket, SOCKE
**SOCKET_TRANSPORT_LINUX_11_067: [** `socket_transport_get_underlying_socket` shall return the `SOCKET_HANDLE` socket value. **]**
**SOCKET_TRANSPORT_LINUX_11_068: [** `socket_transport_get_underlying_socket` shall call `sm_exec_end`. **]**
### socket_transport_is_valid_socket
```c
MOCKABLE_FUNCTION(, bool, socket_transport_is_valid_socket, SOCKET_TRANSPORT_HANDLE, socket_transport_handle);
```
`socket_transport_is_valid_socket` checks that the internal socket is valid.
**SOCKET_TRANSPORT_LINUX_11_093: [** If `socket_transport_handle` is `NULL`, `socket_transport_is_valid_socket` shall fail and return `false`. **]**
**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`. **]**

Просмотреть файл

@ -140,7 +140,7 @@ SOCKET_TRANSPORT_HANDLE socket_transport_create_client(void)
else
{
// Codes_SOCKET_TRANSPORT_LINUX_11_003: [ socket_transport_create_client shall call sm_create to create a sm object with the type set to SOCKET_CLIENT. ]
result->sm = sm_create("Socket_transport_win32");
result->sm = sm_create("Socket_transport_linux");
if (result->sm == NULL)
{
LogError("sm_create failed.");
@ -172,7 +172,7 @@ SOCKET_TRANSPORT_HANDLE socket_transport_create_server(void)
else
{
// Codes_SOCKET_TRANSPORT_LINUX_11_080: [ socket_transport_create_server shall call sm_create to create a sm object with the type set to SOCKET_BINDING. ]
result->sm = sm_create("Socket_transport_win32");
result->sm = sm_create("Socket_transport_linux");
if (result->sm == NULL)
{
LogError("sm_create failed.");
@ -191,6 +191,59 @@ all_ok:
return result;
}
SOCKET_TRANSPORT_HANDLE socket_transport_create_from_socket(SOCKET_HANDLE socket_handle)
{
SOCKET_TRANSPORT* result;
// Codes_SOCKET_TRANSPORT_LINUX_11_086: [ If socket_handle is an INVALID_SOCKET, socket_transport_create_from_socket shall fail and return NULL. ]
if (socket_handle == INVALID_SOCKET)
{
LogError("Invalid socket, unable to create socket_transport_handle.");
}
else
{
// Codes_SOCKET_TRANSPORT_LINUX_11_087: [ socket_transport_create_from_socket shall allocate a new SOCKET_TRANSPORT object. ]
result = malloc(sizeof(SOCKET_TRANSPORT));
if (result == NULL)
{
LogError("failure allocating SOCKET_TRANSPORT: %zu", sizeof(SOCKET_TRANSPORT));
}
else
{
// Codes_SOCKET_TRANSPORT_LINUX_11_088: [ socket_transport_create_from_socket shall call sm_create to create a sm_object with the type set to SOCKET_CLIENT. ]
result->sm = sm_create("Socket_transport_win32");
if (result->sm == NULL)
{
LogError("sm_create failed.");
}
else
{
// Codes_SOCKET_TRANSPORT_WIN32_11_014: [ If sm_open_begin does not return SM_EXEC_GRANTED, socket_transport_create_from_socket shall fail and return NULL. ]
SM_RESULT open_result = sm_open_begin(result->sm);
if (open_result == SM_EXEC_GRANTED)
{
result->type = SOCKET_CLIENT;
// Codes_SOCKET_TRANSPORT_LINUX_11_096: [ socket_transport_create_from_socket shall assign the socket_handle to the new allocated socket transport. ]
result->socket = socket_handle;
sm_open_end(result->sm, true);
// Codes_SOCKET_TRANSPORT_LINUX_11_091: [ On success socket_transport_create_from_socket shall return SOCKET_TRANSPORT_HANDLE. ]
goto all_ok;
}
else
{
LogError("sm_open_begin failed with %" PRI_MU_ENUM " in accept, closing incoming socket.", MU_ENUM_VALUE(SM_RESULT, open_result));
}
sm_destroy(result->sm);
}
free(result);
}
}
// Codes_SOCKET_TRANSPORT_LINUX_11_090: [ On any failure socket_transport_create_from_socket shall return NULL. ]
result = NULL;
all_ok:
return result;
}
void socket_transport_destroy(SOCKET_TRANSPORT_HANDLE socket_transport)
{
// Codes_SOCKET_TRANSPORT_LINUX_11_006: [ If socket_transport is NULL socket_transport_destroy shall return. ]
@ -245,7 +298,7 @@ int socket_transport_connect(SOCKET_TRANSPORT_HANDLE socket_transport, const cha
if (socket_transport->socket == INVALID_SOCKET)
{
// Codes_SOCKET_TRANSPORT_LINUX_11_019: [ If any failure is encountered, socket_transport_connect shall call sm_open_end with false, fail and return a non-zero value. ]
LogError("Failure conneting to client hostname: %s:%" PRIu16 "", hostname, port);
LogError("Failure connecting to client hostname: %s:%" PRIu16 "", hostname, port);
result = MU_FAILURE;
sm_open_end(socket_transport->sm, false);
}
@ -657,7 +710,7 @@ SOCKET_ACCEPT_RESULT socket_transport_accept(SOCKET_TRANSPORT_HANDLE socket_tran
}
else
{
accept_result->sm = sm_create("Socket_transport_win32");
accept_result->sm = sm_create("Socket_transport_linux");
if (accept_result->sm == NULL)
{
LogError("Failed calling sm_create in accept, closing incoming socket.");
@ -728,4 +781,27 @@ SOCKET_HANDLE socket_transport_get_underlying_socket(SOCKET_TRANSPORT_HANDLE soc
}
}
return result;
}
}
bool socket_transport_is_valid_socket(SOCKET_TRANSPORT_HANDLE socket_transport_handle)
{
bool result;
if (socket_transport_handle == NULL)
{
result = false;
LogError("Invalid argument: SOCKET_TRANSPORT_HANDLE socket_transport_handle: %p", socket_transport_handle);
}
else
{
if (socket_transport_handle->socket == INVALID_SOCKET)
{
result = false;
LogError("Invalid socket in argument: SOCKET_TRANSPORT_HANDLE socket_transport_handle: %p", socket_transport_handle);
}
else
{
result = true;
}
}
return result;
}

Просмотреть файл

@ -1581,4 +1581,131 @@ TEST_FUNCTION(socket_transport_get_underlying_socket_not_open_fail)
socket_transport_destroy(socket_handle);
}
// Tests_SOCKET_TRANSPORT_LINUX_11_087: [ socket_transport_create_from_socket shall allocate a new SOCKET_TRANSPORT object. ]
// Tests_SOCKET_TRANSPORT_LINUX_11_088: [ socket_transport_create_from_socket shall call sm_create to create a sm_object with the type set to SOCKET_CLIENT. ]
// Tests_SOCKET_TRANSPORT_LINUX_11_096: [ socket_transport_create_from_socket shall assign the socket_handle to the new allocated socket transport. ]
// Tests_SOCKET_TRANSPORT_LINUX_11_091: [ On success socket_transport_create_from_socket shall return SOCKET_TRANSPORT_HANDLE. ]
TEST_FUNCTION(socket_transport_create_from_socket_succeeds)
{
//arrange
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(malloc(IGNORED_ARG));
STRICT_EXPECTED_CALL(sm_create(IGNORED_ARG));
STRICT_EXPECTED_CALL(sm_open_begin(IGNORED_ARG));
STRICT_EXPECTED_CALL(sm_open_end(IGNORED_ARG, true));
//act
SOCKET_TRANSPORT_HANDLE socket_transport = socket_transport_create_from_socket((SOCKET_HANDLE)test_socket);
//assert
ASSERT_IS_NOT_NULL(socket_transport);
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
//cleanup
socket_transport_destroy(socket_transport);
}
// Tests_SOCKET_TRANSPORT_LINUX_11_086: [ If socket_handle is an INVALID_SOCKET, socket_transport_create_from_socket shall fail and return NULL. ]
TEST_FUNCTION(socket_transport_create_from_socket_invalid_input)
{
//arrange
umock_c_reset_all_calls();
//act
SOCKET_TRANSPORT_HANDLE socket_transport = socket_transport_create_from_socket((SOCKET_HANDLE)INVALID_SOCKET);
//assert
ASSERT_IS_NULL(socket_transport);
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
}
// Tests_SOCKET_TRANSPORT_LINUX_11_097: [ If sm_open_begin does not return SM_EXEC_GRANTED, socket_transport_create_from_socket shall fail and return NULL. ]
// Tests_SOCKET_TRANSPORT_LINUX_11_090: [ On any failure socket_transport_create_from_socket shall return NULL. ]
TEST_FUNCTION(socket_transport_create_from_socket_fail)
{
//arrange
STRICT_EXPECTED_CALL(malloc(IGNORED_ARG));
STRICT_EXPECTED_CALL(sm_create(IGNORED_ARG));
STRICT_EXPECTED_CALL(sm_open_begin(IGNORED_ARG));
STRICT_EXPECTED_CALL(sm_destroy(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
SOCKET_TRANSPORT_HANDLE socket_handle = socket_transport_create_from_socket((SOCKET_HANDLE)test_socket);
//assert
ASSERT_IS_NULL(socket_handle);
//cleanup
socket_transport_destroy(socket_handle);
}
}
}
// Tests_SOCKET_TRANSPORT_LINUX_11_093: [ If socket_transport_handle is NULL, socket_transport_is_valid_socket shall fail and return false. ]
TEST_FUNCTION(socket_transport_is_valid_socket_NULL_input)
{
//arrange
umock_c_reset_all_calls();
//act
bool result = socket_transport_is_valid_socket(NULL);
//assert
ASSERT_IS_TRUE(!result);
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
}
// Tests_SOCKET_TRANSPORT_LINUX_11_095: [ On success, socket_transport_is_valid_socket shall return true. ]
TEST_FUNCTION(socket_transport_is_valid_socket_succeeds)
{
//arrange
SOCKET_TRANSPORT_HANDLE test_socket_transport = socket_transport_create_client();
socket_transport_connect(test_socket_transport, TEST_HOSTNAME, TEST_PORT, TEST_CONNECTION_TIMEOUT);
umock_c_reset_all_calls();
//act
bool result = socket_transport_is_valid_socket(test_socket_transport);
//assert
ASSERT_IS_TRUE(result);
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
//cleanup
socket_transport_disconnect(test_socket_transport);
socket_transport_destroy(test_socket_transport);
}
// Tests_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. ]
TEST_FUNCTION(socket_transport_is_valid_socket_INVALID_SOCKET)
{
//arrange
SOCKET_TRANSPORT_HANDLE test_socket_transport = socket_transport_create_client();
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(sm_open_begin(IGNORED_ARG));
STRICT_EXPECTED_CALL(socket(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
.SetReturn(INVALID_SOCKET);
STRICT_EXPECTED_CALL(sm_open_end(IGNORED_ARG, false));
//act
socket_transport_connect(test_socket_transport, TEST_HOSTNAME, TEST_PORT, TEST_CONNECTION_TIMEOUT);
bool result = socket_transport_is_valid_socket(test_socket_transport);
//assert
ASSERT_IS_TRUE(!result);
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
//cleanup
socket_transport_disconnect(test_socket_transport);
socket_transport_destroy(test_socket_transport);
}
END_TEST_SUITE(TEST_SUITE_NAME_FROM_CMAKE)

Просмотреть файл

@ -51,6 +51,7 @@ typedef struct SOCKET_BUFFER_TAG
MOCKABLE_FUNCTION(, SOCKET_TRANSPORT_HANDLE, socket_transport_create_client);
MOCKABLE_FUNCTION(, SOCKET_TRANSPORT_HANDLE, socket_transport_create_server);
MOCKABLE_FUNCTION(, SOCKET_TRANSPORT_HANDLE, socket_transport_create_from_socket, SOCKET_HANDLE, socket_handle);
MOCKABLE_FUNCTION(, void, socket_transport_destroy, SOCKET_TRANSPORT_HANDLE, socket_transport);
MOCKABLE_FUNCTION(, int, socket_transport_connect, SOCKET_TRANSPORT_HANDLE, socket_transport, const char*, hostname, uint16_t, port, uint32_t, connection_timeout_ms);
@ -63,6 +64,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(, bool, socket_transport_is_valid_socket, SOCKET_TRANSPORT_HANDLE, socket_transport_handle);
```
### socket_transport_create_client
@ -97,6 +99,28 @@ MOCKABLE_FUNCTION(, SOCKET_TRANSPORT_HANDLE, socket_transport_create_server);
**SOCKET_TRANSPORT_WIN32_09_090: [** On success `socket_transport_create_server` shall return `SOCKET_TRANSPORT_HANDLE`. **]**
### socket_transport_create_from_socket
```c
MOCKABLE_FUNCTION(, SOCKET_TRANSPORT_HANDLE, socket_transport_create_from_socket, SOCKET_HANDLE, socket_handle);
```
`socket_transport_create_from_socket` creates a client socket transport from a given socket handle.
**SOCKET_TRANSPORT_WIN32_09_096: [** If socket_handle is an INVALID_SOCKET, `socket_transport_create_from_socket` shall fail and return `NULL`. **]**
**SOCKET_TRANSPORT_WIN32_09_097: [** `socket_transport_create_from_socket` shall allocate a new SOCKET_TRANSPORT object. **]**
**SOCKET_TRANSPORT_WIN32_09_098: [** `socket_transport_create_from_socket` shall call sm_create to create a sm_object with the type set to SOCKET_CLIENT. **]**
**SOCKET_TRANSPORT_WIN32_09_014: [** If `sm_open_begin` does not return `SM_EXEC_GRANTED`, `socket_transport_create_from_socket` shall fail and return `NULL`. **]**
**SOCKET_TRANSPORT_WIN32_09_099: [** `socket_transport_create_from_socket` shall assign the socket_handle to the new allocated socket transport. **]**
**SOCKET_TRANSPORT_WIN32_09_100: [** On any failure `socket_transport_create_from_socket` shall return `NULL`. **]**
**SOCKET_TRANSPORT_WIN32_09_101: [** On success `socket_transport_create_from_socket` shall return SOCKET_TRANSPORT_HANDLE. **]**
### socket_transport_destroy
@ -329,3 +353,17 @@ 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_is_valid_socket
```c
MOCKABLE_FUNCTION(, bool, socket_transport_is_valid_socket, SOCKET_TRANSPORT_HANDLE, socket_transport_handle);
```
**SOCKET_TRANSPORT_WIN32_09_092: [** `socket_transport_is_valid_socket` checks that the internal socket is valid. **]**
**SOCKET_TRANSPORT_WIN32_09_093: [** If `socket_transport_handle` is `NULL`, `socket_transport_is_valid_socket` shall fail and return false. **]**
**SOCKET_TRANSPORT_WIN32_09_094: [** If the socket inside `socket_transport_handle` is an `INVALID_SOCKET`, `socket_transport_is_valid_socket` shall fail and return false. **]**
**SOCKET_TRANSPORT_WIN32_09_095: [** On success, `socket_transport_is_valid_socket` shall return true. **]**

Просмотреть файл

@ -240,6 +240,58 @@ all_ok:
return result;
}
SOCKET_TRANSPORT_HANDLE socket_transport_create_from_socket(SOCKET_HANDLE socket_handle)
{
SOCKET_TRANSPORT* result;
// Codes_SOCKET_TRANSPORT_WIN32_09_096: [ If socket_handle is an INVALID_SOCKET, socket_transport_create_from_socket shall fail and return NULL. ]
if ((SOCKET)socket_handle == INVALID_SOCKET)
{
LogError("Invalid socket, unable to create socket_transport_handle.");
}
else
{
// Codes_SOCKET_TRANSPORT_WIN32_09_097: [ socket_transport_create_from_socket shall allocate a new SOCKET_TRANSPORT object. ]
result = malloc(sizeof(SOCKET_TRANSPORT));
if (result == NULL)
{
LogError("failure allocating SOCKET_TRANSPORT: %zu", sizeof(SOCKET_TRANSPORT));
}
else
{
// Codes_SOCKET_TRANSPORT_WIN32_09_098: [ socket_transport_create_from_socket shall call sm_create to create a sm_object with the type set to SOCKET_CLIENT. ]
result->sm = sm_create("Socket_transport_win32");
if (result->sm == NULL)
{
LogError("sm_create failed.");
}
else
{
// Codes_SOCKET_TRANSPORT_WIN32_09_014: [ If sm_open_begin does not return SM_EXEC_GRANTED, socket_transport_create_from_socket shall fail and return NULL. ]
SM_RESULT open_result = sm_open_begin(result->sm);
if (open_result == SM_EXEC_GRANTED)
{
result->type = SOCKET_CLIENT;
// Codes_SOCKET_TRANSPORT_WIN32_09_099: [ socket_transport_create_from_socket shall assign the socket_handle to the new allocated socket transport. ]
result->socket = (SOCKET)socket_handle;
sm_open_end(result->sm, true);
// Codes_SOCKET_TRANSPORT_WIN32_09_101: [ On success socket_transport_create_from_socket shall return SOCKET_TRANSPORT_HANDLE. ]
goto all_ok;
}
else
{
LogError("sm_open_begin failed with %" PRI_MU_ENUM " in accept, closing incoming socket.", MU_ENUM_VALUE(SM_RESULT, open_result));
}
sm_destroy(result->sm);
}
free(result);
}
}
// Codes_SOCKET_TRANSPORT_WIN32_09_100: [ On any failure socket_transport_create_from_socket shall return NULL. ]
result = NULL;
all_ok:
return result;
}
void socket_transport_destroy(SOCKET_TRANSPORT_HANDLE socket_transport)
{
// Codes_SOCKET_TRANSPORT_WIN32_09_006: [ If socket_transport is NULL socket_transport_destroy shall return. ]
@ -760,3 +812,26 @@ SOCKET_HANDLE socket_transport_get_underlying_socket(SOCKET_TRANSPORT_HANDLE soc
}
return result;
}
bool socket_transport_is_valid_socket(SOCKET_TRANSPORT_HANDLE socket_transport_handle)
{
bool result;
if (socket_transport_handle == NULL)
{
result = false;
LogError("Invalid argument: SOCKET_TRANSPORT_HANDLE socket_transport_handle: %p", socket_transport_handle);
}
else
{
if (socket_transport_handle->socket == INVALID_SOCKET)
{
result = false;
LogError("Invalid socket in argument: SOCKET_TRANSPORT_HANDLE socket_transport_handle: %p", socket_transport_handle);
}
else
{
result = true;
}
}
return result;
}

Просмотреть файл

@ -1837,4 +1837,131 @@ TEST_FUNCTION(socket_transport_get_underlying_socket_NULL_input_fail)
//cleanup
}
// Tests_SOCKET_TRANSPORT_WIN32_09_098: [ socket_transport_create_from_socket shall call sm_create to create a sm_object with the type set to SOCKET_CLIENT. ]
// Tests_SOCKET_TRANSPORT_WIN32_09_097: [ socket_transport_create_from_socket shall allocate a new SOCKET_TRANSPORT object. ]
// Tests_SOCKET_TRANSPORT_WIN32_09_099: [ socket_transport_create_from_socket shall assign the socket_handle to the new allocated socket transport. ]
// Tests_SOCKET_TRANSPORT_WIN32_09_101: [ On success socket_transport_create_from_socket shall return SOCKET_TRANSPORT_HANDLE. ]
TEST_FUNCTION(socket_transport_create_from_socket_succeeds)
{
//arrange
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(malloc(IGNORED_ARG));
STRICT_EXPECTED_CALL(sm_create(IGNORED_ARG));
STRICT_EXPECTED_CALL(sm_open_begin(IGNORED_ARG));
STRICT_EXPECTED_CALL(sm_open_end(IGNORED_ARG, true));
//act
SOCKET_TRANSPORT_HANDLE socket_transport = socket_transport_create_from_socket((SOCKET_HANDLE)test_socket);
//assert
ASSERT_IS_NOT_NULL(socket_transport);
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
//cleanup
socket_transport_destroy(socket_transport);
}
// Tests_SOCKET_TRANSPORT_WIN32_09_096: [ If socket_handle is an INVALID_SOCKET, socket_transport_create_from_socket shall fail and return NULL. ]
TEST_FUNCTION(socket_transport_create_from_socket_invalid_input)
{
//arrange
umock_c_reset_all_calls();
//act
SOCKET_TRANSPORT_HANDLE socket_transport = socket_transport_create_from_socket((SOCKET_HANDLE)INVALID_SOCKET);
//assert
ASSERT_IS_NULL(socket_transport);
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
}
// Tests_SOCKET_TRANSPORT_WIN32_09_014: [ If sm_open_begin does not return SM_EXEC_GRANTED, socket_transport_create_from_socket shall fail and return NULL. ]
// Tests_SOCKET_TRANSPORT_WIN32_09_102: [ On any failure socket_transport_create_from_socket shall return NULL. ]
TEST_FUNCTION(socket_transport_create_from_socket_fail)
{
//arrange
STRICT_EXPECTED_CALL(malloc(IGNORED_ARG));
STRICT_EXPECTED_CALL(sm_create(IGNORED_ARG));
STRICT_EXPECTED_CALL(sm_open_begin(IGNORED_ARG));
STRICT_EXPECTED_CALL(sm_destroy(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
SOCKET_TRANSPORT_HANDLE socket_handle = socket_transport_create_from_socket((SOCKET_HANDLE)test_socket);
//assert
ASSERT_IS_NULL(socket_handle);
//cleanup
socket_transport_destroy(socket_handle);
}
}
}
// Tests_SOCKET_TRANSPORT_WIN32_09_093: [ If socket_transport_handle is NULL, socket_transport_is_valid_socket shall fail and return false. ]
TEST_FUNCTION(socket_transport_is_valid_socket_NULL_input)
{
//arrange
umock_c_reset_all_calls();
//act
bool result = socket_transport_is_valid_socket(NULL);
//assert
ASSERT_IS_TRUE(!result);
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
}
// Tests_SOCKET_TRANSPORT_WIN32_09_095: [ On success, socket_transport_is_valid_socket shall return true.
TEST_FUNCTION(socket_transport_is_valid_socket_succeeds)
{
//arrange
SOCKET_TRANSPORT_HANDLE test_socket_transport = socket_transport_create_client();
socket_transport_connect(test_socket_transport, TEST_HOSTNAME, TEST_PORT, TEST_CONNECTION_TIMEOUT);
umock_c_reset_all_calls();
//act
bool result = socket_transport_is_valid_socket(test_socket_transport);
//assert
ASSERT_IS_TRUE(result);
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
//cleanup
socket_transport_disconnect(test_socket_transport);
socket_transport_destroy(test_socket_transport);
}
// Tests_SOCKET_TRANSPORT_WIN32_09_094: [ If the socket inside socket_transport_handle is an INVALID_SOCKET, socket_transport_is_valid_socket shall fail and return false. ]
TEST_FUNCTION(socket_transport_is_valid_socket_INVALID_SOCKET)
{
//arrange
SOCKET_TRANSPORT_HANDLE test_socket_transport = socket_transport_create_client();
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(sm_open_begin(IGNORED_ARG));
STRICT_EXPECTED_CALL(socket(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
.SetReturn(INVALID_SOCKET);
STRICT_EXPECTED_CALL(sm_open_end(IGNORED_ARG, false));
//act
socket_transport_connect(test_socket_transport, TEST_HOSTNAME, TEST_PORT, TEST_CONNECTION_TIMEOUT);
bool result = socket_transport_is_valid_socket(test_socket_transport);
//assert
ASSERT_IS_TRUE(!result);
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
//cleanup
socket_transport_disconnect(test_socket_transport);
socket_transport_destroy(test_socket_transport);
}
END_TEST_SUITE(TEST_SUITE_NAME_FROM_CMAKE)