diff options
author | Christian Grothoff <christian@grothoff.org> | 2007-06-13 01:12:50 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2007-06-13 01:12:50 +0000 |
commit | baa26cd045be80620924ce41ea506bc8b043f8c7 (patch) | |
tree | 1217606ace7801f488a4b272097408a998ea53a4 | |
parent | 39eda678e0942382936ace4480a4457a837adc2f (diff) | |
download | libmicrohttpd-baa26cd045be80620924ce41ea506bc8b043f8c7.tar.gz libmicrohttpd-baa26cd045be80620924ce41ea506bc8b043f8c7.zip |
fixing compile errors
-rw-r--r-- | src/daemon/daemon.c | 28 | ||||
-rw-r--r-- | src/daemon/internal.h | 171 | ||||
-rw-r--r-- | src/daemon/response.c | 88 | ||||
-rw-r--r-- | src/daemon/session.c | 303 | ||||
-rw-r--r-- | src/daemon/session.h | 97 |
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 | */ | ||
79 | struct 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 | |||
144 | struct 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 | |||
75 | struct MHD_Daemon { | 242 | struct 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 | */ | ||
49 | struct 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 | */ |
189 | int | 109 | int |
190 | MHD_get_response_headers(struct MHD_Response * response, | 110 | MHD_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 @@ | |||
55 | int | 44 | int |
56 | MHD_get_session_values(struct MHD_Session * session, | 45 | MHD_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 | */ |
166 | static void | 155 | static void |
167 | MHD_parse_URL(struct MHD_Session * session) { | 156 | MHD_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 | */ |
196 | static void | 186 | static void |
197 | MHD_parse_session_headers(struct MHD_Session * session) { | 187 | MHD_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 | */ |
272 | static int | 262 | int |
273 | MHD_session_handle_read(struct MHD_Session * session) { | 263 | MHD_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 | */ | ||
330 | static void | ||
331 | MHD_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 | */ |
342 | int | 375 | int |
343 | MHD_session_handle_write(struct MHD_Session * session) { | 376 | MHD_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 | ||
33 | struct 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 | * |