http.hon commit general improvements (43abf13)
   1#ifndef HTTP_H
   2#define HTTP_H
   3
   4#include "cache.h"
   5
   6#include <curl/curl.h>
   7#include <curl/easy.h>
   8
   9#include "strbuf.h"
  10#include "remote.h"
  11#include "url.h"
  12
  13/*
  14 * We detect based on the cURL version if multi-transfer is
  15 * usable in this implementation and define this symbol accordingly.
  16 * This shouldn't be set by the Makefile or by the user (e.g. via CFLAGS).
  17 */
  18#undef USE_CURL_MULTI
  19
  20#if LIBCURL_VERSION_NUM >= 0x071000
  21#define USE_CURL_MULTI
  22#define DEFAULT_MAX_REQUESTS 5
  23#endif
  24
  25#if LIBCURL_VERSION_NUM < 0x070704
  26#define curl_global_cleanup() do { /* nothing */ } while (0)
  27#endif
  28
  29#if LIBCURL_VERSION_NUM < 0x070800
  30#define curl_global_init(a) do { /* nothing */ } while (0)
  31#elif LIBCURL_VERSION_NUM >= 0x070c00
  32#define curl_global_init(a) curl_global_init_mem(a, xmalloc, free, \
  33                                                xrealloc, xstrdup, xcalloc)
  34#endif
  35
  36#if (LIBCURL_VERSION_NUM < 0x070c04) || (LIBCURL_VERSION_NUM == 0x071000)
  37#define NO_CURL_EASY_DUPHANDLE
  38#endif
  39
  40#if LIBCURL_VERSION_NUM < 0x070a03
  41#define CURLE_HTTP_RETURNED_ERROR CURLE_HTTP_NOT_FOUND
  42#endif
  43
  44#if LIBCURL_VERSION_NUM < 0x070c03
  45#define NO_CURL_IOCTL
  46#endif
  47
  48/*
  49 * CURLOPT_USE_SSL was known as CURLOPT_FTP_SSL up to 7.16.4,
  50 * and the constants were known as CURLFTPSSL_*
  51*/
  52#if !defined(CURLOPT_USE_SSL) && defined(CURLOPT_FTP_SSL)
  53#define CURLOPT_USE_SSL CURLOPT_FTP_SSL
  54#define CURLUSESSL_TRY CURLFTPSSL_TRY
  55#endif
  56
  57struct slot_results {
  58        CURLcode curl_result;
  59        long http_code;
  60        long auth_avail;
  61        long http_connectcode;
  62};
  63
  64struct active_request_slot {
  65        CURL *curl;
  66        int in_use;
  67        CURLcode curl_result;
  68        long http_code;
  69        int *finished;
  70        struct slot_results *results;
  71        void *callback_data;
  72        void (*callback_func)(void *data);
  73        struct active_request_slot *next;
  74};
  75
  76struct buffer {
  77        struct strbuf buf;
  78        size_t posn;
  79};
  80
  81/* Curl request read/write callbacks */
  82size_t fread_buffer(char *ptr, size_t eltsize, size_t nmemb, void *strbuf);
  83size_t fwrite_buffer(char *ptr, size_t eltsize, size_t nmemb, void *strbuf);
  84size_t fwrite_null(char *ptr, size_t eltsize, size_t nmemb, void *strbuf);
  85#ifndef NO_CURL_IOCTL
  86curlioerr ioctl_buffer(CURL *handle, int cmd, void *clientp);
  87#endif
  88
  89/* Slot lifecycle functions */
  90struct active_request_slot *get_active_slot(void);
  91int start_active_slot(struct active_request_slot *slot);
  92void run_active_slot(struct active_request_slot *slot);
  93void finish_all_active_slots(void);
  94
  95/*
  96 * This will run one slot to completion in a blocking manner, similar to how
  97 * curl_easy_perform would work (but we don't want to use that, because
  98 * we do not want to intermingle calls to curl_multi and curl_easy).
  99 *
 100 */
 101int run_one_slot(struct active_request_slot *slot,
 102                 struct slot_results *results);
 103
 104#ifdef USE_CURL_MULTI
 105void fill_active_slots(void);
 106void add_fill_function(void *data, int (*fill)(void *));
 107void step_active_slots(void);
 108#endif
 109
 110void http_init(struct remote *remote, const char *url,
 111               int proactive_auth);
 112void http_cleanup(void);
 113struct curl_slist *http_copy_default_headers(void);
 114
 115extern long int git_curl_ipresolve;
 116extern int active_requests;
 117extern int http_is_verbose;
 118extern ssize_t http_post_buffer;
 119extern struct credential http_auth;
 120
 121extern char curl_errorstr[CURL_ERROR_SIZE];
 122
 123enum http_follow_config {
 124        HTTP_FOLLOW_NONE,
 125        HTTP_FOLLOW_ALWAYS,
 126        HTTP_FOLLOW_INITIAL
 127};
 128extern enum http_follow_config http_follow_config;
 129
 130static inline int missing__target(int code, int result)
 131{
 132        return  /* file:// URL -- do we ever use one??? */
 133                (result == CURLE_FILE_COULDNT_READ_FILE) ||
 134                /* http:// and https:// URL */
 135                (code == 404 && result == CURLE_HTTP_RETURNED_ERROR) ||
 136                /* ftp:// URL */
 137                (code == 550 && result == CURLE_FTP_COULDNT_RETR_FILE)
 138                ;
 139}
 140
 141#define missing_target(a) missing__target((a)->http_code, (a)->curl_result)
 142
 143/*
 144 * Normalize curl results to handle CURL_FAILONERROR (or lack thereof). Failing
 145 * http codes have their "result" converted to CURLE_HTTP_RETURNED_ERROR, and
 146 * an appropriate string placed in the errorstr buffer (pass curl_errorstr if
 147 * you don't have a custom buffer).
 148 */
 149void normalize_curl_result(CURLcode *result, long http_code, char *errorstr,
 150                           size_t errorlen);
 151
 152/* Helpers for modifying and creating URLs */
 153void append_remote_object_url(struct strbuf *buf, const char *url,
 154                              const char *hex,
 155                              int only_two_digit_prefix);
 156char *get_remote_object_url(const char *url, const char *hex,
 157                            int only_two_digit_prefix);
 158
 159/* Options for http_get_*() */
 160struct http_get_options {
 161        unsigned no_cache:1,
 162                 initial_request:1;
 163
 164        /* If non-NULL, returns the content-type of the response. */
 165        struct strbuf *content_type;
 166
 167        /*
 168         * If non-NULL, and content_type above is non-NULL, returns
 169         * the charset parameter from the content-type. If none is
 170         * present, returns an empty string.
 171         */
 172        struct strbuf *charset;
 173
 174        /*
 175         * If non-NULL, returns the URL we ended up at, including any
 176         * redirects we followed.
 177         */
 178        struct strbuf *effective_url;
 179
 180        /*
 181         * If both base_url and effective_url are non-NULL, the base URL will
 182         * be munged to reflect any redirections going from the requested url
 183         * to effective_url. See the definition of update_url_from_redirect
 184         * for details.
 185         */
 186        struct strbuf *base_url;
 187
 188        /*
 189         * If not NULL, contains additional HTTP headers to be sent with the
 190         * request. The strings in the list must not be freed until after the
 191         * request has completed.
 192         */
 193        struct string_list *extra_headers;
 194};
 195
 196/* Return values for http_get_*() */
 197#define HTTP_OK                 0
 198#define HTTP_MISSING_TARGET     1
 199#define HTTP_ERROR              2
 200#define HTTP_START_FAILED       3
 201#define HTTP_REAUTH     4
 202#define HTTP_NOAUTH     5
 203
 204/*
 205 * Requests a URL and stores the result in a strbuf.
 206 *
 207 * If the result pointer is NULL, a HTTP HEAD request is made instead of GET.
 208 */
 209int http_get_strbuf(const char *url, struct strbuf *result, struct http_get_options *options);
 210
 211int http_fetch_ref(const char *base, struct ref *ref);
 212
 213/* Helpers for fetching packs */
 214int http_get_info_packs(const char *base_url,
 215                        struct packed_git **packs_head);
 216
 217struct http_pack_request {
 218        char *url;
 219        struct packed_git *target;
 220        struct packed_git **lst;
 221        FILE *packfile;
 222        struct strbuf tmpfile;
 223        struct active_request_slot *slot;
 224};
 225
 226struct http_pack_request *new_http_pack_request(
 227        struct packed_git *target, const char *base_url);
 228int finish_http_pack_request(struct http_pack_request *preq);
 229void release_http_pack_request(struct http_pack_request *preq);
 230
 231/* Helpers for fetching object */
 232struct http_object_request {
 233        char *url;
 234        struct strbuf tmpfile;
 235        int localfile;
 236        CURLcode curl_result;
 237        char errorstr[CURL_ERROR_SIZE];
 238        long http_code;
 239        struct object_id oid;
 240        struct object_id real_oid;
 241        git_hash_ctx c;
 242        git_zstream stream;
 243        int zret;
 244        int rename;
 245        struct active_request_slot *slot;
 246};
 247
 248struct http_object_request *new_http_object_request(
 249        const char *base_url, const struct object_id *oid);
 250void process_http_object_request(struct http_object_request *freq);
 251int finish_http_object_request(struct http_object_request *freq);
 252void abort_http_object_request(struct http_object_request *freq);
 253void release_http_object_request(struct http_object_request *freq);
 254
 255/* setup routine for curl_easy_setopt CURLOPT_DEBUGFUNCTION */
 256void setup_curl_trace(CURL *handle);
 257#endif /* HTTP_H */