in src/ws_url.c [32:208]
static int parse_ws_url(const char* url, WS_URL* ws_url)
{
int result = 0;
size_t url_length = strlen(url);
if (url_length < MIN_URL_PARSABLE_LENGTH)
{
LogError("Invalid url (unexpected length)");
result = MU_FAILURE;
}
// Codes_SRS_WS_URL_09_004: [ If url starts with "ws://" (protocol), ws_url->is_secure shall be set to false ]
if (strncmp(url, WS_PROTOCOL, 5) == 0)
{
ws_url->is_secure = false;
}
// Codes_SRS_WS_URL_09_005: [ If url starts with "wss://" (protocol), ws_url->is_secure shall be set to true ]
else if (strncmp(url, WSS_PROTOCOL, 6) == 0)
{
ws_url->is_secure = true;
}
else
{
// Codes_SRS_WS_URL_09_024: [ If protocol cannot be identified in url, the function shall fail and return NULL ]
LogError("Url protocol prefix not recognized");
result = MU_FAILURE;
}
if (result == 0)
{
size_t host_begin;
const char* port_delimiter = ":";
const char* path_delimiter = "/";
const char* query_delimiter = "?";
const char* delimiters1[3];
const char* delimiters2[1];
size_t delimiter_count = 3;
const char** current_delimiters = delimiters1;
const char* previous_delimiter = NULL;
bool host_parsed = false;
bool port_parsed = false;
bool path_parsed = false;
bool query_parsed = false;
STRING_TOKEN_HANDLE token;
delimiters1[0] = port_delimiter;
delimiters1[1] = path_delimiter;
delimiters1[2] = query_delimiter;
delimiters2[0] = query_delimiter;
host_begin = (ws_url->is_secure ? 6 : 5);
token = StringToken_GetFirst(url + host_begin, url_length - host_begin, current_delimiters, delimiter_count);
if (token == NULL)
{
LogError("Failed getting first url token");
result = MU_FAILURE;
}
else
{
do
{
const char* current_delimiter = (char*)StringToken_GetDelimiter(token);
if (previous_delimiter == NULL && !host_parsed && !port_parsed && !path_parsed && !query_parsed)
{
// Codes_SRS_WS_URL_09_006: [ The pointer to the token starting right after protocol (in the url string) shall be stored in ws_url->host ]
ws_url->host = (char*)StringToken_GetValue(token);
// Codes_SRS_WS_URL_09_008: [ The length from ws_url->host up to the first occurrence of either ":" (port_delimiter), "/" (path_delimiter), "?" (query_delimiter) or \0 shall be stored in ws_url->host_length ]
ws_url->host_length = StringToken_GetLength(token);
// Codes_SRS_WS_URL_09_007: [ If ws_url->host ends up being NULL, the function shall fail and return NULL ]
// Codes_SRS_WS_URL_09_009: [ If ws_url->host_length ends up being zero, the function shall fail and return NULL ]
if (ws_url->host == NULL || ws_url->host_length == 0)
{
LogError("Failed parsing websocket url host");
result = MU_FAILURE;
break;
}
else
{
host_parsed = true;
}
}
// Codes_SRS_WS_URL_09_010: [ If after ws_url->host the port_delimiter occurs (not preceeded by path_delimiter or query_delimiter) the number that follows shall be parsed and stored in ws_url->port ]
else if (previous_delimiter == port_delimiter && host_parsed && !port_parsed && !path_parsed && !query_parsed)
{
const char* port = StringToken_GetValue(token);
size_t port_length = StringToken_GetLength(token);
// Codes_SRS_WS_URL_09_011: [ If the port number fails to be parsed, the function shall fail and return NULL ]
if (port == NULL || port_length == 0)
{
LogError("Failed parsing websocket url port");
result = MU_FAILURE;
break;
}
else
{
char port_copy[10];
(void)memset(port_copy, 0, sizeof(char) * 10);
(void)memcpy(port_copy, port, port_length);
ws_url->port = (size_t)atoi(port_copy);
port_parsed = true;
}
}
// Codes_SRS_WS_URL_09_012: [ If after ws_url->host or the port number the path_delimiter occurs (not preceeded by query_delimiter) the following pointer address shall be stored in ws_url->path ]
else if (previous_delimiter == path_delimiter && host_parsed && !path_parsed && !query_parsed)
{
ws_url->path = (char*)StringToken_GetValue(token);
// Codes_SRS_WS_URL_09_014: [ The length from ws_url->path up to the first occurrence of either query_delimiter or \0 shall be stored in ws_url->path_length ]
ws_url->path_length = StringToken_GetLength(token);
// Codes_SRS_WS_URL_09_013: [ If the path component is present and ws_url->path ends up being NULL, the function shall fail and return NULL ]
// Codes_SRS_WS_URL_09_015: [ If the path component is present and ws_url->path_length ends up being zero, the function shall fail and return NULL ]
if (ws_url->path == NULL || ws_url->path_length == 0)
{
LogError("Failed parsing websocket url path");
result = MU_FAILURE;
break;
}
else
{
path_parsed = true;
}
}
// Codes_SRS_WS_URL_09_016: [ Next if the query_delimiter occurs the following pointer address shall be stored in ws_url->query ]
else if (previous_delimiter == query_delimiter && current_delimiter == NULL && host_parsed && !query_parsed)
{
ws_url->query = (char*)StringToken_GetValue(token);
// Codes_SRS_WS_URL_09_018: [ The length from ws_url->query up to \0 shall be stored in ws_url->query_length ]
ws_url->query_length = StringToken_GetLength(token);
// Codes_SRS_WS_URL_09_017: [ If the query component is present and ws_url->query ends up being NULL, the function shall fail and return NULL ]
// Codes_SRS_WS_URL_09_019: [ If the query component is present and ws_url->query_length ends up being zero, the function shall fail and return NULL ]
if (ws_url->query == NULL || ws_url->query_length == 0)
{
LogError("Failed parsing websocket url query");
result = MU_FAILURE;
break;
}
else
{
query_parsed = true;
}
}
else
{
LogError("Failed parsing websocket url (format not recognized)");
result = MU_FAILURE;
break;
}
if (current_delimiter == path_delimiter)
{
current_delimiters = delimiters2;
delimiter_count = 1;
}
previous_delimiter = current_delimiter;
}
while (StringToken_GetNext(token, current_delimiters, delimiter_count));
StringToken_Destroy(token);
}
}
return result;
}