1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
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.
27 #include <sys/socket.h>
37 #include <arpa/inet.h>
38 #include <netinet/in.h>
39 #include <sys/types.h>
44 #include "http_status.h"
49 #include "scheduler.h"
63 struct request
*mk_request_parse(struct client_request
*cr
)
65 int i
, n
, init_block
=0, n_blocks
=0;
67 struct request
*cr_buf
=0, *cr_search
=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();
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
;
84 cr_buf
->method
= mk_http_method_get(cr_buf
->body
.data
);
87 cr_buf
->log
->ip
= cr
->ip
;
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
;
106 cr
->request
= cr_buf
;
109 cr_search
= cr
->request
;
112 if(cr_search
->next
==NULL
)
114 cr_search
->next
= cr_buf
;
119 cr_search
= cr_search
->next
;
124 n
= mk_string_search(cr
->body
+i
, mk_endblock
.data
);
134 /* Checking pipelining connection */
135 cr_search
= cr
->request
;
141 if(cr_search
->method
!=HTTP_METHOD_GET
&&
142 cr_search
->method
!=HTTP_METHOD_HEAD
)
147 cr_search
= cr_search
->next
;
150 if(pipelined
== FALSE
){
151 /* All pipelined requests must use GET method */
155 cr
->pipelined
= TRUE
;
160 printf("*****************************************");
162 cr_search = cr->request;
164 printf("\n---BLOCK---:\n%s---END BLOCK---\n\n", cr_search->body);
166 cr_search = cr_search->next;
173 int mk_handler_read(int socket
)
176 struct client_request
*cr
;
178 cr
= mk_request_client_get(socket
);
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
);
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
);
208 if (errno
== EAGAIN
) {
212 mk_request_client_remove(socket
);
217 mk_request_client_remove(socket
);
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
,
231 else if(cr
->body_length
+1 >= MAX_REQUEST_BODY
)
233 /* Request is incomplete and our buffer is full,
236 mk_request_client_remove(socket
);
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
);
262 if(!mk_request_parse(cr
))
268 p_request
= cr
->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
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;
304 int mk_request_process(struct client_request
*cr
, struct request
*s_request
)
309 status
= mk_request_header_process(s_request
);
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
);
322 case METHOD_NOT_FOUND
:
323 mk_request_error(M_SERVER_NOT_IMPLEMENTED
, cr
,
324 s_request
, 1, s_request
->log
);
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,
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,
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,
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,
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,
373 if(s_request
->host
.data
)
375 host
=mk_config_host_find(s_request
->host
);
378 s_request
->host_conf
= host
;
381 s_request
->host_conf
= config
->hosts
;
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
,
393 mk_user_home
.len
)==0){
394 if(mk_user_init(cr
, s_request
)!=0){
400 /* Handling method requested */
401 if(s_request
->method
==HTTP_METHOD_POST
)
403 if((status
=mk_method_post(cr
, s_request
))==-1){
408 status
= mk_http_init(cr
, s_request
);
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;
419 int prot_init
=0, prot_end
=0, pos_sep
=0;
425 /* If verification fails it will return always
426 * a bad request status
428 sr
->log
->final_response
= M_CLIENT_BAD_REQUEST
;
431 sr
->method_p
= mk_http_method_check_str(sr
->method
);
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;
444 prot_init
= uri_end
+ 2;
446 if(uri_end
< uri_init
)
452 query_init
= index(sr
->body
.data
+uri_init
, '?');
457 init
= (int) (query_init
-(sr
->body
.data
+uri_init
)) + uri_init
;
463 sr
->query_string
= mk_pointer_create(sr
->body
.data
,
468 /* Request URI Part 2 */
469 sr
->uri
= sr
->log
->uri
= mk_pointer_create(sr
->body
.data
,
470 uri_init
, uri_end
+1);
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
;
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
);
502 host
= mk_request_header_find(toc
, toc_len
, headers
, mk_rh_host
);
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
);
516 sr
->host
=host
; /* maybe null */
517 sr
->port
=config
->standard_port
;
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
,
537 sr
->referer
= mk_request_header_find(toc
, toc_len
, headers
,
539 sr
->user_agent
= mk_request_header_find(toc
, toc_len
, headers
,
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
;
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
;
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
)
577 for(i
=0; i
<toc_len
; i
++)
579 /* status = 1 means that the toc entry was already
582 if(toc
[i
].status
== 1)
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
;
603 /* FIXME: IMPROVE access */
604 /* Look for some index.xxx in pathfile */
605 mk_pointer
mk_request_index(char *pathfile
)
610 struct indexfile
*aux_index
;
612 mk_pointer_reset(&f
);
614 aux_index
=first_index
;
617 m_build_buffer(&file_aux
, &len
, "%s%s",
618 pathfile
, aux_index
->indexname
);
620 if(access(file_aux
,F_OK
)==0)
626 mk_mem_free(file_aux
);
627 aux_index
=aux_index
->next
;
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
)
638 mk_pointer message
, *page
=0;
642 case M_CLIENT_BAD_REQUEST
:
643 page
= mk_request_set_default_page("Bad Request",
645 s_request
->host_conf
->host_signature
);
646 s_log
->error_msg
= request_error_msg_400
;
649 case M_CLIENT_FORBIDDEN
:
650 page
= mk_request_set_default_page("Forbidden",
652 s_request
->host_conf
->host_signature
);
653 s_log
->error_msg
= request_error_msg_403
;
654 // req s_request->uri;
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",
662 s_request
->host_conf
->host_signature
);
663 s_log
->error_msg
= request_error_msg_404
;
665 mk_pointer_free(&message
);
668 case M_CLIENT_METHOD_NOT_ALLOWED
:
669 page
= mk_request_set_default_page("Method Not Allowed",
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
;
677 case M_CLIENT_REQUEST_TIMEOUT
:
678 s_log
->status
=S_LOG_OFF
;
679 s_log
->error_msg
= request_error_msg_408
;
682 case M_CLIENT_LENGTH_REQUIRED
:
683 s_log
->error_msg
= request_error_msg_411
;
686 case M_SERVER_NOT_IMPLEMENTED
:
687 page
= mk_request_set_default_page("Method Not Implemented",
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
;
694 case M_SERVER_INTERNAL_ERROR
:
695 m_build_buffer(&message
.data
, &message
.len
,
696 "Problems found running %s ",
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
);
705 case M_SERVER_HTTP_VERSION_UNSUP
:
706 mk_pointer_reset(&message
);
707 page
= mk_request_set_default_page("HTTP Version Not Supported",
709 s_request
->host_conf
->host_signature
);
710 s_log
->error_msg
= request_error_msg_505
;
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
);
728 mk_pointer_reset(&s_request
->headers
->content_type
);
732 mk_pointer_set(&s_request
->headers
->content_type
, "text/html");
735 mk_header_send(cr
->socket
, cr
, s_request
, s_log
);
738 n
= write(cr
->socket
, page
->data
, page
->len
);
739 mk_pointer_free(page
);
744 /* Build error page */
745 mk_pointer
*mk_request_set_default_page(char *title
, mk_pointer message
, char *signature
)
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
);
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
;
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();
823 void mk_request_free_list(struct client_request
*cr
)
825 struct request
*sr
=0, *before
=0;
831 sr
= before
= cr
->request
;
839 while(before
->next
!=sr
){
840 before
= before
->next
;
852 void mk_request_free(struct request
*sr
)
854 /* I hate it, but I don't know another light way :( */
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
);
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
);
914 /* Create a client request struct and put it on the
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;
929 cr
->status
= MK_REQUEST_STATUS_INCOMPLETE
;
932 mk_pointer_set(&cr
->ip
, mk_socket_get_ip(socket
));
934 /* creation time in unix time */
935 cr
->init_time
= sc
->arrive_time
;
938 cr
->body
= mk_mem_malloc(MAX_REQUEST_BODY
);
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
;
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
);
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
;
970 if(cr
->socket
== socket
)
981 * From thread sched_list_node "list", remove the client_request
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
;
994 if(cr
->socket
== socket
)
996 if(cr
==request_index
->first
)
998 request_index
->first
= cr
->next
;
1002 aux
= request_index
->first
;
1003 while(aux
->next
!=cr
)
1007 aux
->next
= cr
->next
;
1010 request_index
->last
= aux
;
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
);
1031 struct header_toc
*mk_request_header_toc_create(int len
)
1034 struct header_toc
*p
;
1036 p
= (struct header_toc
*) pthread_getspecific(mk_cache_header_toc
);
1038 for(i
=0; i
<len
; i
++)
1047 void mk_request_header_toc_parse(struct header_toc
*toc
, char *data
, int len
)
1053 for(i
=0; i
<len
&& p
; i
++)
1055 l
= strstr(p
, MK_CRLF
);
1061 p
= l
+ mk_crlf
.len
;
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
++;