Skip to content
This repository
Browse code

Cleaned up the async upload code.

  • Loading branch information...
commit c568e1b06d289daad39bc786f77647f714142f21 1 parent ab664cc
Unknown authored
58 src/connection.c
@@ -84,13 +84,11 @@ static inline int Connection_backend_event(Backend *found, Connection *conn)
84 84
85 85 int connection_send_socket_response(Connection *conn)
86 86 {
87   - int rc = Response_send_socket_policy(conn);
88   - check_debug(rc > 0, "Failed to write Flash socket response.");
89   -
90   - return RESP_SENT;
91   -
92   -error:
93   - return CLOSE;
  87 + if(Response_send_socket_policy(conn) > 0) {
  88 + return RESP_SENT;
  89 + } else {
  90 + return CLOSE;
  91 + }
94 92 }
95 93
96 94
@@ -106,6 +104,7 @@ int connection_route_request(Connection *conn)
106 104 } else {
107 105 host = conn->server->default_host;
108 106 }
  107 +
109 108 error_unless(host, conn, 404, "Request for a host we don't have registered: %s", bdata(conn->req->host_name));
110 109
111 110 Backend *found = Host_match_backend(host, path, &route);
@@ -137,7 +136,6 @@ int connection_msg_to_handler(Connection *conn)
137 136 bdata(Request_path(conn->req)));
138 137
139 138 if(pattern_match(IOBuf_start(conn->iob), header_len + body_len, bdata(&PING_PATTERN))) {
140   - Log_request(conn, 200, 0);
141 139 Register_ping(IOBuf_fd(conn->iob));
142 140 } else {
143 141 check(body_len >= 0, "Parsing error, body length ended up being: %d", body_len);
@@ -163,13 +161,35 @@ int connection_msg_to_handler(Connection *conn)
163 161 }
164 162
165 163
  164 +int Connection_send_to_handler(Connection *conn, Handler *handler, char *body, int content_len)
  165 +{
  166 + int rc = 0;
  167 + bstring result = NULL;
  168 +
  169 + result = Request_to_payload(conn->req, handler->send_ident,
  170 + IOBuf_fd(conn->iob), body, content_len);
  171 + check(result, "Failed to create payload for request.");
  172 +
  173 + debug("HTTP TO HANDLER: %.*s", blength(result) - content_len, bdata(result));
  174 +
  175 + rc = Handler_deliver(handler->send_socket, bdata(result), blength(result));
  176 + error_unless(rc != -1, conn, 502, "Failed to deliver to handler: %s",
  177 + bdata(Request_path(conn->req)));
  178 +
  179 + bdestroy(result);
  180 + return 0;
  181 +
  182 +error:
  183 + bdestroy(result);
  184 + return -1;
  185 +}
  186 +
