about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2013-07-13 00:08:00 +0000
committerEric Wong <normalperson@yhbt.net>2013-07-13 09:56:06 +0000
commit22a718de33fef78bab33bc00e52cd230c22e1945 (patch)
tree2ea15384aac63ffb808c05adc3bc2edce86ab05e
parentec096dc8de3d37f4e33e7bc47bcfbe5207ae6855 (diff)
downloadcmogstored-22a718de33fef78bab33bc00e52cd230c22e1945.tar.gz
This makes it easier to write tapsets which key objects
by: PID,FD for uniqueness.  This also avoids some mog_fd_of()
calls.
-rw-r--r--cmogstored.h2
-rw-r--r--http.c31
-rw-r--r--http.h7
-rw-r--r--http_dav.c16
-rw-r--r--http_get.c15
-rw-r--r--http_put.c86
6 files changed, 82 insertions, 75 deletions
diff --git a/cmogstored.h b/cmogstored.h
index 2dffbb2..859236a 100644
--- a/cmogstored.h
+++ b/cmogstored.h
@@ -503,7 +503,7 @@ void mog_httpget_post_accept(int fd, struct mog_svc *,
 enum mog_next mog_http_queue_step(struct mog_fd *) MOG_CHECK;
 void mog_http_quit_step(struct mog_fd *);
 char *mog_http_path(struct mog_http *, char *buf);
-void mog_http_reset(struct mog_http *);
+void mog_http_reset(struct mog_fd *);
 void mog_http_unlink_ftmp(struct mog_http *);
 void mog_http_drop(struct mog_fd *);
 
diff --git a/http.c b/http.c
index d147eb1..7e35252 100644
--- a/http.c
+++ b/http.c
@@ -136,16 +136,18 @@ void mog_http_drop(struct mog_fd *mfd)
 }
 
 /* returns true if we can continue queue step, false if not */
-static enum mog_next http_wbuf_in_progress(struct mog_http *http)
+static enum mog_next http_wbuf_in_progress(struct mog_fd *mfd)
 {
+        struct mog_http *http = &mfd->as.http;
+
         assert(http->wbuf != MOG_WR_ERROR && "still active after write error");
-        switch (mog_tryflush(mog_fd_of(http)->fd, &http->wbuf)) {
+        switch (mog_tryflush(mfd->fd, &http->wbuf)) {
         case MOG_WRSTATE_ERR:
                 return MOG_NEXT_CLOSE;
         case MOG_WRSTATE_DONE:
                 if (!http->_p.persistent) return MOG_NEXT_CLOSE;
                 if (http->forward == NULL)
-                        mog_http_reset(http);
+                        mog_http_reset(mfd);
                 assert(http->_p.buf_off == 0 && "bad offset");
                 return MOG_NEXT_ACTIVE;
         case MOG_WRSTATE_BUSY:
@@ -200,7 +202,7 @@ static enum mog_next http_run(struct mog_fd *mfd, struct mog_rbuf *rbuf,
                         TRACE(CMOGSTORED_HTTP_REQ_BEGIN(true));
 
                 http_defer_rbuf(http, rbuf, buf_len);
-                mog_http_reset(http);
+                mog_http_reset(mfd);
         }
         return MOG_NEXT_ACTIVE;
 }
@@ -239,7 +241,7 @@ static enum mog_next __http_queue_step(struct mog_fd *mfd)
 
         assert(mfd->fd >= 0 && "http fd is invalid");
 
-        if (http->wbuf) return http_wbuf_in_progress(http);
+        if (http->wbuf) return http_wbuf_in_progress(mfd);
         if (http->forward) return http_forward_in_progress(mfd, true);
 
         /* we may have pipelined data in http->rbuf */
@@ -312,10 +314,10 @@ parse:
 
 err507or400:
         if (errno == ERANGE) {
-                mog_http_resp(http, "507 Insufficient Storage", false);
+                mog_http_resp(mfd, "507 Insufficient Storage", false);
         } else {
 err400:
-                mog_http_resp(http, "400 Bad Request", false);
+                mog_http_resp(mfd, "400 Bad Request", false);
         }
         return MOG_NEXT_CLOSE;
 }
@@ -438,15 +440,12 @@ char *mog_http_path(struct mog_http *http, char *buf)
 
 
 /* TODO: see if the iovec overheads of writev() is even worth it... */
-void
-mog_http_resp0(
-        struct mog_http *http,
-        struct iovec *status,
-        bool alive)
+void mog_http_resp0(struct mog_fd *mfd, struct iovec *status, bool alive)
 {
         struct iovec iov;
         struct mog_now *now;
         char *dst = iov.iov_base = mog_fsbuf_get(&iov.iov_len);
+        struct mog_http *http = &mfd->as.http;
 
         assert(status->iov_len * 2 + 1024 < iov.iov_len && "fsbuf too small");
 
@@ -471,12 +470,12 @@ mog_http_resp0(
         iov.iov_len = dst - (char *)iov.iov_base;
         assert(http->wbuf == NULL && "tried to write with wbuf");
 
-        http->wbuf = mog_trywritev(mog_fd_of(http)->fd, &iov, 1);
+        http->wbuf = mog_trywritev(mfd->fd, &iov, 1);
 }
 
 /* call whenever we're ready to read the next HTTP request */
-void mog_http_reset(struct mog_http *http)
+void mog_http_reset(struct mog_fd *mfd)
 {
-        tcp_push(mog_fd_of(http), true);
-        mog_http_reset_parser(http);
+        tcp_push(mfd, true);
+        mog_http_reset_parser(&mfd->as.http);
 }
diff --git a/http.h b/http.h
index 3064d6e..5dd3a30 100644
--- a/http.h
+++ b/http.h
@@ -1,9 +1,8 @@
 #include "iov_str.h"
-void mog_http_resp0(
-        struct mog_http *, struct iovec *status, bool alive);
+void mog_http_resp0(struct mog_fd *, struct iovec *status, bool alive);
 
-#define mog_http_resp(http,conststr,alive) do { \
+#define mog_http_resp(mfd,conststr,alive) do { \
         struct iovec statustmp; \
         IOV_STR(&statustmp, (conststr)); \
-        mog_http_resp0((http), &statustmp, (alive)); \
+        mog_http_resp0((mfd), &statustmp, (alive)); \
 } while (0)
diff --git a/http_dav.c b/http_dav.c
index 8503d45..94e7773 100644
--- a/http_dav.c
+++ b/http_dav.c
@@ -15,7 +15,7 @@ void mog_http_delete(struct mog_fd *mfd, char *buf)
         char *path;
 
         if (mfd->fd_type == MOG_FD_TYPE_HTTPGET) {
-                mog_http_resp(http, "405 Method Not Allowed", true);
+                mog_http_resp(mfd, "405 Method Not Allowed", true);
                 return;
         }
 
@@ -26,7 +26,7 @@ void mog_http_delete(struct mog_fd *mfd, char *buf)
 
         rc = mog_unlink(http->svc, path);
         if (rc == 0) {
-                mog_http_resp(http, "204 No Content", true);
+                mog_http_resp(mfd, "204 No Content", true);
                 return;
         }
 
@@ -35,14 +35,14 @@ void mog_http_delete(struct mog_fd *mfd, char *buf)
         case EISDIR:
         case EACCES:
 forbidden:
-                mog_http_resp(http, "403 Forbidden", true);
+                mog_http_resp(mfd, "403 Forbidden", true);
                 return;
         case ENOENT:
-                mog_http_resp(http, "404 Not Found", true);
+                mog_http_resp(mfd, "404 Not Found", true);
                 return;
         }
         PRESERVE_ERRNO(do {
-                mog_http_resp(http, "500 Internal Server Error", true);
+                mog_http_resp(mfd, "500 Internal Server Error", true);
         } while(0));
 }
 
