in src/uws_client.c [110:355]
UWS_CLIENT_HANDLE uws_client_create(const char* hostname, unsigned int port, const char* resource_name, bool use_ssl, const WS_PROTOCOL* protocols, size_t protocol_count)
{
UWS_CLIENT_HANDLE result;
/* Codes_SRS_UWS_CLIENT_01_002: [ If any of the arguments hostname and resource_name is NULL then uws_client_create shall return NULL. ]*/
if ((hostname == NULL) ||
(resource_name == NULL) ||
/* Codes_SRS_UWS_CLIENT_01_411: [ If protocol_count is non zero and protocols is NULL then uws_client_create shall fail and return NULL. ]*/
((protocols == NULL) && (protocol_count > 0)))
{
LogError("Invalid arguments: hostname = %p, resource_name = %p, protocols = %p, protocol_count = %lu", hostname, resource_name, protocols, (unsigned long)protocol_count);
result = NULL;
}
else
{
/* Codes_SRS_UWS_CLIENT_01_412: [ If the protocol member of any of the items in the protocols argument is NULL, then uws_client_create shall fail and return NULL. ]*/
size_t i;
for (i = 0; i < protocol_count; i++)
{
if (protocols[i].protocol == NULL)
{
break;
}
}
if (i < protocol_count)
{
LogError("Protocol index %lu has NULL name", (unsigned long)i);
result = NULL;
}
else
{
/* Codes_SRS_UWS_CLIENT_01_001: [uws_client_create 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_003: [ If allocating memory for the new uws instance fails then uws_client_create shall return NULL. ]*/
LogError("Could not allocate uWS instance");
}
else
{
(void)memset(result, 0, sizeof(UWS_CLIENT_INSTANCE));
/* Codes_SRS_UWS_CLIENT_01_004: [ The argument hostname shall be copied for later use. ]*/
if (mallocAndStrcpy_s(&result->hostname, hostname) != 0)
{
/* Codes_SRS_UWS_CLIENT_01_392: [ 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_404: [ The argument resource_name shall be copied for later use. ]*/
if (mallocAndStrcpy_s(&result->resource_name, resource_name) != 0)
{
/* Codes_SRS_UWS_CLIENT_01_405: [ If allocating memory for the copy of the resource argument fails, then uws_client_create 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_017: [ uws_client_create 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_018: [ If singlylinkedlist_create fails then uws_client_create 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
{
if (use_ssl == true)
{
TLSIO_CONFIG tlsio_config;
/* Codes_SRS_UWS_CLIENT_01_006: [ If use_ssl is true then uws_client_create shall obtain the interface used to create a tlsio instance by calling platform_get_default_tlsio. ]*/
/* Codes_SRS_UWS_CLIENT_01_076: [ If /secure/ is true, the client MUST perform a TLS handshake over the connection after opening the connection and before sending the handshake data [RFC2818]. ]*/
const IO_INTERFACE_DESCRIPTION* tlsio_interface = platform_get_default_tlsio();
if (tlsio_interface == NULL)
{
/* Codes_SRS_UWS_CLIENT_01_007: [ If obtaining the underlying IO interface fails, then uws_client_create shall fail and return NULL. ]*/
LogError("NULL TLSIO interface description");
result->underlying_io = NULL;
}
else
{
SOCKETIO_CONFIG socketio_config;
/* Codes_SRS_UWS_CLIENT_01_013: [ The create arguments for the tls IO (when use_ssl is 1) shall have: ]*/
/* Codes_SRS_UWS_CLIENT_01_014: [ - hostname set to the hostname argument passed to uws_client_create. ]*/
/* Codes_SRS_UWS_CLIENT_01_015: [ - port set to the port argument passed to uws_client_create. ]*/
socketio_config.hostname = hostname;
socketio_config.port = port;
socketio_config.accepted_socket = NULL;
tlsio_config.hostname = hostname;
tlsio_config.port = port;
tlsio_config.underlying_io_interface = socketio_get_interface_description();
tlsio_config.underlying_io_parameters = &socketio_config;
result->underlying_io = xio_create(tlsio_interface, &tlsio_config);
if (result->underlying_io == NULL)
{
LogError("Cannot create underlying TLS IO.");
}
else
{
// Set the underlying socket to turn on renegotiation
bool set_renegotiation = true;
xio_setoption(result->underlying_io, OPTION_SET_TLS_RENEGOTIATION, &set_renegotiation);
}
}
}
else
{
SOCKETIO_CONFIG socketio_config;
/* Codes_SRS_UWS_CLIENT_01_005: [ If use_ssl is false then uws_client_create shall obtain the interface used to create a socketio instance by calling socketio_get_interface_description. ]*/
const IO_INTERFACE_DESCRIPTION* socketio_interface = socketio_get_interface_description();
if (socketio_interface == NULL)
{
/* Codes_SRS_UWS_CLIENT_01_007: [ If obtaining the underlying IO interface fails, then uws_client_create shall fail and return NULL. ]*/
LogError("NULL socketio interface description");
result->underlying_io = NULL;
}
else
{
/* Codes_SRS_UWS_CLIENT_01_010: [ The create arguments for the socket IO (when use_ssl is 0) shall have: ]*/
/* Codes_SRS_UWS_CLIENT_01_011: [ - hostname set to the hostname argument passed to uws_client_create. ]*/
/* Codes_SRS_UWS_CLIENT_01_012: [ - port set to the port argument passed to uws_client_create. ]*/
socketio_config.hostname = hostname;
socketio_config.port = port;
socketio_config.accepted_socket = NULL;
/* Codes_SRS_UWS_CLIENT_01_008: [ The obtained interface shall be used to create the IO used as underlying IO by the newly created uws instance. ]*/
/* Codes_SRS_UWS_CLIENT_01_009: [ The underlying IO shall be created by calling xio_create. ]*/
result->underlying_io = xio_create(socketio_interface, &socketio_config);
if (result->underlying_io == NULL)
{
LogError("Cannot create underlying socket IO.");
}
}
}
if (result->underlying_io == NULL)
{
/* Codes_SRS_UWS_CLIENT_01_016: [ If xio_create fails, then uws_client_create shall fail and return NULL. ]*/
singlylinkedlist_destroy(result->pending_sends);
Map_Destroy(result->request_headers);
free(result->resource_name);
free(result->hostname);
free(result);
result = NULL;
}
else
{
result->uws_state = UWS_STATE_CLOSED;
/* Codes_SRS_UWS_CLIENT_01_403: [ 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_410: [ 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_413: [ 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_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 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;
}