mirror of
https://github.com/rkd77/elinks.git
synced 2025-06-30 22:19:29 -04:00
[curl] multisocket action also without libevent or libev
This commit is contained in:
parent
776339aea3
commit
a142489a63
@ -458,6 +458,184 @@ sock_cb(CURL *e, curl_socket_t s, int what, void *cbp, void *sockp)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !defined(CONFIG_LIBEVENT) && !defined(CONFIG_LIBEV) && defined(CONFIG_LIBCURL)
|
||||||
|
/* Information associated with a specific easy handle */
|
||||||
|
typedef struct _ConnInfo
|
||||||
|
{
|
||||||
|
CURL *easy;
|
||||||
|
char *url;
|
||||||
|
GlobalInfo *global;
|
||||||
|
char error[CURL_ERROR_SIZE];
|
||||||
|
} ConnInfo;
|
||||||
|
|
||||||
|
/* Information associated with a specific socket */
|
||||||
|
typedef struct _SockInfo
|
||||||
|
{
|
||||||
|
curl_socket_t sockfd;
|
||||||
|
CURL *easy;
|
||||||
|
int action;
|
||||||
|
long timeout;
|
||||||
|
GlobalInfo *global;
|
||||||
|
} SockInfo;
|
||||||
|
|
||||||
|
GlobalInfo g;
|
||||||
|
|
||||||
|
#define mycase(code) \
|
||||||
|
case code: s = __STRING(code)
|
||||||
|
|
||||||
|
/* Die if we get a bad CURLMcode somewhere */
|
||||||
|
void
|
||||||
|
mcode_or_die(const char *where, CURLMcode code)
|
||||||
|
{
|
||||||
|
if (CURLM_OK != code) {
|
||||||
|
const char *s;
|
||||||
|
|
||||||
|
switch(code) {
|
||||||
|
mycase(CURLM_BAD_HANDLE); break;
|
||||||
|
mycase(CURLM_BAD_EASY_HANDLE); break;
|
||||||
|
mycase(CURLM_OUT_OF_MEMORY); break;
|
||||||
|
mycase(CURLM_INTERNAL_ERROR); break;
|
||||||
|
mycase(CURLM_UNKNOWN_OPTION); break;
|
||||||
|
mycase(CURLM_LAST); break;
|
||||||
|
default: s = "CURLM_unknown"; break;
|
||||||
|
mycase(CURLM_BAD_SOCKET);
|
||||||
|
fprintf(stderr, "ERROR: %s returns %s\n", where, s);
|
||||||
|
/* ignore this error */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "ERROR: %s returns %s\n", where, s);
|
||||||
|
//exit(code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Called by libevent when our timeout expires */
|
||||||
|
static void
|
||||||
|
timer_cb(void *userp)
|
||||||
|
{
|
||||||
|
GlobalInfo *g = (GlobalInfo *)userp;
|
||||||
|
CURLMcode rc;
|
||||||
|
|
||||||
|
rc = curl_multi_socket_action(g->multi, CURL_SOCKET_TIMEOUT, 0, &g->still_running);
|
||||||
|
mcode_or_die("timer_cb: curl_multi_socket_action", rc);
|
||||||
|
check_multi_info(g);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update the event timer after curl_multi library calls */
|
||||||
|
static int
|
||||||
|
multi_timer_cb(CURLM *multi, long timeout_ms, GlobalInfo *g)
|
||||||
|
{
|
||||||
|
(void)multi;
|
||||||
|
//fprintf(stderr, "multi_timer_cb: Setting timeout to %ld ms\n", timeout_ms);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if timeout_ms is -1, just delete the timer
|
||||||
|
*
|
||||||
|
* For all other values of timeout_ms, this should set or *update* the timer
|
||||||
|
* to the new value
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (timeout_ms == -1) {
|
||||||
|
kill_timer(&g->tim);
|
||||||
|
} else { /* includes timeout zero */
|
||||||
|
install_timer(&g->tim, timeout_ms, timer_cb, g);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
event_read_cb(void *userp)
|
||||||
|
{
|
||||||
|
SockInfo *f = (SockInfo *)userp;
|
||||||
|
GlobalInfo *g = (GlobalInfo*)f->global;
|
||||||
|
CURLMcode rc;
|
||||||
|
|
||||||
|
int action = CURL_CSELECT_IN;
|
||||||
|
|
||||||
|
rc = curl_multi_socket_action(g->multi, f->sockfd, action, &g->still_running);
|
||||||
|
mcode_or_die("event_cb: curl_multi_socket_action", rc);
|
||||||
|
check_multi_info(g);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
event_write_cb(void *userp)
|
||||||
|
{
|
||||||
|
SockInfo *f = (SockInfo *)userp;
|
||||||
|
GlobalInfo *g = (GlobalInfo*)f->global;
|
||||||
|
CURLMcode rc;
|
||||||
|
|
||||||
|
int action = CURL_CSELECT_OUT;
|
||||||
|
|
||||||
|
rc = curl_multi_socket_action(g->multi, f->sockfd, action, &g->still_running);
|
||||||
|
mcode_or_die("event_cb: curl_multi_socket_action", rc);
|
||||||
|
check_multi_info(g);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clean up the SockInfo structure */
|
||||||
|
static void
|
||||||
|
remsock(SockInfo *f)
|
||||||
|
{
|
||||||
|
//fprintf(stderr, "remsock f=%p\n", f);
|
||||||
|
|
||||||
|
if (f && f->sockfd) {
|
||||||
|
set_handlers(f->sockfd, NULL, NULL, NULL, NULL);
|
||||||
|
mem_free(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Assign information to a SockInfo structure */
|
||||||
|
static void
|
||||||
|
setsock(SockInfo *f, curl_socket_t s, CURL *e, int act, GlobalInfo *g)
|
||||||
|
{
|
||||||
|
int in = act & CURL_POLL_IN;
|
||||||
|
int out = act & CURL_POLL_OUT;
|
||||||
|
|
||||||
|
f->sockfd = s;
|
||||||
|
f->action = act;
|
||||||
|
f->easy = e;
|
||||||
|
|
||||||
|
set_handlers(s, in ? event_read_cb : NULL, out ? event_write_cb : NULL, NULL, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize a new SockInfo structure */
|
||||||
|
static void
|
||||||
|
addsock(curl_socket_t s, CURL *easy, int action, GlobalInfo *g)
|
||||||
|
{
|
||||||
|
//fprintf(stderr, "addsock easy=%p\n", easy);
|
||||||
|
|
||||||
|
SockInfo *fdp = mem_calloc(1, sizeof(SockInfo));
|
||||||
|
fdp->global = g;
|
||||||
|
setsock(fdp, s, easy, action, g);
|
||||||
|
curl_multi_assign(g->multi, s, fdp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CURLMOPT_SOCKETFUNCTION */
|
||||||
|
static int
|
||||||
|
sock_cb(CURL *e, curl_socket_t s, int what, void *cbp, void *sockp)
|
||||||
|
{
|
||||||
|
GlobalInfo *g = (GlobalInfo*) cbp;
|
||||||
|
SockInfo *fdp = (SockInfo*) sockp;
|
||||||
|
// const char *whatstr[]={ "none", "IN", "OUT", "INOUT", "REMOVE" };
|
||||||
|
|
||||||
|
//fprintf(stderr, "socket callback: s=%d e=%p what=%s ", s, e, whatstr[what]);
|
||||||
|
|
||||||
|
if (what == CURL_POLL_REMOVE) {
|
||||||
|
//fprintf(stderr, "\n");
|
||||||
|
remsock(fdp);
|
||||||
|
} else {
|
||||||
|
if (!fdp) {
|
||||||
|
//fprintf(stderr, "Adding data: %s\n", whatstr[what]);
|
||||||
|
addsock(s, e, what, g);
|
||||||
|
} else {
|
||||||
|
//fprintf(stderr, "Changing action from %s to %s\n", whatstr[fdp->action], whatstr[what]);
|
||||||
|
setsock(fdp, s, e, what, g);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef USE_LIBEVENT
|
#ifdef USE_LIBEVENT
|
||||||
const char *
|
const char *
|
||||||
get_libevent_version(void)
|
get_libevent_version(void)
|
||||||
@ -976,6 +1154,22 @@ select_loop(void (*init)(void))
|
|||||||
return;
|
return;
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
#if defined(CONFIG_LIBCURL)
|
||||||
|
memset(&g, 0, sizeof(GlobalInfo));
|
||||||
|
curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||||
|
g.multi = curl_multi_init();
|
||||||
|
|
||||||
|
/* setup the generic multi interface options we want */
|
||||||
|
curl_multi_setopt(g.multi, CURLMOPT_SOCKETFUNCTION, sock_cb);
|
||||||
|
curl_multi_setopt(g.multi, CURLMOPT_SOCKETDATA, &g);
|
||||||
|
curl_multi_setopt(g.multi, CURLMOPT_TIMERFUNCTION, multi_timer_cb);
|
||||||
|
curl_multi_setopt(g.multi, CURLMOPT_TIMERDATA, &g);
|
||||||
|
/* we do not call any curl_multi_socket*() function yet as we have no handles added! */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
while (!program.terminate) {
|
while (!program.terminate) {
|
||||||
struct timeval *timeout = NULL;
|
struct timeval *timeout = NULL;
|
||||||
int n, i, has_timer;
|
int n, i, has_timer;
|
||||||
@ -1082,6 +1276,11 @@ select_loop(void (*init)(void))
|
|||||||
n -= k;
|
n -= k;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if defined(CONFIG_LIBCURL)
|
||||||
|
curl_multi_cleanup(g.multi);
|
||||||
|
curl_global_cleanup();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
kill_timer(&periodic_redraw_timer);
|
kill_timer(&periodic_redraw_timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,8 @@
|
|||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "main/timer.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
@ -31,6 +33,7 @@ extern "C" {
|
|||||||
/* Global information, common to all connections */
|
/* Global information, common to all connections */
|
||||||
typedef struct _GlobalInfo
|
typedef struct _GlobalInfo
|
||||||
{
|
{
|
||||||
|
timer_id_T tim;
|
||||||
struct event_base *evbase;
|
struct event_base *evbase;
|
||||||
struct event fifo_event;
|
struct event fifo_event;
|
||||||
struct event timer_event;
|
struct event timer_event;
|
||||||
@ -51,6 +54,7 @@ void mcode_or_die(const char *where, CURLMcode code);
|
|||||||
/* Global information, common to all connections */
|
/* Global information, common to all connections */
|
||||||
typedef struct _GlobalInfo
|
typedef struct _GlobalInfo
|
||||||
{
|
{
|
||||||
|
timer_id_T tim;
|
||||||
struct ev_loop *loop;
|
struct ev_loop *loop;
|
||||||
struct ev_io fifo_event;
|
struct ev_io fifo_event;
|
||||||
struct ev_timer timer_event;
|
struct ev_timer timer_event;
|
||||||
@ -66,6 +70,23 @@ void check_multi_info(GlobalInfo *g);
|
|||||||
void mcode_or_die(const char *where, CURLMcode code);
|
void mcode_or_die(const char *where, CURLMcode code);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_LIBCURL) && !defined(CONFIG_LIBEV) && !defined(CONFIG_LIBEVENT)
|
||||||
|
/* Global information, common to all connections */
|
||||||
|
typedef struct _GlobalInfo
|
||||||
|
{
|
||||||
|
timer_id_T tim;
|
||||||
|
CURLM *multi;
|
||||||
|
int still_running;
|
||||||
|
FILE *input;
|
||||||
|
} GlobalInfo;
|
||||||
|
|
||||||
|
extern GlobalInfo g;
|
||||||
|
|
||||||
|
void check_multi_info(GlobalInfo *g);
|
||||||
|
|
||||||
|
void mcode_or_die(const char *where, CURLMcode code);
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef void (*select_handler_T)(void *);
|
typedef void (*select_handler_T)(void *);
|
||||||
|
|
||||||
/* Start the select loop after calling the passed @init() function. */
|
/* Start the select loop after calling the passed @init() function. */
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
top_builddir=../../..
|
top_builddir=../../..
|
||||||
include $(top_builddir)/Makefile.config
|
include $(top_builddir)/Makefile.config
|
||||||
|
|
||||||
OBJS-$(CONFIG_LIBEVENT) = ftp.o http.o
|
OBJ = ftp.o http.o
|
||||||
OBJS-$(CONFIG_LIBEV) = ftp.o http.o
|
|
||||||
|
|
||||||
include $(top_srcdir)/Makefile.lib
|
include $(top_srcdir)/Makefile.lib
|
||||||
|
@ -10,7 +10,7 @@ extern "C" {
|
|||||||
|
|
||||||
extern struct module ftpes_protocol_module;
|
extern struct module ftpes_protocol_module;
|
||||||
|
|
||||||
#if defined(CONFIG_FTP) && defined(CONFIG_LIBCURL) && (defined(CONFIG_LIBEVENT) || defined(CONFIG_LIBEV))
|
#if defined(CONFIG_FTP) && defined(CONFIG_LIBCURL)
|
||||||
extern protocol_handler_T ftpes_protocol_handler;
|
extern protocol_handler_T ftpes_protocol_handler;
|
||||||
#else
|
#else
|
||||||
#define ftpes_protocol_handler NULL
|
#define ftpes_protocol_handler NULL
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_LIBCURL) && (defined(CONFIG_LIBEVENT) || defined(CONFIG_LIBEV))
|
#if defined(CONFIG_LIBCURL)
|
||||||
struct connection;
|
struct connection;
|
||||||
|
|
||||||
extern protocol_handler_T http_curl_protocol_handler;
|
extern protocol_handler_T http_curl_protocol_handler;
|
||||||
|
@ -10,7 +10,7 @@ extern "C" {
|
|||||||
|
|
||||||
extern struct module sftp_protocol_module;
|
extern struct module sftp_protocol_module;
|
||||||
|
|
||||||
#if defined(CONFIG_LIBCURL) && (defined(CONFIG_LIBEVENT) || defined(CONFIG_LIBEV))
|
#if defined(CONFIG_LIBCURL)
|
||||||
extern protocol_handler_T sftp_protocol_handler;
|
extern protocol_handler_T sftp_protocol_handler;
|
||||||
#else
|
#else
|
||||||
#define sftp_protocol_handler NULL
|
#define sftp_protocol_handler NULL
|
||||||
|
@ -72,7 +72,7 @@ union option_info ftp_options[] = {
|
|||||||
"anon_passwd", OPT_ZERO, "some@host.domain",
|
"anon_passwd", OPT_ZERO, "some@host.domain",
|
||||||
N_("FTP anonymous password to be sent.")),
|
N_("FTP anonymous password to be sent.")),
|
||||||
|
|
||||||
#if defined(CONFIG_LIBCURL) && (defined(CONFIG_LIBEVENT) || defined(CONFIG_LIBEV))
|
#if defined(CONFIG_LIBCURL)
|
||||||
INIT_OPT_BOOL("protocol.ftp", N_("Use libcurl"),
|
INIT_OPT_BOOL("protocol.ftp", N_("Use libcurl"),
|
||||||
"use_curl", OPT_ZERO, 0,
|
"use_curl", OPT_ZERO, 0,
|
||||||
N_("Use libcurl implementation of ftp.")),
|
N_("Use libcurl implementation of ftp.")),
|
||||||
@ -289,7 +289,7 @@ ok:
|
|||||||
void
|
void
|
||||||
ftp_protocol_handler(struct connection *conn)
|
ftp_protocol_handler(struct connection *conn)
|
||||||
{
|
{
|
||||||
#if defined(CONFIG_LIBCURL) && (defined(CONFIG_LIBEVENT) || defined(CONFIG_LIBEV))
|
#if defined(CONFIG_LIBCURL)
|
||||||
if (get_opt_bool("protocol.ftp.use_curl", NULL)) {
|
if (get_opt_bool("protocol.ftp.use_curl", NULL)) {
|
||||||
ftpes_protocol_handler(conn);
|
ftpes_protocol_handler(conn);
|
||||||
return;
|
return;
|
||||||
|
@ -197,7 +197,7 @@ static union option_info http_options[] = {
|
|||||||
"--- the server only returns the client's request back to "
|
"--- the server only returns the client's request back to "
|
||||||
"the client verbatim. Note that this type of request may "
|
"the client verbatim. Note that this type of request may "
|
||||||
"not be enabled on all servers.")),
|
"not be enabled on all servers.")),
|
||||||
#if defined(CONFIG_LIBCURL) && (defined(CONFIG_LIBEVENT) || defined(CONFIG_LIBEV))
|
#if defined(CONFIG_LIBCURL)
|
||||||
INIT_OPT_BOOL("protocol.http", N_("Use libcurl"),
|
INIT_OPT_BOOL("protocol.http", N_("Use libcurl"),
|
||||||
"use_curl", OPT_ZERO, 0,
|
"use_curl", OPT_ZERO, 0,
|
||||||
N_("Use libcurl implementation of http(s).")),
|
N_("Use libcurl implementation of http(s).")),
|
||||||
@ -533,7 +533,7 @@ static void http_send_header(struct socket *);
|
|||||||
void
|
void
|
||||||
http_protocol_handler(struct connection *conn)
|
http_protocol_handler(struct connection *conn)
|
||||||
{
|
{
|
||||||
#if defined(CONFIG_LIBCURL) && (defined(CONFIG_LIBEVENT) || defined(CONFIG_LIBEV))
|
#if defined(CONFIG_LIBCURL)
|
||||||
if (get_opt_bool("protocol.http.use_curl", NULL)) {
|
if (get_opt_bool("protocol.http.use_curl", NULL)) {
|
||||||
http_curl_protocol_handler(conn);
|
http_curl_protocol_handler(conn);
|
||||||
return;
|
return;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
if conf_data.get('CONFIG_BITTORRENT')
|
if conf_data.get('CONFIG_BITTORRENT')
|
||||||
subdir('bittorrent')
|
subdir('bittorrent')
|
||||||
endif
|
endif
|
||||||
if conf_data.get('CONFIG_LIBCURL') and (conf_data.get('CONFIG_LIBEVENT') or conf_data.get('CONFIG_LIBEV'))
|
if conf_data.get('CONFIG_LIBCURL')
|
||||||
subdir('curl')
|
subdir('curl')
|
||||||
endif
|
endif
|
||||||
if conf_data.get('CONFIG_FINGER')
|
if conf_data.get('CONFIG_FINGER')
|
||||||
|
@ -318,7 +318,7 @@ static struct module *protocol_submodules[] = {
|
|||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_FTP
|
#ifdef CONFIG_FTP
|
||||||
&ftp_protocol_module,
|
&ftp_protocol_module,
|
||||||
#if defined(CONFIG_LIBCURL) && (defined(CONFIG_LIBEVENT) || defined(CONFIG_LIBEV))
|
#if defined(CONFIG_LIBCURL)
|
||||||
&ftpes_protocol_module,
|
&ftpes_protocol_module,
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
@ -332,7 +332,7 @@ static struct module *protocol_submodules[] = {
|
|||||||
#ifdef CONFIG_NNTP
|
#ifdef CONFIG_NNTP
|
||||||
&nntp_protocol_module,
|
&nntp_protocol_module,
|
||||||
#endif
|
#endif
|
||||||
#if defined(CONFIG_LIBCURL) && (defined(CONFIG_LIBEVENT) || defined(CONFIG_LIBEV))
|
#if defined(CONFIG_LIBCURL)
|
||||||
&sftp_protocol_module,
|
&sftp_protocol_module,
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_SMB
|
#ifdef CONFIG_SMB
|
||||||
|
Loading…
x
Reference in New Issue
Block a user