GNU libmicrohttpd 0.9.5

response.c

Go to the documentation of this file.
00001 /*
00002      This file is part of libmicrohttpd
00003      (C) 2007, 2009, 2010 Daniel Pittman and Christian Grothoff
00004 
00005      This library is free software; you can redistribute it and/or
00006      modify it under the terms of the GNU Lesser General Public
00007      License as published by the Free Software Foundation; either
00008      version 2.1 of the License, or (at your option) any later version.
00009 
00010      This library is distributed in the hope that it will be useful,
00011      but WITHOUT ANY WARRANTY; without even the implied warranty of
00012      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013      Lesser General Public License for more details.
00014 
00015      You should have received a copy of the GNU Lesser General Public
00016      License along with this library; if not, write to the Free Software
00017      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00018 */
00019 
00027 #include "internal.h"
00028 #include "response.h"
00029 
00030 
00040 static int
00041 add_response_entry (struct MHD_Response *response,
00042                     enum MHD_ValueKind kind,
00043                     const char *header, 
00044                     const char *content)
00045 {
00046   struct MHD_HTTP_Header *hdr;
00047 
00048   if ((response == NULL) ||
00049       (header == NULL) ||
00050       (content == NULL) ||
00051       (strlen (header) == 0) ||
00052       (strlen (content) == 0) ||
00053       (NULL != strstr (header, "\t")) ||
00054       (NULL != strstr (header, "\r")) ||
00055       (NULL != strstr (header, "\n")) ||
00056       (NULL != strstr (content, "\t")) ||
00057       (NULL != strstr (content, "\r")) || (NULL != strstr (content, "\n")))
00058     return MHD_NO;
00059   hdr = malloc (sizeof (struct MHD_HTTP_Header));
00060   if (hdr == NULL)
00061     return MHD_NO;
00062   hdr->header = strdup (header);
00063   if (hdr->header == NULL)
00064     {
00065       free (hdr);
00066       return MHD_NO;
00067     }
00068   hdr->value = strdup (content);
00069   if (hdr->value == NULL)
00070     {
00071       free (hdr->header);
00072       free (hdr);
00073       return MHD_NO;
00074     }
00075   hdr->kind = kind;
00076   hdr->next = response->first_header;
00077   response->first_header = hdr;
00078   return MHD_YES;
00079 }
00080 
00081 
00090 int
00091 MHD_add_response_header (struct MHD_Response *response,
00092                          const char *header, const char *content)
00093 {
00094   return add_response_entry (response,
00095                              MHD_HEADER_KIND,
00096                              header,
00097                              content);
00098 }
00099 
00100 
00109 int
00110 MHD_add_response_footer (struct MHD_Response *response,
00111                          const char *footer, const char *content)
00112 {
00113   return add_response_entry (response,
00114                              MHD_FOOTER_KIND,
00115                              footer,
00116                              content);
00117 }
00118 
00119 
00128 int
00129 MHD_del_response_header (struct MHD_Response *response,
00130                          const char *header, const char *content)
00131 {
00132   struct MHD_HTTP_Header *pos;
00133   struct MHD_HTTP_Header *prev;
00134 
00135   if ((header == NULL) || (content == NULL))
00136     return MHD_NO;
00137   prev = NULL;
00138   pos = response->first_header;
00139   while (pos != NULL)
00140     {
00141       if ((0 == strcmp (header, pos->header)) &&
00142           (0 == strcmp (content, pos->value)))
00143         {
00144           free (pos->header);
00145           free (pos->value);
00146           if (prev == NULL)
00147             response->first_header = pos->next;
00148           else
00149             prev->next = pos->next;
00150           free (pos);
00151           return MHD_YES;
00152         }
00153       prev = pos;
00154       pos = pos->next;
00155     }
00156   return MHD_NO;
00157 }
00158 
00159 
00168 int
00169 MHD_get_response_headers (struct MHD_Response *response,
00170                           MHD_KeyValueIterator iterator, void *iterator_cls)
00171 {
00172   struct MHD_HTTP_Header *pos;
00173   int numHeaders = 0;
00174   pos = response->first_header;
00175   while (pos != NULL)
00176     {
00177       numHeaders++;
00178       if ((iterator != NULL) &&
00179           (MHD_YES != iterator (iterator_cls,
00180                                 pos->kind, pos->header, pos->value)))
00181         break;
00182       pos = pos->next;
00183     }
00184   return numHeaders;
00185 }
00186 
00187 
00194 const char *
00195 MHD_get_response_header (struct MHD_Response *response, const char *key)
00196 {
00197   struct MHD_HTTP_Header *pos;
00198 
00199   if (key == NULL)
00200     return NULL;
00201   pos = response->first_header;
00202   while (pos != NULL)
00203     {
00204       if (0 == strcmp (key, pos->header))
00205         return pos->value;
00206       pos = pos->next;
00207     }
00208   return NULL;
00209 }
00210 
00211 
00227 struct MHD_Response *
00228 MHD_create_response_from_callback (uint64_t size,
00229                                    size_t block_size,
00230                                    MHD_ContentReaderCallback crc,
00231                                    void *crc_cls,
00232                                    MHD_ContentReaderFreeCallback crfc)
00233 {
00234   struct MHD_Response *retVal;
00235 
00236   if ((crc == NULL) || (block_size == 0))
00237     return NULL;
00238   retVal = malloc (sizeof (struct MHD_Response) + block_size);
00239   if (retVal == NULL)
00240     return NULL;
00241   memset (retVal, 0, sizeof (struct MHD_Response));
00242   retVal->fd = -1;
00243   retVal->data = (void *) &retVal[1];
00244   retVal->data_buffer_size = block_size;
00245   if (pthread_mutex_init (&retVal->mutex, NULL) != 0)
00246     {
00247       free (retVal);
00248       return NULL;
00249     }
00250   retVal->crc = crc;
00251   retVal->crfc = crfc;
00252   retVal->crc_cls = crc_cls;
00253   retVal->reference_count = 1;
00254   retVal->total_size = size;
00255   return retVal;
00256 }
00257 
00258 
00269 static ssize_t
00270 file_reader (void *cls, uint64_t pos, char *buf, size_t max)
00271 {
00272   struct MHD_Response *response = cls;
00273 
00274   (void) lseek (response->fd, pos + response->fd_off, SEEK_SET);
00275   return read (response->fd, buf, max);
00276 }
00277 
00278 
00285 static void
00286 free_callback (void *cls)
00287 {
00288   struct MHD_Response *response = cls;
00289   (void) close (response->fd);
00290   response->fd = -1;
00291 }
00292 
00293 
00303 struct MHD_Response *MHD_create_response_from_fd_at_offset (size_t size,
00304                                                             int fd,
00305                                                             off_t offset)
00306 {
00307   struct MHD_Response *ret;
00308 
00309   ret = MHD_create_response_from_callback (size,
00310                                            4 * 1024,
00311                                            &file_reader,
00312                                            NULL,
00313                                            &free_callback);
00314   if (ret == NULL)
00315     return NULL;
00316   ret->fd = fd;
00317   ret->fd_off = offset;
00318   ret->crc_cls = ret;
00319   return ret;
00320 }
00321 
00322 
00323 
00324 
00333 struct MHD_Response *MHD_create_response_from_fd (size_t size,
00334                                                   int fd)
00335 {
00336   return MHD_create_response_from_fd_at_offset (size, fd, 0);
00337 }
00338 
00339 
00353 struct MHD_Response *
00354 MHD_create_response_from_data (size_t size,
00355                                void *data, int must_free, int must_copy)
00356 {
00357   struct MHD_Response *retVal;
00358   void *tmp;
00359 
00360   if ((data == NULL) && (size > 0))
00361     return NULL;
00362   retVal = malloc (sizeof (struct MHD_Response));
00363   if (retVal == NULL)
00364     return NULL;
00365   memset (retVal, 0, sizeof (struct MHD_Response));
00366   retVal->fd = -1;
00367   if (pthread_mutex_init (&retVal->mutex, NULL) != 0)
00368     {
00369       free (retVal);
00370       return NULL;
00371     }
00372   if ((must_copy) && (size > 0))
00373     {
00374       tmp = malloc (size);
00375       if (tmp == NULL)
00376         {
00377           pthread_mutex_destroy (&retVal->mutex);
00378           free (retVal);
00379           return NULL;
00380         }
00381       memcpy (tmp, data, size);
00382       must_free = MHD_YES;
00383       data = tmp;
00384     }
00385   retVal->crc = NULL;
00386   retVal->crfc = must_free ? &free : NULL;
00387   retVal->crc_cls = must_free ? data : NULL;
00388   retVal->reference_count = 1;
00389   retVal->total_size = size;
00390   retVal->data = data;
00391   retVal->data_size = size;
00392   return retVal;
00393 }
00394 
00395 
00405 struct MHD_Response *
00406 MHD_create_response_from_buffer (size_t size,
00407                                  void *buffer,
00408                                  enum MHD_ResponseMemoryMode mode)
00409 {
00410   return MHD_create_response_from_data (size,
00411                                         buffer,
00412                                         mode == MHD_RESPMEM_MUST_FREE,
00413                                         mode == MHD_RESPMEM_MUST_COPY);
00414 }
00415 
00416 
00423 void
00424 MHD_destroy_response (struct MHD_Response *response)
00425 {
00426   struct MHD_HTTP_Header *pos;
00427 
00428   if (response == NULL)
00429     return;
00430   pthread_mutex_lock (&response->mutex);
00431   if (0 != --(response->reference_count))
00432     {
00433       pthread_mutex_unlock (&response->mutex);
00434       return;
00435     }
00436   pthread_mutex_unlock (&response->mutex);
00437   pthread_mutex_destroy (&response->mutex);
00438   if (response->crfc != NULL)
00439     response->crfc (response->crc_cls);
00440   while (response->first_header != NULL)
00441     {
00442       pos = response->first_header;
00443       response->first_header = pos->next;
00444       free (pos->header);
00445       free (pos->value);
00446       free (pos);
00447     }
00448   free (response);
00449 }
00450 
00451 
00452 void
00453 MHD_increment_response_rc (struct MHD_Response *response)
00454 {
00455   pthread_mutex_lock (&response->mutex);
00456   (response->reference_count)++;
00457   pthread_mutex_unlock (&response->mutex);
00458 }
00459 
00460 
00461 /* end of response.c */