Change Monkey HTTP signature
[MonkeyD.git] / src / request.c
blob05663789d9546c5ea9b0677417d4e8f618dc417f
1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 /* Monkey HTTP Daemon
4 * ------------------
5 * Copyright (C) 2001-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.
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, n, init_block = 0, n_blocks = 0;
65 int pipelined = FALSE;
66 struct request *cr_buf = 0, *cr_search = 0;
68 init_block = 0;
70 for (i = cr->first_block_end; i <= cr->body_length - mk_endblock.len; i++) {
71 /* Allocating request block */
72 cr_buf = mk_request_alloc();
74 /* mk_pointer */
75 cr_buf->body.data = cr->body + init_block;
76 cr_buf->body.len = i - init_block;
78 if (i == cr->first_block_end) {
79 cr_buf->method = cr->first_method;
81 else {
82 cr_buf->method = mk_http_method_get(cr_buf->body.data);
85 cr_buf->next = NULL;
87 i = init_block = i + mk_endblock.len;
89 /* Looking for POST data */
90 if (cr_buf->method == HTTP_METHOD_POST) {
91 cr_buf->post_variables = mk_method_post_get_vars(cr->body, i);
93 if (cr_buf->post_variables.len >= 0) {
94 i = init_block = i + cr_buf->post_variables.len;
98 if (!cr->request) {
99 cr->request = cr_buf;
101 else {
102 cr_search = cr->request;
103 while (cr_search) {
104 if (cr_search->next == NULL) {
105 cr_search->next = cr_buf;
106 break;
108 else {
109 cr_search = cr_search->next;
113 n_blocks++;
114 n = mk_string_search(cr->body + i, mk_endblock.data);
115 if (n <= 0) {
116 break;
118 else {
119 i = i + n;
123 /* Checking pipelining connection */
124 cr_search = cr->request;
125 if (n_blocks > 1) {
126 pipelined = TRUE;
128 while (cr_search) {
129 if (cr_search->method != HTTP_METHOD_GET &&
130 cr_search->method != HTTP_METHOD_HEAD) {
131 pipelined = FALSE;
132 break;
134 cr_search = cr_search->next;
137 if (pipelined == FALSE) {
138 /* All pipelined requests must use GET method */
139 return NULL;
141 else {
142 cr->pipelined = TRUE;
146 /* DEBUG BLOCKS
147 printf("*****************************************");
148 fflush(stdout);
149 cr_search = cr->request;
150 while(cr_search){
151 printf("\n---BLOCK---:\n%s---END BLOCK---\n\n", cr_search->body);
152 fflush(stdout);
153 cr_search = cr_search->next;
157 return cr->request;
160 int mk_handler_read(int socket, struct client_request *cr)
162 int bytes;
164 bytes = read(socket, cr->body + cr->body_length,
165 MAX_REQUEST_BODY - cr->body_length);
167 if (bytes < 0) {
168 if (errno == EAGAIN) {
169 return 1;
171 else {
172 mk_request_client_remove(socket);
173 return -1;
176 if (bytes == 0) {
177 mk_request_client_remove(socket);
178 return -1;
181 if (bytes > 0) {
182 cr->body_length += bytes;
183 cr->body[cr->body_length] = '\0';
186 return bytes;
189 int mk_handler_write(int socket, struct client_request *cr)
191 int bytes, final_status = 0;
192 struct request *sr;
195 * Get node from schedule list node which contains
196 * the information regarding to the current thread
198 if (!cr) {
199 return -1;
202 if (!cr->request) {
203 if (!mk_request_parse(cr)) {
204 return -1;
208 sr = cr->request;
210 while (sr) {
211 /* Request not processed also no plugin has take some action */
212 if (sr->bytes_to_send < 0 && !sr->handled_by) {
213 final_status = mk_request_process(cr, sr);
215 /* Request with data to send by static file sender */
216 else if (sr->bytes_to_send > 0 && !sr->handled_by) {
217 bytes = SendFile(socket, cr, sr);
218 final_status = bytes;
220 else if (sr->handled_by){
221 /* FIXME: Look for loops
222 * sr->handled_by; */
226 * If we got an error, we don't want to parse
227 * and send information for another pipelined request
229 if (final_status > 0) {
230 return final_status;
232 else if (final_status <= 0) {
233 mk_logger_write_log(cr, sr->log, sr->host_conf);
236 sr = sr->next;
239 /* If we are here, is because all pipelined request were
240 * processed successfully, let's return 0;
242 return 0;
245 int mk_request_process(struct client_request *cr, struct request *s_request)
247 int status = 0;
248 struct host *host;
250 status = mk_request_header_process(s_request);
252 if (status < 0) {
253 return EXIT_NORMAL;
256 switch (s_request->method) {
257 case METHOD_NOT_ALLOWED:
258 mk_request_error(M_CLIENT_METHOD_NOT_ALLOWED, cr,
259 s_request, 1, s_request->log);
260 return EXIT_NORMAL;
261 case METHOD_NOT_FOUND:
262 mk_request_error(M_SERVER_NOT_IMPLEMENTED, cr,
263 s_request, 1, s_request->log);
264 return EXIT_NORMAL;
267 s_request->user_home = VAR_OFF;
268 s_request->log->method = s_request->method;
270 /* Valid request URI? */
271 if (s_request->uri_processed == NULL) {
272 mk_request_error(M_CLIENT_BAD_REQUEST, cr, s_request, 1,
273 s_request->log);
274 return EXIT_NORMAL;
277 /* HTTP/1.1 needs Host header */
278 if (!s_request->host.data && s_request->protocol == HTTP_PROTOCOL_11) {
279 s_request->log->final_response = M_CLIENT_BAD_REQUEST;
280 mk_request_error(M_CLIENT_BAD_REQUEST, cr, s_request, 1,
281 s_request->log);
282 return EXIT_NORMAL;
285 /* Method not allowed ? */
286 if (s_request->method == METHOD_NOT_ALLOWED) {
287 s_request->log->final_response = M_CLIENT_METHOD_NOT_ALLOWED;
288 mk_request_error(M_CLIENT_METHOD_NOT_ALLOWED, cr, s_request, 1,
289 s_request->log);
290 return EXIT_NORMAL;
293 /* Validating protocol version */
294 if (s_request->protocol == HTTP_PROTOCOL_UNKNOWN) {
296 s_request->log->final_response = M_SERVER_HTTP_VERSION_UNSUP;
297 mk_request_error(M_SERVER_HTTP_VERSION_UNSUP, cr, s_request, 1,
298 s_request->log);
299 return EXIT_NORMAL;
302 if (s_request->host.data) {
303 host = mk_config_host_find(s_request->host);
304 if (host) {
305 s_request->host_conf = host;
307 else {
308 s_request->host_conf = config->hosts;
311 else {
312 s_request->host_conf = config->hosts;
314 s_request->log->host_conf = s_request->host_conf;
316 /* is requesting an user home directory ? */
317 if (config->user_dir) {
318 if (strncmp(s_request->uri_processed,
319 mk_user_home.data, mk_user_home.len) == 0) {
320 if (mk_user_init(cr, s_request) != 0) {
321 return EXIT_NORMAL;
326 /* Handling method requested */
327 if (s_request->method == HTTP_METHOD_POST) {
328 if ((status = mk_method_post(cr, s_request)) == -1) {
329 return status;
333 status = mk_http_init(cr, s_request);
335 #ifdef TRACE
336 MK_TRACE("HTTP Init returning %i", status);
337 #endif
339 return status;
342 /* Return a struct with method, URI , protocol version
343 and all static headers defined here sent in request */
344 int mk_request_header_process(struct request *sr)
346 int uri_init = 0, uri_end = 0;
347 char *query_init = 0;
348 int prot_init = 0, prot_end = 0, pos_sep = 0;
349 int fh_limit;
350 char *port = 0;
351 char *headers;
352 mk_pointer host;
354 /* If verification fails it will return always
355 * a bad request status
357 sr->log->final_response = M_CLIENT_BAD_REQUEST;
359 /* Method */
360 sr->method_p = mk_http_method_check_str(sr->method);
362 /* Request URI */
363 uri_init = (index(sr->body.data, ' ') - sr->body.data) + 1;
364 fh_limit = (index(sr->body.data, '\n') - sr->body.data);
366 uri_end = mk_string_search_r(sr->body.data, ' ', fh_limit) - 1;
368 if (uri_end <= 0) {
369 return -1;
372 prot_init = uri_end + 2;
374 if (uri_end < uri_init) {
375 return -1;
378 /* Query String */
379 query_init = index(sr->body.data + uri_init, '?');
380 if (query_init) {
381 int init, end;
383 init = (int) (query_init - (sr->body.data + uri_init)) + uri_init;
384 if (init <= uri_end) {
385 end = uri_end;
386 uri_end = init - 1;
388 sr->query_string = mk_pointer_create(sr->body.data,
389 init + 1, end + 1);
393 /* Request URI Part 2 */
394 sr->uri = sr->log->uri = mk_pointer_create(sr->body.data,
395 uri_init, uri_end + 1);
397 if (sr->uri.len < 1) {
398 return -1;
402 /* HTTP Version */
403 prot_end = fh_limit - 1;
404 if (prot_end != prot_init && prot_end > 0) {
405 sr->protocol = sr->log->protocol =
406 mk_http_protocol_check(sr->body.data + prot_init,
407 prot_end - prot_init);
410 headers = sr->body.data + prot_end + mk_crlf.len;
412 /* URI processed */
413 sr->uri_processed = get_real_string(sr->uri);
415 if (!sr->uri_processed) {
416 sr->uri_processed = mk_pointer_to_buf(sr->uri);
417 sr->uri_twin = VAR_ON;
420 /* Creating table of content (index) for request headers */
421 int toc_len = MK_KNOWN_HEADERS;
422 struct header_toc *toc = mk_request_header_toc_create(toc_len);
423 mk_request_header_toc_parse(toc, headers, toc_len);
425 /* Host */
426 host = mk_request_header_find(toc, toc_len, headers, mk_rh_host);
428 if (host.data) {
429 if ((pos_sep = mk_string_char_search(host.data, ':', host.len)) >= 0) {
430 sr->host.data = host.data;
431 sr->host.len = pos_sep;
433 port = mk_string_copy_substr(host.data, pos_sep + 1, host.len);
434 sr->port = atoi(port);
435 mk_mem_free(port);
437 else {
438 sr->host = host; /* maybe null */
439 sr->port = config->standard_port;
442 else {
443 sr->host.data = NULL;
446 /* Looking for headers */
447 sr->accept = mk_request_header_find(toc, toc_len, headers, mk_rh_accept);
448 sr->accept_charset = mk_request_header_find(toc, toc_len, headers,
449 mk_rh_accept_charset);
450 sr->accept_encoding = mk_request_header_find(toc, toc_len, headers,
451 mk_rh_accept_encoding);
454 sr->accept_language = mk_request_header_find(toc, toc_len, headers,
455 mk_rh_accept_language);
456 sr->cookies = mk_request_header_find(toc, toc_len, headers, mk_rh_cookie);
457 sr->connection = mk_request_header_find(toc, toc_len, headers,
458 mk_rh_connection);
459 sr->referer = mk_request_header_find(toc, toc_len, headers,
460 mk_rh_referer);
461 sr->user_agent = mk_request_header_find(toc, toc_len, headers,
462 mk_rh_user_agent);
463 sr->range = mk_request_header_find(toc, toc_len, headers, mk_rh_range);
464 sr->if_modified_since = mk_request_header_find(toc, toc_len, headers,
465 mk_rh_if_modified_since);
467 /* Default Keepalive is off */
468 sr->keep_alive = VAR_OFF;
469 if (sr->connection.data) {
470 if (mk_string_casestr(sr->connection.data, "Keep-Alive")) {
471 sr->keep_alive = VAR_ON;
474 else {
475 /* Default value for HTTP/1.1 */
476 if (sr->protocol == HTTP_PROTOCOL_11) {
477 /* Assume keep-alive connection */
478 sr->keep_alive = VAR_ON;
481 sr->log->final_response = M_HTTP_OK;
483 return 0;
486 /* Return value of some variable sent in request */
487 mk_pointer mk_request_header_find(struct header_toc * toc, int toc_len,
488 char *request_body, mk_pointer header)
490 int i;
491 mk_pointer var;
493 var.data = NULL;
494 var.len = 0;
496 /* new code */
497 if (toc) {
498 for (i = 0; i < toc_len; i++) {
499 /* status = 1 means that the toc entry was already
500 * checked by monkey
502 if (toc[i].status == 1) {
503 continue;
506 if (!toc[i].init)
507 break;
509 if (strncasecmp(toc[i].init, header.data, header.len) == 0) {
510 var.data = toc[i].init + header.len + 1;
511 var.len = toc[i].end - var.data;
512 toc[i].status = 1;
513 return var;
518 return var;
521 /* FIXME: IMPROVE access */
522 /* Look for some index.xxx in pathfile */
523 mk_pointer mk_request_index(char *pathfile)
525 unsigned long len;
526 char *file_aux = 0;
527 mk_pointer f;
528 struct indexfile *aux_index;
530 mk_pointer_reset(&f);
532 aux_index = first_index;
534 while (aux_index) {
535 m_build_buffer(&file_aux, &len, "%s%s",
536 pathfile, aux_index->indexname);
538 if (access(file_aux, F_OK) == 0) {
539 f.data = file_aux;
540 f.len = len;
541 return f;
543 mk_mem_free(file_aux);
544 aux_index = aux_index->next;
547 return f;
550 /* Send error responses */
551 void mk_request_error(int num_error, struct client_request *cr,
552 struct request *s_request, int debug,
553 struct log_info *s_log)
555 char *aux_message = 0;
556 mk_pointer message, *page = 0;
557 long n;
559 switch (num_error) {
560 case M_CLIENT_BAD_REQUEST:
561 page = mk_request_set_default_page("Bad Request",
562 s_request->uri,
563 s_request->host_conf->
564 host_signature);
565 s_log->error_msg = request_error_msg_400;
566 break;
568 case M_CLIENT_FORBIDDEN:
569 page = mk_request_set_default_page("Forbidden",
570 s_request->uri,
571 s_request->host_conf->
572 host_signature);
573 s_log->error_msg = request_error_msg_403;
574 s_log->error_details = s_request->uri;
575 break;
577 case M_CLIENT_NOT_FOUND:
578 m_build_buffer(&message.data, &message.len,
579 "The requested URL was not found on this server.");
580 page = mk_request_set_default_page("Not Found",
581 message,
582 s_request->host_conf->
583 host_signature);
584 s_log->error_msg = request_error_msg_404;
585 s_log->error_details = s_request->uri;
587 mk_pointer_free(&message);
588 break;
590 case M_CLIENT_METHOD_NOT_ALLOWED:
591 page = mk_request_set_default_page("Method Not Allowed",
592 s_request->uri,
593 s_request->host_conf->
594 host_signature);
596 s_log->final_response = M_CLIENT_METHOD_NOT_ALLOWED;
597 s_log->error_msg = request_error_msg_405;
598 s_log->error_details = s_request->method_p;
599 break;
601 case M_CLIENT_REQUEST_TIMEOUT:
602 s_log->status = S_LOG_OFF;
603 s_log->error_msg = request_error_msg_408;
604 break;
606 case M_CLIENT_LENGTH_REQUIRED:
607 s_log->error_msg = request_error_msg_411;
608 break;
610 case M_SERVER_NOT_IMPLEMENTED:
611 page = mk_request_set_default_page("Method Not Implemented",
612 s_request->uri,
613 s_request->host_conf->
614 host_signature);
615 s_log->final_response = M_SERVER_NOT_IMPLEMENTED;
616 s_log->error_msg = request_error_msg_501;
617 s_log->error_details = s_request->method_p;
618 break;
620 case M_SERVER_INTERNAL_ERROR:
621 m_build_buffer(&message.data, &message.len,
622 "Problems found running %s ", s_request->uri);
623 page = mk_request_set_default_page("Internal Server Error",
624 message,
625 s_request->host_conf->
626 host_signature);
627 s_log->error_msg = request_error_msg_500;
629 mk_pointer_free(&message);
630 break;
632 case M_SERVER_HTTP_VERSION_UNSUP:
633 mk_pointer_reset(&message);
634 page = mk_request_set_default_page("HTTP Version Not Supported",
635 message,
636 s_request->host_conf->
637 host_signature);
638 s_log->error_msg = request_error_msg_505;
639 break;
642 s_log->final_response = num_error;
644 s_request->headers->status = num_error;
645 if (page) {
646 s_request->headers->content_length = page->len;
647 s_request->headers->content_length_p = mk_utils_int2mkp(page->len);
650 s_request->headers->location = NULL;
651 s_request->headers->cgi = SH_NOCGI;
652 s_request->headers->pconnections_left = 0;
653 mk_pointer_reset(&s_request->headers->last_modified);
655 if (aux_message)
656 mk_mem_free(aux_message);
658 if (!page) {
659 mk_pointer_reset(&s_request->headers->content_type);
661 else {
662 mk_pointer_set(&s_request->headers->content_type, "text/html");
665 mk_header_send(cr->socket, cr, s_request, s_log);
667 if (debug == 1) {
668 n = write(cr->socket, page->data, page->len);
669 mk_pointer_free(page);
670 mk_mem_free(page);
674 /* Build error page */
675 mk_pointer *mk_request_set_default_page(char *title, mk_pointer message,
676 char *signature)
678 char *temp;
679 mk_pointer *p;
681 p = mk_mem_malloc(sizeof(mk_pointer));
683 temp = mk_pointer_to_buf(message);
684 m_build_buffer(&p->data, &p->len,
685 MK_REQUEST_DEFAULT_PAGE, title, temp, signature);
686 mk_mem_free(temp);
688 return p;
691 /* Create a memory allocation in order to handle the request data */
692 struct request *mk_request_alloc()
694 struct request *request = 0;
696 request = mk_mem_malloc(sizeof(struct request));
697 request->log = mk_mem_malloc(sizeof(struct log_info));
699 request->status = VAR_OFF; /* Request not processed yet */
700 request->make_log = VAR_ON; /* build log file of this request ? */
702 mk_pointer_reset(&request->body);
704 request->log->final_response = M_HTTP_OK;
705 request->log->status = S_LOG_ON;
706 mk_pointer_reset(&request->log->size_p);
707 mk_pointer_reset(&request->log->error_msg);
709 request->status = VAR_ON;
710 request->method = METHOD_NOT_FOUND;
712 mk_pointer_reset(&request->uri);
713 request->uri_processed = NULL;
714 request->uri_twin = VAR_OFF;
716 request->accept.data = NULL;
717 request->accept_language.data = NULL;
718 request->accept_encoding.data = NULL;
719 request->accept_charset.data = NULL;
720 request->content_length = 0;
721 request->content_type.data = NULL;
722 request->connection.data = NULL;
723 request->cookies.data = NULL;
724 request->host.data = NULL;
725 request->if_modified_since.data = NULL;
726 request->last_modified_since.data = NULL;
727 request->range.data = NULL;
728 request->referer.data = NULL;
729 request->resume.data = NULL;
730 request->user_agent.data = NULL;
732 request->post_variables.data = NULL;
734 request->user_uri = NULL;
735 mk_pointer_reset(&request->query_string);
737 request->file_info = NULL;
738 request->virtual_user = NULL;
739 request->script_filename = NULL;
740 mk_pointer_reset(&request->real_path);
741 request->host_conf = config->hosts;
743 request->loop = 0;
744 request->bytes_to_send = -1;
745 request->bytes_offset = 0;
746 request->fd_file = -1;
748 /* Response Headers */
749 request->headers = mk_header_create();
751 request->handled_by = NULL;
752 return request;
755 void mk_request_free_list(struct client_request *cr)
757 struct request *sr = 0, *before = 0;
759 /* sr = last node */
761 while (cr->request) {
762 sr = before = cr->request;
764 while (sr->next) {
765 sr = sr->next;
768 if (sr != cr->request) {
769 while (before->next != sr) {
770 before = before->next;
772 before->next = NULL;
774 else {
775 cr->request = NULL;
777 mk_request_free(sr);
779 cr->request = NULL;
782 void mk_request_free(struct request *sr)
784 /* I hate it, but I don't know another light way :( */
785 if (sr->fd_file > 0) {
786 close(sr->fd_file);
788 if (sr->headers) {
789 mk_mem_free(sr->headers->location);
790 mk_pointer_free(&sr->headers->content_length_p);
791 mk_pointer_free(&sr->headers->last_modified);
793 mk_mem_free(sr->headers->content_type);
794 headers->content_type never it's allocated
795 with malloc or something, so we don't need
796 to free it, the value has been freed before
797 in M_METHOD_Get_and_Head(struct request *sr)
799 this BUG was reported by gentoo team.. thanks guys XD
802 mk_mem_free(sr->headers);
806 if (sr->log) {
808 * We do not free log->size_p, as if it was
809 * used due to an error, it points to the
810 * same memory block than header->content_length_p
811 * points to, we just reset it.
813 mk_pointer_reset(&sr->log->size_p);
816 * sr->log->error_msg just point to
817 * local data on request.c, no
818 * dynamic allocation is made
821 mk_mem_free(sr->log);
824 mk_pointer_reset(&sr->body);
825 mk_pointer_reset(&sr->uri);
827 if (sr->uri_twin == VAR_ON) {
828 mk_mem_free(sr->uri_processed);
831 mk_pointer_free(&sr->post_variables);
832 mk_mem_free(sr->user_uri);
833 mk_pointer_reset(&sr->query_string);
835 mk_mem_free(sr->file_info);
836 mk_mem_free(sr->virtual_user);
837 mk_mem_free(sr->script_filename);
838 mk_pointer_free(&sr->real_path);
839 mk_mem_free(sr);
842 /* Create a client request struct and put it on the
843 * main list
845 struct client_request *mk_request_client_create(int socket)
847 struct request_idx *request_index;
848 struct client_request *cr;
849 struct sched_connection *sc;
851 sc = mk_sched_get_connection(NULL, socket);
852 cr = mk_mem_malloc(sizeof(struct client_request));
854 /* IPv4 Address */
855 cr->ipv4 = &sc->ipv4;
857 cr->pipelined = FALSE;
858 cr->counter_connections = 0;
859 cr->socket = socket;
860 cr->status = MK_REQUEST_STATUS_INCOMPLETE;
861 cr->request = NULL;
863 /* creation time in unix time */
864 cr->init_time = sc->arrive_time;
866 cr->next = NULL;
867 cr->body = mk_mem_malloc(MAX_REQUEST_BODY);
868 cr->body_length = 0;
869 cr->first_block_end = -1;
870 cr->first_method = HTTP_METHOD_UNKNOWN;
872 request_index = mk_sched_get_request_index();
873 if (!request_index->first) {
874 request_index->first = request_index->last = cr;
876 else {
877 request_index->last->next = cr;
878 request_index->last = cr;
880 mk_sched_set_request_index(request_index);
883 mk_sched_update_thread_status(NULL,
884 MK_SCHEDULER_ACTIVE_UP,
885 MK_SCHEDULER_CLOSED_NONE);
887 return cr;
890 struct client_request *mk_request_client_get(int socket)
892 struct request_idx *request_index;
893 struct client_request *cr = NULL;
895 request_index = mk_sched_get_request_index();
896 cr = request_index->first;
897 while (cr != NULL) {
898 if (cr->socket == socket) {
899 break;
901 cr = cr->next;
904 return cr;
908 * From thread sched_list_node "list", remove the client_request
909 * struct information
911 struct client_request *mk_request_client_remove(int socket)
913 struct request_idx *request_index;
914 struct client_request *cr, *aux;
916 request_index = mk_sched_get_request_index();
917 cr = request_index->first;
919 while (cr) {
920 if (cr->socket == socket) {
921 if (cr == request_index->first) {
922 request_index->first = cr->next;
924 else {
925 aux = request_index->first;
926 while (aux->next != cr) {
927 aux = aux->next;
929 aux->next = cr->next;
930 if (!aux->next) {
931 request_index->last = aux;
934 break;
936 cr = cr->next;
939 /* No keep alive connection */
940 if (cr->counter_connections == 0) {
941 mk_sched_update_thread_status(NULL,
942 MK_SCHEDULER_ACTIVE_DOWN,
943 MK_SCHEDULER_CLOSED_UP);
945 //mk_pointer_free(&cr->ip);
946 mk_mem_free(cr->body);
947 mk_mem_free(cr);
949 return NULL;
952 struct header_toc *mk_request_header_toc_create(int len)
954 int i;
955 struct header_toc *p;
957 p = (struct header_toc *) pthread_getspecific(mk_cache_header_toc);
959 for (i = 0; i < len; i++) {
960 p[i].init = NULL;
961 p[i].end = NULL;
962 p[i].status = 0;
964 return p;
967 void mk_request_header_toc_parse(struct header_toc *toc, char *data, int len)
969 char *p, *l;
970 int i;
972 p = data;
973 for (i = 0; i < len && p; i++) {
974 l = strstr(p, MK_CRLF);
975 if (l) {
976 toc[i].init = p;
977 toc[i].end = l;
978 p = l + mk_crlf.len;
980 else {
981 break;
986 void mk_request_ka_next(struct client_request *cr)
988 bzero(cr->body, sizeof(cr->body));
989 cr->first_method = -1;
990 cr->first_block_end = -1;
991 cr->body_length = 0;
992 cr->counter_connections++;