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