comparison src/http/ngx_http_parse.c @ 692:6db6e93f55ee NGINX_1_3_9

nginx 1.3.9 *) Feature: support for chunked transfer encoding while reading client request body. *) Feature: the $request_time and $msec variables can now be used not only in the "log_format" directive. *) Bugfix: cache manager and cache loader processes might not be able to start if more than 512 listen sockets were used. *) Bugfix: in the ngx_http_dav_module.
author Igor Sysoev <http://sysoev.ru>
date Tue, 27 Nov 2012 00:00:00 +0400
parents bfa81a0490a2
children
comparison
equal deleted inserted replaced
691:acfd484db0ca 692:6db6e93f55ee
1816 1816
1817 } else { 1817 } else {
1818 args->len = 0; 1818 args->len = 0;
1819 } 1819 }
1820 } 1820 }
1821
1822
1823 ngx_int_t
1824 ngx_http_parse_chunked(ngx_http_request_t *r, ngx_buf_t *b,
1825 ngx_http_chunked_t *ctx)
1826 {
1827 u_char *pos, ch, c;
1828 ngx_int_t rc;
1829 enum {
1830 sw_chunk_start = 0,
1831 sw_chunk_size,
1832 sw_chunk_extension,
1833 sw_chunk_extension_almost_done,
1834 sw_chunk_data,
1835 sw_after_data,
1836 sw_after_data_almost_done,
1837 sw_last_chunk_extension,
1838 sw_last_chunk_extension_almost_done,
1839 sw_trailer,
1840 sw_trailer_almost_done,
1841 sw_trailer_header,
1842 sw_trailer_header_almost_done
1843 } state;
1844
1845 state = ctx->state;
1846
1847 if (state == sw_chunk_data && ctx->size == 0) {
1848 state = sw_after_data;
1849 }
1850
1851 rc = NGX_AGAIN;
1852
1853 for (pos = b->pos; pos < b->last; pos++) {
1854
1855 ch = *pos;
1856
1857 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1858 "http chunked byte: %02Xd s:%d", ch, state);
1859
1860 switch (state) {
1861
1862 case sw_chunk_start:
1863 if (ch >= '0' && ch <= '9') {
1864 state = sw_chunk_size;
1865 ctx->size = ch - '0';
1866 break;
1867 }
1868
1869 c = (u_char) (ch | 0x20);
1870
1871 if (c >= 'a' && c <= 'f') {
1872 state = sw_chunk_size;
1873 ctx->size = c - 'a' + 10;
1874 break;
1875 }
1876
1877 goto invalid;
1878
1879 case sw_chunk_size:
1880 if (ch >= '0' && ch <= '9') {
1881 ctx->size = ctx->size * 16 + (ch - '0');
1882 break;
1883 }
1884
1885 c = (u_char) (ch | 0x20);
1886
1887 if (c >= 'a' && c <= 'f') {
1888 ctx->size = ctx->size * 16 + (c - 'a' + 10);
1889 break;
1890 }
1891
1892 if (ctx->size == 0) {
1893
1894 switch (ch) {
1895 case CR:
1896 state = sw_last_chunk_extension_almost_done;
1897 break;
1898 case LF:
1899 state = sw_trailer;
1900 break;
1901 case ';':
1902 case ' ':
1903 case '\t':
1904 state = sw_last_chunk_extension;
1905 break;
1906 default:
1907 goto invalid;
1908 }
1909
1910 break;
1911 }
1912
1913 switch (ch) {
1914 case CR:
1915 state = sw_chunk_extension_almost_done;
1916 break;
1917 case LF:
1918 state = sw_chunk_data;
1919 break;
1920 case ';':
1921 case ' ':
1922 case '\t':
1923 state = sw_chunk_extension;
1924 break;
1925 default:
1926 goto invalid;
1927 }
1928
1929 break;
1930
1931 case sw_chunk_extension:
1932 switch (ch) {
1933 case CR:
1934 state = sw_chunk_extension_almost_done;
1935 break;
1936 case LF:
1937 state = sw_chunk_data;
1938 }
1939 break;
1940
1941 case sw_chunk_extension_almost_done:
1942 if (ch == LF) {
1943 state = sw_chunk_data;
1944 break;
1945 }
1946 goto invalid;
1947
1948 case sw_chunk_data:
1949 rc = NGX_OK;
1950 goto data;
1951
1952 case sw_after_data:
1953 switch (ch) {
1954 case CR:
1955 state = sw_after_data_almost_done;
1956 break;
1957 case LF:
1958 state = sw_chunk_start;
1959 }
1960 break;
1961
1962 case sw_after_data_almost_done:
1963 if (ch == LF) {
1964 state = sw_chunk_start;
1965 break;
1966 }
1967 goto invalid;
1968
1969 case sw_last_chunk_extension:
1970 switch (ch) {
1971 case CR:
1972 state = sw_last_chunk_extension_almost_done;
1973 break;
1974 case LF:
1975 state = sw_trailer;
1976 }
1977 break;
1978
1979 case sw_last_chunk_extension_almost_done:
1980 if (ch == LF) {
1981 state = sw_trailer;
1982 break;
1983 }
1984 goto invalid;
1985
1986 case sw_trailer:
1987 switch (ch) {
1988 case CR:
1989 state = sw_trailer_almost_done;
1990 break;
1991 case LF:
1992 goto done;
1993 default:
1994 state = sw_trailer_header;
1995 }
1996 break;
1997
1998 case sw_trailer_almost_done:
1999 if (ch == LF) {
2000 goto done;
2001 }
2002 goto invalid;
2003
2004 case sw_trailer_header:
2005 switch (ch) {
2006 case CR:
2007 state = sw_trailer_header_almost_done;
2008 break;
2009 case LF:
2010 state = sw_trailer;
2011 }
2012 break;
2013
2014 case sw_trailer_header_almost_done:
2015 if (ch == LF) {
2016 state = sw_trailer;
2017 break;
2018 }
2019 goto invalid;
2020
2021 }
2022 }
2023
2024 data:
2025
2026 ctx->state = state;
2027 b->pos = pos;
2028
2029 switch (state) {
2030
2031 case sw_chunk_start:
2032 ctx->length = 3 /* "0" LF LF */;
2033 break;
2034 case sw_chunk_size:
2035 ctx->length = 2 /* LF LF */
2036 + (ctx->size ? ctx->size + 4 /* LF "0" LF LF */ : 0);
2037 break;
2038 case sw_chunk_extension:
2039 case sw_chunk_extension_almost_done:
2040 ctx->length = 1 /* LF */ + ctx->size + 4 /* LF "0" LF LF */;
2041 break;
2042 case sw_chunk_data:
2043 ctx->length = ctx->size + 4 /* LF "0" LF LF */;
2044 break;
2045 case sw_after_data:
2046 case sw_after_data_almost_done:
2047 ctx->length = 4 /* LF "0" LF LF */;
2048 break;
2049 case sw_last_chunk_extension:
2050 case sw_last_chunk_extension_almost_done:
2051 ctx->length = 2 /* LF LF */;
2052 break;
2053 case sw_trailer:
2054 case sw_trailer_almost_done:
2055 ctx->length = 1 /* LF */;
2056 break;
2057 case sw_trailer_header:
2058 case sw_trailer_header_almost_done:
2059 ctx->length = 2 /* LF LF */;
2060 break;
2061
2062 }
2063
2064 return rc;
2065
2066 done:
2067
2068 ctx->state = 0;
2069 b->pos = pos + 1;
2070
2071 return NGX_DONE;
2072
2073 invalid:
2074
2075 return NGX_ERROR;
2076 }