improved timeout handling and progress bar for autodownloads

http get now uses two timeout values: one for the max time since last
server response, and one for total download time.

When AC is waiting for a server response (before a http header was
received), the progress bar will show the timeout "completion".
This commit is contained in:
ac-stef
2015-09-07 14:53:57 +02:00
parent 0f37595c30
commit 7bdd91bc9f
4 changed files with 25 additions and 16 deletions
+6 -5
View File
@@ -75,7 +75,7 @@ int pingpckserver(void *data) // fetch updates.txt from a media server, measure
SDL_mutexV(pckpinglog_lock);
if(s->resolved)
{
int res = h.get(updatestxt, 5000, 0, true); // http HEAD request only - to get a nice ping value
int res = h.get(updatestxt, 5000, 10000, 0, true); // http HEAD request only - to get a nice ping value
if(h.response > 0)
{
s->ping = h.elapsedtime;
@@ -85,7 +85,7 @@ int pingpckserver(void *data) // fetch updates.txt from a media server, measure
if(h.response == 200)
{
h.outvec = new vector<uchar>;
res = h.get(updatestxt, 5000); // http GET
res = h.get(updatestxt, 5000, 20000); // http GET
if(res >= 0 && h.response == 200)
{ // parse updates.txt
h.outvec->add('\0');
@@ -341,9 +341,10 @@ int progress_callback_dlpackage(void *data, float progress)
if(progress_of < 0)
{
defformatstring(txt)("downloading %s... (esc to abort)", (const char *)data);
show_out_of_renderloop_progress(min(progress, 1.0f), txt);
if(progress < 0) show_out_of_renderloop_progress(progress + 1.0f, "waiting for response (esc to abort)");
else show_out_of_renderloop_progress(min(progress, 1.0f), txt);
}
else loadingscreen("downloading package %d of %d...\n%s %d%%\n(ESC to cancel)", progress_n, progress_of, (const char *)data, int(100.0 * progress));
else loadingscreen("downloading package %d of %d...\n%s \fs%s%d%%\fr\n(ESC to cancel)", progress_n, progress_of, (const char *)data, progress < 0 ? "\f3waiting " : "", int(100.0 * fabs(progress)));
if(interceptkey(SDLK_ESCAPE))
{
canceldownloads = true;
@@ -361,7 +362,7 @@ bool dlpackage(httpget &h, package *pck, pckserver *s) // download one package f
if(*host && h.set_host(host))
{
h.outstream = openvecfile(NULL);
int got = h.get(pck->requestname, 60000);
int got = h.get(pck->requestname, 6000, 90000);
if(!h.response)
{
if(!canceldownloads && s) s->ping = 0; // received a hard error from the server connection, better not try this one again
+13 -7
View File
@@ -86,13 +86,14 @@ bool httpget::connect(bool force)
return true;
}
int httpget::get(const char *url1, uint timeout, int range, bool head)
int httpget::get(const char *url1, uint timeout, uint totaltimeout, int range, bool head)
{
int redirects = 0, res = 0, transferred = 0;
vector<char> *content = NULL;
ASSERT(timeout); // zero is not allowed
ASSERT(timeout && totaltimeout); // zero is not allowed
stopwatch to;
to.start();
uint lastresponse = 0;
reset(1); // clear old response values and url
url = newstring(url1);
@@ -135,18 +136,20 @@ int httpget::get(const char *url1, uint timeout, int range, bool head)
buf.dataLength -= sent;
tcp_age.start();
traffic += sent;
lastresponse = to.elapsed();
}
float progress = ((float) to.elapsed()) / timeout;
if(progress > 1.0f) ERROR("timeout");
if(execcallback(progress)) return -1; // show progress bar, check for user interrupt
elapsedtime = to.elapsed();
if(elapsedtime > totaltimeout || elapsedtime > lastresponse + timeout) ERROR("timeout 1");
if(execcallback(-float(elapsedtime - lastresponse) / timeout)) return -1; // show progress bar, check for user interrupt
}
// get response
bool again = false, haveheader = false;
if(!retry) for(;;)
{
float progress = ((float) (elapsedtime = to.elapsed())) / timeout;
if(progress > 1.0f) ERROR("timeout");
elapsedtime = to.elapsed();
if(elapsedtime > totaltimeout || elapsedtime > lastresponse + timeout) ERROR(elapsedtime > totaltimeout ? "timeout 2" : "timeout 3");
float progress = -float(elapsedtime - lastresponse) / timeout;
enet_uint32 events = ENET_SOCKET_WAIT_RECEIVE;
if(rawrec.length() > maxsize || datarec.length() > maxsize) break;
if(enet_socket_wait(tcp, &events, 250) >= 0 && events)
@@ -164,6 +167,7 @@ int httpget::get(const char *url1, uint timeout, int range, bool head)
tcp_age.start();
traffic += recv;
if((transferred += recv) > maxtransfer) ERROR("transfer size exceeds limit");
lastresponse = to.elapsed();
// parsing received data
rawrec.add('\0'); // append '\0' to use string functions safely - will be removed again
@@ -248,6 +252,7 @@ int httpget::get(const char *url1, uint timeout, int range, bool head)
}
else break;
}
progress = float(datarec.length()) / (maxtransfer | 1); // not accurate, but moving
}
else
{
@@ -256,6 +261,7 @@ int httpget::get(const char *url1, uint timeout, int range, bool head)
progress = float(rawrec.length() - 1) / contentlength; // get a real progress bar
if(rawrec.length() - 1 >= contentlength) content = &rawrec;
}
else progress = float(rawrec.length() - 1) / (maxtransfer | 1); // not accurate, but moving
}
}
rawrec.drop();
+3 -2
View File
@@ -257,7 +257,8 @@ struct httpget
// result
char *header;
int response, chunked, gzipped, contentlength, offset, elapsedtime, traffic;
int response, chunked, gzipped, contentlength, offset, traffic;
uint elapsedtime;
vector<uchar> *outvec; // receives data, if not NULL (must be set up manually)
stream *outstream; // receives data, if not NULL (must be set up manually)
@@ -268,7 +269,7 @@ struct httpget
bool execcallback(float progress);
void disconnect();
bool connect(bool force = false);
int get(const char *url1, uint timeout, int range = 0, bool head = false); // get web ressource
int get(const char *url1, uint timeout, uint totaltimeout, int range = 0, bool head = false); // get web ressource
};
extern char *urlencode(const char *s, bool strict = false);
+3 -2
View File
@@ -1310,7 +1310,8 @@ bool cllock = false, clfail = false;
int progress_callback_retrieveservers(void *data, float progress)
{
show_out_of_renderloop_progress(min(progress, 1.0f), (const char *)data);
if(progress < 0) show_out_of_renderloop_progress(progress + 1.0f, "waiting for response (esc to abort)");
else show_out_of_renderloop_progress(min(progress, 1.0f), (const char *)data);
return interceptkey(SDLK_ESCAPE) ? 1 : 0;
}
@@ -1329,7 +1330,7 @@ void retrieveservers(vector<char> &data)
defformatstring(url)("/retrieve.do?action=list&name=%s&version=%d&build=%d", urlencode(global_name, true), AC_VERSION, getbuildtype()|(1<<16));
h.outvec = (vector<uchar> *) &data; // ouch...
show_out_of_renderloop_progress(0, progresstext);
h.get(url, RETRIEVELIMIT);
h.get(url, RETRIEVELIMIT, RETRIEVELIMIT);
if(h.response != 200) data.setsize(0);
h.outvec = NULL; // must not be cleaned up by httpget
if(data.length()) data.add('\0');