]> git.proxmox.com Git - mirror_qemu.git/blob - block/curl.c
include/qemu/osdep.h: Don't include qapi/error.h
[mirror_qemu.git] / block / curl.c
1 /*
2 * QEMU Block driver for CURL images
3 *
4 * Copyright (c) 2009 Alexander Graf <agraf@suse.de>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24 #include "qemu/osdep.h"
25 #include "qapi/error.h"
26 #include "qemu-common.h"
27 #include "qemu/error-report.h"
28 #include "block/block_int.h"
29 #include "qapi/qmp/qbool.h"
30 #include "qapi/qmp/qstring.h"
31 #include "crypto/secret.h"
32 #include <curl/curl.h>
33
34 // #define DEBUG_CURL
35 // #define DEBUG_VERBOSE
36
37 #ifdef DEBUG_CURL
38 #define DPRINTF(fmt, ...) do { printf(fmt, ## __VA_ARGS__); } while (0)
39 #else
40 #define DPRINTF(fmt, ...) do { } while (0)
41 #endif
42
43 #if LIBCURL_VERSION_NUM >= 0x071000
44 /* The multi interface timer callback was introduced in 7.16.0 */
45 #define NEED_CURL_TIMER_CALLBACK
46 #define HAVE_SOCKET_ACTION
47 #endif
48
49 #ifndef HAVE_SOCKET_ACTION
50 /* If curl_multi_socket_action isn't available, define it statically here in
51 * terms of curl_multi_socket. Note that ev_bitmask will be ignored, which is
52 * less efficient but still safe. */
53 static CURLMcode __curl_multi_socket_action(CURLM *multi_handle,
54 curl_socket_t sockfd,
55 int ev_bitmask,
56 int *running_handles)
57 {
58 return curl_multi_socket(multi_handle, sockfd, running_handles);
59 }
60 #define curl_multi_socket_action __curl_multi_socket_action
61 #endif
62
63 #define PROTOCOLS (CURLPROTO_HTTP | CURLPROTO_HTTPS | \
64 CURLPROTO_FTP | CURLPROTO_FTPS | \
65 CURLPROTO_TFTP)
66
67 #define CURL_NUM_STATES 8
68 #define CURL_NUM_ACB 8
69 #define SECTOR_SIZE 512
70 #define READ_AHEAD_DEFAULT (256 * 1024)
71 #define CURL_TIMEOUT_DEFAULT 5
72 #define CURL_TIMEOUT_MAX 10000
73
74 #define FIND_RET_NONE 0
75 #define FIND_RET_OK 1
76 #define FIND_RET_WAIT 2
77
78 #define CURL_BLOCK_OPT_URL "url"
79 #define CURL_BLOCK_OPT_READAHEAD "readahead"
80 #define CURL_BLOCK_OPT_SSLVERIFY "sslverify"
81 #define CURL_BLOCK_OPT_TIMEOUT "timeout"
82 #define CURL_BLOCK_OPT_COOKIE "cookie"
83 #define CURL_BLOCK_OPT_USERNAME "username"
84 #define CURL_BLOCK_OPT_PASSWORD_SECRET "password-secret"
85 #define CURL_BLOCK_OPT_PROXY_USERNAME "proxy-username"
86 #define CURL_BLOCK_OPT_PROXY_PASSWORD_SECRET "proxy-password-secret"
87
88 struct BDRVCURLState;
89
90 typedef struct CURLAIOCB {
91 BlockAIOCB common;
92 QEMUBH *bh;
93 QEMUIOVector *qiov;
94
95 int64_t sector_num;
96 int nb_sectors;
97
98 size_t start;
99 size_t end;
100 } CURLAIOCB;
101
102 typedef struct CURLState
103 {
104 struct BDRVCURLState *s;
105 CURLAIOCB *acb[CURL_NUM_ACB];
106 CURL *curl;
107 curl_socket_t sock_fd;
108 char *orig_buf;
109 size_t buf_start;
110 size_t buf_off;
111 size_t buf_len;
112 char range[128];
113 char errmsg[CURL_ERROR_SIZE];
114 char in_use;
115 } CURLState;
116
117 typedef struct BDRVCURLState {
118 CURLM *multi;
119 QEMUTimer timer;
120 size_t len;
121 CURLState states[CURL_NUM_STATES];
122 char *url;
123 size_t readahead_size;
124 bool sslverify;
125 uint64_t timeout;
126 char *cookie;
127 bool accept_range;
128 AioContext *aio_context;
129 char *username;
130 char *password;
131 char *proxyusername;
132 char *proxypassword;
133 } BDRVCURLState;
134
135 static void curl_clean_state(CURLState *s);
136 static void curl_multi_do(void *arg);
137 static void curl_multi_read(void *arg);
138
139 #ifdef NEED_CURL_TIMER_CALLBACK
140 static int curl_timer_cb(CURLM *multi, long timeout_ms, void *opaque)
141 {
142 BDRVCURLState *s = opaque;
143
144 DPRINTF("CURL: timer callback timeout_ms %ld\n", timeout_ms);
145 if (timeout_ms == -1) {
146 timer_del(&s->timer);
147 } else {
148 int64_t timeout_ns = (int64_t)timeout_ms * 1000 * 1000;
149 timer_mod(&s->timer,
150 qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + timeout_ns);
151 }
152 return 0;
153 }
154 #endif
155
156 static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action,
157 void *userp, void *sp)
158 {
159 BDRVCURLState *s;
160 CURLState *state = NULL;
161 curl_easy_getinfo(curl, CURLINFO_PRIVATE, (char **)&state);
162 state->sock_fd = fd;
163 s = state->s;
164
165 DPRINTF("CURL (AIO): Sock action %d on fd %d\n", action, fd);
166 switch (action) {
167 case CURL_POLL_IN:
168 aio_set_fd_handler(s->aio_context, fd, false,
169 curl_multi_read, NULL, state);
170 break;
171 case CURL_POLL_OUT:
172 aio_set_fd_handler(s->aio_context, fd, false,
173 NULL, curl_multi_do, state);
174 break;
175 case CURL_POLL_INOUT:
176 aio_set_fd_handler(s->aio_context, fd, false,
177 curl_multi_read, curl_multi_do, state);
178 break;
179 case CURL_POLL_REMOVE:
180 aio_set_fd_handler(s->aio_context, fd, false,
181 NULL, NULL, NULL);
182 break;
183 }
184
185 return 0;
186 }
187
188 static size_t curl_header_cb(void *ptr, size_t size, size_t nmemb, void *opaque)
189 {
190 BDRVCURLState *s = opaque;
191 size_t realsize = size * nmemb;
192 const char *accept_line = "Accept-Ranges: bytes";
193
194 if (realsize >= strlen(accept_line)
195 && strncmp((char *)ptr, accept_line, strlen(accept_line)) == 0) {
196 s->accept_range = true;
197 }
198
199 return realsize;
200 }
201
202 static size_t curl_read_cb(void *ptr, size_t size, size_t nmemb, void *opaque)
203 {
204 CURLState *s = ((CURLState*)opaque);
205 size_t realsize = size * nmemb;
206 int i;
207
208 DPRINTF("CURL: Just reading %zd bytes\n", realsize);
209
210 if (!s || !s->orig_buf)
211 return 0;
212
213 if (s->buf_off >= s->buf_len) {
214 /* buffer full, read nothing */
215 return 0;
216 }
217 realsize = MIN(realsize, s->buf_len - s->buf_off);
218 memcpy(s->orig_buf + s->buf_off, ptr, realsize);
219 s->buf_off += realsize;
220
221 for(i=0; i<CURL_NUM_ACB; i++) {
222 CURLAIOCB *acb = s->acb[i];
223
224 if (!acb)
225 continue;
226
227 if ((s->buf_off >= acb->end)) {
228 qemu_iovec_from_buf(acb->qiov, 0, s->orig_buf + acb->start,
229 acb->end - acb->start);
230 acb->common.cb(acb->common.opaque, 0);
231 qemu_aio_unref(acb);
232 s->acb[i] = NULL;
233 }
234 }
235
236 return realsize;
237 }
238
239 static int curl_find_buf(BDRVCURLState *s, size_t start, size_t len,
240 CURLAIOCB *acb)
241 {
242 int i;
243 size_t end = start + len;
244
245 for (i=0; i<CURL_NUM_STATES; i++) {
246 CURLState *state = &s->states[i];
247 size_t buf_end = (state->buf_start + state->buf_off);
248 size_t buf_fend = (state->buf_start + state->buf_len);
249
250 if (!state->orig_buf)
251 continue;
252 if (!state->buf_off)
253 continue;
254
255 // Does the existing buffer cover our section?
256 if ((start >= state->buf_start) &&
257 (start <= buf_end) &&
258 (end >= state->buf_start) &&
259 (end <= buf_end))
260 {
261 char *buf = state->orig_buf + (start - state->buf_start);
262
263 qemu_iovec_from_buf(acb->qiov, 0, buf, len);
264 acb->common.cb(acb->common.opaque, 0);
265
266 return FIND_RET_OK;
267 }
268
269 // Wait for unfinished chunks
270 if (state->in_use &&
271 (start >= state->buf_start) &&
272 (start <= buf_fend) &&
273 (end >= state->buf_start) &&
274 (end <= buf_fend))
275 {
276 int j;
277
278 acb->start = start - state->buf_start;
279 acb->end = acb->start + len;
280
281 for (j=0; j<CURL_NUM_ACB; j++) {
282 if (!state->acb[j]) {
283 state->acb[j] = acb;
284 return FIND_RET_WAIT;
285 }
286 }
287 }
288 }
289
290 return FIND_RET_NONE;
291 }
292
293 static void curl_multi_check_completion(BDRVCURLState *s)
294 {
295 int msgs_in_queue;
296
297 /* Try to find done transfers, so we can free the easy
298 * handle again. */
299 for (;;) {
300 CURLMsg *msg;
301 msg = curl_multi_info_read(s->multi, &msgs_in_queue);
302
303 /* Quit when there are no more completions */
304 if (!msg)
305 break;
306
307 if (msg->msg == CURLMSG_DONE) {
308 CURLState *state = NULL;
309 curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE,
310 (char **)&state);
311
312 /* ACBs for successful messages get completed in curl_read_cb */
313 if (msg->data.result != CURLE_OK) {
314 int i;
315 static int errcount = 100;
316
317 /* Don't lose the original error message from curl, since
318 * it contains extra data.
319 */
320 if (errcount > 0) {
321 error_report("curl: %s", state->errmsg);
322 if (--errcount == 0) {
323 error_report("curl: further errors suppressed");
324 }
325 }
326
327 for (i = 0; i < CURL_NUM_ACB; i++) {
328 CURLAIOCB *acb = state->acb[i];
329
330 if (acb == NULL) {
331 continue;
332 }
333
334 acb->common.cb(acb->common.opaque, -EPROTO);
335 qemu_aio_unref(acb);
336 state->acb[i] = NULL;
337 }
338 }
339
340 curl_clean_state(state);
341 break;
342 }
343 }
344 }
345
346 static void curl_multi_do(void *arg)
347 {
348 CURLState *s = (CURLState *)arg;
349 int running;
350 int r;
351
352 if (!s->s->multi) {
353 return;
354 }
355
356 do {
357 r = curl_multi_socket_action(s->s->multi, s->sock_fd, 0, &running);
358 } while(r == CURLM_CALL_MULTI_PERFORM);
359
360 }
361
362 static void curl_multi_read(void *arg)
363 {
364 CURLState *s = (CURLState *)arg;
365
366 curl_multi_do(arg);
367 curl_multi_check_completion(s->s);
368 }
369
370 static void curl_multi_timeout_do(void *arg)
371 {
372 #ifdef NEED_CURL_TIMER_CALLBACK
373 BDRVCURLState *s = (BDRVCURLState *)arg;
374 int running;
375
376 if (!s->multi) {
377 return;
378 }
379
380 curl_multi_socket_action(s->multi, CURL_SOCKET_TIMEOUT, 0, &running);
381
382 curl_multi_check_completion(s);
383 #else
384 abort();
385 #endif
386 }
387
388 static CURLState *curl_init_state(BlockDriverState *bs, BDRVCURLState *s)
389 {
390 CURLState *state = NULL;
391 int i, j;
392
393 do {
394 for (i=0; i<CURL_NUM_STATES; i++) {
395 for (j=0; j<CURL_NUM_ACB; j++)
396 if (s->states[i].acb[j])
397 continue;
398 if (s->states[i].in_use)
399 continue;
400
401 state = &s->states[i];
402 state->in_use = 1;
403 break;
404 }
405 if (!state) {
406 aio_poll(bdrv_get_aio_context(bs), true);
407 }
408 } while(!state);
409
410 if (!state->curl) {
411 state->curl = curl_easy_init();
412 if (!state->curl) {
413 return NULL;
414 }
415 curl_easy_setopt(state->curl, CURLOPT_URL, s->url);
416 curl_easy_setopt(state->curl, CURLOPT_SSL_VERIFYPEER,
417 (long) s->sslverify);
418 if (s->cookie) {
419 curl_easy_setopt(state->curl, CURLOPT_COOKIE, s->cookie);
420 }
421 curl_easy_setopt(state->curl, CURLOPT_TIMEOUT, (long)s->timeout);
422 curl_easy_setopt(state->curl, CURLOPT_WRITEFUNCTION,
423 (void *)curl_read_cb);
424 curl_easy_setopt(state->curl, CURLOPT_WRITEDATA, (void *)state);
425 curl_easy_setopt(state->curl, CURLOPT_PRIVATE, (void *)state);
426 curl_easy_setopt(state->curl, CURLOPT_AUTOREFERER, 1);
427 curl_easy_setopt(state->curl, CURLOPT_FOLLOWLOCATION, 1);
428 curl_easy_setopt(state->curl, CURLOPT_NOSIGNAL, 1);
429 curl_easy_setopt(state->curl, CURLOPT_ERRORBUFFER, state->errmsg);
430 curl_easy_setopt(state->curl, CURLOPT_FAILONERROR, 1);
431
432 if (s->username) {
433 curl_easy_setopt(state->curl, CURLOPT_USERNAME, s->username);
434 }
435 if (s->password) {
436 curl_easy_setopt(state->curl, CURLOPT_PASSWORD, s->password);
437 }
438 if (s->proxyusername) {
439 curl_easy_setopt(state->curl,
440 CURLOPT_PROXYUSERNAME, s->proxyusername);
441 }
442 if (s->proxypassword) {
443 curl_easy_setopt(state->curl,
444 CURLOPT_PROXYPASSWORD, s->proxypassword);
445 }
446
447 /* Restrict supported protocols to avoid security issues in the more
448 * obscure protocols. For example, do not allow POP3/SMTP/IMAP see
449 * CVE-2013-0249.
450 *
451 * Restricting protocols is only supported from 7.19.4 upwards.
452 */
453 #if LIBCURL_VERSION_NUM >= 0x071304
454 curl_easy_setopt(state->curl, CURLOPT_PROTOCOLS, PROTOCOLS);
455 curl_easy_setopt(state->curl, CURLOPT_REDIR_PROTOCOLS, PROTOCOLS);
456 #endif
457
458 #ifdef DEBUG_VERBOSE
459 curl_easy_setopt(state->curl, CURLOPT_VERBOSE, 1);
460 #endif
461 }
462
463 state->s = s;
464
465 return state;
466 }
467
468 static void curl_clean_state(CURLState *s)
469 {
470 if (s->s->multi)
471 curl_multi_remove_handle(s->s->multi, s->curl);
472 s->in_use = 0;
473 }
474
475 static void curl_parse_filename(const char *filename, QDict *options,
476 Error **errp)
477 {
478 qdict_put(options, CURL_BLOCK_OPT_URL, qstring_from_str(filename));
479 }
480
481 static void curl_detach_aio_context(BlockDriverState *bs)
482 {
483 BDRVCURLState *s = bs->opaque;
484 int i;
485
486 for (i = 0; i < CURL_NUM_STATES; i++) {
487 if (s->states[i].in_use) {
488 curl_clean_state(&s->states[i]);
489 }
490 if (s->states[i].curl) {
491 curl_easy_cleanup(s->states[i].curl);
492 s->states[i].curl = NULL;
493 }
494 g_free(s->states[i].orig_buf);
495 s->states[i].orig_buf = NULL;
496 }
497 if (s->multi) {
498 curl_multi_cleanup(s->multi);
499 s->multi = NULL;
500 }
501
502 timer_del(&s->timer);
503 }
504
505 static void curl_attach_aio_context(BlockDriverState *bs,
506 AioContext *new_context)
507 {
508 BDRVCURLState *s = bs->opaque;
509
510 aio_timer_init(new_context, &s->timer,
511 QEMU_CLOCK_REALTIME, SCALE_NS,
512 curl_multi_timeout_do, s);
513
514 assert(!s->multi);
515 s->multi = curl_multi_init();
516 s->aio_context = new_context;
517 curl_multi_setopt(s->multi, CURLMOPT_SOCKETFUNCTION, curl_sock_cb);
518 #ifdef NEED_CURL_TIMER_CALLBACK
519 curl_multi_setopt(s->multi, CURLMOPT_TIMERDATA, s);
520 curl_multi_setopt(s->multi, CURLMOPT_TIMERFUNCTION, curl_timer_cb);
521 #endif
522 }
523
524 static QemuOptsList runtime_opts = {
525 .name = "curl",
526 .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
527 .desc = {
528 {
529 .name = CURL_BLOCK_OPT_URL,
530 .type = QEMU_OPT_STRING,
531 .help = "URL to open",
532 },
533 {
534 .name = CURL_BLOCK_OPT_READAHEAD,
535 .type = QEMU_OPT_SIZE,
536 .help = "Readahead size",
537 },
538 {
539 .name = CURL_BLOCK_OPT_SSLVERIFY,
540 .type = QEMU_OPT_BOOL,
541 .help = "Verify SSL certificate"
542 },
543 {
544 .name = CURL_BLOCK_OPT_TIMEOUT,
545 .type = QEMU_OPT_NUMBER,
546 .help = "Curl timeout"
547 },
548 {
549 .name = CURL_BLOCK_OPT_COOKIE,
550 .type = QEMU_OPT_STRING,
551 .help = "Pass the cookie or list of cookies with each request"
552 },
553 {
554 .name = CURL_BLOCK_OPT_USERNAME,
555 .type = QEMU_OPT_STRING,
556 .help = "Username for HTTP auth"
557 },
558 {
559 .name = CURL_BLOCK_OPT_PASSWORD_SECRET,
560 .type = QEMU_OPT_STRING,
561 .help = "ID of secret used as password for HTTP auth",
562 },
563 {
564 .name = CURL_BLOCK_OPT_PROXY_USERNAME,
565 .type = QEMU_OPT_STRING,
566 .help = "Username for HTTP proxy auth"
567 },
568 {
569 .name = CURL_BLOCK_OPT_PROXY_PASSWORD_SECRET,
570 .type = QEMU_OPT_STRING,
571 .help = "ID of secret used as password for HTTP proxy auth",
572 },
573 { /* end of list */ }
574 },
575 };
576
577
578 static int curl_open(BlockDriverState *bs, QDict *options, int flags,
579 Error **errp)
580 {
581 BDRVCURLState *s = bs->opaque;
582 CURLState *state = NULL;
583 QemuOpts *opts;
584 Error *local_err = NULL;
585 const char *file;
586 const char *cookie;
587 double d;
588 const char *secretid;
589
590 static int inited = 0;
591
592 if (flags & BDRV_O_RDWR) {
593 error_setg(errp, "curl block device does not support writes");
594 return -EROFS;
595 }
596
597 opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
598 qemu_opts_absorb_qdict(opts, options, &local_err);
599 if (local_err) {
600 error_propagate(errp, local_err);
601 goto out_noclean;
602 }
603
604 s->readahead_size = qemu_opt_get_size(opts, CURL_BLOCK_OPT_READAHEAD,
605 READ_AHEAD_DEFAULT);
606 if ((s->readahead_size & 0x1ff) != 0) {
607 error_setg(errp, "HTTP_READAHEAD_SIZE %zd is not a multiple of 512",
608 s->readahead_size);
609 goto out_noclean;
610 }
611
612 s->timeout = qemu_opt_get_number(opts, CURL_BLOCK_OPT_TIMEOUT,
613 CURL_TIMEOUT_DEFAULT);
614 if (s->timeout > CURL_TIMEOUT_MAX) {
615 error_setg(errp, "timeout parameter is too large or negative");
616 goto out_noclean;
617 }
618
619 s->sslverify = qemu_opt_get_bool(opts, CURL_BLOCK_OPT_SSLVERIFY, true);
620
621 cookie = qemu_opt_get(opts, CURL_BLOCK_OPT_COOKIE);
622 s->cookie = g_strdup(cookie);
623
624 file = qemu_opt_get(opts, CURL_BLOCK_OPT_URL);
625 if (file == NULL) {
626 error_setg(errp, "curl block driver requires an 'url' option");
627 goto out_noclean;
628 }
629
630 s->username = g_strdup(qemu_opt_get(opts, CURL_BLOCK_OPT_USERNAME));
631 secretid = qemu_opt_get(opts, CURL_BLOCK_OPT_PASSWORD_SECRET);
632
633 if (secretid) {
634 s->password = qcrypto_secret_lookup_as_utf8(secretid, errp);
635 if (!s->password) {
636 goto out_noclean;
637 }
638 }
639
640 s->proxyusername = g_strdup(
641 qemu_opt_get(opts, CURL_BLOCK_OPT_PROXY_USERNAME));
642 secretid = qemu_opt_get(opts, CURL_BLOCK_OPT_PROXY_PASSWORD_SECRET);
643 if (secretid) {
644 s->proxypassword = qcrypto_secret_lookup_as_utf8(secretid, errp);
645 if (!s->proxypassword) {
646 goto out_noclean;
647 }
648 }
649
650 if (!inited) {
651 curl_global_init(CURL_GLOBAL_ALL);
652 inited = 1;
653 }
654
655 DPRINTF("CURL: Opening %s\n", file);
656 s->aio_context = bdrv_get_aio_context(bs);
657 s->url = g_strdup(file);
658 state = curl_init_state(bs, s);
659 if (!state)
660 goto out_noclean;
661
662 // Get file size
663
664 s->accept_range = false;
665 curl_easy_setopt(state->curl, CURLOPT_NOBODY, 1);
666 curl_easy_setopt(state->curl, CURLOPT_HEADERFUNCTION,
667 curl_header_cb);
668 curl_easy_setopt(state->curl, CURLOPT_HEADERDATA, s);
669 if (curl_easy_perform(state->curl))
670 goto out;
671 curl_easy_getinfo(state->curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &d);
672 if (d)
673 s->len = (size_t)d;
674 else if(!s->len)
675 goto out;
676 if ((!strncasecmp(s->url, "http://", strlen("http://"))
677 || !strncasecmp(s->url, "https://", strlen("https://")))
678 && !s->accept_range) {
679 pstrcpy(state->errmsg, CURL_ERROR_SIZE,
680 "Server does not support 'range' (byte ranges).");
681 goto out;
682 }
683 DPRINTF("CURL: Size = %zd\n", s->len);
684
685 curl_clean_state(state);
686 curl_easy_cleanup(state->curl);
687 state->curl = NULL;
688
689 curl_attach_aio_context(bs, bdrv_get_aio_context(bs));
690
691 qemu_opts_del(opts);
692 return 0;
693
694 out:
695 error_setg(errp, "CURL: Error opening file: %s", state->errmsg);
696 curl_easy_cleanup(state->curl);
697 state->curl = NULL;
698 out_noclean:
699 g_free(s->cookie);
700 g_free(s->url);
701 qemu_opts_del(opts);
702 return -EINVAL;
703 }
704
705 static const AIOCBInfo curl_aiocb_info = {
706 .aiocb_size = sizeof(CURLAIOCB),
707 };
708
709
710 static void curl_readv_bh_cb(void *p)
711 {
712 CURLState *state;
713 int running;
714
715 CURLAIOCB *acb = p;
716 BDRVCURLState *s = acb->common.bs->opaque;
717
718 qemu_bh_delete(acb->bh);
719 acb->bh = NULL;
720
721 size_t start = acb->sector_num * SECTOR_SIZE;
722 size_t end;
723
724 // In case we have the requested data already (e.g. read-ahead),
725 // we can just call the callback and be done.
726 switch (curl_find_buf(s, start, acb->nb_sectors * SECTOR_SIZE, acb)) {
727 case FIND_RET_OK:
728 qemu_aio_unref(acb);
729 // fall through
730 case FIND_RET_WAIT:
731 return;
732 default:
733 break;
734 }
735
736 // No cache found, so let's start a new request
737 state = curl_init_state(acb->common.bs, s);
738 if (!state) {
739 acb->common.cb(acb->common.opaque, -EIO);
740 qemu_aio_unref(acb);
741 return;
742 }
743
744 acb->start = 0;
745 acb->end = (acb->nb_sectors * SECTOR_SIZE);
746
747 state->buf_off = 0;
748 g_free(state->orig_buf);
749 state->buf_start = start;
750 state->buf_len = acb->end + s->readahead_size;
751 end = MIN(start + state->buf_len, s->len) - 1;
752 state->orig_buf = g_try_malloc(state->buf_len);
753 if (state->buf_len && state->orig_buf == NULL) {
754 curl_clean_state(state);
755 acb->common.cb(acb->common.opaque, -ENOMEM);
756 qemu_aio_unref(acb);
757 return;
758 }
759 state->acb[0] = acb;
760
761 snprintf(state->range, 127, "%zd-%zd", start, end);
762 DPRINTF("CURL (AIO): Reading %d at %zd (%s)\n",
763 (acb->nb_sectors * SECTOR_SIZE), start, state->range);
764 curl_easy_setopt(state->curl, CURLOPT_RANGE, state->range);
765
766 curl_multi_add_handle(s->multi, state->curl);
767
768 /* Tell curl it needs to kick things off */
769 curl_multi_socket_action(s->multi, CURL_SOCKET_TIMEOUT, 0, &running);
770 }
771
772 static BlockAIOCB *curl_aio_readv(BlockDriverState *bs,
773 int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
774 BlockCompletionFunc *cb, void *opaque)
775 {
776 CURLAIOCB *acb;
777
778 acb = qemu_aio_get(&curl_aiocb_info, bs, cb, opaque);
779
780 acb->qiov = qiov;
781 acb->sector_num = sector_num;
782 acb->nb_sectors = nb_sectors;
783
784 acb->bh = aio_bh_new(bdrv_get_aio_context(bs), curl_readv_bh_cb, acb);
785 qemu_bh_schedule(acb->bh);
786 return &acb->common;
787 }
788
789 static void curl_close(BlockDriverState *bs)
790 {
791 BDRVCURLState *s = bs->opaque;
792
793 DPRINTF("CURL: Close\n");
794 curl_detach_aio_context(bs);
795
796 g_free(s->cookie);
797 g_free(s->url);
798 }
799
800 static int64_t curl_getlength(BlockDriverState *bs)
801 {
802 BDRVCURLState *s = bs->opaque;
803 return s->len;
804 }
805
806 static BlockDriver bdrv_http = {
807 .format_name = "http",
808 .protocol_name = "http",
809
810 .instance_size = sizeof(BDRVCURLState),
811 .bdrv_parse_filename = curl_parse_filename,
812 .bdrv_file_open = curl_open,
813 .bdrv_close = curl_close,
814 .bdrv_getlength = curl_getlength,
815
816 .bdrv_aio_readv = curl_aio_readv,
817
818 .bdrv_detach_aio_context = curl_detach_aio_context,
819 .bdrv_attach_aio_context = curl_attach_aio_context,
820 };
821
822 static BlockDriver bdrv_https = {
823 .format_name = "https",
824 .protocol_name = "https",
825
826 .instance_size = sizeof(BDRVCURLState),
827 .bdrv_parse_filename = curl_parse_filename,
828 .bdrv_file_open = curl_open,
829 .bdrv_close = curl_close,
830 .bdrv_getlength = curl_getlength,
831
832 .bdrv_aio_readv = curl_aio_readv,
833
834 .bdrv_detach_aio_context = curl_detach_aio_context,
835 .bdrv_attach_aio_context = curl_attach_aio_context,
836 };
837
838 static BlockDriver bdrv_ftp = {
839 .format_name = "ftp",
840 .protocol_name = "ftp",
841
842 .instance_size = sizeof(BDRVCURLState),
843 .bdrv_parse_filename = curl_parse_filename,
844 .bdrv_file_open = curl_open,
845 .bdrv_close = curl_close,
846 .bdrv_getlength = curl_getlength,
847
848 .bdrv_aio_readv = curl_aio_readv,
849
850 .bdrv_detach_aio_context = curl_detach_aio_context,
851 .bdrv_attach_aio_context = curl_attach_aio_context,
852 };
853
854 static BlockDriver bdrv_ftps = {
855 .format_name = "ftps",
856 .protocol_name = "ftps",
857
858 .instance_size = sizeof(BDRVCURLState),
859 .bdrv_parse_filename = curl_parse_filename,
860 .bdrv_file_open = curl_open,
861 .bdrv_close = curl_close,
862 .bdrv_getlength = curl_getlength,
863
864 .bdrv_aio_readv = curl_aio_readv,
865
866 .bdrv_detach_aio_context = curl_detach_aio_context,
867 .bdrv_attach_aio_context = curl_attach_aio_context,
868 };
869
870 static BlockDriver bdrv_tftp = {
871 .format_name = "tftp",
872 .protocol_name = "tftp",
873
874 .instance_size = sizeof(BDRVCURLState),
875 .bdrv_parse_filename = curl_parse_filename,
876 .bdrv_file_open = curl_open,
877 .bdrv_close = curl_close,
878 .bdrv_getlength = curl_getlength,
879
880 .bdrv_aio_readv = curl_aio_readv,
881
882 .bdrv_detach_aio_context = curl_detach_aio_context,
883 .bdrv_attach_aio_context = curl_attach_aio_context,
884 };
885
886 static void curl_block_init(void)
887 {
888 bdrv_register(&bdrv_http);
889 bdrv_register(&bdrv_https);
890 bdrv_register(&bdrv_ftp);
891 bdrv_register(&bdrv_ftps);
892 bdrv_register(&bdrv_tftp);
893 }
894
895 block_init(curl_block_init);