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 ( (NULL == response) ||
00049        (NULL == header) ||
00050        (NULL == content) ||
00051        (0 == strlen (header)) ||
00052        (0 == strlen (content)) ||
00053        (NULL != strchr (header, '\t')) ||
00054        (NULL != strchr (header, '\r')) ||
00055        (NULL != strchr (header, '\n')) ||
00056        (NULL != strchr (content, '\t')) ||
00057        (NULL != strchr (content, '\r')) || 
00058        (NULL != strchr (content, '\n')) )
00059     return MHD_NO;
00060   if (NULL == (hdr = malloc (sizeof (struct MHD_HTTP_Header))))
00061     return MHD_NO;
00062   if (NULL == (hdr->header = strdup (header)))
00063     {
00064       free (hdr);
00065       return MHD_NO;
00066     }
00067   if (NULL == (hdr->value = strdup (content)))
00068     {
00069       free (hdr->header);
00070       free (hdr);
00071       return MHD_NO;
00072     }
00073   hdr->kind = kind;
00074   hdr->next = response->first_header;
00075   response->first_header = hdr;
00076   return MHD_YES;
00077 }
00078 
00079 
00088 int
00089 MHD_add_response_header (struct MHD_Response *response,
00090                          const char *header, const char *content)
00091 {
00092   return add_response_entry (response,
00093                              MHD_HEADER_KIND,
00094                              header,
00095                              content);
00096 }
00097 
00098 
00107 int
00108 MHD_add_response_footer (struct MHD_Response *response,
00109                          const char *footer, const char *content)
00110 {
00111   return add_response_entry (response,
00112                              MHD_FOOTER_KIND,
00113                              footer,
00114                              content);
00115 }
00116 
00117 
00126 int
00127 MHD_del_response_header (struct MHD_Response *response,
00128                          const char *header, const char *content)
00129 {
00130   struct MHD_HTTP_Header *pos;
00131   struct MHD_HTTP_Header *prev;
00132 
00133   if ( (NULL == header) || (NULL == content) )
00134     return MHD_NO;
00135   prev = NULL;
00136   pos = response->first_header;
00137   while (pos != NULL)
00138     {
00139       if ((0 == strcmp (header, pos->header)) &&
00140           (0 == strcmp (content, pos->value)))
00141         {
00142           free (pos->header);
00143           free (pos->value);
00144           if (NULL == prev)
00145             response->first_header = pos->next;
00146           else
00147             prev->next = pos->next;
00148           free (pos);
00149           return MHD_YES;
00150         }
00151       prev = pos;
00152       pos = pos->next;
00153     }
00154   return MHD_NO;
00155 }
00156 
00157 
00166 int
00167 MHD_get_response_headers (struct MHD_Response *response,
00168                           MHD_KeyValueIterator iterator, void *iterator_cls)
00169 {
00170   struct MHD_HTTP_Header *pos;
00171   int numHeaders = 0;
00172 
00173   for (pos = response->first_header; NULL != pos; pos = pos->next)
00174     {
00175       numHeaders++;
00176       if ((NULL != iterator) &&
00177           (MHD_YES != iterator (iterator_cls,
00178                                 pos->kind, pos->header, pos->value)))
00179         break;
00180     }
00181   return numHeaders;
00182 }
00183 
00184 
00191 const char *
00192 MHD_get_response_header (struct MHD_Response *response, const char *key)
00193 {
00194   struct MHD_HTTP_Header *pos;
00195 
00196   if (NULL == key)
00197     return NULL;
00198   for (pos = response->first_header; NULL != pos; pos = pos->next)
00199     if (0 == strcmp (key, pos->header))
00200       return pos->value;
00201   return NULL;
00202 }
00203 
00204 
00220 struct MHD_Response *
00221 MHD_create_response_from_callback (uint64_t size,
00222                                    size_t block_size,
00223                                    MHD_ContentReaderCallback crc,
00224                                    void *crc_cls,
00225                                    MHD_ContentReaderFreeCallback crfc)
00226 {
00227   struct MHD_Response *response;
00228 
00229   if ((NULL == crc) || (0 == block_size))
00230     return NULL;
00231   if (NULL == (response = malloc (sizeof (struct MHD_Response) + block_size)))
00232     return NULL;
00233   memset (response, 0, sizeof (struct MHD_Response));
00234   response->fd = -1;
00235   response->data = (void *) &response[1];
00236   response->data_buffer_size = block_size;
00237   if (0 != pthread_mutex_init (&response->mutex, NULL))
00238     {
00239       free (response);
00240       return NULL;
00241     }
00242   response->crc = crc;
00243   response->crfc = crfc;
00244   response->crc_cls = crc_cls;
00245   response->reference_count = 1;
00246   response->total_size = size;
00247   return response;
00248 }
00249 
00250 
00261 static ssize_t
00262 file_reader (void *cls, uint64_t pos, char *buf, size_t max)
00263 {
00264   struct MHD_Response *response = cls;
00265   ssize_t n;
00266 
00267   (void) lseek (response->fd, pos + response->fd_off, SEEK_SET);
00268   n = read (response->fd, buf, max);
00269   if (0 == n) 
00270     return MHD_CONTENT_READER_END_OF_STREAM;
00271   if (n < 0) 
00272     return MHD_CONTENT_READER_END_WITH_ERROR;
00273   return n;
00274 }
00275 
00276 
00283 static void
00284 free_callback (void *cls)
00285 {
00286   struct MHD_Response *response = cls;
00287 
00288   (void) close (response->fd);
00289   response->fd = -1;
00290 }
00291 
00292 
00302 struct MHD_Response *MHD_create_response_from_fd_at_offset (size_t size,
00303                                                             int fd,
00304                                                             off_t offset)
00305 {
00306   struct MHD_Response *response;
00307 
00308   response = MHD_create_response_from_callback (size,
00309                                                 4 * 1024,
00310                                                 &file_reader,
00311                                                 NULL,
00312                                                 &free_callback);
00313   if (NULL == response)
00314     return NULL;
00315   response->fd = fd;
00316   response->fd_off = offset;
00317   response->crc_cls = response;
00318   return response;
00319 }
00320 
00321 
00330 struct MHD_Response *MHD_create_response_from_fd (size_t size,
00331                                                   int fd)
00332 {
00333   return MHD_create_response_from_fd_at_offset (size, fd, 0);
00334 }
00335 
00336 
00350 struct MHD_Response *
00351 MHD_create_response_from_data (size_t size,
00352                                void *data, int must_free, int must_copy)
00353 {
00354   struct MHD_Response *response;
00355   void *tmp;
00356 
00357   if ((NULL == data) && (size > 0))
00358     return NULL;
00359   if (NULL == (response = malloc (sizeof (struct MHD_Response))))
00360     return NULL;
00361   memset (response, 0, sizeof (struct MHD_Response));
00362   response->fd = -1;
00363   if (0 != pthread_mutex_init (&response->mutex, NULL))
00364     {
00365       free (response);
00366       return NULL;
00367     }
00368   if ((must_copy) && (size > 0))
00369     {
00370       if (NULL == (tmp = malloc (size)))
00371         {
00372           pthread_mutex_destroy (&response->mutex);
00373           free (response);
00374           return NULL;
00375         }
00376       memcpy (tmp, data, size);
00377       must_free = MHD_YES;
00378       data = tmp;
00379     }
00380   response->crc = NULL;
00381   response->crfc = must_free ? &free : NULL;
00382   response->crc_cls = must_free ? data : NULL;
00383   response->reference_count = 1;
00384   response->total_size = size;
00385   response->data = data;
00386   response->data_size = size;
00387   return response;
00388 }
00389 
00390 
00400 struct MHD_Response *
00401 MHD_create_response_from_buffer (size_t size,
00402                                  void *buffer,
00403                                  enum MHD_ResponseMemoryMode mode)
00404 {
00405   return MHD_create_response_from_data (size,
00406                                         buffer,
00407                                         mode == MHD_RESPMEM_MUST_FREE,
00408                                         mode == MHD_RESPMEM_MUST_COPY);
00409 }
00410 
00411 
00418 void
00419 MHD_destroy_response (struct MHD_Response *response)
00420 {
00421   struct MHD_HTTP_Header *pos;
00422 
00423   if (NULL == response)
00424     return;
00425   pthread_mutex_lock (&response->mutex);
00426   if (0 != --(response->reference_count))
00427     {
00428       pthread_mutex_unlock (&response->mutex);
00429       return;
00430     }
00431   pthread_mutex_unlock (&response->mutex);
00432   pthread_mutex_destroy (&response->mutex);
00433   if (response->crfc != NULL)
00434     response->crfc (response->crc_cls);
00435   while (NULL != response->first_header)
00436     {
00437       pos = response->first_header;
00438       response->first_header = pos->next;
00439       free (pos->header);
00440       free (pos->value);
00441       free (pos);
00442     }
00443   free (response);
00444 }
00445 
00446 
00447 void
00448 MHD_increment_response_rc (struct MHD_Response *response)
00449 {
00450   pthread_mutex_lock (&response->mutex);
00451   (response->reference_count)++;
00452   pthread_mutex_unlock (&response->mutex);
00453 }
00454 
00455 
00456 /* end of response.c */

Generated on 28 Jan 2013 for GNU libmicrohttpd by  doxygen 1.6.1