Abort curl connections setting the timeout (avoid crash closing connections)

This commit is contained in:
David Capello 2016-05-17 16:13:25 -03:00
parent c875e24928
commit d495c4d18a
4 changed files with 33 additions and 35 deletions

View File

@ -18,30 +18,26 @@
namespace net { namespace net {
class HttpRequestImpl class HttpRequestImpl {
{
public: public:
HttpRequestImpl(const std::string& url) HttpRequestImpl(const std::string& url)
: m_curl(curl_easy_init()) : m_curl(curl_easy_init())
, m_headerlist(NULL) , m_headerlist(nullptr)
, m_response(NULL) , m_response(nullptr) {
{
curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, this); curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, this);
curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, &HttpRequestImpl::writeBodyCallback); curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, &HttpRequestImpl::writeBodyCallback);
curl_easy_setopt(m_curl, CURLOPT_URL, url.c_str()); curl_easy_setopt(m_curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(m_curl, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(m_curl, CURLOPT_NOSIGNAL, 1);
} }
~HttpRequestImpl() ~HttpRequestImpl() {
{
if (m_headerlist) if (m_headerlist)
curl_slist_free_all(m_headerlist); curl_slist_free_all(m_headerlist);
curl_easy_cleanup(m_curl); curl_easy_cleanup(m_curl);
} }
void setHeaders(const HttpHeaders& headers) void setHeaders(const HttpHeaders& headers) {
{
if (m_headerlist) { if (m_headerlist) {
curl_slist_free_all(m_headerlist); curl_slist_free_all(m_headerlist);
m_headerlist = NULL; m_headerlist = NULL;
@ -59,31 +55,31 @@ public:
curl_easy_setopt(m_curl, CURLOPT_HTTPHEADER, m_headerlist); curl_easy_setopt(m_curl, CURLOPT_HTTPHEADER, m_headerlist);
} }
void send(HttpResponse& response) bool send(HttpResponse& response) {
{
m_response = &response; m_response = &response;
curl_easy_perform(m_curl); int res = curl_easy_perform(m_curl);
if (res != CURLE_OK)
return false;
long code; long code;
curl_easy_getinfo(m_curl, CURLINFO_RESPONSE_CODE, &code); curl_easy_getinfo(m_curl, CURLINFO_RESPONSE_CODE, &code);
m_response->setStatus(code); m_response->setStatus(code);
return true;
} }
void abort() void abort() {
{ curl_easy_setopt(m_curl, CURLOPT_TIMEOUT_MS, 1);
curl_easy_cleanup(m_curl); curl_easy_setopt(m_curl, CURLOPT_CONNECTTIMEOUT_MS, 1);
} }
private: private:
std::size_t writeBody(char* ptr, std::size_t bytes) std::size_t writeBody(char* ptr, std::size_t bytes) {
{
ASSERT(m_response != NULL); ASSERT(m_response != NULL);
m_response->write(ptr, bytes); m_response->write(ptr, bytes);
return bytes; return bytes;
} }
static std::size_t writeBodyCallback(char* ptr, std::size_t size, std::size_t nmemb, void* userdata) static std::size_t writeBodyCallback(char* ptr, std::size_t size, std::size_t nmemb, void* userdata) {
{
HttpRequestImpl* req = reinterpret_cast<HttpRequestImpl*>(userdata); HttpRequestImpl* req = reinterpret_cast<HttpRequestImpl*>(userdata);
return req->writeBody(ptr, size*nmemb); return req->writeBody(ptr, size*nmemb);
} }
@ -108,9 +104,9 @@ void HttpRequest::setHeaders(const HttpHeaders& headers)
m_impl->setHeaders(headers); m_impl->setHeaders(headers);
} }
void HttpRequest::send(HttpResponse& response) bool HttpRequest::send(HttpResponse& response)
{ {
m_impl->send(response); return m_impl->send(response);
} }
void HttpRequest::abort() void HttpRequest::abort()

View File

@ -1,5 +1,5 @@
// Aseprite Network Library // Aseprite Network Library
// Copyright (c) 2001-2015 David Capello // Copyright (c) 2001-2016 David Capello
// //
// This file is released under the terms of the MIT license. // This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information. // Read LICENSE.txt for more information.
@ -18,14 +18,13 @@ class HttpHeaders;
class HttpRequestImpl; class HttpRequestImpl;
class HttpResponse; class HttpResponse;
class HttpRequest class HttpRequest {
{
public: public:
HttpRequest(const std::string& url); HttpRequest(const std::string& url);
~HttpRequest(); ~HttpRequest();
void setHeaders(const HttpHeaders& headers); void setHeaders(const HttpHeaders& headers);
void send(HttpResponse& response); bool send(HttpResponse& response);
void abort(); void abort();
private: private:

View File

@ -96,7 +96,7 @@ public:
m_request->abort(); m_request->abort();
} }
void checkNewVersion(const Uuid& uuid, const std::string& extraParams, CheckUpdateDelegate* delegate) bool checkNewVersion(const Uuid& uuid, const std::string& extraParams, CheckUpdateDelegate* delegate)
{ {
#ifndef UPDATE_URL #ifndef UPDATE_URL
#define UPDATE_URL "" #define UPDATE_URL ""
@ -120,13 +120,16 @@ public:
std::stringstream body; std::stringstream body;
net::HttpResponse response(&body); net::HttpResponse response(&body);
m_request->send(response); if (m_request->send(response)) {
TRACE("Checking updates: %s (User-Agent: %s)\n", url.c_str(), getUserAgent().c_str());
TRACE("Response:\n--\n%s--\n", body.str().c_str());
TRACE("Checking updates: %s (User-Agent: %s)\n", url.c_str(), getUserAgent().c_str()); CheckUpdateResponse data(body.str());
TRACE("Response:\n--\n%s--\n", body.str().c_str()); delegate->onResponse(data);
return true;
CheckUpdateResponse data(body.str()); }
delegate->onResponse(data); else
return false;
} }
private: private:
@ -148,9 +151,9 @@ void CheckUpdate::abort()
m_impl->abort(); m_impl->abort();
} }
void CheckUpdate::checkNewVersion(const Uuid& uuid, const std::string& extraParams, CheckUpdateDelegate* delegate) bool CheckUpdate::checkNewVersion(const Uuid& uuid, const std::string& extraParams, CheckUpdateDelegate* delegate)
{ {
m_impl->checkNewVersion(uuid, extraParams, delegate); return m_impl->checkNewVersion(uuid, extraParams, delegate);
} }
} // namespace updater } // namespace updater

View File

@ -80,7 +80,7 @@ namespace updater {
// Sends a request to the "updates server" and calls the delegate // Sends a request to the "updates server" and calls the delegate
// when the response is received. // when the response is received.
void checkNewVersion(const Uuid& uuid, const std::string& extraParams, CheckUpdateDelegate* delegate); bool checkNewVersion(const Uuid& uuid, const std::string& extraParams, CheckUpdateDelegate* delegate);
private: private:
class CheckUpdateImpl; class CheckUpdateImpl;