summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/http_session.c219
-rwxr-xr-xtests/http-gtest-async.cpp32
2 files changed, 162 insertions, 89 deletions
diff --git a/src/http_session.c b/src/http_session.c
index bd64331..1a25abd 100644
--- a/src/http_session.c
+++ b/src/http_session.c
@@ -19,101 +19,144 @@
static int generated_session_id = -1;
+static bool __is_auth_required(http_status_code_e status)
+{
+ return (status == HTTP_STATUS_UNAUTHORIZED || status == HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED);
+}
+
+static http_error_code_e __convert_to_http_error_code(CURLcode code)
+{
+ DBG("curl code[%d]", code);
+ switch (code) {
+ case CURLE_OK:
+ return HTTP_ERROR_NONE;
+ case CURLE_COULDNT_RESOLVE_HOST:
+ return HTTP_ERROR_COULDNT_RESOLVE_HOST;
+ case CURLE_COULDNT_CONNECT:
+ return HTTP_ERROR_COULDNT_CONNECT;
+ case CURLE_SSL_CONNECT_ERROR:
+ return HTTP_ERROR_SSL_CONNECT_ERROR;
+ case CURLE_OPERATION_TIMEDOUT:
+ return HTTP_ERROR_OPERATION_TIMEDOUT;
+ case CURLE_ABORTED_BY_CALLBACK:
+ return HTTP_ERROR_CANCELED;
+ default:
+ return HTTP_ERROR_OPERATION_FAILED;
+ }
+}
+
+static void __set_requried_auth_scheme(__http_transaction_h *transaction)
+{
+ if (transaction == NULL)
+ return;
+
+ long http_auth = _CURL_HTTP_AUTH_NONE;
+ long proxy_auth = _CURL_HTTP_AUTH_NONE;
+ curl_easy_getinfo(transaction->easy_handle, CURLINFO_HTTPAUTH_AVAIL, &http_auth);
+ curl_easy_getinfo(transaction->easy_handle, CURLINFO_PROXYAUTH_AVAIL, &proxy_auth);
+
+ bool is_proxy_auth = (proxy_auth != _CURL_HTTP_AUTH_NONE);
+ http_auth_scheme_e auth_scheme = _get_http_auth_scheme(is_proxy_auth, http_auth);
+ http_transaction_set_http_auth_scheme(transaction, auth_scheme);
+}
+
+static void _update_auth_info(__http_transaction_h *transaction)
+{
+ if (transaction == NULL)
+ return;
+
+ transaction->auth_required = TRUE;
+
+ __set_requried_auth_scheme(transaction);
+ _set_authentication_info(transaction);
+}
+
+static void _handle_success_request(__http_transaction_h *transaction)
+{
+ if (!transaction->completed_cb)
+ return;
+
+ http_status_code_e status = 0;
+ http_transaction_response_get_status_code(transaction, &status);
+ DBG("Status(%d)\n", status);
+
+ if (__is_auth_required(status))
+ _update_auth_info(transaction);
+
+ if (transaction->completed_cb)
+ transaction->completed_cb(transaction, transaction->completed_user_data);
+}
+
+static void _handle_fail_request(__http_transaction_h *transaction, http_error_code_e error)
+{
+ DBG("Error: %d", error);
+ if (!transaction)
+ return;
+
+ if (!transaction->aborted_cb)
+ return;
+
+ if (transaction->aborted_cb)
+ transaction->aborted_cb(transaction, error, transaction->aborted_user_data);
+}
+
+static void _handle_result(__http_transaction_h *transaction, CURLcode result)
+{
+ if (transaction == NULL)
+ return;
+
+ switch (result)
+ {
+ case CURLE_OK:
+ return _handle_success_request(transaction);
+ case CURLE_COULDNT_RESOLVE_HOST:
+ case CURLE_COULDNT_CONNECT:
+ case CURLE_SSL_CONNECT_ERROR:
+ case CURLE_OPERATION_TIMEDOUT:
+ case CURLE_ABORTED_BY_CALLBACK:
+ default:
+ return _handle_fail_request(transaction, __convert_to_http_error_code(result));
+ }
+}
+
static void _handle_completed_transaction(__http_session_h *user_data)
{
- __http_transaction_h *transaction = NULL;
- __http_session_h *session = user_data;
+ if (user_data == NULL)
+ return;
+ __http_session_h *session = user_data;
CURLMsg* message = NULL;
int count = 0;
- CURL* curl_easy = NULL;
- char* url = NULL;
- CURLcode curl_code = CURLE_OK;
-
- if (!session) return;
-
- message = curl_multi_info_read(session->multi_handle, &count);
-
- while (message != NULL) {
- if (message->msg == CURLMSG_DONE) {
- curl_easy = message->easy_handle;
- curl_code = message->data.result;
-
- if (curl_easy) {
- curl_easy_getinfo(curl_easy, CURLINFO_PRIVATE, (char**) &transaction);
- curl_easy_getinfo(curl_easy, CURLINFO_EFFECTIVE_URL, &url);
- }
-
- if (!transaction) break;
-
- if (transaction->upload_event)
- _close_upload_file(transaction);
-
- DBG("Completed -%s: result(%d)\n", url, curl_code);
-
- switch (curl_code) {
- case CURLE_OK:
- if (transaction->completed_cb) {
- long http_auth = _CURL_HTTP_AUTH_NONE;
- long proxy_auth = _CURL_HTTP_AUTH_NONE;
- http_status_code_e status = 0;
- bool auth_req = FALSE;
- bool proxy = FALSE;
-
- http_transaction_response_get_status_code(transaction, &status);
- DBG("Status(%d)\n", status);
-
- if (status == HTTP_STATUS_UNAUTHORIZED || status == HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED) {
-
- transaction->auth_required = auth_req = TRUE;
-
- curl_easy_getinfo(transaction->easy_handle, CURLINFO_HTTPAUTH_AVAIL, &http_auth);
- curl_easy_getinfo(transaction->easy_handle, CURLINFO_PROXYAUTH_AVAIL, &proxy_auth);
-
- if (proxy_auth != _CURL_HTTP_AUTH_NONE)
- proxy = TRUE;
-
- http_auth_scheme_e auth_scheme = _get_http_auth_scheme(proxy, http_auth);
- http_transaction_set_http_auth_scheme(transaction, auth_scheme);
- _set_authentication_info(transaction);
- }
- if (transaction->completed_cb)
- transaction->completed_cb(transaction, transaction->completed_user_data);
- }
-
- break;
- case CURLE_COULDNT_RESOLVE_HOST:
- if (transaction->aborted_cb)
- transaction->aborted_cb(transaction, HTTP_ERROR_COULDNT_RESOLVE_HOST, transaction->aborted_user_data);
- break;
- case CURLE_COULDNT_CONNECT:
- if (transaction->aborted_cb)
- transaction->aborted_cb(transaction, HTTP_ERROR_COULDNT_CONNECT, transaction->aborted_user_data);
- break;
- case CURLE_SSL_CONNECT_ERROR:
- if (transaction->aborted_cb)
- transaction->aborted_cb(transaction, HTTP_ERROR_SSL_CONNECT_ERROR, transaction->aborted_user_data);
- break;
- case CURLE_OPERATION_TIMEDOUT:
- if (transaction->aborted_cb)
- transaction->aborted_cb(transaction, HTTP_ERROR_OPERATION_TIMEDOUT, transaction->aborted_user_data);
- break;
- case CURLE_ABORTED_BY_CALLBACK:
- if (transaction->aborted_cb)
- transaction->aborted_cb(transaction, HTTP_ERROR_CANCELED, transaction->aborted_user_data);
- break;
- default:
- if (transaction->aborted_cb)
- transaction->aborted_cb(transaction, HTTP_ERROR_OPERATION_FAILED, transaction->aborted_user_data);
- break;
- }
-
- if (session->multi_handle != NULL && curl_easy != NULL)
- curl_multi_remove_handle(session->multi_handle, transaction->easy_handle);
- }
+ do {
message = curl_multi_info_read(session->multi_handle, &count);
- }
+ if (message == NULL)
+ continue;
+
+ if (message->msg != CURLMSG_DONE)
+ continue;
+
+ char* url = NULL;
+ __http_transaction_h *transaction = NULL;
+ CURL *curl_easy = message->easy_handle;
+ if (curl_easy) {
+ curl_easy_getinfo(curl_easy, CURLINFO_PRIVATE, (char **)&transaction);
+ curl_easy_getinfo(curl_easy, CURLINFO_EFFECTIVE_URL, &url);
+ }
+
+ if (!transaction)
+ break;
+
+ if (transaction->upload_event)
+ _close_upload_file(transaction);
+
+ DBG("Completed -%s: result(%d)\n", url, message->data.result);
+ _handle_result(transaction, message->data.result);
+
+ if (session->multi_handle != NULL && curl_easy != NULL)
+ curl_multi_remove_handle(session->multi_handle, transaction->easy_handle);
+
+ } while (message != NULL);
}
gboolean curl_request_check(gpointer data)
diff --git a/tests/http-gtest-async.cpp b/tests/http-gtest-async.cpp
index 7a22374..3f0a613 100755
--- a/tests/http-gtest-async.cpp
+++ b/tests/http-gtest-async.cpp
@@ -37,6 +37,7 @@ static bool _completed_flag;
static bool _canceled_flag;
static bool _paused_flag;
static bool _resumed_flag;
+static http_error_code_e _error_code;
static void _completed_cb(http_transaction_h http_transaction, void *user_data);
static void _aborted_cb(http_transaction_h http_transaction,
@@ -57,6 +58,7 @@ class HttpAsyncTest: public ::testing::Test {
_canceled_flag = false;
_paused_flag = false;
_resumed_flag = false;
+ _error_code = HTTP_ERROR_NONE;
http_init();
http_session_create(HTTP_SESSION_MODE_NORMAL, &session);
@@ -88,6 +90,7 @@ static void _aborted_cb(http_transaction_h http_transaction,
http_error_code_e error, void *user_data)
{
_completed_flag = false;
+ _error_code = error;
if (error == HTTP_ERROR_CANCELED)
_canceled_flag = true;
HttpTestUtil::stopMainLoop();
@@ -120,7 +123,7 @@ static void _progress_resume_cb(http_transaction_h http_transaction,
_resumed_flag = true;
}
-TEST_F(HttpAsyncTest, SubmitN)
+TEST_F(HttpAsyncTest, SubmitN1)
{
http_transaction_request_set_uri(transaction, "https://untrusted-root.badssl.com");
EXPECT_EQ(HTTP_ERROR_NONE, http_transaction_submit(transaction));
@@ -128,6 +131,32 @@ TEST_F(HttpAsyncTest, SubmitN)
HttpTestUtil::runMainLoop();
EXPECT_EQ(false, _completed_flag);
+#if !defined USE_LOCALHOST_SERVER
+ EXPECT_EQ(HTTP_ERROR_SSL_CONNECT_ERROR, _error_code);
+#endif
+}
+
+TEST_F(HttpAsyncTest, SubmitN2)
+{
+ http_transaction_request_set_uri(transaction, "123qw12qw123");
+ EXPECT_EQ(HTTP_ERROR_NONE, http_transaction_submit(transaction));
+
+ HttpTestUtil::runMainLoop();
+
+ EXPECT_EQ(false, _completed_flag);
+ EXPECT_EQ(HTTP_ERROR_COULDNT_RESOLVE_HOST, _error_code);
+}
+
+TEST_F(HttpAsyncTest, SubmitN3)
+{
+ http_transaction_set_timeout(transaction, 2);
+ http_transaction_request_set_uri(transaction, "192.168.0.248");
+ EXPECT_EQ(HTTP_ERROR_NONE, http_transaction_submit(transaction));
+
+ HttpTestUtil::runMainLoop();
+
+ EXPECT_EQ(false, _completed_flag);
+ EXPECT_EQ(HTTP_ERROR_OPERATION_TIMEDOUT, _error_code);
}
TEST_F(HttpAsyncTest, SubmitP)
@@ -147,6 +176,7 @@ TEST_F(HttpAsyncTest, CancelP)
HttpTestUtil::runMainLoop();
EXPECT_EQ(true, _canceled_flag);
+ EXPECT_EQ(HTTP_ERROR_CANCELED, _error_code);
}
TEST_F(HttpAsyncTest, PauseP)