1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
|
/*
* http.h - dnssec-trigger HTTP client code to GET a simple URL
*
* Copyright (c) 2012, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
*
* This file contains an implementation of HTTP fetch for a simple URL file.
*/
#ifndef HTTP_H
#define HTTP_H
struct comm_base;
struct comm_point;
#include <ldns/buffer.h>
#include <ldns/packet.h>
struct svr;
struct http_probe;
struct probe_ip;
struct comm_reply;
/**
* overall HTTP probe structure
*/
struct http_general {
struct svr* svr;
/* array of urls to attempt to transfer from */
char** urls;
/* array of checkcodes to check - the content of those urls */
char** codes;
/* number of urls in array */
size_t url_num;
/* the ipv4 http probe */
struct http_probe* v4;
/* the ipv6 http probe */
struct http_probe* v6;
/* http works */
int saw_http_work;
};
/**
* HTTP probe. The url split up and results.
*/
struct http_probe {
/* the current url (const reference) */
char* url;
/* hostname */
char* hostname;
/* filename (not prefixed with a / ) */
char* filename;
/* url index in urls array */
size_t url_idx;
/* are we fetching the address record or doing http_get? */
int do_addr;
/* is this ipv6? */
int ip6;
/* num addr queries */
int num_addr_qs;
/* num addr queries that failed */
int num_failed_addr_qs;
/* list of addresses (RR records) */
ldns_rr_list* addr;
/* port number */
int port;
/* number of redirects we followed */
int redirects;
/* result: did we get addresses? */
int got_addrs;
/* result: does it connect? */
int connects;
/* result: does it work (correct page) */
int works;
/* is the probe finished? */
int finished;
};
/** the number of urls to try to probe; in case one fails. */
#define HTTP_NUM_URLS_MAX_PROBE 3
/** max number of address queries for one name (all to different caches,
* once for A then for AAAA, so double that number in sockets is needed). */
#define HTTP_MAX_ADDR_QUERIES 5
/** max number of redirects in sequence */
#define HTTP_MAX_REDIRECT 8
/**
* create and randomise http general structure
* @param svr: with config and create and register probes here.
* @return: new http lookup administration
*/
struct http_general* http_general_start(struct svr* svr);
/**
* delete the http_general structure.
* @param hg: http lookup administration
*/
void http_general_delete(struct http_general* hg);
/**
* The http lookup is completely done, either success (NULL) or fail reason
*/
void http_general_done(const char* reason);
/** a host addr lookup is done (with an error or NULL) */
void http_host_outq_done(struct probe_ip* p, const char* reason);
/** a host addr lookup is done, here is the packet (QR, rcode NOERROR).
* The pkt is freeed by this routine. */
void http_host_outq_result(struct probe_ip* p, ldns_pkt* pkt);
/**
* Structure that represents an open TCP activity for a HTTP (no -s) GET.
*/
struct http_get {
/* The url of the target */
char* url;
/* hostname : name of host part of the URL */
char* hostname;
/* filename : name of file part of URL (*not* prefixed with a / ) */
char* filename;
/* state of the HTTP transaction */
enum http_get_state {
/* we are not sending or reading any things */
http_state_none,
/* we are sending the request (initial headers) */
http_state_request,
/* we are reading the reply headers */
http_state_reply_header,
/* we are reading the reply (HTTP/1.0) */
http_state_reply_data,
/* we are reading chunked reply headers (HTTP/1.1) */
http_state_chunk_header,
/* we are reading chunked reply data (HTTP/1.1) */
http_state_chunk_data,
} state;
/* data length (of replydata or chunkdata) */
size_t datalen;
/* max data we want (0 is no max) */
size_t data_limit;
/* this is a redirect response */
int redirect_now;
/* the buffer with contents sent/received */
ldns_buffer* buf;
/* the buffer with the result data */
ldns_buffer* data;
/* my comm_base */
struct comm_base* base;
/* my comm_point (a comm_raw) */
struct comm_point* cp;
/* the timer */
struct comm_timer* timer;
/* destination IP as a string */
char* dest;
/* port number */
int port;
/* the probe that this is part of */
struct probe_ip* probe;
};
/* define max length that the buffer is created for */
#define MAX_HTTP_LENGTH 16384
/* the timeout for the HTTP part of the httpprobe operation, in msec */
#define HTTP_TIMEOUT 3000
/* HTTP port */
#define HTTP_PORT 80
/**
* Create a new HTTP GET for the given url (http://example.com/bla.txt)
* It does a plain (noSSL) http GET.
* @param url: The url to fetch.
* @param base: comm_base to register connect-ed TCP socket's comm_point.
* @param probe: probe this is part of.
* @return new get or NULL on failure (malloc failure).
*/
struct http_get* http_get_create(const char* url, struct comm_base* base,
struct probe_ip* probe);
/**
* Delete a HTTP GET fetch.
* @param hg: http_get structure to delete.
*/
void http_get_delete(struct http_get* hg);
/**
* Perform the fetch that was initialised.
* Parses, connects, and so on.
* @param hg: http_get structure.
* @param dest: destination IP address.
* @param port: port number (HTTP_PORT is the default 80).
* @param err: the detailed error on failure (set to constant string).
* @return false if failed.
*/
int http_get_fetch(struct http_get* hg, const char* dest, int port, char** err);
/** handle socket events on http_get */
int http_get_callback(struct comm_point* cp, void* arg, int err,
struct comm_reply* reply);
/** handle timeout for the http_get operation */
void http_get_timeout_handler(void* arg);
/** pick random RR from rr list, removes it from the list. list not empty*/
ldns_rr* http_pick_random_addr(ldns_rr_list* list);
#endif /* HTTP_H */
|