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:
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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');
|
||||
|
||||
Reference in New Issue
Block a user