Fix Headers TOC parser, use body length as limit
[MonkeyD.git] / src / request.c
blob866da77a9fcab2294ae26246d5838542d08e5c7f
1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 /* Monkey HTTP Daemon
4 * ------------------
5 * Copyright (C) 2001-2010, Eduardo Silva P. <edsiper@gmail.com>
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.
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <sys/stat.h>
25 #include <unistd.h>
26 #include <string.h>
27 #include <sys/socket.h>
28 #include <sys/time.h>
29 #include <time.h>
30 #include <netdb.h>
31 #include <sys/wait.h>
32 #include <signal.h>
33 #include <errno.h>
35 #include <string.h>
37 #include <arpa/inet.h>
38 #include <netinet/in.h>
39 #include <sys/types.h>
41 #include "request.h"
42 #include "monkey.h"
43 #include "http.h"
44 #include "http_status.h"
45 #include "string.h"
46 #include "str.h"
47 #include "config.h"
48 #include "scheduler.h"
49 #include "epoll.h"
50 #include "socket.h"
51 #include "logfile.h"
52 #include "utils.h"
53 #include "header.h"
54 #include "user.h"
55 #include "method.h"
56 #include "memory.h"
57 #include "socket.h"
58 #include "cache.h"
59 #include "clock.h"
60 #include "utils.h"
62 struct request *mk_request_parse(struct client_request *cr)
64 int i, end;
65 int blocks = 0;
66 struct request *cr_buf = 0, *cr_search = 0;
68 for (i = 0; i <= cr->body_pos_end; i++) {
69 /* Look for CRLFCRLF (\r\n\r\n), maybe some pipelining
70 * request can be involved.
71 * Previous catch in mk_http_pending_request
73 end = mk_string_search(cr->body + i, mk_endblock.data) + i;
75 if (end < 0) {
76 return NULL;
79 /* Allocating request block */
80 cr_buf = mk_request_alloc();
82 /* mk_pointer */
83 cr_buf->body.data = cr->body + i;
84 cr_buf->body.len = end - i;
86 /* Method, previous catch in mk_http_pending_request */
87 if (i == 0) {
88 cr_buf->method = cr->first_method;
90 else {
91 cr_buf->method = mk_http_method_get(cr_buf->body.data);
93 cr_buf->next = NULL;
95 /* Looking for POST data */
96 if (cr_buf->method == HTTP_METHOD_POST) {
97 cr_buf->post_variables = mk_method_post_get_vars(cr->body,
98 end + mk_endblock.len);
99 if (cr_buf->post_variables.len >= 0) {
100 i += cr_buf->post_variables.len;
104 /* Increase index to the end of the current block */
105 i = (end + mk_endblock.len) - 1;
107 /* Link block */
108 if (!cr->request) {
109 cr->request = cr_buf;
111 else {
112 cr_search = cr->request;
113 while (cr_search) {
114 if (cr_search->next == NULL) {
115 cr_search->next = cr_buf;
116 break;
118 else {
119 cr_search = cr_search->next;
124 /* Update counter */
125 blocks++;
129 /* DEBUG BLOCKS */
130 cr_search = cr->request;
131 while(cr_search){
132 printf("\n");
133 MK_TRACE("BLOCK INIT");
134 mk_pointer_print(cr_search->body);
135 MK_TRACE("BLOCK_END");
137 cr_search = cr_search->next;
141 /* Checking pipelining connection */
142 cr_search = cr->request;
143 if (blocks > 1) {
144 while (cr_search) {
145 /* Pipelining request must use GET or HEAD methods */
146 if (cr_search->method != HTTP_METHOD_GET &&
147 cr_search->method != HTTP_METHOD_HEAD) {
148 return NULL;
150 cr_search = cr_search->next;
153 cr->pipelined = TRUE;
156 return cr->request;
159 int mk_handler_read(int socket, struct client_request *cr)
161 int bytes;
163 bytes = read(socket, cr->body + cr->body_length,
164 MAX_REQUEST_BODY - cr->body_length);
166 if (bytes < 0) {
167 if (errno == EAGAIN) {
168 return 1;
170 else {
171 mk_request_client_remove(socket);
172 return -1;
175 if (bytes == 0) {
176 mk_request_client_remove(socket);
177 return -1;
180 if (bytes > 0) {
181 cr->body_length += bytes;
182 cr->body[cr->body_length] = '\0';
185 return bytes;
188 int mk_handler_write(int socket, struct client_request *cr)
190 int bytes, final_status = 0;
191 struct request *sr;
194 * Get node from schedule list node which contains
195 * the information regarding to the current thread
197 if (!cr) {
198 return -1;
201 if (!cr->request) {
202 if (!mk_request_parse(cr)) {
203 return -1;
207 sr = cr->request;
209 while (sr) {
210 /* Request not processed also no plugin has take some action */
211 if (sr->bytes_to_send < 0 && !sr->handled_by) {
212 final_status = mk_request_process(cr, sr);
214 /* Request with data to send by static file sender */
215 else if (sr->bytes_to_send > 0 && !sr->handled_by) {
216 bytes = SendFile(socket, cr, sr);
217 final_status = bytes;
219 else if (sr->handled_by){
220 /* FIXME: Look for loops
221 * sr->handled_by; */
225 * If we got an error, we don't want to parse
226 * and send information for another pipelined request
228 if (final_status > 0) {
229 return final_status;
231 else if (final_status <= 0) {
232 switch (final_status) {
233 case EXIT_NORMAL:
234 mk_logger_write_log(cr, sr->log, sr->host_conf);
235 if (sr->close_now == VAR_ON) {
236 return -1;
238 break;
239 case EXIT_ABORT:
240 return -1;
241 break;
245 sr = sr->next;
248 /* If we are here, is because all pipelined request were
249 * processed successfully, let's return 0;
251 return 0;
254 int mk_request_process(struct client_request *cr, struct request *s_request)
256 int status = 0;
257 struct host *host;
259 status = mk_request_header_process(s_request);
261 if (status < 0) {
262 return EXIT_ABORT;
265 switch (s_request->method) {
266 case METHOD_NOT_ALLOWED:
267 mk_request_error(M_CLIENT_METHOD_NOT_ALLOWED, cr,
268 s_request, 1, s_request->log);
269 return EXIT_NORMAL;
270 case METHOD_NOT_FOUND:
271 mk_request_error(M_SERVER_NOT_IMPLEMENTED, cr,
272 s_request, 1, s_request->log);
273 return EXIT_NORMAL;
276 s_request->user_home = VAR_OFF;
277 s_request->log->method = s_request->method;
279 /* Valid request URI? */
280 if (s_request->uri_processed == NULL) {
281 mk_request_error(M_CLIENT_BAD_REQUEST, cr, s_request, 1,
282 s_request->log);
283 return EXIT_NORMAL;
286 /* HTTP/1.1 needs Host header */
287 if (!s_request->host.data && s_request->protocol == HTTP_PROTOCOL_11) {
288 s_request->log->final_response = M_CLIENT_BAD_REQUEST;
289 mk_request_error(M_CLIENT_BAD_REQUEST, cr, s_request, 1,
290 s_request->log);
291 return EXIT_NORMAL;
294 /* Method not allowed ? */
295 if (s_request->method == METHOD_NOT_ALLOWED) {
296 s_request->log->final_response = M_CLIENT_METHOD_NOT_ALLOWED;
297 mk_request_error(M_CLIENT_METHOD_NOT_ALLOWED, cr, s_request, 1,
298 s_request->log);
299 return EXIT_NORMAL;
302 /* Validating protocol version */
303 if (s_request->protocol == HTTP_PROTOCOL_UNKNOWN) {
305 s_request->log->final_response = M_SERVER_HTTP_VERSION_UNSUP;
306 mk_request_error(M_SERVER_HTTP_VERSION_UNSUP, cr, s_request, 1,
307 s_request->log);
308 return EXIT_NORMAL;
311 if (s_request->host.data) {
312 host = mk_config_host_find(s_request->host);
313 if (host) {
314 s_request->host_conf = host;
316 else {
317 s_request->host_conf = config->hosts;
320 else {
321 s_request->host_conf = config->hosts;
323 s_request->log->host_conf = s_request->host_conf;
325 /* is requesting an user home directory ? */
326 if (config->user_dir) {
327 if (strncmp(s_request->uri_processed,
328 mk_user_home.data, mk_user_home.len) == 0) {
329 if (mk_user_init(cr, s_request) != 0) {
330 return EXIT_NORMAL;
335 /* Handling method requested */
336 if (s_request->method == HTTP_METHOD_POST) {
337 if ((status = mk_method_post(cr, s_request)) == -1) {
338 return status;
342 status = mk_http_init(cr, s_request);
344 #ifdef TRACE
345 MK_TRACE("HTTP Init returning %i", status);
346 #endif
348 return status;
351 /* Return a struct with method, URI , protocol version
352 and all static headers defined here sent in request */
353 int mk_request_header_process(struct request *sr)
355 int uri_init = 0, uri_end = 0;
356 char *query_init = 0;
357 int prot_init = 0, prot_end = 0, pos_sep = 0;
358 int fh_limit;
359 char *port = 0;
360 char *headers;
361 mk_pointer host;
363 /* If verification fails it will return always
364 * a bad request status
366 sr->log->final_response = M_CLIENT_BAD_REQUEST;
368 /* Method */
369 sr->method_p = mk_http_method_check_str(sr->method);
371 /* Request URI */
372 uri_init = (index(sr->body.data, ' ') - sr->body.data) + 1;
373 fh_limit = (index(sr->body.data, '\n') - sr->body.data);
375 uri_end = mk_string_search_r(sr->body.data, ' ', fh_limit) - 1;
377 if (uri_end <= 0) {
378 return -1;
381 prot_init = uri_end + 2;
383 if (uri_end < uri_init) {
384 return -1;
387 /* Query String */
388 query_init = index(sr->body.data + uri_init, '?');
389 if (query_init) {
390 int init, end;
392 init = (int) (query_init - (sr->body.data + uri_init)) + uri_init;
393 if (init <= uri_end) {
394 end = uri_end;
395 uri_end = init - 1;
397 sr->query_string = mk_pointer_create(sr->body.data,
398 init + 1, end + 1);
402 /* Request URI Part 2 */
403 sr->uri = sr->log->uri = mk_pointer_create(sr->body.data,
404 uri_init, uri_end + 1);
406 if (sr->uri.len < 1) {
407 return -1;
411 /* HTTP Version */
412 prot_end = fh_limit - 1;
413 if (prot_end != prot_init && prot_end > 0) {
414 sr->protocol = sr->log->protocol =
415 mk_http_protocol_check(sr->body.data + prot_init,
416 prot_end - prot_init);
419 headers = sr->body.data + prot_end + mk_crlf.len;
421 /* URI processed */
422 sr->uri_processed = mk_utils_hexuri_to_ascii(sr->uri);
424 if (!sr->uri_processed) {
425 sr->uri_processed = mk_pointer_to_buf(sr->uri);
426 sr->uri_twin = VAR_ON;
429 /* Creating table of content (index) for request headers */
430 int toc_len = MK_KNOWN_HEADERS;
431 int headers_len = sr->body.len - (prot_end + mk_crlf.len);
433 struct header_toc *toc = mk_request_header_toc_create(toc_len);
434 mk_request_header_toc_parse(toc, toc_len, headers, headers_len);
436 /* Host */
437 host = mk_request_header_find(toc, toc_len, headers, mk_rh_host);
439 if (host.data) {
440 if ((pos_sep = mk_string_char_search(host.data, ':', host.len)) >= 0) {
441 sr->host.data = host.data;
442 sr->host.len = pos_sep;
444 port = mk_string_copy_substr(host.data, pos_sep + 1, host.len);
445 sr->port = atoi(port);
446 mk_mem_free(port);
448 else {
449 sr->host = host; /* maybe null */
450 sr->port = config->standard_port;
453 else {
454 sr->host.data = NULL;
457 /* Looking for headers */
458 sr->accept = mk_request_header_find(toc, toc_len, headers, mk_rh_accept);
459 sr->accept_charset = mk_request_header_find(toc, toc_len, headers,
460 mk_rh_accept_charset);
461 sr->accept_encoding = mk_request_header_find(toc, toc_len, headers,
462 mk_rh_accept_encoding);
465 sr->accept_language = mk_request_header_find(toc, toc_len, headers,
466 mk_rh_accept_language);
467 sr->cookies = mk_request_header_find(toc, toc_len, headers, mk_rh_cookie);
468 sr->connection = mk_request_header_find(toc, toc_len, headers,
469 mk_rh_connection);
470 sr->referer = mk_request_header_find(toc, toc_len, headers,
471 mk_rh_referer);
472 sr->user_agent = mk_request_header_find(toc, toc_len, headers,
473 mk_rh_user_agent);
474 sr->range = mk_request_header_find(toc, toc_len, headers, mk_rh_range);
475 sr->if_modified_since = mk_request_header_find(toc, toc_len, headers,
476 mk_rh_if_modified_since);
478 /* Default Keepalive is off */
479 sr->keep_alive = VAR_OFF;
480 if (sr->connection.data) {
481 if (mk_string_casestr(sr->connection.data, "Keep-Alive")) {
482 sr->keep_alive = VAR_ON;
484 else if(mk_string_casestr(sr->connection.data, "Close")) {
485 sr->close_now = VAR_ON;
488 else {
489 /* Default value for HTTP/1.1 */
490 if (sr->protocol == HTTP_PROTOCOL_11) {
491 /* Assume keep-alive connection */
492 sr->keep_alive = VAR_ON;
495 sr->log->final_response = M_HTTP_OK;
497 return 0;
500 /* Return value of some variable sent in request */
501 mk_pointer mk_request_header_find(struct header_toc * toc, int toc_len,
502 char *request_body, mk_pointer header)
504 int i;
505 mk_pointer var;
507 var.data = NULL;
508 var.len = 0;
510 /* new code */
511 if (toc) {
512 for (i = 0; i < toc_len; i++) {
513 /* status = 1 means that the toc entry was already
514 * checked by monkey
516 if (toc[i].status == 1) {
517 continue;
520 if (!toc[i].init)
521 break;
523 if (strncasecmp(toc[i].init, header.data, header.len) == 0) {
524 var.data = toc[i].init + header.len + 1;
525 var.len = toc[i].end - var.data;
526 toc[i].status = 1;
527 return var;
532 return var;
535 /* FIXME: IMPROVE access */
536 /* Look for some index.xxx in pathfile */
537 mk_pointer mk_request_index(char *pathfile)
539 unsigned long len;
540 char *file_aux = 0;
541 mk_pointer f;
542 struct indexfile *aux_index;
544 mk_pointer_reset(&f);
546 aux_index = first_index;
548 while (aux_index) {
549 m_build_buffer(&file_aux, &len, "%s%s",
550 pathfile, aux_index->indexname);
552 if (access(file_aux, F_OK) == 0) {
553 f.data = file_aux;
554 f.len = len;
555 return f;
557 mk_mem_free(file_aux);
558 aux_index = aux_index->next;
561 return f;
564 /* Send error responses */
565 void mk_request_error(int num_error, struct client_request *cr,
566 struct request *s_request, int debug,
567 struct log_info *s_log)
569 char *aux_message = 0;
570 mk_pointer message, *page = 0;
571 long n;
573 s_log->error_details.data = NULL;
575 switch (num_error) {
576 case M_CLIENT_BAD_REQUEST:
577 page = mk_request_set_default_page("Bad Request",
578 s_request->uri,
579 s_request->host_conf->
580 host_signature);
581 s_log->error_msg = request_error_msg_400;
582 break;
584 case M_CLIENT_FORBIDDEN:
585 page = mk_request_set_default_page("Forbidden",
586 s_request->uri,
587 s_request->host_conf->
588 host_signature);
589 s_log->error_msg = request_error_msg_403;
590 s_log->error_details = s_request->uri;
591 break;
593 case M_CLIENT_NOT_FOUND:
594 m_build_buffer(&message.data, &message.len,
595 "The requested URL was not found on this server.");
596 page = mk_request_set_default_page("Not Found",
597 message,
598 s_request->host_conf->
599 host_signature);
600 s_log->error_msg = request_error_msg_404;
601 s_log->error_details = s_request->uri;
603 mk_pointer_free(&message);
604 break;
606 case M_CLIENT_METHOD_NOT_ALLOWED:
607 page = mk_request_set_default_page("Method Not Allowed",
608 s_request->uri,
609 s_request->host_conf->
610 host_signature);
612 s_log->final_response = M_CLIENT_METHOD_NOT_ALLOWED;
613 s_log->error_msg = request_error_msg_405;
614 s_log->error_details = s_request->method_p;
615 break;
617 case M_CLIENT_REQUEST_TIMEOUT:
618 s_log->status = S_LOG_OFF;
619 s_log->error_msg = request_error_msg_408;
620 break;
622 case M_CLIENT_LENGTH_REQUIRED:
623 s_log->error_msg = request_error_msg_411;
624 break;
626 case M_SERVER_NOT_IMPLEMENTED:
627 page = mk_request_set_default_page("Method Not Implemented",
628 s_request->uri,
629 s_request->host_conf->
630 host_signature);
631 s_log->final_response = M_SERVER_NOT_IMPLEMENTED;
632 s_log->error_msg = request_error_msg_501;
633 s_log->error_details = s_request->method_p;
634 break;
636 case M_SERVER_INTERNAL_ERROR:
637 m_build_buffer(&message.data, &message.len,
638 "Problems found running %s ", s_request->uri);
639 page = mk_request_set_default_page("Internal Server Error",
640 message,
641 s_request->host_conf->
642 host_signature);
643 s_log->error_msg = request_error_msg_500;
645 mk_pointer_free(&message);
646 break;
648 case M_SERVER_HTTP_VERSION_UNSUP:
649 mk_pointer_reset(&message);
650 page = mk_request_set_default_page("HTTP Version Not Supported",
651 message,
652 s_request->host_conf->
653 host_signature);
654 s_log->error_msg = request_error_msg_505;
655 break;
658 s_log->final_response = num_error;
660 s_request->headers->status = num_error;
661 if (page) {
662 s_request->headers->content_length = page->len;
663 s_request->headers->content_length_p = mk_utils_int2mkp(page->len);
666 s_request->headers->location = NULL;
667 s_request->headers->cgi = SH_NOCGI;
668 s_request->headers->pconnections_left = 0;
669 mk_pointer_reset(&s_request->headers->last_modified);
671 if (aux_message)
672 mk_mem_free(aux_message);
674 if (!page) {
675 mk_pointer_reset(&s_request->headers->content_type);
677 else {
678 mk_pointer_set(&s_request->headers->content_type, "text/html\r\n");
681 mk_header_send(cr->socket, cr, s_request, s_log);
683 if (debug == 1) {
684 n = write(cr->socket, page->data, page->len);
685 mk_pointer_free(page);
686 mk_mem_free(page);
690 /* Build error page */
691 mk_pointer *mk_request_set_default_page(char *title, mk_pointer message,
692 char *signature)
694 char *temp;
695 mk_pointer *p;
697 p = mk_mem_malloc(sizeof(mk_pointer));
699 temp = mk_pointer_to_buf(message);
700 m_build_buffer(&p->data, &p->len,
701 MK_REQUEST_DEFAULT_PAGE, title, temp, signature);
702 mk_mem_free(temp);
704 return p;
707 /* Create a memory allocation in order to handle the request data */
708 struct request *mk_request_alloc()
710 struct request *request = 0;
712 request = mk_mem_malloc(sizeof(struct request));
713 request->log = mk_mem_malloc(sizeof(struct log_info));
715 request->status = VAR_OFF; /* Request not processed yet */
716 request->make_log = VAR_ON; /* build log file of this request ? */
717 request->close_now = VAR_OFF;
719 mk_pointer_reset(&request->body);
721 request->log->final_response = M_HTTP_OK;
722 request->log->status = S_LOG_ON;
723 mk_pointer_reset(&request->log->size_p);
724 mk_pointer_reset(&request->log->error_msg);
726 request->status = VAR_ON;
727 request->method = METHOD_NOT_FOUND;
729 mk_pointer_reset(&request->uri);
730 request->uri_processed = NULL;
731 request->uri_twin = VAR_OFF;
733 request->accept.data = NULL;
734 request->accept_language.data = NULL;
735 request->accept_encoding.data = NULL;
736 request->accept_charset.data = NULL;
737 request->content_length = 0;
738 request->content_type.data = NULL;
739 request->connection.data = NULL;
740 request->cookies.data = NULL;
741 request->host.data = NULL;
742 request->if_modified_since.data = NULL;
743 request->last_modified_since.data = NULL;
744 request->range.data = NULL;
745 request->referer.data = NULL;
746 request->resume.data = NULL;
747 request->user_agent.data = NULL;
749 request->post_variables.data = NULL;
751 request->user_uri = NULL;
752 mk_pointer_reset(&request->query_string);
754 request->file_info = NULL;
755 request->virtual_user = NULL;
756 request->script_filename = NULL;
757 mk_pointer_reset(&request->real_path);
758 request->host_conf = config->hosts;
760 request->loop = 0;
761 request->bytes_to_send = -1;
762 request->bytes_offset = 0;
763 request->fd_file = -1;
765 /* Response Headers */
766 request->headers = mk_header_create();
768 request->handled_by = NULL;
769 return request;
772 void mk_request_free_list(struct client_request *cr)
774 struct request *sr = 0, *before = 0;
776 /* sr = last node */
778 while (cr->request) {
779 sr = before = cr->request;
781 while (sr->next) {
782 sr = sr->next;
785 if (sr != cr->request) {
786 while (before->next != sr) {
787 before = before->next;
789 before->next = NULL;
791 else {
792 cr->request = NULL;
794 mk_request_free(sr);
796 cr->request = NULL;
799 void mk_request_free(struct request *sr)
801 /* I hate it, but I don't know another light way :( */
802 if (sr->fd_file > 0) {
803 close(sr->fd_file);
805 if (sr->headers) {
806 mk_mem_free(sr->headers->location);
807 mk_pointer_free(&sr->headers->content_length_p);
808 mk_pointer_free(&sr->headers->last_modified);
810 mk_mem_free(sr->headers->content_type);
811 headers->content_type never it's allocated
812 with malloc or something, so we don't need
813 to free it, the value has been freed before
814 in M_METHOD_Get_and_Head(struct request *sr)
816 this BUG was reported by gentoo team.. thanks guys XD
819 mk_mem_free(sr->headers);
823 if (sr->log) {
825 * We do not free log->size_p, as if it was
826 * used due to an error, it points to the
827 * same memory block than header->content_length_p
828 * points to, we just reset it.
830 mk_pointer_reset(&sr->log->size_p);
833 * sr->log->error_msg just point to
834 * local data on request.c, no
835 * dynamic allocation is made
838 mk_mem_free(sr->log);
841 mk_pointer_reset(&sr->body);
842 mk_pointer_reset(&sr->uri);
844 if (sr->uri_twin == VAR_ON) {
845 mk_mem_free(sr->uri_processed);
848 mk_pointer_free(&sr->post_variables);
849 mk_mem_free(sr->user_uri);
850 mk_pointer_reset(&sr->query_string);
852 mk_mem_free(sr->file_info);
853 mk_mem_free(sr->virtual_user);
854 mk_mem_free(sr->script_filename);
855 mk_pointer_free(&sr->real_path);
856 mk_mem_free(sr);
859 /* Create a client request struct and put it on the
860 * main list
862 struct client_request *mk_request_client_create(int socket)
864 struct request_idx *request_index;
865 struct client_request *cr;
866 struct sched_connection *sc;
868 sc = mk_sched_get_connection(NULL, socket);
869 cr = mk_mem_malloc(sizeof(struct client_request));
871 /* IPv4 Address */
872 cr->ipv4 = &sc->ipv4;
874 cr->pipelined = FALSE;
875 cr->counter_connections = 0;
876 cr->socket = socket;
877 cr->status = MK_REQUEST_STATUS_INCOMPLETE;
878 cr->request = NULL;
880 /* creation time in unix time */
881 cr->init_time = sc->arrive_time;
883 cr->next = NULL;
884 cr->body = mk_mem_malloc(MAX_REQUEST_BODY);
885 cr->body_length = 0;
886 cr->body_pos_end = -1;
887 cr->first_method = HTTP_METHOD_UNKNOWN;
889 request_index = mk_sched_get_request_index();
890 if (!request_index->first) {
891 request_index->first = request_index->last = cr;
893 else {
894 request_index->last->next = cr;
895 request_index->last = cr;
897 mk_sched_set_request_index(request_index);
899 return cr;
902 struct client_request *mk_request_client_get(int socket)
904 struct request_idx *request_index;
905 struct client_request *cr = NULL;
907 request_index = mk_sched_get_request_index();
908 cr = request_index->first;
909 while (cr != NULL) {
910 if (cr->socket == socket) {
911 break;
913 cr = cr->next;
916 return cr;
920 * From thread sched_list_node "list", remove the client_request
921 * struct information
923 struct client_request *mk_request_client_remove(int socket)
925 struct request_idx *request_index;
926 struct client_request *cr, *aux;
928 request_index = mk_sched_get_request_index();
929 cr = request_index->first;
931 while (cr) {
932 if (cr->socket == socket) {
933 if (cr == request_index->first) {
934 request_index->first = cr->next;
936 else {
937 aux = request_index->first;
938 while (aux->next != cr) {
939 aux = aux->next;
941 aux->next = cr->next;
942 if (!aux->next) {
943 request_index->last = aux;
946 break;
948 cr = cr->next;
951 //mk_pointer_free(&cr->ip);
952 mk_mem_free(cr->body);
953 mk_mem_free(cr);
955 return NULL;
958 struct header_toc *mk_request_header_toc_create(int len)
960 int i;
961 struct header_toc *p;
963 p = (struct header_toc *) pthread_getspecific(mk_cache_header_toc);
965 for (i = 0; i < len; i++) {
966 p[i].init = NULL;
967 p[i].end = NULL;
968 p[i].status = 0;
970 return p;
973 void mk_request_header_toc_parse(struct header_toc *toc, int toc_len, char *data, int len)
975 char *p, *l = 0;
976 int i;
978 p = data;
979 for (i = 0; i < toc_len && p && l < data + len; i++) {
980 l = strstr(p, MK_CRLF);
981 if (l) {
982 toc[i].init = p;
983 toc[i].end = l;
984 p = l + mk_crlf.len;
986 else {
987 break;
992 void mk_request_ka_next(struct client_request *cr)
994 bzero(cr->body, sizeof(cr->body));
995 cr->first_method = -1;
996 cr->body_pos_end = -1;
997 cr->body_length = 0;
998 cr->counter_connections++;
1000 /* Update data for scheduler */
1001 cr->init_time = log_current_utime;
1002 cr->status = MK_REQUEST_STATUS_INCOMPLETE;