@@ -52,7 +52,7 @@ void mog_http_mkcol(struct mog_fd *mfd, char *buf)
         char *path;
 
         if (mfd->fd_type == MOG_FD_TYPE_HTTPGET) {
-                mog_http_resp(http, "405 Method Not Allowed", true);
+                mog_http_resp(mfd, "405 Method Not Allowed", true);
                 return;
         }
         path = mog_http_path(http, buf);
@@ -64,7 +64,7 @@ void mog_http_mkcol(struct mog_fd *mfd, char *buf)
          * this.
          */
         if (path)
-                mog_http_resp(http, "400 Bad Request", true);
+                mog_http_resp(mfd, "400 Bad Request", true);
         else /* path traversal attack */
-                mog_http_resp(http, "403 Forbidden", true);
+                mog_http_resp(mfd, "403 Forbidden", true);
 }
diff --git a/http_get.c b/http_get.c
index 45470e5..252ec5c 100644
--- a/http_get.c
+++ b/http_get.c
@@ -44,8 +44,9 @@ static ssize_t linux_sendfile(int sockfd, int filefd, off_t *off, size_t count)
  * so we won't hurt code maintainability by optimizing away snprintf()
  * ourselves.  This function is ugly enough already
  */
-static off_t http_get_resp_hdr(struct mog_http *http, struct stat *sb)
+static off_t http_get_resp_hdr(struct mog_fd *mfd, struct stat *sb)
 {
+        struct mog_http *http = &mfd->as.http;
         char *modified;
         void *buf;
         size_t len;
@@ -176,7 +177,7 @@ bad_range:
         if (http->_p.http_method == MOG_HTTP_METHOD_HEAD)
                 count = 0;
 
-        http->wbuf = mog_trysend(mog_fd_of(http)->fd, buf, len, (off_t)count);
+        http->wbuf = mog_trysend(mfd->fd, buf, len, (off_t)count);
 
         return (off_t)count;
 }
@@ -219,7 +220,7 @@ void mog_http_get_open(struct mog_fd *mfd, char *buf)
                 file->fsize = sb.st_size;
         }
 
-        len = http_get_resp_hdr(http, &sb);
+        len = http_get_resp_hdr(mfd, &sb);
 
         /* http->forward may be NULL even if file is set if we had an error */
         if (http->wbuf == NULL && http->forward) {
@@ -233,14 +234,14 @@ err:
         switch (errno) {
         case EACCES:
 forbidden:
-                mog_http_resp(http, "403 Forbidden", true);
+                mog_http_resp(mfd, "403 Forbidden", true);
                 return;
         case ENOENT:
-                mog_http_resp(http, "404 Not Found", true);
+                mog_http_resp(mfd, "404 Not Found", true);
                 return;
         }
         PRESERVE_ERRNO(do {
-                mog_http_resp(http, "500 Internal Server Error", true);
+                mog_http_resp(mfd, "500 Internal Server Error", true);
         } while(0));
 }
 
@@ -288,7 +289,7 @@ retry:
 done:
         mog_file_close(http->forward);
         if (http->_p.persistent) {
-                mog_http_reset(http);
+                mog_http_reset(mfd);
                 return MOG_NEXT_ACTIVE;
         }
         return MOG_NEXT_CLOSE;
diff --git a/http_put.c b/http_put.c
index 56a6325..da21f64 100644
--- a/http_put.c
+++ b/http_put.c
@@ -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)