Commit cde771f1f9fbb88fc725550f76edd7b6d527314a

Authored by totoro
1 parent 973a3fae

[!] improve speed on receiving files under HTTP server

Showing 1 changed file with 437 additions and 317 deletions   Show diff stats
web/CXM_multihost_http_server.anubis
... ... @@ -11,8 +11,9 @@
11 11 Cédric Ricard
12 12  
13 13  
14   - *Revised* July 2007.
15   -
  14 + *Revised*
  15 + June 2015 : Optimization of the file upload
  16 + July 2007 : Initial version in calexium_lib
16 17  
17 18  
18 19 *Overviews*
... ... @@ -169,6 +170,7 @@ read tools/printable_tree.anubis
169 170 read system/string.anubis
170 171 read system/files.anubis
171 172 read system/lists.anubis
  173 +read system/data_io.anubis
172 174 read web/mime.anubis
173 175  
174 176  
... ... @@ -843,7 +845,6 @@ define ReadResult
843 845 connection.read_pos <- *connection.read_pos + size_read;
844 846 //accumulate_t1(t1_tmp);
845 847 if size > size_read then
846   - //println("Wanted " + size + ", read only " + size_read);
847 848  
848 849 terminal read_from_connexion(connection, size - size_read, time_out, result_buffer, position+size_read)
849 850 // {
... ... @@ -862,7 +863,6 @@ define ReadResult
862 863 timeout then timeout,
863 864 ok(ba) then
864 865 with size_read = length(ba),
865   - //println("Wanted 32768, read only " + size_read);
866 866 //the needed read is higher than the
867 867 if size > size_read then
868 868 put(ba, result_buffer, position, 0);
... ... @@ -934,7 +934,31 @@ define Result(Error,Word8)
934 934 ok(h)
935 935 }.
936 936  
937   -
  937 +define ByteArray
  938 + get_and_erase_buffer
  939 + (
  940 + BufferedConnection connection,
  941 + SState s
  942 + )=
  943 + with head = to_byte_array(implode(*s.unput_chars)),
  944 + tail = extract(*connection.buffer, *connection.read_pos, length(*connection.buffer)),
  945 +// println("--- get_and_erase_buffer ----");
  946 +// println("unput char length : "+length(to_string(head)));
  947 +// println("connection.read_pos : "+*connection.read_pos);
  948 +// println("connection.buffer length : "+length(*connection.buffer));
  949 +// println(" tail length : "+length(tail));
  950 +// println(" -- unputchar content ");
  951 +// println("["+to_string(head)+"]");
  952 +// println(" -- buffer content ");
  953 +// println("["+to_string(*connection.buffer)+"]");
  954 +// println(" -- tail content ");
  955 +// println("["+to_string(tail)+"]");
  956 + s.unput_chars <- [];
  957 + connection.buffer <- constant_byte_array(0,0);
  958 + connection.read_pos <- 0;
  959 + head + tail
  960 + .
  961 +
938 962  
939 963  
940 964  
... ... @@ -1632,43 +1656,44 @@ define Bool
1632 1656 if ('a' +=< c & c +=< 'z') then true else
1633 1657 if ('A' +=< c & c +=< 'Z') then true else
1634 1658 if ('0' +=< c & c +=< '9') then true else
1635   - if c = '-' then true else
  1659 + if c = '-' then true else
1636 1660 c = '_'.
1637 1661  
1638 1662 define Result(Error,String)
1639   - read_header_name
1640   - (
1641   - BufferedConnection connection,
1642   - Int dead_line,
1643   - List(Word8) so_far,
1644   - DenialOfService dos,
1645   - SState s
1646   - ) =
  1663 + read_header_name
  1664 + (
  1665 + BufferedConnection connection,
  1666 + Int dead_line,
  1667 + List(Word8) so_far,
  1668 + DenialOfService dos,
  1669 + SState s
  1670 + ) =
