connectivity: don't cache HTTP response for comparing connectivity response

We don't need to remember (and compare) all the bytes that we received.
We can just compare them right away, and remember how many good bytes
we received.
This commit is contained in:
Thomas Haller
2019-01-14 14:40:12 +01:00
parent 7807ffff83
commit 477e91d753

View File

@@ -92,7 +92,7 @@ struct _NMConnectivityCheckHandle {
struct curl_slist *request_headers;
struct curl_slist *hosts;
GString *recv_msg;
gsize response_good_cnt;
guint curl_timer;
int ch_ifindex;
@@ -271,8 +271,6 @@ cb_data_complete (NMConnectivityCheckHandle *cb_data,
#if WITH_CONCHECK
_con_config_unref (cb_data->concheck.con_config);
if (cb_data->concheck.recv_msg)
g_string_free (cb_data->concheck.recv_msg, TRUE);
#endif
g_free (cb_data->ifspec);
if (cb_data->completed_log_message_free)
@@ -391,8 +389,7 @@ _con_curl_check_connectivity (CURLM *mhandle, int sockfd, int ev_bitmask)
}
if ( response_code == 200
&& ( !cb_data->concheck.recv_msg
|| cb_data->concheck.recv_msg->len == 0)) {
&& cb_data->concheck.response_good_cnt == 0) {
/* we expected no response, and indeed we got an empty reply (with status code 200) */
cb_data_queue_completed (cb_data,
NM_CONNECTIVITY_FULL,
@@ -561,6 +558,8 @@ easy_write_cb (void *buffer, size_t size, size_t nmemb, void *userdata)
{
NMConnectivityCheckHandle *cb_data = userdata;
size_t len = size * nmemb;
size_t response_len;
size_t check_len;
const char *response;
if (cb_data->completed_state != NM_CONNECTIVITY_UNKNOWN) {
@@ -573,11 +572,6 @@ easy_write_cb (void *buffer, size_t size, size_t nmemb, void *userdata)
return len;
}
if (!cb_data->concheck.recv_msg)
cb_data->concheck.recv_msg = g_string_sized_new (len + 10);
g_string_append_len (cb_data->concheck.recv_msg, buffer, len);
response = _con_config_get_response (cb_data->concheck.con_config);;
if (response[0] == '\0') {
@@ -586,22 +580,55 @@ easy_write_cb (void *buffer, size_t size, size_t nmemb, void *userdata)
* response based on the status code 204.
*
* Continue receiving... */
cb_data->concheck.response_good_cnt += len;
if (cb_data->concheck.response_good_cnt > (gsize) (100 * 1024)) {
/* we expect an empty response. We accept either
* 1) status code 204 and any response
* 2) status code 200 and an empty reponse.
*
* Here, we want to continue receiving data, to see whether we have
* case 1). Arguably, the server shouldn't send us 204 with a non-empty
* response, but we accept that also with a non-empty response, so
* keep receiving.
*
* However, if we get an excessive amound of data, we put a stop on it
* and fail. */
cb_data_queue_completed (cb_data,
NM_CONNECTIVITY_PORTAL,
"unexpected non-empty response",
NULL);
return 0;
}
return len;
}
if (cb_data->concheck.recv_msg->len >= strlen (response)) {
/* We already have enough data -- check response */
if (g_str_has_prefix (cb_data->concheck.recv_msg->str, response)) {
cb_data_queue_completed (cb_data,
NM_CONNECTIVITY_FULL,
"expected response",
NULL);
} else {
cb_data_queue_completed (cb_data,
NM_CONNECTIVITY_PORTAL,
"unexpected response",
NULL);
}
nm_assert (cb_data->concheck.response_good_cnt < strlen (response));
response_len = strlen (response);
check_len = NM_MIN (len,
response_len - cb_data->concheck.response_good_cnt);
if (strncmp (&response[cb_data->concheck.response_good_cnt],
buffer,
check_len) != 0) {
cb_data_queue_completed (cb_data,
NM_CONNECTIVITY_PORTAL,
"unexpected response",
NULL);
return 0;
}
cb_data->concheck.response_good_cnt += len;
if (cb_data->concheck.response_good_cnt >= response_len) {
/* We already have enough data, and it matched. */
cb_data_queue_completed (cb_data,
NM_CONNECTIVITY_FULL,
"expected response",
NULL);
return 0;
}