0
@@ -180,6 +180,78 @@ void on_timeout(struct ev_loop *loop, ev_timer *watcher, int revents)
0
#define client_finished_parsing http_parser_is_finished(&client->parser)
0
+#define total_request_size (client->content_length + client->parser.nread)
0
+void* read_body_into_file(void *_client)
0
+ ebb_client *client = (ebb_client*)_client;
0
+ static unsigned int id;
0
+ assert(client->server->open);
0
+ assert(client->content_length > 0);
0
+ assert(client_finished_parsing);
0
+ /* set blocking socket */
0
+ int flags = fcntl(client->fd, F_GETFL, 0);
0
+ assert(0 <= fcntl(client->fd, F_SETFL, flags & ~O_NONBLOCK));
0
+ sprintf(client->upload_file_filename, "/tmp/ebb_upload_%010d", id++);
0
+ tmpfile = fopen(client->upload_file_filename, "w+");
0
+ if(tmpfile == NULL) ebb_error("Cannot open tmpfile %s", client->upload_file_filename);
0
+ client->upload_file = tmpfile;
0
+ size_t body_head_length = client->read - client->parser.nread;
0
+ size_t written = 0, r;
0
+ while(written < body_head_length) {
0
+ r = fwrite( client->request_buffer + sizeof(char)*(client->parser.nread + written)
0
+ , body_head_length - written
0
+ ebb_client_close(client);
0
+ // ebb_debug("wrote request header to file. written: %d, content_length: %d", written, client->content_length);
0
+ while(written < client->content_length) {
0
+ received = recv(client->fd
0
+ , min(client->content_length - written, bufsize)
0
+ if(received < 0) goto error;
0
+ client->read += received;
0
+ rv = fwrite( buffer + w*sizeof(char)
0
+ if(rv <= 0) goto error;
0
+ // ebb_debug("%d bytes written to file %s", written, client->upload_file_filename);
0
+ ebb_client_close(client);
0
void on_readable(struct ev_loop *loop, ev_io *watcher, int revents)
0
@@ -189,27 +261,41 @@ void on_readable(struct ev_loop *loop, ev_io *watcher, int revents)
0
assert(client->server->open);
0
assert(client->server->loop == loop);
0
assert(&client->read_watcher == watcher);
0
- assert(FALSE == client_finished_parsing);
0
ssize_t read = recv( client->fd
0
- , client->request_buffer + client->nread_head
0
- , EBB_BUFFERSIZE - client->nread_head - 1
0
+ , client->request_buffer + client->read
0
+ , EBB_BUFFERSIZE - client->read - 1 /* -1 is for making ragel happy below */
0
if(read <= 0) goto error; /* XXX is this the right action to take for read==0 ? */
0
- client->nread_head += read;
0
ev_timer_again(loop, &client->timeout_watcher);
0
- client->request_buffer[client->nread_head] = '\0'; /* make ragel happy */
0
- http_parser_execute( &client->parser
0
- , client->request_buffer
0
- , client->parser.nread
0
- if(http_parser_has_error(&client->parser)) goto error;
0
- if(client_finished_parsing) {
0
+ if(FALSE == client_finished_parsing) {
0
+ client->request_buffer[client->read] = '\0'; /* make ragel happy */
0
+ http_parser_execute( &client->parser
0
+ , client->request_buffer
0
+ , client->parser.nread
0
+ if(http_parser_has_error(&client->parser)) goto error;
0
+ if(total_request_size == client->read) {
0
ev_io_stop(loop, watcher);
0
+ client->nread_from_body = 0;
0
+ if(client_finished_parsing && total_request_size > EBB_BUFFERSIZE ) {
0
+ /* read body into file - in a thread */
0
+ ev_io_stop(loop, watcher);
0
+ assert(0 <= pthread_create(&thread, NULL, read_body_into_file, client));
0
+ pthread_join(thread, NULL);
0
@@ -217,11 +303,7 @@ error:
0
ebb_client_close(client);
0
-void on_request( struct ev_loop *loop
0
+void on_request(struct ev_loop *loop, ev_io *watcher, int revents)
0
ebb_server *server = (ebb_server*)(watcher->data);
0
@@ -281,9 +363,9 @@ void on_request( struct ev_loop *loop
0
- client->nread_head = client->nread_body = 0;
0
+ client->read = client->nread_from_body = 0;
0
client->response_buffer->len = 0; /* see note in ebb_client_close */
0
- client->content_length = -1;
0
+ client->content_length = 0;
0
/* SETUP READ AND TIMEOUT WATCHERS */
0
client->read_watcher.data = client;
0
@@ -404,7 +486,10 @@ void ebb_client_close(ebb_client *client)
0
ev_io_stop(client->server->loop, &client->write_watcher);
0
ev_timer_stop(client->server->loop, &client->timeout_watcher);
0
- http_parser_finish(&client->parser);
0
+ if(client->upload_file) {
0
+ fclose(client->upload_file);
0
+ unlink(client->upload_file_filename);
0
/* here we do not free the already allocated GString client->response_buffer
0
* that we're holding the response in. we reuse it again -
0
@@ -462,59 +547,6 @@ void ebb_client_write(ebb_client *client, const char *data, int length)
0
-/* pass an allocated buffer and the length to read. this function will try to
0
- * fill the buffer with that length of data read from the body of the request.
0
- * the return value says how much was actually written.
0
- * return length read on successful read
0
- * returns -2 if the nonblocking socket is not yet availible for reading
0
- * returns -3 if content_length is present and the request is finished.
0
-int ebb_client_read(ebb_client *client, char *buffer, int length)
0
- char* body_beginning = client->request_buffer + client->parser.nread;
0
- int body_beginning_size = client->nread_head - client->parser.nread;
0
- if(!client->open) return -1;
0
- assert(client->nread_body >= 0);
0
- assert(client_finished_parsing);
0
- assert(client->parser.nread + body_beginning_size < EBB_BUFFERSIZE);
0
- assert(client->parser.nread + body_beginning_size == client->nread_head);
0
- if(client->nread_body == client->content_length) return(-3);
0
- if(client->nread_body < body_beginning_size) {
0
- to_read = min(length, body_beginning_size - client->nread_body);
0
- assert(0 <= to_read && to_read <= length);
0
- , body_beginning + client->nread_body
0
- client->nread_body += to_read;
0
- /* allow for requests where the content length is not mentioned. e.g.
0
- read = recv(client->fd, buffer, length, 0);
0
- //ebb_info("recv(%d, buffer, %d, 0) -> %d (%s)", client->fd, length, read, strerror(errno));
0
- if(errno == EAGAIN) return -2;
0
- ebb_warning("closing client. ebb_client_read: %s", strerror(errno));
0
- ebb_client_close(client);
0
- client->nread_body += read;
0
void ebb_client_finished(ebb_client *client)
0
@@ -538,6 +570,34 @@ void ebb_client_finished(ebb_client *client)
0
+/* pass an allocated buffer and the length to read. this function will try to
0
+ * fill the buffer with that length of data read from the body of the request.
0
+ * the return value says how much was actually written.
0
+int ebb_client_read(ebb_client *client, char *buffer, int length)
0
+ assert(client_finished_parsing);
0
+ if(client->upload_file) {
0
+ read = fread(buffer, 1, length, client->upload_file);
0
+ /* TODO error checking! */
0
+ char* request_body = client->request_buffer + client->parser.nread;
0
+ read = ramp(min(length, client->content_length - client->nread_from_body));
0
+ , request_body + client->nread_from_body
0
+ client->nread_from_body += read;
0
/* The following socket creation routines are modified and stolen from memcached */
0
static int server_socket(const int port) {
Comments
No one has commented yet.