aboutsummaryrefslogtreecommitdiff
path: root/src/microhttpd/response.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/microhttpd/response.c')
-rw-r--r--src/microhttpd/response.c153
1 files changed, 153 insertions, 0 deletions
diff --git a/src/microhttpd/response.c b/src/microhttpd/response.c
index 4ae46bf3..3dbcd245 100644
--- a/src/microhttpd/response.c
+++ b/src/microhttpd/response.c
@@ -846,6 +846,153 @@ MHD_create_response_from_buffer_with_free_callback (size_t size,
846} 846}
847 847
848 848
849/**
850 * Create a response object from an array of memory buffers.
851 * The response object can be extended with header information and then be used
852 * any number of times.
853 *
854 * @param iov the array for response data buffers, an internal copy of this
855 * will be made
856 * @param iovcnt the number of elements in @a iov
857 * @param free_cb the callback to clean up any data associated with @a iov when
858 * the response is destroyed.
859 * @param cls the argument passed to @a free_cb
860 * @return NULL on error (i.e. invalid arguments, out of memory)
861 */
862_MHD_EXTERN struct MHD_Response *
863MHD_create_response_from_iovec (const struct MHD_IoVec *iov,
864 int iovcnt,
865 MHD_ContentReaderFreeCallback free_cb,
866 void *cls)
867{
868 struct MHD_Response *response;
869
870 if ((NULL == iov) && (0 < iovcnt))
871 return NULL;
872
873 response = MHD_calloc_ (1, sizeof (struct MHD_Response));
874 if (NULL != response)
875 {
876 if (MHD_mutex_init_ (&response->mutex))
877 {
878 int i;
879 int i_cp; /**< Index in the copy of iov */
880 uint64_t total_size;
881 void *last_valid_buffer;
882
883 i_cp = 0;
884 total_size = 0;
885 last_valid_buffer = NULL;
886 /* Calculate final size, number of valid elements, and check 'iov' */
887 for (i = 0; iovcnt > i; ++i)
888 {
889#if defined(MHD_WINSOCK_SOCKETS) && defined(_WIN64)
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)
910 i_cp++;
911#else /* ! MHD_POSIX_SOCKETS && _WIN64 */
912 i_add = iov[i].iov_len / ULONG_MAX;
913 if (0 != iov[i].iov_len % ULONG_MAX)
914 i_add++;
915 if (INT_MAX < (i_add + i_cp))
916 {
917 i_cp = -1; /* overflow */
918 break;
919 }
920 i_cp += (int) i_add;
921#endif /* ! MHD_POSIX_SOCKETS && _WIN64 */
922 }
923 if (0 <= i_cp)
924 {
925 response->fd = -1;
926 response->reference_count = 1;
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 }
987 /* Some error condition */
988 MHD_mutex_destroy_chk_ (&response->mutex);
989 }
990 free (response);
991 }
992 return NULL;
993}
994
995
849#ifdef UPGRADE_SUPPORT 996#ifdef UPGRADE_SUPPORT
850/** 997/**
851 * This connection-specific callback is provided by MHD to 998 * This connection-specific callback is provided by MHD to
@@ -1287,6 +1434,12 @@ MHD_destroy_response (struct MHD_Response *response)
1287#endif 1434#endif
1288 if (NULL != response->crfc) 1435 if (NULL != response->crfc)
1289 response->crfc (response->crc_cls); 1436 response->crfc (response->crc_cls);
1437
1438 if (NULL != response->data_iov)
1439 {
1440 free (response->data_iov);
1441 }
1442
1290 while (NULL != response->first_header) 1443 while (NULL != response->first_header)
1291 { 1444 {
1292 pos = response->first_header; 1445 pos = response->first_header;