Changeset 1947
- Timestamp:
- 09/05/08 12:57:58 (4 months ago)
- Files:
-
- cherokee/trunk/ChangeLog (modified) (1 diff)
- cherokee/trunk/cherokee/connection-protected.h (modified) (1 diff)
- cherokee/trunk/cherokee/connection.c (modified) (9 diffs)
- cherokee/trunk/cherokee/handler.h (modified) (1 diff)
- cherokee/trunk/cherokee/handler_cgi_base.c (modified) (7 diffs)
- cherokee/trunk/cherokee/handler_cgi_base.h (modified) (1 diff)
- cherokee/trunk/cherokee/util.c (modified) (1 diff)
- cherokee/trunk/cherokee/util.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
cherokee/trunk/ChangeLog
r1946 r1947 1 2008-09-05 Alvaro Lopez Ortega <alvaro@alobbs.com> 2 3 * cherokee/connection-protected.h, cherokee/handler_cgi_base.c, 4 cherokee/handler_cgi_base.h, cherokee/handler.h, cherokee/util.h, 5 cherokee/util.c, cherokee/connection.c: Reimplements the Chunked 6 encoding support. Now it is system-wide and does less memory 7 moves/allocations. 8 1 9 2008-09-04 Alvaro Lopez Ortega <alvaro@alobbs.com> 2 10 cherokee/trunk/cherokee/connection-protected.h
r1944 r1947 198 198 cherokee_boolean_t chunked_encoding; 199 199 cherokee_buffer_t chunked_len; 200 size_t chunked_sent; 201 struct iovec chunks[3]; 202 uint16_t chunksn; 200 203 }; 201 204 cherokee/trunk/cherokee/connection.c
r1945 r1947 149 149 150 150 n->chunked_encoding = false; 151 n->chunked_sent = 0; 151 152 cherokee_buffer_init (&n->chunked_len); 152 153 … … 257 258 conn->expiration_time = 0; 258 259 conn->chunked_encoding = false; 260 conn->chunked_sent = 0; 259 261 260 262 memset (conn->regex_ovector, OVECTOR_LEN * sizeof(int), 0); … … 626 628 } 627 629 628 /* It might need to deactive Keep-Alive after checking the 629 * handler headers.. 630 /* If the connection is using Kee-Alive, it must either know 631 * the length or use chunked encoding. Otherwise, Keep-Alive 632 * has to be turned off. 630 633 */ 631 634 if ((conn->keepalive != 0) && 632 (conn->chunked_encoding == false) &&633 635 (http_method_with_body (conn->error_code))) 634 636 { 635 if (HANDLER_SUPPORTS (conn->handler, hsupport_maybe_length)) { 636 if (strcasestr (conn->header_buffer.buf, "Content-Length: ") == NULL) 637 if ((! HANDLER_SUPPORTS (conn->handler, hsupport_length)) || 638 ((HANDLER_SUPPORTS (conn->handler, hsupport_maybe_length)) && 639 (! strcasestr (conn->header_buffer.buf, "Content-Length: ")))) 640 { 641 conn->chunked_encoding = ( 642 // srv->allow_chunked 643 (conn->header.version == http_version_11)); 644 645 if (! conn->chunked_encoding) 637 646 conn->keepalive = 0; 638 639 } else if (! HANDLER_SUPPORTS (conn->handler, hsupport_length)) {640 conn->keepalive = 0;641 647 } 642 648 } … … 866 872 /* Use writev to send the chunk-begin mark 867 873 */ 868 if ((conn->chunked_encoding) && 869 (! cherokee_buffer_is_empty (&conn->chunked_len))) 874 if (conn->chunked_encoding) 870 875 { 871 struct iovec bufs[2]; 872 873 bufs[0].iov_base = conn->chunked_len.buf; 874 bufs[0].iov_len = conn->chunked_len.len; 875 bufs[1].iov_base = conn->buffer.buf; 876 bufs[1].iov_len = conn->buffer.len; 877 878 ret = cherokee_socket_writev (&conn->socket, bufs, 2, &sent); 876 struct iovec tmp[3]; 877 878 tmp[0].iov_base = conn->chunked_len.buf; 879 tmp[0].iov_len = conn->chunked_len.len; 880 tmp[1].iov_base = conn->buffer.buf; 881 tmp[1].iov_len = conn->buffer.len; 882 tmp[2].iov_base = CRLF; 883 tmp[2].iov_len = 2; 884 885 cherokee_iovec_skip_sent (tmp, 3, 886 conn->chunks, &conn->chunksn, 887 conn->chunked_sent); 888 889 ret = cherokee_socket_writev (&conn->socket, conn->chunks, conn->chunksn, &sent); 879 890 if (unlikely (ret != ret_ok)) { 880 891 switch (ret) { … … 893 904 } 894 905 895 if (unlikely (sent <= conn->chunked_len.len)) { 896 cherokee_buffer_move_to_begin (&conn->chunked_len, sent); 897 906 conn->chunked_sent += sent; 907 908 /* Clean the information buffer only when everything 909 * has been sent. 910 */ 911 if (cherokee_iovec_was_sent (tmp, 3, conn->chunked_sent)) { 912 cherokee_buffer_clean (&conn->chunked_len); 913 cherokee_buffer_clean (&conn->buffer); 914 ret = ret_ok; 898 915 } else { 899 cherokee_buffer_move_to_begin (&conn->buffer, (sent - conn->chunked_len.len)); 900 cherokee_buffer_clean (&conn->chunked_len); 901 } 902 903 return (conn->buffer.len > 0) ? ret_eagain : ret_ok; 916 ret = ret_eagain; 917 } 918 919 goto out; 904 920 } 905 921 … … 908 924 ret = cherokee_socket_bufwrite (&conn->socket, &conn->buffer, &sent); 909 925 if (unlikely(ret != ret_ok)) return ret; 910 911 /* Add to the connection traffic counter912 */913 cherokee_connection_tx_add (conn, sent);914 926 915 927 /* Drop out the sent info … … 922 934 ret = ret_eagain; 923 935 } 936 937 out: 938 /* Add to the connection traffic counter 939 */ 940 cherokee_connection_tx_add (conn, sent); 924 941 925 942 /* If this connection has a handler without Content-Length support … … 1026 1043 /* Return now if no encoding is needed. 1027 1044 */ 1028 if (conn->encoder == NULL) 1029 return step_ret; 1030 1031 /* Encode handler output. 1032 */ 1033 switch (step_ret) { 1034 case ret_eof: 1035 case ret_eof_have_data: 1036 ret = cherokee_encoder_flush (conn->encoder, &conn->buffer, &conn->encoder_buffer); 1037 step_ret = (conn->encoder_buffer.len == 0) ? ret_eof : ret_eof_have_data; 1038 break; 1039 default: 1040 ret = cherokee_encoder_encode (conn->encoder, &conn->buffer, &conn->encoder_buffer); 1041 break; 1042 } 1043 if (ret < ret_ok) return ret; 1044 1045 /* Swap buffers 1046 */ 1047 cherokee_buffer_swap_buffers (&conn->buffer, &conn->encoder_buffer); 1048 cherokee_buffer_clean (&conn->encoder_buffer); 1045 if (conn->encoder != NULL) { 1046 /* Encode handler output. 1047 */ 1048 switch (step_ret) { 1049 case ret_eof: 1050 case ret_eof_have_data: 1051 ret = cherokee_encoder_flush (conn->encoder, &conn->buffer, &conn->encoder_buffer); 1052 step_ret = (conn->encoder_buffer.len == 0) ? ret_eof : ret_eof_have_data; 1053 break; 1054 default: 1055 ret = cherokee_encoder_encode (conn->encoder, &conn->buffer, &conn->encoder_buffer); 1056 break; 1057 } 1058 if (ret < ret_ok) 1059 return ret; 1060 1061 /* Swap buffers 1062 */ 1063 cherokee_buffer_swap_buffers (&conn->buffer, &conn->encoder_buffer); 1064 cherokee_buffer_clean (&conn->encoder_buffer); 1065 } 1066 1067 /* Chunked encoding header 1068 */ 1069 if (conn->chunked_encoding) { 1070 /* In case it is the last package, turn the chunked 1071 * encoding off and send the final mark. 1072 */ 1073 if ((step_ret == ret_eof) || 1074 (step_ret == ret_eof_have_data)) 1075 { 1076 cherokee_buffer_add_str (&conn->buffer, "0" CRLF CRLF); 1077 conn->chunked_encoding = false; 1078 1079 step_ret = ret_eof_have_data; 1080 1081 } else { 1082 /* Build the Chunked package header: 1083 * len(str(hex(4294967295))+"\r\n\0") = 13 1084 */ 1085 cherokee_buffer_clean (&conn->chunked_len); 1086 cherokee_buffer_ensure_size (&conn->chunked_len, 13); 1087 cherokee_buffer_add_ulong16 (&conn->chunked_len, conn->buffer.len); 1088 cherokee_buffer_add_str (&conn->chunked_len, CRLF); 1089 1090 conn->chunked_sent = 0; 1091 } 1092 } 1049 1093 1050 1094 return step_ret; … … 2036 2080 2037 2081 cherokee_buffer_clean (&conn->web_directory); 2082 conn->chunked_encoding = false; 2038 2083 2039 2084 TRACE_CONN(conn); cherokee/trunk/cherokee/handler.h
r1853 r1947 49 49 hsupport_length = 1, /* Knows the length. Eg: for keep-alive */ 50 50 hsupport_maybe_length = 1 << 1, /* It might include content-length */ 51 hsupport_chunked = 1 << 2, /* Support Chunked transfer encoding */ 52 hsupport_range = 1 << 3, /* Can handle "Range: bytes=" requests */ 53 hsupport_error = 1 << 4, /* It is an error handler */ 54 hsupport_full_headers = 1 << 5, /* Handler adds the full header stack */ 55 hsupport_skip_headers = 1 << 6 /* The server shouldn't add any headers */ 51 hsupport_range = 1 << 2, /* Can handle "Range: bytes=" requests */ 52 hsupport_error = 1 << 3, /* It is an error handler */ 53 hsupport_full_headers = 1 << 4, /* Handler adds the full header stack */ 54 hsupport_skip_headers = 1 << 5 /* The server shouldn't add any headers */ 56 55 } cherokee_handler_support_t; 57 56 cherokee/trunk/cherokee/handler_cgi_base.c
r1944 r1947 35 35 36 36 #define ENTRIES "cgibase" 37 #define LAST_CHUNK "0" CRLF CRLF38 37 39 38 #define set_env(cgi,key,val,len) \ … … 178 177 props->change_user = false; 179 178 props->check_file = true; 180 props->allow_chunked = true;181 179 props->allow_xsendfile = false; 182 180 props->pass_req_headers = false; … … 211 209 } else if (equal_buf_str (&subconf->key, "check_file")) { 212 210 props->check_file = !! atoi(subconf->val.buf); 213 214 } else if (equal_buf_str (&subconf->key, "allow_chunked")) {215 props->allow_chunked = !! atoi(subconf->val.buf);216 211 217 212 } else if (equal_buf_str (&subconf->key, "xsendfile")) { … … 965 960 } 966 961 967 /* Chunked encoding968 */969 conn->chunked_encoding = (970 (conn->keepalive > 0) &&971 (cgi->content_length_set == false) &&972 (conn->header.version == http_version_11) &&973 (HANDLER_CGI_BASE_PROPS(cgi)->allow_chunked));974 975 TRACE (ENTRIES, "Chunked: Keepalive: %d, len not set=%d, version ok=%d, allowed=%d => %d\n",976 (conn->keepalive > 0),977 (cgi->content_length_set == false),978 (conn->header.version == http_version_11),979 (HANDLER_CGI_BASE_PROPS(cgi)->allow_chunked),980 conn->chunked_encoding);981 982 962 return ret_ok; 983 963 } … … 988 968 cherokee_buffer_t *outbuf) 989 969 { 990 ret_t ret; 991 cherokee_buffer_t *inbuf = &cgi->data; 992 cherokee_connection_t *conn = HANDLER_CONN(cgi); 970 ret_t ret; 971 cherokee_buffer_t *inbuf = &cgi->data; 993 972 994 973 /* Is it replying a "X-Sendfile" request? … … 1004 983 TRACE (ENTRIES, "sending stored data: %d bytes\n", cgi->data.len); 1005 984 1006 if (conn->chunked_encoding) {1007 /* Build the chunk-hader:1008 * len(str(hex(4294967295))+"\r\n\0") = 131009 */1010 cherokee_buffer_ensure_size (&conn->chunked_len, 13);1011 cherokee_buffer_add_ulong16 (&conn->chunked_len, cgi->data.len);1012 cherokee_buffer_add_str (&conn->chunked_len, CRLF);1013 }1014 1015 985 cherokee_buffer_add_buffer (outbuf, &cgi->data); 1016 986 cherokee_buffer_clean (&cgi->data); 1017 987 1018 988 if (cgi->got_eof) { 1019 if (conn->chunked_encoding) {1020 cherokee_buffer_add_str (outbuf, LAST_CHUNK);1021 }1022 989 return ret_eof_have_data; 1023 990 } … … 1031 998 1032 999 if (inbuf->len > 0) { 1033 cherokee_buffer_add_buffer (outbuf, inbuf); 1000 cherokee_buffer_add_buffer (outbuf, inbuf); 1034 1001 cherokee_buffer_clean (inbuf); 1035 1036 if (conn->chunked_encoding) {1037 cherokee_buffer_ensure_size (&conn->chunked_len, 13);1038 cherokee_buffer_add_ulong16 (&conn->chunked_len, outbuf->len);1039 cherokee_buffer_add_str (&conn->chunked_len, CRLF);1040 }1041 }1042 1043 if ((conn->chunked_encoding) &&1044 ((ret == ret_eof) || (ret == ret_eof_have_data)))1045 {1046 cherokee_buffer_add_str (outbuf, LAST_CHUNK);1047 return ret_eof_have_data;1048 1002 } 1049 1003 cherokee/trunk/cherokee/handler_cgi_base.h
r1944 r1947 106 106 cherokee_buffer_t script_alias; 107 107 cherokee_boolean_t check_file; 108 cherokee_boolean_t allow_chunked;109 108 cherokee_boolean_t allow_xsendfile; 110 109 cherokee_boolean_t is_error_handler; cherokee/trunk/cherokee/util.c
r1885 r1947 1425 1425 return ret_ok; 1426 1426 } 1427 1428 1429 ret_t 1430 cherokee_iovec_skip_sent (struct iovec *orig, uint16_t orig_len, 1431 struct iovec *dest, uint16_t *dest_len, 1432 size_t sent) 1433 { 1434 int i; 1435 int j = 0; 1436 size_t total = 0; 1437 int add = 0; 1438 1439 for (i=0; i<orig_len; i++) { 1440 if (sent >= total + orig[i].iov_len) { 1441 /* Already sent */ 1442 total += orig[i].iov_len; 1443 1444 } else if (add) { 1445 /* Add the whole thing */ 1446 dest[j].iov_len = orig[i].iov_len; 1447 dest[j].iov_base = orig[i].iov_base; 1448 j++; 1449 1450 } else { 1451 /* Add only a piece */ 1452 dest[j].iov_len = orig[i].iov_len - (sent - total); 1453 dest[j].iov_base = orig[i].iov_base + (sent - total); 1454 j++; 1455 add = 1; 1456 } 1457 } 1458 1459 *dest_len = j; 1460 return ret_ok; 1461 } 1462 1463 1464 int 1465 cherokee_iovec_was_sent (struct iovec *orig, uint16_t orig_len, size_t sent) 1466 { 1467 int i; 1468 size_t total =0; 1469 1470 for (i=0; i<orig_len; i++) { 1471 total += orig[i].iov_len; 1472 if (total > sent) { 1473 return 0; 1474 } 1475 } 1476 1477 return 1; 1478 } cherokee/trunk/cherokee/util.h
r1885 r1947 122 122 void cherokee_print_wrapped (cherokee_buffer_t *buffer); 123 123 124 ret_t cherokee_iovec_skip_sent (struct iovec orig[], uint16_t orig_len, 125 struct iovec dest[], uint16_t *dest_len, 126 size_t sent); 127 128 int cherokee_iovec_was_sent (struct iovec orig[], uint16_t orig_len, size_t sent); 129 124 130 /* Debug 125 131 */