aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/daemon/daemon.c28
-rw-r--r--src/daemon/internal.h171
-rw-r--r--src/daemon/response.c88
-rw-r--r--src/daemon/session.c303
-rw-r--r--src/daemon/session.h97
5 files changed, 326 insertions, 361 deletions
diff --git a/src/daemon/daemon.c b/src/daemon/daemon.c
index e52ac940..0ebf21d0 100644
--- a/src/daemon/daemon.c
+++ b/src/daemon/daemon.c
@@ -26,16 +26,6 @@
26 * @version 0.1.0 26 * @version 0.1.0
27 */ 27 */
28 28
29#include <stdio.h>
30#include <stdlib.h>
31#include <netdb.h>
32#include <string.h>
33#include <unistd.h>
34#include <stdarg>
35#include <fcntl.h>
36#include <pthread.h>
37#include <netinet/in.h>
38
39#include "microhttpd.h" 29#include "microhttpd.h"
40#include "internal.h" 30#include "internal.h"
41#include "response.h" 31#include "response.h"
@@ -120,10 +110,10 @@ MHD_unregister_handler(struct MHD_Daemon * daemon,
120 pos = daemon->handlers; 110 pos = daemon->handlers;
121 prev = NULL; 111 prev = NULL;
122 while (pos != NULL) { 112 while (pos != NULL) {
123 if ( (dh == ah->dh) && 113 if ( (dh == pos->dh) &&
124 (dh_cls == ah->dh_cls) && 114 (dh_cls == pos->dh_cls) &&
125 (0 == strcmp(uri_prefix, 115 (0 == strcmp(uri_prefix,
126 ah->uri_prefix)) ) { 116 pos->uri_prefix)) ) {
127 if (prev == NULL) 117 if (prev == NULL)
128 daemon->handlers = pos->next; 118 daemon->handlers = pos->next;
129 else 119 else
@@ -160,10 +150,10 @@ MHD_get_fdset(struct MHD_Daemon * daemon,
160 ( (daemon->options & MHD_USE_THREAD_PER_CONNECTION) != 0) ) 150 ( (daemon->options & MHD_USE_THREAD_PER_CONNECTION) != 0) )
161 return MHD_NO; 151 return MHD_NO;
162 FD_SET(daemon->socket_fd, 152 FD_SET(daemon->socket_fd,
163 &daemon->read_fd_set); 153 read_fd_set);
164 if ( (*max_fd) < daemon->socket_fd) 154 if ( (*max_fd) < daemon->socket_fd)
165 *max_fd = daemon->socket_fd; 155 *max_fd = daemon->socket_fd;
166 pos = daemon->session; 156 pos = daemon->connections;
167 while (pos != NULL) { 157 while (pos != NULL) {
168 if (MHD_YES != MHD_session_get_fdset(pos, 158 if (MHD_YES != MHD_session_get_fdset(pos,
169 read_fd_set, 159 read_fd_set,
@@ -249,7 +239,7 @@ MHD_accept_connection(struct MHD_Daemon * daemon) {
249 strerror(errno)); 239 strerror(errno));
250 return MHD_NO; 240 return MHD_NO;
251 } 241 }
252 if (MHD_NO == daemon->apc(mhd->apc_cls, 242 if (MHD_NO == daemon->apc(daemon->apc_cls,
253 &addr, 243 &addr,
254 addrlen)) { 244 addrlen)) {
255 close(s); 245 close(s);
@@ -485,16 +475,14 @@ MHD_start_daemon(unsigned int options,
485 retVal->port = port; 475 retVal->port = port;
486 retVal->apc = apc; 476 retVal->apc = apc;
487 retVal->apc_cls = apc_cls; 477 retVal->apc_cls = apc_cls;
488 retVal->dh = dh;
489 retVal->dh_cls = dh_cls;
490 retVal->socket_fd = socket_fd; 478 retVal->socket_fd = socket_fd;
491 retVal->default_handler.dh = dh; 479 retVal->default_handler.dh = dh;
492 retVal->default_handler.dh_cls = dh_cls; 480 retVal->default_handler.dh_cls = dh_cls;
493 retVal->default_henader.uri_prefix = ""; 481 retVal->default_handler.uri_prefix = "";
494 retVal->default_handler.next = NULL; 482 retVal->default_handler.next = NULL;
495 if ( ( (0 != (options & MHD_USE_THREAD_PER_CONNECTION)) || 483 if ( ( (0 != (options & MHD_USE_THREAD_PER_CONNECTION)) ||
496 (0 != (options & MHD_USE_SELECT_INTERNALLY)) ) && 484 (0 != (options & MHD_USE_SELECT_INTERNALLY)) ) &&
497 (0 != pthread_create(&daemon->pid, 485 (0 != pthread_create(&retVal->pid,
498 NULL, 486 NULL,
499 &MHD_select_thread, 487 &MHD_select_thread,
500 daemon)) ) { 488 daemon)) ) {
diff --git a/src/daemon/internal.h b/src/daemon/internal.h
index 2f7fd194..61653d8e 100644
--- a/src/daemon/internal.h
+++ b/src/daemon/internal.h
@@ -35,7 +35,8 @@
35#include <netdb.h> 35#include <netdb.h>
36#include <string.h> 36#include <string.h>
37#include <unistd.h> 37#include <unistd.h>
38#include <stdarg> 38#include <stdarg.h>
39#include <errno.h>
39#include <fcntl.h> 40#include <fcntl.h>
40#include <pthread.h> 41#include <pthread.h>
41#include <netinet/in.h> 42#include <netinet/in.h>
@@ -45,7 +46,7 @@
45 46
46#define MHD_MAX_BUF_SIZE 2048 47#define MHD_MAX_BUF_SIZE 2048
47 48
48 49#define MAX(a,b) ((a)<(b)) ? (b) : (a)
49 50
50/** 51/**
51 * Header or cookie in HTTP request or response. 52 * Header or cookie in HTTP request or response.
@@ -72,6 +73,172 @@ struct MHD_Access_Handler {
72}; 73};
73 74
74 75
76/**
77 * Representation of a response.
78 */
79struct MHD_Response {
80
81 /**
82 * Headers to send for the response. Initially
83 * the linked list is created in inverse order;
84 * the order should be inverted before sending!
85 */
86 struct MHD_HTTP_Header * first_header;
87
88 /**
89 * Buffer pointing to data that we are supposed
90 * to send as a response.
91 */
92 char * data;
93
94 /**
95 * Closure to give to the content reader
96 * free callback.
97 */
98 void * crc_cls;
99
100 /**
101 * How do we get more data? NULL if we are
102 * given all of the data up front.
103 */
104 MHD_ContentReaderCallback crc;
105
106 /**
107 * NULL if data must not be freed, otherwise
108 * either user-specified callback or "&free".
109 */
110 MHD_ContentReaderFreeCallback crfc;
111
112 /**
113 * Mutex to synchronize access to data/size and
114 * reference counts.
115 */
116 pthread_mutex_t mutex;
117
118 /**
119 * Reference count for this response. Free
120 * once the counter hits zero.
121 */
122 unsigned int reference_count;
123
124 /**
125 * Set to -1 if size is not known.
126 */
127 size_t total_size;
128
129 /**
130 * Size of data.
131 */
132 size_t data_size;
133
134 /**
135 * At what offset in the stream is the
136 * beginning of data located?
137 */
138 size_t data_start;
139
140};
141
142
143
144struct MHD_Session {
145 struct MHD_Session * next;
146
147 struct MHD_Daemon * daemon;
148
149 struct MHD_HTTP_Header * headers_received;
150
151 struct MHD_Response * response;
152
153 char * method;
154
155 char * url;
156
157 /**
158 * Buffer for reading requests.
159 */
160 char * read_buffer;
161
162 /**
163 * Buffer for writing response.
164 */
165 char * write_buffer;
166
167 /**
168 * Foreign address (of length addr_len).
169 */
170 struct sockaddr_in * addr;
171
172 /**
173 * Thread for this session (if we are using
174 * one thread per connection).
175 */
176 pthread_t pid;
177
178 size_t read_buffer_size;
179
180 size_t readLoc;
181
182 size_t write_buffer_size;
183
184 size_t writeLoc;
185
186 /**
187 * Current write position in the actual response
188 * (excluding headers, content only; should be 0
189 * while sending headers).
190 */
191 size_t messagePos;
192
193 /**
194 * Remaining (!) number of bytes in the upload.
195 * Set to -1 for unknown (connection will close
196 * to indicate end of upload).
197 */
198 size_t uploadSize;
199
200 /**
201 * Length of the foreign address.
202 */
203 socklen_t addr_len;
204
205 /**
206 * Socket for this connection. Set to -1 if
207 * this connection has died (daemon should clean
208 * up in that case).
209 */
210 int socket_fd;
211
212 /**
213 * Have we finished receiving all of the headers yet?
214 * Set to 1 once we are done processing all of the
215 * headers. Note that due to pipelining, it is
216 * possible that the NEXT request is already
217 * (partially) waiting in the read buffer.
218 */
219 int headersReceived;
220
221 /**
222 * Have we finished receiving the data from a
223 * potential file-upload?
224 */
225 int bodyReceived;
226
227 /**
228 * Have we finished sending all of the headers yet?
229 */
230 int headersSent;
231
232 /**
233 * HTTP response code. Only valid if response object
234 * is already set.
235 */
236 unsigned int responseCode;
237
238};
239
240
241
75struct MHD_Daemon { 242struct MHD_Daemon {
76 243
77 struct MHD_Access_Handler * handlers; 244 struct MHD_Access_Handler * handlers;
diff --git a/src/daemon/response.c b/src/daemon/response.c
index a26b003b..1584dbfd 100644
--- a/src/daemon/response.c
+++ b/src/daemon/response.c
@@ -26,91 +26,11 @@
26 * @version 0.1.0 26 * @version 0.1.0
27 */ 27 */
28 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" 29#include "microhttpd.h"
41#include "response.h" 30#include "response.h"
42#include "internal.h" 31#include "internal.h"
43#include "config.h" 32#include "config.h"
44 33
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/** 34/**
115 * Add a header line to the response. 35 * Add a header line to the response.
116 * 36 *
@@ -134,9 +54,9 @@ MHD_add_response_header(struct MHD_Response * response,
134 (NULL != strstr(content, "\r")) || 54 (NULL != strstr(content, "\r")) ||
135 (NULL != strstr(content, "\n")) ) 55 (NULL != strstr(content, "\n")) )
136 return MHD_NO; 56 return MHD_NO;
137 hdr = malloc(sizeof(MHD_HTTP_Header)); 57 hdr = malloc(sizeof(struct MHD_HTTP_Header));
138 hdr->header = STRDUP(header); 58 hdr->header = strdup(header);
139 hdr->value = STRDUP(content); 59 hdr->value = strdup(content);
140 hdr->kind = MHD_HEADER_KIND; 60 hdr->kind = MHD_HEADER_KIND;
141 hdr->next = response->first_header; 61 hdr->next = response->first_header;
142 response->first_header = hdr; 62 response->first_header = hdr;
@@ -188,7 +108,7 @@ MHD_del_response_header(struct MHD_Response * response,
188 */ 108 */
189int 109int
190MHD_get_response_headers(struct MHD_Response * response, 110MHD_get_response_headers(struct MHD_Response * response,
191 MHD_KeyValueIterator * iterator, 111 MHD_KeyValueIterator iterator,
192 void * iterator_cls) { 112 void * iterator_cls) {
193 struct MHD_HTTP_Header * pos; 113 struct MHD_HTTP_Header * pos;
194 int numHeaders = 0; 114 int numHeaders = 0;
diff --git a/src/daemon/session.c b/src/daemon/session.c
index c50af0ba..fa3864ca 100644
--- a/src/daemon/session.c
+++ b/src/daemon/session.c
@@ -26,17 +26,6 @@
26 * @version 0.1.0 26 * @version 0.1.0
27 */ 27 */
28 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" 29#include "microhttpd.h"
41#include "session.h" 30#include "session.h"
42#include "response.h" 31#include "response.h"
@@ -55,7 +44,7 @@
55int 44int
56MHD_get_session_values(struct MHD_Session * session, 45MHD_get_session_values(struct MHD_Session * session,
57 enum MHD_ValueKind kind, 46 enum MHD_ValueKind kind,
58 MHD_KeyValueIterator * iterator, 47 MHD_KeyValueIterator iterator,
59 void * iterator_cls) { 48 void * iterator_cls) {
60 int ret; 49 int ret;
61 struct MHD_HTTP_Header * pos; 50 struct MHD_HTTP_Header * pos;
@@ -95,7 +84,6 @@ MHD_lookup_session_value(struct MHD_Session * session,
95 84
96 if (session == NULL) 85 if (session == NULL)
97 return NULL; 86 return NULL;
98 ret = 0;
99 pos = session->headers_received; 87 pos = session->headers_received;
100 while (pos != NULL) { 88 while (pos != NULL) {
101 if ( (0 != (pos->kind & kind)) && 89 if ( (0 != (pos->kind & kind)) &&
@@ -145,7 +133,8 @@ MHD_session_get_fdset(struct MHD_Session * session,
145 int * max_fd) { 133 int * max_fd) {
146 /* FIXME: need to be VERY careful here 134 /* FIXME: need to be VERY careful here
147 determining when the socket is ready for 135 determining when the socket is ready for
148 reading/writing; plenty of cases to handle! */ 136 reading/writing; plenty of cases to handle!
137 (the current code is one big bug) */
149 FD_SET(session->socket_fd, read_fd_set); 138 FD_SET(session->socket_fd, read_fd_set);
150 FD_SET(session->socket_fd, write_fd_set); 139 FD_SET(session->socket_fd, write_fd_set);
151 if (session->socket_fd > *max_fd) 140 if (session->socket_fd > *max_fd)
@@ -165,6 +154,7 @@ MHD_session_get_fdset(struct MHD_Session * session,
165 */ 154 */
166static void 155static void
167MHD_parse_URL(struct MHD_Session * session) { 156MHD_parse_URL(struct MHD_Session * session) {
157#if 0
168 char * working; 158 char * working;
169 int pos,i; 159 int pos,i;
170 160
@@ -179,10 +169,10 @@ MHD_parse_URL(struct MHD_Session * session) {
179 pos = 0; 169 pos = 0;
180 170
181 session->documentName = session->headers[0]->value+pos; 171 session->documentName = session->headers[0]->value+pos;
172#endif
182} 173}
183 174
184 175
185
186/** 176/**
187 * This function is designed to parse the input buffer of a given session. 177 * This function is designed to parse the input buffer of a given session.
188 * 178 *
@@ -195,6 +185,7 @@ MHD_parse_URL(struct MHD_Session * session) {
195 */ 185 */
196static void 186static void
197MHD_parse_session_headers(struct MHD_Session * session) { 187MHD_parse_session_headers(struct MHD_Session * session) {
188#if 0
198 const char * crlfcrlf = "\r\n\r\n"; 189 const char * crlfcrlf = "\r\n\r\n";
199 const char * crlf = "\r\n"; 190 const char * crlf = "\r\n";
200 191
@@ -249,8 +240,7 @@ MHD_parse_session_headers(struct MHD_Session * session) {
249 session->headers[session->firstFreeHeader++] = newHeader; 240 session->headers[session->firstFreeHeader++] = newHeader;
250 curTok = strtok_r(NULL, crlf, &saveptr); 241 curTok = strtok_r(NULL, crlf, &saveptr);
251 } 242 }
252 243#endif
253 return numBytes;
254} 244}
255 245
256 246
@@ -269,7 +259,7 @@ MHD_find_access_handler(struct MHD_Session * session) {
269 * (multithreaded, external select, internal select) call this function 259 * (multithreaded, external select, internal select) call this function
270 * to handle reads. 260 * to handle reads.
271 */ 261 */
272static int 262int
273MHD_session_handle_read(struct MHD_Session * session) { 263MHD_session_handle_read(struct MHD_Session * session) {
274 int bytes_read; 264 int bytes_read;
275 void * tmp; 265 void * tmp;
@@ -322,8 +312,8 @@ MHD_session_handle_read(struct MHD_Session * session) {
322 return MHD_NO; 312 return MHD_NO;
323 } 313 }
324 /* dh left "processed" bytes in buffer for next time... */ 314 /* dh left "processed" bytes in buffer for next time... */
325 memmove(session->readBuffer, 315 memmove(session->read_buffer,
326 &session->readBuffer[session->readLoc - processed], 316 &session->read_buffer[session->readLoc - processed],
327 processed); 317 processed);
328 session->readLoc = processed; 318 session->readLoc = processed;
329 session->uploadSize -= processed; 319 session->uploadSize -= processed;
@@ -332,157 +322,154 @@ MHD_session_handle_read(struct MHD_Session * session) {
332 return MHD_YES; 322 return MHD_YES;
333} 323}
334 324
325/**
326 * Allocate the session's write buffer and
327 * fill it with all of the headers from the
328 * HTTPd's response.
329 */
330static void
331MHD_build_header_response(struct MHD_Session * session) {
332 size_t size;
333 size_t off;
334 struct MHD_HTTP_Header * pos;
335 char code[32];
336 char * data;
337
338 sprintf(code,
339 "HTTP/1.1 %u\r\n",
340 session->responseCode);
341 off = strlen(code);
342 /* estimate size */
343 size = off + 2; /* extra \r\n at the end */
344 pos = session->response->first_header;
345 while (pos != NULL) {
346 size += strlen(pos->header) + strlen(pos->value) + 4; /* colon, space, linefeeds */
347 pos = pos->next;
348 }
349 /* produce data */
350 data = malloc(size);
351 memcpy(data,
352 code,
353 off);
354 pos = session->response->first_header;
355 while (pos != NULL) {
356 sprintf(&data[off],
357 "%s: %s\r\n",
358 pos->header,
359 pos->value);
360 off += strlen(pos->header) + strlen(pos->value) + 4;
361 pos = pos->next;
362 }
363 if (off != size)
364 abort();
365 session->write_buffer = data;
366 session->write_buffer_size = size;
367}
335 368
336/** 369/**
337 * This function was created to handle writes to sockets when it has been 370 * This function was created to handle writes to sockets when it has
338 * determined that the socket can be written to. If there is no data 371 * been determined that the socket can be written to. All
339 * to be written, however, the function call does nothing. All implementations 372 * implementations (multithreaded, external select, internal select)
340 * (multithreaded, external select, internal select) call this function 373 * call this function
341 */ 374 */
342int 375int
343MHD_session_handle_write(struct MHD_Session * session) { 376MHD_session_handle_write(struct MHD_Session * session) {
344 struct MHD_Response * response; 377 struct MHD_Response * response;
345 int i; 378 int ret;
346 char * buffer[2048];
347 char * responseMessage;
348 int numBytesInMessage;
349 379
350 response = session->response; 380 response = session->response;
351 if(response == NULL) { 381 if(response == NULL) {
352 /* FIXME: LOG: why are we here? */ 382 /* FIXME: LOG: why are we here? */
353 return MHD_NO; 383 return MHD_NO;
354 } 384 }
355 numBytesInMessage = 25; 385 if (! session->headersSent) {
356 responseMessage = malloc(25); 386 if (session->write_buffer == NULL)
357 387 MHD_build_header_response(session);
358 pthread_mutex_lock(&response->mutex); 388 ret = send(session->socket_fd,
359 389 &session->write_buffer[session->writeLoc],
360 if(!response->headersSent) { 390 session->write_buffer_size - session->writeLoc,
361 sprintf(responseMessage, "HTTP/1.1 %i Go to hell!\r\n", response->responseCode); 391 0);
362 fprintf(stderr, "%s\n", responseMessage); 392 if (ret < 0) {
363 if(send(session->socket_fd, responseMessage, strlen(responseMessage), 0) != strlen(responseMessage)) { 393 if (errno == EINTR)
364 fprintf(stderr, "Error! could not send an entire header in one call to send! unable to handle this case as of this time.\n"); 394 return MHD_YES;
365 pthread_mutex_unlock(&response->mutex); 395 /* FIXME: log error */
366 return MHD_NO; 396 close(session->socket_fd);
367 } 397 session->socket_fd = -1;
368 398 return MHD_NO;
369 for(i = 0; i < MHD_MAX_HEADERS; i++) { 399 }
370 if(response->headers[i] == NULL) 400 session->writeLoc += ret;
371 continue; 401 if (session->writeLoc == session->write_buffer_size) {
372 402 session->writeLoc = 0;
373 if(strlen(response->headers[i]->header) + strlen(response->headers[i]->value) + 5 > numBytesInMessage) { 403 free(session->write_buffer);
374 free(responseMessage); 404 session->write_buffer = NULL;
375 responseMessage = malloc(strlen(response->headers[i]->header) + strlen(response->headers[i]->value) + 5); 405 session->write_buffer_size = 0;
376 if(responseMessage == NULL) { 406 session->headersSent = 1;
377 if(daemon->options & MHD_USE_DEBUG) 407 }
378 fprintf(stderr, "Error allocating memory!\n"); 408 return MHD_YES;
379 pthread_mutex_unlock(&response->mutex); 409 }
380 return MHD_NO; 410 if (response->total_size <= session->messagePos)
381 } 411 abort(); /* internal error */
382 numBytesInMessage = strlen(response->headers[i]->header) + strlen(response->headers[i]->value) + 5; 412 if (response->crc != NULL)
383 } 413 pthread_mutex_lock(&response->mutex);
384 sprintf(responseMessage, "%s: %s\r\n", response->headers[i]->header, response->headers[i]->value); 414
385 fprintf(stderr, "%s\n", responseMessage); 415 /* prepare send buffer */
386 if(send(session->socket_fd, responseMessage, strlen(responseMessage), 0) != strlen(responseMessage)) { 416 if ( (response->data == NULL) ||
387 fprintf(stderr, "Error! could not send an entire header in one call to send! unable to handle this case as of this time.\n"); 417 (response->data_start > session->messagePos) ||
388 pthread_mutex_unlock(&response->mutex); 418 (response->data_start + response->data_size < session->messagePos) ) {
389 return MHD_NO; 419 if (response->data_size == 0) {
390 } 420 if (response->data != NULL)
391 } 421 free(response->data);
392 422 response->data = malloc(MHD_MAX_BUF_SIZE);
393 response->headersSent = 1; 423 response->data_size = MHD_MAX_BUF_SIZE;
394 } 424 }
395 425 ret = response->crc(response->crc_cls,
396 if(response->data != NULL) { 426 session->messagePos,
397 if(response->bytesSentSoFar == 0) { 427 response->data,
398 if(numBytesInMessage < 32) { 428 MAX(MHD_MAX_BUF_SIZE,
399 free(responseMessage); 429 response->data_size - session->messagePos));
400 responseMessage = malloc(32); 430 if (ret == -1) {
401 if(responseMessage == NULL) { 431 /* end of message, signal other side by closing! */
402 if(daemon->options & MHD_USE_DEBUG) 432 response->data_size = session->messagePos;
403 fprintf(stderr, "Error allocating memory!\n"); 433 close(session->socket_fd);
404 pthread_mutex_unlock(&response->mutex); 434 session->socket_fd = -1;
405 return MHD_NO; 435 return MHD_YES;
406 } 436 }
407 } 437 response->data_start = session->messagePos;
408 sprintf(responseMessage, "Content-length: %llu\r\n\r\n", (unsigned long long)response->size); 438 response->data_size = ret;
409 fprintf(stderr, "%s\n", responseMessage); 439 if (ret == 0)
410 if(send(session->socket_fd, responseMessage, strlen(responseMessage),0)!= strlen(responseMessage)) { 440 return MHD_YES; /* or NO? */
411 fprintf(stderr, "Error! could not send an entire header in one call to send! unable to handle this case as of this time.\n"); 441 }
412 pthread_mutex_unlock(&response->mutex); 442
413 return MHD_NO; 443 /* transmit */
414 } 444 ret = send(session->socket_fd,
415 } 445 &response->data[session->messagePos - response->data_start],
416 446 response->data_size - (session->messagePos - response->data_start),
417 i = send(session->socket_fd, response->data+response->bytesSentSoFar, response->size-response->bytesSentSoFar,0); 447 0);
418 response->bytesSentSoFar += i; 448 if (response->crc != NULL)
419 449 pthread_mutex_unlock(&response->mutex);
420 fprintf(stderr, "Sent %i bytes of data\nTotal to send is %llu bytes\n", i, (unsigned long long)response->size); 450 if (ret == -1) {
421 451 if (errno == EINTR)
422 if(response->bytesSentSoFar == response->size) { 452 return MHD_YES;
423 session->currentResponses[session->currentResponse] = NULL; 453 /* FIXME: log */
424 session->currentResponse = (session->currentResponse + 1) % MHD_MAX_RESPONSE; 454 return MHD_NO;
425 response->currentSession = NULL; 455 }
426 456 session->messagePos += ret;
427 if(response->freeWhenFinished) { 457 if (session->messagePos == response->data_size) {
428 pthread_mutex_unlock(&response->mutex); 458 /* reset session, wait for next request! */
429 MHD_destroy_response(response); 459 MHD_destroy_response(response);
430 } 460 session->responseCode = 0;
431 /*THIS NEEDS TO BE HANDLED ANOTHER WAY!!! TIMEOUT, ect..., as of now this is the only way to get test case to work 461 session->response = NULL;
432 * since client never disconnects on their own! 462 session->headersReceived = 0;
433 */ 463 session->headersSent = 0;
434 if(session->currentResponses[session->currentResponse] == NULL) { 464 session->bodyReceived = 0;
435 MHD_destroy_session(session); 465 session->messagePos = 0;
436 daemon->connections[connection_id] = NULL; 466 free(session->write_buffer);
437 return MHD_NO; 467 session->write_buffer = NULL;
438 } 468 session->write_buffer_size = 0;
439 } 469 }
440 } else { 470 return MHD_YES;
441 if(response->crc == NULL) {
442 pthread_mutex_unlock(&response->mutex);
443 return MHD_NO;
444 }
445
446 if(response->bytesSentSoFar == 0) {
447 if(send(session->socket_fd, "\r\n", response->size,0) != 2) {
448 fprintf(stderr, "Error! could not send an entire header in one call to send! unable to handle this case as of this time.\n");
449 pthread_mutex_unlock(&response->mutex);
450 return MHD_NO;
451 }
452 }
453 memset(buffer, 0, 2048);
454
455 i = response->crc(response->crc_cls, response->bytesSentSoFar, (char *)buffer, 2048);
456
457 if(i == -1) {
458 pthread_mutex_unlock(&response->mutex);
459
460 session->currentResponses[session->currentResponse] = NULL;
461 session->currentResponse = (session->currentResponse + 1) % MHD_MAX_RESPONSE;
462 response->currentSession = NULL;
463
464 if(response->freeWhenFinished) {
465 pthread_mutex_unlock(&response->mutex);
466 MHD_destroy_response(response);
467 }
468 /*THIS NEEDS TO BE HANDLED ANOTHER WAY!!! TIMEOUT, ect..., as of now this is the only way to get test case to work
469 * since client never disconnects on their own!
470 */
471 if(session->currentResponses[session->currentResponse] == NULL) {
472 MHD_destroy_session(session);
473 daemon->connections[connection_id] = NULL;
474 return MHD_NO;
475 }
476
477 } else {
478 i = send(session->socket_fd, buffer, i,0);
479 response->bytesSentSoFar += i;
480 }
481 }
482 pthread_mutex_unlock(&response->mutex);
483 return MHD_YES;
484} 471}
485 472
486 473/* end of session.c */
487 474
488 475
diff --git a/src/daemon/session.h b/src/daemon/session.h
index 24ddd641..0097a398 100644
--- a/src/daemon/session.h
+++ b/src/daemon/session.h
@@ -30,103 +30,6 @@
30#define SESSION_H 30#define SESSION_H
31 31
32 32
33struct MHD_Session {
34 struct MHD_Session * next;
35
36 struct MHD_Daemon * daemon;
37
38 struct MHD_HTTP_Header * headers_received;
39
40 struct MHD_Response * response;
41
42 char * method;
43
44 char * url;
45
46 /**
47 * Buffer for reading requests.
48 */
49 void * read_buffer;
50
51 /**
52 * Buffer for writing response.
53 */
54 void * write_buffer;
55
56 /**
57 * Foreign address (of length addr_len).
58 */
59 struct sockaddr_in * addr;
60
61 /**
62 * Thread for this session (if we are using
63 * one thread per connection).
64 */
65 pthread_t pid;
66
67 size_t read_buffer_size;
68
69 size_t readLoc;
70
71 size_t write_buffer_size;
72
73 size_t writeLoc;
74
75 /**
76 * Current write position in the actual response
77 * (excluding headers, content only; should be 0
78 * while sending headers).
79 */
80 size_t messagePos;
81
82 /**
83 * Remaining (!) number of bytes in the upload.
84 * Set to -1 for unknown (connection will close
85 * to indicate end of upload).
86 */
87 size_t uploadSize;
88
89 /**
90 * Length of the foreign address.
91 */
92 socklen_t addr_len;
93
94 /**
95 * Socket for this connection. Set to -1 if
96 * this connection has died (daemon should clean
97 * up in that case).
98 */
99 int socket_fd;
100
101 /**
102 * Have we finished receiving all of the headers yet?
103 * Set to 1 once we are done processing all of the
104 * headers. Note that due to pipelining, it is
105 * possible that the NEXT request is already
106 * (partially) waiting in the read buffer.
107 */
108 int headersReceived;
109
110 /**
111 * Have we finished receiving the data from a
112 * potential file-upload?
113 */
114 int bodyReceived;
115
116 /**
117 * Have we finished sending all of the headers yet?
118 */
119 int headersSent;
120
121 /**
122 * HTTP response code. Only valid if response object
123 * is already set.
124 */
125 unsigned int responseCode;
126
127};
128
129
130/** 33/**
131 * Obtain the select sets for this session. 34 * Obtain the select sets for this session.
132 * 35 *