error to set_default_page return pointer
[MonkeyD.git] / src / request.c
bloba19a46c55854a392b02c373e7189e9c27c48693d
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 "cgi.h"
47 #include "str.h"
48 #include "config.h"
49 #include "scheduler.h"
50 #include "epoll.h"
51 #include "socket.h"
52 #include "logfile.h"
53 #include "utils.h"
54 #include "header.h"
55 #include "deny.h"
56 #include "user.h"
57 #include "method.h"
58 #include "memory.h"
59 #include "socket.h"
60 #include "cache.h"
61 #include "clock.h"
63 struct request *mk_request_parse(struct client_request *cr)
65 int i, n, init_block=0, n_blocks=0;
66 int pipelined=FALSE;
67 struct request *cr_buf=0, *cr_search=0;
69 init_block = 0;
71 for(i=cr->first_block_end; i<=cr->body_length-mk_endblock.len; i++)
73 /* Allocating request block */
74 cr_buf = mk_request_alloc();
76 /* mk_pointer */
77 cr_buf->body.data = cr->body+init_block;
78 cr_buf->body.len = i-init_block;
80 if(i==cr->first_block_end){
81 cr_buf->method = cr->first_method;
83 else{
84 cr_buf->method = mk_http_method_get(cr_buf->body.data);
87 cr_buf->log->ip = cr->ip;
88 cr_buf->next = NULL;
90 i = init_block = i + mk_endblock.len;
92 /* Looking for POST data */
93 if(cr_buf->method == HTTP_METHOD_POST)
95 cr_buf->post_variables =
96 mk_method_post_get_vars(cr->body, i);
98 if(cr_buf->post_variables.len >= 0)
100 i = init_block = i+cr_buf->post_variables.len;
104 if(!cr->request)
106 cr->request = cr_buf;
108 else{
109 cr_search = cr->request;
110 while(cr_search)
112 if(cr_search->next==NULL)
114 cr_search->next = cr_buf;
115 break;
117 else
119 cr_search = cr_search->next;
123 n_blocks++;
124 n = mk_string_search(cr->body+i, mk_endblock.data);
125 if(n<=0)
127 break;
129 else{
130 i = i + n;
134 /* Checking pipelining connection */
135 cr_search = cr->request;
136 if(n_blocks>1)
138 pipelined = TRUE;
140 while(cr_search){
141 if(cr_search->method!=HTTP_METHOD_GET &&
142 cr_search->method!=HTTP_METHOD_HEAD)
144 pipelined = FALSE;
145 break;
147 cr_search = cr_search->next;
150 if(pipelined == FALSE){
151 /* All pipelined requests must use GET method */
152 return NULL;
154 else{
155 cr->pipelined = TRUE;
159 /* DEBUG BLOCKS
160 printf("*****************************************");
161 fflush(stdout);
162 cr_search = cr->request;
163 while(cr_search){
164 printf("\n---BLOCK---:\n%s---END BLOCK---\n\n", cr_search->body);
165 fflush(stdout);
166 cr_search = cr_search->next;
170 return cr->request;
173 int mk_handler_read(int socket)
175 int bytes, efd;
176 struct client_request *cr;
178 cr = mk_request_client_get(socket);
179 if(!cr)
181 /* Note: Linux don't set TCP_NODELAY socket flag by default,
182 * also we set the client socket on non-blocking mode
184 mk_socket_set_tcp_nodelay(socket);
185 mk_socket_set_nonblocking(socket);
187 cr = mk_request_client_create(socket);
189 /* Update requests counter */
190 mk_sched_update_thread_status(MK_SCHEDULER_ACTIVE_UP,
191 MK_SCHEDULER_CLOSED_DOWN);
193 else{
194 /* If cr struct already exists, that could means that we
195 * are facing a keepalive connection, need to verify, if it
196 * applies we increase the thread status for active connections
198 if(cr->counter_connections > 1 && cr->body_length == 0){
199 mk_sched_update_thread_status(MK_SCHEDULER_ACTIVE_UP,
200 MK_SCHEDULER_CLOSED_NONE);
204 bytes = read(socket, cr->body+cr->body_length,
205 MAX_REQUEST_BODY-cr->body_length);
207 if (bytes < 0) {
208 if (errno == EAGAIN) {
209 return 1;
211 else{
212 mk_request_client_remove(socket);
213 return -1;
216 if (bytes == 0){
217 mk_request_client_remove(socket);
218 return -1;
221 if(bytes > 0)
223 cr->body_length+=bytes;
224 cr->body[cr->body_length] = '\0';
226 if(mk_http_pending_request(cr)==0){
227 efd = mk_sched_get_thread_poll();
228 mk_epoll_socket_change_mode(efd, socket,
229 MK_EPOLL_WRITE);
231 else if(cr->body_length+1 >= MAX_REQUEST_BODY)
233 /* Request is incomplete and our buffer is full,
234 * close connection
236 mk_request_client_remove(socket);
237 return -1;
241 return 0;
244 int mk_handler_write(int socket, struct client_request *cr)
246 int bytes, final_status=0;
247 struct request *p_request;
250 * Get node from schedule list node which contains
251 * the information regarding to the current thread
253 cr = mk_request_client_get(socket);
255 if(!cr)
257 return -1;
260 if(!cr->request)
262 if(!mk_request_parse(cr))
264 return -1;
268 p_request = cr->request;
270 while(p_request)
272 /* Request not processed */
273 if(p_request->bytes_to_send < 0)
275 final_status = mk_request_process(cr, p_request);
277 /* Request with data to send */
278 else if(p_request->bytes_to_send>0)
280 bytes = SendFile(socket, cr, p_request);
281 final_status = bytes;
284 * If we got an error, we don't want to parse
285 * and send information for another pipelined request
287 if(final_status > 0)
289 return final_status;
291 else if(final_status <= 0)
293 mk_logger_write_log(p_request->log, p_request->host_conf);
295 p_request = p_request->next;
298 /* If we are here, is because all pipelined request were
299 * processed successfully, let's return 0;
301 return 0;
304 int mk_request_process(struct client_request *cr, struct request *s_request)
306 int status=0;
307 struct host *host;
309 status = mk_request_header_process(s_request);
311 if(status<0)
313 return EXIT_NORMAL;
316 switch(s_request->method)
318 case METHOD_NOT_ALLOWED:
319 mk_request_error(M_CLIENT_METHOD_NOT_ALLOWED, cr,
320 s_request, 1, s_request->log);
321 return EXIT_NORMAL;
322 case METHOD_NOT_FOUND:
323 mk_request_error(M_SERVER_NOT_IMPLEMENTED, cr,
324 s_request, 1, s_request->log);
325 return EXIT_NORMAL;
328 s_request->user_home=VAR_OFF;
329 s_request->log->method = s_request->method;
331 /* Valid request URI? */
332 if(s_request->uri_processed==NULL){
333 mk_request_error(M_CLIENT_BAD_REQUEST, cr, s_request, 1,
334 s_request->log);
335 return EXIT_NORMAL;
338 /* URL it's Allowed ? */
339 if(Deny_Check(s_request, cr->ip.data)==-1) {
340 s_request->log->final_response=M_CLIENT_FORBIDDEN;
341 mk_request_error(M_CLIENT_FORBIDDEN, cr, s_request, 1,
342 s_request->log);
343 return EXIT_NORMAL;
347 /* HTTP/1.1 needs Host header */
348 if(!s_request->host.data && s_request->protocol==HTTP_PROTOCOL_11){
349 s_request->log->final_response=M_CLIENT_BAD_REQUEST;
350 mk_request_error(M_CLIENT_BAD_REQUEST, cr, s_request,1,
351 s_request->log);
352 return EXIT_NORMAL;
355 /* Method not allowed ? */
356 if(s_request->method==METHOD_NOT_ALLOWED){
357 s_request->log->final_response=M_CLIENT_METHOD_NOT_ALLOWED;
358 mk_request_error(M_CLIENT_METHOD_NOT_ALLOWED, cr, s_request, 1,
359 s_request->log);
360 return EXIT_NORMAL;
363 /* Validating protocol version */
364 if(s_request->protocol == HTTP_PROTOCOL_UNKNOWN)
367 s_request->log->final_response=M_SERVER_HTTP_VERSION_UNSUP;
368 mk_request_error(M_SERVER_HTTP_VERSION_UNSUP, cr, s_request, 1,
369 s_request->log);
370 return EXIT_NORMAL;
373 if(s_request->host.data)
375 host=mk_config_host_find(s_request->host);
376 if(host)
378 s_request->host_conf = host;
380 else{
381 s_request->host_conf = config->hosts;
384 else{
385 s_request->host_conf = config->hosts;
387 s_request->log->host_conf = s_request->host_conf;
389 /* is requesting an user home directory ? */
390 if(config->user_dir){
391 if(strncmp(s_request->uri_processed,
392 mk_user_home.data,
393 mk_user_home.len)==0){
394 if(mk_user_init(cr, s_request)!=0){
395 return EXIT_NORMAL;
400 /* Handling method requested */
401 if(s_request->method==HTTP_METHOD_POST)
403 if((status=mk_method_post(cr, s_request))==-1){
404 return status;
408 status = mk_http_init(cr, s_request);
410 return status;
413 /* Return a struct with method, URI , protocol version
414 and all static headers defined here sent in request */
415 int mk_request_header_process(struct request *sr)
417 int uri_init=0, uri_end=0;
418 char *query_init=0;
419 int prot_init=0, prot_end=0, pos_sep=0;
420 int fh_limit;
421 char *port=0;
422 char *headers;
423 mk_pointer host;
425 /* If verification fails it will return always
426 * a bad request status
428 sr->log->final_response = M_CLIENT_BAD_REQUEST;
430 /* Method */
431 sr->method_p = mk_http_method_check_str(sr->method);
433 /* Request URI */
434 uri_init = (index(sr->body.data, ' ') - sr->body.data) + 1;
435 fh_limit = (index(sr->body.data, '\n') - sr->body.data);
437 uri_end = mk_string_search_r(sr->body.data, ' ', fh_limit) - 1;
439 if(uri_end <= 0)
441 return -1;
444 prot_init = uri_end + 2;
446 if(uri_end < uri_init)
448 return -1;
451 /* Query String */
452 query_init = index(sr->body.data+uri_init, '?');
453 if(query_init)
455 int init, end;
457 init = (int) (query_init-(sr->body.data+uri_init)) + uri_init;
458 if(init <= uri_end)
460 end = uri_end;
461 uri_end = init - 1;
463 sr->query_string = mk_pointer_create(sr->body.data,
464 init+1, end+1);
468 /* Request URI Part 2 */
469 sr->uri = sr->log->uri = mk_pointer_create(sr->body.data,
470 uri_init, uri_end+1);
472 if(sr->uri.len<1)
474 return -1;
478 /* HTTP Version */
479 prot_end = fh_limit-1;
480 if(prot_end!=prot_init && prot_end>0){
481 sr->protocol = sr->log->protocol =
482 mk_http_protocol_check(sr->body.data+prot_init, prot_end-prot_init);
485 headers = sr->body.data+prot_end+mk_crlf.len;
487 /* URI processed */
488 sr->uri_processed = get_real_string(sr->uri);
490 if(!sr->uri_processed)
492 sr->uri_processed = mk_pointer_to_buf(sr->uri);
493 sr->uri_twin = VAR_ON;
496 /* Creating table of content (index) for request headers */
497 int toc_len = MK_KNOWN_HEADERS;
498 struct header_toc *toc = mk_request_header_toc_create(toc_len);
499 mk_request_header_toc_parse(toc, headers, toc_len);
501 /* Host */
502 host = mk_request_header_find(toc, toc_len, headers, mk_rh_host);
504 if(host.data)
506 if((pos_sep = mk_string_char_search(host.data, ':', host.len))>=0)
508 sr->host.data = host.data;
509 sr->host.len = pos_sep;
511 port = mk_string_copy_substr(host.data, pos_sep+1, host.len);
512 sr->port = atoi(port);
513 mk_mem_free(port);
515 else{
516 sr->host=host; /* maybe null */
517 sr->port=config->standard_port;
520 else{
521 sr->host.data=NULL;
524 /* Looking for headers */
525 sr->accept = mk_request_header_find(toc, toc_len, headers, mk_rh_accept);
526 sr->accept_charset = mk_request_header_find(toc, toc_len, headers,
527 mk_rh_accept_charset);
528 sr->accept_encoding = mk_request_header_find(toc, toc_len, headers,
529 mk_rh_accept_encoding);
532 sr->accept_language = mk_request_header_find(toc, toc_len, headers,
533 mk_rh_accept_language);
534 sr->cookies = mk_request_header_find(toc, toc_len, headers, mk_rh_cookie);
535 sr->connection = mk_request_header_find(toc, toc_len, headers,
536 mk_rh_connection);
537 sr->referer = mk_request_header_find(toc, toc_len, headers,
538 mk_rh_referer);
539 sr->user_agent = mk_request_header_find(toc, toc_len, headers,
540 mk_rh_user_agent);
541 sr->range = mk_request_header_find(toc, toc_len, headers, mk_rh_range);
542 sr->if_modified_since = mk_request_header_find(toc, toc_len, headers,
543 mk_rh_if_modified_since);
545 /* Default Keepalive is off */
546 sr->keep_alive = VAR_OFF;
547 if(sr->connection.data){
548 if(mk_string_casestr(sr->connection.data, "Keep-Alive")){
549 sr->keep_alive = VAR_ON;
552 else{
553 /* Default value for HTTP/1.1 */
554 if(sr->protocol==HTTP_PROTOCOL_11){
555 /* Assume keep-alive connection */
556 sr->keep_alive = VAR_ON;
559 sr->log->final_response = M_HTTP_OK;
561 return 0;
564 /* Return value of some variable sent in request */
565 mk_pointer mk_request_header_find(struct header_toc *toc, int toc_len,
566 char *request_body, mk_pointer header)
568 int i;
569 mk_pointer var;
571 var.data = NULL;
572 var.len = 0;
574 /* new code */
575 if(toc)
577 for(i=0; i<toc_len; i++)
579 /* status = 1 means that the toc entry was already
580 * checked by monkey
582 if(toc[i].status == 1)
584 continue;
587 if(!toc[i].init)
588 break;
590 if(strncasecmp(toc[i].init, header.data, header.len)==0)
592 var.data = toc[i].init + header.len + 1;
593 var.len = toc[i].end - var.data;
594 toc[i].status = 1;
595 return var;
600 return var;
603 /* FIXME: IMPROVE access */
604 /* Look for some index.xxx in pathfile */
605 mk_pointer mk_request_index(char *pathfile)
607 unsigned long len;
608 char *file_aux=0;
609 mk_pointer f;
610 struct indexfile *aux_index;
612 mk_pointer_reset(&f);
614 aux_index=first_index;
616 while(aux_index) {
617 m_build_buffer(&file_aux, &len, "%s%s",
618 pathfile, aux_index->indexname);
620 if(access(file_aux,F_OK)==0)
622 f.data = file_aux;
623 f.len = len;
624 return f;
626 mk_mem_free(file_aux);
627 aux_index=aux_index->next;
630 return f;
633 /* Send error responses */
634 void mk_request_error(int num_error, struct client_request *cr,
635 struct request *s_request, int debug, struct log_info *s_log)
637 char *aux_message=0;
638 mk_pointer message, *page=0;
639 long n;
641 switch(num_error) {
642 case M_CLIENT_BAD_REQUEST:
643 page = mk_request_set_default_page("Bad Request",
644 s_request->uri,
645 s_request->host_conf->host_signature);
646 s_log->error_msg = request_error_msg_400;
647 break;
649 case M_CLIENT_FORBIDDEN:
650 page = mk_request_set_default_page("Forbidden",
651 s_request->uri,
652 s_request->host_conf->host_signature);
653 s_log->error_msg = request_error_msg_403;
654 // req s_request->uri;
655 break;
657 case M_CLIENT_NOT_FOUND:
658 m_build_buffer(&message.data, &message.len,
659 "The requested URL was not found on this server.");
660 page = mk_request_set_default_page("Not Found",
661 message,
662 s_request->host_conf->host_signature);
663 s_log->error_msg = request_error_msg_404;
664 // req uri;
665 mk_pointer_free(&message);
666 break;
668 case M_CLIENT_METHOD_NOT_ALLOWED:
669 page = mk_request_set_default_page("Method Not Allowed",
670 s_request->uri,
671 s_request->host_conf->host_signature);
673 s_log->final_response=M_CLIENT_METHOD_NOT_ALLOWED;
674 s_log->error_msg = request_error_msg_405;
675 break;
677 case M_CLIENT_REQUEST_TIMEOUT:
678 s_log->status=S_LOG_OFF;
679 s_log->error_msg = request_error_msg_408;
680 break;
682 case M_CLIENT_LENGTH_REQUIRED:
683 s_log->error_msg = request_error_msg_411;
684 break;
686 case M_SERVER_NOT_IMPLEMENTED:
687 page = mk_request_set_default_page("Method Not Implemented",
688 s_request->uri,
689 s_request->host_conf->host_signature);
690 s_log->final_response=M_SERVER_NOT_IMPLEMENTED;
691 s_log->error_msg = request_error_msg_501;
692 break;
694 case M_SERVER_INTERNAL_ERROR:
695 m_build_buffer(&message.data, &message.len,
696 "Problems found running %s ",
697 s_request->uri);
698 page = mk_request_set_default_page("Internal Server Error",
699 message, s_request->host_conf->host_signature);
700 s_log->error_msg = request_error_msg_500;
702 mk_pointer_free(&message);
703 break;
705 case M_SERVER_HTTP_VERSION_UNSUP:
706 mk_pointer_reset(&message);
707 page = mk_request_set_default_page("HTTP Version Not Supported",
708 message,
709 s_request->host_conf->host_signature);
710 s_log->error_msg = request_error_msg_505;
711 break;
714 s_log->final_response=num_error;
716 s_request->headers->status = num_error;
717 s_request->headers->content_length = page->len;
718 s_request->headers->content_length_p = mk_utils_int2mkp(page->len);
719 s_request->headers->location = NULL;
720 s_request->headers->cgi = SH_NOCGI;
721 s_request->headers->pconnections_left = 0;
722 mk_pointer_reset(&s_request->headers->last_modified);
724 if(aux_message) mk_mem_free(aux_message);
726 if(!page->data)
728 mk_pointer_reset(&s_request->headers->content_type);
730 else
732 mk_pointer_set(&s_request->headers->content_type, "text/html");
735 mk_header_send(cr->socket, cr, s_request, s_log);
737 if(debug==1){
738 n = write(cr->socket, page->data, page->len);
739 mk_pointer_free(page);
740 mk_mem_free(page);
744 /* Build error page */
745 mk_pointer *mk_request_set_default_page(char *title, mk_pointer message, char *signature)
747 char *temp;
748 mk_pointer *p;
750 p = mk_mem_malloc(sizeof(mk_pointer));
752 temp = mk_pointer_to_buf(message);
753 m_build_buffer(&p->data, &p->len,
754 MK_REQUEST_DEFAULT_PAGE,
755 title, temp, signature);
756 mk_mem_free(temp);
758 return p;
761 /* Create a memory allocation in order to handle the request data */
762 struct request *mk_request_alloc()
764 struct request *request=0;
766 request = mk_mem_malloc(sizeof(struct request));
767 request->log = mk_mem_malloc(sizeof(struct log_info));
769 request->status=VAR_OFF; /* Request not processed yet */
770 request->make_log=VAR_ON; /* build log file of this request ? */
772 mk_pointer_reset(&request->body);
774 request->log->final_response=M_HTTP_OK;
775 request->log->status=S_LOG_ON;
776 mk_pointer_reset(&request->log->size_p);
777 mk_pointer_reset(&request->log->error_msg);
779 request->status=VAR_ON;
780 request->method=METHOD_NOT_FOUND;
782 mk_pointer_reset(&request->uri);
783 request->uri_processed = NULL;
784 request->uri_twin = VAR_OFF;
786 request->accept.data = NULL;
787 request->accept_language.data = NULL;
788 request->accept_encoding.data = NULL;
789 request->accept_charset.data = NULL;
790 request->content_type.data = NULL;
791 request->connection.data = NULL;
792 request->cookies.data = NULL;
793 request->host.data = NULL;
794 request->if_modified_since.data = NULL;
795 request->last_modified_since.data = NULL;
796 request->range.data = NULL;
797 request->referer.data = NULL;
798 request->resume.data = NULL;
799 request->user_agent.data = NULL;
801 request->post_variables.data = NULL;
803 request->user_uri = NULL;
804 mk_pointer_reset(&request->query_string);
806 request->file_info = NULL;
807 request->virtual_user = NULL;
808 request->script_filename = NULL;
809 mk_pointer_reset(&request->real_path);
810 request->host_conf = config->hosts;
812 request->loop = 0;
813 request->bytes_to_send = -1;
814 request->bytes_offset = 0;
815 request->fd_file = -1;
817 /* Response Headers */
818 request->headers = mk_header_create();
820 return request;
823 void mk_request_free_list(struct client_request *cr)
825 struct request *sr=0, *before=0;
827 /* sr = last node */
829 while(cr->request)
831 sr = before = cr->request;
833 while(sr->next)
835 sr = sr->next;
838 if(sr!=cr->request){
839 while(before->next!=sr){
840 before = before->next;
842 before->next = NULL;
844 else{
845 cr->request = NULL;
847 mk_request_free(sr);
849 cr->request = NULL;
852 void mk_request_free(struct request *sr)
854 /* I hate it, but I don't know another light way :( */
855 if(sr->fd_file>0)
857 close(sr->fd_file);
859 if(sr->headers){
860 mk_mem_free(sr->headers->location);
861 mk_pointer_free(&sr->headers->content_length_p);
862 mk_pointer_free(&sr->headers->last_modified);
864 mk_mem_free(sr->headers->content_type);
865 headers->content_type never it's allocated
866 with malloc or something, so we don't need
867 to free it, the value has been freed before
868 in M_METHOD_Get_and_Head(struct request *sr)
870 this BUG was reported by gentoo team.. thanks guys XD
873 mk_mem_free(sr->headers);
877 if(sr->log){
879 * We do not free log->size_p, as if it was
880 * used due to an error, it points to the
881 * same memory block than header->content_length_p
882 * points to, we just reset it.
884 mk_pointer_reset(&sr->log->size_p);
887 * sr->log->error_msg just point to
888 * local data on request.c, no
889 * dynamic allocation is made
892 mk_mem_free(sr->log);
895 mk_pointer_reset(&sr->body);
896 mk_pointer_reset(&sr->uri);
898 if(sr->uri_twin==VAR_ON)
900 mk_mem_free(sr->uri_processed);
903 mk_pointer_free(&sr->post_variables);
904 mk_mem_free(sr->user_uri);
905 mk_pointer_reset(&sr->query_string);
907 mk_mem_free(sr->file_info);
908 mk_mem_free(sr->virtual_user);
909 mk_mem_free(sr->script_filename);
910 mk_pointer_free(&sr->real_path);
911 mk_mem_free(sr);
914 /* Create a client request struct and put it on the
915 * main list
917 struct client_request *mk_request_client_create(int socket)
919 struct request_idx *request_index;
920 struct client_request *cr;
921 struct sched_connection *sc;
923 sc = mk_sched_get_connection(NULL, socket);
924 cr = mk_mem_malloc(sizeof(struct client_request));
926 cr->pipelined = FALSE;
927 cr->counter_connections = 0;
928 cr->socket = socket;
929 cr->status = MK_REQUEST_STATUS_INCOMPLETE;
930 cr->request = NULL;
932 mk_pointer_set(&cr->ip, mk_socket_get_ip(socket));
934 /* creation time in unix time */
935 cr->init_time = sc->arrive_time;
937 cr->next = NULL;
938 cr->body = mk_mem_malloc(MAX_REQUEST_BODY);
939 cr->body_length = 0;
940 cr->first_block_end = -1;
941 cr->first_method = HTTP_METHOD_UNKNOWN;
943 request_index = mk_sched_get_request_index();
944 if(!request_index->first)
946 request_index->first = request_index->last = cr;
948 else{
949 request_index->last->next = cr;
950 request_index->last = cr;
952 mk_sched_set_request_index(request_index);
955 mk_sched_update_thread_status(MK_SCHEDULER_ACTIVE_UP,
956 MK_SCHEDULER_CLOSED_NONE);
958 return cr;
961 struct client_request *mk_request_client_get(int socket)
963 struct request_idx *request_index;
964 struct client_request *cr=NULL;
966 request_index = mk_sched_get_request_index();
967 cr = request_index->first;
968 while(cr!=NULL)
970 if(cr->socket == socket)
972 break;
974 cr = cr->next;
977 return cr;
981 * From thread sched_list_node "list", remove the client_request
982 * struct information
984 struct client_request *mk_request_client_remove(int socket)
986 struct request_idx *request_index;
987 struct client_request *cr, *aux;
989 request_index = mk_sched_get_request_index();
990 cr = request_index->first;
992 while(cr)
994 if(cr->socket == socket)
996 if(cr==request_index->first)
998 request_index->first = cr->next;
1000 else
1002 aux = request_index->first;
1003 while(aux->next!=cr)
1005 aux = aux->next;
1007 aux->next = cr->next;
1008 if(!aux->next)
1010 request_index->last = aux;
1013 break;
1015 cr = cr->next;
1018 /* No keep alive connection */
1019 if(cr->counter_connections == 0){
1020 mk_sched_update_thread_status(MK_SCHEDULER_ACTIVE_DOWN,
1021 MK_SCHEDULER_CLOSED_UP);
1024 mk_pointer_free(&cr->ip);
1025 mk_mem_free(cr->body);
1026 mk_mem_free(cr);
1028 return NULL;
1031 struct header_toc *mk_request_header_toc_create(int len)
1033 int i;
1034 struct header_toc *p;
1036 p = (struct header_toc *) pthread_getspecific(mk_cache_header_toc);
1038 for(i=0; i<len; i++)
1040 p[i].init = NULL;
1041 p[i].end = NULL;
1042 p[i].status = 0;
1044 return p;
1047 void mk_request_header_toc_parse(struct header_toc *toc, char *data, int len)
1049 char *p, *l;
1050 int i;
1052 p = data;
1053 for(i=0; i<len && p; i++)
1055 l = strstr(p, MK_CRLF);
1057 if(l)
1059 toc[i].init = p;
1060 toc[i].end = l;
1061 p = l + mk_crlf.len;
1063 else
1065 break;
1070 void mk_request_ka_next(struct client_request *cr)
1072 bzero(cr->body, sizeof(cr->body));
1073 cr->first_method = -1;
1074 cr->first_block_end = -1;
1075 cr->body_length = 0;
1076 cr->counter_connections++;