1647 1671 if next_char(connection, dead_line, dos, s) is
1648 1672 {
1649 1673 error(msg) then error(msg),
1650   - ok(c) then
  1674 + ok(c) then
1651 1675 if is_header_name_char(c)
1652   - then read_header_name(connection,dead_line,[to_lower(c) . so_far],dos, s)
  1676 + then read_header_name(connection, dead_line, [to_lower(c) . so_far], dos, s)
1653 1677 else unput(c, s); ok(implode(reverse(so_far)))
1654 1678 }.
1655 1679  
1656 1680 define Result(Error,One)
1657   - skip_colon
1658   - (
1659   - BufferedConnection connection,
1660   - Int dead_line,
1661   - DenialOfService dos,
1662   - SState s
1663   - ) =
1664   - if skip_http_blanks(connection, dead_line, dos, s) is
1665   - {
1666   - error(msg) then error(msg),
1667   - ok(_) then
1668   - if next_char(connection, dead_line, dos, s) is
1669   - {
1670   - error(msg) then error(msg),
1671   - ok(c) then
  1681 + skip_colon
  1682 + (
  1683 + BufferedConnection connection,
  1684 + Int dead_line,
  1685 + DenialOfService dos,
  1686 + SState s
  1687 + ) =
  1688 + //Skip the blank char until ':'
  1689 + if skip_http_blanks(connection, dead_line, dos, s) is
  1690 + {
  1691 + error(msg) then error(msg),
  1692 + ok(_) then
  1693 + if next_char(connection, dead_line, dos, s) is
  1694 + {
  1695 + error(msg) then error(msg),
  1696 + ok(c) then
1672 1697 if c = ':'
1673 1698 then ok(unique)
1674 1699 else error(colon_expected)
... ... @@ -1718,49 +1743,54 @@ define Result(Error,Maybe(HTTP_header))
1718 1743 DenialOfService dos,
1719 1744 SState s
1720 1745 ) =
1721   - if read_header_name(connection, dead_line, [], dos, s) is
1722   - {
1723   - error(msg) then error(msg),
1724   - ok(name) then
1725   - if name = "" then
1726   - if read_and_ignore(connection, dead_line, 2, dos, s) /* 13 and 10 */ is
1727   - {
1728   - error(msg) then error(msg),
1729   - ok(_) then // this is the blank line
1730   - ok(failure) // end of headers
  1746 + //Find the name
  1747 + if read_header_name(connection, dead_line, [], dos, s) is
  1748 + {
  1749 + error(msg) then error(msg),
  1750 + ok(name) then
  1751 + if name = "" then
  1752 + if read_and_ignore(connection, dead_line, 2, dos, s) /* 13 and 10 */ is
  1753 + {
  1754 + error(msg) then error(msg),
  1755 + ok(_) then // this is the blank line
  1756 + ok(failure) // end of headers
  1757 + }
  1758 + //skip the ':' and blank before and after it
  1759 + else if skip_colon(connection, dead_line, dos, s) is
  1760 + {
  1761 + error(msg) then error(msg),
  1762 + ok(_) then
  1763 + //skip the blank char after the ':'
  1764 + if skip_http_blanks(connection, dead_line, dos, s) is
  1765 + {
  1766 + error(msg) then error(msg),
  1767 + ok(_) then
  1768 + //Now read the value
  1769 + if read_header_value(connection, dead_line, [], dos, s) is
  1770 + {
  1771 + error(msg) then error(msg),
  1772 + ok(value) then ok(success(http_header(name,value)))
1731 1773 }
1732   - else if skip_colon(connection, dead_line, dos, s) is
1733   - {
1734   - error(msg) then error(msg),
1735   - ok(_) then if skip_http_blanks(connection, dead_line, dos, s) is
1736   - {
1737   - error(msg) then error(msg),
1738   - ok(_) then if read_header_value(connection, dead_line, [], dos, s) is
1739   - {
1740   - error(msg) then error(msg),
1741   - ok(value) then
1742   - ok(success(http_header(name,value)))
1743   - }
1744   - }
1745   - }
1746   - }.
  1774 + }
  1775 + }
  1776 + }.
1747 1777  
1748 1778  
1749 1779  
1750 1780 Reading all the headers.
1751 1781  
1752 1782 define Result(Error,List(HTTP_header))
1753   - read_http_headers
1754   - (
1755   - BufferedConnection connection,
1756   - Int dead_line,
1757   - DenialOfService dos,
1758   - SState s
1759   - ) =
1760   - if read_header(connection, dead_line, dos, s) is
1761   - {
1762   - error(msg) then error(msg),
1763   - ok(mbh) then if mbh is
  1783 + read_http_headers
  1784 + (
  1785 + BufferedConnection connection,
  1786 + Int dead_line,
  1787 + DenialOfService dos,
  1788 + SState s
  1789 + ) =
  1790 + if read_header(connection, dead_line, dos, s) is
  1791 + {
  1792 + error(msg) then error(msg),
  1793 + ok(mbh) then if mbh is
1764 1794 {
1765 1795 failure then ok([ ]),
1766 1796 success(header) then
... ... @@ -1784,21 +1814,21 @@ define Result(Error,List(HTTP_header))
1784 1814 header is not present, the size is assumed to be zero.
1785 1815  
1786 1816 define Result(Error,Int)
1787   - get_body_size
1788   - (
1789   - List(HTTP_header) headers
1790   - ) =
1791   - if headers is
1792   - {
1793   - [ ] then ok(0),
1794   - [h . t] then if h is http_header(name,value) then
1795   - if name = "content-length"
1796   - then if decimal_scan(value) is
1797   - {
1798   - failure then error(incorrect_content_length_value),
1799   - success(n) then ok(n)
1800   - }
1801   - else get_body_size(t)
  1817 + get_body_size
  1818 + (
  1819 + List(HTTP_header) headers
  1820 + ) =
  1821 + if headers is
  1822 + {
  1823 + [ ] then ok(0),
  1824 + [h . t] then if h is http_header(name,value) then
  1825 + if name = "content-length"
  1826 + then if decimal_scan(value) is
  1827 + {
  1828 + failure then error(incorrect_content_length_value),
  1829 + success(n) then ok(n)
  1830 + }
  1831 + else get_body_size(t)
1802 1832 }.
1803 1833  
1804 1834  
... ... @@ -1820,17 +1850,18 @@ define Result(Error,Int)
1820 1850 required number of bytes. However, if the number of bytes read is zero, the connection
1821 1851 may be broken. In that case, we must not try to read indefinitely. On the contrary, we
1822 1852 make at most 10 retries, with a small sleeping time between any two of them.
1823   -
  1853 +
1824 1854 define Result(Error, ByteArray)
1825 1855 read_http_body
1826 1856 (
1827 1857 BufferedConnection connection,
1828   - Int body_size,
1829   - ByteArray so_far, // when calling this function, 'so_far' is the empty byte array
1830   - Int retries // this function is called with retries = 10
  1858 + Int body_size,
  1859 + ByteArray so_far, // when calling this function, 'so_far' is the empty byte array
  1860 + Int retries // this function is called with retries = 10
1831 1861 ) =
1832 1862 if body_size = 0 then ok(constant_byte_array(0,0)) else
1833 1863 if retries =< 0 then error(cannot_read_from_connection) else
  1864 +
1834 1865 if read_from_connexion(connection,body_size,60,constant_byte_array(body_size,0),0) is
1835 1866 {
1836 1867 error then error(cannot_read_from_connection),
... ... @@ -2016,19 +2047,19 @@ public define Bool
2016 2047  
2017 2048  
2018 2049 define Maybe(MIME)
2019   - recognize_mime_type_from_ext
2020   - (
2021   - String ext,
2022   - List(MIME) l
2023   - ) =
2024   - if l is
2025   - {
2026   - [ ] then success(mime("application", "octet-stream", [])), // failure,
2027   - [h . t] then if h is mime(type, subtype, extensions) then
2028   - if contains_no_case(extensions, ext)
2029   - then success(h)
2030   - else recognize_mime_type_from_ext(ext,t)
2031   - }.
  2050 + recognize_mime_type_from_ext
  2051 + (
  2052 + String ext,
  2053 + List(MIME) l
  2054 + ) =
  2055 + if l is
  2056 + {
  2057 + [ ] then success(mime("application", "octet-stream", [])), // failure,
  2058 + [h . t] then if h is mime(type, subtype, extensions) then
  2059 + if contains_no_case(extensions, ext)
  2060 + then success(h)
  2061 + else recognize_mime_type_from_ext(ext,t)
  2062 + }.
2032 2063  
2033 2064 define Maybe(MIME)
2034 2065 recognize_mime_type_from_uri
... ... @@ -2038,13 +2069,8 @@ define Maybe(MIME)
2038 2069 ) =
2039 2070 recognize_mime_type_from_ext(get_uri_extension(uri),known_mime_types(desc)).
2040 2071  
2041   -
2042 2072  
2043 2073  
2044   -
2045   -
2046   -
2047   -
2048 2074 *** [5.4] Formating HTTP headers.
2049 2075  
2050 2076 This is the formating for sending to the client (hence, it has nothing to do with the
... ... @@ -2187,11 +2213,11 @@ define String
2187 2213 Maybe(FileTimes) mb_ftimes,
2188 2214 Int size,
2189 2215 ) =
2190   - if mb_ftimes is
2191   - {
2192   - failure then println("Warning: no file times for '" + filename + "', etag won't be very accurate."); to_ascii(sha1((filename, size))),
2193   - success(ftimes) then to_ascii(md5((filename, ftimes, size)))
2194   - }.
  2216 + if mb_ftimes is
  2217 + {
  2218 + failure then println("Warning: no file times for '" + filename + "', etag won't be very accurate."); to_ascii(sha1((filename, size))),
  2219 + success(ftimes) then to_ascii(md5((filename, ftimes, size)))
  2220 + }.
2195 2221  
2196 2222 define Bool
2197 2223 are_same_etag
... ... @@ -2243,18 +2269,18 @@ define One
2243 2269 Checking if a connection is under SSL.
2244 2270  
2245 2271 define Bool
2246   - is_SSL
2247   - (
2248   - Connection c
2249   - ) =
2250   - if c is
2251   - {
2252   - file_r(_) then false,
2253   - file_w(_) then false,
2254   - file_rw(_) then false,
2255   - tcp(_) then false,
2256   - ssl(_) then true
2257   - }.
  2272 + is_SSL
  2273 + (
  2274 + Connection c
  2275 + ) =
  2276 + if c is
  2277 + {
  2278 + file_r(_) then false,
  2279 + file_w(_) then false,
  2280 + file_rw(_) then false,
  2281 + tcp(_) then false,
  2282 + ssl(_) then true
  2283 + }.
2258 2284  
2259 2285  
2260 2286  
... ... @@ -2527,10 +2553,10 @@ define Maybe(String)
2527 2553 }.
2528 2554  
2529 2555 define Maybe(String)
2530   - get_boundary
2531   - (
2532   - List(HTTP_header) headers
2533   - ) =
  2556 + get_boundary
  2557 + (
  2558 + List(HTTP_header) headers
  2559 + )=
2534 2560 if headers is
2535 2561 {
2536 2562 [ ] then failure,
... ... @@ -2586,13 +2612,13 @@ define Maybe(String)
2586 2612 argument.
2587 2613  
2588 2614 define Maybe(Int)
2589   - find
2590   - (
2591   - String what,
2592   - ByteArray where,
2593   - Int start,
2594   - Int end
2595   - ) =
  2615 + find
  2616 + (
  2617 + String what,
  2618 + ByteArray where,
  2619 + Int start,
  2620 + Int end
  2621 + ) =
2596 2622 if find(to_byte_array(what),where,start) is
2597 2623 {
2598 2624 failure then failure,
... ... @@ -2601,7 +2627,23 @@ define Maybe(Int)
2601 2627 then failure
2602 2628 else success(n)
2603 2629 }.
2604   -
  2630 +
  2631 +define Maybe(Int)
  2632 + find
  2633 + (
  2634 + String what,
  2635 + String where,
  2636 + Int start,
  2637 + Int end
  2638 + ) =
  2639 + if find_string(where,what,start) is
  2640 + {
  2641 + failure then failure,
  2642 + success(n) then
  2643 + if n+length(what) >= end
  2644 + then failure
  2645 + else success(n)
  2646 + }.
2605 2647  
2606 2648 define String
2607 2649 read_attribute_value
... ... @@ -2642,26 +2684,26 @@ define Maybe(String)
2642 2684  
2643 2685  
2644 2686 define Maybe((String,Maybe(String)))
2645   - find_name_and_filename
2646   - (
2647   - ByteArray body,
2648   - Int start,
2649   - Int end
2650   - ) =
2651   - if find(to_byte_array("Content-Disposition"),body,start) is
2652   - {
2653   - failure then failure,
2654   - success(n) then
2655   - if find_attribute("name",body,n+19,end) is
2656   - {
2657   - failure then failure,
2658   - success(name_value) then if find_attribute("filename",body,n+19,end) is
2659   - {
2660   - failure then success((name_value,failure)),
2661   - success(filename_value) then success((name_value,success(filename_value)))
2662   - }
2663   - }
2664   - }.
  2687 + find_name_and_filename
  2688 + (
  2689 + ByteArray body,
  2690 + Int start,
  2691 + Int end
  2692 + ) =
  2693 + if find(to_byte_array("Content-Disposition"),body,start) is
  2694 + {
  2695 + failure then failure,
  2696 + success(n) then
  2697 + if find_attribute("name",body,n+19,end) is
  2698 + {
  2699 + failure then failure,
  2700 + success(name_value) then if find_attribute("filename",body,n+19,end) is
  2701 + {
  2702 + failure then success((name_value,failure)),
  2703 + success(filename_value) then success((name_value,success(filename_value)))
  2704 + }
  2705 + }
  2706 + }.
2665 2707  
2666 2708  
2667 2709  
... ... @@ -2697,27 +2739,38 @@ define Maybe((String,Maybe(String)))
2697 2739 define Maybe(String) // returns the temporary file name
2698 2740 save_uploaded_file
2699 2741 (
2700   - Web_Site_Description desc,
2701   - ByteArray body,
2702   - Int start,
2703   - Int end,
2704   - SState s
  2742 + Web_Site_Description desc,
  2743 + RStream body_fd,
  2744 +// ByteArray body,
  2745 + Int start,
  2746 + Int end,
  2747 + SState s
2705 2748 ) =
2706 2749 s.uploaded_file_count <- 1 + *(s.uploaded_file_count);
2707 2750 with tfn = "_"+to_decimal(virtual_machine_id)+"_"+to_decimal(*(s.uploaded_file_count)),
2708   - if (Maybe(RWStream))file(site_directory(desc)+"/upload_temporary/"+tfn, new) is
2709   - {
2710   - failure then failure,
2711   - success(f) then
2712   - if reliable_write(file(f),extract(body,start,end)) is
2713   - {
2714   - failure then failure,
2715   - success(nw) then
2716   - if nw = end - start
2717   - then success(tfn)
2718   - else failure
2719   - }
2720   - }.
  2751 +// println("save_uploaded_file to :"+site_directory(desc)+"/upload_temporary/"+tfn);
  2752 +// println("start offset = "+start+" end offset = "+end);
  2753 + //make data_io which is the size of the file to extract
  2754 + if copy_Data_IO_to_file(make_data_io(body_fd, start, end - start), site_directory(desc)+"/upload_temporary/"+tfn) is copy_ok(_)
  2755 + then success(tfn)
  2756 + else failure
  2757 + .
  2758 +
  2759 +
  2760 +
  2761 +// if (Maybe(RWStream))file(site_directory(desc)+"/upload_temporary/"+tfn, new) is
  2762 +// {
  2763 +// failure then failure,
  2764 +// success(f) then
  2765 +// if reliable_write(file(f),extract(body,start,end)) is
  2766 +// {
  2767 +// failure then failure,
  2768 +// success(nw) then
  2769 +// if nw = end - start
  2770 +// then success(tfn)
  2771 +// else failure
  2772 +// }
  2773 +// }.
2721 2774  
2722 2775  
2723 2776  
... ... @@ -2763,94 +2816,114 @@ define String
2763 2816 *** [5.7.6] Reading a multipart entity.
2764 2817  
2765 2818 define Maybe(Web_arg)
2766   - get_multipart_entity
2767   - (
2768   - Web_Site_Description desc,
2769   - ByteArray body,
2770   - Int start,
2771   - Int end,
2772   - SState s
2773   - ) =
2774   - if find(to_byte_array(crlf+crlf),body,start) is
2775   - {
2776   - failure then failure,
2777   - success(k) then
2778   - if k >= end // must be within this entity, not the next one
2779   - then failure
2780   - else if find_name_and_filename(body,start,k) is
2781   - {
2782   - failure then failure,
2783   - success(n_mbfn) then if n_mbfn is (name,mbfn) then
  2819 + get_multipart_entity
  2820 + (
  2821 + Web_Site_Description desc,
  2822 + String body_temp_file,
  2823 + Int start_offset, //real offset in source file of the part
  2824 + Int end_offset, //real offset in source file of the part
  2825 + SState s
  2826 + )=
  2827 + //Get header of the part
  2828 + if find_the_first(body_temp_file, crlf+crlf, start_offset, end_offset) is
  2829 + {
  2830 + failure then failure,
  2831 + success(k) then
  2832 + if (Maybe(RStream))file(body_temp_file, read) is
  2833 + {
  2834 + failure then failure,
  2835 + success(body_fd) then
  2836 + if read_bytes(make_data_io(body_fd, start_offset, k), k) is success(header_part) then
  2837 +
  2838 + if find_name_and_filename(header_part, 0, k) is
  2839 + {
  2840 + failure then failure,
  2841 + success(n_mbfn) then if n_mbfn is (name, mbfn) then
2784 2842 if mbfn is
2785   - {
  2843 + {
2786 2844 failure then
2787   - success(web_arg(name,to_string(extract(body,k+4,end-2)))),
  2845 + if read_bytes(make_data_io(body_fd, start_offset+k+4, (end_offset-2)-(start_offset+k+4)), (end_offset-2)-(start_offset+k+4)) is success(attachement) then
  2846 + success(web_arg(name,to_string(attachement)))
2788 2847 // we must substract 2 to end because of crlf just before the boundary
  2848 + else
  2849 + failure,
2789 2850  
2790 2851 success(fn) then
2791   - if save_uploaded_file(desc, body, k+4, end-2, s) is
2792   - {
2793   - failure then failure,
2794   - success(tfn) then
2795   - success(upload(name,remove_path(fn),
2796   - site_directory(desc)+"/upload_temporary/"+tfn))
  2852 + if save_uploaded_file(desc, body_fd, start_offset+k+4, end_offset-2, s) is
  2853 + {
  2854 + failure then failure,
  2855 + success(tfn) then success(upload(name, remove_path(fn), site_directory(desc)+"/upload_temporary/"+tfn))
2797 2856  
2798 2857 }
2799 2858 }
2800 2859 }
2801   - }.
  2860 + else
  2861 + failure
  2862 + }
  2863 + }.
2802 2864  
2803 2865  
2804 2866  
2805 2867 define List(Web_arg)
2806   - read_multipart_form_data_encoded_web_args
2807   - (
2808   - Web_Site_Description desc,
2809   - ByteArray body,
2810   - ByteArray __boundary,
2811   - Int i,
2812   - SState s
2813   - ) =
2814   - if find(__boundary,body,i) is
2815   - {
2816   - failure then [ ],
2817   - success(n) then
2818   - if find(__boundary,body,n+length(__boundary)) is
2819   - {
2820   - failure then [ ],
2821   - success(m) then
2822   - if get_multipart_entity(desc, body, n+length(__boundary), m, s) is
2823   - {
2824   - failure then [ ],
2825   - success(wa) then
2826   - [wa . read_multipart_form_data_encoded_web_args(desc, body, __boundary, m, s)]
2827   - }
2828   - }
2829   - }.
  2868 + read_multipart_form_data_encoded_web_args
  2869 + (
  2870 + Web_Site_Description desc,
  2871 + String body_temp_file,
  2872 + String __boundary,
  2873 + Int file_offset,
  2874 + SState s
  2875 + ) =
  2876 + with boundary_length = length(__boundary),
  2877 +// println(
  2878 +//"read_multipart_form_data_encoded_web_args
  2879 +// boundary["+__boundary+"]
  2880 +// body_temp_file : "+body_temp_file+"
  2881 +// file_offset : "+file_offset);
  2882 + //get the first boundary position
  2883 + if find_the_first(body_temp_file, __boundary, file_offset) is
  2884 + {
  2885 + failure then println("first boundary not found");[ ],
  2886 + success(first) then
  2887 + with first = first + file_offset, //adjust the offset to real offset in file
  2888 + //get the second boundary position
  2889 + if find_the_first(body_temp_file, __boundary, first + boundary_length) is
  2890 + {
  2891 + failure then println("last boundary found");[ ],
  2892 + success(last) then
  2893 + with last = last + first + boundary_length, //adjust the offset to real offset in file
  2894 + //Extract the file content here
  2895 + if get_multipart_entity(desc, body_temp_file, first+boundary_length, last, s) is
  2896 + {
  2897 + failure then [ ],
  2898 + success(wa) then
  2899 + [wa . read_multipart_form_data_encoded_web_args(desc, body_temp_file, __boundary, last, s)]
  2900 + }
  2901 + }
  2902 + }.
2830 2903  
2831 2904  
2832 2905  
2833 2906 define One
2834 2907 multipart_form_data_answer
2835 2908 (
2836   - String host_name,
2837   - Web_Site_Description desc,
2838   - Connection connection,
2839   - Word32 ip_addr,
2840   - HTTP_RequestLine request_line,
2841   - List(HTTP_header) headers,
2842   - ByteArray body,
2843   - One -> String generate_tt,
2844   - SState s
  2909 + String host_name,
  2910 + Web_Site_Description desc,
  2911 + Connection connection,
  2912 + Word32 ip_addr,
  2913 + HTTP_RequestLine request_line,
  2914 + List(HTTP_header) headers,
  2915 + String body_temp_file,
  2916 + One -> String generate_tt,
  2917 + SState s
2845 2918 ) =
2846   - if get_boundary(headers) is
2847   - {
2848   - failure then unique,
2849   - success(boundary) then
2850   - with all_web_args = query_string(request_line) +
  2919 + if get_boundary(headers) is
  2920 + {
  2921 + failure then unique,
  2922 + success(boundary) then
  2923 + with all_web_args = query_string(request_line) +
2851 2924 read_multipart_form_data_encoded_web_args(desc,
2852   - body,
2853   - to_byte_array("--"+boundary),
  2925 + body_temp_file,
  2926 + "--"+boundary,
2854 2927 0,
2855 2928 s),
2856 2929 uri = uri(request_line),
... ... @@ -2967,47 +3040,46 @@ define String
2967 3040 is achieved through the header 'Content-Type'.
2968 3041  
2969 3042 define EncodingType
2970   - get_encoding_type
2971   - (
2972   - List(HTTP_header) headers
2973   - ) =
2974   - if headers is
2975   - {
2976   - [ ] then www_url, // this is the default
2977   - [h . t] then if h is http_header(name,value) then
2978   - if name = "content-type"
2979   - then if find("multipart/form-data",value,0) is
2980   - {
2981   - failure then www_url,
2982   - success(_) then multipart_form_data
2983   - }
2984   - else get_encoding_type(t)
  3043 + get_encoding_type
  3044 + (
  3045 + List(HTTP_header) headers
  3046 + ) =
  3047 + if headers is
  3048 + {
  3049 + [ ] then www_url, // this is the default
  3050 + [h . t] then if h is http_header(name, value) then
  3051 + if name = "content-type"
  3052 + then if find("multipart/form-data",value,0) is
  3053 + {
  3054 + failure then www_url,
  3055 + success(_) then multipart_form_data
  3056 + }
  3057 + else
  3058 + get_encoding_type(t) //content-type not found, check the next header line
2985 3059 }.
2986 3060  
2987 3061  
2988 3062  
2989   -define One
2990   - send_answer
2991   - (
2992   - String host_name,
2993   - Web_Site_Description desc,
2994   - Connection connection,
2995   - HTTP_RequestLine rqline,
2996   - List(HTTP_header) headers,
2997   - ByteArray body,
2998   - One -> String generate_tt,
2999   - SState s
3000   - ) =
3001   - if rqline is request_line(type,uri,qstring) then
3002   - with rqline2 = request_line(type,handle_redirection(redirections(desc),uri,headers),qstring),
3003   - if remote_IP_address_and_port(connection) is (ip_addr,_) then
3004   - if get_encoding_type(headers) is
3005   - {
3006   - www_url then
3007   - www_url_answer(host_name,desc,connection,ip_addr,rqline2,headers,body,generate_tt),
3008   - multipart_form_data then
3009   - multipart_form_data_answer(host_name,desc,connection,ip_addr,rqline2,headers,body,generate_tt, s)
3010   - }.
  3063 + define One
  3064 + send_answer
  3065 + (
  3066 + String host_name,
  3067 + Web_Site_Description desc,
  3068 + Connection connection,
  3069 + HTTP_RequestLine rqline,
  3070 + List(HTTP_header) headers,
  3071 + ByteArray body,
  3072 + One -> String generate_tt,
  3073 + SState s
  3074 + )=
  3075 + if rqline is request_line(type, uri, qstring) then
  3076 + with rqline2 = request_line(type, handle_redirection(redirections(desc), uri, headers), qstring),
  3077 + if remote_IP_address_and_port(connection) is (ip_addr,_) then
  3078 + if get_encoding_type(headers) is
  3079 + {
  3080 + www_url then www_url_answer(host_name, desc, connection, ip_addr, rqline2, headers, body, generate_tt),
  3081 + multipart_form_data then multipart_form_data_answer(host_name, desc, connection, ip_addr, rqline2, headers, body, generate_tt, s)
  3082 + }.
3011 3083  
3012 3084  
3013 3085  
... ... @@ -3110,54 +3182,102 @@ define One
3110 3182 SState s
3111 3183 ) =
3112 3184 //t0 <- (UTime)unow;
3113   - with start_time = (Int)now,
3114   - s.sttm <- start_time;
3115   - //println("Request time: " + format_http_date(start_time));
3116   - if dos is denial_of_service(mc_v,rld_v,hd_v,ad_v,ld_v,ra_v) then
3117   - if remote_IP_address_and_port(connection.conn) is (ip_addr,port) then
3118   - if read_request_line(connection, start_time+*rld_v, dos, s) is
3119   - {
3120   - error(msg) then print(format(msg)),
3121   - ok(request_line) then
3122   - //print_delta("read_request_line");
3123   - if read_http_headers(connection, start_time+*hd_v, dos, s) is
3124   - {
3125   - error(msg) then print(format(msg)),
3126   - ok(headers) then //print_delta("read_http_headers");
3127   - if get_site(headers,sites) is
3128   - {
3129   - failure then unique,
3130   - success(p) then if p is (host_name,desc) then
3131   - //print_delta("get_site");
3132   - if get_body_size(headers) is
3133   - {
3134   - error(msg) then log_journal_msg(desc,format(msg)),
3135   - ok(body_size) then
  3185 + with start_time = (Int)now,
  3186 + s.sttm <- start_time;
  3187 + //println("Request time: " + format_http_date(start_time));
  3188 + if dos is denial_of_service(mc_v,rld_v,hd_v,ad_v,ld_v,ra_v) then
  3189 + if remote_IP_address_and_port(connection.conn) is (ip_addr,port) then
  3190 + if read_request_line(connection, start_time+*rld_v, dos, s) is
  3191 + {
  3192 + error(msg) then print(format(msg)),
  3193 + ok(rqline) then //request line
  3194 + //print_delta("read_request_line");
  3195 + if read_http_headers(connection, start_time+*hd_v, dos, s) is
  3196 + {
  3197 + error(msg) then print(format(msg)),
  3198 + ok(headers) then //print_delta("read_http_headers");
  3199 + if get_site(headers,sites) is
  3200 + {
  3201 + failure then unique,
  3202 + success(p) then if p is (host_name, desc) then
  3203 + //Body Size
  3204 + if get_body_size(headers) is
  3205 + {
  3206 + error(msg) then log_journal_msg(desc,format(msg)),
  3207 + ok(body_size) then
  3208 + if rqline is request_line(type, uri, qstring) then
  3209 + with rqline2 = request_line(type, handle_redirection(redirections(desc), uri, headers), qstring),
  3210 +
  3211 + //Get the type of encoding which decide if we read the content in ByteArray for www_url or in
  3212 + //temporary file for multipart.
  3213 + with generate_tt = make_generate_trust_ticket(dos),
  3214 + if get_encoding_type(headers) is
  3215 + {
  3216 + //WWW_URL
  3217 + www_url then
  3218 + if read_http_body(connection,body_size,constant_byte_array(0,0),1000) is
  3219 + {
  3220 + error(msg) then log_journal_msg(desc,format(msg)),
  3221 + ok(body) then
  3222 + www_url_answer(host_name, desc, connection.conn, ip_addr, rqline2, headers, body, generate_tt);
  3223 + //it's HTTP 1.1 keep-alive is default
  3224 + http_https_handler(sites, connection, is_https, dos, s)
  3225 + }
  3226 + //MULTIPART_FORM_DATA
  3227 + multipart_form_data then
  3228 +
  3229 + if body_size > 0 then
  3230 + with t0 = (UTime)unow,
  3231 + println("read body, size "+body_size);
  3232 +
  3233 + if get_socket_from_connection(conn(connection)) is
  3234 + {
  3235 + failure then println("can't get socket"),
  3236 + success(source) then
3136 3237  
3137   - with t0 = (UTime)unow,
3138   - (if body_size > 0 then
3139   - println("read body, size "+body_size)
3140   - else
3141   - unique);
3142   - if read_http_body(connection,body_size,constant_byte_array(0,0),1000) is
3143   - {
3144   - error(msg) then log_journal_msg(desc,format(msg)),
3145   - ok(body) then
3146   - with duration = (UTime) unow - t0,
3147   - (if body_size > 0 then
3148   - println("Read body "+body_size+" duration: " + __utime_to_string(duration))
3149   - else
3150   - unique);
  3238 + with tmp_body_file = "/temp/" + virtual_machine_id + "-" + now,
  3239 + if (Maybe(RWStream))file(desc.site_directory + tmp_body_file, new) is
  3240 + {
  3241 + failure then println("can't create target file "+desc.site_directory + tmp_body_file),//nothing to write
  3242 + success(target) then
  3243 +
  3244 + //get the content of the current buffer and unput char list
  3245 + with buffer = get_and_erase_buffer(connection, s),
  3246 + buffer_size = length(buffer),
  3247 + //println("buffer Size = "+buffer_size);
  3248 + //println("Old body size "+body_size+" New body size request = "+body_size - buffer_size);
  3249 + if flush(buffer, weaken(target)) is
  3250 + {
  3251 + failure then println("Can't flush the buffer"),
  3252 + success(_) then
  3253 + if copy_file(weaken(source), weaken(target), body_size - buffer_size) is copy_ok(read_size) then
  3254 +
  3255 + with duration = (UTime) unow - t0,
  3256 + println("Read body "+read_size+" duration: " + __utime_to_string(duration));
  3257 +
  3258 + multipart_form_data_answer(host_name, desc, connection.conn, ip_addr, rqline2, headers, desc.site_directory + tmp_body_file, generate_tt, s);
  3259 +
  3260 + //it's HTTP 1.1 keep-alive is default
  3261 + http_https_handler(sites, connection, is_https, dos, s)
  3262 +
  3263 + else
  3264 + println("Can't copy data from stream to temporary file ")
  3265 + }}}
  3266 + else
  3267 + println("bbody_size = 0 !")
  3268 + }
  3269 +
3151 3270 //print_delta("before send_answer");
3152   - send_answer(host_name, desc,connection.conn, request_line, headers, body,
3153   - make_generate_trust_ticket(dos), s);
3154   - //it's HTTP 1.1 keep-alive is default
3155   - http_https_handler(sites, connection, is_https, dos, s)
  3271 +// with body = constant_byte_array(0,0),
  3272 +// send_answer(host_name, desc,connection.conn, request_line, headers, body,
  3273 +// make_generate_trust_ticket(dos), s);
  3274 +// //it's HTTP 1.1 keep-alive is default
  3275 +// http_https_handler(sites, connection, is_https, dos, s)
3156 3276 //with duration = (UTime) unow - *t0,
3157 3277 //println("Request duration: " + __utime_to_string(duration))
3158 3278 //println("BufferRead duration: " + __utime_to_string(*t1));
3159 3279 //println("next_char duration: " + __utime_to_string(*t2))
3160   - }
  3280 +
3161 3281 }
3162 3282 }
3163 3283 }
... ...