diff options
Diffstat (limited to 'http_put.c')
-rw-r--r-- | http_put.c | 86 |
1 files changed, 47 insertions, 39 deletions
@@ -12,8 +12,10 @@ static __thread struct { char state[128]; } rnd; -static void file_close_null(struct mog_http *http) +static void file_close_null(struct mog_fd *mfd) { + struct mog_http *http = &mfd->as.http; + if (http->forward == NULL) return; mog_http_unlink_ftmp(http); @@ -71,10 +73,10 @@ bool mog_http_write_full(struct mog_fd *file_mfd, char *buf, size_t buf_len) return false; } -#define stop(http,status) stop0((http),(status),sizeof(status)-1); +#define stop(mfd,status) stop0((mfd),(status),sizeof(status)-1); MOG_NOINLINE static enum mog_next -stop0(struct mog_http *http, const char *status, size_t status_len) +stop0(struct mog_fd *mfd, const char *status, size_t status_len) { if (status) { struct iovec iov; @@ -84,26 +86,26 @@ stop0(struct mog_http *http, const char *status, size_t status_len) iov.iov_base = deconst.out; iov.iov_len = status_len; - mog_http_resp0(http, &iov, false); + mog_http_resp0(mfd, &iov, false); } - file_close_null(http); + file_close_null(mfd); return MOG_NEXT_CLOSE; } MOG_NOINLINE static enum mog_next -write_err(struct mog_http *http, const char *default_msg) +write_err(struct mog_fd *mfd, const char *default_msg) { switch (errno) { case ERANGE: case ENOSPC: case EFBIG: - return stop(http, "507 Insufficient Storage"); + return stop(mfd, "507 Insufficient Storage"); } if (default_msg == NULL) default_msg = "500 Internal Server Error"; - return stop0(http, default_msg, strlen(default_msg)); + return stop0(mfd, default_msg, strlen(default_msg)); } static bool md5_ok(struct mog_http *http) @@ -142,31 +144,35 @@ static bool set_perms_commit(struct mog_http *http) return false; } -static void put_commit_resp(struct mog_http *http) +static void put_commit_resp(struct mog_fd *mfd) { + struct mog_http *http = &mfd->as.http; + if (md5_ok(http)) { /* true if there's no MD5, too */ if (set_perms_commit(http)) { - file_close_null(http); - mog_http_resp(http, "201 Created", true); + file_close_null(mfd); + mog_http_resp(mfd, "201 Created", true); } else { - file_close_null(http); - mog_http_resp(http, "500 Internal Server Error", false); + file_close_null(mfd); + mog_http_resp(mfd, "500 Internal Server Error", false); } } else { - file_close_null(http); - mog_http_resp(http, "400 Bad Request", true); + file_close_null(mfd); + mog_http_resp(mfd, "400 Bad Request", true); } } -static enum mog_next http_put_commit(struct mog_http *http) +static enum mog_next http_put_commit(struct mog_fd *mfd) { - put_commit_resp(http); + struct mog_http *http = &mfd->as.http; + + put_commit_resp(mfd); if (http->wbuf && http->wbuf != MOG_WR_ERROR) return MOG_NEXT_WAIT_WR; if (!http->_p.persistent || http->wbuf == MOG_WR_ERROR) return MOG_NEXT_CLOSE; - mog_http_reset(http); + mog_http_reset(mfd); return MOG_NEXT_ACTIVE; } @@ -196,8 +202,9 @@ static void stash_advance_rbuf(struct mog_http *http, char *buf, size_t buf_len) } static void -chunked_body_after_header(struct mog_http *http, char *buf, size_t buf_len) +chunked_body_after_header(struct mog_fd *mfd, char *buf, size_t buf_len) { + struct mog_http *http = &mfd->as.http; size_t tmpoff = http->_p.buf_off; mog_chunk_init(http); @@ -205,7 +212,7 @@ chunked_body_after_header(struct mog_http *http, char *buf, size_t buf_len) switch (mog_chunk_parse(http, buf, buf_len)) { case MOG_PARSER_ERROR: - (void)write_err(http, "400 Bad Request"); + (void)write_err(mfd, "400 Bad Request"); return; case MOG_PARSER_CONTINUE: assert(http->_p.chunk_state != MOG_CHUNK_STATE_DONE); @@ -227,7 +234,7 @@ chunked_body_after_header(struct mog_http *http, char *buf, size_t buf_len) http->_p.skip_rbuf_defer = 1; return; case MOG_CHUNK_STATE_DONE: - put_commit_resp(http); + put_commit_resp(mfd); assert(http->_p.buf_off > 0 && "http->_p.buf_off unset after chunk body done"); stash_advance_rbuf(http, buf, buf_len); @@ -237,8 +244,9 @@ chunked_body_after_header(struct mog_http *http, char *buf, size_t buf_len) } static void -identity_body_after_header(struct mog_http *http, char *buf, size_t buf_len) +identity_body_after_header(struct mog_fd *mfd, char *buf, size_t buf_len) { + struct mog_http *http = &mfd->as.http; size_t body_len = buf_len - http->_p.buf_off; char *body_ptr = buf + http->_p.buf_off; @@ -248,7 +256,7 @@ identity_body_after_header(struct mog_http *http, char *buf, size_t buf_len) return; http->_p.buf_off += body_len; if (!mog_http_write_full(http->forward, body_ptr, body_len)) - (void)write_err(http, NULL); + (void)write_err(mfd, NULL); } static bool lengths_ok(struct mog_http *http) @@ -361,7 +369,7 @@ void mog_http_put(struct mog_fd *mfd, char *buf, size_t buf_len) struct mog_file *file; if (mfd->fd_type == MOG_FD_TYPE_HTTPGET) { - mog_http_resp(http, "405 Method Not Allowed", false); + mog_http_resp(mfd, "405 Method Not Allowed", false); return; } @@ -372,7 +380,7 @@ void mog_http_put(struct mog_fd *mfd, char *buf, size_t buf_len) assert(path[0] == '/' && "bad path"); if (!lengths_ok(http)) { - write_err(http, "400 Bad Request"); + write_err(mfd, "400 Bad Request"); return; } @@ -397,25 +405,25 @@ void mog_http_put(struct mog_fd *mfd, char *buf, size_t buf_len) && "http->_p.buf_off is wrong"); if (http->_p.chunked) - chunked_body_after_header(http, buf, buf_len); + chunked_body_after_header(mfd, buf, buf_len); else - identity_body_after_header(http, buf, buf_len); + identity_body_after_header(mfd, buf, buf_len); return; err: switch (errno) { case EINVAL: - mog_http_resp(http, "400 Bad Request", false); + mog_http_resp(mfd, "400 Bad Request", false); return; case ENOENT: - mog_http_resp(http, "404 Not Found", false); + mog_http_resp(mfd, "404 Not Found", false); return; case EACCES: - mog_http_resp(http, "403 Forbidden", false); + mog_http_resp(mfd, "403 Forbidden", false); return; } syslog(LOG_ERR, "problem starting PUT for path=%s (%m)", path); - (void)write_err(http, NULL); + (void)write_err(mfd, NULL); } static unsigned last_data_recv(int fd) @@ -473,7 +481,7 @@ static enum mog_next identity_put_in_progress(struct mog_fd *mfd) if (http->_p.has_content_range) need += http->_p.range_beg; if (need == 0) - return http_put_commit(http); + return http_put_commit(mfd); buf = mog_fsbuf_get(&buf_len); again: @@ -484,10 +492,10 @@ retry: r = read(mfd->fd, buf, buf_len); if (r > 0) { if (!mog_http_write_full(http->forward, buf, r)) - return write_err(http, NULL); + return write_err(mfd, NULL); need -= r; if (need == 0) - return http_put_commit(http); + return http_put_commit(mfd); if (mog_ioq_contended()) return MOG_NEXT_WAIT_RD; @@ -502,7 +510,7 @@ retry: /* assume all read() errors mean socket is unwritable, too */ read_err_dbg(mfd, r); - return stop(http, NULL); + return stop(mfd, NULL); } static enum mog_next chunked_put_in_progress(struct mog_fd *mfd) @@ -539,7 +547,7 @@ again: if (r <= 0) goto read_err; if (!mog_http_write_full(http->forward, buf, r)) - return write_err(http, NULL); + return write_err(mfd, NULL); http->_p.content_len -= r; @@ -581,7 +589,7 @@ chunk_state_trailer: switch (mog_chunk_parse(http, buf, buf_len)) { case MOG_PARSER_ERROR: - return write_err(http, "400 Bad Request"); + return write_err(mfd, "400 Bad Request"); case MOG_PARSER_CONTINUE: assert(http->_p.chunk_state != MOG_CHUNK_STATE_DONE); case MOG_PARSER_DONE: @@ -610,7 +618,7 @@ chunk_state_trailer: assert(http->rbuf->rsize > 0 && http->_p.buf_off == 0 && "bad rbuf"); - return http_put_commit(http); + return http_put_commit(mfd); } } assert(0 && "compiler bug?"); @@ -625,7 +633,7 @@ read_err: } } read_err_dbg(mfd, r); - return stop(http, NULL); + return stop(mfd, NULL); } enum mog_next mog_http_put_in_progress(struct mog_fd *mfd) |