GNU libmicrohttpd  0.9.29
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
response.c
Go to the documentation of this file.
1 /*
2  This file is part of libmicrohttpd
3  (C) 2007, 2009, 2010 Daniel Pittman and Christian Grothoff
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Lesser General Public
7  License as published by the Free Software Foundation; either
8  version 2.1 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public
16  License along with this library; if not, write to the Free Software
17  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19 
27 #include "internal.h"
28 #include "response.h"
29 
30 
40 static int
41 add_response_entry (struct MHD_Response *response,
42  enum MHD_ValueKind kind,
43  const char *header,
44  const char *content)
45 {
46  struct MHD_HTTP_Header *hdr;
47 
48  if ( (NULL == response) ||
49  (NULL == header) ||
50  (NULL == content) ||
51  (0 == strlen (header)) ||
52  (0 == strlen (content)) ||
53  (NULL != strchr (header, '\t')) ||
54  (NULL != strchr (header, '\r')) ||
55  (NULL != strchr (header, '\n')) ||
56  (NULL != strchr (content, '\t')) ||
57  (NULL != strchr (content, '\r')) ||
58  (NULL != strchr (content, '\n')) )
59  return MHD_NO;
60  if (NULL == (hdr = malloc (sizeof (struct MHD_HTTP_Header))))
61  return MHD_NO;
62  if (NULL == (hdr->header = strdup (header)))
63  {
64  free (hdr);
65  return MHD_NO;
66  }
67  if (NULL == (hdr->value = strdup (content)))
68  {
69  free (hdr->header);
70  free (hdr);
71  return MHD_NO;
72  }
73  hdr->kind = kind;
74  hdr->next = response->first_header;
75  response->first_header = hdr;
76  return MHD_YES;
77 }
78 
79 
89 int
91  const char *header, const char *content)
92 {
93  return add_response_entry (response,
95  header,
96  content);
97 }
98 
99 
109 int
111  const char *footer, const char *content)
112 {
113  return add_response_entry (response,
115  footer,
116  content);
117 }
118 
119 
129 int
131  const char *header,
132  const char *content)
133 {
134  struct MHD_HTTP_Header *pos;
135  struct MHD_HTTP_Header *prev;
136 
137  if ( (NULL == header) || (NULL == content) )
138  return MHD_NO;
139  prev = NULL;
140  pos = response->first_header;
141  while (pos != NULL)
142  {
143  if ((0 == strcmp (header, pos->header)) &&
144  (0 == strcmp (content, pos->value)))
145  {
146  free (pos->header);
147  free (pos->value);
148  if (NULL == prev)
149  response->first_header = pos->next;
150  else
151  prev->next = pos->next;
152  free (pos);
153  return MHD_YES;
154  }
155  prev = pos;
156  pos = pos->next;
157  }
158  return MHD_NO;
159 }
160 
161 
172 int
174  MHD_KeyValueIterator iterator, void *iterator_cls)
175 {
176  struct MHD_HTTP_Header *pos;
177  int numHeaders = 0;
178 
179  for (pos = response->first_header; NULL != pos; pos = pos->next)
180  {
181  numHeaders++;
182  if ((NULL != iterator) &&
183  (MHD_YES != iterator (iterator_cls,
184  pos->kind, pos->header, pos->value)))
185  break;
186  }
187  return numHeaders;
188 }
189 
190 
199 const char *
201  const char *key)
202 {
203  struct MHD_HTTP_Header *pos;
204 
205  if (NULL == key)
206  return NULL;
207  for (pos = response->first_header; NULL != pos; pos = pos->next)
208  if (0 == strcmp (key, pos->header))
209  return pos->value;
210  return NULL;
211 }
212 
213 
230 struct MHD_Response *
232  size_t block_size,
234  void *crc_cls,
236 {
237  struct MHD_Response *response;
238 
239  if ((NULL == crc) || (0 == block_size))
240  return NULL;
241  if (NULL == (response = malloc (sizeof (struct MHD_Response) + block_size)))
242  return NULL;
243  memset (response, 0, sizeof (struct MHD_Response));
244  response->fd = MHD_INVALID_SOCKET;
245  response->data = (void *) &response[1];
246  response->data_buffer_size = block_size;
247  if (0 != pthread_mutex_init (&response->mutex, NULL))
248  {
249  free (response);
250  return NULL;
251  }
252  response->crc = crc;
253  response->crfc = crfc;
254  response->crc_cls = crc_cls;
255  response->reference_count = 1;
256  response->total_size = size;
257  return response;
258 }
259 
260 
271 static ssize_t
272 file_reader (void *cls, uint64_t pos, char *buf, size_t max)
273 {
274  struct MHD_Response *response = cls;
275  ssize_t n;
276 
277  (void) lseek (response->fd, pos + response->fd_off, SEEK_SET);
278  n = read (response->fd, buf, max);
279  if (0 == n)
281  if (n < 0)
283  return n;
284 }
285 
286 
293 static void
294 free_callback (void *cls)
295 {
296  struct MHD_Response *response = cls;
297 
298  (void) close (response->fd);
299  response->fd = MHD_INVALID_SOCKET;
300 }
301 
302 
319 struct MHD_Response *
321  int fd,
322  off_t offset)
323 {
324  struct MHD_Response *response;
325 
326  response = MHD_create_response_from_callback (size,
327  4 * 1024,
328  &file_reader,
329  NULL,
330  &free_callback);
331  if (NULL == response)
332  return NULL;
333  response->fd = fd;
334  response->fd_off = offset;
335  response->crc_cls = response;
336  return response;
337 }
338 
339 
349 struct MHD_Response *
351  int fd)
352 {
353  return MHD_create_response_from_fd_at_offset (size, fd, 0);
354 }
355 
356 
371 struct MHD_Response *
373  void *data, int must_free, int must_copy)
374 {
375  struct MHD_Response *response;
376  void *tmp;
377 
378  if ((NULL == data) && (size > 0))
379  return NULL;
380  if (NULL == (response = malloc (sizeof (struct MHD_Response))))
381  return NULL;
382  memset (response, 0, sizeof (struct MHD_Response));
383  response->fd = MHD_INVALID_SOCKET;
384  if (0 != pthread_mutex_init (&response->mutex, NULL))
385  {
386  free (response);
387  return NULL;
388  }
389  if ((must_copy) && (size > 0))
390  {
391  if (NULL == (tmp = malloc (size)))
392  {
393  pthread_mutex_destroy (&response->mutex);
394  free (response);
395  return NULL;
396  }
397  memcpy (tmp, data, size);
398  must_free = MHD_YES;
399  data = tmp;
400  }
401  response->crc = NULL;
402  response->crfc = must_free ? &free : NULL;
403  response->crc_cls = must_free ? data : NULL;
404  response->reference_count = 1;
405  response->total_size = size;
406  response->data = data;
407  response->data_size = size;
408  return response;
409 }
410 
411 
422 struct MHD_Response *
424  void *buffer,
425  enum MHD_ResponseMemoryMode mode)
426 {
427  return MHD_create_response_from_data (size,
428  buffer,
429  mode == MHD_RESPMEM_MUST_FREE,
430  mode == MHD_RESPMEM_MUST_COPY);
431 }
432 
433 
443 void
445 {
446  struct MHD_HTTP_Header *pos;
447 
448  if (NULL == response)
449  return;
450  pthread_mutex_lock (&response->mutex);
451  if (0 != --(response->reference_count))
452  {
453  pthread_mutex_unlock (&response->mutex);
454  return;
455  }
456  pthread_mutex_unlock (&response->mutex);
457  pthread_mutex_destroy (&response->mutex);
458  if (response->crfc != NULL)
459  response->crfc (response->crc_cls);
460  while (NULL != response->first_header)
461  {
462  pos = response->first_header;
463  response->first_header = pos->next;
464  free (pos->header);
465  free (pos->value);
466  free (pos);
467  }
468  free (response);
469 }
470 
471 
472 void
474 {
475  pthread_mutex_lock (&response->mutex);
476  (response->reference_count)++;
477  pthread_mutex_unlock (&response->mutex);
478 }
479 
480 
481 /* end of response.c */
int(* MHD_KeyValueIterator)(void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
Definition: microhttpd.h:1215
uint64_t total_size
Definition: internal.h:295
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_callback(uint64_t size, size_t block_size, MHD_ContentReaderCallback crc, void *crc_cls, MHD_ContentReaderFreeCallback crfc)
Definition: response.c:231
static void free_callback(void *cls)
Definition: response.c:294
off_t fd_off
Definition: internal.h:306
_MHD_EXTERN int MHD_add_response_header(struct MHD_Response *response, const char *header, const char *content)
Definition: response.c:90
#define NULL
Definition: reason_phrase.c:31
MHD_ContentReaderFreeCallback crfc
Definition: internal.h:284
pthread_mutex_t mutex
Definition: internal.h:290
void(* MHD_ContentReaderFreeCallback)(void *cls)
Definition: microhttpd.h:1281
static ssize_t file_reader(void *cls, uint64_t pos, char *buf, size_t max)
Definition: response.c:272
#define MHD_YES
Definition: microhttpd.h:134
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_fd_at_offset(size_t size, int fd, off_t offset)
Definition: response.c:320
size_t data_size
Definition: internal.h:311
enum MHD_ValueKind kind
Definition: internal.h:244
struct MHD_HTTP_Header * first_header
Definition: internal.h:260
char * value
Definition: internal.h:238
Methods for managing response objects.
size_t data_buffer_size
Definition: internal.h:316
#define MHD_INVALID_SOCKET
Definition: microhttpd.h:175
internal shared structures
_MHD_EXTERN int MHD_add_response_footer(struct MHD_Response *response, const char *footer, const char *content)
Definition: response.c:110
unsigned int reference_count
Definition: internal.h:322
_MHD_EXTERN void MHD_destroy_response(struct MHD_Response *response)
Definition: response.c:444
void MHD_increment_response_rc(struct MHD_Response *response)
Definition: response.c:473
ssize_t(* MHD_ContentReaderCallback)(void *cls, uint64_t pos, char *buf, size_t max)
Definition: microhttpd.h:1265
#define MHD_CONTENT_READER_END_OF_STREAM
Definition: microhttpd.h:160
MHD_ValueKind
Definition: microhttpd.h:872
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_fd(size_t size, int fd)
Definition: response.c:350
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_buffer(size_t size, void *buffer, enum MHD_ResponseMemoryMode mode)
Definition: response.c:423
static int add_response_entry(struct MHD_Response *response, enum MHD_ValueKind kind, const char *header, const char *content)
Definition: response.c:41
char * header
Definition: internal.h:233
struct MHD_HTTP_Header * next
Definition: internal.h:227
#define MHD_CONTENT_READER_END_WITH_ERROR
Definition: microhttpd.h:161
MHD_ContentReaderCallback crc
Definition: internal.h:278
void * crc_cls
Definition: internal.h:272
char * data
Definition: internal.h:266
_MHD_EXTERN int MHD_del_response_header(struct MHD_Response *response, const char *header, const char *content)
Definition: response.c:130
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_data(size_t size, void *data, int must_free, int must_copy)
Definition: response.c:372
#define MHD_NO
Definition: microhttpd.h:139
_MHD_EXTERN const char * MHD_get_response_header(struct MHD_Response *response, const char *key)
Definition: response.c:200
_MHD_EXTERN int MHD_get_response_headers(struct MHD_Response *response, MHD_KeyValueIterator iterator, void *iterator_cls)
Definition: response.c:173
MHD_ResponseMemoryMode
Definition: microhttpd.h:1727