1 /* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
2 
3 #include "lib.h"
4 #include "str.h"
5 #include "array.h"
6 #include "istream.h"
7 #include "ostream-private.h"
8 #include "http-date.h"
9 #include "http-transfer.h"
10 #include "http-server-private.h"
11 
12 struct http_server_response_payload {
13 	struct http_server_response *resp;
14 	struct const_iovec *iov;
15 	unsigned int iov_count, iov_idx;
16 	size_t iov_pos;
17 };
18 
19 /*
20  * Response
21  */
22 
http_server_response_update_event(struct http_server_response * resp)23 static void http_server_response_update_event(struct http_server_response *resp)
24 {
25 	event_add_int(resp->event, "status", resp->status);
26 	event_set_append_log_prefix(resp->event,
27 				    t_strdup_printf("%u response: ",
28 						    resp->status));
29 }
30 
31 struct http_server_response *
http_server_response_create(struct http_server_request * req,unsigned int status,const char * reason)32 http_server_response_create(struct http_server_request *req,
33 			    unsigned int status, const char *reason)
34 {
35 	struct http_server_response *resp;
36 
37 	i_assert(req->state < HTTP_SERVER_REQUEST_STATE_SENT_RESPONSE);
38 
39 	if (req->response == NULL) {
40 		resp = req->response = p_new(req->pool,
41 					     struct http_server_response, 1);
42 	} else {
43 		/* Was already composing a response, but decided to
44 		   start a new one (would usually be a failure response)
45 		 */
46 		resp = req->response;
47 
48 		ARRAY_TYPE(string) perm_headers = resp->perm_headers;
49 		i_zero(&resp->perm_headers);
50 
51 		http_server_response_request_free(resp);
52 		i_zero(resp);
53 
54 		resp->perm_headers = perm_headers;
55 	}
56 
57 	resp->request = req;
58 	resp->status = status;
59 	resp->reason = p_strdup(req->pool, reason);
60 	resp->headers = str_new(default_pool, 256);
61 	resp->date = (time_t)-1;
62 	resp->event = event_create(req->event);
63 	http_server_response_update_event(resp);
64 
65 	if (array_is_created(&resp->perm_headers)) {
66 		unsigned int i, count;
67 		char *const *headers = array_get(&resp->perm_headers, &count);
68 		for (i = 0; i < count; i += 2)
69 			http_server_response_add_header(resp, headers[i],
70 							headers[i+1]);
71 	}
72 	return resp;
73 }
74 
http_server_response_request_free(struct http_server_response * resp)75 void http_server_response_request_free(struct http_server_response *resp)
76 {
77 	e_debug(resp->event, "Free");
78 
79 	/* Cannot be destroyed while payload output stream still exists */
80 	i_assert(resp->payload_stream == NULL);
81 
82 	i_stream_unref(&resp->payload_input);
83 	o_stream_unref(&resp->payload_output);
84 	event_unref(&resp->event);
85 	str_free(&resp->headers);
86 
87 	if (array_is_created(&resp->perm_headers)) {
88 		char *headers;
89 
90 		array_foreach_elem(&resp->perm_headers, headers)
91 			i_free(headers);
92 		array_free(&resp->perm_headers);
93 	}
94 }
95 
http_server_response_request_destroy(struct http_server_response * resp)96 void http_server_response_request_destroy(struct http_server_response *resp)
97 {
98 	e_debug(resp->event, "Destroy");
99 
100 	if (resp->payload_stream != NULL)
101 		http_server_ostream_response_destroyed(resp->payload_stream);
102 }
103 
http_server_response_request_abort(struct http_server_response * resp,const char * reason)104 void http_server_response_request_abort(struct http_server_response *resp,
105 					const char *reason)
106 {
107 	if (reason == NULL)
108 		e_debug(resp->event, "Abort");
109 	else
110 		e_debug(resp->event, "Abort: %s", reason);
111 
112 	if (resp->payload_stream != NULL) {
113 		http_server_ostream_set_error(resp->payload_stream,
114 					      EPIPE, reason);
115 	}
116 }
117 
http_server_response_ref(struct http_server_response * resp)118 void http_server_response_ref(struct http_server_response *resp)
119 {
120 	http_server_request_ref(resp->request);
121 }
122 
http_server_response_unref(struct http_server_response ** _resp)123 bool http_server_response_unref(struct http_server_response **_resp)
124 {
125 	struct http_server_response *resp = *_resp;
126 	struct http_server_request *req;
127 
128 	*_resp = NULL;
129 	if (resp == NULL)
130 		return FALSE;
131 
132 	req = resp->request;
133 	return http_server_request_unref(&req);
134 }
135 
http_server_response_add_header(struct http_server_response * resp,const char * key,const char * value)136 void http_server_response_add_header(struct http_server_response *resp,
137 				     const char *key, const char *value)
138 {
139 	i_assert(!resp->submitted);
140 	i_assert(strchr(key, '\r') == NULL && strchr(key, '\n') == NULL);
141 	i_assert(strchr(value, '\r') == NULL && strchr(value, '\n') == NULL);
142 
143 	/* Mark presence of special headers */
144 	switch (key[0]) {
145 	case 'c': case 'C':
146 		if (strcasecmp(key, "Connection") == 0)
147 			resp->have_hdr_connection = TRUE;
148 		else 	if (strcasecmp(key, "Content-Length") == 0)
149 			resp->have_hdr_body_spec = TRUE;
150 		break;
151 	case 'd': case 'D':
152 		if (strcasecmp(key, "Date") == 0)
153 			resp->have_hdr_date = TRUE;
154 		break;
155 	case 't': case 'T':
156 		if (strcasecmp(key, "Transfer-Encoding") == 0)
157 			resp->have_hdr_body_spec = TRUE;
158 		break;
159 	}
160 	str_printfa(resp->headers, "%s: %s\r\n", key, value);
161 }
162 
http_server_response_update_status(struct http_server_response * resp,unsigned int status,const char * reason)163 void http_server_response_update_status(struct http_server_response *resp,
164 					unsigned int status,
165 					const char *reason)
166 {
167 	i_assert(!resp->submitted);
168 	resp->status = status;
169 	/* Free not called because pool is alloconly */
170 	resp->reason = p_strdup(resp->request->pool, reason);
171 }
172 
http_server_response_set_date(struct http_server_response * resp,time_t date)173 void http_server_response_set_date(struct http_server_response *resp,
174 				   time_t date)
175 {
176 	i_assert(!resp->submitted);
177 
178 	resp->date = date;
179 }
180 
http_server_response_set_payload(struct http_server_response * resp,struct istream * input)181 void http_server_response_set_payload(struct http_server_response *resp,
182 				      struct istream *input)
183 {
184 	int ret;
185 
186 	i_assert(!resp->submitted);
187 	i_assert(resp->payload_input == NULL);
188 	i_assert(resp->payload_stream == NULL);
189 
190 	i_stream_ref(input);
191 	resp->payload_input = input;
192 	if ((ret = i_stream_get_size(input, TRUE, &resp->payload_size)) <= 0) {
193 		if (ret < 0) {
194 			e_error(resp->event, "i_stream_get_size(%s) failed: %s",
195 				i_stream_get_name(input),
196 				i_stream_get_error(input));
197 		}
198 		resp->payload_size = 0;
199 		resp->payload_chunked = TRUE;
200 	} else {
201 		i_assert(input->v_offset <= resp->payload_size);
202 		resp->payload_size -= input->v_offset;
203 	}
204 	resp->payload_offset = input->v_offset;
205 }
206 
http_server_response_set_payload_data(struct http_server_response * resp,const unsigned char * data,size_t size)207 void http_server_response_set_payload_data(struct http_server_response *resp,
208 					   const unsigned char *data,
209 					   size_t size)
210 {
211 	struct istream *input;
212 	unsigned char *payload_data;
213 
214 	i_assert(!resp->submitted);
215 	i_assert(resp->payload_input == NULL);
216 	i_assert(resp->payload_stream == NULL);
217 
218 	if (size == 0)
219 		return;
220 
221 	payload_data = p_malloc(resp->request->pool, size);
222 	memcpy(payload_data, data, size);
223 	input = i_stream_create_from_data(payload_data, size);
224 
225 	http_server_response_set_payload(resp, input);
226 	i_stream_unref(&input);
227 }
228 
229 struct ostream *
http_server_response_get_payload_output(struct http_server_response * resp,size_t max_buffer_size,bool blocking)230 http_server_response_get_payload_output(struct http_server_response *resp,
231 					size_t max_buffer_size, bool blocking)
232 {
233 	struct http_server_request *req = resp->request;
234 	struct http_server_connection *conn = req->conn;
235 	struct ostream *output;
236 
237 	i_assert(conn != NULL);
238 	i_assert(!resp->submitted);
239 	i_assert(resp->payload_input == NULL);
240 	i_assert(resp->payload_stream == NULL);
241 
242 	output = http_server_ostream_create(resp, max_buffer_size, blocking);
243 	o_stream_set_name(output,
244 		t_strdup_printf("(conn %s: request %s: %u response payload)",
245 				conn->conn.label,
246 				http_server_request_label(req), resp->status));
247 	return output;
248 }
249 
http_server_response_add_auth(struct http_server_response * resp,const struct http_auth_challenge * chlng)250 void http_server_response_add_auth(struct http_server_response *resp,
251 				   const struct http_auth_challenge *chlng)
252 {
253 	struct http_auth_challenge *new;
254 	pool_t pool = resp->request->pool;
255 
256 	if (!array_is_created(&resp->auth_challenges))
257 		p_array_init(&resp->auth_challenges, pool, 4);
258 
259 	new = array_append_space(&resp->auth_challenges);
260 	http_auth_challenge_copy(pool, new, chlng);
261 }
262 
http_server_response_add_auth_basic(struct http_server_response * resp,const char * realm)263 void http_server_response_add_auth_basic(struct http_server_response *resp,
264 					 const char *realm)
265 {
266 	struct http_auth_challenge chlng;
267 
268 	http_auth_basic_challenge_init(&chlng, realm);
269 	http_server_response_add_auth(resp, &chlng);
270 }
271 
272 static void
http_server_response_do_submit(struct http_server_response * resp)273 http_server_response_do_submit(struct http_server_response *resp)
274 {
275 	i_assert(!resp->submitted);
276 	if (resp->date == (time_t)-1)
277 		resp->date = ioloop_time;
278 	resp->submitted = TRUE;
279 	http_server_request_submit_response(resp->request);
280 }
281 
http_server_response_submit(struct http_server_response * resp)282 void http_server_response_submit(struct http_server_response *resp)
283 {
284 	e_debug(resp->event, "Submitted");
285 
286 	http_server_response_do_submit(resp);
287 }
288 
http_server_response_submit_close(struct http_server_response * resp)289 void http_server_response_submit_close(struct http_server_response *resp)
290 {
291 	http_server_request_connection_close(resp->request, TRUE);
292 	http_server_response_submit(resp);
293 }
294 
http_server_response_submit_tunnel(struct http_server_response * resp,http_server_tunnel_callback_t callback,void * context)295 void http_server_response_submit_tunnel(struct http_server_response *resp,
296 					http_server_tunnel_callback_t callback,
297 					void *context)
298 {
299 	e_debug(resp->event, "Started tunnelling");
300 
301 	resp->tunnel_callback = callback;
302 	resp->tunnel_context = context;
303 	http_server_request_connection_close(resp->request, TRUE);
304 	http_server_response_do_submit(resp);
305 }
306 
307 static int
http_server_response_flush_payload(struct http_server_response * resp)308 http_server_response_flush_payload(struct http_server_response *resp)
309 {
310 	struct http_server_request *req = resp->request;
311 	struct http_server_connection *conn = req->conn;
312 	int ret;
313 
314 	if (resp->payload_output != conn->conn.output &&
315 	    (ret = o_stream_finish(resp->payload_output)) <= 0) {
316 		if (ret < 0)
317 			http_server_connection_handle_output_error(conn);
318 		else
319 			http_server_connection_start_idle_timeout(conn);
320 		return ret;
321 	}
322 
323 	return 1;
324 }
325 
http_server_response_request_finished(struct http_server_response * resp)326 void http_server_response_request_finished(struct http_server_response *resp)
327 {
328 	e_debug(resp->event, "Finished");
329 
330 	if (resp->payload_stream != NULL)
331 		http_server_ostream_response_finished(resp->payload_stream);
332 }
333 
http_server_response_finish_payload_out(struct http_server_response * resp)334 int http_server_response_finish_payload_out(struct http_server_response *resp)
335 {
336 	struct http_server_request *req = resp->request;
337 	struct http_server_connection *conn = req->conn;
338 	int ret;
339 
340 	if (req->state >= HTTP_SERVER_REQUEST_STATE_FINISHED)
341 		return 1;
342 
343 	resp->payload_finished = TRUE;
344 
345 	if (resp->payload_output != NULL) {
346 		ret = http_server_response_flush_payload(resp);
347 		if (ret < 0)
348 			return -1;
349 		if (ret == 0) {
350 			e_debug(resp->event,
351 				"Not quite finished sending payload");
352 			return 0;
353 		}
354 		o_stream_unref(&resp->payload_output);
355 		resp->payload_output = NULL;
356 	}
357 
358 	e_debug(resp->event, "Finished sending payload");
359 
360 	http_server_connection_ref(conn);
361 	conn->output_locked = FALSE;
362 	if (conn->conn.output != NULL && !conn->conn.output->closed) {
363 		if (resp->payload_corked &&
364 			o_stream_uncork_flush(conn->conn.output) < 0)
365 			http_server_connection_handle_output_error(conn);
366 		o_stream_set_flush_callback(conn->conn.output,
367 					    http_server_connection_output,
368 					    conn);
369 	}
370 
371 	if (conn->request_queue_head == NULL ||
372 	    (conn->request_queue_head->state !=
373 	     HTTP_SERVER_REQUEST_STATE_PROCESSING))
374 		http_server_connection_start_idle_timeout(conn);
375 
376 	http_server_request_finished(resp->request);
377 	http_server_connection_unref(&conn);
378 	return 1;
379 }
380 
381 static int
http_server_response_output_payload(struct http_server_response ** _resp,const unsigned char * data,size_t size)382 http_server_response_output_payload(struct http_server_response **_resp,
383 				    const unsigned char *data, size_t size)
384 {
385 	struct http_server_response *resp = *_resp;
386 	struct http_server_request *req = resp->request;
387 	struct ostream *output;
388 	ssize_t sret;
389 	int ret;
390 
391 	i_assert(req->state < HTTP_SERVER_REQUEST_STATE_SUBMITTED_RESPONSE ||
392 		 req->state == HTTP_SERVER_REQUEST_STATE_PAYLOAD_OUT);
393 
394 	http_server_response_ref(resp);
395 
396 	if (resp->payload_stream == NULL) {
397 		output = http_server_response_get_payload_output(
398 			resp, IO_BLOCK_SIZE, TRUE);
399 	} else {
400 		output = http_server_ostream_get_output(resp->payload_stream);
401 	}
402 
403 	if (data != NULL) {
404 		if ((sret = o_stream_send(output, data, size)) < 0) {
405 			*_resp = NULL;
406 			o_stream_destroy(&output);
407 			http_server_response_unref(&resp);
408 			return -1;
409 		}
410 		i_assert((size_t)sret == size);
411 	} else {
412 		if ((ret = o_stream_finish(output)) < 0) {
413 			*_resp = NULL;
414 			o_stream_destroy(&output);
415 			http_server_response_unref(&resp);
416 			return -1;
417 		}
418 		i_assert(ret > 0);
419 	}
420 
421 	switch (req->state) {
422 	case HTTP_SERVER_REQUEST_STATE_FINISHED:
423 		ret = 1;
424 		break;
425 	case HTTP_SERVER_REQUEST_STATE_ABORTED:
426 		e_debug(resp->event,
427 			"Request aborted while sending blocking payload");
428 		ret = -1;
429 		break;
430 	default:
431 		ret = 0;
432 		break;
433 	}
434 
435 	if (data == NULL)
436 		o_stream_destroy(&output);
437 
438 	/* Callback may have messed with our pointer, so unref using local
439 	   variable */
440 	if (!http_server_response_unref(&resp))
441 		*_resp = NULL;
442 
443 	/* Return status */
444 	return ret;
445 }
446 
http_server_response_send_payload(struct http_server_response ** _resp,const unsigned char * data,size_t size)447 int http_server_response_send_payload(struct http_server_response **_resp,
448 				      const unsigned char *data, size_t size)
449 {
450 	struct http_server_response *resp = *_resp;
451 	int ret;
452 
453 	resp->payload_corked = TRUE;
454 
455 	i_assert(data != NULL);
456 
457 	ret = http_server_response_output_payload(&resp, data, size);
458 	if (ret < 0)
459 		*_resp = NULL;
460 	else {
461 		i_assert(ret == 0);
462 		i_assert(resp != NULL);
463 	}
464 	return ret;
465 }
466 
http_server_response_finish_payload(struct http_server_response ** _resp)467 int http_server_response_finish_payload(struct http_server_response **_resp)
468 {
469 	struct http_server_response *resp = *_resp;
470 	int ret;
471 
472 	*_resp = NULL;
473 	ret = http_server_response_output_payload(&resp, NULL, 0);
474 	i_assert(ret != 0);
475 	return ret < 0 ? -1 : 0;
476 }
477 
http_server_response_abort_payload(struct http_server_response ** _resp)478 void http_server_response_abort_payload(struct http_server_response **_resp)
479 {
480 	struct http_server_response *resp = *_resp;
481 	struct http_server_request *req = resp->request;
482 
483 	*_resp = NULL;
484 
485 	http_server_request_abort(&req, "Aborted sending response payload");
486 }
487 
488 static void
http_server_response_payload_input(struct http_server_response * resp)489 http_server_response_payload_input(struct http_server_response *resp)
490 {
491 	struct http_server_connection *conn = resp->request->conn;
492 
493 	io_remove(&conn->io_resp_payload);
494 
495 	(void)http_server_connection_output(conn);
496 }
497 
http_server_response_send_more(struct http_server_response * resp)498 int http_server_response_send_more(struct http_server_response *resp)
499 {
500 	struct http_server_connection *conn = resp->request->conn;
501 	struct ostream *output = resp->payload_output;
502 	enum ostream_send_istream_result res;
503 
504 	i_assert(resp->payload_output != NULL);
505 
506 	if (resp->payload_finished) {
507 		e_debug(resp->event, "Finish sending payload (more)");
508 		return http_server_response_finish_payload_out(resp);
509 	}
510 
511 	if (resp->payload_stream != NULL) {
512 		conn->output_locked = TRUE;
513 		return http_server_ostream_continue(resp->payload_stream);
514 	}
515 
516 	i_assert(resp->payload_input != NULL);
517 	io_remove(&conn->io_resp_payload);
518 
519 	/* Chunked ostream needs to write to the parent stream's buffer */
520 	o_stream_set_max_buffer_size(output, IO_BLOCK_SIZE);
521 	res = o_stream_send_istream(output, resp->payload_input);
522 	o_stream_set_max_buffer_size(output, SIZE_MAX);
523 
524 	switch (res) {
525 	case OSTREAM_SEND_ISTREAM_RESULT_FINISHED:
526 		/* Finished sending */
527 		if (!resp->payload_chunked &&
528 		    (resp->payload_input->v_offset - resp->payload_offset) !=
529 			resp->payload_size) {
530 			e_error(resp->event,
531 				"Payload stream %s size changed unexpectedly",
532 				i_stream_get_name(resp->payload_input));
533 			http_server_connection_close(
534 				&conn, "Payload read failure");
535 			return -1;
536 		}
537 		/* Finished sending payload */
538 		e_debug(resp->event, "Finish sending payload");
539 		return http_server_response_finish_payload_out(resp);
540 	case OSTREAM_SEND_ISTREAM_RESULT_WAIT_INPUT:
541 		/* Input is blocking (server needs to act; disable timeout) */
542 		conn->output_locked = TRUE;
543 		http_server_connection_stop_idle_timeout(conn);
544 		conn->io_resp_payload = io_add_istream(resp->payload_input,
545 			http_server_response_payload_input, resp);
546 		return 1;
547 	case OSTREAM_SEND_ISTREAM_RESULT_WAIT_OUTPUT:
548 		/* Output is blocking (client needs to act; enable timeout) */
549 		conn->output_locked = TRUE;
550 		http_server_connection_start_idle_timeout(conn);
551 		o_stream_set_flush_pending(output, TRUE);
552 		//e_debug(resp->event, "Partially sent payload");
553 		return 0;
554 	case OSTREAM_SEND_ISTREAM_RESULT_ERROR_INPUT:
555 		/* We're in the middle of sending a response, so the connection
556 		   will also have to be aborted */
557 		e_error(resp->event, "read(%s) failed: %s",
558 			i_stream_get_name(resp->payload_input),
559 			i_stream_get_error(resp->payload_input));
560 		http_server_connection_close(&conn,
561 			"Payload read failure");
562 		return -1;
563 	case OSTREAM_SEND_ISTREAM_RESULT_ERROR_OUTPUT:
564 		/* Failed to send response */
565 		http_server_connection_handle_output_error(conn);
566 		return -1;
567 	}
568 	i_unreached();
569 }
570 
http_server_response_send_real(struct http_server_response * resp)571 static int http_server_response_send_real(struct http_server_response *resp)
572 {
573 	struct http_server_request *req = resp->request;
574 	struct http_server_connection *conn = req->conn;
575 	string_t *rtext = t_str_new(256);
576 	struct const_iovec iov[3];
577 	uoff_t content_length = 0;
578 	bool chunked = FALSE, send_content_length = FALSE, close = FALSE;
579 	bool is_head = http_request_method_is(&req->req, "HEAD");
580 	int ret;
581 
582 	i_assert(!conn->output_locked);
583 
584 	/* Determine response payload to send */
585 	if (resp->payload_input != NULL) {
586 		i_assert(resp->tunnel_callback == NULL &&
587 			 resp->status / 100 != 1 &&
588 			 resp->status != 204 && resp->status != 304);
589 		if (resp->payload_chunked) {
590 			if (http_server_request_version_equals(req, 1, 0)) {
591 				/* Connection close marks end of payload
592 				 */
593 				close = TRUE;
594 			} else {
595 				/* Input stream with unknown size */
596 				chunked = TRUE;
597 			}
598 		} else {
599 			/* Send Content-Length if we have specified a payload,
600 			   even if it's 0 bytes. */
601 			content_length = resp->payload_size;
602 			send_content_length = TRUE;
603 		}
604 	} else if (resp->payload_stream != NULL) {
605 		/* HTTP payload output stream */
606 		if (!http_server_ostream_get_size(resp->payload_stream,
607 						  &content_length)) {
608 			/* size not known at this point */
609 			chunked = TRUE;
610 		} else {
611 			/* output stream already finished, so data is
612 			   pre-buffered */
613 			send_content_length = TRUE;
614 		}
615 	} else if (resp->tunnel_callback == NULL && resp->status / 100 != 1 &&
616 		   resp->status != 204 && resp->status != 304 && !is_head) {
617 		/* RFC 7230, Section 3.3: Message Body
618 
619 		   Responses to the HEAD request method (Section 4.3.2 of
620 		   [RFC7231]) never include a message body because the
621 		   associated response header fields (e.g., Transfer-Encoding,
622 		   Content-Length, etc.), if present, indicate only what their
623 		   values would have been if the request method had been GET
624 	           (Section 4.3.1 of [RFC7231]). 2xx (Successful) responses to a
625 		   CONNECT request method (Section 4.3.6 of [RFC7231]) switch to
626 		   tunnel mode instead of having a message body. All 1xx
627 		   (Informational), 204 (No Content), and 304 (Not Modified)
628 		   responses do not include a message body. All other responses
629 		   do include a message body, although the body might be of zero
630 		   length.
631 
632 		   RFC 7230, Section 3.3.2: Content-Length
633 
634 		   A server MUST NOT send a Content-Length header field in any
635 		   2xx (Successful) response to a CONNECT request (Section 4.3.6
636 		   of [RFC7231]).
637 
638 		   -> Create empty body if it is missing.
639 		 */
640 		send_content_length = TRUE;
641 	}
642 
643 	/* Initialize output payload stream if needed */
644 	if (is_head) {
645 		e_debug(resp->event, "A HEAD response has no payload");
646 	} else if (chunked) {
647 		i_assert(resp->payload_input != NULL ||
648 			 resp->payload_stream != NULL);
649 
650 		e_debug(resp->event, "Will send payload in chunks");
651 
652 		resp->payload_output =
653 			http_transfer_chunked_ostream_create(conn->conn.output);
654 	} else if (send_content_length) {
655 		i_assert(resp->payload_input != NULL || content_length == 0 ||
656 			 resp->payload_stream != NULL);
657 
658 		e_debug(resp->event,
659 			"Will send payload with explicit size %"PRIuUOFF_T,
660 			content_length);
661 
662 		if (content_length > 0) {
663 			resp->payload_output = conn->conn.output;
664 			o_stream_ref(conn->conn.output);
665 		}
666 	} else if (close) {
667 		i_assert(resp->payload_input != NULL);
668 
669 		e_debug(resp->event,
670 			"Will close connection after sending payload "
671 			"(HTTP/1.0)");
672 
673 		resp->payload_output = conn->conn.output;
674 		o_stream_ref(conn->conn.output);
675 	} else {
676 		e_debug(resp->event, "Response has no payload");
677 	}
678 
679 	/* Create status line */
680 	str_append(rtext, "HTTP/1.1 ");
681 	str_printfa(rtext, "%u", resp->status);
682 	str_append(rtext, " ");
683 	str_append(rtext, resp->reason);
684 
685 	/* Create special headers implicitly if not set explicitly using
686 	   http_server_response_add_header() */
687 	if (!resp->have_hdr_date) {
688 		str_append(rtext, "\r\nDate: ");
689 		str_append(rtext, http_date_create(resp->date));
690 		str_append(rtext, "\r\n");
691 	}
692 	if (array_is_created(&resp->auth_challenges)) {
693 		str_append(rtext, "WWW-Authenticate: ");
694 		http_auth_create_challenges(rtext, &resp->auth_challenges);
695 		str_append(rtext, "\r\n");
696 	}
697 	if (chunked) {
698 		if (!resp->have_hdr_body_spec)
699 			str_append(rtext, "Transfer-Encoding: chunked\r\n");
700 	} else if (send_content_length) {
701 		if (!resp->have_hdr_body_spec) {
702 			str_printfa(rtext, "Content-Length: %"PRIuUOFF_T"\r\n",
703 				    content_length);
704 		}
705 	}
706 	if (!resp->have_hdr_connection) {
707 		close = (close || req->req.connection_close ||
708 			 req->connection_close || req->conn->input_broken);
709 		if (close && resp->tunnel_callback == NULL)
710 			str_append(rtext, "Connection: close\r\n");
711 		else if (http_server_request_version_equals(req, 1, 0))
712 			str_append(rtext, "Connection: Keep-Alive\r\n");
713 	}
714 
715 	/* Status line + implicit headers */
716 	iov[0].iov_base = str_data(rtext);
717 	iov[0].iov_len = str_len(rtext);
718 	/* Explicit headers */
719 	iov[1].iov_base = str_data(resp->headers);
720 	iov[1].iov_len = str_len(resp->headers);
721 	/* End of header */
722 	iov[2].iov_base = "\r\n";
723 	iov[2].iov_len = 2;
724 
725 	req->state = HTTP_SERVER_REQUEST_STATE_PAYLOAD_OUT;
726 	o_stream_cork(conn->conn.output);
727 
728 	if (o_stream_sendv(conn->conn.output, iov, N_ELEMENTS(iov)) < 0) {
729 		http_server_connection_handle_output_error(conn);
730 		return -1;
731 	}
732 
733 	e_debug(resp->event, "Sent header");
734 
735 	if (resp->payload_stream != NULL)
736 		http_server_ostream_output_available(resp->payload_stream);
737 	if (resp->payload_output != NULL) {
738 		/* Non-blocking payload */
739 		ret = http_server_response_send_more(resp);
740 		if (ret < 0)
741 			return -1;
742 	} else {
743 		/* No payload to send */
744 		e_debug(resp->event, "No payload to send");
745 		if (resp->payload_stream != NULL) {
746 			ret = http_server_ostream_continue(resp->payload_stream);
747 			if (ret < 0)
748 				return -1;
749 		}
750 		conn->output_locked = FALSE;
751 		ret = http_server_response_finish_payload_out(resp);
752 		if (ret < 0)
753 			return -1;
754 	}
755 
756 	if (conn->conn.output != NULL && !resp->payload_corked &&
757 	    o_stream_uncork_flush(conn->conn.output) < 0) {
758 		http_server_connection_handle_output_error(conn);
759 		return -1;
760 	}
761 	return ret;
762 }
763 
http_server_response_send(struct http_server_response * resp)764 int http_server_response_send(struct http_server_response *resp)
765 {
766 	int ret;
767 
768 	T_BEGIN {
769 		ret = http_server_response_send_real(resp);
770 	} T_END;
771 	return ret;
772 }
773 
http_server_response_get_status(struct http_server_response * resp,int * status_r,const char ** reason_r)774 void http_server_response_get_status(struct http_server_response *resp,
775 				     int *status_r, const char **reason_r)
776 {
777 	i_assert(resp != NULL);
778 	*status_r = resp->status;
779 	*reason_r = resp->reason;
780 }
781 
http_server_response_get_total_size(struct http_server_response * resp)782 uoff_t http_server_response_get_total_size(struct http_server_response *resp)
783 {
784 	i_assert(resp != NULL);
785 	return resp->payload_size + str_len(resp->headers);
786 }
787 
http_server_response_add_permanent_header(struct http_server_response * resp,const char * key,const char * value)788 void http_server_response_add_permanent_header(struct http_server_response *resp,
789 					       const char *key, const char *value)
790 {
791 	http_server_response_add_header(resp, key, value);
792 
793 	if (!array_is_created(&resp->perm_headers))
794 		i_array_init(&resp->perm_headers, 4);
795 	char *key_dup = i_strdup(key);
796 	char *value_dup = i_strdup(value);
797 	array_push_back(&resp->perm_headers, &key_dup);
798 	array_push_back(&resp->perm_headers, &value_dup);
799 }
800