comparison src/curl/curl.c @ 764:5810f14fc8e6 trunk

[svn] - revert r1624 due to the fact that it breaks
author nenolod
date Thu, 01 Mar 2007 04:33:43 -0800
parents 58dcfb61cf76
children b02927277ccb
comparison
equal deleted inserted replaced
763:58dcfb61cf76 764:5810f14fc8e6
30 30
31 #define BUFFER_SIZE 256 * 1024 31 #define BUFFER_SIZE 256 * 1024
32 #define REVERSE_SEEK_SIZE 2048 32 #define REVERSE_SEEK_SIZE 2048
33 33
34 #define DEBUG_CONNECTION 0 34 #define DEBUG_CONNECTION 0
35 #define DEBUG_OPEN_CLOSE 0 35 #define DEBUG_OPEN_CLOSE 1
36 #define DEBUG_SEEK 0 36 #define DEBUG_SEEK 0
37 #define DEBUG_READ 0 37 #define DEBUG_READ 0
38 #define DEBUG_HEADERS 0 38 #define DEBUG_HEADERS 0
39 #define DEBUG_ICY 0 39 #define DEBUG_ICY 0
40 #define DEBUG_ICY_WRAP 0 40 #define DEBUG_ICY_WRAP 0
59 gchar *buffer; 59 gchar *buffer;
60 60
61 gsize rd_index; 61 gsize rd_index;
62 gsize wr_index; 62 gsize wr_index;
63 63
64 gsize hdrs_start;
65 gsize hdr_index; 64 gsize hdr_index;
66 65
67 GSList *stream_stack; // stack for stream functions (getc, ungetc) 66 GSList *stream_stack; // stack for stream functions (getc, ungetc)
68 67
69 gboolean header; // true if we haven't finished the header yet 68 gboolean header; // true if we haven't finished the header yet
398 { 397 {
399 size_t leftover; 398 size_t leftover;
400 // Empty header means the end of the headers 399 // Empty header means the end of the headers
401 handle->header = 0; 400 handle->header = 0;
402 handle->hdr_index = (i + 2) % handle->buffer_length; 401 handle->hdr_index = (i + 2) % handle->buffer_length;
403 // There's some after the header; we have to put 402 // We read from the start of the data in the request
404 // it in the buffer where we started the headers 403 handle->rd_index = handle->hdr_index;
405 // and account for it in wr_abs. 404 // We've already written the amount that's after
406 leftover = (handle->wr_index - handle->hdr_index + 405 // the header.
407 handle->buffer_length) % 406 leftover = (handle->wr_index - handle->hdr_index + handle->buffer_length) % handle->buffer_length;
408 handle->buffer_length;
409 handle->wr_abs += leftover; 407 handle->wr_abs += leftover;
410 if (handle->download) 408 if (handle->download)
411 { 409 {
412 // the data which has to go into the 410 // the data which has to go into the
413 // beginning of the file must be at the end 411 // beginning of the file must be at the end
414 // of the input that we've dealt with. 412 // of the input that we've dealt with.
415 vfs_fwrite(ptr + ret - leftover, leftover, 1, 413 vfs_fwrite(ptr + ret - leftover, leftover, 1,
416 handle->download); 414 handle->download);
417 } 415 }
418 handle->wr_index = handle->hdrs_start;
419 if (handle->wr_index + leftover > handle->buffer_length)
420 {
421 g_print("Wrapped rewrite\n");
422 memcpy(handle->buffer + handle->wr_index, ptr + ret,
423 handle->buffer_length - handle->wr_index);
424 memcpy(handle->buffer, ptr + ret +
425 handle->buffer_length - handle->wr_index,
426 leftover - handle->buffer_length +
427 handle->wr_index);
428 }
429 else
430 {
431 memcpy(handle->buffer + handle->wr_index, ptr + ret,
432 leftover);
433 }
434 handle->wr_index = (handle->wr_index + leftover) %
435 handle->buffer_length;
436 handle->icy_left = handle->icy_interval; 416 handle->icy_left = handle->icy_interval;
437 if (handle->icy_interval) 417 if (handle->icy_interval)
438 { 418 {
439 handle->icy_left -= 419 handle->icy_left -=
440 (handle->wr_index - handle->hdr_index + handle->buffer_length) % handle->buffer_length; 420 (handle->wr_index - handle->hdr_index + handle->buffer_length) % handle->buffer_length;
456 static gpointer 436 static gpointer
457 curl_manage_request(gpointer arg) 437 curl_manage_request(gpointer arg)
458 { 438 {
459 CurlHandle *handle = arg; 439 CurlHandle *handle = arg;
460 CURLcode result; 440 CURLcode result;
461 do 441 if (DEBUG_CONNECTION)
442 g_print("Connect %p\n", handle);
443
444 if (handle->no_data)
445 curl_easy_setopt(handle->curl, CURLOPT_NOBODY, 1);
446 else
462 { 447 {
463 if (DEBUG_CONNECTION) 448 if (DEBUG_CONNECTION)
464 g_print("Connect %p\n", handle); 449 g_print("Start from %d\n", handle->wr_abs);
465 450 curl_easy_setopt(handle->curl, CURLOPT_RESUME_FROM, handle->wr_abs);
466 if (handle->no_data) 451
467 curl_easy_setopt(handle->curl, CURLOPT_NOBODY, 1); 452 curl_easy_setopt(handle->curl, CURLOPT_NOBODY, 0);
468 else 453 curl_easy_setopt(handle->curl, CURLOPT_HTTPGET, 1);
469 { 454 }
470 if (DEBUG_CONNECTION) 455
471 g_print("Start from %d\n", handle->wr_abs); 456 handle->header = 1;
472 curl_easy_setopt(handle->curl, CURLOPT_RESUME_FROM, handle->wr_abs); 457 handle->hdr_index = 0;
473 458 handle->icy_interval = 0;
474 curl_easy_setopt(handle->curl, CURLOPT_NOBODY, 0); 459
475 curl_easy_setopt(handle->curl, CURLOPT_HTTPGET, 1); 460 result = curl_easy_perform(handle->curl);
476 } 461 if (result == CURLE_OK)
477 462 update_length(handle);
478 handle->header = 1; 463 // We expect to get CURLE_WRITE_ERROR if we cancel.
479 handle->hdr_index = handle->wr_index; 464 // We get CURLE_GOT_NOTHING if we send a HEAD request to a shoutcast server.
480 handle->hdrs_start = handle->wr_index; 465 // We get CURLE_HTTP_RANGE_ERROR if we try to use range with shoutcast.
481 handle->icy_interval = 0; 466 if (result != CURLE_OK && result != CURLE_WRITE_ERROR &&
482 467 result != CURLE_GOT_NOTHING && result != CURLE_HTTP_RANGE_ERROR &&
483 if (DEBUG_CONNECTION) 468 result != CURLE_PARTIAL_FILE)
484 g_print("About to perform %p\n", handle); 469 {
485 result = curl_easy_perform(handle->curl); 470 g_print("Got curl error %d\n", result);
486 if (result == CURLE_OK) 471 handle->failed = 1;
487 { 472 }
488 update_length(handle); 473 if (DEBUG_CONNECTION)
489 //g_print("Length: %d\n", handle->length); 474 g_print("Done %p%s", handle, handle->cancel ? " (aborted)\n" : "\n");
490 }
491 // We expect to get CURLE_WRITE_ERROR if we cancel.
492 // We get CURLE_GOT_NOTHING if we send a HEAD request to a shoutcast server.
493 // We get CURLE_HTTP_RANGE_ERROR if we try to use range with shoutcast.
494 // Why do we get CURLE_PARTIAL_FILE?
495 if (result != CURLE_OK && result != CURLE_WRITE_ERROR &&
496 result != CURLE_GOT_NOTHING && result != CURLE_HTTP_RANGE_ERROR &&
497 result != CURLE_PARTIAL_FILE)
498 {
499 g_print("Got curl error %d\n", result);
500 handle->failed = 1;
501 }
502 if (DEBUG_CONNECTION)
503 g_print("Got curl error %d\n", result);
504 if (result == CURLE_PARTIAL_FILE)
505 {
506 if (DEBUG_CONNECTION)
507 g_print("Lost connection %p; restarting\n", handle);
508 continue;
509 }
510 if (DEBUG_CONNECTION)
511 g_print("Done %p%s", handle, handle->cancel ? " (aborted)\n" : "\n");
512 break;
513 }
514 while (1);
515 handle->cancel = 1; 475 handle->cancel = 1;
516 return NULL; 476 return NULL;
517 } 477 }
518 478
519 static void curl_req_xfer(CurlHandle *handle) 479 static void curl_req_xfer(CurlHandle *handle)
524 return; 484 return;
525 } 485 }
526 if (!handle->thread) 486 if (!handle->thread)
527 { 487 {
528 handle->cancel = 0; 488 handle->cancel = 0;
529 handle->rd_index = 0; //BUFFER_SIZE - 100; 489 handle->wr_index = 0;
530 handle->wr_index = handle->rd_index; 490 handle->rd_index = 0;
531 handle->wr_abs = handle->rd_abs; 491 handle->wr_abs = handle->rd_abs;
532 if (DEBUG_CONNECTION) 492 if (DEBUG_CONNECTION)
533 g_print("Starting connection %p at %d\n", handle, handle->wr_abs); 493 g_print("Starting connection %p at %d\n", handle, handle->wr_abs);
534 handle->thread = g_thread_create(curl_manage_request, handle, 494 handle->thread = g_thread_create(curl_manage_request, handle,
535 TRUE, NULL); 495 TRUE, NULL);
865 posn = handle->rd_abs; 825 posn = handle->rd_abs;
866 826
867 if (whence == SEEK_SET) 827 if (whence == SEEK_SET)
868 handle->rd_abs = offset; 828 handle->rd_abs = offset;
869 else if (whence == SEEK_END) 829 else if (whence == SEEK_END)
870 { 830 handle->rd_abs = handle->length + offset;
871 if (-offset > handle->length)
872 handle->rd_abs = 0;
873 else
874 handle->rd_abs = handle->length + offset;
875 }
876 else 831 else
877 { 832 handle->rd_abs = handle->rd_abs + offset;
878 if (-offset > handle->rd_abs)
879 handle->rd_abs = 0;
880 else
881 handle->rd_abs = handle->rd_abs + offset;
882 }
883
884 if (handle->rd_abs > handle->length)
885 {
886 g_print("Seek before start of file: %d %d = %d\n", posn, offset,
887 handle->rd_abs);
888 }
889 833
890 // XXXX 834 // XXXX
891 // There's a race here between finding available space and 835 // There's a race here between finding available space and
892 // allocating it and the check below. 836 // allocating it and the check below.
893 837