in src/header_detect_io.c [463:620]
static CONCRETE_IO_HANDLE header_detect_io_create(void* io_create_parameters)
{
HEADER_DETECT_IO_INSTANCE* result;
if (io_create_parameters == NULL)
{
/* Codes_SRS_HEADER_DETECT_IO_01_003: [ If `io_create_parameters` is NULL, `header_detect_io_create` shall fail and return NULL. ]*/
LogError("NULL io_create_parameters");
result = NULL;
}
else
{
/* Codes_SRS_HEADER_DETECT_IO_01_004: [ `io_create_parameters` shall be used as `HEADER_DETECT_IO_CONFIG*`. ]*/
HEADER_DETECT_IO_CONFIG* header_detect_io_config = (HEADER_DETECT_IO_CONFIG*)io_create_parameters;
/* Codes_SRS_HEADER_DETECT_IO_01_005: [ If the member `header_detect_entry_count` of `HEADER_DETECT_IO_CONFIG` is 0 then `header_detect_io_create` shall fail and return NULL. ]*/
if ((header_detect_io_config->header_detect_entry_count == 0) ||
/* Codes_SRS_HEADER_DETECT_IO_01_006: [ If the member `header_detect_entries` is NULL then `header_detect_io_create` shall fail and return NULL. ]*/
(header_detect_io_config->header_detect_entries == NULL) ||
/* Codes_SRS_HEADER_DETECT_IO_01_007: [ If the member `underlying_io` is NULL then `header_detect_io_create` shall fail and return NULL. ]*/
(header_detect_io_config->underlying_io == NULL))
{
LogError("Bad create parameters: header_detect_entry_count = %lu, header_detect_entries = %p, underlying_io = %p",
(unsigned long)header_detect_io_config->header_detect_entry_count,
header_detect_io_config->header_detect_entries,
header_detect_io_config->underlying_io);
result = NULL;
}
else
{
size_t i;
bool null_io_found = false;
for (i = 0; i < header_detect_io_config->header_detect_entry_count; i++)
{
/* Codes_SRS_HEADER_DETECT_IO_01_052: [ The `io` member in the in each of the `header_detect_entries` shall be allowed to be NULL. ]*/
if (header_detect_io_config->header_detect_entries[i].header.header_bytes == NULL)
{
LogError("header detect entry %u is invalid", (unsigned int)i);
break;
}
if (header_detect_io_config->header_detect_entries[i].io_interface_description == NULL)
{
null_io_found = true;
}
}
if (i < header_detect_io_config->header_detect_entry_count)
{
result = NULL;
}
else if (!null_io_found)
{
/* Codes_SRS_HEADER_DETECT_IO_01_054: [ At least one entry in `header_detect_entries` shall have IO set to NULL, otherwise `header_detect_io_create` shall fail and return NULL. ]*/
LogError("No default header found");
result = NULL;
}
else
{
/* Codes_SRS_HEADER_DETECT_IO_01_001: [ `header_detect_io_create` shall create a new header detect IO instance and on success it shall return a non-NULL handle to the newly created instance. ] */
result = (HEADER_DETECT_IO_INSTANCE*)calloc(1, sizeof(HEADER_DETECT_IO_INSTANCE));
if (result == NULL)
{
/* Codes_SRS_HEADER_DETECT_IO_01_002: [ If allocating memory for the header detect IO instance fails, `header_detect_io_create` shall fail and return NULL. ]*/
LogError("Cannot allocate memory for header detect IO");
}
else
{
/* Codes_SRS_HEADER_DETECT_IO_01_009: [ The `header_detect_entries` array shall be copied so that it can be later used when detecting which header was received. ]*/
size_t calloc_size = safe_multiply_size_t(header_detect_io_config->header_detect_entry_count, sizeof(INTERNAL_HEADER_DETECT_ENTRY));
if (calloc_size == SIZE_MAX ||
(result->header_detect_entries = (INTERNAL_HEADER_DETECT_ENTRY*)calloc(1, calloc_size)) == NULL)
{
LogError("Could not allocate header_detect_entries, size:%zu", calloc_size);
free(result);
result = NULL;
}
else
{
result->header_detect_entry_count = header_detect_io_config->header_detect_entry_count;
/* Codes_SRS_HEADER_DETECT_IO_01_009: [ The `header_detect_entries` array shall be copied so that it can be later used when detecting which header was received. ]*/
for (i = 0; i < header_detect_io_config->header_detect_entry_count; i++)
{
result->header_detect_entries[i].header_size = header_detect_io_config->header_detect_entries[i].header.header_size;
result->header_detect_entries[i].header_bytes = (unsigned char*)malloc(result->header_detect_entries[i].header_size);
if (result->header_detect_entries[i].header_bytes == NULL)
{
/* Codes_SRS_HEADER_DETECT_IO_01_010: [ If allocating memory for the `header_detect_entries` or its constituents fails then `header_detect_io_create` shall fail and return NULL. ]*/
break;
}
else
{
/* Codes_SRS_HEADER_DETECT_IO_01_014: [ For each entry in `header_detect_entries` the `header` field shall also be copied. ]*/
(void)memcpy(result->header_detect_entries[i].header_bytes, header_detect_io_config->header_detect_entries[i].header.header_bytes, result->header_detect_entries[i].header_size);
result->header_detect_entries[i].io_interface_description = header_detect_io_config->header_detect_entries[i].io_interface_description;
}
}
if (i < header_detect_io_config->header_detect_entry_count)
{
size_t j;
LogError("Failed copying header detect configuration");
for (j = 0; j < i; j++)
{
free(result->header_detect_entries[j].header_bytes);
}
free(result->header_detect_entries);
free(result);
result = NULL;
}
else
{
/* Codes_SRS_HEADER_DETECT_IO_01_060: [ `header_detect_io_create` shall create a singly linked list by calling `singlylinkedlist_create` where the chained detected IOs shall be stored. ]*/
result->chained_io_list = singlylinkedlist_create();
if (result->chained_io_list == NULL)
{
/* Codes_SRS_HEADER_DETECT_IO_01_065: [ If `singlylinkedlist_create` fails then `header_detect_io_create` shall fail and return NULL. ]*/
LogError("Failed copying header detect configuration");
for (i = 0; i < result->header_detect_entry_count; i++)
{
free(result->header_detect_entries[i].header_bytes);
result->header_detect_entries[i].header_bytes = NULL;
}
free(result->header_detect_entries);
free(result);
result = NULL;
}
else
{
result->underlying_io = header_detect_io_config->underlying_io;
result->on_io_open_complete = NULL;
result->on_io_close_complete = NULL;
result->on_io_error = NULL;
result->on_bytes_received = NULL;
result->on_io_open_complete_context = NULL;
result->on_io_close_complete_context = NULL;
result->on_io_error_context = NULL;
result->on_bytes_received_context = NULL;
/* Codes_SRS_HEADER_DETECT_IO_01_070: [ If no detected IO was created then `header_detect_io_close_async` shall close the `underlying_io` passed in `header_detect_io_create`. ]*/
result->last_io = &result->underlying_io;
result->io_state = IO_STATE_NOT_OPEN;
}
}
}
}
}
}
}
return result;
}