166 187
167 188 int connection_http_to_handler(Connection *conn)
168 189 {
169 190 int content_len = Request_content_length(conn->req);
170 191 int rc = 0;
171 192 char *body = NULL;
172   - bstring result = NULL;
173 193
174 194 Handler *handler = Request_get_action(conn->req, handler);
175 195 error_unless(handler, conn, 404, "No action for request: %s", bdata(Request_path(conn->req)));
@@ -180,11 +200,10 @@ int connection_http_to_handler(Connection *conn)
180 200 if(content_len == 0) {
181 201 body = "";
182 202 } else if(content_len > MAX_CONTENT_LENGTH) {
183   - bstring upload_store = Upload_file(conn, handler, content_len);
184   -
185 203 body = "";
186 204 content_len = 0;
187   - check(upload_store != NULL, "Failed to upload file.");
  205 + rc = Upload_file(conn, handler, content_len);
  206 + check(rc == 0, "Failed to upload file.");
188 207 } else {
189 208 if(content_len > conn->iob->len) {
190 209 // temporarily grow the buffer
@@ -196,23 +215,14 @@ int connection_http_to_handler(Connection *conn)
196 215 check(body != NULL, "Client closed the connection during upload.");
197 216 }
198 217
199   - Log_request(conn, 200, content_len);
  218 + rc = Connection_send_to_handler(conn, handler, body, content_len);
  219 + check_debug(rc == 0, "Failed to deliver to the handler.");
200 220
201   - result = Request_to_payload(conn->req, handler->send_ident,
202   - IOBuf_fd(conn->iob), body, content_len);
203   - check(result, "Failed to create payload for request.");
204   -
205   - debug("HTTP TO HANDLER: %.*s", blength(result) - content_len, bdata(result));
206   -
207   - rc = Handler_deliver(handler->send_socket, bdata(result), blength(result));
208   - error_unless(rc != -1, conn, 502, "Failed to deliver to handler: %s",
209   - bdata(Request_path(conn->req)));
  221 + Log_request(conn, 200, content_len);
210 222
211   - bdestroy(result);
212 223 return REQ_SENT;
213 224
214 225 error:
215   - bdestroy(result);
216 226 return CLOSE;
217 227 }
218 228
2  src/connection.h
@@ -69,6 +69,8 @@ void Connection_accept(Connection *conn);
69 69
70 70 void Connection_task(void *v);
71 71
  72 +struct Handler;
  73 +int Connection_send_to_handler(Connection *conn, Handler *handler, char *body, int content_len);
72 74
73 75 int Connection_deliver_raw(int to_fd, bstring buf);
74 76
85 src/upload.c
@@ -3,67 +3,82 @@
3 3 #include "setting.h"
4 4 #include "response.h"
5 5
  6 +bstring UPLOAD_STORE = NULL;
6 7
7 8
8   -bstring Upload_file(Connection *conn, Handler *handler, int content_len)
  9 +static inline int stream_to_disk(IOBuf *iob, int content_len, int tmpfd)
9 10 {
10   - int rc = 0;
11   - int tmpfd = 0;
12   - bstring result = NULL;
13 11 char *data = NULL;
  12 + int avail = 0;
14 13
15   - // need a setting for the moby store where large uploads should go
16   - bstring upload_store = Setting_get_str("upload.temp_store", NULL);
17   - error_unless(upload_store, conn, 413, "Request entity is too large: %d, and no upload.temp_store setting for where to put the big files.", content_len);
  14 + IOBuf_resize(iob, MAX_CONTENT_LENGTH); // give us a good buffer size
18 15
19   - upload_store = bstrcpy(upload_store); // Setting owns the original
  16 + while(content_len > 0) {
  17 + data = IOBuf_read_some(iob, &avail);
  18 + check(!IOBuf_closed(iob), "Closed while reading from IOBuf.");
  19 + content_len -= avail;
20 20
21   - // TODO: handler should be set to allow large uploads, otherwise error
  21 + check(write(tmpfd, data, avail) == avail, "Failed to write requested amount to tempfile: %d", avail);
22 22
23   - tmpfd = mkstemp((char *)upload_store->data);
24   - check(tmpfd != -1, "Failed to create secure tempfile, did you end it with XXXXXX?");
25   - log_info("Writing tempfile %s for large upload.", bdata(upload_store));
  23 + IOBuf_read_commit(iob, avail);
  24 + }
26 25
27   - // send the initial headers we have so they can kill it if they want
28   - dict_alloc_insert(conn->req->headers, bfromcstr("X-Mongrel2-Upload-Start"), upload_store);
  26 + check(content_len == 0, "Failed to write everything to the large upload tmpfile.");
29 27
30   - result = Request_to_payload(conn->req, handler->send_ident,
31   - IOBuf_fd(conn->iob), "", 0);
32   - check(result, "Failed to create initial payload for upload attempt.");
  28 + return 0;
33 29
34   - rc = Handler_deliver(handler->send_socket, bdata(result), blength(result));
35   - check(rc != -1, "Failed to deliver upload attempt to handler.");
  30 +error:
  31 + return -1;
  32 +}
36 33
37   - // all good so start streaming chunks into the temp file in the moby dir
38   - IOBuf_resize(conn->iob, MAX_CONTENT_LENGTH); // give us a good buffer size
39 34
40   - while(content_len > 0) {
41   - data = IOBuf_read_some(conn->iob, &rc);
42   - check(!IOBuf_closed(conn->iob), "Closed while reading from IOBuf.");
43   - content_len -= rc;
  35 +int Upload_notify(Connection *conn, Handler *handler, const char *stage, bstring tmp_name)
  36 +{
  37 + bstring key = bformat("X-Mongrel2-Upload-%s", stage);
  38 + dict_alloc_insert(conn->req->headers, key, tmp_name);
44 39
45   - check(write(tmpfd, data, rc) == rc, "Failed to write requested amount to tempfile: %d", rc);
  40 + return Connection_send_to_handler(conn, handler, "", 0);
  41 +}
  42 +
  43 +int Upload_file(Connection *conn, Handler *handler, int content_len)
  44 +{
  45 + int rc = 0;
  46 + int tmpfd = 0;
  47 + bstring tmp_name = NULL;
  48 + bstring result = NULL;
46 49
47   - IOBuf_read_commit(conn->iob, rc);
  50 + if(UPLOAD_STORE == NULL) {
  51 + UPLOAD_STORE = Setting_get_str("upload.temp_store", NULL);
  52 + error_unless(UPLOAD_STORE, conn, 413, "Request entity is too large: %d, and no upload.temp_store setting for where to put the big files.", content_len);
48 53 }
49 54
50   - check(content_len == 0, "Bad math on writing out the upload tmpfile: %s, it's %d", bdata(upload_store), content_len);
  55 + tmp_name = bstrcpy(UPLOAD_STORE);
  56 +
  57 + tmpfd = mkstemp((char *)tmp_name->data);
  58 + check(tmpfd != -1, "Failed to create secure tempfile, did you end it with XXXXXX?");
  59 + log_info("Writing tempfile %s for large upload.", bdata(tmp_name));
  60 +
  61 + rc = Upload_notify(conn, handler, "Start", tmp_name);
  62 + check(rc == 0, "Failed to notify of the start of upload.");
  63 +
  64 + rc = stream_to_disk(conn->iob, content_len, tmpfd);
  65 + check(rc == 0, "Failed to stream to disk.");
51 66
52   - // moby dir write is done, add a header to the request that indicates where to get it
53   - dict_alloc_insert(conn->req->headers, bfromcstr("X-Mongrel2-Upload-Done"), upload_store);
  67 + rc = Upload_notify(conn, handler, "Done", tmp_name);
  68 + check(rc == 0, "Failed to notify the end of the upload.");
54 69
55 70 bdestroy(result);
56 71 fdclose(tmpfd);
57   - return upload_store;
  72 + return 0;
58 73
59 74 error:
60 75 bdestroy(result);
61 76 fdclose(tmpfd);
62 77
63   - if(upload_store) {
64   - unlink((char *)upload_store->data);
65   - bdestroy(upload_store);
  78 + if(tmp_name) {
  79 + unlink((char *)tmp_name->data);
  80 + bdestroy(tmp_name);
66 81 }
67 82
68   - return NULL;
  83 + return -1;
69 84 }
4 src/upload.h
@@ -3,8 +3,8 @@
3 3
4 4 #include "connection.h"
5 5 #include "handler.h"
6   -#include "bstring.h"
7 6
8   -bstring Upload_file(Connection *conn, Handler *handler, int content_len);
  7 +int Upload_file(Connection *conn, Handler *handler, int content_len);
  8 +int Upload_notify(Connection *conn, Handler *handler, const char *stage, bstring tmp_name);
9 9
10 10 #endif

0 comments on commit c568e1b

Please sign in to comment.
Something went wrong with that request. Please try again.