in src/uws_client.c [357:539]
UWS_CLIENT_HANDLE uws_client_create_with_io(const IO_INTERFACE_DESCRIPTION* io_interface, void* io_create_parameters, const char* hostname, unsigned int port, const char* resource_name, const WS_PROTOCOL* protocols, size_t protocol_count)
{
UWS_CLIENT_HANDLE result;
/* Codes_SRS_UWS_CLIENT_01_516: [ If any of the arguments io_interface, hostname and resource_name is NULL then uws_client_create_with_io shall return NULL. ]*/
if ((hostname == NULL) ||
(io_interface == NULL) ||
(resource_name == NULL) ||
/* Codes_SRS_UWS_CLIENT_01_525: [ If protocol_count is non zero and protocols is NULL then uws_client_create_with_io shall fail and return NULL. ]*/
((protocols == NULL) && (protocol_count > 0)))
{
LogError("Invalid arguments: io_interface = %p, resource_name = %p, protocols = %p, protocol_count = %lu", io_interface, resource_name, protocols, (unsigned long)protocol_count);
result = NULL;
}
else
{
size_t i;
for (i = 0; i < protocol_count; i++)
{
if (protocols[i].protocol == NULL)
{
break;
}
}
if (i < protocol_count)
{
/* Codes_SRS_UWS_CLIENT_01_526: [ If the protocol member of any of the items in the protocols argument is NULL, then uws_client_create_with_io shall fail and return NULL. ]*/
LogError("Protocol index %lu has NULL name", (unsigned long)i);
result = NULL;
}
else
{
/* Codes_SRS_UWS_CLIENT_01_515: [ uws_client_create_with_io shall create an instance of uws and return a non-NULL handle to it. ]*/
result = (UWS_CLIENT_HANDLE)malloc(sizeof(UWS_CLIENT_INSTANCE));
if (result == NULL)
{
/* Codes_SRS_UWS_CLIENT_01_517: [ If allocating memory for the new uws instance fails then uws_client_create_with_io shall return NULL. ]*/
LogError("Could not allocate uWS instance");
}
else
{
memset(result, 0, sizeof(UWS_CLIENT_INSTANCE));
/* Codes_SRS_UWS_CLIENT_01_518: [ The argument hostname shall be copied for later use. ]*/
if (mallocAndStrcpy_s(&result->hostname, hostname) != 0)
{
/* Codes_SRS_UWS_CLIENT_01_519: [ If allocating memory for the copy of the hostname argument fails, then uws_client_create shall return NULL. ]*/
LogError("Could not copy hostname.");
free(result);
result = NULL;
}
else
{
/* Codes_SRS_UWS_CLIENT_01_523: [ The argument resource_name shall be copied for later use. ]*/
if (mallocAndStrcpy_s(&result->resource_name, resource_name) != 0)
{
/* Codes_SRS_UWS_CLIENT_01_529: [ If allocating memory for the copy of the resource_name argument fails, then uws_client_create_with_io shall return NULL. ]*/
LogError("Could not copy resource.");
free(result->hostname);
free(result);
result = NULL;
}
else if ((result->request_headers = Map_Create(NULL)) == NULL)
{
LogError("Failed allocating MAP for request headers");
free(result->resource_name);
free(result->hostname);
free(result);
result = NULL;
}
else
{
/* Codes_SRS_UWS_CLIENT_01_530: [ uws_client_create_with_io shall create a pending send IO list that is to be used to queue send packets by calling singlylinkedlist_create. ]*/
result->pending_sends = singlylinkedlist_create();
if (result->pending_sends == NULL)
{
/* Codes_SRS_UWS_CLIENT_01_531: [ If singlylinkedlist_create fails then uws_client_create_with_io shall fail and return NULL. ]*/
LogError("Could not allocate pending send frames list");
Map_Destroy(result->request_headers);
free(result->resource_name);
free(result->hostname);
free(result);
result = NULL;
}
else
{
/* Codes_SRS_UWS_CLIENT_01_521: [ The underlying IO shall be created by calling xio_create, while passing as arguments the io_interface and io_create_parameters argument values. ]*/
result->underlying_io = xio_create(io_interface, io_create_parameters);
if (result->underlying_io == NULL)
{
/* Codes_SRS_UWS_CLIENT_01_522: [ If xio_create fails, then uws_client_create_with_io shall fail and return NULL. ]*/
LogError("Cannot create underlying IO.");
singlylinkedlist_destroy(result->pending_sends);
Map_Destroy(result->request_headers);
free(result->resource_name);
free(result->hostname);
free(result);
result = NULL;
}
else
{
// Set the underlying socket to turn on renegotiation
bool set_renegotiation = true;
(void)xio_setoption(result->underlying_io, OPTION_SET_TLS_RENEGOTIATION, &set_renegotiation);
result->uws_state = UWS_STATE_CLOSED;
/* Codes_SRS_UWS_CLIENT_01_520: [ The argument port shall be copied for later use. ]*/
result->port = port;
result->fragmented_frame_type = WS_FRAME_TYPE_UNKNOWN;
result->protocol_count = protocol_count;
/* Codes_SRS_UWS_CLIENT_01_524: [ The protocols argument shall be allowed to be NULL, in which case no protocol is to be specified by the client in the upgrade request. ]*/
if (protocols == NULL)
{
result->protocols = NULL;
}
else
{
size_t malloc_size = safe_multiply_size_t(sizeof(WS_INSTANCE_PROTOCOL), protocol_count);
if (malloc_size == SIZE_MAX ||
(result->protocols = (WS_INSTANCE_PROTOCOL*)malloc(malloc_size)) == NULL)
{
/* Codes_SRS_UWS_CLIENT_01_414: [ If allocating memory for the copied protocol information fails then uws_client_create shall fail and return NULL. ]*/
LogError("Cannot allocate memory for the protocols array. size=%zu", malloc_size);
xio_destroy(result->underlying_io);
singlylinkedlist_destroy(result->pending_sends);
Map_Destroy(result->request_headers);
free(result->resource_name);
free(result->hostname);
free(result);
result = NULL;
}
else
{
/* Codes_SRS_UWS_CLIENT_01_527: [ The protocol information indicated by protocols and protocol_count shall be copied for later use (for constructing the upgrade request). ]*/
for (i = 0; i < protocol_count; i++)
{
if (mallocAndStrcpy_s(&result->protocols[i].protocol, protocols[i].protocol) != 0)
{
/* Codes_SRS_UWS_CLIENT_01_528: [ If allocating memory for the copied protocol information fails then uws_client_create_with_io shall fail and return NULL. ]*/
LogError("Cannot allocate memory for the protocol index %u.", (unsigned int)i);
break;
}
}
if (i < protocol_count)
{
size_t j;
for (j = 0; j < i; j++)
{
free(result->protocols[j].protocol);
}
free(result->protocols);
xio_destroy(result->underlying_io);
singlylinkedlist_destroy(result->pending_sends);
Map_Destroy(result->request_headers);
free(result->resource_name);
free(result->hostname);
free(result);
result = NULL;
}
else
{
result->protocol_count = protocol_count;
}
}
}
}
}
}
}
}
}
}
return result;
}