1 /* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
2 
3 #include "lib.h"
4 #include "net.h"
5 #include "str.h"
6 #include "str-sanitize.h"
7 #include "hash.h"
8 #include "array.h"
9 #include "llist.h"
10 #include "time-util.h"
11 #include "istream.h"
12 #include "ostream.h"
13 #include "file-lock.h"
14 #include "dns-lookup.h"
15 #include "http-url.h"
16 #include "http-date.h"
17 #include "http-auth.h"
18 #include "http-response-parser.h"
19 #include "http-transfer.h"
20 
21 #include "http-client-private.h"
22 
23 const char *http_request_state_names[] = {
24 	"new",
25 	"queued",
26 	"payload_out",
27 	"waiting",
28 	"got_response",
29 	"payload_in",
30 	"finished",
31 	"aborted"
32 };
33 
34 /*
35  * Request
36  */
37 
38 static bool
39 http_client_request_send_error(struct http_client_request *req,
40 			       unsigned int status, const char *error);
41 
http_client_request_label(struct http_client_request * req)42 const char *http_client_request_label(struct http_client_request *req)
43 {
44 	if (req->label == NULL) {
45 		req->label = p_strdup_printf(
46 			req->pool, "[Req%u: %s %s%s]", req->id, req->method,
47 			http_url_create_host(&req->origin_url), req->target);
48 	}
49 	return req->label;
50 }
51 
http_client_request_update_event(struct http_client_request * req)52 static void http_client_request_update_event(struct http_client_request *req)
53 {
54 	event_add_str(req->event, "method", req->method);
55 	event_add_str(req->event, "dest_host", req->origin_url.host.name);
56 	event_add_int(req->event, "dest_port",
57 		      http_url_get_port(&req->origin_url));
58 	if (req->target != NULL)
59 		event_add_str(req->event, "target", req->target);
60 	event_set_append_log_prefix(
61 		req->event, t_strdup_printf("request %s: ",
62 			str_sanitize(http_client_request_label(req), 256)));
63 }
64 
65 static struct event_passthrough *
http_client_request_result_event(struct http_client_request * req)66 http_client_request_result_event(struct http_client_request *req)
67 {
68 	struct http_client_connection *conn = req->conn;
69 
70 	if (conn != NULL) {
71 		if (req->state == HTTP_REQUEST_STATE_PAYLOAD_OUT) {
72 			/* Got here prematurely; use bytes written so far */
73 			i_assert(req->request_offset <
74 				 conn->conn.output->offset);
75 			req->bytes_out = conn->conn.output->offset -
76 				req->request_offset;
77 		}
78 		if (conn->incoming_payload != NULL &&
79 		    (req->state == HTTP_REQUEST_STATE_GOT_RESPONSE ||
80 		     req->state == HTTP_REQUEST_STATE_PAYLOAD_IN)) {
81 			/* Got here prematurely; use bytes read so far */
82 			i_assert(conn->in_req_callback ||
83 				 conn->pending_request == req);
84 			i_assert(req->response_offset <
85 				 conn->conn.input->v_offset);
86 			req->bytes_in = conn->conn.input->v_offset -
87 				req->response_offset;
88 		}
89 	}
90 
91 	struct event_passthrough *e = event_create_passthrough(req->event);
92 	if (req->queue != NULL &&
93 	    req->queue->addr.type != HTTP_CLIENT_PEER_ADDR_UNIX)
94 		e->add_str("dest_ip", net_ip2addr(&req->queue->addr.a.tcp.ip));
95 
96 	return e->add_int("status_code", req->last_status)->
97 		add_int("attempts", req->attempts)->
98 		add_int("redirects", req->redirects)->
99 		add_int("bytes_in", req->bytes_in)->
100 		add_int("bytes_out", req->bytes_out);
101 }
102 
103 static struct http_client_request *
http_client_request_new(struct http_client * client,const char * method,http_client_request_callback_t * callback,void * context)104 http_client_request_new(struct http_client *client, const char *method,
105 			http_client_request_callback_t *callback, void *context)
106 {
107 	static unsigned int id_counter = 0;
108 	pool_t pool;
109 	struct http_client_request *req;
110 
111 	pool = pool_alloconly_create("http client request", 2048);
112 	req = p_new(pool, struct http_client_request, 1);
113 	req->pool = pool;
114 	req->refcount = 1;
115 	req->client = client;
116 	req->id = ++id_counter;
117 	req->method = p_strdup(pool, method);
118 	req->callback = callback;
119 	req->context = context;
120 	req->date = (time_t)-1;
121 	req->event = event_create(client->event);
122 
123 	/* Default to client-wide settings: */
124 	req->max_attempts = client->set.max_attempts;
125 	req->attempt_timeout_msecs = client->set.request_timeout_msecs;
126 
127 	req->state = HTTP_REQUEST_STATE_NEW;
128 	return req;
129 }
130 
131 #undef http_client_request
132 struct http_client_request *
http_client_request(struct http_client * client,const char * method,const char * host,const char * target,http_client_request_callback_t * callback,void * context)133 http_client_request(struct http_client *client,
134 		    const char *method, const char *host, const char *target,
135 		    http_client_request_callback_t *callback, void *context)
136 {
137 	struct http_client_request *req;
138 
139 	req = http_client_request_new(client, method, callback, context);
140 	req->origin_url.host.name = p_strdup(req->pool, host);
141 	req->target = (target == NULL ? "/" : p_strdup(req->pool, target));
142 	http_client_request_update_event(req);
143 	return req;
144 }
145 
146 #undef http_client_request_url
147 struct http_client_request *
http_client_request_url(struct http_client * client,const char * method,const struct http_url * target_url,http_client_request_callback_t * callback,void * context)148 http_client_request_url(struct http_client *client,
149 			const char *method, const struct http_url *target_url,
150 			http_client_request_callback_t *callback, void *context)
151 {
152 	struct http_client_request *req;
153 
154 	req = http_client_request_new(client, method, callback, context);
155 	http_url_copy_authority(req->pool, &req->origin_url, target_url);
156 	req->target = p_strdup(req->pool, http_url_create_target(target_url));
157 	if (target_url->user != NULL && *target_url->user != '\0' &&
158 	    target_url->password != NULL) {
159 		req->username = p_strdup(req->pool, target_url->user);
160 		req->password = p_strdup(req->pool, target_url->password);
161 	}
162 	http_client_request_update_event(req);
163 	return req;
164 }
165 
166 #undef http_client_request_url_str
167 struct http_client_request *
http_client_request_url_str(struct http_client * client,const char * method,const char * url_str,http_client_request_callback_t * callback,void * context)168 http_client_request_url_str(struct http_client *client,
169 			    const char *method, const char *url_str,
170 			    http_client_request_callback_t *callback,
171 			    void *context)
172 {
173 	struct http_client_request *req, *tmpreq;
174 	struct http_url *target_url;
175 	const char *error;
176 
177 	req = tmpreq = http_client_request_new(client, method,
178 					       callback, context);
179 
180 	if (http_url_parse(url_str, NULL, HTTP_URL_ALLOW_USERINFO_PART,
181 			   req->pool, &target_url, &error) < 0) {
182 		req->label = p_strdup_printf(req->pool, "[Req%u: %s %s]",
183 					     req->id, req->method, url_str);
184 		http_client_request_error(
185 			&tmpreq, HTTP_CLIENT_REQUEST_ERROR_INVALID_URL,
186 			t_strdup_printf("Invalid HTTP URL: %s", error));
187 		http_client_request_update_event(req);
188 		return req;
189 	}
190 
191 	req->origin_url = *target_url;
192 	req->target = p_strdup(req->pool, http_url_create_target(target_url));
193 	if (target_url->user != NULL && *target_url->user != '\0' &&
194 	    target_url->password != NULL) {
195 		req->username = p_strdup(req->pool, target_url->user);
196 		req->password = p_strdup(req->pool, target_url->password);
197 	}
198 	http_client_request_update_event(req);
199 	return req;
200 }
201 
202 #undef http_client_request_connect
203 struct http_client_request *
http_client_request_connect(struct http_client * client,const char * host,in_port_t port,http_client_request_callback_t * callback,void * context)204 http_client_request_connect(struct http_client *client,
205 			    const char *host, in_port_t port,
206 			    http_client_request_callback_t *callback,
207 			    void *context)
208 {
209 	struct http_client_request *req;
210 
211 	req = http_client_request_new(client, "CONNECT", callback, context);
212 	req->origin_url.host.name = p_strdup(req->pool, host);
213 	req->origin_url.port = port;
214 	req->connect_tunnel = TRUE;
215 	req->target = req->origin_url.host.name;
216 	http_client_request_update_event(req);
217 	return req;
218 }
219 
220 #undef http_client_request_connect_ip
221 struct http_client_request *
http_client_request_connect_ip(struct http_client * client,const struct ip_addr * ip,in_port_t port,http_client_request_callback_t * callback,void * context)222 http_client_request_connect_ip(struct http_client *client,
223 			       const struct ip_addr *ip, in_port_t port,
224 			       http_client_request_callback_t *callback,
225 			       void *context)
226 {
227 	struct http_client_request *req;
228 	const char *hostname;
229 
230 	i_assert(ip->family != 0);
231 	hostname = net_ip2addr(ip);
232 
233 	req = http_client_request_connect(client, hostname, port,
234 					  callback, context);
235 	req->origin_url.host.ip = *ip;
236 	return req;
237 }
238 
http_client_request_set_event(struct http_client_request * req,struct event * event)239 void http_client_request_set_event(struct http_client_request *req,
240 				   struct event *event)
241 {
242 	event_unref(&req->event);
243 	req->event = event_create(event);
244 	event_set_forced_debug(req->event, req->client->set.debug);
245 	http_client_request_update_event(req);
246 }
247 
http_client_request_add(struct http_client_request * req)248 static void http_client_request_add(struct http_client_request *req)
249 {
250 	struct http_client *client = req->client;
251 
252 	DLLIST_PREPEND(&client->requests_list, req);
253 	client->requests_count++;
254 	req->listed = TRUE;
255 }
256 
http_client_request_remove(struct http_client_request * req)257 static void http_client_request_remove(struct http_client_request *req)
258 {
259 	struct http_client *client = req->client;
260 
261 	if (client == NULL) {
262 		i_assert(!req->listed);
263 		return;
264 	}
265 	if (req->listed) {
266 		/* Only decrease pending request counter if this request was
267 		   submitted */
268 		DLLIST_REMOVE(&client->requests_list, req);
269 		client->requests_count--;
270 	}
271 	req->listed = FALSE;
272 
273 	if (client->requests_count == 0 && client->waiting)
274 		io_loop_stop(client->ioloop);
275 }
276 
http_client_request_ref(struct http_client_request * req)277 void http_client_request_ref(struct http_client_request *req)
278 {
279 	i_assert(req->refcount > 0);
280 	req->refcount++;
281 }
282 
http_client_request_unref(struct http_client_request ** _req)283 bool http_client_request_unref(struct http_client_request **_req)
284 {
285 	struct http_client_request *req = *_req;
286 	struct http_client *client = req->client;
287 
288 	i_assert(req->refcount > 0);
289 
290 	*_req = NULL;
291 
292 	if (--req->refcount > 0)
293 		return TRUE;
294 
295 	if (client == NULL) {
296 		e_debug(req->event, "Free (client already destroyed)");
297 	} else {
298 		e_debug(req->event, "Free (requests left=%d)",
299 			client->requests_count);
300 	}
301 
302 	/* Cannot be destroyed while it is still pending */
303 	i_assert(req->conn == NULL);
304 
305 	if (req->queue != NULL)
306 		http_client_queue_drop_request(req->queue, req);
307 
308 	if (req->destroy_callback != NULL) {
309 		req->destroy_callback(req->destroy_context);
310 		req->destroy_callback = NULL;
311 	}
312 
313 	http_client_request_remove(req);
314 
315 	if (client != NULL) {
316 		if (client->requests_count == 0 && client->waiting)
317 			io_loop_stop(client->ioloop);
318 		if (req->delayed_error != NULL)
319 			http_client_remove_request_error(req->client, req);
320 	}
321 	i_stream_unref(&req->payload_input);
322 	o_stream_unref(&req->payload_output);
323 	str_free(&req->headers);
324 	event_unref(&req->event);
325 	pool_unref(&req->pool);
326 	return FALSE;
327 }
328 
http_client_request_destroy(struct http_client_request ** _req)329 void http_client_request_destroy(struct http_client_request **_req)
330 {
331 	struct http_client_request *req = *_req, *tmp_req;
332 	struct http_client *client = req->client;
333 
334 	*_req = NULL;
335 
336 	if (client == NULL) {
337 		e_debug(req->event, "Destroy (client already destroyed)");
338 	} else {
339 		e_debug(req->event, "Destroy (requests left=%d)",
340 			client->requests_count);
341 	}
342 
343 
344 	if (req->state < HTTP_REQUEST_STATE_FINISHED)
345 		req->state = HTTP_REQUEST_STATE_ABORTED;
346 	req->callback = NULL;
347 
348 	if (req->queue != NULL)
349 		http_client_queue_drop_request(req->queue, req);
350 
351 	if (client != NULL && req->delayed_error != NULL)
352 		http_client_remove_request_error(req->client, req);
353 	req->delayed_error = NULL;
354 
355 	if (req->destroy_callback != NULL) {
356 		void (*callback)(void *) = req->destroy_callback;
357 
358 		req->destroy_callback = NULL;
359 		callback(req->destroy_context);
360 	}
361 
362 	if (req->conn != NULL)
363 		http_client_connection_request_destroyed(req->conn, req);
364 
365 	tmp_req = req;
366 	http_client_request_remove(req);
367 	if (http_client_request_unref(&tmp_req))
368 		req->client = NULL;
369 }
370 
http_client_request_set_port(struct http_client_request * req,in_port_t port)371 void http_client_request_set_port(struct http_client_request *req,
372 				  in_port_t port)
373 {
374 	i_assert(req->state == HTTP_REQUEST_STATE_NEW);
375 	req->origin_url.port = port;
376 	event_add_int(req->event, "port", port);
377 }
378 
http_client_request_set_ssl(struct http_client_request * req,bool ssl)379 void http_client_request_set_ssl(struct http_client_request *req, bool ssl)
380 {
381 	i_assert(req->state == HTTP_REQUEST_STATE_NEW);
382 	req->origin_url.have_ssl = ssl;
383 }
384 
http_client_request_set_urgent(struct http_client_request * req)385 void http_client_request_set_urgent(struct http_client_request *req)
386 {
387 	i_assert(req->state == HTTP_REQUEST_STATE_NEW);
388 	req->urgent = TRUE;
389 }
390 
http_client_request_set_preserve_exact_reason(struct http_client_request * req)391 void http_client_request_set_preserve_exact_reason(
392 	struct http_client_request *req)
393 {
394 	req->preserve_exact_reason = TRUE;
395 }
396 
397 static bool
http_client_request_lookup_header_pos(struct http_client_request * req,const char * key,size_t * key_pos_r,size_t * value_pos_r,size_t * next_pos_r)398 http_client_request_lookup_header_pos(struct http_client_request *req,
399 				      const char *key, size_t *key_pos_r,
400 				      size_t *value_pos_r, size_t *next_pos_r)
401 {
402 	const unsigned char *data, *p;
403 	size_t size, line_len;
404 	size_t key_len = strlen(key);
405 
406 	if (req->headers == NULL)
407 		return FALSE;
408 
409 	data = str_data(req->headers);
410 	size = str_len(req->headers);
411 	while ((p = memchr(data, '\n', size)) != NULL) {
412 		line_len = (p+1) - data;
413 		if (size > key_len && i_memcasecmp(data, key, key_len) == 0 &&
414 		    data[key_len] == ':' && data[key_len+1] == ' ') {
415 			/* Key was found from header, replace its value */
416 			*key_pos_r = str_len(req->headers) - size;
417 			*value_pos_r = *key_pos_r + key_len + 2;
418 			*next_pos_r = *key_pos_r + line_len;
419 			return TRUE;
420 		}
421 		size -= line_len;
422 		data += line_len;
423 	}
424 	return FALSE;
425 }
426 
427 static void
http_client_request_add_header_full(struct http_client_request * req,const char * key,const char * value,bool replace_existing)428 http_client_request_add_header_full(struct http_client_request *req,
429 				    const char *key, const char *value,
430 				    bool replace_existing)
431 {
432 	size_t key_pos, value_pos, next_pos;
433 
434 	i_assert(req->state == HTTP_REQUEST_STATE_NEW ||
435 		 /* Allow calling for retries */
436 		 req->state == HTTP_REQUEST_STATE_GOT_RESPONSE ||
437 		 req->state == HTTP_REQUEST_STATE_ABORTED);
438 	/* Make sure key or value can't break HTTP headers entirely */
439 	i_assert(strpbrk(key, ":\r\n") == NULL);
440 	i_assert(strpbrk(value, "\r\n") == NULL);
441 
442 	/* Mark presence of special headers */
443 	switch (key[0]) {
444 	case 'a': case 'A':
445 		if (strcasecmp(key, "Authorization") == 0)
446 			req->have_hdr_authorization = TRUE;
447 		break;
448 	case 'c': case 'C':
449 		if (strcasecmp(key, "Connection") == 0)
450 			req->have_hdr_connection = TRUE;
451 		else if (strcasecmp(key, "Content-Length") == 0)
452 			req->have_hdr_body_spec = TRUE;
453 		break;
454 	case 'd': case 'D':
455 		if (strcasecmp(key, "Date") == 0)
456 			req->have_hdr_date = TRUE;
457 		break;
458 	case 'e': case 'E':
459 		if (strcasecmp(key, "Expect") == 0)
460 			req->have_hdr_expect = TRUE;
461 		break;
462 	case 'h': case 'H':
463 		if (strcasecmp(key, "Host") == 0)
464 			req->have_hdr_host = TRUE;
465 		break;
466 	case 'p': case 'P':
467 		i_assert(strcasecmp(key, "Proxy-Authorization") != 0);
468 		break;
469 	case 't': case 'T':
470 		if (strcasecmp(key, "Transfer-Encoding") == 0)
471 			req->have_hdr_body_spec = TRUE;
472 		break;
473 	case 'u': case 'U':
474 		if (strcasecmp(key, "User-Agent") == 0)
475 			req->have_hdr_user_agent = TRUE;
476 		break;
477 	}
478 	if (req->headers == NULL)
479 		req->headers = str_new(default_pool, 256);
480 	if (!http_client_request_lookup_header_pos(req, key, &key_pos,
481 						   &value_pos, &next_pos))
482 		str_printfa(req->headers, "%s: %s\r\n", key, value);
483 	else if (replace_existing) {
484 		/* Don't delete CRLF */
485 		size_t old_value_len = next_pos - value_pos - 2;
486 		str_replace(req->headers, value_pos, old_value_len, value);
487 	}
488 }
489 
http_client_request_add_header(struct http_client_request * req,const char * key,const char * value)490 void http_client_request_add_header(struct http_client_request *req,
491 				    const char *key, const char *value)
492 {
493 	http_client_request_add_header_full(req, key, value, TRUE);
494 }
495 
http_client_request_add_missing_header(struct http_client_request * req,const char * key,const char * value)496 void http_client_request_add_missing_header(struct http_client_request *req,
497 					    const char *key, const char *value)
498 {
499 	http_client_request_add_header_full(req, key, value, FALSE);
500 }
501 
http_client_request_remove_header(struct http_client_request * req,const char * key)502 void http_client_request_remove_header(struct http_client_request *req,
503 				       const char *key)
504 {
505 	size_t key_pos, value_pos, next_pos;
506 
507 	i_assert(req->state == HTTP_REQUEST_STATE_NEW ||
508 		 /* Allow calling for retries */
509 		 req->state == HTTP_REQUEST_STATE_GOT_RESPONSE ||
510 		 req->state == HTTP_REQUEST_STATE_ABORTED);
511 
512 	if (http_client_request_lookup_header_pos(req, key, &key_pos,
513 						  &value_pos, &next_pos))
514 		str_delete(req->headers, key_pos, next_pos - key_pos);
515 }
516 
http_client_request_lookup_header(struct http_client_request * req,const char * key)517 const char *http_client_request_lookup_header(struct http_client_request *req,
518 					      const char *key)
519 {
520 	size_t key_pos, value_pos, next_pos;
521 
522 	if (!http_client_request_lookup_header_pos(req, key, &key_pos,
523 						   &value_pos, &next_pos))
524 		return NULL;
525 
526 	/* Don't return CRLF */
527 	return t_strndup(str_data(req->headers) + value_pos,
528 			 next_pos - value_pos - 2);
529 }
530 
http_client_request_set_date(struct http_client_request * req,time_t date)531 void http_client_request_set_date(struct http_client_request *req, time_t date)
532 {
533 	i_assert(req->state == HTTP_REQUEST_STATE_NEW);
534 	req->date = date;
535 }
536 
http_client_request_set_payload(struct http_client_request * req,struct istream * input,bool sync)537 void http_client_request_set_payload(struct http_client_request *req,
538 				     struct istream *input, bool sync)
539 {
540 	int ret;
541 
542 	i_assert(req->state == HTTP_REQUEST_STATE_NEW);
543 	i_assert(req->payload_input == NULL);
544 
545 	i_stream_ref(input);
546 	req->payload_input = input;
547 	if ((ret = i_stream_get_size(input, TRUE, &req->payload_size)) <= 0) {
548 		if (ret < 0) {
549 			i_error("i_stream_get_size(%s) failed: %s",
550 				i_stream_get_name(input),
551 				i_stream_get_error(input));
552 		}
553 		req->payload_size = 0;
554 		req->payload_chunked = TRUE;
555 	} else {
556 		i_assert(input->v_offset <= req->payload_size);
557 		req->payload_size -= input->v_offset;
558 	}
559 	req->payload_offset = input->v_offset;
560 
561 	/* Prepare request payload sync using 100 Continue response from server
562 	 */
563 	if ((req->payload_chunked || req->payload_size > 0) && sync)
564 		req->payload_sync = TRUE;
565 }
566 
http_client_request_set_payload_data(struct http_client_request * req,const unsigned char * data,size_t size)567 void http_client_request_set_payload_data(struct http_client_request *req,
568 					  const unsigned char *data,
569 					  size_t size)
570 {
571 	struct istream *input;
572 	unsigned char *payload_data;
573 
574 	if (size == 0)
575 		return;
576 
577 	payload_data = p_malloc(req->pool, size);
578 	memcpy(payload_data, data, size);
579 	input = i_stream_create_from_data(payload_data, size);
580 
581 	http_client_request_set_payload(req, input, FALSE);
582 	i_stream_unref(&input);
583 }
584 
http_client_request_set_payload_empty(struct http_client_request * req)585 void http_client_request_set_payload_empty(struct http_client_request *req)
586 {
587 	req->payload_empty = TRUE;
588 }
589 
http_client_request_set_timeout_msecs(struct http_client_request * req,unsigned int msecs)590 void http_client_request_set_timeout_msecs(struct http_client_request *req,
591 					   unsigned int msecs)
592 {
593 	i_assert(req->state == HTTP_REQUEST_STATE_NEW ||
594 		 req->state == HTTP_REQUEST_STATE_GOT_RESPONSE);
595 
596 	req->timeout_msecs = msecs;
597 }
598 
http_client_request_set_timeout(struct http_client_request * req,const struct timeval * time)599 void http_client_request_set_timeout(struct http_client_request *req,
600 				     const struct timeval *time)
601 {
602 	i_assert(req->state == HTTP_REQUEST_STATE_NEW ||
603 		 req->state == HTTP_REQUEST_STATE_GOT_RESPONSE);
604 
605 	req->timeout_time = *time;
606 	req->timeout_msecs = 0;
607 }
608 
http_client_request_set_attempt_timeout_msecs(struct http_client_request * req,unsigned int msecs)609 void http_client_request_set_attempt_timeout_msecs(
610 	struct http_client_request *req, unsigned int msecs)
611 {
612 	i_assert(req->state == HTTP_REQUEST_STATE_NEW ||
613 		 req->state == HTTP_REQUEST_STATE_GOT_RESPONSE);
614 
615 	req->attempt_timeout_msecs = msecs;
616 }
617 
http_client_request_set_max_attempts(struct http_client_request * req,unsigned int max_attempts)618 void http_client_request_set_max_attempts(struct http_client_request *req,
619 					  unsigned int max_attempts)
620 {
621 	i_assert(req->state == HTTP_REQUEST_STATE_NEW ||
622 		 req->state == HTTP_REQUEST_STATE_GOT_RESPONSE);
623 
624 	req->max_attempts = max_attempts;
625 }
626 
http_client_request_set_event_headers(struct http_client_request * req,const char * const * headers)627 void http_client_request_set_event_headers(struct http_client_request *req,
628 					   const char *const *headers)
629 {
630 	req->event_headers = p_strarray_dup(req->pool, headers);
631 }
632 
http_client_request_set_auth_simple(struct http_client_request * req,const char * username,const char * password)633 void http_client_request_set_auth_simple(struct http_client_request *req,
634 					 const char *username,
635 					 const char *password)
636 {
637 	req->username = p_strdup(req->pool, username);
638 	req->password = p_strdup(req->pool, password);
639 }
640 
http_client_request_set_proxy_url(struct http_client_request * req,const struct http_url * proxy_url)641 void http_client_request_set_proxy_url(struct http_client_request *req,
642 				       const struct http_url *proxy_url)
643 {
644 	i_assert(req->state == HTTP_REQUEST_STATE_NEW ||
645 		 req->state == HTTP_REQUEST_STATE_GOT_RESPONSE);
646 
647 	req->host_url = http_url_clone_authority(req->pool, proxy_url);
648 	req->host_socket = NULL;
649 }
650 
http_client_request_set_proxy_socket(struct http_client_request * req,const char * proxy_socket)651 void http_client_request_set_proxy_socket(struct http_client_request *req,
652 					  const char *proxy_socket)
653 {
654 	i_assert(req->state == HTTP_REQUEST_STATE_NEW ||
655 		 req->state == HTTP_REQUEST_STATE_GOT_RESPONSE);
656 
657 	req->host_socket = p_strdup(req->pool, proxy_socket);
658 	req->host_url = NULL;
659 }
660 
http_client_request_delay_until(struct http_client_request * req,time_t time)661 void http_client_request_delay_until(struct http_client_request *req,
662 				     time_t time)
663 {
664 	req->release_time.tv_sec = time;
665 	req->release_time.tv_usec = 0;
666 }
667 
http_client_request_delay(struct http_client_request * req,time_t seconds)668 void http_client_request_delay(struct http_client_request *req, time_t seconds)
669 {
670 	req->release_time = ioloop_timeval;
671 	req->release_time.tv_sec += seconds;
672 }
673 
http_client_request_delay_msecs(struct http_client_request * req,unsigned int msecs)674 void http_client_request_delay_msecs(struct http_client_request *req,
675 				     unsigned int msecs)
676 {
677 	req->release_time = ioloop_timeval;
678 	timeval_add_msecs(&req->release_time, msecs);
679 }
680 
http_client_request_delay_from_response(struct http_client_request * req,const struct http_response * response)681 int http_client_request_delay_from_response(
682 	struct http_client_request *req, const struct http_response *response)
683 {
684 	time_t retry_after = response->retry_after;
685 	unsigned int max;
686 
687 	i_assert(req->client != NULL);
688 
689 	if (retry_after == (time_t)-1)
690 		return 0;  /* no delay */
691 	if (retry_after < ioloop_time)
692 		return 0;  /* delay already expired */
693 	max = (req->client->set.max_auto_retry_delay == 0 ?
694 	       req->attempt_timeout_msecs / 1000 :
695 	       req->client->set.max_auto_retry_delay);
696 	if ((unsigned int)(retry_after - ioloop_time) > max)
697 		return -1; /* delay too long */
698 	req->release_time.tv_sec = retry_after;
699 	req->release_time.tv_usec = 0;
700 	return 1; /* valid delay */
701 }
702 
703 const char *
http_client_request_get_method(const struct http_client_request * req)704 http_client_request_get_method(const struct http_client_request *req)
705 {
706 	return req->method;
707 }
708 
709 const char *
http_client_request_get_target(const struct http_client_request * req)710 http_client_request_get_target(const struct http_client_request *req)
711 {
712 	return req->target;
713 }
714 
715 const struct http_url *
http_client_request_get_origin_url(const struct http_client_request * req)716 http_client_request_get_origin_url(const struct http_client_request *req)
717 {
718 	return &req->origin_url;
719 }
720 
721 enum http_request_state
http_client_request_get_state(const struct http_client_request * req)722 http_client_request_get_state(const struct http_client_request *req)
723 {
724 	return req->state;
725 }
726 
727 unsigned int
http_client_request_get_attempts(const struct http_client_request * req)728 http_client_request_get_attempts(const struct http_client_request *req)
729 {
730 	return req->attempts;
731 }
732 
http_client_request_get_stats(struct http_client_request * req,struct http_client_request_stats * stats_r)733 void http_client_request_get_stats(struct http_client_request *req,
734 				   struct http_client_request_stats *stats_r)
735 {
736 	struct http_client *client = req->client;
737 	int diff_msecs;
738 	uint64_t wait_usecs;
739 
740 	i_zero(stats_r);
741 	if (!req->submitted)
742 		return;
743 
744 	/* Total elapsed time since message was submitted */
745 	diff_msecs = timeval_diff_msecs(&ioloop_timeval, &req->submit_time);
746 	stats_r->total_msecs = (unsigned int)I_MAX(diff_msecs, 0);
747 
748 	/* Elapsed time since message was first sent */
749 	if (req->first_sent_time.tv_sec > 0) {
750 		diff_msecs = timeval_diff_msecs(&ioloop_timeval,
751 						&req->first_sent_time);
752 		stats_r->first_sent_msecs = (unsigned int)I_MAX(diff_msecs, 0);
753 	}
754 
755 	/* Elapsed time since message was last sent */
756 	if (req->sent_time.tv_sec > 0) {
757 		diff_msecs = timeval_diff_msecs(&ioloop_timeval,
758 						&req->sent_time);
759 		stats_r->last_sent_msecs = (unsigned int)I_MAX(diff_msecs, 0);
760 	}
761 
762 	if (req->conn != NULL) {
763 		/* Time spent in other ioloops */
764 		i_assert(ioloop_global_wait_usecs >=
765 			 req->sent_global_ioloop_usecs);
766 		stats_r->other_ioloop_msecs = (unsigned int)
767 			(ioloop_global_wait_usecs -
768 				req->sent_global_ioloop_usecs + 999) / 1000;
769 
770 		/* Time spent in the http-client's own ioloop */
771 		if (client != NULL && client->waiting) {
772 			wait_usecs =
773 				io_wait_timer_get_usecs(req->conn->io_wait_timer);
774 			i_assert(wait_usecs >= req->sent_http_ioloop_usecs);
775 			stats_r->http_ioloop_msecs = (unsigned int)
776 				(wait_usecs -
777 				 req->sent_http_ioloop_usecs + 999) / 1000;
778 
779 			i_assert(stats_r->other_ioloop_msecs >=
780 				 stats_r->http_ioloop_msecs);
781 			stats_r->other_ioloop_msecs -= stats_r->http_ioloop_msecs;
782 		}
783 	}
784 
785 	/* Total time spent on waiting for file locks */
786 	wait_usecs = file_lock_wait_get_total_usecs();
787 	i_assert(wait_usecs >= req->sent_lock_usecs);
788 	stats_r->lock_msecs = (unsigned int)
789 		(wait_usecs - req->sent_lock_usecs + 999) / 1000;
790 
791 	/* Number of attempts for this request */
792 	stats_r->attempts = req->attempts;
793 	/* Number of send attempts for this request */
794 	stats_r->send_attempts = req->send_attempts;
795 }
796 
http_client_request_append_stats_text(struct http_client_request * req,string_t * str)797 void http_client_request_append_stats_text(struct http_client_request *req,
798 					   string_t *str)
799 {
800 	struct http_client_request_stats stats;
801 
802 	if (!req->submitted) {
803 		str_append(str, "not yet submitted");
804 		return;
805 	}
806 
807 	http_client_request_get_stats(req, &stats);
808 
809 	str_printfa(str, "queued %u.%03u secs ago",
810 		    stats.total_msecs/1000, stats.total_msecs%1000);
811 	if (stats.attempts > 0)
812 		str_printfa(str, ", %u times retried", stats.attempts);
813 
814 	if (stats.send_attempts == 0) {
815 		str_append(str, ", not yet sent");
816 	} else {
817 		str_printfa(str, ", %u send attempts in %u.%03u secs",
818 			    stats.send_attempts, stats.first_sent_msecs/1000,
819 			    stats.first_sent_msecs%1000);
820 		if (stats.send_attempts > 1) {
821 			str_printfa(str, ", %u.%03u in last attempt",
822 				    stats.last_sent_msecs/1000,
823 				    stats.last_sent_msecs%1000);
824 		}
825 	}
826 
827 	if (stats.http_ioloop_msecs > 0) {
828 		str_printfa(str, ", %u.%03u in http ioloop",
829 			    stats.http_ioloop_msecs/1000,
830 			    stats.http_ioloop_msecs%1000);
831 	}
832 	str_printfa(str, ", %u.%03u in other ioloops",
833 		    stats.other_ioloop_msecs/1000,
834 		    stats.other_ioloop_msecs%1000);
835 
836 	if (stats.lock_msecs > 0) {
837 		str_printfa(str, ", %u.%03u in locks",
838 			    stats.lock_msecs/1000, stats.lock_msecs%1000);
839 	}
840 }
841 
842 enum http_response_payload_type
http_client_request_get_payload_type(struct http_client_request * req)843 http_client_request_get_payload_type(struct http_client_request *req)
844 {
845 	/* RFC 7230, Section 3.3:
846 
847 	   The presence of a message body in a response depends on both the
848 	   request method to which it is responding and the response status code
849 	   (Section 3.1.2 of [RFC7230]). Responses to the HEAD request method
850 	   (Section 4.3.2 of [RFC7231]) never include a message body because the
851 	   associated response header fields (e.g., Transfer-Encoding,
852 	   Content-Length, etc.), if present, indicate only what their values
853 	   would have been if the request method had been GET (Section 4.3.1 of
854 	   [RFC7231]). 2xx (Successful) responses to a CONNECT request method
855 	   (Section 4.3.6 of [RFC7231]) switch to tunnel mode instead of having
856 	   a message body.
857 	 */
858 	if (strcmp(req->method, "HEAD") == 0)
859 		return HTTP_RESPONSE_PAYLOAD_TYPE_NOT_PRESENT;
860 	if (strcmp(req->method, "CONNECT") == 0)
861 		return HTTP_RESPONSE_PAYLOAD_TYPE_ONLY_UNSUCCESSFUL;
862 	return HTTP_RESPONSE_PAYLOAD_TYPE_ALLOWED;
863 }
864 
http_client_request_do_submit(struct http_client_request * req)865 static void http_client_request_do_submit(struct http_client_request *req)
866 {
867 	struct http_client *client = req->client;
868 	struct http_client_host *host;
869 	const char *proxy_socket_path = client->set.proxy_socket_path;
870 	const struct http_url *proxy_url = client->set.proxy_url;
871 	bool have_proxy =
872 		((proxy_socket_path != NULL) || (proxy_url != NULL) ||
873 		 (req->host_socket != NULL) || (req->host_url != NULL));
874 	const char *authority, *target;
875 
876 	if (req->state == HTTP_REQUEST_STATE_ABORTED)
877 		return;
878 	i_assert(client != NULL);
879 	i_assert(req->state == HTTP_REQUEST_STATE_NEW);
880 
881 	authority = http_url_create_authority(&req->origin_url);
882 	if (req->connect_tunnel) {
883 		/* Connect requests require authority form for request target */
884 		target = authority;
885 	} else {
886 		/* Absolute target URL */
887 		target = t_strconcat(http_url_create_host(&req->origin_url),
888 				     req->target, NULL);
889 	}
890 
891 	/* Determine what host to contact to submit this request */
892 	if (have_proxy) {
893 		if (req->host_socket != NULL) {
894 			/* Specific socket proxy */
895 			req->host_url = NULL;
896 		} else if (req->host_url != NULL) {
897 			/* Specific normal proxy */
898 			req->host_socket = NULL;
899 		} else if (req->origin_url.have_ssl &&
900 			   !client->set.no_ssl_tunnel &&
901 			   !req->connect_tunnel) {
902 			/* Tunnel to origin server */
903 			req->host_url = &req->origin_url;
904 			req->ssl_tunnel = TRUE;
905 		} else if (proxy_socket_path != NULL) {
906 			/* Proxy on unix socket */
907 			req->host_socket = proxy_socket_path;
908 			req->host_url = NULL;
909 		} else {
910 			/* Normal proxy server */
911 			req->host_url = proxy_url;
912 			req->host_socket = NULL;
913 		}
914 	} else {
915 		/* Origin server */
916 		req->host_url = &req->origin_url;
917 	}
918 
919 	/* Use submission date if no date is set explicitly */
920 	if (req->date == (time_t)-1)
921 		req->date = ioloop_time;
922 
923 	/* Prepare value for Host header */
924 	req->authority = p_strdup(req->pool, authority);
925 
926 	/* Debug label */
927 	req->label = p_strdup_printf(req->pool, "[Req%u: %s %s]",
928 				     req->id, req->method, target);
929 
930 	/* Update request target */
931 	if (req->connect_tunnel || have_proxy)
932 		req->target = p_strdup(req->pool, target);
933 
934 	if (!have_proxy) {
935 		/* If we don't have a proxy, CONNECT requests are handled by
936 		   creating the requested connection directly */
937 		req->connect_direct = req->connect_tunnel;
938 		if (req->connect_direct)
939 			req->urgent = TRUE;
940 	}
941 
942 	if (req->timeout_time.tv_sec == 0) {
943 		if (req->timeout_msecs > 0) {
944 			req->timeout_time = ioloop_timeval;
945 			timeval_add_msecs(&req->timeout_time,
946 					  req->timeout_msecs);
947 		} else if (client->set.request_absolute_timeout_msecs > 0) {
948 			req->timeout_time = ioloop_timeval;
949 			timeval_add_msecs(&req->timeout_time,
950 				client->set.request_absolute_timeout_msecs);
951 		}
952 	}
953 
954 	host = http_client_host_get(client, req->host_url);
955 	req->state = HTTP_REQUEST_STATE_QUEUED;
956 	req->last_status = 0;
957 
958 	http_client_host_submit_request(host, req);
959 }
960 
http_client_request_submit(struct http_client_request * req)961 void http_client_request_submit(struct http_client_request *req)
962 {
963 	i_assert(req->client != NULL);
964 
965 	req->submit_time = ioloop_timeval;
966 
967 	http_client_request_update_event(req);
968 	http_client_request_do_submit(req);
969 
970 	req->submitted = TRUE;
971 	http_client_request_add(req);
972 
973 	e_debug(req->event, "Submitted (requests left=%d)",
974 		req->client->requests_count);
975 }
976 
http_client_request_get_peer_addr(const struct http_client_request * req,struct http_client_peer_addr * addr)977 void http_client_request_get_peer_addr(const struct http_client_request *req,
978 				       struct http_client_peer_addr *addr)
979 {
980 	const char *host_socket = req->host_socket;
981 	const struct http_url *host_url = req->host_url;
982 
983 	/* The IP address may be unassigned in the returned peer address, since
984 	   that is only available at this stage when the target URL has an
985 	   explicit IP address. */
986 	i_zero(addr);
987 	if (host_socket != NULL) {
988 		addr->type = HTTP_CLIENT_PEER_ADDR_UNIX;
989 		addr->a.un.path = host_socket;
990 	} else if (req->connect_direct) {
991 		addr->type = HTTP_CLIENT_PEER_ADDR_RAW;
992 		addr->a.tcp.ip = host_url->host.ip;
993 		addr->a.tcp.port =
994 			http_url_get_port_default(host_url, HTTPS_DEFAULT_PORT);
995 	} else if (host_url->have_ssl) {
996 		if (req->ssl_tunnel)
997 			addr->type = HTTP_CLIENT_PEER_ADDR_HTTPS_TUNNEL;
998 		else
999 			addr->type = HTTP_CLIENT_PEER_ADDR_HTTPS;
1000 		addr->a.tcp.ip = host_url->host.ip;
1001 		addr->a.tcp.https_name = host_url->host.name;
1002 		addr->a.tcp.port = http_url_get_port(host_url);
1003 	} else {
1004 		addr->type = HTTP_CLIENT_PEER_ADDR_HTTP;
1005 		addr->a.tcp.ip = host_url->host.ip;
1006 		addr->a.tcp.port = http_url_get_port(host_url);
1007 	}
1008 }
1009 
http_client_request_flush_payload(struct http_client_request * req)1010 static int http_client_request_flush_payload(struct http_client_request *req)
1011 {
1012 	struct http_client_connection *conn = req->conn;
1013 	int ret;
1014 
1015 	if (req->payload_output != conn->conn.output &&
1016 	    (ret = o_stream_finish(req->payload_output)) <= 0) {
1017 		if (ret < 0)
1018 			http_client_connection_handle_output_error(conn);
1019 		return ret;
1020 	}
1021 
1022 	return 1;
1023 }
1024 
1025 static int
http_client_request_finish_payload_out(struct http_client_request * req)1026 http_client_request_finish_payload_out(struct http_client_request *req)
1027 {
1028 	struct http_client_connection *conn = req->conn;
1029 	int ret;
1030 
1031 	i_assert(conn != NULL);
1032 	req->payload_finished = TRUE;
1033 
1034 	/* Drop payload output stream */
1035 	if (req->payload_output != NULL) {
1036 		ret = http_client_request_flush_payload(req);
1037 		if (ret < 0)
1038 			return -1;
1039 		if (ret == 0) {
1040 			e_debug(req->event,
1041 				"Not quite finished sending payload");
1042 			return 0;
1043 		}
1044 		o_stream_unref(&req->payload_output);
1045 		req->payload_output = NULL;
1046 	}
1047 
1048 	i_assert(req->request_offset < conn->conn.output->offset);
1049 	req->bytes_out = conn->conn.output->offset - req->request_offset;
1050 
1051 	/* Advance state only when request didn't get aborted in the mean time
1052 	 */
1053 	if (req->state != HTTP_REQUEST_STATE_ABORTED) {
1054 		i_assert(req->state == HTTP_REQUEST_STATE_PAYLOAD_OUT);
1055 
1056 		/* we're now waiting for a response from the server */
1057 		req->state = HTTP_REQUEST_STATE_WAITING;
1058 		http_client_connection_start_request_timeout(conn);
1059 	}
1060 
1061 	/* Release connection */
1062 	conn->output_locked = FALSE;
1063 
1064 	e_debug(req->event, "Finished sending%s payload",
1065 		(req->state == HTTP_REQUEST_STATE_ABORTED ? " aborted" : ""));
1066 	return 1;
1067 }
1068 
1069 static int
http_client_request_continue_payload(struct http_client_request ** _req,const unsigned char * data,size_t size)1070 http_client_request_continue_payload(struct http_client_request **_req,
1071 				     const unsigned char *data, size_t size)
1072 {
1073 	struct ioloop *prev_ioloop, *client_ioloop, *prev_client_ioloop;
1074 	struct http_client_request *req = *_req;
1075 	struct http_client_connection *conn = req->conn;
1076 	struct http_client *client = req->client;
1077 	int ret;
1078 
1079 	i_assert(client != NULL);
1080 	i_assert(req->state == HTTP_REQUEST_STATE_NEW ||
1081 		 req->state == HTTP_REQUEST_STATE_PAYLOAD_OUT);
1082 	i_assert(req->payload_input == NULL);
1083 
1084 	if (conn != NULL)
1085 		http_client_connection_ref(conn);
1086 	http_client_request_ref(req);
1087 	req->payload_wait = TRUE;
1088 
1089 	if (data == NULL) {
1090 		req->payload_input = NULL;
1091 		if (req->state == HTTP_REQUEST_STATE_PAYLOAD_OUT)
1092 			(void)http_client_request_finish_payload_out(req);
1093 	} else {
1094 		req->payload_input = i_stream_create_from_data(data, size);
1095 		i_stream_set_name(req->payload_input, "<HTTP request payload>");
1096 	}
1097 	req->payload_size = 0;
1098 	req->payload_chunked = TRUE;
1099 
1100 	if (req->state == HTTP_REQUEST_STATE_NEW)
1101 		http_client_request_submit(req);
1102 	if (req->state == HTTP_REQUEST_STATE_ABORTED) {
1103 		/* Request already failed */
1104 		if (req->delayed_error != NULL) {
1105 			struct http_client_request *tmpreq = req;
1106 
1107 			/* Handle delayed error outside ioloop; the caller
1108 			   expects callbacks occurring, so there is no need for
1109 			   delay. Also, it is very important that any error
1110 			   triggers a callback before
1111 			   http_client_request_send_payload() finishes, since
1112 			   its return value is not always checked.
1113 			 */
1114 			http_client_remove_request_error(client, req);
1115 			http_client_request_error_delayed(&tmpreq);
1116 		}
1117 	} else {
1118 		/* Wait for payload data to be written */
1119 
1120 		prev_ioloop = current_ioloop;
1121 		client_ioloop = io_loop_create();
1122 		prev_client_ioloop = http_client_switch_ioloop(client);
1123 		if (client->set.dns_client != NULL)
1124 			dns_client_switch_ioloop(client->set.dns_client);
1125 
1126 		client->waiting = TRUE;
1127 		while (req->state < HTTP_REQUEST_STATE_PAYLOAD_IN) {
1128 			e_debug(req->event, "Waiting for request to finish");
1129 
1130 			if (req->state == HTTP_REQUEST_STATE_PAYLOAD_OUT) {
1131 				o_stream_set_flush_pending(
1132 					req->payload_output, TRUE);
1133 			}
1134 
1135 			io_loop_run(client_ioloop);
1136 
1137 			if (req->state == HTTP_REQUEST_STATE_PAYLOAD_OUT &&
1138 				req->payload_input->eof) {
1139 				i_stream_unref(&req->payload_input);
1140 				req->payload_input = NULL;
1141 				break;
1142 			}
1143 		}
1144 		client->waiting = FALSE;
1145 
1146 		if (prev_client_ioloop != NULL)
1147 			io_loop_set_current(prev_client_ioloop);
1148 		else
1149 			io_loop_set_current(prev_ioloop);
1150 		(void)http_client_switch_ioloop(client);
1151 		if (client->set.dns_client != NULL)
1152 			dns_client_switch_ioloop(client->set.dns_client);
1153 		io_loop_set_current(client_ioloop);
1154 		io_loop_destroy(&client_ioloop);
1155 	}
1156 
1157 	switch (req->state) {
1158 	case HTTP_REQUEST_STATE_PAYLOAD_IN:
1159 	case HTTP_REQUEST_STATE_FINISHED:
1160 		ret = 1;
1161 		break;
1162 	case HTTP_REQUEST_STATE_ABORTED:
1163 		ret = -1;
1164 		break;
1165 	default:
1166 		ret = 0;
1167 		break;
1168 	}
1169 
1170 	req->payload_wait = FALSE;
1171 
1172 	/* callback may have messed with our pointer, so unref using local
1173 	   variable */
1174 	if (!http_client_request_unref(&req))
1175 		*_req = NULL;
1176 
1177 	if (conn != NULL)
1178 		http_client_connection_unref(&conn);
1179 
1180 	return ret;
1181 }
1182 
http_client_request_send_payload(struct http_client_request ** _req,const unsigned char * data,size_t size)1183 int http_client_request_send_payload(struct http_client_request **_req,
1184 				     const unsigned char *data, size_t size)
1185 {
1186 	struct http_client_request *req = *_req;
1187 	int ret;
1188 
1189 	i_assert(data != NULL);
1190 
1191 	ret = http_client_request_continue_payload(&req, data, size);
1192 	if (ret < 0) {
1193 		/* Failed to send payload */
1194 		*_req = NULL;
1195 	} else if (ret > 0) {
1196 		/* Premature end of request;
1197 		   server sent error before all payload could be sent */
1198 		ret = -1;
1199 		*_req = NULL;
1200 	} else {
1201 		/* Not finished sending payload */
1202 		i_assert(req != NULL);
1203 	}
1204 	return ret;
1205 }
1206 
http_client_request_finish_payload(struct http_client_request ** _req)1207 int http_client_request_finish_payload(struct http_client_request **_req)
1208 {
1209 	struct http_client_request *req = *_req;
1210 	int ret;
1211 
1212 	*_req = NULL;
1213 	ret = http_client_request_continue_payload(&req, NULL, 0);
1214 	i_assert(ret != 0);
1215 	return ret < 0 ? -1 : 0;
1216 }
1217 
http_client_request_payload_input(struct http_client_request * req)1218 static void http_client_request_payload_input(struct http_client_request *req)
1219 {
1220 	struct http_client_connection *conn = req->conn;
1221 
1222 	io_remove(&conn->io_req_payload);
1223 
1224 	(void)http_client_connection_output(conn);
1225 }
1226 
http_client_request_send_more(struct http_client_request * req,bool pipelined)1227 int http_client_request_send_more(struct http_client_request *req,
1228 				  bool pipelined)
1229 {
1230 	struct http_client_connection *conn = req->conn;
1231 	struct http_client_context *cctx = conn->ppool->peer->cctx;
1232 	struct ostream *output = req->payload_output;
1233 	enum ostream_send_istream_result res;
1234 	const char *error;
1235 	uoff_t offset;
1236 
1237 	if (req->payload_finished)
1238 		return http_client_request_finish_payload_out(req);
1239 
1240 	i_assert(req->payload_input != NULL);
1241 	i_assert(req->payload_output != NULL);
1242 
1243 	io_remove(&conn->io_req_payload);
1244 
1245 	/* Chunked ostream needs to write to the parent stream's buffer */
1246 	offset = req->payload_input->v_offset;
1247 	o_stream_set_max_buffer_size(output, IO_BLOCK_SIZE);
1248 	res = o_stream_send_istream(output, req->payload_input);
1249 	o_stream_set_max_buffer_size(output, SIZE_MAX);
1250 
1251 	i_assert(req->payload_input->v_offset >= offset);
1252 	e_debug(req->event, "Send more (sent %"PRIuUOFF_T", buffered=%zu)",
1253 		(uoff_t)(req->payload_input->v_offset - offset),
1254 		o_stream_get_buffer_used_size(output));
1255 
1256 	switch (res) {
1257 	case OSTREAM_SEND_ISTREAM_RESULT_FINISHED:
1258 		/* Finished sending */
1259 		if (!req->payload_chunked &&
1260 		    (req->payload_input->v_offset - req->payload_offset) !=
1261 			req->payload_size) {
1262 			error = t_strdup_printf(
1263 				"BUG: stream '%s' input size changed: "
1264 				"%"PRIuUOFF_T"-%"PRIuUOFF_T" != %"PRIuUOFF_T,
1265 				i_stream_get_name(req->payload_input),
1266 				req->payload_input->v_offset,
1267 				req->payload_offset, req->payload_size);
1268 			i_error("%s", error); //FIXME: remove?
1269 			http_client_connection_lost(&conn, error);
1270 			return -1;
1271 		}
1272 
1273 		if (req->payload_wait) {
1274 			/* This chunk of input is finished
1275 			   (client needs to act; disable timeout) */
1276 			i_assert(!pipelined);
1277 			conn->output_locked = TRUE;
1278 			http_client_connection_stop_request_timeout(conn);
1279 			if (req->client != NULL && req->client->waiting)
1280 				io_loop_stop(req->client->ioloop);
1281 			return 0;
1282 		}
1283 		/* Finished sending payload */
1284 		return http_client_request_finish_payload_out(req);
1285 	case OSTREAM_SEND_ISTREAM_RESULT_WAIT_INPUT:
1286 		/* Input is blocking (client needs to act; disable timeout) */
1287 		conn->output_locked = TRUE;
1288 		if (!pipelined)
1289 			http_client_connection_stop_request_timeout(conn);
1290 		conn->io_req_payload = io_add_istream_to(
1291 			cctx->ioloop, req->payload_input,
1292 			http_client_request_payload_input, req);
1293 		return 1;
1294 	case OSTREAM_SEND_ISTREAM_RESULT_WAIT_OUTPUT:
1295 		/* Output is blocking (server needs to act; enable timeout) */
1296 		conn->output_locked = TRUE;
1297 		if (!pipelined)
1298 			http_client_connection_start_request_timeout(conn);
1299 		e_debug(req->event, "Partially sent payload");
1300 		return 0;
1301 	case OSTREAM_SEND_ISTREAM_RESULT_ERROR_INPUT:
1302 		/* We're in the middle of sending a request, so the connection
1303 		   will also have to be aborted */
1304 		error = t_strdup_printf("read(%s) failed: %s",
1305 					i_stream_get_name(req->payload_input),
1306 					i_stream_get_error(req->payload_input));
1307 
1308 		/* The payload stream assigned to this request is broken, fail
1309 		   this the request immediately */
1310 		http_client_request_error(&req,
1311 			HTTP_CLIENT_REQUEST_ERROR_BROKEN_PAYLOAD,
1312 			"Broken payload stream");
1313 
1314 		http_client_connection_lost(&conn, error);
1315 		return -1;
1316 	case OSTREAM_SEND_ISTREAM_RESULT_ERROR_OUTPUT:
1317 		/* Failed to send request */
1318 		http_client_connection_handle_output_error(conn);
1319 		return -1;
1320 	}
1321 	i_unreached();
1322 }
1323 
1324 static int
http_client_request_send_real(struct http_client_request * req,bool pipelined)1325 http_client_request_send_real(struct http_client_request *req, bool pipelined)
1326 {
1327 	const struct http_client_settings *set = &req->client->set;
1328 	struct http_client_connection *conn = req->conn;
1329 	string_t *rtext = t_str_new(256);
1330 	struct const_iovec iov[3];
1331 	int ret;
1332 
1333 	i_assert(!req->conn->output_locked);
1334 	i_assert(req->payload_output == NULL);
1335 
1336 	/* Create request line */
1337 	str_append(rtext, req->method);
1338 	str_append(rtext, " ");
1339 	str_append(rtext, req->target);
1340 	str_append(rtext, " HTTP/1.1\r\n");
1341 
1342 	/* Create special headers implicitly if not set explicitly using
1343 	   http_client_request_add_header() */
1344 	if (!req->have_hdr_host) {
1345 		str_append(rtext, "Host: ");
1346 		str_append(rtext, req->authority);
1347 		str_append(rtext, "\r\n");
1348 	}
1349 	if (!req->have_hdr_date) {
1350 		str_append(rtext, "Date: ");
1351 		str_append(rtext, http_date_create(req->date));
1352 		str_append(rtext, "\r\n");
1353 	}
1354 	if (!req->have_hdr_authorization &&
1355 		req->username != NULL && req->password != NULL) {
1356 		struct http_auth_credentials auth_creds;
1357 
1358 		http_auth_basic_credentials_init(&auth_creds,
1359 			req->username, req->password);
1360 
1361 		str_append(rtext, "Authorization: ");
1362 		http_auth_create_credentials(rtext, &auth_creds);
1363 		str_append(rtext, "\r\n");
1364 	}
1365 	if (http_client_request_to_proxy(req) &&
1366 		set->proxy_username != NULL && set->proxy_password != NULL) {
1367 		struct http_auth_credentials auth_creds;
1368 
1369 		http_auth_basic_credentials_init(&auth_creds,
1370 			set->proxy_username, set->proxy_password);
1371 
1372 		str_append(rtext, "Proxy-Authorization: ");
1373 		http_auth_create_credentials(rtext, &auth_creds);
1374 		str_append(rtext, "\r\n");
1375 	}
1376 	if (!req->have_hdr_user_agent && req->client->set.user_agent != NULL) {
1377 		str_printfa(rtext, "User-Agent: %s\r\n",
1378 			    req->client->set.user_agent);
1379 	}
1380 	if (!req->have_hdr_expect && req->payload_sync) {
1381 		str_append(rtext, "Expect: 100-continue\r\n");
1382 	}
1383 	if (req->payload_input != NULL && req->payload_chunked) {
1384 		// FIXME: can't do this for a HTTP/1.0 server
1385 		if (!req->have_hdr_body_spec)
1386 			str_append(rtext, "Transfer-Encoding: chunked\r\n");
1387 		req->payload_output =
1388 			http_transfer_chunked_ostream_create(conn->conn.output);
1389 		o_stream_set_finish_also_parent(req->payload_output, FALSE);
1390 	} else if (req->payload_input != NULL ||
1391 		req->payload_empty ||
1392 		strcasecmp(req->method, "POST") == 0 ||
1393 		strcasecmp(req->method, "PUT") == 0) {
1394 
1395 		/* Send Content-Length if we have specified a payload or when
1396 		   one is normally expected, even if it's 0 bytes. */
1397 		i_assert(req->payload_input != NULL || req->payload_size == 0);
1398 		if (!req->have_hdr_body_spec) {
1399 			str_printfa(rtext, "Content-Length: %"PRIuUOFF_T"\r\n",
1400 				req->payload_size);
1401 		}
1402 		if (req->payload_input != NULL) {
1403 			req->payload_output = conn->conn.output;
1404 			o_stream_ref(conn->conn.output);
1405 		}
1406 	}
1407 	if (!req->have_hdr_connection &&
1408 		!http_client_request_to_proxy(req)) {
1409 		/* RFC 2068, Section 19.7.1:
1410 
1411 		   A client MUST NOT send the Keep-Alive connection token to a
1412 		   proxy server as HTTP/1.0 proxy servers do not obey the rules
1413 		   of HTTP/1.1 for parsing the Connection header field.
1414 		 */
1415 		str_append(rtext, "Connection: Keep-Alive\r\n");
1416 	}
1417 
1418 	/* Request line + implicit headers */
1419 	iov[0].iov_base = str_data(rtext);
1420 	iov[0].iov_len = str_len(rtext);
1421 	/* Explicit headers */
1422 	if (req->headers != NULL) {
1423 		iov[1].iov_base = str_data(req->headers);
1424 		iov[1].iov_len = str_len(req->headers);
1425 	} else {
1426 		iov[1].iov_base = "";
1427 		iov[1].iov_len = 0;
1428 	}
1429 	/* End of header */
1430 	iov[2].iov_base = "\r\n";
1431 	iov[2].iov_len = 2;
1432 
1433 	req->state = HTTP_REQUEST_STATE_PAYLOAD_OUT;
1434 	req->payload_finished = FALSE;
1435 
1436 	req->send_attempts++;
1437 	if (req->first_sent_time.tv_sec == 0)
1438 		req->first_sent_time = ioloop_timeval;
1439 	req->sent_time = ioloop_timeval;
1440 	req->sent_lock_usecs = file_lock_wait_get_total_usecs();
1441 	req->sent_global_ioloop_usecs = ioloop_global_wait_usecs;
1442 	req->sent_http_ioloop_usecs =
1443 		io_wait_timer_get_usecs(req->conn->io_wait_timer);
1444 
1445 	ret = 1;
1446 	o_stream_cork(conn->conn.output);
1447 	req->request_offset = conn->conn.output->offset;
1448 
1449 	if (o_stream_sendv(conn->conn.output, iov, N_ELEMENTS(iov)) < 0) {
1450 		http_client_connection_handle_output_error(conn);
1451 		return -1;
1452 	}
1453 
1454 	e_debug(req->event, "Sent header");
1455 
1456 	if (req->payload_output != NULL) {
1457 		if (!req->payload_sync) {
1458 			ret = http_client_request_send_more(req, pipelined);
1459 			if (ret < 0)
1460 				return -1;
1461 		} else {
1462 			e_debug(req->event, "Waiting for 100-continue");
1463 			conn->output_locked = TRUE;
1464 		}
1465 	} else {
1466 		req->state = HTTP_REQUEST_STATE_WAITING;
1467 		if (!pipelined)
1468 			http_client_connection_start_request_timeout(req->conn);
1469 		conn->output_locked = FALSE;
1470 	}
1471 	if (conn->conn.output != NULL) {
1472 		i_assert(req->request_offset < conn->conn.output->offset);
1473 		req->bytes_out = conn->conn.output->offset - req->request_offset;
1474 		if (o_stream_uncork_flush(conn->conn.output) < 0) {
1475 			http_client_connection_handle_output_error(conn);
1476 			return -1;
1477 		}
1478 	}
1479 	return ret;
1480 }
1481 
http_client_request_send(struct http_client_request * req,bool pipelined)1482 int http_client_request_send(struct http_client_request *req, bool pipelined)
1483 {
1484 	int ret;
1485 
1486 	T_BEGIN {
1487 		ret = http_client_request_send_real(req, pipelined);
1488 	} T_END;
1489 
1490 	return ret;
1491 }
1492 
http_client_request_callback(struct http_client_request * req,struct http_response * response)1493 bool http_client_request_callback(struct http_client_request *req,
1494 				  struct http_response *response)
1495 {
1496 	http_client_request_callback_t *callback = req->callback;
1497 	unsigned int orig_attempts = req->attempts;
1498 
1499 	req->state = HTTP_REQUEST_STATE_GOT_RESPONSE;
1500 	req->last_status = response->status;
1501 
1502 	req->callback = NULL;
1503 	if (callback != NULL) {
1504 		struct http_response response_copy = *response;
1505 
1506 		if (req->attempts > 0 && !req->preserve_exact_reason) {
1507 			unsigned int total_msecs =
1508 				timeval_diff_msecs(&ioloop_timeval,
1509 						   &req->submit_time);
1510 			response_copy.reason = t_strdup_printf(
1511 				"%s (%u retries in %u.%03u secs)",
1512 				response_copy.reason, req->attempts,
1513 				total_msecs/1000, total_msecs%1000);
1514 		}
1515 
1516 		callback(&response_copy, req->context);
1517 		if (req->attempts != orig_attempts) {
1518 			/* Retrying */
1519 			req->callback = callback;
1520 			http_client_request_resubmit(req);
1521 			return FALSE;
1522 		} else {
1523 			/* Release payload early
1524 			   (prevents server/client deadlock in proxy) */
1525 			i_stream_unref(&req->payload_input);
1526 		}
1527 	}
1528 	return TRUE;
1529 }
1530 
1531 static bool
http_client_request_send_error(struct http_client_request * req,unsigned int status,const char * error)1532 http_client_request_send_error(struct http_client_request *req,
1533 			       unsigned int status, const char *error)
1534 {
1535 	http_client_request_callback_t *callback;
1536 	bool sending = (req->state == HTTP_REQUEST_STATE_PAYLOAD_OUT);
1537 	unsigned int orig_attempts = req->attempts;
1538 
1539 	req->state = HTTP_REQUEST_STATE_ABORTED;
1540 
1541 	callback = req->callback;
1542 	req->callback = NULL;
1543 	if (callback != NULL) {
1544 		struct http_response response;
1545 
1546 		http_response_init(&response, status, error);
1547 		(void)callback(&response, req->context);
1548 
1549 		if (req->attempts != orig_attempts) {
1550 			/* Retrying */
1551 			req->callback = callback;
1552 			http_client_request_resubmit(req);
1553 			return FALSE;
1554 		} else {
1555 			/* Release payload early
1556 			   (prevents server/client deadlock in proxy) */
1557 			if (!sending && req->payload_input != NULL)
1558 				i_stream_unref(&req->payload_input);
1559 		}
1560 	}
1561 	if (req->payload_wait) {
1562 		i_assert(req->client != NULL);
1563 		io_loop_stop(req->client->ioloop);
1564 	}
1565 	return TRUE;
1566 }
1567 
http_client_request_error_delayed(struct http_client_request ** _req)1568 void http_client_request_error_delayed(struct http_client_request **_req)
1569 {
1570 	struct http_client_request *req = *_req;
1571 	const char *error = req->delayed_error;
1572 	unsigned int status = req->delayed_error_status;
1573 	bool destroy;
1574 
1575 	i_assert(req->state == HTTP_REQUEST_STATE_ABORTED);
1576 
1577 	*_req = NULL;
1578 	req->delayed_error = NULL;
1579 	req->delayed_error_status = 0;
1580 
1581 	i_assert(error != NULL && status != 0);
1582 	destroy = http_client_request_send_error(req, status, error);
1583 	if (req->queue != NULL)
1584 		http_client_queue_drop_request(req->queue, req);
1585 	if (destroy)
1586 		http_client_request_destroy(&req);
1587 }
1588 
http_client_request_error(struct http_client_request ** _req,unsigned int status,const char * error)1589 void http_client_request_error(struct http_client_request **_req,
1590 			       unsigned int status, const char *error)
1591 {
1592 	struct http_client_request *req = *_req;
1593 
1594 	*_req = NULL;
1595 
1596 	i_assert(req->delayed_error_status == 0);
1597 	i_assert(req->state < HTTP_REQUEST_STATE_FINISHED);
1598 
1599 	req->state = HTTP_REQUEST_STATE_ABORTED;
1600 	req->last_status = status;
1601 
1602 	e_debug(http_client_request_result_event(req)->
1603 			set_name("http_request_finished")->event(),
1604 		"Error: %u %s", status, error);
1605 
1606 	if (req->queue != NULL)
1607 		http_client_queue_drop_request(req->queue, req);
1608 
1609 	if (req->client != NULL &&
1610 	    (!req->submitted ||
1611 	     req->state == HTTP_REQUEST_STATE_GOT_RESPONSE)) {
1612 		/* We're still in http_client_request_submit() or in the
1613 		   callback during a retry attempt. delay reporting the error,
1614 		   so the caller doesn't have to handle immediate or nested
1615 		   callbacks. */
1616 		req->delayed_error = p_strdup(req->pool, error);
1617 		req->delayed_error_status = status;
1618 		http_client_delay_request_error(req->client, req);
1619 	} else {
1620 		if (http_client_request_send_error(req, status, error))
1621 			http_client_request_destroy(&req);
1622 	}
1623 }
1624 
http_client_request_abort(struct http_client_request ** _req)1625 void http_client_request_abort(struct http_client_request **_req)
1626 {
1627 	struct http_client_request *req = *_req;
1628 	bool sending;
1629 
1630 	if (req == NULL)
1631 		return;
1632 
1633 	sending = (req->state == HTTP_REQUEST_STATE_PAYLOAD_OUT);
1634 
1635 	*_req = NULL;
1636 
1637 	if (req->state >= HTTP_REQUEST_STATE_FINISHED &&
1638 	    req->delayed_error_status == 0)
1639 		return;
1640 
1641 	req->callback = NULL;
1642 	req->state = HTTP_REQUEST_STATE_ABORTED;
1643 	if (req->last_status == 0)
1644 		req->last_status = HTTP_CLIENT_REQUEST_ERROR_ABORTED;
1645 
1646 	if (req->state > HTTP_REQUEST_STATE_NEW &&
1647 	    req->delayed_error_status == 0) {
1648 		e_debug(http_client_request_result_event(req)->
1649 			set_name("http_request_finished")->event(),
1650 			"Aborted");
1651 	}
1652 
1653 	/* Release payload early (prevents server/client deadlock in proxy) */
1654 	if (!sending && req->payload_input != NULL)
1655 		i_stream_unref(&req->payload_input);
1656 
1657 	if (req->queue != NULL)
1658 		http_client_queue_drop_request(req->queue, req);
1659 	if (req->payload_wait) {
1660 		i_assert(req->client != NULL);
1661 		i_assert(req->client->ioloop != NULL);
1662 		io_loop_stop(req->client->ioloop);
1663 	}
1664 	http_client_request_destroy(&req);
1665 }
1666 
http_client_request_finish(struct http_client_request * req)1667 void http_client_request_finish(struct http_client_request *req)
1668 {
1669 	if (req->state >= HTTP_REQUEST_STATE_FINISHED)
1670 		return;
1671 
1672 	i_assert(req->refcount > 0);
1673 
1674 	e_debug(http_client_request_result_event(req)->
1675 		set_name("http_request_finished")->event(),
1676 		"Finished");
1677 
1678 	req->callback = NULL;
1679 	req->state = HTTP_REQUEST_STATE_FINISHED;
1680 
1681 	if (req->queue != NULL)
1682 		http_client_queue_drop_request(req->queue, req);
1683 	if (req->payload_wait) {
1684 		i_assert(req->client != NULL);
1685 		i_assert(req->client->ioloop != NULL);
1686 		io_loop_stop(req->client->ioloop);
1687 	}
1688 	http_client_request_unref(&req);
1689 }
1690 
1691 static int
http_client_request_reset(struct http_client_request * req,bool rewind,const char ** error_r)1692 http_client_request_reset(struct http_client_request *req, bool rewind,
1693 			  const char **error_r)
1694 {
1695 	/* Rewind payload stream */
1696 	if (rewind && req->payload_input != NULL && req->payload_size > 0) {
1697 		if (req->payload_input->v_offset != req->payload_offset &&
1698 		    !req->payload_input->seekable) {
1699 			*error_r = "Cannot resend payload; "
1700 				   "stream is not seekable";
1701 			return -1;
1702 		}
1703 		i_stream_seek(req->payload_input, req->payload_offset);
1704 	}
1705 
1706 	/* Drop payload output stream from previous attempt */
1707 	o_stream_unref(&req->payload_output);
1708 
1709 	/* Reset payload state */
1710 	req->payload_finished = FALSE;
1711 
1712 	return 0;
1713 }
1714 
http_client_request_redirect(struct http_client_request * req,unsigned int status,const char * location)1715 void http_client_request_redirect(struct http_client_request *req,
1716 				  unsigned int status, const char *location)
1717 {
1718 	struct http_url *url;
1719 	const char *error, *target, *origin_url;
1720 
1721 	i_assert(req->client != NULL);
1722 	i_assert(!req->payload_wait);
1723 
1724 	req->last_status = status;
1725 
1726 	/* parse URL */
1727 	if (http_url_parse(location, NULL, 0,
1728 			   pool_datastack_create(), &url, &error) < 0) {
1729 		http_client_request_error(
1730 			&req, HTTP_CLIENT_REQUEST_ERROR_INVALID_REDIRECT,
1731 			t_strdup_printf("Invalid redirect location: %s",
1732 					error));
1733 		return;
1734 	}
1735 
1736 	i_assert(req->redirects <= req->client->set.max_redirects);
1737 	if (++req->redirects > req->client->set.max_redirects) {
1738 		if (req->client->set.max_redirects > 0) {
1739 			http_client_request_error(
1740 				&req,
1741 				HTTP_CLIENT_REQUEST_ERROR_INVALID_REDIRECT,
1742 				t_strdup_printf(
1743 					"Redirected more than %d times",
1744 					req->client->set.max_redirects));
1745 		} else {
1746 			http_client_request_error(
1747 				&req,
1748 				HTTP_CLIENT_REQUEST_ERROR_INVALID_REDIRECT,
1749 				"Redirect refused");
1750 		}
1751 		return;
1752 	}
1753 
1754 	if (http_client_request_reset(req, (status != 303), &error) < 0) {
1755 		http_client_request_error(
1756 			&req, HTTP_CLIENT_REQUEST_ERROR_ABORTED,
1757 			t_strdup_printf("Redirect failed: %s", error));
1758 		return;
1759 	}
1760 
1761 	target = http_url_create_target(url);
1762 
1763 	http_url_copy(req->pool, &req->origin_url, url);
1764 	req->target = p_strdup(req->pool, target);
1765 
1766 	req->host = NULL;
1767 
1768 	origin_url = http_url_create(&req->origin_url);
1769 
1770 	e_debug(http_client_request_result_event(req)->
1771 			set_name("http_request_redirected")->event(),
1772 		"Redirecting to %s%s (redirects=%u)",
1773 		origin_url, target, req->redirects);
1774 
1775 	req->label = p_strdup_printf(req->pool, "[%s %s%s]",
1776 				     req->method, origin_url, req->target);
1777 
1778 	/* RFC 7231, Section 6.4.4:
1779 
1780 	   -> A 303 `See Other' redirect status response is handled a bit
1781 	   differently. Basically, the response content is located elsewhere,
1782 	   but the original (POST) request is handled already.
1783 	 */
1784 	if (status == 303 && strcasecmp(req->method, "HEAD") != 0 &&
1785 	    strcasecmp(req->method, "GET") != 0) {
1786 		// FIXME: should we provide the means to skip this step? The
1787 		// original request was already handled at this point.
1788 		req->method = p_strdup(req->pool, "GET");
1789 
1790 		/* drop payload */
1791 		i_stream_unref(&req->payload_input);
1792 		req->payload_size = 0;
1793 		req->payload_offset = 0;
1794 	}
1795 
1796 	/* Resubmit */
1797 	req->state = HTTP_REQUEST_STATE_NEW;
1798 	http_client_request_do_submit(req);
1799 }
1800 
http_client_request_resubmit(struct http_client_request * req)1801 void http_client_request_resubmit(struct http_client_request *req)
1802 {
1803 	const char *error;
1804 
1805 	i_assert(!req->payload_wait);
1806 
1807 	e_debug(req->event, "Resubmitting request");
1808 
1809 	if (http_client_request_reset(req, TRUE, &error) < 0) {
1810 		http_client_request_error(
1811 			&req, HTTP_CLIENT_REQUEST_ERROR_ABORTED,
1812 			t_strdup_printf("Resubmission failed: %s", error));
1813 		return;
1814 	}
1815 
1816 	req->peer = NULL;
1817 	req->state = HTTP_REQUEST_STATE_QUEUED;
1818 	req->redirects = 0;
1819 	req->last_status = 0;
1820 	http_client_host_submit_request(req->host, req);
1821 }
1822 
http_client_request_retry(struct http_client_request * req,unsigned int status,const char * error)1823 void http_client_request_retry(struct http_client_request *req,
1824 			       unsigned int status, const char *error)
1825 {
1826 	if (req->client == NULL || req->client->set.no_auto_retry ||
1827 	    !http_client_request_try_retry(req))
1828 		http_client_request_error(&req, status, error);
1829 }
1830 
http_client_request_try_retry(struct http_client_request * req)1831 bool http_client_request_try_retry(struct http_client_request *req)
1832 {
1833 	/* Don't ever retry if we're sending data in small blocks via
1834 	   http_client_request_send_payload() and we're not waiting for a
1835 	   100 continue (there's no way to rewind the payload for a retry)
1836 	 */
1837 	if (req->payload_wait &&
1838 	    (!req->payload_sync || req->payload_sync_continue))
1839 		return FALSE;
1840 	/* Limit the number of attempts for each request */
1841 	if (req->attempts+1 >= req->max_attempts)
1842 		return FALSE;
1843 	req->attempts++;
1844 
1845 	e_debug(http_client_request_result_event(req)->
1846 		set_name("http_request_retried")->event(),
1847 		"Retrying (attempts=%d)", req->attempts);
1848 
1849 	if (req->callback != NULL)
1850 		http_client_request_resubmit(req);
1851 	return TRUE;
1852 }
1853 
1854 #undef http_client_request_set_destroy_callback
http_client_request_set_destroy_callback(struct http_client_request * req,void (* callback)(void *),void * context)1855 void http_client_request_set_destroy_callback(struct http_client_request *req,
1856 					      void (*callback)(void *),
1857 					      void *context)
1858 {
1859 	req->destroy_callback = callback;
1860 	req->destroy_context = context;
1861 }
1862 
http_client_request_start_tunnel(struct http_client_request * req,struct http_client_tunnel * tunnel)1863 void http_client_request_start_tunnel(struct http_client_request *req,
1864 				      struct http_client_tunnel *tunnel)
1865 {
1866 	struct http_client_connection *conn = req->conn;
1867 
1868 	i_assert(req->state == HTTP_REQUEST_STATE_GOT_RESPONSE);
1869 
1870 	http_client_connection_start_tunnel(&conn, tunnel);
1871 }
1872