Fix broken Pipelining support
[MonkeyD.git] / src / request.c
blob2ca99edf3551d7cd5f08ed53b636c389868d146d
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 int pipelined = FALSE;
67 struct request *cr_buf = 0, *cr_search = 0;
69 for (i = 0; i <= cr->body_pos_end; i++) {
70 /* Look for CRLFCRLF (\r\n\r\n), maybe some pipelining
71 * request can be involved.
72 * Previous catch in mk_http_pending_request
74 if (i == 0) {
75 end = cr->body_pos_end;
77 else {
78 end = mk_string_search(cr->body + i, mk_endblock.data) + i;
81 if (end < 0) {
82 return NULL;
85 /* Allocating request block */
86 cr_buf = mk_request_alloc();
88 /* mk_pointer */
89 cr_buf->body.data = cr->body + i;
90 cr_buf->body.len = end - i;
92 /* Method, previous catch in mk_http_pending_request */
93 if (i == 0) {
94 cr_buf->method = cr->first_method;
96 else {
97 cr_buf->method = mk_http_method_get(cr_buf->body.data);
99 cr_buf->next = NULL;
101 /* Looking for POST data */
102 if (cr_buf->method == HTTP_METHOD_POST) {
103 cr_buf->post_variables = mk_method_post_get_vars(cr->body,
104 end + mk_endblock.len);
105 if (cr_buf->post_variables.len >= 0) {
106 i += cr_buf->post_variables.len;
110 /* Increase index to the end of the current block */
111 i = (end + mk_endblock.len) - 1;
113 /* Link block */
114 if (!cr->request) {
115 cr->request = cr_buf;
117 else {
118 cr_search = cr->request;
119 while (cr_search) {
120 if (cr_search->next == NULL) {
121 cr_search->next = cr_buf;
122 break;
124 else {
125 cr_search = cr_search->next;
130 /* Update counter */
131 blocks++;
135 /* DEBUG BLOCKS
136 cr_search = cr->request;
137 while(cr_search){
138 printf("\n");
139 MK_TRACE("BLOCK INIT");
140 mk_pointer_print(cr_search->body);
141 MK_TRACE("BLOCK_END");
143 cr_search = cr_search->next;
147 /* Checking pipelining connection */
148 cr_search = cr->request;
149 if (blocks > 1) {
150 pipelined = TRUE;
152 while (cr_search) {
153 if (cr_search->method != HTTP_METHOD_GET &&
154 cr_search->method != HTTP_METHOD_HEAD) {
155 pipelined = FALSE;
156 break;
158 cr_search = cr_search->next;
161 if (pipelined == FALSE) {
162 /* All pipelined requests must use GET method */
163 return NULL;
165 else {
166 cr->pipelined = TRUE;
170 return cr->request;
173 int mk_handler_read(int socket, struct client_request *cr)
175 int bytes;
177 bytes = read(socket, cr->body + cr->body_length,
178 MAX_REQUEST_BODY - cr->body_length);
180 if (bytes < 0) {
181 if (errno == EAGAIN) {
182 return 1;
184 else {
185 mk_request_client_remove(socket);
186 return -1;
189 if (bytes == 0) {
190 mk_request_client_remove(socket);
191 return -1;
194 if (bytes > 0) {
195 cr->body_length += bytes;
196 cr->body[cr->body_length] = '\0';
199 return bytes;
202 int mk_handler_write(int socket, struct client_request *cr)
204 int bytes, final_status = 0;
205 struct request *sr;
208 * Get node from schedule list node which contains
209 * the information regarding to the current thread
211 if (!cr) {
212 return -1;
215 if (!cr->request) {
216 if (!mk_request_parse(cr)) {
217 return -1;
221 sr = cr->request;
223 while (sr) {
224 /* Request not processed also no plugin has take some action */
225 if (sr->bytes_to_send < 0 && !sr->handled_by) {
226 final_status = mk_request_process(cr, sr);
228 /* Request with data to send by static file sender */
229 else if (sr->bytes_to_send > 0 && !sr->handled_by) {
230 bytes = SendFile(socket, cr, sr);
231 final_status = bytes;
233 else if (sr->handled_by){
234 /* FIXME: Look for loops
235 * sr->handled_by; */
239 * If we got an error, we don't want to parse
240 * and send information for another pipelined request
242 if (final_status > 0) {
243 return final_status;
245 else if (final_status <= 0) {
246 switch (final_status) {
247 case EXIT_NORMAL:
248 mk_logger_write_log(cr, sr->log, sr->host_conf);
249 break;
250 case EXIT_ABORT:
251 return -1;
252 break;
256 sr = sr->next;
259 /* If we are here, is because all pipelined request were
260 * processed successfully, let's return 0;
262 return 0;
265 int mk_request_process(struct client_request *cr, struct request *s_request)
267 int status = 0;
268 struct host *host;
270 status = mk_request_header_process(s_request);
272 if (status < 0) {
273 return EXIT_ABORT;
276 switch (s_request->method) {
277 case METHOD_NOT_ALLOWED:
278 mk_request_error(M_CLIENT_METHOD_NOT_ALLOWED, cr,
279 s_request, 1, s_request->log);
280 return EXIT_NORMAL;
281 case METHOD_NOT_FOUND:
282 mk_request_error(M_SERVER_NOT_IMPLEMENTED, cr,
283 s_request, 1, s_request->log);
284 return EXIT_NORMAL;
287 s_request->user_home = VAR_OFF;
288 s_request->log->method = s_request->method;
290 /* Valid request URI? */
291 if (s_request->uri_processed == NULL) {
292 mk_request_error(M_CLIENT_BAD_REQUEST, cr, s_request, 1,
293 s_request->log);
294 return EXIT_NORMAL;
297 /* HTTP/1.1 needs Host header */
298 if (!s_request->host.data && s_request->protocol == HTTP_PROTOCOL_11) {
299 s_request->log->final_response = M_CLIENT_BAD_REQUEST;
300 mk_request_error(M_CLIENT_BAD_REQUEST, cr, s_request, 1,
301 s_request->log);
302 return EXIT_NORMAL;
305 /* Method not allowed ? */
306 if (s_request->method == METHOD_NOT_ALLOWED) {
307 s_request->log->final_response = M_CLIENT_METHOD_NOT_ALLOWED;
308 mk_request_error(M_CLIENT_METHOD_NOT_ALLOWED, cr, s_request, 1,
309 s_request->log);
310 return EXIT_NORMAL;
313 /* Validating protocol version */
314 if (s_request->protocol == HTTP_PROTOCOL_UNKNOWN) {
316 s_request->log->final_response = M_SERVER_HTTP_VERSION_UNSUP;
317 mk_request_error(M_SERVER_HTTP_VERSION_UNSUP, cr, s_request, 1,
318 s_request->log);
319 return EXIT_NORMAL;
322 if (s_request->host.data) {
323 host = mk_config_host_find(s_request->host);
324 if (host) {
325 s_request->host_conf = host;
327 else {
328 s_request->host_conf = config->hosts;
331 else {
332 s_request->host_conf = config->hosts;
334 s_request->log->host_conf = s_request->host_conf;
336 /* is requesting an user home directory ? */
337 if (config->user_dir) {
338 if (strncmp(s_request->uri_processed,
339 mk_user_home.data, mk_user_home.len) == 0) {
340 if (mk_user_init(cr, s_request) != 0) {
341 return EXIT_NORMAL;
346 /* Handling method requested */
347 if (s_request->method == HTTP_METHOD_POST) {
348 if ((status = mk_method_post(cr, s_request)) == -1) {
349 return status;
353 status = mk_http_init(cr, s_request);
355 #ifdef TRACE
356 MK_TRACE("HTTP Init returning %i", status);
357 #endif
359 return status;
362 /* Return a struct with method, URI , protocol version
363 and all static headers defined here sent in request */
364 int mk_request_header_process(struct request *sr)
366 int uri_init = 0, uri_end = 0;
367 char *query_init = 0;
368 int prot_init = 0, prot_end = 0, pos_sep = 0;
369 int fh_limit;
370 char *port = 0;
371 char *headers;
372 mk_pointer host;
374 /* If verification fails it will return always
375 * a bad request status
377 sr->log->final_response = M_CLIENT_BAD_REQUEST;
379 /* Method */
380 sr->method_p = mk_http_method_check_str(sr->method);
382 /* Request URI */
383 uri_init = (index(sr->body.data, ' ') - sr->body.data) + 1;
384 fh_limit = (index(sr->body.data, '\n') - sr->body.data);
386 uri_end = mk_string_search_r(sr->body.data, ' ', fh_limit) - 1;
388 if (uri_end <= 0) {
389 return -1;
392 prot_init = uri_end + 2;
394 if (uri_end < uri_init) {
395 return -1;
398 /* Query String */
399 query_init = index(sr->body.data + uri_init, '?');
400 if (query_init) {
401 int init, end;
403 init = (int) (query_init - (sr->body.data + uri_init)) + uri_init;
404 if (init <= uri_end) {
405 end = uri_end;
406 uri_end = init - 1;
408 sr->query_string = mk_pointer_create(sr->body.data,
409 init + 1, end + 1);
413 /* Request URI Part 2 */
414 sr->uri = sr->log->uri = mk_pointer_create(sr->body.data,
415 uri_init, uri_end + 1);
417 if (sr->uri.len < 1) {
418 return -1;
422 /* HTTP Version */
423 prot_end = fh_limit - 1;
424 if (prot_end != prot_init && prot_end > 0) {
425 sr->protocol = sr->log->protocol =
426 mk_http_protocol_check(sr->body.data + prot_init,
427 prot_end - prot_init);
430 headers = sr->body.data + prot_end + mk_crlf.len;
432 /* URI processed */
433 sr->uri_processed = mk_utils_hexuri_to_ascii(sr->uri);
435 if (!sr->uri_processed) {
436 sr->uri_processed = mk_pointer_to_buf(sr->uri);
437 sr->uri_twin = VAR_ON;
440 /* Creating table of content (index) for request headers */
441 int toc_len = MK_KNOWN_HEADERS;
442 struct header_toc *toc = mk_request_header_toc_create(toc_len);
443 mk_request_header_toc_parse(toc, headers, toc_len);
445 /* Host */
446 host = mk_request_header_find(toc, toc_len, headers, mk_rh_host);
448 if (host.data) {
449 if ((pos_sep = mk_string_char_search(host.data, ':', host.len)) >= 0) {
450 sr->host.data = host.data;
451 sr->host.len = pos_sep;
453 port = mk_string_copy_substr(host.data, pos_sep + 1, host.len);
454 sr->port = atoi(port);
455 mk_mem_free(port);
457 else {
458 sr->host = host; /* maybe null */
459 sr->port = config->standard_port;
462 else {
463 sr->host.data = NULL;
466 /* Looking for headers */
467 sr->accept = mk_request_header_find(toc, toc_len, headers, mk_rh_accept);
468 sr->accept_charset = mk_request_header_find(toc, toc_len, headers,
469 mk_rh_accept_charset);
470 sr->accept_encoding = mk_request_header_find(toc, toc_len, headers,
471 mk_rh_accept_encoding);
474 sr->accept_language = mk_request_header_find(toc, toc_len, headers,
475 mk_rh_accept_language);
476 sr->cookies = mk_request_header_find(toc, toc_len, headers, mk_rh_cookie);
477 sr->connection = mk_request_header_find(toc, toc_len, headers,
478 mk_rh_connection);
479 sr->referer = mk_request_header_find(toc, toc_len, headers,
480 mk_rh_referer);
481 sr->user_agent = mk_request_header_find(toc, toc_len, headers,
482 mk_rh_user_agent);
483 sr->range = mk_request_header_find(toc, toc_len, headers, mk_rh_range);
484 sr->if_modified_since = mk_request_header_find(toc, toc_len, headers,
485 mk_rh_if_modified_since);
487 /* Default Keepalive is off */
488 sr->keep_alive = VAR_OFF;
489 if (sr->connection.data) {
490 if (mk_string_casestr(sr->connection.data, "Keep-Alive")) {
491 sr->keep_alive = VAR_ON;
494 else {
495 /* Default value for HTTP/1.1 */
496 if (sr->protocol == HTTP_PROTOCOL_11) {
497 /* Assume keep-alive connection */
498 sr->keep_alive = VAR_ON;
501 sr->log->final_response = M_HTTP_OK;
503 return 0;
506 /* Return value of some variable sent in request */
507 mk_pointer mk_request_header_find(struct header_toc * toc, int toc_len,
508 char *request_body, mk_pointer header)
510 int i;
511 mk_pointer var;
513 var.data = NULL;
514 var.len = 0;
516 /* new code */
517 if (toc) {
518 for (i = 0; i < toc_len; i++) {
519 /* status = 1 means that the toc entry was already
520 * checked by monkey
522 if (toc[i].status == 1) {
523 continue;
526 if (!toc[i].init)
527 break;
529 if (strncasecmp(toc[i].init, header.data, header.len) == 0) {
530 var.data = toc[i].init + header.len + 1;
531 var.len = toc[i].end - var.data;
532 toc[i].status = 1;
533 return var;
538 return var;
541 /* FIXME: IMPROVE access */
542 /* Look for some index.xxx in pathfile */
543 mk_pointer mk_request_index(char *pathfile)
545 unsigned long len;
546 char *file_aux = 0;
547 mk_pointer f;
548 struct indexfile *aux_index;
550 mk_pointer_reset(&f);
552 aux_index = first_index;
554 while (aux_index) {
555 m_build_buffer(&file_aux, &len, "%s%s",
556 pathfile, aux_index->indexname);
558 if (access(file_aux, F_OK) == 0) {
559 f.data = file_aux;
560 f.len = len;
561 return f;
563 mk_mem_free(file_aux);
564 aux_index = aux_index->next;
567 return f;
570 /* Send error responses */
571 void mk_request_error(int num_error, struct client_request *cr,
572 struct request *s_request, int debug,
573 struct log_info *s_log)
575 char *aux_message = 0;
576 mk_pointer message, *page = 0;
577 long n;
579 switch (num_error) {
580 case M_CLIENT_BAD_REQUEST:
581 page = mk_request_set_default_page("Bad Request",
582 s_request->uri,
583 s_request->host_conf->
584 host_signature);
585 s_log->error_msg = request_error_msg_400;
586 break;
588 case M_CLIENT_FORBIDDEN:
589 page = mk_request_set_default_page("Forbidden",
590 s_request->uri,
591 s_request->host_conf->
592 host_signature);
593 s_log->error_msg = request_error_msg_403;
594 s_log->error_details = s_request->uri;
595 break;
597 case M_CLIENT_NOT_FOUND:
598 m_build_buffer(&message.data, &message.len,
599 "The requested URL was not found on this server.");
600 page = mk_request_set_default_page("Not Found",
601 message,
602 s_request->host_conf->
603 host_signature);
604 s_log->error_msg = request_error_msg_404;
605 s_log->error_details = s_request->uri;
607 mk_pointer_free(&message);
608 break;
610 case M_CLIENT_METHOD_NOT_ALLOWED:
611 page = mk_request_set_default_page("Method Not Allowed",
612 s_request->uri,
613 s_request->host_conf->
614 host_signature);
616 s_log->final_response = M_CLIENT_METHOD_NOT_ALLOWED;
617 s_log->error_msg = request_error_msg_405;
618 s_log->error_details = s_request->method_p;
619 break;
621 case M_CLIENT_REQUEST_TIMEOUT:
622 s_log->status = S_LOG_OFF;
623 s_log->error_msg = request_error_msg_408;
624 break;
626 case M_CLIENT_LENGTH_REQUIRED:
627 s_log->error_msg = request_error_msg_411;
628 break;
630 case M_SERVER_NOT_IMPLEMENTED:
631 page = mk_request_set_default_page("Method Not Implemented",
632 s_request->uri,
633 s_request->host_conf->
634 host_signature);
635 s_log->final_response = M_SERVER_NOT_IMPLEMENTED;
636 s_log->error_msg = request_error_msg_501;
637 s_log->error_details = s_request->method_p;
638 break;
640 case M_SERVER_INTERNAL_ERROR:
641 m_build_buffer(&message.data, &message.len,
642 "Problems found running %s ", s_request->uri);
643 page = mk_request_set_default_page("Internal Server Error",
644 message,
645 s_request->host_conf->
646 host_signature);
647 s_log->error_msg = request_error_msg_500;
649 mk_pointer_free(&message);
650 break;
652 case M_SERVER_HTTP_VERSION_UNSUP:
653 mk_pointer_reset(&message);
654 page = mk_request_set_default_page("HTTP Version Not Supported",
655 message,
656 s_request->host_conf->
657 host_signature);
658 s_log->error_msg = request_error_msg_505;
659 break;
662 s_log->final_response = num_error;
664 s_request->headers->status = num_error;
665 if (page) {
666 s_request->headers->content_length = page->len;
667 s_request->headers->content_length_p = mk_utils_int2mkp(page->len);
670 s_request->headers->location = NULL;
671 s_request->headers->cgi = SH_NOCGI;
672 s_request->headers->pconnections_left = 0;
673 mk_pointer_reset(&s_request->headers->last_modified);
675 if (aux_message)
676 mk_mem_free(aux_message);
678 if (!page) {
679 mk_pointer_reset(&s_request->headers->content_type);
681 else {
682 mk_pointer_set(&s_request->headers->content_type, "text/html");
685 mk_header_send(cr->socket, cr, s_request, s_log);
687 if (debug == 1) {
688 n = write(cr->socket, page->data, page->len);
689 mk_pointer_free(page);
690 mk_mem_free(page);
694 /* Build error page */
695 mk_pointer *mk_request_set_default_page(char *title, mk_pointer message,
696 char *signature)
698 char *temp;
699 mk_pointer *p;
701 p = mk_mem_malloc(sizeof(mk_pointer));
703 temp = mk_pointer_to_buf(message);
704 m_build_buffer(&p->data, &p->len,
705 MK_REQUEST_DEFAULT_PAGE, title, temp, signature);
706 mk_mem_free(temp);
708 return p;
711 /* Create a memory allocation in order to handle the request data */
712 struct request *mk_request_alloc()
714 struct request *request = 0;
716 request = mk_mem_malloc(sizeof(struct request));
717 request->log = mk_mem_malloc(sizeof(struct log_info));
719 request->status = VAR_OFF; /* Request not processed yet */
720 request->make_log = VAR_ON; /* build log file of this request ? */
722 mk_pointer_reset(&request->body);
724 request->log->final_response = M_HTTP_OK;
725 request->log->status = S_LOG_ON;
726 mk_pointer_reset(&request->log->size_p);
727 mk_pointer_reset(&request->log->error_msg);
729 request->status = VAR_ON;
730 request->method = METHOD_NOT_FOUND;
732 mk_pointer_reset(&request->uri);
733 request->uri_processed = NULL;
734 request->uri_twin = VAR_OFF;
736 request->accept.data = NULL;
737 request->accept_language.data = NULL;
738 request->accept_encoding.data = NULL;
739 request->accept_charset.data = NULL;
740 request->content_length = 0;
741 request->content_type.data = NULL;
742 request->connection.data = NULL;
743 request->cookies.data = NULL;
744 request->host.data = NULL;
745 request->if_modified_since.data = NULL;
746 request->last_modified_since.data = NULL;
747 request->range.data = NULL;
748 request->referer.data = NULL;
749 request->resume.data = NULL;
750 request->user_agent.data = NULL;
752 request->post_variables.data = NULL;
754 request->user_uri = NULL;
755 mk_pointer_reset(&request->query_string);
757 request->file_info = NULL;
758 request->virtual_user = NULL;
759 request->script_filename = NULL;
760 mk_pointer_reset(&request->real_path);
761 request->host_conf = config->hosts;
763 request->loop = 0;
764 request->bytes_to_send = -1;
765 request->bytes_offset = 0;
766 request->fd_file = -1;
768 /* Response Headers */
769 request->headers = mk_header_create();
771 request->handled_by = NULL;
772 return request;
775 void mk_request_free_list(struct client_request *cr)
777 struct request *sr = 0, *before = 0;
779 /* sr = last node */
781 while (cr->request) {
782 sr = before = cr->request;
784 while (sr->next) {
785 sr = sr->next;
788 if (sr != cr->request) {
789 while (before->next != sr) {
790 before = before->next;
792 before->next = NULL;
794 else {
795 cr->request = NULL;
797 mk_request_free(sr);
799 cr->request = NULL;
802 void mk_request_free(struct request *sr)
804 /* I hate it, but I don't know another light way :( */
805 if (sr->fd_file > 0) {
806 close(sr->fd_file);
808 if (sr->headers) {
809 mk_mem_free(sr->headers->location);
810 mk_pointer_free(&sr->headers->content_length_p);
811 mk_pointer_free(&sr->headers->last_modified);
813 mk_mem_free(sr->headers->content_type);
814 headers->content_type never it's allocated
815 with malloc or something, so we don't need
816 to free it, the value has been freed before
817 in M_METHOD_Get_and_Head(struct request *sr)
819 this BUG was reported by gentoo team.. thanks guys XD
822 mk_mem_free(sr->headers);
826 if (sr->log) {
828 * We do not free log->size_p, as if it was
829 * used due to an error, it points to the
830 * same memory block than header->content_length_p
831 * points to, we just reset it.
833 mk_pointer_reset(&sr->log->size_p);
836 * sr->log->error_msg just point to
837 * local data on request.c, no
838 * dynamic allocation is made
841 mk_mem_free(sr->log);
844 mk_pointer_reset(&sr->body);
845 mk_pointer_reset(&sr->uri);
847 if (sr->uri_twin == VAR_ON) {
848 mk_mem_free(sr->uri_processed);
851 mk_pointer_free(&sr->post_variables);
852 mk_mem_free(sr->user_uri);
853 mk_pointer_reset(&sr->query_string);
855 mk_mem_free(sr->file_info);
856 mk_mem_free(sr->virtual_user);
857 mk_mem_free(sr->script_filename);
858 mk_pointer_free(&sr->real_path);
859 mk_mem_free(sr);
862 /* Create a client request struct and put it on the
863 * main list
865 struct client_request *mk_request_client_create(int socket)
867 struct request_idx *request_index;
868 struct client_request *cr;
869 struct sched_connection *sc;
871 sc = mk_sched_get_connection(NULL, socket);
872 cr = mk_mem_malloc(sizeof(struct client_request));
874 /* IPv4 Address */
875 cr->ipv4 = &sc->ipv4;
877 cr->pipelined = FALSE;
878 cr->counter_connections = 0;
879 cr->socket = socket;
880 cr->status = MK_REQUEST_STATUS_INCOMPLETE;
881 cr->request = NULL;
883 /* creation time in unix time */
884 cr->init_time = sc->arrive_time;
886 cr->next = NULL;
887 cr->body = mk_mem_malloc(MAX_REQUEST_BODY);
888 cr->body_length = 0;
889 cr->body_pos_end = -1;
890 cr->first_method = HTTP_METHOD_UNKNOWN;
892 request_index = mk_sched_get_request_index();
893 if (!request_index->first) {
894 request_index->first = request_index->last = cr;
896 else {
897 request_index->last->next = cr;
898 request_index->last = cr;
900 mk_sched_set_request_index(request_index);
902 return cr;
905 struct client_request *mk_request_client_get(int socket)
907 struct request_idx *request_index;
908 struct client_request *cr = NULL;
910 request_index = mk_sched_get_request_index();
911 cr = request_index->first;
912 while (cr != NULL) {
913 if (cr->socket == socket) {
914 break;
916 cr = cr->next;
919 return cr;
923 * From thread sched_list_node "list", remove the client_request
924 * struct information
926 struct client_request *mk_request_client_remove(int socket)
928 struct request_idx *request_index;
929 struct client_request *cr, *aux;
931 request_index = mk_sched_get_request_index();
932 cr = request_index->first;
934 while (cr) {
935 if (cr->socket == socket) {
936 if (cr == request_index->first) {
937 request_index->first = cr->next;
939 else {
940 aux = request_index->first;
941 while (aux->next != cr) {
942 aux = aux->next;
944 aux->next = cr->next;
945 if (!aux->next) {
946 request_index->last = aux;
949 break;
951 cr = cr->next;
954 //mk_pointer_free(&cr->ip);
955 mk_mem_free(cr->body);
956 mk_mem_free(cr);
958 return NULL;
961 struct header_toc *mk_request_header_toc_create(int len)
963 int i;
964 struct header_toc *p;
966 p = (struct header_toc *) pthread_getspecific(mk_cache_header_toc);
968 for (i = 0; i < len; i++) {
969 p[i].init = NULL;
970 p[i].end = NULL;
971 p[i].status = 0;
973 return p;
976 void mk_request_header_toc_parse(struct header_toc *toc, char *data, int len)
978 char *p, *l;
979 int i;
981 p = data;
982 for (i = 0; i < len && p; i++) {
983 l = strstr(p, MK_CRLF);
984 if (l) {
985 toc[i].init = p;
986 toc[i].end = l;
987 p = l + mk_crlf.len;
989 else {
990 break;
995 void mk_request_ka_next(struct client_request *cr)
997 bzero(cr->body, sizeof(cr->body));
998 cr->first_method = -1;
999 cr->body_pos_end = -1;
1000 cr->body_length = 0;
1001 cr->counter_connections++;