// Some versions of CURL don't report the correct exepected size when following redirects // This manual interpretation of the expected size fixes this. static size_t wswcurl_readheader( void *ptr, size_t size, size_t nmemb, void *stream ) { char buf[1024], *str; int slen; wswcurl_req *req = (wswcurl_req*)stream; memset( buf, 0, sizeof( buf ) ); memcpy( buf, ptr, ( size * nmemb ) > ( sizeof( buf ) - 1 ) ? ( sizeof( buf ) - 1 ) : ( size * nmemb ) ); str = buf; while( *str ) { if( ( *str >= 'a' ) && ( *str <= 'z' ) ) { *str -= 'a' - 'A'; } str++; } if( ( str = (char*)strstr( buf, "CONTENT-LENGTH:" ) ) ) { int length; while( *str && ( *str != ':' ) ) { str++; } str++; while( *str && ( *str == ' ' ) ) { str++; } slen = strlen( str ) - 1; while( ( slen > 0 ) && ( ( str[slen] == '\n' ) || ( str[slen] == '\r' ) || ( str[slen] == ' ' ) ) ) { str[slen] = '\0'; slen = strlen( str ) - 1; } length = atoi( str ); if( length >= 0 ) { req->rx_expsize = length; } } else if( ( str = (char*)strstr( buf, "TRANSFER-ENCODING:" ) ) ) { req->rx_expsize = 0; } qcurl_easy_getinfo( req->curl, CURLINFO_RESPONSE_CODE, &( req->respcode ) ); // call header callback function if( req->callback_header ) { req->callback_header( req, buf, req->customp ); } req->last_action = wswcurl_now(); return size * nmemb; }
static size_t wswcurl_write(void *ptr, size_t size, size_t nmemb, void *stream) { float progress; long numb; wswcurl_req *req = (wswcurl_req*)stream; if( !req->headers_done ) { req->headers_done = 1; } numb = size * nmemb; req->rxreceived += numb; req->last_action = wswcurl_now(); progress = !req->rx_expsize ? 0.0 : (float)(((double)req->rxreceived / (double)req->rx_expsize) * 100.0); clamp( progress, 0, 100 ); if( req->callback_read ) { return req->callback_read( req, ptr, numb, progress, req->customp ); } else { chained_buffer_t *cb; // Allocate new buffer cb = ( chained_buffer_t* )WMALLOC( sizeof(*cb) + numb ); memset( cb, 0, sizeof(*cb) ); // Stick the buffer to the end of the chain if( req->btail ) req->btail->next = cb; req->btail = cb; if( !req->bhead ) req->bhead = cb; memcpy( cb->data, ptr, numb ); cb->data[numb] = '\0'; cb->rxsize = numb; } return numb; }
int wswcurl_perform() { int ret = 0; wswcurl_req *r, *next; if (!curlmulti) return 0; // process requests in FIFO manner // check for timed out requests and requests that need to be paused r = http_requests_hnode; while( r ) { next = r->prev; if (r->status == WSTATUS_QUEUED) { // queued if (curlmulti_num_handles < WMAXMULTIHANDLES) { if (curl_multi_add_handle(curlmulti, r->curl)) { CURLDBG(("OOPS: CURL MULTI ADD HANDLE FAIL!!!")); } r->status = WSTATUS_STARTED; r->last_action = wswcurl_now(); curlmulti_num_handles++; } else { // stay in queue } } // handle pauses for synchronous requests if( r->status == WSTATUS_STARTED && !r->callback_read ) { if( r->rxreceived >= r->rxreturned + WMAXBUFFERING ) { wswcurl_pause( r ); } } // handle timeouts if( r->status == WSTATUS_STARTED ) { time_t now = wswcurl_now(); if( r->paused ) { // paused r->last_action = now; } else if( r->timeout && ( r->last_action + r->timeout <= now ) ) { // timed out r->respcode = -1; r->status = -CURLE_OPERATION_TIMEDOUT; if( r->callback_done ) { r->callback_done( r, r->status, r->customp ); } } } r = next; } //CURLDBG(("CURL BEFORE MULTI_PERFORM\n")); while ( curl_multi_perform(curlmulti, &ret) == CURLM_CALL_MULTI_PERFORM) { CURLDBG((" CURL MULTI LOOP\n")); } ret += wswcurl_checkmsg(); //CURLDBG(("CURL after checkmsg\n")); return ret; }