block/curl: Remember all sockets
For some connection types (like FTP, generally), more than one socket may be used (in FTP's case: control vs. data stream). As of commit 838ef602498b8d1985a231a06f5e328e2946a81d ("curl: Eliminate unnecessary use of curl_multi_socket_all"), we have to remember all of the sockets used by libcurl, but in fact we only did that for a single one. Since one libcurl connection may use multiple sockets, however, we have to remember them all. Cc: qemu-stable@nongnu.org Signed-off-by: Max Reitz <mreitz@redhat.com> Message-id: 20161025025431.24714-4-mreitz@redhat.com Signed-off-by: Jeff Cody <jcody@redhat.com>
This commit is contained in:
parent
4e7676571b
commit
ff5ca1664a
47
block/curl.c
47
block/curl.c
@ -103,12 +103,17 @@ typedef struct CURLAIOCB {
|
|||||||
size_t end;
|
size_t end;
|
||||||
} CURLAIOCB;
|
} CURLAIOCB;
|
||||||
|
|
||||||
|
typedef struct CURLSocket {
|
||||||
|
int fd;
|
||||||
|
QLIST_ENTRY(CURLSocket) next;
|
||||||
|
} CURLSocket;
|
||||||
|
|
||||||
typedef struct CURLState
|
typedef struct CURLState
|
||||||
{
|
{
|
||||||
struct BDRVCURLState *s;
|
struct BDRVCURLState *s;
|
||||||
CURLAIOCB *acb[CURL_NUM_ACB];
|
CURLAIOCB *acb[CURL_NUM_ACB];
|
||||||
CURL *curl;
|
CURL *curl;
|
||||||
curl_socket_t sock_fd;
|
QLIST_HEAD(, CURLSocket) sockets;
|
||||||
char *orig_buf;
|
char *orig_buf;
|
||||||
size_t buf_start;
|
size_t buf_start;
|
||||||
size_t buf_off;
|
size_t buf_off;
|
||||||
@ -162,10 +167,27 @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action,
|
|||||||
{
|
{
|
||||||
BDRVCURLState *s;
|
BDRVCURLState *s;
|
||||||
CURLState *state = NULL;
|
CURLState *state = NULL;
|
||||||
|
CURLSocket *socket;
|
||||||
|
|
||||||
curl_easy_getinfo(curl, CURLINFO_PRIVATE, (char **)&state);
|
curl_easy_getinfo(curl, CURLINFO_PRIVATE, (char **)&state);
|
||||||
state->sock_fd = fd;
|
|
||||||
s = state->s;
|
s = state->s;
|
||||||
|
|
||||||
|
QLIST_FOREACH(socket, &state->sockets, next) {
|
||||||
|
if (socket->fd == fd) {
|
||||||
|
if (action == CURL_POLL_REMOVE) {
|
||||||
|
QLIST_REMOVE(socket, next);
|
||||||
|
g_free(socket);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!socket) {
|
||||||
|
socket = g_new0(CURLSocket, 1);
|
||||||
|
socket->fd = fd;
|
||||||
|
QLIST_INSERT_HEAD(&state->sockets, socket, next);
|
||||||
|
}
|
||||||
|
socket = NULL;
|
||||||
|
|
||||||
DPRINTF("CURL (AIO): Sock action %d on fd %d\n", action, (int)fd);
|
DPRINTF("CURL (AIO): Sock action %d on fd %d\n", action, (int)fd);
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case CURL_POLL_IN:
|
case CURL_POLL_IN:
|
||||||
@ -353,6 +375,7 @@ static void curl_multi_check_completion(BDRVCURLState *s)
|
|||||||
static void curl_multi_do(void *arg)
|
static void curl_multi_do(void *arg)
|
||||||
{
|
{
|
||||||
CURLState *s = (CURLState *)arg;
|
CURLState *s = (CURLState *)arg;
|
||||||
|
CURLSocket *socket, *next_socket;
|
||||||
int running;
|
int running;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -360,10 +383,13 @@ static void curl_multi_do(void *arg)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
/* Need to use _SAFE because curl_multi_socket_action() may trigger
|
||||||
r = curl_multi_socket_action(s->s->multi, s->sock_fd, 0, &running);
|
* curl_sock_cb() which might modify this list */
|
||||||
} while(r == CURLM_CALL_MULTI_PERFORM);
|
QLIST_FOREACH_SAFE(socket, &s->sockets, next, next_socket) {
|
||||||
|
do {
|
||||||
|
r = curl_multi_socket_action(s->s->multi, socket->fd, 0, &running);
|
||||||
|
} while (r == CURLM_CALL_MULTI_PERFORM);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void curl_multi_read(void *arg)
|
static void curl_multi_read(void *arg)
|
||||||
@ -467,6 +493,7 @@ static CURLState *curl_init_state(BlockDriverState *bs, BDRVCURLState *s)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QLIST_INIT(&state->sockets);
|
||||||
state->s = s;
|
state->s = s;
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
@ -476,6 +503,14 @@ static void curl_clean_state(CURLState *s)
|
|||||||
{
|
{
|
||||||
if (s->s->multi)
|
if (s->s->multi)
|
||||||
curl_multi_remove_handle(s->s->multi, s->curl);
|
curl_multi_remove_handle(s->s->multi, s->curl);
|
||||||
|
|
||||||
|
while (!QLIST_EMPTY(&s->sockets)) {
|
||||||
|
CURLSocket *socket = QLIST_FIRST(&s->sockets);
|
||||||
|
|
||||||
|
QLIST_REMOVE(socket, next);
|
||||||
|
g_free(socket);
|
||||||
|
}
|
||||||
|
|
||||||
s->in_use = 0;
|
s->in_use = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user