diff options
-rw-r--r-- | doc/libmicrohttpd.texi | 2 | ||||
-rw-r--r-- | src/include/microhttpd.h | 6 | ||||
-rw-r--r-- | src/microhttpd/connection.c | 13 | ||||
-rw-r--r-- | src/microhttpd/internal.h | 92 | ||||
-rw-r--r-- | src/microhttpd/response.c | 217 |
5 files changed, 169 insertions, 161 deletions
diff --git a/doc/libmicrohttpd.texi b/doc/libmicrohttpd.texi index 2a4f09d2..bb6cab7c 100644 --- a/doc/libmicrohttpd.texi +++ b/doc/libmicrohttpd.texi | |||
@@ -2181,7 +2181,7 @@ The response object can be extended with header information and then be used | |||
2181 | any number of times. | 2181 | any number of times. |
2182 | @table @var | 2182 | @table @var |
2183 | @item iov | 2183 | @item iov |
2184 | the array for response data buffers, an internal copy of this will be made; | 2184 | the array for response data buffers, an internal copy of this will be made; however, note that the data pointed to by the @var{iov} is not copied and must be preserved unchanged at the given locations until the response is no longer in use and the @var{crfc} is called; |
2185 | 2185 | ||
2186 | @item iovcnt | 2186 | @item iovcnt |
2187 | the number of elements in @var{iov}; | 2187 | the number of elements in @var{iov}; |
diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h index b416e62a..1d44f344 100644 --- a/src/include/microhttpd.h +++ b/src/include/microhttpd.h | |||
@@ -1974,14 +1974,14 @@ union MHD_ConnectionInfo | |||
1974 | 1974 | ||
1975 | 1975 | ||
1976 | /** | 1976 | /** |
1977 | * I/O vector type. Provided for use with MHD_create_response_from_iovec. | 1977 | * I/O vector type. Provided for use with #MHD_create_response_from_iovec(). |
1978 | */ | 1978 | */ |
1979 | struct MHD_IoVec | 1979 | struct MHD_IoVec |
1980 | { | 1980 | { |
1981 | /** | 1981 | /** |
1982 | * The pointer to the memory region for I/O. | 1982 | * The pointer to the memory region for I/O. |
1983 | */ | 1983 | */ |
1984 | void *iov_base; | 1984 | const void *iov_base; |
1985 | 1985 | ||
1986 | /** | 1986 | /** |
1987 | * The size in bytes of the memory region for I/O. | 1987 | * The size in bytes of the memory region for I/O. |
@@ -3262,7 +3262,7 @@ MHD_create_response_from_fd_at_offset64 (uint64_t size, | |||
3262 | */ | 3262 | */ |
3263 | _MHD_EXTERN struct MHD_Response * | 3263 | _MHD_EXTERN struct MHD_Response * |
3264 | MHD_create_response_from_iovec (const struct MHD_IoVec *iov, | 3264 | MHD_create_response_from_iovec (const struct MHD_IoVec *iov, |
3265 | int iovcnt, | 3265 | unsigned int iovcnt, |
3266 | MHD_ContentReaderFreeCallback free_cb, | 3266 | MHD_ContentReaderFreeCallback free_cb, |
3267 | void *cls); | 3267 | void *cls); |
3268 | 3268 | ||
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c index 7f2dcd75..25d920e2 100644 --- a/src/microhttpd/connection.c +++ b/src/microhttpd/connection.c | |||
@@ -800,11 +800,12 @@ try_ready_normal_body (struct MHD_Connection *connection) | |||
800 | if (NULL != response->data_iov) | 800 | if (NULL != response->data_iov) |
801 | { | 801 | { |
802 | size_t copy_size; | 802 | size_t copy_size; |
803 | |||
803 | if (NULL != connection->resp_iov.iov) | 804 | if (NULL != connection->resp_iov.iov) |
804 | return MHD_YES; | 805 | return MHD_YES; |
805 | |||
806 | copy_size = response->data_iovcnt * sizeof(MHD_iovec_); | 806 | copy_size = response->data_iovcnt * sizeof(MHD_iovec_); |
807 | connection->resp_iov.iov = MHD_pool_allocate (connection->pool, copy_size, | 807 | connection->resp_iov.iov = MHD_pool_allocate (connection->pool, |
808 | copy_size, | ||
808 | true); | 809 | true); |
809 | if (NULL == connection->resp_iov.iov) | 810 | if (NULL == connection->resp_iov.iov) |
810 | { | 811 | { |
@@ -814,7 +815,9 @@ try_ready_normal_body (struct MHD_Connection *connection) | |||
814 | _ ("Closing connection (out of memory).\n")); | 815 | _ ("Closing connection (out of memory).\n")); |
815 | return MHD_NO; | 816 | return MHD_NO; |
816 | } | 817 | } |
817 | memcpy (connection->resp_iov.iov, response->data_iov, copy_size); | 818 | memcpy (connection->resp_iov.iov, |
819 | response->data_iov, | ||
820 | copy_size); | ||
818 | connection->resp_iov.cnt = response->data_iovcnt; | 821 | connection->resp_iov.cnt = response->data_iovcnt; |
819 | connection->resp_iov.sent = 0; | 822 | connection->resp_iov.sent = 0; |
820 | return MHD_YES; | 823 | return MHD_YES; |
@@ -3047,7 +3050,9 @@ MHD_connection_handle_write (struct MHD_Connection *connection) | |||
3047 | #endif /* _MHD_HAVE_SENDFILE */ | 3050 | #endif /* _MHD_HAVE_SENDFILE */ |
3048 | if (NULL != response->data_iov) | 3051 | if (NULL != response->data_iov) |
3049 | { | 3052 | { |
3050 | ret = MHD_send_iovec_ (connection, &connection->resp_iov, true); | 3053 | ret = MHD_send_iovec_ (connection, |
3054 | &connection->resp_iov, | ||
3055 | true); | ||
3051 | } | 3056 | } |
3052 | else | 3057 | else |
3053 | { | 3058 | { |
diff --git a/src/microhttpd/internal.h b/src/microhttpd/internal.h index ba71d1eb..06e7e4a7 100644 --- a/src/microhttpd/internal.h +++ b/src/microhttpd/internal.h | |||
@@ -92,8 +92,9 @@ | |||
92 | * @param fd the FD to close | 92 | * @param fd the FD to close |
93 | */ | 93 | */ |
94 | #define MHD_fd_close_chk_(fd) do { \ | 94 | #define MHD_fd_close_chk_(fd) do { \ |
95 | if ( (0 != close ((fd)) && (EBADF == errno)) ) \ | 95 | if ( (0 != close ((fd)) && (EBADF == errno)) ) { \ |
96 | MHD_PANIC (_ ("Failed to close FD.\n")); \ | 96 | MHD_PANIC (_ ("Failed to close FD.\n")); \ |
97 | } \ | ||
97 | } while (0) | 98 | } while (0) |
98 | 99 | ||
99 | /* | 100 | /* |
@@ -509,7 +510,7 @@ struct MHD_Response | |||
509 | /** | 510 | /** |
510 | * Number of elements in data_iov. | 511 | * Number of elements in data_iov. |
511 | */ | 512 | */ |
512 | size_t data_iovcnt; | 513 | unsigned int data_iovcnt; |
513 | }; | 514 | }; |
514 | 515 | ||
515 | 516 | ||
@@ -1933,12 +1934,13 @@ struct MHD_Daemon | |||
1933 | #define DLL_insert(head,tail,element) do { \ | 1934 | #define DLL_insert(head,tail,element) do { \ |
1934 | mhd_assert (NULL == (element)->next); \ | 1935 | mhd_assert (NULL == (element)->next); \ |
1935 | mhd_assert (NULL == (element)->prev); \ | 1936 | mhd_assert (NULL == (element)->prev); \ |
1936 | (element)->next = (head); \ | 1937 | (element)->next = (head); \ |
1937 | (element)->prev = NULL; \ | 1938 | (element)->prev = NULL; \ |
1938 | if ((tail) == NULL) \ | 1939 | if ((tail) == NULL) { \ |
1939 | (tail) = element; \ | 1940 | (tail) = element; \ |
1940 | else \ | 1941 | } else { \ |
1941 | (head)->prev = element; \ | 1942 | (head)->prev = element; \ |
1943 | } \ | ||
1942 | (head) = (element); } while (0) | 1944 | (head) = (element); } while (0) |
1943 | 1945 | ||
1944 | 1946 | ||
@@ -1954,15 +1956,17 @@ struct MHD_Daemon | |||
1954 | #define DLL_remove(head,tail,element) do { \ | 1956 | #define DLL_remove(head,tail,element) do { \ |
1955 | mhd_assert ( (NULL != (element)->next) || ((element) == (tail))); \ | 1957 | mhd_assert ( (NULL != (element)->next) || ((element) == (tail))); \ |
1956 | mhd_assert ( (NULL != (element)->prev) || ((element) == (head))); \ | 1958 | mhd_assert ( (NULL != (element)->prev) || ((element) == (head))); \ |
1957 | if ((element)->prev == NULL) \ | 1959 | if ((element)->prev == NULL) { \ |
1958 | (head) = (element)->next; \ | 1960 | (head) = (element)->next; \ |
1959 | else \ | 1961 | } else { \ |
1960 | (element)->prev->next = (element)->next; \ | 1962 | (element)->prev->next = (element)->next; \ |
1961 | if ((element)->next == NULL) \ | 1963 | } \ |
1962 | (tail) = (element)->prev; \ | 1964 | if ((element)->next == NULL) { \ |
1963 | else \ | 1965 | (tail) = (element)->prev; \ |
1966 | } else { \ | ||
1964 | (element)->next->prev = (element)->prev; \ | 1967 | (element)->next->prev = (element)->prev; \ |
1965 | (element)->next = NULL; \ | 1968 | } \ |
1969 | (element)->next = NULL; \ | ||
1966 | (element)->prev = NULL; } while (0) | 1970 | (element)->prev = NULL; } while (0) |
1967 | 1971 | ||
1968 | 1972 | ||
@@ -1977,12 +1981,13 @@ struct MHD_Daemon | |||
1977 | #define XDLL_insert(head,tail,element) do { \ | 1981 | #define XDLL_insert(head,tail,element) do { \ |
1978 | mhd_assert (NULL == (element)->nextX); \ | 1982 | mhd_assert (NULL == (element)->nextX); \ |
1979 | mhd_assert (NULL == (element)->prevX); \ | 1983 | mhd_assert (NULL == (element)->prevX); \ |
1980 | (element)->nextX = (head); \ | 1984 | (element)->nextX = (head); \ |
1981 | (element)->prevX = NULL; \ | 1985 | (element)->prevX = NULL; \ |
1982 | if (NULL == (tail)) \ | 1986 | if (NULL == (tail)) { \ |
1983 | (tail) = element; \ | 1987 | (tail) = element; \ |
1984 | else \ | 1988 | } else { \ |
1985 | (head)->prevX = element; \ | 1989 | (head)->prevX = element; \ |
1990 | } \ | ||
1986 | (head) = (element); } while (0) | 1991 | (head) = (element); } while (0) |
1987 | 1992 | ||
1988 | 1993 | ||
@@ -1998,15 +2003,17 @@ struct MHD_Daemon | |||
1998 | #define XDLL_remove(head,tail,element) do { \ | 2003 | #define XDLL_remove(head,tail,element) do { \ |
1999 | mhd_assert ( (NULL != (element)->nextX) || ((element) == (tail))); \ | 2004 | mhd_assert ( (NULL != (element)->nextX) || ((element) == (tail))); \ |
2000 | mhd_assert ( (NULL != (element)->prevX) || ((element) == (head))); \ | 2005 | mhd_assert ( (NULL != (element)->prevX) || ((element) == (head))); \ |
2001 | if (NULL == (element)->prevX) \ | 2006 | if (NULL == (element)->prevX) { \ |
2002 | (head) = (element)->nextX; \ | 2007 | (head) = (element)->nextX; \ |
2003 | else \ | 2008 | } else { \ |
2004 | (element)->prevX->nextX = (element)->nextX; \ | 2009 | (element)->prevX->nextX = (element)->nextX; \ |
2005 | if (NULL == (element)->nextX) \ | 2010 | } \ |
2006 | (tail) = (element)->prevX; \ | 2011 | if (NULL == (element)->nextX) { \ |
2007 | else \ | 2012 | (tail) = (element)->prevX; \ |
2013 | } else { \ | ||
2008 | (element)->nextX->prevX = (element)->prevX; \ | 2014 | (element)->nextX->prevX = (element)->prevX; \ |
2009 | (element)->nextX = NULL; \ | 2015 | } \ |
2016 | (element)->nextX = NULL; \ | ||
2010 | (element)->prevX = NULL; } while (0) | 2017 | (element)->prevX = NULL; } while (0) |
2011 | 2018 | ||
2012 | 2019 | ||
@@ -2020,11 +2027,12 @@ struct MHD_Daemon | |||
2020 | */ | 2027 | */ |
2021 | #define EDLL_insert(head,tail,element) do { \ | 2028 | #define EDLL_insert(head,tail,element) do { \ |
2022 | (element)->nextE = (head); \ | 2029 | (element)->nextE = (head); \ |
2023 | (element)->prevE = NULL; \ | 2030 | (element)->prevE = NULL; \ |
2024 | if ((tail) == NULL) \ | 2031 | if ((tail) == NULL) { \ |
2025 | (tail) = element; \ | 2032 | (tail) = element; \ |
2026 | else \ | 2033 | } else { \ |
2027 | (head)->prevE = element; \ | 2034 | (head)->prevE = element; \ |
2035 | } \ | ||
2028 | (head) = (element); } while (0) | 2036 | (head) = (element); } while (0) |
2029 | 2037 | ||
2030 | 2038 | ||
@@ -2037,16 +2045,18 @@ struct MHD_Daemon | |||
2037 | * @param tail pointer to the tail of the EDLL | 2045 | * @param tail pointer to the tail of the EDLL |
2038 | * @param element element to remove | 2046 | * @param element element to remove |
2039 | */ | 2047 | */ |
2040 | #define EDLL_remove(head,tail,element) do { \ | 2048 | #define EDLL_remove(head,tail,element) do { \ |
2041 | if ((element)->prevE == NULL) \ | 2049 | if ((element)->prevE == NULL) { \ |
2042 | (head) = (element)->nextE; \ | 2050 | (head) = (element)->nextE; \ |
2043 | else \ | 2051 | } else { \ |
2044 | (element)->prevE->nextE = (element)->nextE; \ | 2052 | (element)->prevE->nextE = (element)->nextE; \ |
2045 | if ((element)->nextE == NULL) \ | 2053 | } \ |
2046 | (tail) = (element)->prevE; \ | 2054 | if ((element)->nextE == NULL) { \ |
2047 | else \ | 2055 | (tail) = (element)->prevE; \ |
2056 | } else { \ | ||
2048 | (element)->nextE->prevE = (element)->prevE; \ | 2057 | (element)->nextE->prevE = (element)->prevE; \ |
2049 | (element)->nextE = NULL; \ | 2058 | } \ |
2059 | (element)->nextE = NULL; \ | ||
2050 | (element)->prevE = NULL; } while (0) | 2060 | (element)->prevE = NULL; } while (0) |
2051 | 2061 | ||
2052 | 2062 | ||
diff --git a/src/microhttpd/response.c b/src/microhttpd/response.c index 3dbcd245..14e036c8 100644 --- a/src/microhttpd/response.c +++ b/src/microhttpd/response.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of libmicrohttpd | 2 | This file is part of libmicrohttpd |
3 | Copyright (C) 2007, 2009, 2010, 2016, 2017 Daniel Pittman and Christian Grothoff | 3 | Copyright (C) 2007-2021 Daniel Pittman and Christian Grothoff |
4 | 4 | ||
5 | This library is free software; you can redistribute it and/or | 5 | This library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Lesser General Public | 6 | modify it under the terms of the GNU Lesser General Public |
@@ -861,135 +861,128 @@ MHD_create_response_from_buffer_with_free_callback (size_t size, | |||
861 | */ | 861 | */ |
862 | _MHD_EXTERN struct MHD_Response * | 862 | _MHD_EXTERN struct MHD_Response * |
863 | MHD_create_response_from_iovec (const struct MHD_IoVec *iov, | 863 | MHD_create_response_from_iovec (const struct MHD_IoVec *iov, |
864 | int iovcnt, | 864 | unsigned int iovcnt, |
865 | MHD_ContentReaderFreeCallback free_cb, | 865 | MHD_ContentReaderFreeCallback free_cb, |
866 | void *cls) | 866 | void *cls) |
867 | { | 867 | { |
868 | struct MHD_Response *response; | 868 | struct MHD_Response *response; |
869 | unsigned int i; | ||
870 | int i_cp = 0; /**< Index in the copy of iov */ | ||
871 | uint64_t total_size = 0; | ||
872 | const void *last_valid_buffer = NULL; | ||
869 | 873 | ||
870 | if ((NULL == iov) && (0 < iovcnt)) | 874 | if ((NULL == iov) && (0 < iovcnt)) |
871 | return NULL; | 875 | return NULL; |
872 | 876 | ||
873 | response = MHD_calloc_ (1, sizeof (struct MHD_Response)); | 877 | response = MHD_calloc_ (1, sizeof (struct MHD_Response)); |
874 | if (NULL != response) | 878 | if (NULL == response) |
879 | return NULL; | ||
880 | if (! MHD_mutex_init_ (&response->mutex)) | ||
881 | { | ||
882 | free (response); | ||
883 | return NULL; | ||
884 | } | ||
885 | /* Calculate final size, number of valid elements, and check 'iov' */ | ||
886 | for (i = 0; i < iovcnt; ++i) | ||
875 | { | 887 | { |
876 | if (MHD_mutex_init_ (&response->mutex)) | 888 | if (0 == iov[i].iov_len) |
889 | continue; /* skip zero-sized elements */ | ||
890 | if (NULL == iov[i].iov_base) | ||
877 | { | 891 | { |
878 | int i; | 892 | i_cp = -1; /* error */ |
879 | int i_cp; /**< Index in the copy of iov */ | 893 | break; |
880 | uint64_t total_size; | 894 | } |
881 | void *last_valid_buffer; | 895 | if ( (total_size > (total_size + iov[i].iov_len)) || |
882 | 896 | (INT_MAX == i_cp) || | |
883 | i_cp = 0; | 897 | (SSIZE_MAX < iov[i].iov_len) ) |
884 | total_size = 0; | 898 | { |
885 | last_valid_buffer = NULL; | 899 | i_cp = -1; /* overflow */ |
886 | /* Calculate final size, number of valid elements, and check 'iov' */ | 900 | break; |
887 | for (i = 0; iovcnt > i; ++i) | 901 | } |
888 | { | 902 | last_valid_buffer = iov[i].iov_base; |
889 | #if defined(MHD_WINSOCK_SOCKETS) && defined(_WIN64) | 903 | total_size += iov[i].iov_len; |
890 | int64_t i_add; | ||
891 | #endif /* ! MHD_WINSOCK_SOCKETS && _WIN64 */ | ||
892 | if (0 == iov[i].iov_len) | ||
893 | continue; /* skip zero-sized elements */ | ||
894 | |||
895 | if (NULL == iov[i].iov_base) | ||
896 | { | ||
897 | i_cp = -1; /* error */ | ||
898 | break; | ||
899 | } | ||
900 | if ( (total_size > (total_size + iov[i].iov_len)) || | ||
901 | (INT_MAX == i_cp) || | ||
902 | (SSIZE_MAX < iov[i].iov_len) ) | ||
903 | { | ||
904 | i_cp = -1; /* overflow */ | ||
905 | break; | ||
906 | } | ||
907 | last_valid_buffer = iov[i].iov_base; | ||
908 | total_size += iov[i].iov_len; | ||
909 | #if defined(MHD_POSIX_SOCKETS) || ! defined(_WIN64) | 904 | #if defined(MHD_POSIX_SOCKETS) || ! defined(_WIN64) |
910 | i_cp++; | 905 | i_cp++; |
911 | #else /* ! MHD_POSIX_SOCKETS && _WIN64 */ | 906 | #else /* ! MHD_POSIX_SOCKETS && _WIN64 */ |
912 | i_add = iov[i].iov_len / ULONG_MAX; | 907 | { |
913 | if (0 != iov[i].iov_len % ULONG_MAX) | 908 | int64_t i_add; |
914 | i_add++; | 909 | |
915 | if (INT_MAX < (i_add + i_cp)) | 910 | i_add = iov[i].iov_len / ULONG_MAX; |
916 | { | 911 | if (0 != iov[i].iov_len % ULONG_MAX) |
917 | i_cp = -1; /* overflow */ | 912 | i_add++; |
918 | break; | 913 | if (INT_MAX < (i_add + i_cp)) |
919 | } | ||
920 | i_cp += (int) i_add; | ||
921 | #endif /* ! MHD_POSIX_SOCKETS && _WIN64 */ | ||
922 | } | ||
923 | if (0 <= i_cp) | ||
924 | { | 914 | { |
925 | response->fd = -1; | 915 | i_cp = -1; /* overflow */ |
926 | response->reference_count = 1; | 916 | break; |
927 | response->total_size = total_size; | ||
928 | response->crc_cls = cls; | ||
929 | response->crfc = free_cb; | ||
930 | if (1 < i_cp) | ||
931 | { | ||
932 | MHD_iovec_ *iov_copy; | ||
933 | int num_copy_elements = i_cp; | ||
934 | |||
935 | iov_copy = MHD_calloc_ (num_copy_elements, sizeof(MHD_iovec_)); | ||
936 | if (NULL != iov_copy) | ||
937 | { | ||
938 | i_cp = 0; | ||
939 | for (i = 0; iovcnt > i; ++i) | ||
940 | { | ||
941 | size_t element_size; | ||
942 | uint8_t *buf; | ||
943 | |||
944 | if (0 == iov[i].iov_len) | ||
945 | continue; /* skip zero-sized elements */ | ||
946 | |||
947 | buf = (uint8_t*) iov[i].iov_base; | ||
948 | element_size = iov[i].iov_len; | ||
949 | #if defined(MHD_WINSOCK_SOCKETS) && defined(_WIN64) | ||
950 | while (ULONG_MAX < element_size) | ||
951 | { | ||
952 | iov_copy[i_cp].iov_base = (void*) buf; | ||
953 | iov_copy[i_cp].iov_len = ULONG_MAX; | ||
954 | buf += ULONG_MAX; | ||
955 | element_size -= ULONG_MAX; | ||
956 | i_cp++; | ||
957 | } | ||
958 | #endif /* MHD_WINSOCK_SOCKETS && _WIN64 */ | ||
959 | iov_copy[i_cp].iov_base = (void*) buf; | ||
960 | iov_copy[i_cp].iov_len = element_size; | ||
961 | i_cp++; | ||
962 | } | ||
963 | |||
964 | mhd_assert (num_copy_elements == i_cp); | ||
965 | response->data_iov = iov_copy; | ||
966 | response->data_iovcnt = i_cp; | ||
967 | |||
968 | return response; | ||
969 | } | ||
970 | |||
971 | } | ||
972 | else if (1 == i_cp) | ||
973 | { | ||
974 | mhd_assert (NULL != last_valid_buffer); | ||
975 | response->data = last_valid_buffer; | ||
976 | response->data_size = total_size; | ||
977 | |||
978 | return response; | ||
979 | } | ||
980 | else /* if (0 == i_nz) */ | ||
981 | { | ||
982 | mhd_assert (0 == total_size); | ||
983 | |||
984 | return response; | ||
985 | } | ||
986 | } | 917 | } |
987 | /* Some error condition */ | 918 | i_cp += (int) i_add; |
988 | MHD_mutex_destroy_chk_ (&response->mutex); | ||
989 | } | 919 | } |
920 | #endif /* ! MHD_POSIX_SOCKETS && _WIN64 */ | ||
921 | } | ||
922 | if (-1 == i_cp) | ||
923 | { | ||
924 | /* Some error condition */ | ||
925 | MHD_mutex_destroy_chk_ (&response->mutex); | ||
990 | free (response); | 926 | free (response); |
927 | return NULL; | ||
928 | } | ||
929 | response->fd = -1; | ||
930 | response->reference_count = 1; | ||
931 | response->total_size = total_size; | ||
932 | response->crc_cls = cls; | ||
933 | response->crfc = free_cb; | ||
934 | if (0 == i_cp) | ||
935 | { | ||
936 | mhd_assert (0 == total_size); | ||
937 | return response; | ||
938 | } | ||
939 | if (1 == i_cp) | ||
940 | { | ||
941 | mhd_assert (NULL != last_valid_buffer); | ||
942 | response->data = (void *) last_valid_buffer; | ||
943 | response->data_size = total_size; | ||
944 | return response; | ||
945 | } | ||
946 | mhd_assert (1 < i_cp); | ||
947 | { | ||
948 | MHD_iovec_ *iov_copy; | ||
949 | int num_copy_elements = i_cp; | ||
950 | |||
951 | iov_copy = MHD_calloc_ (num_copy_elements, | ||
952 | sizeof(MHD_iovec_)); | ||
953 | if (NULL == iov_copy) | ||
954 | { | ||
955 | MHD_mutex_destroy_chk_ (&response->mutex); | ||
956 | free (response); | ||
957 | return NULL; | ||
958 | } | ||
959 | i_cp = 0; | ||
960 | for (i = 0; i < iovcnt; ++i) | ||
961 | { | ||
962 | size_t element_size = iov[i].iov_len; | ||
963 | const void *buf = iov[i].iov_base; | ||
964 | |||
965 | if (0 == element_size) | ||
966 | continue; /* skip zero-sized elements */ | ||
967 | #if defined(MHD_WINSOCK_SOCKETS) && defined(_WIN64) | ||
968 | while (ULONG_MAX < element_size) | ||
969 | { | ||
970 | iov_copy[i_cp].iov_base = buf; | ||
971 | iov_copy[i_cp].iov_len = ULONG_MAX; | ||
972 | buf += ULONG_MAX; | ||
973 | element_size -= ULONG_MAX; | ||
974 | i_cp++; | ||
975 | } | ||
976 | #endif /* MHD_WINSOCK_SOCKETS && _WIN64 */ | ||
977 | iov_copy[i_cp].iov_base = (void *) buf; | ||
978 | iov_copy[i_cp].iov_len = element_size; | ||
979 | i_cp++; | ||
980 | } | ||
981 | mhd_assert (num_copy_elements == i_cp); | ||
982 | response->data_iov = iov_copy; | ||
983 | response->data_iovcnt = i_cp; | ||
984 | return response; | ||
991 | } | 985 | } |
992 | return NULL; | ||
993 | } | 986 | } |
994 | 987 | ||
995 | 988 | ||