blob: 6f32183cb35af7dfe7ca74e3974ba5150268c079 [file] [log] [blame]
rspangler@google.com49fdf182009-10-10 00:57:34 +00001// Copyright (c) 2009 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
adlr@google.comc98a7ed2009-12-04 18:54:03 +00005#ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_LIBCURL_HTTP_FETCHER_H__
6#define CHROMEOS_PLATFORM_UPDATE_ENGINE_LIBCURL_HTTP_FETCHER_H__
rspangler@google.com49fdf182009-10-10 00:57:34 +00007
8#include <map>
9#include <string>
10#include <curl/curl.h>
11#include <glib.h>
12#include "base/basictypes.h"
adlr@google.comc98a7ed2009-12-04 18:54:03 +000013#include "chromeos/obsolete_logging.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000014#include "update_engine/http_fetcher.h"
15
16// This is a concrete implementation of HttpFetcher that uses libcurl to do the
17// http work.
18
19namespace chromeos_update_engine {
20
21class LibcurlHttpFetcher : public HttpFetcher {
22 public:
23 LibcurlHttpFetcher()
24 : curl_multi_handle_(NULL), curl_handle_(NULL),
25 timeout_source_(NULL), transfer_in_progress_(false),
26 idle_ms_(1000) {}
27
28 // Cleans up all internal state. Does not notify delegate
29 ~LibcurlHttpFetcher();
30
31 // Begins the transfer if it hasn't already begun.
32 virtual void BeginTransfer(const std::string& url);
33
34 // If the transfer is in progress, aborts the transfer early.
35 // The transfer cannot be resumed.
36 virtual void TerminateTransfer();
37
38 // Suspend the transfer by calling curl_easy_pause(CURLPAUSE_ALL).
39 virtual void Pause();
40
41 // Resume the transfer by calling curl_easy_pause(CURLPAUSE_CONT).
42 virtual void Unpause();
43
44 // Libcurl sometimes asks to be called back after some time while
45 // leaving that time unspecified. In that case, we pick a reasonable
46 // default of one second, but it can be overridden here. This is
47 // primarily useful for testing.
48 // From http://curl.haxx.se/libcurl/c/curl_multi_timeout.html:
49 // if libcurl returns a -1 timeout here, it just means that libcurl
50 // currently has no stored timeout value. You must not wait too long
51 // (more than a few seconds perhaps) before you call
52 // curl_multi_perform() again.
53 void set_idle_ms(long ms) {
54 idle_ms_ = ms;
55 }
56 private:
adlr@google.comc98a7ed2009-12-04 18:54:03 +000057 // Resumes a transfer where it left off. This will use the
58 // HTTP Range: header to make a new connection from where the last
59 // left off.
60 virtual void ResumeTransfer(const std::string& url);
rspangler@google.com49fdf182009-10-10 00:57:34 +000061
62 // These two methods are for glib main loop callbacks. They are called
63 // when either a file descriptor is ready for work or when a timer
64 // has fired. The static versions are shims for libcurl which has a C API.
65 bool FDCallback(GIOChannel *source, GIOCondition condition);
66 static gboolean StaticFDCallback(GIOChannel *source,
67 GIOCondition condition,
68 gpointer data) {
69 return reinterpret_cast<LibcurlHttpFetcher*>(data)->FDCallback(source,
70 condition);
71 }
72 bool TimeoutCallback();
73 static gboolean StaticTimeoutCallback(gpointer data) {
74 return reinterpret_cast<LibcurlHttpFetcher*>(data)->TimeoutCallback();
75 }
76
77 // Calls into curl_multi_perform to let libcurl do its work. Returns after
78 // curl_multi_perform is finished, which may actually be after more than
79 // one call to curl_multi_perform. This method will set up the glib run
80 // loop with sources for future work that libcurl will do.
81 // This method will not block.
82 void CurlPerformOnce();
83
84 // Sets up glib main loop sources as needed by libcurl. This is generally
85 // the file descriptor of the socket and a timer in case nothing happens
86 // on the fds.
87 void SetupMainloopSources();
88
89 // Callback called by libcurl when new data has arrived on the transfer
90 size_t LibcurlWrite(void *ptr, size_t size, size_t nmemb);
91 static size_t StaticLibcurlWrite(void *ptr, size_t size,
92 size_t nmemb, void *stream) {
93 return reinterpret_cast<LibcurlHttpFetcher*>(stream)->
94 LibcurlWrite(ptr, size, nmemb);
95 }
96
97 // Cleans up the following if they are non-null:
98 // curl(m) handles, io_channels_, timeout_source_.
99 void CleanUp();
100
101 // Handles for the libcurl library
102 CURLM *curl_multi_handle_;
103 CURL *curl_handle_;
104
105 // a list of all file descriptors that we're waiting on from the
106 // glib main loop
107 typedef std::map<int, std::pair<GIOChannel*, guint> > IOChannels;
108 IOChannels io_channels_;
109
110 // if non-NULL, a timer we're waiting on. glib main loop will call us back
111 // when it fires.
112 GSource* timeout_source_;
113
114 bool transfer_in_progress_;
115
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000116 // The transfer size. -1 if not known.
117 off_t transfer_size_;
118
119 // How many bytes have been downloaded and sent to the delegate.
120 off_t bytes_downloaded_;
121
122 // If we resumed an earlier transfer, data offset that we used for the
123 // new connection. 0 otherwise.
124 off_t resume_offset_;
125
rspangler@google.com49fdf182009-10-10 00:57:34 +0000126 long idle_ms_;
127 DISALLOW_COPY_AND_ASSIGN(LibcurlHttpFetcher);
128};
129
130} // namespace chromeos_update_engine
131
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000132#endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_LIBCURL_HTTP_FETCHER_H__