From 2dd24efbcea3d447020d71f089f31a61e5422bae Mon Sep 17 00:00:00 2001 From: Alain B Date: Sat, 26 Dec 2020 22:39:35 +0100 Subject: [PATCH 1/4] Provides a definition for fcurl_feof --- include/fcurl.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/fcurl.h b/include/fcurl.h index 14b791c..cb95fe7 100644 --- a/include/fcurl.h +++ b/include/fcurl.h @@ -29,6 +29,7 @@ size_t fcurl_read(void *ptr, size_t size, size_t nmemb, FCURL *stream); size_t fcurl_write(const void *ptr, size_t size, size_t nmemb, FCURL *stream); int fcurl_flush(FCURL *stream); +int fcurl_eof(FCURL *stream); int fcurl_close(FCURL *stream); int fcurl_getc(FCURL *stream); char *fcurl_gets(char *s, int size, FCURL *stream); From 075c14ca44ef1ad292297869f201ee48898f882c Mon Sep 17 00:00:00 2001 From: Alain B Date: Sat, 26 Dec 2020 22:40:57 +0100 Subject: [PATCH 2/4] Fixed bug memcpy in callback + basic implem of feof --- src/fcurl.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/fcurl.c b/src/fcurl.c index 6c41bbd..07929eb 100644 --- a/src/fcurl.c +++ b/src/fcurl.c @@ -47,7 +47,7 @@ static size_t write_callback(char *buffer, size_t size, size_t nitems, size_t n_copytouser = MIN(size, n_remainuser); /* space left in the user buffer, copy as much as possible to there */ - memcpy(h->user.p, buffer, n_copytouser); + memcpy(h->user.p + h->user.used, buffer, n_copytouser); buffer += n_copytouser; size -= n_copytouser; @@ -196,6 +196,8 @@ int fcurl_close(struct fcurl_handle *h) /* cleanup */ curl_easy_cleanup(h->curl); + curl_multi_cleanup(h->mh); + free(h->b.p); free(h); @@ -204,11 +206,8 @@ int fcurl_close(struct fcurl_handle *h) int fcurl_eof(struct fcurl_handle *h) { - int ret=0; - - /* add code here */ - - return ret; + /* Still does not make difference between EOF and errors */ + return (h->transfer_complete && 0 == h->b.used); } /* From 1deed29f2f6f66154d416e0cec221707a82609aa Mon Sep 17 00:00:00 2001 From: Alain B Date: Mon, 28 Dec 2020 10:29:24 +0100 Subject: [PATCH 3/4] New algorithm: replaced mallocs with pauses (curl_easy_pause) --- src/fcurl.c | 62 ++++++++++++++++------------------------------------ src/handle.h | 3 ++- 2 files changed, 21 insertions(+), 44 deletions(-) diff --git a/src/fcurl.c b/src/fcurl.c index 07929eb..793ee4b 100644 --- a/src/fcurl.c +++ b/src/fcurl.c @@ -40,8 +40,9 @@ static size_t write_callback(char *buffer, size_t size, size_t nitems, osize = size; /* keep the original input size for returning */ - n_remaining = h->b.size - h->b.used; /* remaining space in private buffer */ n_remainuser = h->user.size - h->user.used; /* remaining space in user buffer */ + buffer += h->used; + size -= h->used; if(n_remainuser) { size_t n_copytouser = MIN(size, n_remainuser); @@ -55,35 +56,16 @@ static size_t write_callback(char *buffer, size_t size, size_t nitems, h->user.used += n_copytouser; } - if(!size) + if(!size) { /* all data is taken care of */ + h->used = 0; return osize; - - if(size > n_remaining) { - char *newp; - size_t n_missing = (size - n_remaining); - - /* we will have reaons to go back and reconsider buffer growth algorithms - later */ - size_t newsize = h->b.size + n_missing + BUFFERGROWTHMARGIN; - - newp = realloc(h->b.p, newsize); - if(!newp) { - /* use fprintf() during intial debugging */ - fprintf(stderr, "out of memory!\n"); - return 0; /* makes the transfer fail */ - } - else { - h->b.size = newsize; - h->b.p = newp; - } } - /* copy data from libcurl into our handle specific buffer */ - memcpy(&h->b.p[h->b.used], buffer, size); - h->b.used += size; - - return osize; + /* Excess data, pause the transfer, storing how much is already used */ + h->used = osize - size; + h->paused = true; + return CURL_WRITEFUNC_PAUSE; } /* @@ -98,25 +80,20 @@ static int transfer(struct fcurl_handle *h, const void *target, size_t max) h->user.used = 0; h->user.size = max; - if(h->b.used) { - /* there is data left from the previous invoke */ - size_t n_copytouser = MIN(h->b.used, max); - memcpy((char *)target, h->b.p, n_copytouser); - h->user.used += n_copytouser; - - /* slide the remaining buffer to the beginning */ - memmove(h->b.p, h->b.p+n_copytouser, h->b.used - n_copytouser); - h->b.used -= n_copytouser; - - if(h->user.used == max) - return 0; - } - else if(h->transfer_complete) + if(h->transfer_complete) return 1; /* no buffer data left and transfer complete == done */ if(!h->transfer_complete) { do { - mc = curl_multi_wait(h->mh, NULL, 0, 5000, &numfds); + if (h->paused) { + /* Unpause + no 'wait' because it was paused with excess data */ + h->paused = false; + curl_easy_pause(h->curl, CURLPAUSE_CONT); + mc = CURLM_OK; + } + else { + mc = curl_multi_wait(h->mh, NULL, 0, 5000, &numfds); + } if(mc == CURLM_OK) { int left; struct CURLMsg *m; @@ -198,7 +175,6 @@ int fcurl_close(struct fcurl_handle *h) curl_multi_cleanup(h->mh); - free(h->b.p); free(h); return ret; @@ -207,7 +183,7 @@ int fcurl_close(struct fcurl_handle *h) int fcurl_eof(struct fcurl_handle *h) { /* Still does not make difference between EOF and errors */ - return (h->transfer_complete && 0 == h->b.used); + return h->transfer_complete; } /* diff --git a/src/handle.h b/src/handle.h index bf60cac..c840672 100644 --- a/src/handle.h +++ b/src/handle.h @@ -31,9 +31,10 @@ struct buffer { struct fcurl_handle { CURL *curl; CURLM *mh; + bool paused; + size_t used; /* used in callback buffer before pausing */ bool transfer_complete; CURLcode transfer_rc; /* assigned after completed transfer */ - struct buffer b; /* allocated and handled internally */ struct buffer user; /* as provided by the application */ }; From dec60b951eefede095129e48a0fb2897b142a7d6 Mon Sep 17 00:00:00 2001 From: Alain B Date: Wed, 30 Dec 2020 09:18:22 +0100 Subject: [PATCH 4/4] Styling: replaced TABs with space as the original styling does. --- src/fcurl.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/fcurl.c b/src/fcurl.c index 793ee4b..0374662 100644 --- a/src/fcurl.c +++ b/src/fcurl.c @@ -86,10 +86,10 @@ static int transfer(struct fcurl_handle *h, const void *target, size_t max) if(!h->transfer_complete) { do { if (h->paused) { - /* Unpause + no 'wait' because it was paused with excess data */ - h->paused = false; - curl_easy_pause(h->curl, CURLPAUSE_CONT); - mc = CURLM_OK; + /* Unpause + no 'wait' because it was paused with excess data */ + h->paused = false; + curl_easy_pause(h->curl, CURLPAUSE_CONT); + mc = CURLM_OK; } else { mc = curl_multi_wait(h->mh, NULL, 0, 5000, &numfds);