#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <curl/curl.h>
#include <curl/types.h>
#include <curl/easy.h>
struct data {
int type;
union {
CURL *curl;
FILE *file;
} handle;
char buffer[CURL_MAX_WRITE_SIZE];
char *readptr;
int bytes;
CURLMcode m;
};
typedef struct data URL_FILE;
CURLM *multi_handle;
static
size_t write_callback(char *buffer,
size_t size,
size_t nitems,
void *userp)
{
URL_FILE *url = (URL_FILE *)userp;
size *= nitems;
memcpy(url->readptr, buffer, size);
url->readptr += size;
url->bytes += size;
return size;
}
URL_FILE *url_fopen(char *url, char *operation)
{
URL_FILE *file;
int still_running;
file = (URL_FILE *)malloc(sizeof(URL_FILE));
if(!file)
return NULL;
memset(file, 0, sizeof(URL_FILE));
file->type = 1;
file->handle.curl = curl_easy_init();
curl_easy_setopt(file->handle.curl, CURLOPT_URL, url);
curl_easy_setopt(file->handle.curl, CURLOPT_FILE, file);
curl_easy_setopt(file->handle.curl, CURLOPT_VERBOSE, FALSE);
curl_easy_setopt(file->handle.curl, CURLOPT_WRITEFUNCTION, write_callback);
if(!multi_handle)
multi_handle = curl_multi_init();
curl_multi_add_handle(multi_handle, file->handle.curl);
while(CURLM_CALL_MULTI_PERFORM ==
curl_multi_perform(multi_handle, &still_running));
return file;
}
void url_fclose(URL_FILE *file)
{
curl_multi_remove_handle(multi_handle, file->handle.curl);
curl_easy_cleanup(file->handle.curl);
}
size_t url_fread(void *ptr, size_t size, size_t nmemb, URL_FILE *file)
{
fd_set fdread;
fd_set fdwrite;
fd_set fdexcep;
int maxfd;
struct timeval timeout;
int rc;
int still_running = 0;
if(!file->bytes) {
file->readptr = file->buffer;
if(CURLM_CALL_MULTI_PERFORM == file->m) {
while(CURLM_CALL_MULTI_PERFORM ==
curl_multi_perform(multi_handle, &still_running)) {
if(file->bytes) {
printf("(fread) WOAH! THis happened!\n");
break;
}
}
if(!still_running) {
printf("NO MORE RUNNING AROUND!\n");
return 0;
}
}
FD_ZERO(&fdread);
FD_ZERO(&fdwrite);
FD_ZERO(&fdexcep);
timeout.tv_sec = 500;
timeout.tv_usec = 0;
curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
switch(rc) {
case -1:
break;
case 0:
break;
default:
do {
file->m = curl_multi_perform(multi_handle, &still_running);
if(file->bytes)
break;
} while(CURLM_CALL_MULTI_PERFORM == file->m);
if(!still_running)
printf("NO MORE RUNNING AROUND!\n");
break;
}
}
else
printf("(fread) Skip network read\n");
if(file->bytes) {
int want = size * nmemb;
if(file->bytes < want)
want = file->bytes;
memcpy(ptr, file->readptr, want);
file->readptr += want;
file->bytes -= want;
printf("(fread) return %d bytes\n", want);
return want;
}
return 0;
}
int main(int argc, char *argv[])
{
URL_FILE *handle;
int nread;
char buffer[256];
handle = url_fopen("http://www.haxx.se", "r");
if(!handle) {
printf("couldn't url_fopen()\n");
}
do {
nread = url_fread(buffer, sizeof(buffer), 1, handle);
printf("We got: %d bytes\n", nread);
} while(nread);
url_fclose(handle);
return 0;
}