1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
5 * Copyright (C) 2008, Eduardo Silva P.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Library General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
32 #include "http_status.h"
40 int mk_header_iov_add_entry(struct mk_iov
*mk_io
, mk_pointer data
,
41 mk_pointer sep
, int free
)
43 return mk_iov_add_entry(mk_io
, data
.data
, data
.len
, sep
, free
);
46 struct mk_iov
*mk_header_iov_get()
48 return pthread_getspecific(mk_cache_iov_header
);
51 void mk_header_iov_free(struct mk_iov
*iov
)
53 mk_iov_free_marked(iov
);
56 /* Send_Header , envia las cabeceras principales */
57 int mk_header_send(int fd
, struct client_request
*cr
,
58 struct request
*sr
, struct log_info
*s_log
)
61 unsigned long len
= 0;
63 struct header_values
*sh
;
68 iov
= mk_header_iov_get();
73 mk_header_iov_add_entry(iov
, mk_hr_http_ok
,
74 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
78 mk_header_iov_add_entry(iov
, mk_hr_http_partial
,
79 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
83 s_log
->status
= S_LOG_OFF
;
84 mk_header_iov_add_entry(iov
, mk_hr_redir_moved
,
85 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
89 s_log
->status
= S_LOG_ON
;
90 mk_header_iov_add_entry(iov
, mk_hr_redir_moved_t
,
91 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
95 s_log
->status
= S_LOG_OFF
;
96 mk_header_iov_add_entry(iov
, mk_hr_not_modified
,
97 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
100 case M_CLIENT_BAD_REQUEST
:
101 mk_header_iov_add_entry(iov
, mk_hr_client_bad_request
,
102 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
105 case M_CLIENT_FORBIDDEN
:
106 mk_header_iov_add_entry(iov
, mk_hr_client_forbidden
,
107 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
110 case M_CLIENT_NOT_FOUND
:
111 mk_header_iov_add_entry(iov
, mk_hr_client_not_found
,
112 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
115 case M_CLIENT_METHOD_NOT_ALLOWED
:
116 mk_header_iov_add_entry(iov
, mk_hr_client_method_not_allowed
,
117 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
120 case M_CLIENT_REQUEST_TIMEOUT
:
121 mk_header_iov_add_entry(iov
, mk_hr_client_request_timeout
,
122 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
123 s_log
->status
= S_LOG_OFF
;
126 case M_CLIENT_LENGTH_REQUIRED
:
127 mk_header_iov_add_entry(iov
, mk_hr_client_length_required
,
128 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
131 case M_SERVER_NOT_IMPLEMENTED
:
132 mk_header_iov_add_entry(iov
, mk_hr_server_not_implemented
,
133 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
136 case M_SERVER_INTERNAL_ERROR
:
137 mk_header_iov_add_entry(iov
, mk_hr_server_internal_error
,
138 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
141 case M_SERVER_HTTP_VERSION_UNSUP
:
142 mk_header_iov_add_entry(iov
,
143 mk_hr_server_http_version_unsup
,
144 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
148 if (sh
->status
!= 0) {
149 s_log
->final_response
= sh
->status
;
153 mk_header_iov_free(iov
);
158 mk_iov_add_entry(iov
, sr
->host_conf
->header_host_signature
.data
,
159 sr
->host_conf
->header_host_signature
.len
,
160 mk_iov_crlf
, MK_IOV_NOT_FREE_BUF
);
163 mk_iov_add_entry(iov
,
164 mk_header_short_date
.data
,
165 mk_header_short_date
.len
,
166 mk_iov_header_value
, MK_IOV_NOT_FREE_BUF
);
167 mk_iov_add_entry(iov
,
168 header_current_time
.data
,
169 header_current_time
.len
,
170 mk_iov_crlf
, MK_IOV_NOT_FREE_BUF
);
173 if (config
->keep_alive
== VAR_ON
&&
174 cr
->request
->connection
.data
!= NULL
&&
175 cr
->request
->keep_alive
== VAR_ON
&&
176 (cr
->counter_connections
< config
->max_keep_alive_request
)) {
177 m_build_buffer(&buffer
,
179 "Keep-Alive: timeout=%i, max=%i"
181 config
->keep_alive_timeout
,
182 (config
->max_keep_alive_request
-
183 cr
->counter_connections
)
185 mk_iov_add_entry(iov
, buffer
, len
, mk_iov_none
, MK_IOV_FREE_BUF
);
186 mk_iov_add_entry(iov
,
187 mk_header_conn_ka
.data
,
188 mk_header_conn_ka
.len
,
189 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
191 else if (sr
->protocol
>= HTTP_PROTOCOL_10
|| sr
->content_length
== 0) {
192 mk_iov_add_entry(iov
,
193 mk_header_conn_close
.data
,
194 mk_header_conn_close
.len
,
195 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
199 if (sh
->location
!= NULL
) {
200 mk_iov_add_entry(iov
,
201 mk_header_short_location
.data
,
202 mk_header_short_location
.len
,
203 mk_iov_header_value
, MK_IOV_NOT_FREE_BUF
);
205 mk_iov_add_entry(iov
,
207 strlen(sh
->location
), mk_iov_crlf
, MK_IOV_FREE_BUF
);
211 if (sh
->last_modified
.len
> 0) {
212 mk_iov_add_entry(iov
, mk_header_last_modified
.data
,
213 mk_header_last_modified
.len
,
214 mk_iov_header_value
, MK_IOV_NOT_FREE_BUF
);
215 mk_iov_add_entry(iov
, sh
->last_modified
.data
,
216 sh
->last_modified
.len
,
217 mk_iov_crlf
, MK_IOV_NOT_FREE_BUF
);
221 if (sh
->content_type
.len
> 0) {
222 mk_iov_add_entry(iov
,
223 mk_header_short_ct
.data
,
224 mk_header_short_ct
.len
,
225 mk_iov_header_value
, MK_IOV_NOT_FREE_BUF
);
227 mk_iov_add_entry(iov
,
228 sh
->content_type
.data
,
229 sh
->content_type
.len
,
230 mk_iov_crlf
, MK_IOV_NOT_FREE_BUF
);
233 /* Transfer Encoding */
234 switch (sh
->transfer_encoding
) {
235 case MK_HEADER_TE_TYPE_CHUNKED
:
236 mk_iov_add_entry(iov
,
237 mk_header_te_chunked
.data
,
238 mk_header_te_chunked
.len
,
239 mk_iov_crlf
, MK_IOV_NOT_FREE_BUF
);
244 mk_iov_add_entry(iov,
245 mk_header_accept_ranges.data,
246 mk_header_accept_ranges.len,
247 mk_iov_crlf, MK_IOV_NOT_FREE_BUF);
249 /* TamaƱo total de la informacion a enviar */
250 if ((sh
->content_length
!= 0 &&
251 (sh
->ranges
[0] >= 0 || sh
->ranges
[1] >= 0)) &&
252 config
->resume
== VAR_ON
) {
256 if (sh
->ranges
[0] >= 0 && sh
->ranges
[1] == -1) {
257 length
= (unsigned int)
258 (sh
->content_length
- sh
->ranges
[0]);
259 m_build_buffer(&buffer
, &len
, "%s %i", RH_CONTENT_LENGTH
, length
);
260 mk_iov_add_entry(iov
, buffer
, len
, mk_iov_crlf
, MK_IOV_FREE_BUF
);
262 m_build_buffer(&buffer
,
267 (sh
->content_length
- 1), sh
->content_length
);
268 mk_iov_add_entry(iov
, buffer
, len
, mk_iov_crlf
, MK_IOV_FREE_BUF
);
272 if (sh
->ranges
[0] >= 0 && sh
->ranges
[1] >= 0) {
273 length
= (unsigned int)
274 abs(sh
->ranges
[1] - sh
->ranges
[0]) + 1;
275 m_build_buffer(&buffer
, &len
, "%s %d", RH_CONTENT_LENGTH
, length
);
276 mk_iov_add_entry(iov
, buffer
, len
, mk_iov_crlf
, MK_IOV_FREE_BUF
);
278 m_build_buffer(&buffer
,
282 sh
->ranges
[0], sh
->ranges
[1], sh
->content_length
);
284 mk_iov_add_entry(iov
, buffer
, len
, mk_iov_crlf
, MK_IOV_FREE_BUF
);
288 if (sh
->ranges
[0] == -1 && sh
->ranges
[1] > 0) {
289 length
= (unsigned int) sh
->ranges
[1];
291 if (length
> sh
->content_length
) {
292 length
= sh
->content_length
;
293 sh
->ranges
[1] = sh
->content_length
;
296 m_build_buffer(&buffer
, &len
, "%s %d", RH_CONTENT_LENGTH
, length
);
297 mk_iov_add_entry(iov
, buffer
, len
, mk_iov_crlf
, MK_IOV_FREE_BUF
);
299 m_build_buffer(&buffer
,
303 (sh
->content_length
- sh
->ranges
[1]),
304 (sh
->content_length
- 1), sh
->content_length
);
305 mk_iov_add_entry(iov
, buffer
, len
, mk_iov_crlf
, MK_IOV_FREE_BUF
);
308 else if (sh
->content_length
>= 0) {
309 mk_iov_add_entry(iov
, mk_rh_content_length
.data
,
310 mk_rh_content_length
.len
,
311 mk_iov_space
, MK_IOV_NOT_FREE_BUF
);
313 mk_iov_add_entry(iov
, sh
->content_length_p
.data
,
314 sh
->content_length_p
.len
,
315 mk_iov_crlf
, MK_IOV_NOT_FREE_BUF
);
318 if (sh
->cgi
== SH_NOCGI
|| sh
->breakline
== MK_HEADER_BREAKLINE
) {
319 mk_iov_add_entry(iov
, mk_iov_crlf
.data
, mk_iov_crlf
.len
,
320 mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
323 mk_socket_set_cork_flag(fd
, TCP_CORK_ON
);
324 mk_iov_send(fd
, iov
, MK_IOV_SEND_TO_SOCKET
);
326 #ifdef DEBUG_HEADERS_OUT
327 mk_iov_send(0, iov
, MK_IOV_SEND_TO_SOCKET
);
330 mk_header_iov_free(iov
);
335 char *mk_header_chunked_line(int len
)
339 buf
= mk_mem_malloc_z(10);
340 snprintf(buf
, 9, "%x%s", len
, MK_CRLF
);
345 struct header_values
*mk_header_create()
347 struct header_values
*headers
;
350 (struct header_values
*) mk_mem_malloc(sizeof(struct header_values
));
351 headers
->ranges
[0] = -1;
352 headers
->ranges
[1] = -1;
353 headers
->content_length
= -1;
354 headers
->transfer_encoding
= -1;
355 mk_pointer_reset(&headers
->content_length_p
);
356 mk_pointer_reset(&headers
->content_type
);
357 mk_pointer_reset(&headers
->last_modified
);
358 headers
->location
= NULL
;