aboutsummaryrefslogtreecommitdiff
path: root/src/daemon/response.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2007-06-12 06:48:11 +0000
committerChristian Grothoff <christian@grothoff.org>2007-06-12 06:48:11 +0000
commit641853be5073b9b2dc5c60fa414271ccbec0c0aa (patch)
tree7da8c1810f45ea5cd07923808ed158662c1aadc6 /src/daemon/response.c
parentc09343fb06be96edac01bbe48d8a269d898c91fd (diff)
downloadlibmicrohttpd-641853be5073b9b2dc5c60fa414271ccbec0c0aa.tar.gz
libmicrohttpd-641853be5073b9b2dc5c60fa414271ccbec0c0aa.zip
cleaning up the code big time -- incomplete
Diffstat (limited to 'src/daemon/response.c')
-rw-r--r--src/daemon/response.c333
1 files changed, 333 insertions, 0 deletions
diff --git a/src/daemon/response.c b/src/daemon/response.c
new file mode 100644
index 00000000..a26b003b
--- /dev/null
+++ b/src/daemon/response.c
@@ -0,0 +1,333 @@
1/*
2 This file is part of libmicrohttpd
3 (C) 2007 Daniel Pittman
4
5 libmicrohttpd is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 libmicrohttpd is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with libmicrohttpd; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file response.c
23 * @brief Methods for managing response objects
24 * @author Daniel Pittman
25 * @author Christian Grothoff
26 * @version 0.1.0
27 */
28
29
30#include <stdio.h>
31#include <stdlib.h>
32#include <netdb.h>
33#include <string.h>
34#include <unistd.h>
35#include <stdarg>
36#include <fcntl.h>
37#include <pthread.h>
38#include <netinet/in.h>
39
40#include "microhttpd.h"
41#include "response.h"
42#include "internal.h"
43#include "config.h"
44
45
46/**
47 * Representation of a response.
48 */
49struct MHD_Response {
50
51 /**
52 * Headers to send for the response. Initially
53 * the linked list is created in inverse order;
54 * the order should be inverted before sending!
55 */
56 struct MHD_HTTP_Header * first_header;
57
58 /**
59 * Buffer pointing to data that we are supposed
60 * to send as a response.
61 */
62 void * data;
63
64 /**
65 * Closure to give to the content reader
66 * free callback.
67 */
68 void * crc_cls;
69
70 /**
71 * How do we get more data? NULL if we are
72 * given all of the data up front.
73 */
74 MHD_ContentReaderCallback crc;
75
76 /**
77 * NULL if data must not be freed, otherwise
78 * either user-specified callback or "&free".
79 */
80 MHD_ContentReaderFreeCallback crfc;
81
82 /**
83 * Mutex to synchronize access to data/size and
84 * reference counts.
85 */
86 pthread_mutex_t mutex;
87
88 /**
89 * Reference count for this response. Free
90 * once the counter hits zero.
91 */
92 unsigned int reference_count;
93
94 /**
95 * Set to -1 if size is not known.
96 */
97 size_t total_size;
98
99 /**
100 * Size of data.
101 */
102 size_t data_size;
103
104 /**
105 * At what offset in the stream is the
106 * beginning of data located?
107 */
108 size_t data_start;
109
110};
111
112
113
114/**
115 * Add a header line to the response.
116 *
117 * @return MHD_NO on error (i.e. invalid header or content format).
118 */
119int
120MHD_add_response_header(struct MHD_Response * response,
121 const char * header,
122 const char * content) {
123 struct MHD_HTTP_Header * hdr;
124
125 if ( (response == NULL) ||
126 (header == NULL) ||
127 (content == NULL) ||
128 (strlen(header) == 0) ||
129 (strlen(content) == 0) ||
130 (NULL != strstr(header, "\t")) ||
131 (NULL != strstr(header, "\r")) ||
132 (NULL != strstr(header, "\n")) ||
133 (NULL != strstr(content, "\t")) ||
134 (NULL != strstr(content, "\r")) ||
135 (NULL != strstr(content, "\n")) )
136 return MHD_NO;
137 hdr = malloc(sizeof(MHD_HTTP_Header));
138 hdr->header = STRDUP(header);
139 hdr->value = STRDUP(content);
140 hdr->kind = MHD_HEADER_KIND;
141 hdr->next = response->first_header;
142 response->first_header = hdr;
143 return MHD_YES;
144}
145
146/**
147 * Delete a header line from the response.
148 *
149 * @return MHD_NO on error (no such header known)
150 */
151int
152MHD_del_response_header(struct MHD_Response * response,
153 const char * header,
154 const char * content) {
155 struct MHD_HTTP_Header * pos;
156 struct MHD_HTTP_Header * prev;
157
158 if ( (header == NULL) ||
159 (content == NULL) )
160 return MHD_NO;
161 prev = NULL;
162 pos = response->first_header;
163 while (pos != NULL) {
164 if ( (0 == strcmp(header, pos->header)) &&
165 (0 == strcmp(content, pos->value)) ) {
166 free(pos->header);
167 free(pos->value);
168 if (prev == NULL)
169 response->first_header = pos->next;
170 else
171 prev->next = pos->next;
172 free(pos);
173 return MHD_YES;
174 }
175 prev = pos;
176 pos = pos->next;
177 }
178 return MHD_NO;
179}
180
181/**
182 * Get all of the headers added to a response.
183 *
184 * @param iterator callback to call on each header;
185 * maybe NULL (then just count headers)
186 * @param iterator_cls extra argument to iterator
187 * @return number of entries iterated over
188 */
189int
190MHD_get_response_headers(struct MHD_Response * response,
191 MHD_KeyValueIterator * iterator,
192 void * iterator_cls) {
193 struct MHD_HTTP_Header * pos;
194 int numHeaders = 0;
195 pos = response->first_header;
196 while (pos != NULL) {
197 numHeaders++;
198 if ( (iterator != NULL) &&
199 (MHD_YES != iterator(iterator_cls,
200 pos->kind,
201 pos->header,
202 pos->value)) )
203 break;
204 pos = pos->next;
205 }
206 return numHeaders;
207}
208
209
210/**
211 * Create a response object. The response object can be extended with
212 * header information and then be used any number of times.
213 *
214 * @param size size of the data portion of the response, -1 for unknown
215 * @param crc callback to use to obtain response data
216 * @param crc_cls extra argument to crc
217 * @param crfc callback to call to free crc_cls resources
218 * @return NULL on error (i.e. invalid arguments, out of memory)
219 */
220struct MHD_Response *
221MHD_create_response_from_callback(size_t size,
222 MHD_ContentReaderCallback crc,
223 void * crc_cls,
224 MHD_ContentReaderFreeCallback crfc) {
225 struct MHD_Response * retVal;
226
227 if (crc == NULL)
228 return NULL;
229 retVal = malloc(sizeof(struct MHD_Response));
230 memset(retVal,
231 0,
232 sizeof(struct MHD_Response));
233 if (pthread_mutex_init(&retVal->mutex, NULL) != 0) {
234 free(retVal);
235 return NULL;
236 }
237 retVal->crc = crc;
238 retVal->crfc = crfc;
239 retVal->crc_cls = crc_cls;
240 retVal->reference_count = 1;
241 retVal->total_size = size;
242 return retVal;
243}
244
245/**
246 * Create a response object. The response object can be extended with
247 * header information and then be used any number of times.
248 *
249 * @param size size of the data portion of the response
250 * @param data the data itself
251 * @param must_free libmicrohttpd should free data when done
252 * @param must_copy libmicrohttpd must make a copy of data
253 * right away, the data maybe released anytime after
254 * this call returns
255 * @return NULL on error (i.e. invalid arguments, out of memory)
256 */
257struct MHD_Response *
258MHD_create_response_from_data(size_t size,
259 void * data,
260 int must_free,
261 int must_copy) {
262 struct MHD_Response * retVal;
263 void * tmp;
264
265 if ( (data == NULL) &&
266 (size > 0) )
267 return NULL;
268 retVal = malloc(sizeof(struct MHD_Response));
269 memset(retVal,
270 0,
271 sizeof(struct MHD_Response));
272 if (pthread_mutex_init(&retVal->mutex, NULL) != 0) {
273 free(retVal);
274 return NULL;
275 }
276 if ( (must_copy) &&
277 (size > 0) ) {
278 tmp = malloc(size);
279 memcpy(tmp,
280 data,
281 size);
282 must_free = 1;
283 data = tmp;
284 }
285 retVal->crc = NULL;
286 retVal->crfc = must_free ? &free : NULL;
287 retVal->crc_cls = must_free ? data : NULL;
288 retVal->reference_count = 1;
289 retVal->total_size = size;
290 retVal->data = data;
291 retVal->data_size = size;
292 return retVal;
293}
294
295/**
296 * Destroy a response object and associated resources. Note that
297 * libmicrohttpd may keep some of the resources around if the response
298 * is still in the queue for some clients, so the memory may not
299 * necessarily be freed immediatley.
300 */
301void
302MHD_destroy_response(struct MHD_Response * response) {
303 struct MHD_HTTP_Header * pos;
304
305 if (response == NULL)
306 return;
307 pthread_mutex_lock(&response->mutex);
308 if (0 != --response->reference_count) {
309 pthread_mutex_unlock(&response->mutex);
310 return;
311 }
312 pthread_mutex_unlock(&response->mutex);
313 pthread_mutex_destroy(&response->mutex);
314 while (response->first_header != NULL) {
315 pos = response->first_header;
316 response->first_header = pos->next;
317 free(pos->header);
318 free(pos->value);
319 free(pos);
320 }
321 free(response);
322}
323
324
325void
326MHD_increment_response_rc(struct MHD_Response * response) {
327 pthread_mutex_lock(&response->mutex);
328 response->reference_count++;
329 pthread_mutex_unlock(&response->mutex);
330}
331
332
333/* end of response.c */