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