curl timeout management

This commit is contained in:
Sorunome 2019-10-18 19:46:39 +02:00
parent b9bbcf0209
commit 08ed4523f3
No known key found for this signature in database
GPG key ID: 63E31F7B5993A9C4
3 changed files with 71 additions and 14 deletions

View file

@ -25,6 +25,11 @@ struct UserInfo {
std::string avatarUrl; std::string avatarUrl;
}; };
enum struct RequestError : u8 {
none,
timeout,
};
class Client { class Client {
private: private:
public: public:
@ -36,13 +41,14 @@ public:
bool stopSyncing = false; bool stopSyncing = false;
bool isSyncing = false; bool isSyncing = false;
Thread syncThread; Thread syncThread;
RequestError lastRequestError;
void (* sync_event_callback)(std::string roomId, json_t* event) = 0; void (* sync_event_callback)(std::string roomId, json_t* event) = 0;
void processSync(json_t* sync); void processSync(json_t* sync);
json_t* doSync(std::string token); json_t* doSync(std::string token, int timeout);
void startSync(); void startSync();
json_t* doRequest(const char* method, std::string path, json_t* body = NULL); json_t* doRequest(const char* method, std::string path, json_t* body = NULL, int timeout = 5);
json_t* doRequestCurl(const char* method, std::string url, json_t* body = NULL); json_t* doRequestCurl(const char* method, std::string url, json_t* body, int timeout);
json_t* doRequestHttpc(const char* method, std::string url, json_t* body = NULL); json_t* doRequestHttpc(const char* method, std::string url, json_t* body, int timeout);
public: public:
Client(std::string homeserverUrl, std::string matrixToken = "", Store* clientStore = NULL); Client(std::string homeserverUrl, std::string matrixToken = "", Store* clientStore = NULL);
std::string getToken(); std::string getToken();

View file

@ -407,13 +407,15 @@ void Client::processSync(json_t* sync) {
} }
void Client::startSync() { void Client::startSync() {
int timeout = 60;
while (true) { while (true) {
std::string token = store->getSyncToken(); std::string token = store->getSyncToken();
if (stopSyncing) { if (stopSyncing) {
return; return;
} }
json_t* ret = doSync(token); json_t* ret = doSync(token, timeout);
if (ret) { if (ret) {
timeout = 60;
// set the token for the next batch // set the token for the next batch
json_t* token = json_object_get(ret, "next_batch"); json_t* token = json_object_get(ret, "next_batch");
if (token) { if (token) {
@ -423,19 +425,24 @@ void Client::startSync() {
} }
processSync(ret); processSync(ret);
json_decref(ret); json_decref(ret);
} else {
if (lastRequestError == RequestError::timeout) {
timeout += 10*60;
D printf_top("Timeout reached, increasing it to %d\n", timeout);
}
} }
svcSleepThread((u64)1000000ULL * (u64)200); svcSleepThread((u64)1000000ULL * (u64)200);
} }
} }
json_t* Client::doSync(std::string token) { json_t* Client::doSync(std::string token, int timeout) {
// D printf_top("Doing sync with token %s\n", token.c_str()); // D printf_top("Doing sync with token %s\n", token.c_str());
std::string query = "?full_state=false&timeout=" + std::to_string(SYNC_TIMEOUT); std::string query = "?full_state=false&timeout=" + std::to_string(SYNC_TIMEOUT);
if (token != "") { if (token != "") {
query += "&since=" + token; query += "&since=" + token;
} }
return doRequest("GET", "/_matrix/client/r0/sync" + query, NULL); return doRequest("GET", "/_matrix/client/r0/sync" + query, NULL, timeout);
} }
size_t DoRequestWriteCallback(char *contents, size_t size, size_t nmemb, void *userp) { size_t DoRequestWriteCallback(char *contents, size_t size, size_t nmemb, void *userp) {
@ -444,21 +451,30 @@ size_t DoRequestWriteCallback(char *contents, size_t size, size_t nmemb, void *u
} }
bool doingCurlRequest = false; bool doingCurlRequest = false;
bool doingHttpcRequest = false;
json_t* Client::doRequest(const char* method, std::string path, json_t* body) { json_t* Client::doRequest(const char* method, std::string path, json_t* body, int timeout) {
std::string url = hsUrl + path; std::string url = hsUrl + path;
requestId++; requestId++;
return doRequestCurl(method, url, body, timeout);
/*
if (!doingCurlRequest) { if (!doingCurlRequest) {
doingCurlRequest = true; doingCurlRequest = true;
json_t* ret = doRequestCurl(method, url, body); json_t* ret = doRequestCurl(method, url, body, timeout);
doingCurlRequest = false; doingCurlRequest = false;
return ret; return ret;
} else if (!doingHttpcRequest) {
doingHttpcRequest = true;
json_t* ret = doRequestHttpc(method, url, body, timeout);
doingHttpcRequest = false;
return ret;
} else { } else {
return doRequestHttpc(method, url, body); return doRequestCurl(method, url, body, timeout);
} }
*/
} }
json_t* Client::doRequestCurl(const char* method, std::string url, json_t* body) { json_t* Client::doRequestCurl(const char* method, std::string url, json_t* body, int timeout) {
D printf_top("Opening Request %d with CURL\n%s\n", requestId, url.c_str()); D printf_top("Opening Request %d with CURL\n%s\n", requestId, url.c_str());
if (!SOC_buffer) { if (!SOC_buffer) {
@ -499,7 +515,7 @@ json_t* Client::doRequestCurl(const char* method, std::string url, json_t* body)
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, method); curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, method);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, DoRequestWriteCallback); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, DoRequestWriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L); curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout);
// curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); // curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
// curl_easy_setopt(curl, CURLOPT_STDERR, stdout); // curl_easy_setopt(curl, CURLOPT_STDERR, stdout);
@ -507,6 +523,9 @@ json_t* Client::doRequestCurl(const char* method, std::string url, json_t* body)
curl_easy_cleanup(curl); curl_easy_cleanup(curl);
if (res != CURLE_OK) { if (res != CURLE_OK) {
D printf_top("curl res not ok %d\n", res); D printf_top("curl res not ok %d\n", res);
if (res == CURLE_OPERATION_TIMEDOUT) {
lastRequestError = RequestError::timeout;
}
return NULL; return NULL;
} }
@ -520,7 +539,7 @@ json_t* Client::doRequestCurl(const char* method, std::string url, json_t* body)
return content; return content;
} }
json_t* Client::doRequestHttpc(const char* method, std::string url, json_t* body) { json_t* Client::doRequestHttpc(const char* method, std::string url, json_t* body, int timeout) {
D printf_top("Opening Request %d with HTTPC\n%s\n", requestId, url.c_str()); D printf_top("Opening Request %d with HTTPC\n%s\n", requestId, url.c_str());
if (!HTTPC_inited) { if (!HTTPC_inited) {
@ -565,7 +584,7 @@ json_t* Client::doRequestHttpc(const char* method, std::string url, json_t* body
} }
ret = httpcBeginRequest(&context); ret = httpcBeginRequest(&context);
if (ret) { if (ret) {
D printf_top("Failed to perform request\n"); D printf_top("Failed to perform request %ld\n", ret);
httpcCloseContext(&context); httpcCloseContext(&context);
return NULL; return NULL;
} }
@ -576,6 +595,7 @@ json_t* Client::doRequestHttpc(const char* method, std::string url, json_t* body
url = std::string(newUrl); url = std::string(newUrl);
} }
} while ((statusCode >= 301 && statusCode <= 303) || (statusCode >= 307 && statusCode <= 308)); } while ((statusCode >= 301 && statusCode <= 303) || (statusCode >= 307 && statusCode <= 308));
D printf_top("Request http thingy successful\n");
ret = httpcGetDownloadSizeState(&context, NULL, &contentSize); ret = httpcGetDownloadSizeState(&context, NULL, &contentSize);
if (ret != 0) { if (ret != 0) {
httpcCloseContext(&context); httpcCloseContext(&context);

View file

@ -22,3 +22,34 @@ std::string urlencode(std::string s) {
} }
return e.str(); return e.str();
} }
/*
Result httpcDownloadDataTimeout(httpcContext *context, u8* buffer, u32 size, u32 *downloadedsize, u64 timeout)
{
Result ret=0;
Result dlret=HTTPC_RESULTCODE_DOWNLOADPENDING;
u32 pos=0, sz=0;
u32 dlstartpos=0;
u32 dlpos=0;
if(downloadedsize)*downloadedsize = 0;
ret=httpcGetDownloadSizeState(context, &dlstartpos, NULL);
if(R_FAILED(ret))return ret;
while(pos < size && dlret==HTTPC_RESULTCODE_DOWNLOADPENDING)
{
sz = size - pos;
dlret=httpcReceiveDataTimeout(context, &buffer[pos], sz, timeout);
ret=httpcGetDownloadSizeState(context, &dlpos, NULL);
if(R_FAILED(ret))return ret;
pos = dlpos - dlstartpos;
}
if(downloadedsize)*downloadedsize = pos;
return dlret;
}
*/